从零写一个工控多协议通讯库(五):画面组态——从写死一个监视器,到用组态把它拼出来
本文首发于我的博客talkplc.com系《从零写一个工控多协议通讯库》系列第五篇。转载请注明出处。第四篇接第二种协议时立过一个标准新协议进来框架和界面一行不改。S7 通过了考试。但界面本身一直是块心病——协议树、点表、收发帧监视全是写死在MainWindow里的。这篇把界面也变成数据原来是我写一个监控软件现在监控软件的页面由组态软件拼出来。项目代号 talkplc个人时间与设备自研实现不碰任何厂商代码。起点一份代码即界面的监视器talkplc 的监视窗口长这样左边协议树右边串口参数、八列点表、收发帧监视顶上一颗连接状态灯。功能没毛病但每加一个显示需求都要改 C 重新编译。界面是代码不是数据。组态软件WinCC、组态王、Ignition 这类的路子正好相反界面是一份配置文件运行器加载它、按配置采集和显示。好处人人都知道。但真下手做的时候问题一个一个冒出来。设计器画的东西运行器怎么认这需要一个双方都认的东西也就是契约。构件数值、仪表、按钮这些怎么加才不用改一堆地方这个问题协议层已经答过一次注册表。还有表格、设备列表这种长得像表的东西是一个一个写还是有别的办法第一步契约先行别管界面设计器和运行器是两个角色工控惯例是组态环境和运行环境分开。但它们之间只需要一个东西工程文件。所以第一刀切在数据上。工程 project connections[] screens[] connections[i] 一个 tp_conn_config 一个 id协议/链路/点表全是已有的 screens[i] 画布尺寸 widgets[]构件数组 widgets[j] type rect 绑定(conn id 点名) 各自属性构件绑定用名字连接 id 加点名而不是索引稳定、可读手改 JSON 也不容易错运行时再解析成索引。旧的单连接配置文件自动视作一个iddefault的连接向前兼容白送。有了契约程序形态反而是小事。一个 exe 两个模式--design进设计器产出工程--screen进运行器消费工程。设计器只产不跑设计态不连设备构件画占位运行器只跑不编辑。将来要拆成两个程序或者把运行器下沉到嵌入式LVGL契约一个字不用改。内核照旧零改。运行器核心tp_runtime是个纯 C 引擎吃一份工程每连接自动开一个会话每拍把值递给渲染层。Qt 只是它的一个前端。构件自己报属性属性面板谁也不认识设计器里最容易被低估的是属性面板。我的做法是让每个构件自己声明有哪些属性绑定、量程、颜色、动作面板只负责把声明渲染成编辑行、把编辑写回去QListWidgetPropGaugeItem::typeProps()const{QListWidgetPropL;LwpMake(unit,单位,WP_Text)wpMake(min,最小,WP_Real)wpMake(max,最大,WP_Real);returnL;}面板是通用的加构件不用改面板。这句话后来被我自己打脸了一次。画面跳转按钮有个 bug属性面板显示目标画面画面1存盘后却是空的跳转永远没反应。查下来是两个不起眼的事凑在一起——下拉框显示着第一项但这个值从没被写进构件。你看到的和你存下来的不是一回事。修法是把所见即所存定成面板的硬规则值为空时把显示着的默认项真正提交进去。这个 bug 比功能本身值钱。通用 UI 的坑往往就藏在显示和数据的缝隙里。加构件和加协议一个待遇前四篇最得意的设计是协议注册表tp_registry名字到工厂加协议等于加一行框架核心零改。那构件凭什么例外// gui/screen/items/TableItem.cpp 文件尾staticScreenItem*makeTable(ints,intw,consttp_screen_widget_td){returnnewTableItem(s,w,d);}namespace{structTableRegistrar{TableRegistrar(){ItemInfo ii{table,表格,70,360,260,paintTableIcon,makeTable};itemRegistryAdd(ii);}}tableReg_;}每个构件一个自包含文件文件尾一个静态注册器把自己登记进ItemRegistry登记的内容是类型名、调色板标签、默认尺寸、图标、工厂。设计器的调色板和工厂只读注册表。工厂 switch、调色板数组、图标 if/else这些我在第一版里亲手写过的东西全都不存在了。加一个构件 加一个文件 CMake 一行。和加协议一个待遇。一段弯路专门构件的坑接下来我犯了这篇里最大的错值得原样记下来。做设备管理页左边设备列表右边选中设备的点表和参数的时候我按老习惯写了三个专门构件类TableItem点表四列写死、DeviceListItem设备列表、DevParamsItem参数卡带编辑按钮。每个都要新类、工厂分支、调色板注册、图标、默认尺寸。注册表明明已经把成本降到加一个文件了我还在往一个文件里堆类。手上有了新工具脑袋还在旧习惯里。想通之后全部推倒。点表、设备列表、参数卡本质是同一种东西一张表只是数据源不同。于是通用表格有了source属性conn是整连接点表可以子集选点devices是设备清单行点击可以选中设备devattr是选中设备的属性卡。列用columns配行点击动作用row_action配。参数卡上那个编辑参数按钮就是普通按钮构件的一个动作actionparams。{type:table,source:devices,columns:dot,id,proto,row_action:select,rect:[40,96,300,660]}上面这七行就是原来 DeviceListItem 那 150 行类的全部。后来我给自己定了个规矩再遇到表状的东西先想能不能用通用表格配出来能配就不写类。让右侧跟着左侧走master-detail 还差一口气左边点了一台设备右边的点表、仪表怎么跟着换给构件绑定加一个特殊值conn意思是跟随运行器当前选中的设备。选中状态放在tp_runtime里绑定解析每次即时求值解析成选中的连接 id。任何构件绑上就自动联动跨设备同名点位比如都叫 temp无缝跟随不同名的显示无效。参数编辑也顺下来了。画面上一个编辑参数按钮绑点了弹出该设备当前值预填的表单。表单字段来自协议清单protocols.json每种协议声明自己有哪些可编辑参数又是一层配置。确定之后改配置、断开重连、自动存回工程 JSON。运行中的监视页面可以改波特率、换 IP改完状态灯闪一下连接中就回来了。验收把监视器拼回来说再多验收标准就一条原来写死的那个监视页面现在能用设计器拼出来。标题是文本构件点表是通用表格绑连接写入行是输入框绑点位仪表盘是三个 gauge。原来几百行 C 的界面现在是四十来行 JSON。点表里每一行的值和状态是活的仪表的指针在动。再往上叠一层就是完整的设备管理页三台设备三种协议S7、Modbus RTU、Omron NJ全部跑内置仿真从站点左边的行右边整块跟着换参数卡上改个采集周期重连生效存盘留痕。而它本身也是设计器里拖出来的没有硬件怎么验证老规矩sim链路三台仿真从站一起跑画面上的值就是活的。纯 C 的契约层工程读写、绑定解析、选中、重连在 ctest 里跑一遍全绿GUI 层人工过——画面来回切几轮看跳转设备列表点几行看右侧跟不跟参数改个采集周期看状态灯闪一下连接中再回来。没有 PLC 也能把整条画面逻辑过一遍这套方法从第一篇用到现在。接下来四篇立住了数据面协议是外挂的这一篇立住了表达面。工程 JSON 是设计器和运行器之间唯一的东西构件自描述加注册表加构件和加协议一样便宜表状界面是配置不是类型这条弯路比任何功能都值钱一个字符master-detail 免费送。后面排得上号的趋势曲线window_s字段从第一版起就躺在契约里等着被用、设计器里一键生成设备页、把纯 C 运行器搬到 LVGL 上。契约不变换个前端而已。每加一层都回来对照一次改动越小说明当初的抽象越对。系列前四篇① 架构与传输抽象 · ② Modbus TCP 与重构 · ③ 数据构件仪表盘 · ④ 西门子 S7

相关新闻

Python趣味游戏开发:少儿编程启蒙实践

Python趣味游戏开发:少儿编程启蒙实践

1. 项目概述:用Python打造趣味小游戏的启蒙实践这个项目源于我在少儿编程教学中的一次课堂实践——通过编写简单小游戏来巩固Python基础知识。不同于传统枯燥的语法练习,游戏开发能让孩子在创造中获得即时反馈,当看到自己编写的代码变成可交互…

2026/9/10 21:47:44 阅读更多 →
CarSim 2021.0 完整安装、破解与Simulink联合仿真环境搭建指南

CarSim 2021.0 完整安装、破解与Simulink联合仿真环境搭建指南

1. 项目概述与核心价值如果你正在做车辆动力学仿真、自动驾驶算法开发或者相关的科研项目,那么CarSim这个名字对你来说一定不陌生。它几乎是这个领域绕不开的工业标准软件,尤其是在和MATLAB/Simulink做联合仿真的时候,CarSim提供的车辆模型精…

2026/9/20 7:43:16 阅读更多 →
Python实战:从零构建钢筋混凝土柱PMM相互作用图计算与可视化工具

Python实战:从零构建钢筋混凝土柱PMM相互作用图计算与可视化工具

1. 从需求到图纸:为什么我们需要PMM图?在结构工程、机械设计或者任何涉及复杂构件分析的领域,我们常常会遇到一个核心问题:如何直观、定量地评估一个构件在承受弯矩(M)和轴力(P)共同…

2026/9/18 14:50:43 阅读更多 →

最新新闻

jQuery学堂面试避坑指南:3个原理点搞定最佳实践

jQuery学堂面试避坑指南:3个原理点搞定最佳实践

jQuery学堂面试避坑指南:3个原理点搞定最佳实践 面试被问原理答不上来,是不是瞬间冷汗直流?很多开发新手在 jQuery 相关问题上卡壳,往往不是因为不懂语法,而是没摸透底层逻辑与工程落地的最佳实践。今天把 jQuery…

2026/9/22 3:22:57 阅读更多 →
搞定HTTPSWWW.域名配置,实战项目不再卡环境

搞定HTTPSWWW.域名配置,实战项目不再卡环境

搞定HTTPSWWW.域名配置,实战项目不再卡环境 配置环境就卡半天,是不是你的常态?明明照着教程敲代码,一运行就报连接错误,排查半天发现是域名解析或协议头没写对。在真实的 实战项目…

2026/9/22 3:22:57 阅读更多 →
拒绝画饼:手机游戏外包中手写实现核心逻辑的避坑指南

拒绝画饼:手机游戏外包中手写实现核心逻辑的避坑指南

拒绝画饼:手机游戏外包中手写实现核心逻辑的避坑指南 是不是看了一堆Cocos或Unity的教程,视频里代码跑得飞起,轮到自己接手手机游戏外包项目时,却连个像样的状态机都写不出来?这种“眼高手低”的尴尬,在接外包单时最致命。客户不在乎你背了多…

2026/9/22 3:22:57 阅读更多 →
搞懂新媒体矩阵源码解析,3步搞定从语法到实战

搞懂新媒体矩阵源码解析,3步搞定从语法到实战

搞懂新媒体矩阵源码解析,3步搞定从语法到实战 很多开发者苦学 Python 或 Java 语法半年,敲代码时手速飞快,一旦要独立搭建一个完整的项目,立马大脑一片空白。这种“手有余而心不足”的尴尬,往往不是代码写得不熟,而是缺乏对底层架构的宏…

2026/9/22 3:21:57 阅读更多 →
5年老兵分享:吃鸡压枪灵敏度避坑指南,从零到实战

5年老兵分享:吃鸡压枪灵敏度避坑指南,从零到实战

5年老兵分享:吃鸡压枪灵敏度避坑指南,从零到实战 刚学会几个语法,打开IDE却大脑一片空白?这种“代码孤岛”现象,在房建工程数字化改造中太常见了。很多工程师拿着Python或Java的教程,对着屏幕发呆,不知道数据怎么流、接口怎么通。今天这…

2026/9/22 3:21:57 阅读更多 →
5分钟图解原理:工程预算定额代码调试全解析

5分钟图解原理:工程预算定额代码调试全解析

5分钟图解原理:工程预算定额代码调试全解析 复制来的工程预算定额计算脚本,一跑就报错?或者结果跟手算对不上,你盯着屏幕抓瞎,完全不知道哪行代码在“捣乱”。别慌,这种“黑盒”困境,90%的新手都踩过坑。今天不聊虚的,我们用 图解原理…

2026/9/22 3:21:57 阅读更多 →

日新闻

3台商务办公笔记本实测:手写实现环境配置,告别卡半天

3台商务办公笔记本实测:手写实现环境配置,告别卡半天

3台商务办公笔记本实测:手写实现环境配置,告别卡半天 配置环境就卡半天?别怪机器慢,多半是你没选对工具链。在Java、Go或Python的项目现场, 手写实现…

2026/9/22 0:00:41 阅读更多 →
剑帝加点速查手册:3分钟搞懂核心逻辑

剑帝加点速查手册:3分钟搞懂核心逻辑

剑帝加点速查手册:3分钟搞懂核心逻辑 面试被问原理答不上来,是不是常态?别慌。很多开发者对着 GitHub 开源仓库里的代码发呆,看似简单实则暗藏玄机。今天这份【剑帝加点】速查手册,直接带你拆解核心实现,把面试必考的原理讲透。…

2026/9/22 0:00:41 阅读更多 →
手写实现图片压缩网站核心:搞定WebP转换与质量调优

手写实现图片压缩网站核心:搞定WebP转换与质量调优

手写实现图片压缩网站核心:搞定WebP转换与质量调优 复制来的代码跑不通不知道怎么调?别慌,这种“复制粘贴地狱”在开发圈太常见了。尤其是做 图片压缩网站…

2026/9/22 0:00:41 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/21 3:13:20 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/21 2:19:36 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/21 4:51:05 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/21 15:36:51 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/21 15:36:51 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/22 2:43:42 阅读更多 →