用 Mongoose Library 打造完整设备仪表盘:Modbus TCP 主站控制台实战解析
用 Mongoose Library 打造完整设备仪表盘Modbus TCP 主站控制台实战解析【免费下载链接】mongooseEmbedded web server, with TCP/IP network stack, MQTT and Websocket项目地址: https://gitcode.com/gh_mirrors/mon/mongoose导读本指南以 tutorials/tcp/modbus-dashboard 示例为核心讲解如何将 Mongoose Library 集成进嵌入式设备构建一个集Web UI、REST API、Modbus TCP 主站与 MQTT 转发于一体的完整设备仪表盘。读完本文你将掌握如何用 Mongoose 的多连接事件驱动模型同时服务 HTTP/HTTPS 与 Modbus TCP 请求、如何把 Web 前端整体打包进固件二进制无需文件系统、如何实现设备设置的持久化与在线修改以及如何通过 JSON 指令驱动 Modbus 读写操作。示例定位一个完整的设备仪表盘根据 README.md该示例演示了 Mongoose Library 集成进嵌入式设备后所能提供的完整设备仪表盘能力目标特性包括认证登录保护的仪表盘login-protected dashboard多用户登录支持多个登录账号并可能拥有不同权限Web UI 完全内嵌固件前端资源打包进固件二进制运行时无需文件系统即可服务对文件系统故障具备弹性变更实时传播所有更改都会同步到所有已连接的客户端。需要说明的是登录认证与实时推送属于该系列教程tutorials/device-dashboard的目标能力框架而在本 modbus-dashboard 示例的落地代码中可实际运行验证的核心能力是Modbus 主站控制台 设置持久化 MQTT 转发配置 内嵌 Web UI。下文将基于仓库真实源码逐一剖析这些能力的实现。目录结构与构建方式该示例的完整文件布局如下tutorials/tcp/modbus-dashboard/ ├── certs/ # TLS 证书server_cert.pem / server_key.pem ├── web_root/ # Web 前端资源 │ ├── bundle.js # Preact htm preact-router 打包产物 │ ├── history.min.js # hash 路由依赖 │ ├── index.html # 页面入口 │ ├── main.js # 前端逻辑ES Module │ └── tailwind.config.js # Tailwind 样式配置 ├── Makefile # 构建脚本 ├── main.c # 程序入口事件循环 ├── mongoose.c / mongoose.h # Mongoose 单文件库 ├── net.c / net.h # 仪表盘核心实现HTTP API Modbus ├── pack.js # 打包文件系统生成脚本 └── packed_fs.c # 由 pack.js 生成的 C 资源文件在 Makefile 中示例由main.c mongoose.c net.c packed_fs.c四个源文件编译而成默认构建命令为make # 构建并运行默认编译为 ./example make TLSmbedtls # 启用 mbedTLS 的 HTTPS 支持自动 clone mbedtls v2.28.2 make clean # 清理构建产物其中两个关键生成目标值得注意# Bundle JS libraries (preact, preact-router, ...) into a single file web_root/bundle.js: curl -s https://npm.reversehttp.com/preact,preact/hooks,htm/preact,preact-router -o $ # Generate packed filesystem for serving Web UI packed_fs.c: $(wildcard web_root/*) $(wildcard certs/*) Makefile web_root/bundle.js node pack.js $(addsuffix ::gzip, $(wildcard web_root/*)) certs/* $也就是说前端依赖Preact、preact/hooks、htm/preact、preact-router被在线打包为单个bundle.jspacked_fs.c则由 pack.js 把web_root下所有资源并标注::gzip进行 gzip 压缩及certs证书一起生成为 C 源码。mbedtls目标则用于拉取 TLS 实现当make TLSmbedtls时 Makefile 会追加-DMG_TLSMG_TLS_MBED编译选项并编译 mbedtls 库源码。程序入口与事件循环main.c 展示了典型 Mongoose 应用的骨架int main(void) { struct mg_mgr mgr; signal(SIGPIPE, SIG_IGN); signal(SIGINT, signal_handler); signal(SIGTERM, signal_handler); mg_log_set(MG_LL_DEBUG); // Set debug log level mg_mgr_init(mgr); web_init(mgr); while (s_sig_num 0) { mg_mgr_poll(mgr, 50); } mg_mgr_free(mgr); return 0; }流程非常简洁初始化事件管理器mg_mgr_init→ 调用web_init注册 HTTP/HTTPS 监听器与定时器 → 以 50ms 周期循环mg_mgr_poll驱动所有事件直到收到 SIGINT/SIGTERM。全部业务逻辑被收敛在web_init与net.c的各个事件回调中。网络层初始化HTTP HTTPS SNTP 内嵌文件系统net.c 的web_init是整个仪表盘的后端入口void web_init(struct mg_mgr *mgr) { set_default_settings(s_settings); web_load_settings(s_settings, sizeof(s_settings)); mg_http_listen(mgr, HTTP_URL, fn, NULL); mg_http_listen(mgr, HTTPS_URL, fn, (void *) 1); mg_timer_add(mgr, 10 * 60 * 1000, MG_TIMER_RUN_NOW | MG_TIMER_REPEAT, timer_sntp_fn, mgr); mg_mem_files mg_packed_files; // Use generated packed filesystem }监听地址定义在 net.h并允许在编译期覆盖#if !defined(HTTP_URL) #define HTTP_URL http://0.0.0.0:8000 #endif #if !defined(HTTPS_URL) #define HTTPS_URL https://0.0.0.0:8443 #endif默认同时监听HTTP 8000与HTTPS 8443。此外还注册了一个每 10 分钟执行一次、启动立即运行的 SNTP 定时器通过mg_sntp_connect连接udp://time.google.com:123同步设备时间——这为 Modbus 响应的超时判断提供了可靠的时间基准。REST API 设计设置读写与设备控制HTTP 请求统一由fn回调处理net.c通过mg_match分发路由API 端点方法功能/api/settings/getGET读取设备设置并返回 JSON/api/settings/setPOST接收 JSON 并更新、持久化设置/api/modbus/execPOST执行一次 Modbus TCP 请求JSON 参数/api/device/resetPOST设备复位返回true非 API 路径一律交给mg_http_serve_dir提供静态资源服务struct mg_http_serve_opts opts; memset(opts, 0, sizeof(opts)); #if MG_ARCH MG_ARCH_UNIX || MG_ARCH MG_ARCH_WIN32 opts.root_dir web_root; // On workstations, use filesystem #else opts.root_dir /web_root; // On embedded, use packed files opts.fs mg_fs_packed; #endif mg_http_serve_dir(c, ev_data, opts);这里体现了 README 强调的双模式设计在桌面工作站UNIX/Win32上直接读磁盘目录web_root便于开发调试在嵌入式平台上则从mg_fs_packed即打包进固件的资源中读取/web_root下的文件完全不需要文件系统。设备设置的数据模型net.c定义了设备设置结构体struct device_settings { uint32_t magic; int log_level; bool mqtt_enabled; char mqtt_server_url[64]; char mqtt_topic_tx[16]; char mqtt_topic_rx[16]; };set_default_settings提供出厂默认值magic 为SETTINGS_MAGIC即0xaabbccdd日志级别MG_LL_DEBUGMQTT 服务器mqtt://broker.hivemq.com:1883收发主题modbus1/tx与modbus1/rx。/api/settings/set处理函数使用 Mongoose 的 JSON 解析 APImg_json_get_bool、mg_json_get_long、mg_json_get_str从请求体中提取mqtt_enabled、log_level、mqtt_server_url、mqtt_topic_rx、mqtt_topic_tx等字段更新后调用web_save_settings持久化并以{%m:%s,%m:%m}格式回写{status:...,message:...}。设置持久化web_load_settings与web_save_settings在 main.c 中实现落盘文件为settings.binbool web_load_settings(void *buf, size_t len) { struct mg_str data mg_file_read(mg_fs_posix, CONFIG_FILE); // 读取失败或长度不匹配时记录错误否则 memcpy 到缓冲区 ... } bool web_save_settings(void *buf, size_t len) { MG_INFO((Saving to %s, CONFIG_FILE)); return mg_file_write(mg_fs_posix, CONFIG_FILE, buf, len); }web_load_settings要求文件大小与结构体完全一致data.len ! len即报错这是嵌入式场景常用的固定长度二进制配置块模式magic字段则用于校验配置块是否有效。net.h中导出的这套接口web_init/web_load_settings/web_save_settings也正是 README 所说的可将同一套 Web 框架移植到其他硬件平台的抽象边界——换平台只需重新实现读写两个函数。Modbus TCP 主站的实现细节这是本示例最有技术含量的部分Mongoose 的事件驱动模型天然适合同时扮演HTTP 服务器与Modbus TCP 客户端两种角色。发起请求从 JSON 参数到 Modbus 帧前端点击 Execute 后/api/modbus/exec收到形如{url: tcp://192.168.0.100:502, id: 1, reg: 0, func: 3, nregs: 1, timeout: 1500}的 JSON。handle_modbus_exec调用start_modbus_requestnet.c解析参数并建立到从站的 TCP 连接char *url mg_json_get_str(json, $.url); long timeout mg_json_get_long(json, $.timeout, 750); uint8_t id (uint8_t) mg_json_get_long(json, $.id, 1); uint16_t reg (uint16_t) mg_json_get_long(json, $.reg, 1); uint8_t func (uint8_t) mg_json_get_long(json, $.func, 0); uint16_t nregs (uint16_t) mg_json_get_long(json, $.nregs, 1);随后逐字节拼装 Modbus TCP 应用数据单元ADUsend16(c, 1); // TID: 事务标识 send16(c, 0); // Protocol identifier: 0 (modbus) send16(c, 0); // Length: 稍后回填 send8(c, id); // Client ID从站地址 send8(c, func); // 功能码对于功能码 3/4读保持/输入寄存器、6写单寄存器、16写多寄存器追加起始寄存器号与寄存器数量写多寄存器16还会按$.values[i]逐个填入要写入的寄存器值对于功能码 43读设备标识则追加 MEI 类型 14、基本设备 ID 1、对象 ID 0厂商名。最后回填长度字段*lp mg_htons((uint16_t) (c-send.len - len)); // Set length field响应处理帧组装、超时与事件回传Modbus 连接的回调mfn处理两类事件MG_EV_READ先判断最小长度 8继续攒数据从第 4 字节取出 PDU 长度不足则继续缓冲凑齐一帧后通过mg_call(t, MG_EV_USER, c-recv)把收到的数据以用户自定义事件MG_EV_USER转发给发起请求的 HTTP 连接然后关闭 Modbus 连接MG_EV_POLL若设置了expiration_time且已超时mg_millis()比较关闭连接。HTTP 侧则维护两个超时发起请求后cd-expiration_time mg_millis() 15001.5 秒内未收到响应即回false收到MG_EV_USER后清除超时并调用print_mb_resp把原始响应解析成 JSON 回给浏览器功能码 3/4解析为寄存器值数组[...]功能码 43解析为{mei:..,devid:..,conformity:..,more:..,next:..,objects:[{...}]}结构其他功能码返回null。同时响应中还附带raw字段mg_print_hex十六进制原始字节方便调试。这套HTTP 连接等待 Modbus 连接结果的联动完全依靠 Mongoose 的mg_call用户事件机制实现连接间无需共享任何锁或全局队列。内嵌文件系统Web UI 与固件零依赖README 特别强调Web UI 可完全嵌入固件二进制无需文件系统。支撑这一能力的是 pack.js它读取命令行传入的每个文件生成static const unsigned char vN[] {...}字节数组末尾补 0 使其成为 asciz 字符串并附带{/path, vN, sizeof(vN)-1, mtime}元信息最终输出mg_packed_files[]数组。配合 Mongoose 提供的打包文件系统接口见 mongoose.h 与 src/fs_packed.cextern const struct mg_mem_file *mg_mem_files; // 激活打包 FS 的挂载点 struct mg_str mg_unpacked(const char *path); // 按路径取打包资源 extern const struct mg_mem_file mg_packed_files[]; // 打包资源表示例通过mg_mem_files mg_packed_files激活打包 FSTLS 证书也走同一通道加载opts.cert mg_unpacked(/certs/server_cert.pem); opts.key mg_unpacked(/certs/server_key.pem); mg_tls_init(c, opts);由于所有 Web 资源HTML/JS/CSS/证书都以 gzip 压缩后的二进制形式躺在固件里设备即便完全没有外部存储也能完整提供 HTTPS 页面服务——这正是 README 所说对 FS 问题具有弹性的含义。前端Preact 单页应用与两个核心页面前端入口 index.html 通过 CDN Tailwind 与history.min.js提供样式与 hash 路由主逻辑在 main.jsES Module从bundle.js导入h, render, useState, useEffect, useRef, html, Router。应用基于Preact htm编写包含两个页面Modbus Master Console默认页表单控件与后端 JSON 参数一一对应Slave URLtcp://192.168.0.100:502默认即从站 TCP 地址Connect timeout毫秒范围 50–5000默认 1500Slave ID1–253默认 1Starting Register0–65535默认 0Register Count1–125默认 1改变数量时自动把 Values 重置为零填充数组Values写寄存器功能码 16/6时使用格式如1或1,2,3Function下拉选择 3读多保持寄存器、4读多输入寄存器、16写多保持寄存器、43读设备标识。点击 Execute 后发起fetch(api/modbus/exec, {method: post, body: JSON.stringify({...})})响应 JSON 格式化显示在右侧pre面板中。Settings 页设备设置包含两个区块MQTT Forwarding开关mqtt_enabled、mqtt_server_url、mqtt_topic_rx、mqtt_topic_tx点击 Save Settings 通过api/settings/set保存成功后弹出 Notification 提示Console Loglog_level下拉Disable/Error/Info/Debug 对应 0–3。页面上还以 Developer Note 形式说明了 MQTT 转发协议每次成功查询到 Modbus 从站后设备会向 TX 主题发送一条 MQTT 消息同时RX 主题可接收格式如下的 JSON 命令来远程触发 Modbus 请求{url: tcp://IP:PORT, reg: NUM, id: NUM, func: NUM}这使得仪表盘不仅能在本地浏览器操作还能经 MQTT 进行云侧或远程控制构成浏览器 → HTTP API → Modbus TCP 从站与MQTT RX → Modbus TCP 从站两条控制路径。小结通过 modbus-dashboard 示例可以清楚看到 Mongoose Library 的核心设计哲学单一事件循环、多连接协作。同一个mg_mgr里HTTP 监听连接fn回调、Modbus 客户端连接mfn回调、SNTP 定时器彼此独立又通过mg_call/MG_EV_USER协同——设备仪表盘所需的前端服务、后端 API、现场总线通信与云端桥接仅凭数 KB 的 C 代码即可全部承载。如果你打算为嵌入式设备做一个自带 Web 界面、支持现场总线、可远程管理的完整方案这个示例的结构net.h的抽象接口 pack.js的资源打包 JSON API 路由是一个极佳的参考起点。更完整的图文教程可进一步参考同仓库的 tutorials/device-dashboard 系列array/full/minimal 三个变体与 tutorials/mqtt 下的 MQTT 相关示例。【免费下载链接】mongooseEmbedded web server, with TCP/IP network stack, MQTT and Websocket项目地址: https://gitcode.com/gh_mirrors/mon/mongoose创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

告别官方文档迷雾:私钥管理入门到精通实战

告别官方文档迷雾:私钥管理入门到精通实战

告别官方文档迷雾:私钥管理入门到精通实战 官方文档动辄上百页,读完还是不知道私钥该存哪?别急,这篇教程直接带你从0到1搞定。…

2026/9/23 14:22:23 阅读更多 →
「请3休13」长假远程挂机谁更靠谱?实测ToDesk、向日葵、RustDesk远程稳定性、断线重连、远程终端

「请3休13」长假远程挂机谁更靠谱?实测ToDesk、向日葵、RustDesk远程稳定性、断线重连、远程终端

前言五一、国庆这种长假,数字爱好者最纠结的不是去哪玩,而是家里那台电脑怎么安排。游戏挂着自动刷材料、下载任务挂着跑满带宽、AI模型跑个几天几夜——这些场景有个共同点:人不在电脑前,但电脑不能停。远控软件在这个场景里解决…

2026/9/23 14:22:23 阅读更多 →
Webamp 集成 Milkdrop 可视化:基于 Butterchurn 的 Milkdrop 可视化器完全使用指南

Webamp 集成 Milkdrop 可视化:基于 Butterchurn 的 Milkdrop 可视化器完全使用指南

前端音视频 【免费下载链接】webamp Winamp 2 reimplemented for the browser 项目地址: https://gitcode.com/gh_mirrors/we/webamp 点击查看 免费下载 Milkdrop 是 Winamp 上最具代表性的音乐可视化效果,Webamp 通过 JavaScript 移植版 Butterchurn 在…

2026/9/23 14:21:22 阅读更多 →

最新新闻

ESP、MSR与恢复分区:UEFI/GPT电脑启动的三大核心分区

ESP、MSR与恢复分区:UEFI/GPT电脑启动的三大核心分区

1. 这三个“看不见”的分区,才是现代电脑真正开机的钥匙你有没有试过重装系统时突然发现磁盘里多出几个100MB、500MB甚至几GB的“空白分区”,既打不开又删不掉?右键一看属性——类型是“系统”“恢复”“EFI系统分区”,名字一串乱…

2026/9/23 14:59:23 阅读更多 →
3步搞定sd卡分区恢复图解原理避坑指南

3步搞定sd卡分区恢复图解原理避坑指南

3步搞定sd卡分区恢复图解原理避坑指南 别再说自己只会写 Hello World 了。 你是不是也卡在“语法都背下来了,但面对一个脏盘、坏道或者误格式化的 SD 卡时,脑子一片空白”? 别急,今天不聊虚的,咱们直接拆解 sd卡分区恢复…

2026/9/23 14:59:23 阅读更多 →
系统架构师-云原生架构

系统架构师-云原生架构

一、云原生架构的含义 云原生架构是一种以业务逻辑为中心、以云设施为依托的架构方法论。它的核心动作是:把应用里那些跟业务无关、但每个应用又不得不写的代码——比如服务发现、负载均衡、熔断重试、安全认证、监控埋点、配置管理、弹性伸缩——全部从业务代码中剥…

2026/9/23 14:59:23 阅读更多 →
基于OpenCV的轻量级陌生人实时报警系统

基于OpenCV的轻量级陌生人实时报警系统

简介:这是一套面向计算机专业本科生的Python毕业设计实战项目,基于OpenCV实现视频流中实时人脸识别与陌生人报警功能,适用于课程设计、期末大作业及项目能力强化训练。资源包共40个文件,涵盖5个UI界面设计文件(.ui&…

2026/9/23 14:59:23 阅读更多 →
SOFC热应力耦合仿真与优化实践

SOFC热应力耦合仿真与优化实践

1. 项目背景与核心价值固体氧化物燃料电池(SOFC)作为第三代燃料电池技术,因其高效率、低排放和燃料灵活性,在分布式发电和清洁能源领域具有重要应用前景。但在实际运行中,热应力导致的电池结构失效是制约其寿命的关键因…

2026/9/23 14:59:23 阅读更多 →
二维爆炸波FDTD仿真实战:从ZIP包到可信压力场

二维爆炸波FDTD仿真实战:从ZIP包到可信压力场

简介:本资源是一套面向计算物理、数值分析与科学计算初学者的二维波动方程数值模拟实践代码集,聚焦有限差分法(FDM)在偏微分方程求解中的核心应用,适用于高校物理、工程力学、声学仿真等方向的学习与教学。压缩包共6个…

2026/9/23 14:58:22 阅读更多 →

日新闻

3招搞定手机怎么下载微信面试难题实战项目解析

3招搞定手机怎么下载微信面试难题实战项目解析

3招搞定手机怎么下载微信面试难题实战项目解析 面试被问“手机怎么下载微信”背后的原理,90%的人答不上来。别笑,这看似弱智的问题,实则是考察你对移动应用分发机制、安全校验及网络协议理解的试金石。我带过不少校招新人,他们背了八股文,却连一个A…

2026/9/23 0:00:23 阅读更多 →
2k显示屏性能优化踩坑:版本升级后API全变了,这份源码解析救了我

2k显示屏性能优化踩坑:版本升级后API全变了,这份源码解析救了我

2k显示屏性能优化踩坑:版本升级后API全变了,这份源码解析救了我 刚把开发环境的显示器从1080P换到2K,跑老项目直接报错,版本升级后 API…

2026/9/23 0:01:25 阅读更多 →
3步搞定美眉图实战项目,告别官方文档抓不住重点

3步搞定美眉图实战项目,告别官方文档抓不住重点

3步搞定美眉图实战项目,告别官方文档抓不住重点 官方文档翻了三遍还是云里雾里?别急,美眉图在实战项目中常被用来做数据可视化,但它的原理比你想的简单。今天咱们直接上手,用一个完整的小项目把美眉图跑通,不再死磕那些冗长的理论说明。…

2026/9/23 0:01:25 阅读更多 →

周新闻

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

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

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

2026/9/23 4:55:02 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

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

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

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

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

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

2026/9/23 9:53:41 阅读更多 →

月新闻

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

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

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

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

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

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

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

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

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

2026/9/23 9:53:40 阅读更多 →