You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

458 lines
18 KiB

2 years ago
2 years ago
1 year ago
2 years ago
1 year ago
1 year ago
1 year ago
2 years ago
2 years ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
2 years ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
2 years ago
1 year ago
1 year ago
2 years ago
2 years ago
1 year ago
2 years ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
  1. #include "mainwindow.h"
  2. #include <QDateTime>
  3. #include <QMessageBox>
  4. #include <QtConcurrent>
  5. #include <QtCore/QVariant>
  6. #include <QtSerialPort/QSerialPort>
  7. #include <QtSerialPort/QSerialPortInfo>
  8. #include <QtWidgets/QLineEdit>
  9. #include "./ui_mainwindow.h"
  10. #include "iflytop_canbus/iflytop_canbus_master.hpp"
  11. #include "logger.hpp"
  12. #include "qt_serial_datachannel.hpp"
  13. #include "reglist.hpp"
  14. #include "zexception.hpp"
  15. #include "zui/z_function_list_box.hpp"
  16. #include "zui/zq_vtab_page.hpp"
  17. //
  18. #include <thread>
  19. #include "iflytop_canbus\regid.hpp"
  20. #include "zui/zui.hpp"
  21. using namespace std;
  22. using namespace iflytop;
  23. using namespace zcr;
  24. typedef enum {
  25. kone_lead_ecg,
  26. kthree_lead_ecg,
  27. } device_type_t;
  28. static MainWindow *m_mainWindow;
  29. static QTDataChannel G_QTDataChannel;
  30. static QTDataChannel G_WaveDataChannel;
  31. static int PublicState_DeviceIDVal = 0;
  32. QT_REQUIRE_CONFIG(groupbox);
  33. #define TAG "MainWindow"
  34. static const char *fmt(const char *fmt, ...) {
  35. va_list args;
  36. va_start(args, fmt);
  37. static char buf[1024] = {0};
  38. vsnprintf(buf, sizeof(buf), fmt, args);
  39. va_end(args);
  40. return buf;
  41. }
  42. void MainWindow::log_output(QtMsgType type, const QMessageLogContext &context, const QString &msg) {}
  43. void MainWindow::doinui_slot(QFunction func) {
  44. if (func.get()) func.get()();
  45. }
  46. /***********************************************************************************************************************
  47. * PreviewShow *
  48. ***********************************************************************************************************************/
  49. void MainWindow::instructionPreviewShow(QString text) {
  50. QString info;
  51. info.append(QDateTime::currentDateTime().toString("hh:mm:ss.zzz "));
  52. info.append(" |");
  53. info.append(text);
  54. emit doinui_signal(QFunction([this, info]() { ui->instructionPreview->append(info); }));
  55. }
  56. void MainWindow::reportPreviewShow(QString text) {
  57. QString info;
  58. info.append(QDateTime::currentDateTime().toString("hh:mm:ss.zzz "));
  59. info.append(text);
  60. emit doinui_signal(QFunction([this, info]() {
  61. if (ui->reportPreview->document()->lineCount() > 1000) {
  62. ui->reportPreview->document()->clear();
  63. }
  64. ui->reportPreview->append(info);
  65. }));
  66. }
  67. void MainWindow::blockDataUploadPreviewShow(QString text) {
  68. QString info;
  69. info.append(QDateTime::currentDateTime().toString("hh:mm:ss.zzz "));
  70. info.append(text);
  71. emit doinui_signal(QFunction([this, info]() {
  72. if (ui->uploadDataPreview->document()->lineCount() > 1000) {
  73. ui->uploadDataPreview->document()->clear();
  74. }
  75. ui->uploadDataPreview->append(info);
  76. }));
  77. }
  78. void MainWindow::rawDataPreviewShow(QString text) {
  79. QString info;
  80. info.append(QDateTime::currentDateTime().toString("hh:mm:ss.zzz"));
  81. info.append(text);
  82. emit doinui_signal(QFunction([this, info]() {
  83. if (ui->rawDataPreview->document()->lineCount() > 1000) {
  84. ui->rawDataPreview->document()->clear();
  85. }
  86. ui->rawDataPreview->append(info);
  87. }));
  88. }
  89. void MainWindow::instructionPreviewClear() {
  90. doinui_signal(QFunction([this]() { ui->instructionPreview->clear(); }));
  91. }
  92. #pragma pack(push, 1)
  93. typedef struct {
  94. uint16_t header;
  95. int16_t wave1;
  96. int16_t wave2;
  97. int16_t wave3;
  98. int16_t wave4;
  99. int16_t wave5;
  100. uint8_t check;
  101. uint16_t tail;
  102. } Wave_t;
  103. #pragma pack(pop)
  104. void MainWindow::displayWave(int16_t wave1, int16_t wave2, int16_t wave3) {
  105. // 1. 生成波形数据
  106. Wave_t wave;
  107. wave.header = 0xAAAA;
  108. wave.wave1 = wave1;
  109. wave.wave2 = wave2;
  110. wave.wave3 = wave3;
  111. wave.wave4 = 0;
  112. wave.wave5 = 0;
  113. wave.tail = 0x5555;
  114. wave.check = 0;
  115. uint8_t check = 0;
  116. for (size_t i = 2; i < sizeof(wave) - 2; i++) {
  117. check += ((uint8_t *)&wave)[i];
  118. }
  119. wave.check = check;
  120. // 2. 发送波形数据
  121. G_WaveDataChannel.send((uint8_t *)&wave, sizeof(wave));
  122. }
  123. /***********************************************************************************************************************
  124. * UI相关构造 *
  125. ***********************************************************************************************************************/
  126. void MainWindow::constructBaseUI() {
  127. /**
  128. * @brief UI
  129. */
  130. {
  131. const auto infos = QSerialPortInfo::availablePorts();
  132. for (const QSerialPortInfo &info : infos) {
  133. ui->serialPortCB->addItem(info.portName());
  134. }
  135. }
  136. ui->serialBaudrateCB->addItem("9600");
  137. ui->serialBaudrateCB->addItem("14400");
  138. ui->serialBaudrateCB->addItem("19200");
  139. ui->serialBaudrateCB->addItem("38400");
  140. ui->serialBaudrateCB->addItem("57600");
  141. ui->serialBaudrateCB->addItem("115200");
  142. ui->serialBaudrateCB->addItem("460800");
  143. ui->serialBaudrateCB->addItem("500000");
  144. ui->serialBaudrateCB->addItem("2000000");
  145. ui->serialBaudrateCB->setCurrentIndex(6);
  146. connect(ui->serialPortRefreshKey, &QPushButton::clicked, this, [this](bool check) {
  147. ui->serialPortCB->clear();
  148. const auto infos = QSerialPortInfo::availablePorts();
  149. for (const QSerialPortInfo &info : infos) {
  150. ui->serialPortCB->addItem(info.portName());
  151. }
  152. });
  153. connect(ui->serialOpenKey, &QPushButton::clicked, this, [=](bool check) {
  154. // 打开串口
  155. if (ui->serialOpenKey->text() == "打开") {
  156. G_QTDataChannel.setPortName(ui->serialPortCB->currentText().toStdString());
  157. G_QTDataChannel.setBaudRate(ui->serialBaudrateCB->currentText().toInt());
  158. G_QTDataChannel.setDataBits(QSerialPort::Data8);
  159. G_QTDataChannel.setParity(QSerialPort::NoParity);
  160. G_QTDataChannel.setFlowControl(QSerialPort::NoFlowControl);
  161. G_QTDataChannel.setStopBits(QSerialPort::OneStop);
  162. /**
  163. * @brief
  164. */
  165. if (!G_QTDataChannel.open()) {
  166. QMessageBox::about(NULL, "提示", "串口无法打开,串口不存在或已被占??");
  167. return;
  168. }
  169. ui->serialOpenKey->setText("关闭");
  170. // 下拉菜单控件使能
  171. ui->serialBaudrateCB->setEnabled(false);
  172. ui->serialPortCB->setEnabled(false);
  173. ui->serialPortRefreshKey->setEnabled(false);
  174. IflytopCanbusMaster::ins()->updateChannelConfig();
  175. } else {
  176. G_QTDataChannel.close();
  177. ui->serialOpenKey->setText("打开");
  178. ui->serialBaudrateCB->setEnabled(true);
  179. ui->serialPortCB->setEnabled(true);
  180. ui->serialPortRefreshKey->setEnabled(true);
  181. }
  182. });
  183. /**
  184. * @brief UI
  185. */
  186. {
  187. const auto infos = QSerialPortInfo::availablePorts();
  188. for (const QSerialPortInfo &info : infos) {
  189. ui->waveSerialPortCB->addItem(info.portName());
  190. }
  191. }
  192. ui->waveSerialBaudrateCB->addItem("9600");
  193. ui->waveSerialBaudrateCB->addItem("14400");
  194. ui->waveSerialBaudrateCB->addItem("19200");
  195. ui->waveSerialBaudrateCB->addItem("38400");
  196. ui->waveSerialBaudrateCB->addItem("57600");
  197. ui->waveSerialBaudrateCB->addItem("115200");
  198. ui->waveSerialBaudrateCB->addItem("460800");
  199. ui->waveSerialBaudrateCB->addItem("500000");
  200. ui->waveSerialBaudrateCB->addItem("2000000");
  201. // ui->waveSerialBaudrateCB->addItems
  202. ui->waveSerialBaudrateCB->setCurrentIndex(6);
  203. connect(ui->waveSerialPortRefreshKey, &QPushButton::clicked, this, [this](bool check) {
  204. ui->waveSerialPortCB->clear();
  205. const auto infos = QSerialPortInfo::availablePorts();
  206. for (const QSerialPortInfo &info : infos) {
  207. ui->waveSerialPortCB->addItem(info.portName());
  208. }
  209. });
  210. connect(ui->waveSerialOpenKey, &QPushButton::clicked, this, [=](bool check) {
  211. // 打开串口
  212. if (ui->waveSerialOpenKey->text() == "打开") {
  213. G_WaveDataChannel.setPortName(ui->waveSerialPortCB->currentText().toStdString());
  214. G_WaveDataChannel.setBaudRate(ui->waveSerialBaudrateCB->currentText().toInt());
  215. G_WaveDataChannel.setDataBits(QSerialPort::Data8);
  216. G_WaveDataChannel.setParity(QSerialPort::NoParity);
  217. G_WaveDataChannel.setFlowControl(QSerialPort::NoFlowControl);
  218. G_WaveDataChannel.setStopBits(QSerialPort::OneStop);
  219. if (!G_WaveDataChannel.open()) {
  220. QMessageBox::about(NULL, "提示", "串口无法打开,串口不存在或已被占??");
  221. return;
  222. }
  223. ui->waveSerialOpenKey->setText("关闭");
  224. // 下拉菜单控件使能
  225. ui->waveSerialBaudrateCB->setEnabled(false);
  226. ui->waveSerialPortCB->setEnabled(false);
  227. ui->waveSerialPortRefreshKey->setEnabled(false);
  228. } else {
  229. G_WaveDataChannel.close();
  230. ui->waveSerialOpenKey->setText("打开");
  231. ui->waveSerialBaudrateCB->setEnabled(true);
  232. ui->waveSerialPortCB->setEnabled(true);
  233. ui->waveSerialPortRefreshKey->setEnabled(true);
  234. }
  235. });
  236. }
  237. void MainWindow::displayInfo(bool suc, QString info) {}
  238. MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
  239. /**
  240. * @brief QT初始化
  241. */
  242. ui->setupUi(this);
  243. m_mainWindow = this;
  244. qRegisterMetaType<int32_t>("int32_t");
  245. qRegisterMetaType<uint32_t>("uint32_t");
  246. qRegisterMetaType<float>("float");
  247. qRegisterMetaType<function<void()>>("function<void()>");
  248. qRegisterMetaType<QFunction>("QFunction");
  249. connect(this, SIGNAL(doinui_signal(QFunction)), this, SLOT(doinui_slot(QFunction)));
  250. ZQUI::ins()->initialize();
  251. ZQUI::ins()->setBlockDataUploadPreviewShow([this](QString text) { blockDataUploadPreviewShow(text); });
  252. ZQUI::ins()->setInstructionPreviewShow([this](QString text) { instructionPreviewShow(text); });
  253. ZQUI::ins()->setReportPreviewShow([this](QString text) { reportPreviewShow(text); });
  254. ZQUI::ins()->setRawDataPreviewShow([this](QString text) { rawDataPreviewShow(text); });
  255. ZQUI::ins()->setInstructionPreviewClear([this]() { instructionPreviewClear(); });
  256. /**
  257. * @brief
  258. */
  259. constructBaseUI();
  260. constructAppUI();
  261. /**
  262. * @brief
  263. */
  264. G_QTDataChannel.init();
  265. G_WaveDataChannel.init();
  266. IflytopCanbusMaster::ins()->initialize(&G_QTDataChannel);
  267. IflytopCanbusMaster::ins()->regOnRawData([this](raw_data_type_t type, uint8_t *hex, uint32_t hexlen) {
  268. if (type == kcmd_cmd) {
  269. iflytop_canbus_frame_t *frame = (iflytop_canbus_frame_t *)hex;
  270. ZQUI::ins()->rawDataPreviewShow("[CMD ] %s %s [id:%d cmd:%d,%d]", zhex2str(hex, sizeof(iflytop_canbus_frame_t)).c_str(), //
  271. zhex2str(frame->data, hexlen - sizeof(iflytop_canbus_frame_t)).c_str(), //
  272. frame->device_id, frame->cmd_main_id, frame->cmd_sub_id //
  273. );
  274. } else if (type == kcmd_receipt) {
  275. ZQUI::ins()->rawDataPreviewShow("[RECEIPT] %s", zhex2str(hex, hexlen).c_str());
  276. } else if (type == kcmd_report) {
  277. ZQUI::ins()->rawDataPreviewShow("[REPORT ] %s", zhex2str(hex, hexlen).c_str());
  278. }
  279. });
  280. }
  281. MainWindow::~MainWindow() { delete ui; }
  282. void MainWindow::processException(const zexception &e) { //
  283. ZQUI::ins()->instructionPreviewShow("%s", e.what());
  284. }
  285. int32_t MainWindow::getDeviceId() { return PublicState_DeviceIDVal; }
  286. void MainWindow::constructAppUI() {
  287. /***********************************************************************************************************************
  288. * *
  289. ***********************************************************************************************************************/
  290. {
  291. ZQVTabPage *tab = new ZQVTabPage(ui->buttonTabWidget, "模块操作");
  292. {
  293. ZQFunctionListBox *box = new ZQFunctionListBox(tab, "模块基础操作", 4);
  294. box->newFunc("扫描模块", {}, [this](int argn, const char **args) { //
  295. for (size_t i = 1; i < 255; i++) {
  296. try {
  297. IflytopCanbusMaster::ins()->ping(i);
  298. ZQUI::ins()->instructionPreviewShow("module :%d isOnline", i);
  299. } catch (const zexception &e) {
  300. if (e.ecode() != ke_overtime) {
  301. processException(e);
  302. break;
  303. }
  304. }
  305. }
  306. ZQUI::ins()->instructionPreviewShow("ScanModuleEnd");
  307. });
  308. }
  309. {
  310. ZQFunctionListBox *box = new ZQFunctionListBox(tab, "电机配置", 4);
  311. box->newFunc("电机设置编码器分辨率", {"resolution"}, [this](int argn, const char **args) { IflytopCanbusMaster::ins()->motor_set_enc_resolution(getDeviceId(), atoi(args[0])); });
  312. box->newFunc("设置IRUM", {"[0-31]"}, [this](int argn, const char **args) { IflytopCanbusMaster::ins()->writereg(getDeviceId(), kreg_stepmotor_irun, atoi(args[0])); });
  313. box->newFunc("设置IHOLD", {"[0-31]"}, [this](int argn, const char **args) { IflytopCanbusMaster::ins()->writereg(getDeviceId(), kreg_stepmotor_ihold, atoi(args[0])); });
  314. box->newFunc("设置默认速度", {"velocity"}, [this](int argn, const char **args) { IflytopCanbusMaster::ins()->writereg(getDeviceId(), kreg_motor_default_velocity, atoi(args[0])); });
  315. box->newFunc("激活配置", {}, [this](int argn, const char **args) { IflytopCanbusMaster::ins()->module_active_cfg(getDeviceId()); });
  316. }
  317. {
  318. ZQFunctionListBox *box = new ZQFunctionListBox(tab, "电机状态读取", 4);
  319. box->newFunc("电机读取编码器值", {}, [this](int argn, const char **args) {
  320. int32_t retval = IflytopCanbusMaster::ins()->motor_read_enc_val(getDeviceId());
  321. ZQUI::ins()->instructionPreviewShow("encVal %d", retval);
  322. });
  323. box->newFunc("电机读取编码器分辨率", {}, [this](int argn, const char **args) {
  324. int32_t retval = IflytopCanbusMaster::ins()->motor_get_enc_resolution(getDeviceId());
  325. ZQUI::ins()->instructionPreviewShow("encResolution %d", retval);
  326. });
  327. }
  328. {
  329. ZQFunctionListBox *box = new ZQFunctionListBox(tab, "电机操作", 4);
  330. box->newFunc("停止电机", {}, [this](int argn, const char **args) { IflytopCanbusMaster::ins()->module_stop(getDeviceId()); });
  331. box->newFunc("急停电机", {}, [this](int argn, const char **args) { IflytopCanbusMaster::ins()->module_break(getDeviceId()); });
  332. box->newFunc("激活配置", {}, [this](int argn, const char **args) { IflytopCanbusMaster::ins()->module_active_cfg(getDeviceId()); });
  333. box->newFunc("电机使能", {"enable"}, [this](int argn, const char **args) { IflytopCanbusMaster::ins()->motor_enable(getDeviceId(), atoi(args[0])); });
  334. box->newFunc("电机旋转", {"direction"}, [this](int argn, const char **args) { IflytopCanbusMaster::ins()->motor_easy_rotate(getDeviceId(), atoi(args[0])); });
  335. box->newFunc("电机移动", {"distance"}, [this](int argn, const char **args) { IflytopCanbusMaster::ins()->motor_easy_move_by(getDeviceId(), atoi(args[0])); });
  336. box->newFunc("电机移动到", {"position"}, [this](int argn, const char **args) { IflytopCanbusMaster::ins()->motor_easy_move_to(getDeviceId(), atoi(args[0])); });
  337. box->newFunc("电机归零", {}, [this](int argn, const char **args) { IflytopCanbusMaster::ins()->motor_easy_move_to_zero(getDeviceId()); });
  338. box->newFunc("电机设置当前位置", {"position"}, [this](int argn, const char **args) { IflytopCanbusMaster::ins()->motor_easy_set_current_pos(getDeviceId(), atoi(args[0])); });
  339. box->newFunc("电机移动到IO", {"io"}, [this](int argn, const char **args) { IflytopCanbusMaster::ins()->motor_easy_move_to_io(getDeviceId(), atoi(args[0])); });
  340. box->newFunc("电机设置子设备寄存器", {"regaddr", "val"}, [this](int argn, const char **args) { IflytopCanbusMaster::ins()->motor_set_subdevice_reg(getDeviceId(), atoi(args[0]), atoi(args[1])); });
  341. box->newFunc("电机读取子设备寄存器", {"regaddr"}, [this](int argn, const char **args) {
  342. int32_t retval = IflytopCanbusMaster::ins()->motor_get_subdevice_reg(getDeviceId(), atoi(args[0]));
  343. ZQUI::ins()->instructionPreviewShow("regVal 0x%08x", retval);
  344. });
  345. }
  346. {
  347. ZQFunctionListBox *box = new ZQFunctionListBox(tab, "驱动底层配置", 4);
  348. box->newFunc("电机设置子设备寄存器", {"regaddr", "val"}, [this](int argn, const char **args) { IflytopCanbusMaster::ins()->motor_set_subdevice_reg(getDeviceId(), atoi(args[0]), atoi(args[1])); });
  349. box->newFunc("电机读取子设备寄存器", {"regaddr"}, [this](int argn, const char **args) {
  350. int32_t retval = IflytopCanbusMaster::ins()->motor_get_subdevice_reg(getDeviceId(), atoi(args[0]));
  351. ZQUI::ins()->instructionPreviewShow("regVal 0x%08x", retval);
  352. });
  353. }
  354. tab->addSpacer();
  355. }
  356. m_testThread.reset(new std::thread([this]() {
  357. while (true) {
  358. if (m_testState) {
  359. try {
  360. IflytopCanbusMaster::ins()->ping(getDeviceId());
  361. } catch (const zexception &e) {
  362. processException(e);
  363. }
  364. }
  365. std::this_thread::sleep_for(std::chrono::milliseconds(10));
  366. }
  367. }));
  368. {
  369. ZQVTabPage *tab = new ZQVTabPage(ui->buttonTabWidget, "暴力测试");
  370. // static
  371. {
  372. ZQFunctionListBox *box = new ZQFunctionListBox(tab, "模块基础操作", 4);
  373. box->newFunc("开始测试", {"间隔"}, [this](int argn, const char **args) { //
  374. int interval = atoi(args[0]);
  375. m_testState = true;
  376. });
  377. box->newFunc("停止测试", {}, [this](int argn, const char **args) { //
  378. m_testState = false;
  379. });
  380. }
  381. }
  382. /***********************************************************************************************************************
  383. * *
  384. ***********************************************************************************************************************/
  385. {
  386. ZQVTabPage *tab = new ZQVTabPage(ui->buttonTabWidget, "寄存器操作");
  387. ZRegTableList *tableBox = new ZRegTableList(tab, "寄存器操作");
  388. tableBox->initializeRegOperation(
  389. [this](int32_t add, int32_t val) { //
  390. IflytopCanbusMaster::ins()->writereg(getDeviceId(), add, val);
  391. return true;
  392. },
  393. [this](int32_t add, int32_t *val) { //
  394. IflytopCanbusMaster::ins()->readreg(getDeviceId(), add, val);
  395. return true;
  396. });
  397. tableBox->newFunc("激活配置", {}, [this](int argn, const char **args) { IflytopCanbusMaster::ins()->module_active_cfg(getDeviceId()); });
  398. for (auto &var : GetRegList()) {
  399. tableBox->addReg(var.title.c_str(), var.addr, var.flag);
  400. }
  401. tableBox->addSpacer();
  402. tab->addSpacer();
  403. }
  404. }
  405. void MainWindow::on_PublicState_ConfirmKey_clicked() { PublicState_DeviceIDVal = ui->PublicState_DeviceID->toPlainText().toInt(); }