QT开发之旅一DS7400主机调试工具
接触QT三年有余,期间因为工作需要断断续续学习过,2010年开始接触,当时好像是4.7版本,现在都已经到5.2版本了,更新真快,前阵子安装了下5.2版本,还是有很多变化的,不过感觉好像编译速度慢了很多,而且编译出来的可执行文件需要附带的DLL多了很多,感觉不爽,所以还是回到了4.7版本的开发,一个重要原因是现在大部分的开发板都移植好了4.7版本的运行库,可以方便的将WINDOWS程序移植到嵌入式linux下,5.0以上的版本貌似还没有哪家公司移植到了嵌入式linux上,估计有很多个人已经移植过。
QT也是一套C++框架,和VC++类似,和VC一样有个好处就是编译好的可执行程序,一般不需要安装什么框架的,附带DLL就行,内存要求非常低,这个很适合在嵌入式设备上面跑。之前用.NET做了三年的项目开发,每当在客户电脑上面安装一个几十兆的框架时,甚是不爽,经过了三年多的比较,最终选用QT作为以后的开发首选。经过EnigmaVirtualBox7.0.exe这个工具的压缩,还可以将可执行程序封包到一个EXE,屡试不爽!
之前一直在网络上面参考别人的代码,现在也该拿出自己的一些东西来分享分享了,这个系列将会粗略的讲解一些工具和小项目的开发过程及遇到的难题和解决办法,将会全部开源并提供下载地址,其实这个开发之旅是有过一定的基础的,所以基础的东西可能都是一笔带过。需要读者自己下载源码去研究,阅读别人的代码还是可以学习到很多东西的,就算是一个循环一个简单的文本存储,都会有一些技巧在里面,我开源出来的代码不一定都是没问题的,但是确实是经过自己几经雕琢封装好的,还是有一定借鉴价值哦!
用DS7400主机调试工具作为开发之旅的第一个项目,是因为之前用.NET写过,而且陆续有很多人看到过加过我QQ咨询过,自己也用在多个商业项目中,所以把这个单独提取出来发布出来,直接一个可执行程序无需任何框架就可以在windows98以上的电脑上跑,甚是爽!
项目名称:DS7400主机调试工具
开发环境:WIN7+QT4.7+QT CREATOR2.8+MINGW
技术实现:通过串口与DS7400报警主机通信,解析协议并作出处理
实现功能:主机布防撤防,防区故障断开旁路报警等
运行截图:
粗略步骤:
第一步:准备QT串口通信文件,QT4.7没有包含串口通信的相关类,到了5.1后面的版本才有,所以需要引入第三方的串口类,毫无疑问在QT中网上用的绝大部分都是这几个文件win_qextserialport.h,win_qextserialport.cpp,qextserialbase.h,qextserialbase.cpp,源码都已经提供,在对应项目中右键选择添加现有文件,选择这四个文件。
第二步:添加主界面,放置好对应控件,并命名。
第三步:自定义报警按钮控件,就是一旦布防撤防报警等状态出现的时候,对应颜色改变,这里我是用的贴图,有状态改变时,对应背景图改变,源码里的mybuttonalarm类还封装了三种报警按钮样式。核心代码很简单如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | void myButtonAlarm::paintEvent(QPaintEvent *event) { QPainter painter( this ); QPixmap pixMap( this ->CurrentImage); QFont font( "Arial" ,10,QFont::Bold, true ); QRectF rect(0,0,32,47); painter.setFont(font); painter.drawPixmap(0,0,32,32,pixMap); painter.drawText(rect,Qt::AlignBottom | Qt::AlignCenter, this ->defenceID); } |
就是将对应图片和文字画上去。
第四步:封装DS7400主机通信类。
博世DS7400主机通信协议格式
格式依次为: 85 18 09 6B(示例)
第一位为标识,第二位为事件类型(0E布防0D撤防07报警等),第三位为防区号(对应16进制转换成10进制加一,例如09转成10进制为09,再加一是10,对应010防区),第四位是校验码
布防:85 0E 00 74
报警主机:123 主机防区/分区:1 报警主机消息:AREA_ARM_DS7400
撤防:85 0D 00 77
报警主机:123 主机防区/分区:1 报警主机消息:AREA_DISARM_DS7400
取消报警:85 0C 00 76
报警主机:123 主机防区/分区:1 报警主机消息:CANCEL_ALARM_DS7400
正常:A0 02 5D
接收到DS7400主机状态报告
09防区:撤防状态与布防状态
正常断开:85 18 08 6A
报警主机:123 主机防区/分区:9 报警主机消息:ZONE_OPEN_DS7400
正常连上:85 19 08 6B
报警主机:123 主机防区/分区:9 报警主机消息:ZONE_RESTORE_DS7400
报警断开:85 18 08 6A 85 07 08 75
报警主机:123 主机防区/分区:9 报警主机消息:ZONE_OPEN_DS7400
报警主机:123 主机防区/分区:9 报警主机消息:BURGLAR_ZONE_ALARM_DS7400
报警连上:85 19 08 6B 85 11 08 63
报警主机:123 主机防区/分区:9 报警主机消息:ZONE_RESTORE_DS7400
报警主机:123 主机防区/分区:9 报警主机消息:ZONE_ALARM_RESTORE_DS7400
旁路:85 0F 08 7D
报警主机:123 主机防区/分区:9 报警主机消息:FORCED_BYPASS_DS7400
第五步:实例化串口类,通信。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | void frmMain::on_btnOpen_clicked() { if (ui->btnOpen->text()== "打开串口" ) { QString port=ui->cboxPortName->currentText(); DS7400->SetHostID( "" ); DS7400->SetHostName( "" ); DS7400->SetHostType( "" ); DS7400->SetHostAddr(1); DS7400->SetHostConnectType( "COM" ); DS7400->SetHostConnectValue(port); if (DS7400->Open()) { connect(DS7400,SIGNAL(Connect(QString)), this ,SLOT(Connect())); connect(DS7400,SIGNAL(DisConnect(QString)), this ,SLOT(DisConnect())); connect(DS7400,SIGNAL(BuFang(QString, int )), this ,SLOT(BuFang())); connect(DS7400,SIGNAL(CheFang(QString, int )), this ,SLOT(CheFang())); connect(DS7400,SIGNAL(BaoJing(QString,QString)), this ,SLOT(BaoJing(QString,QString))); connect(DS7400,SIGNAL(DuanKai(QString,QString)), this ,SLOT(DuanKai(QString,QString))); connect(DS7400,SIGNAL(GuZhang(QString,QString)), this ,SLOT(GuZhang(QString,QString))); connect(DS7400,SIGNAL(HuiFu(QString,QString)), this ,SLOT(HuiFu(QString,QString))); connect(DS7400,SIGNAL(PangLu(QString,QString)), this ,SLOT(PangLu(QString,QString))); ui->btnOpen->setText( "关闭串口" ); this ->AddMessage( "打开串口成功" ); } else { this ->AddMessage( "打开串口失败" ); } } else { DS7400->Close(); disconnect(DS7400,SIGNAL(Connect(QString)), this ,SLOT(Connect())); disconnect(DS7400,SIGNAL(DisConnect(QString)), this ,SLOT(DisConnect())); disconnect(DS7400,SIGNAL(BuFang(QString, int )), this ,SLOT(BuFang())); disconnect(DS7400,SIGNAL(CheFang(QString, int )), this ,SLOT(CheFang())); disconnect(DS7400,SIGNAL(BaoJing(QString,QString)), this ,SLOT(BaoJing(QString,QString))); disconnect(DS7400,SIGNAL(DuanKai(QString,QString)), this ,SLOT(DuanKai(QString,QString))); disconnect(DS7400,SIGNAL(GuZhang(QString,QString)), this ,SLOT(GuZhang(QString,QString))); disconnect(DS7400,SIGNAL(HuiFu(QString,QString)), this ,SLOT(HuiFu(QString,QString))); disconnect(DS7400,SIGNAL(PangLu(QString,QString)), this ,SLOT(PangLu(QString,QString))); ui->btnOpen->setText( "打开串口" ); this ->AddMessage( "关闭串口成功" ); } } |
第六步:实现具体槽函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 | void frmMain::AddMessage(QString Message) { ui->txtData->append(QString( "收到消息:%1 时间:%2" ) .arg(Message) .arg(QDateTime::currentDateTime().toString( "yyyy-MM-dd HH:mm:ss" ))); } void frmMain::Connect() { this ->AddMessage( "主机上线" ); } void frmMain::DisConnect() { this ->AddMessage( "主机下线" ); } void frmMain::BuFang() { int count=ui->gboxMain->children().count(); for ( int i=0;i<count;i++) { myButtonAlarm *btn=(myButtonAlarm *)ui->gboxMain->children().at(i); btn->SetDefenceStatus(DefenceStatusBuFang); } this ->AddMessage( "主机布防" ); } void frmMain::CheFang() { int count=ui->gboxMain->children().count(); for ( int i=0;i<count;i++) { myButtonAlarm *btn=(myButtonAlarm *)ui->gboxMain->children().at(i); btn->SetDefenceStatus(DefenceStatusCheFang); } this ->AddMessage( "主机撤防" ); } void frmMain::BaoJing() { int count=ui->gboxMain->children().count(); for ( int i=0;i<count;i++) { myButtonAlarm *btn=(myButtonAlarm *)ui->gboxMain->children().at(i); btn->SetDefenceStatus(DefenceStatusBaoJing); } this ->AddMessage( "主机报警" ); } void frmMain::PangLu() { int count=ui->gboxMain->children().count(); for ( int i=0;i<count;i++) { myButtonAlarm *btn=(myButtonAlarm *)ui->gboxMain->children().at(i); btn->SetDefenceStatus(DefenceStatusPangLu); } this ->AddMessage( "主机旁路" ); } void frmMain::DuanKai() { int count=ui->gboxMain->children().count(); for ( int i=0;i<count;i++) { myButtonAlarm *btn=(myButtonAlarm *)ui->gboxMain->children().at(i); btn->SetDefenceStatus(DefenceStatusDuanKai); } this ->AddMessage( "主机断开" ); } void frmMain::GuZhang() { int count=ui->gboxMain->children().count(); for ( int i=0;i<count;i++) { myButtonAlarm *btn=(myButtonAlarm *)ui->gboxMain->children().at(i); btn->SetDefenceStatus(DefenceStatusGuZhang); } this ->AddMessage( "主机故障" ); } void frmMain::BaoJing(QString hostID, QString defenceID) { int count=ui->gboxMain->children().count(); for ( int i=0;i<count;i++) { myButtonAlarm *btn=(myButtonAlarm *)ui->gboxMain->children().at(i); if (btn->GetDefenceID()==defenceID) { btn->SetDefenceStatus(DefenceStatusBaoJing); break ; } } this ->AddMessage(QString( "%1防区报警" ).arg(defenceID)); } void frmMain::DuanKai(QString hostID, QString defenceID) { int count=ui->gboxMain->children().count(); for ( int i=0;i<count;i++) { myButtonAlarm *btn=(myButtonAlarm *)ui->gboxMain->children().at(i); if (btn->GetDefenceID()==defenceID) { btn->SetDefenceStatus(DefenceStatusDuanKai); break ; } } this ->AddMessage(QString( "%1防区断开" ).arg(defenceID)); } void frmMain::GuZhang(QString hostID, QString defenceID) { int count=ui->gboxMain->children().count(); for ( int i=0;i<count;i++) { myButtonAlarm *btn=(myButtonAlarm *)ui->gboxMain->children().at(i); if (btn->GetDefenceID()==defenceID) { btn->SetDefenceStatus(DefenceStatusGuZhang); break ; } } this ->AddMessage(QString( "%1防区故障" ).arg(defenceID)); } void frmMain::HuiFu(QString hostID, QString defenceID) { int count=ui->gboxMain->children().count(); for ( int i=0;i<count;i++) { myButtonAlarm *btn=(myButtonAlarm *)ui->gboxMain->children().at(i); if (btn->GetDefenceID()==defenceID) { btn->SetDefenceStatus(DefenceStatusCheFang); break ; } } this ->AddMessage(QString( "%1防区恢复" ).arg(defenceID)); } void frmMain::PangLu(QString hostID, QString defenceID) { int count=ui->gboxMain->children().count(); for ( int i=0;i<count;i++) { myButtonAlarm *btn=(myButtonAlarm *)ui->gboxMain->children().at(i); if (btn->GetDefenceID()==defenceID) { btn->SetDefenceStatus(DefenceStatusPangLu); break ; } } this ->AddMessage(QString( "%1防区旁路" ).arg(defenceID)); } |
这里采用QString(“”)而不是tr(“”) ,之前看过某人说过要慎用tr,确实,tr是用来国际化的,如果需要字符串拼接,可以用QString(“%1”).arg(“”)这种占位符形式,很方便。和.NET里面的string.Forrmat用法一样。
博客园上传资源大小有限,所以放到了CSDN上面,如有不便还请见谅,可以向私人索取!
可执行文件下载地址:http://download.csdn.net/detail/feiyangqingyun/6708143
源码猛点这里:http://download.csdn.net/detail/feiyangqingyun/6708149
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· [AI/GPT/综述] AI Agent的设计模式综述