model_select.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. #include "model_select.h"
  2. #include "ui_model_select.h"
  3. #include <QProcess>
  4. #include <QFile>
  5. #include <QTextStream>
  6. model_select::model_select(QWidget *parent) : QMainWindow(parent),
  7. ui(new Ui::model_select)
  8. {
  9. ui->setupUi(this);
  10. initsetting(); // 初始化设置
  11. }
  12. // tree代码
  13. void model_select::handleTreeItemClicked(const QModelIndex &index)
  14. {
  15. // 转发信号
  16. emit treeItemClicked(index);
  17. }
  18. void model_select::setTreeModel(tree_model_set *model)
  19. {
  20. treeModel = model; // 设置 tree_model_set 实例
  21. }
  22. void model_select::setTree_init()
  23. {
  24. QStandardItemModel *model = treeModel->tree_set();
  25. ui->tree_set->setModel(model);
  26. ui->tree_set->expandAll();
  27. // 将 QTreeView 的 clicked 信号连接到 handleTreeItemClicked 槽函数
  28. connect(ui->tree_set, &QTreeView::clicked, this, &model_select::handleTreeItemClicked);
  29. }
  30. //
  31. model_select::~model_select()
  32. {
  33. delete ui;
  34. }
  35. void model_select::on_setListen_clicked()
  36. {
  37. unsigned short port = ui->port->text().toUShort(); // 获取端口号
  38. ms->listen(QHostAddress::Any, port); // 监听所有地址上的指定端口
  39. // ui->setListen->setDisabled(true); // 禁用监听按钮
  40. // this->hide();
  41. openSimulinkModel("tcp_test_link.m"); // 使用socket调用
  42. sim_time_wt = ui->sim_time_wt->text(); // 获取仿真时间
  43. QString pro_sim_time_wt="sim_time_wt:";
  44. file_write(&pro_sim_time_wt, &sim_time_wt); // 写入仿真时间到配置文件
  45. // QString pro_PauseInterval="PauseInterval:";
  46. // QString PauseInterval="5";
  47. // file_write(&pro_PauseInterval, &PauseInterval); // 写入仿真时间到配置文件
  48. ui->setListen->setText("继续仿真");
  49. }
  50. void model_select::initsetting()
  51. {
  52. this->setWindowTitle("开始设置");
  53. ui->port->setText("8899");
  54. ui->sim_time_wt->setText("100");
  55. ui->sim_time_qh->setText("100");
  56. connectNum = 0;
  57. // 初始化树
  58. setTree_init();
  59. // 初始化下拉菜单内容
  60. cbo_select_Init();
  61. // 连接信号槽
  62. // 创建监听的服务器对象
  63. ms = new QTcpServer(this);
  64. connect(ms, &QTcpServer::newConnection, this, [=]()
  65. {
  66. QTcpSocket *clientSocket = ms->nextPendingConnection();
  67. mstatus->setPixmap(QPixmap(":/accessibility.svg").scaled(20, 20));
  68. // 将客户端连接添加到连接管理中
  69. connectedClients[clientSocket] = "";
  70. // 增加处理连接的信号和槽
  71. connectClient(clientSocket);
  72. receive_Client(clientSocket); });
  73. // 状态栏处理动作
  74. mstatus = new QLabel;
  75. ui->statusbar->addWidget(new QLabel("是否有用户连接:"));
  76. ui->statusbar->addWidget(mstatus);
  77. }
  78. void model_select::connectClient(QTcpSocket *clientSocket)
  79. {
  80. connectNum++;
  81. connect(clientSocket, &QTcpSocket::disconnected, this, [=]()
  82. {
  83. clientSocket->close();
  84. connectedClients.remove(clientSocket);
  85. connectNum = 0;
  86. // 更新状态栏
  87. if (connectNum == 0) {
  88. mstatus->setPixmap(QPixmap(":/chat-bubble-xmark.svg").scaled(20, 20));
  89. } });
  90. }
  91. void model_select::openSimulinkModel(const QString &modelName)
  92. {
  93. static QProcess *process = nullptr; // 静态变量,保持 MATLAB 进程
  94. if (!process) // 如果尚未启动 MATLAB 进程
  95. {
  96. process = new QProcess();
  97. QString program = "D:/app/matlab_2021b/bin/matlab.exe";
  98. QString model_path = "D:/desktop/NGS/model_git/model_zl/tcp";
  99. model_path.replace("/", "\\\\");
  100. QStringList arguments;
  101. arguments << "-r" << QString("cd('%1'); run('%2');").arg(model_path, modelName)
  102. << "-nosplash"
  103. << "-nodesktop";
  104. // connect(process, &QProcess::finished, [=]()
  105. // {
  106. // qDebug() << "MATLAB finished with exit code " << process->exitCode();
  107. // process->deleteLater();
  108. // process = nullptr; // 结束后将指针置为空以便下次重新启动
  109. // });
  110. process->start(program, arguments);
  111. if (!process->waitForStarted())
  112. {
  113. qDebug() << "Failed to start MATLAB!";
  114. delete process; // 启动失败,释放资源
  115. process = nullptr; // 将指针置为空
  116. }
  117. else
  118. {
  119. qDebug() << "MATLAB started successfully.";
  120. }
  121. }
  122. else // 如果正在运行 MATLAB 进程
  123. {
  124. QString model_path = "D:/desktop/NGS/model_git/model_zl/tcp";
  125. QString command = QString("cd('%1'); run('%2');").arg(model_path, modelName);
  126. // 通过标准输入将命令发送到 MATLAB
  127. process->write(command.toUtf8() + "\n");
  128. process->waitForBytesWritten();
  129. qDebug() << "Sent command to running MATLAB: " << command;
  130. }
  131. }
  132. // 编写cbo_select的槽函数,下拉菜单的内容
  133. void model_select::cbo_select_Init()
  134. {
  135. // 代码解释:初始化model_select的下拉菜单内容,并设置当前选择项为"选择仿真模型"
  136. ui->cbo_model_select->addItem("选择仿真模型");
  137. ui->cbo_model_select->addItem("稳态模型");
  138. ui->cbo_model_select->addItem("切换模型");
  139. ui->cbo_model_select->setCurrentIndex(0);
  140. connect(ui->cbo_model_select, &QComboBox::currentIndexChanged, this, &model_select::cbo_select_changed);
  141. // 代码解释:初始化下拉菜单内容,并设置当前选择项为"选择仿真模型"
  142. ui->cbo_wt->addItem("选择稳态工况");
  143. ui->cbo_wt->addItem("27节");
  144. ui->cbo_wt->addItem("18节");
  145. ui->cbo_wt->addItem("12节");
  146. ui->cbo_wt->addItem("2.5节");
  147. ui->cbo_wt->addItem("9节");
  148. ui->cbo_wt->addItem("6节");
  149. ui->cbo_wt->addItem("6节静音");
  150. ui->cbo_wt->setCurrentIndex(0);
  151. connect(ui->cbo_wt, &QComboBox::currentIndexChanged, this, &model_select::cbo_wt_changed);
  152. // 代码解释:初始化工况下拉菜单内容,并设置当前选择项为"稳态工况"
  153. ui->cbo_condition->addItem("选择工况");
  154. connect(ui->cbo_condition, &QComboBox::currentIndexChanged, this, &model_select::cbo_condition_changed);
  155. ui->cbo_qh->addItem("选择切换工况");
  156. ui->cbo_qh->addItem("切换1");
  157. ui->cbo_qh->addItem("切换2");
  158. ui->cbo_qh->addItem("切换3");
  159. ui->cbo_qh->addItem("切换4");
  160. ui->cbo_qh->addItem("切换5");
  161. ui->cbo_qh->addItem("切换6");
  162. ui->cbo_qh->setCurrentIndex(0);
  163. //connect(ui->cbo_qh, &QComboBox::currentIndexChanged, this, &model_select::cbo_qh_changed);
  164. ui->cbo_lg->addItem("先开后关");
  165. ui->cbo_lg->addItem("预定顺序");
  166. ui->cbo_lg->setCurrentIndex(0);
  167. //connect(ui->cbo_lg, &QComboBox::currentIndexChanged, this, &model_select::cbo_lg_changed);
  168. ui->cbo_target->addItem("迅速");
  169. ui->cbo_target->addItem("平稳");
  170. ui->cbo_target->addItem("缓慢");
  171. ui->cbo_target->setCurrentIndex(0);
  172. //connect(ui->cbo_target, &QComboBox::currentIndexChanged, this, &model_select::cbo_target_changed);
  173. ui->line_gsf->setText("100");
  174. ui->line_gsp->setText("100");
  175. ui->line_nsp->setText("100");
  176. ui->line_nshf->setText("100");
  177. ui->cbo_pid->addItem("专家系统");
  178. ui->cbo_pid->addItem("PI");
  179. ui->cbo_pid->addItem("PID");
  180. ui->cbo_pid->setCurrentIndex(0);
  181. ui->cbo_pid_wt->addItem("专家系统");
  182. ui->cbo_pid_wt->addItem("PI");
  183. ui->cbo_pid_wt->addItem("PID");
  184. ui->cbo_pid_wt->setCurrentIndex(0);
  185. //connect(ui->cbo_pid, &QComboBox::currentIndexChanged, this, &model_select::cbo_pid_changed);
  186. }
  187. // slot函数,下拉菜单内容改变时触发
  188. void model_select::cbo_select_changed(int index)
  189. {
  190. QString modelAddress = "wt"; // 模型的地址大泵模型地址
  191. QString pro_dress = "model_address:";
  192. if (index == 1)
  193. {
  194. // 往txt中写入大泵稳态模型的地址
  195. modelAddress="wt";
  196. }
  197. else if (index == 2)
  198. {
  199. // 往txt中写入小泵稳态模型的地址
  200. modelAddress = "qh";
  201. }
  202. file_write(&pro_dress, &modelAddress);
  203. // ui->cbo_model_select->setDisabled(true);
  204. file_write(&pro_dress, &modelAddress);
  205. }
  206. void model_select::cbo_wt_changed(int index)
  207. {
  208. QString wt_str = "condition_wt:";
  209. QString wt_num = "27";
  210. if (index == 1)
  211. {
  212. wt_num = "27";
  213. }
  214. else if (index == 2)
  215. {
  216. wt_num = "18";
  217. }
  218. else if (index == 3)
  219. {
  220. wt_num = "12";
  221. }
  222. else if (index == 4)
  223. {
  224. wt_num = "2.5";
  225. }
  226. else if (index == 5)
  227. {
  228. wt_num = "9";
  229. }
  230. else if (index == 6)
  231. {
  232. wt_num = "6";
  233. }
  234. else if (index == 7)
  235. {
  236. wt_num = "61";
  237. }
  238. file_write(&wt_str, &wt_num);
  239. }
  240. // slot函数,工况下拉菜单内容改变时触发
  241. void model_select::cbo_condition_changed(int index)
  242. {
  243. // 根据下拉菜单的选中项切换显示界面
  244. switch (index)
  245. {
  246. case 0:
  247. ui->condition->setCurrentIndex(0); // 显示第一个页面
  248. break;
  249. case 1:
  250. ui->condition->setCurrentIndex(1); // 显示第二个页面
  251. break;
  252. case 2:
  253. ui->condition->setCurrentIndex(2); // 显示第三个页面
  254. break;
  255. default:
  256. break;
  257. }
  258. }
  259. // 读取txt文件
  260. void model_select::file_read()
  261. {
  262. QFile file("D:/desktop/NGS/model_git/model_zl/tcp/model_address.txt"); // 要读取的文件名
  263. // 以只读模式打开文件
  264. if (file.open(QIODevice::ReadOnly | QIODevice::Text))
  265. {
  266. QTextStream in(&file);
  267. QString line = in.readLine(); // 读取一行
  268. while (!line.isNull())
  269. {
  270. // 处理每行数据
  271. qDebug() << "Line: " << line;
  272. line = in.readLine(); // 读取下一行
  273. }
  274. file.close(); // 关闭文件
  275. }
  276. else
  277. {
  278. // 处理文件打开失败的情况
  279. qDebug() << "Unable to open file for reading.";
  280. }
  281. }
  282. // 写入txt文件
  283. void model_select::file_write(QString *prs_name, QString *msg)
  284. {
  285. QString modelAddress = *prs_name + *msg; // 将指针解引用并连接字符串
  286. QFile file("D:/desktop/NGS/model_git/model_zl/tcp/model_address.txt"); // 要写入的文件名
  287. // 以附加模式打开文件
  288. if (file.open(QIODevice::Append | QIODevice::Text))
  289. {
  290. QTextStream out(&file);
  291. out << modelAddress << '\n'; // 写入地址并换行
  292. file.close(); // 关闭文件
  293. }
  294. else
  295. {
  296. // 处理文件打开失败的情况
  297. qDebug() << "Unable to open file for writing.";
  298. }
  299. }
  300. void model_select::on_btn_pause_clicked()//TCP发送pause命令
  301. {
  302. QString serverMsg = "pasue"; //
  303. for (auto clientSocket : connectedClients.keys()) {
  304. if (clientSocket->state() == QAbstractSocket::ConnectedState) {
  305. clientSocket->write(serverMsg.toUtf8()); // 发送消息
  306. }
  307. }
  308. }
  309. void model_select::receive_Client(QTcpSocket *clientSocket)
  310. {
  311. connect(clientSocket, &QTcpSocket::readyRead, this, [=]()
  312. {
  313. QByteArray data = clientSocket->readAll();
  314. if (data.isEmpty())
  315. return;
  316. char dataType = data.at(0); // 读取前缀
  317. data.remove(0, 1); // 移除前缀t
  318. if (dataType == 't') {
  319. // 处理文本数据
  320. QString message = QString::fromUtf8(data);
  321. qDebug() << "收到文本: " << message;
  322. }
  323. //发送信号到界面
  324. emit receive_msg(data);
  325. data.clear(); // 清空 data
  326. } );
  327. }