嵌入式应用开发笔记之web端设备控制台

发布时间:2026/7/4 20:25:18

嵌入式应用开发笔记之web端设备控制台 前正在学习嵌入式应用开发非科班非系统学习半路出家型选手但是有一定Linux基础手头正好有一个嵌入式开发设备硬件资源如下主要参数配置处理器单核792MHz Cortex® A7处理器内存DDR3 512MB存储eMMC 4GB/8GBRS2321路调试串口RS4854路CAN-bus3路以太网2路软件资源如下Ubuntu20.04系统RT-Linux内核各种驱动程序我想要把手头这个嵌入式设备的硬件资源都用起来所以做了一个web端设备控制台应用来练手其中需要的技术栈有lighttpdfcgisqlite3接下来就是开发过程了有几个阶段开发环境搭建web服务器及网页设计cgi后端代码编写di/do、led、adc、485、CAN、sqlite3)开发环境搭建采用vscodedocker的方案其中docker容器提供实际编译环境(arm-linux-gnueabihf-gcc等)vscode用于连接docker容器进行代码编写工作。docker容器部署在宿主机安装了必要的软件开发包和编译器并且添加了异质架构支持arm64armhf交叉编译嵌入式设备提供RS232的调试串口通过这个串口登录到系统中然后可以进行一些准备工作比如修改网路设置因为我需要使用ssh进行宿主机和设备端的连接并且web服务器也需要解决网络问题。宿主机可以联网设备端暂时无法联网所以需要额外的软件就需要先在宿主机编译源码然后再scp到设备端比如lighttpd和sqlite3设备端本身是没有的sqlite3的安装下载[源码](SQLite Download Page)到宿主机(docker)选择sqlite-autoconf-3530200.tar.gz这样的包用tar进行解压缩并进入到解压后的目录中配置编译环境和输出目录采用静态编译方式./configure \ --hostarm-linux-gnueabihf \ --prefix/tmp/em500/embed_pack/sqlite \ --disable-readline \ --disable-shared \ --enable-staticscp可执行文件sqlite3到设备端其余的输出文件include和lib在cgi代码中会用到web服务器及网页设计首先是对lighttpd.conf文件的配置这个文件决定了嵌入式设备于浏览器交互过程中调用的fcgi代码如下所示fastcgi.server ( # 把 /api/* 的请求交给 FastCGI 处理 /cgi-bin/app.fcgi ( app-handler ( socket /tmp/app.fcgi.socket, check-local disable, # 核心告诉 lighttpd 用哪个二进制来启动 FCGI 线程池 bin-path /var/www/cgi-bin/app.fcgi, max-procs 2, # 常驻进程数嵌入式设 1~3 即可 idle-timeout 30, ) ), /cgi-bin/history.fcgi ( history-handler ( socket /tmp/history.fcgi.socket, check-local disable, bin-path /var/www/cgi-bin/history.fcgi, max-procs 1, idle-timeout 30, ) ), )使用到两个fcgi文件app.fcgi和history.fcgi这两个fcgi代码在后面介绍网页的界面设计借助ai直接生成很简约就只有一个页面页面上的交互控件对应了嵌入式设备本身自带的硬件资源的可控/可读/可写部分图片如下所示在调试cgi功能的时候有几种调试方式wireshark抓包查看数据包的详细信息、包括请求头、请求参数等浏览器控制台查看报错信息cgi代码回发调试信息浏览器弹窗、控制台打印信息cgi后端代码编写在静态编译时所有依赖库都需要显式指定包括系统库我写了两个fcgi代码分别是app.fcgi和history.fcgi。编译history.fcgi的命令如下arm-linux-gnueabihf-gcc \ -static \ -o history.fcgi \ history.cpp \ -I$TARGET_DIR/usr/local/include \ -I$TARGET_DIR/sqlite/include \ $TARGET_DIR/usr/local/lib/libfcgi.a \ $TARGET_DIR/sqlite/lib/libsqlite3.a \ -lm \ -ldl \ -lpthread其中app.fcgi的功能是多路Led指示灯控制、多路数字输出(DO)控制、多路数字输入状态(DI)控制、以及多路ADC模拟量采集对于cgi的交互过程代码讲解如下在web端的js请求轮询请求const response await fetch(/cgi-bin/app.fcgi); const data await response.json();发送控制命令const response await fetch(/cgi-bin/app.fcgi, { method: POST, headers: { Content-Type: application/json }, body: JSON.stringify({ type: type, channel: channel,value: value }) }); const result await response.json();获取历史数据const url /cgi-bin/history.cgi?dataType${encodeURIComponent(dataType)}timeRange${encodeURIComponent(timeRange)}; const response await fetch(url, { method: GET });在设备服务器端首先是获取请求信息/* 获取请求方法 */ char *method getenv(REQUEST_METHOD); /* 获取请求资源url */ char *uri getenv(REQUEST_URI);分别处理不同请求// 处理控制请求POST if (strcmp(method, POST) 0 strstr(uri, /cgi-bin/app.fcgi)) { // 读取 POST 数据 FCGI_fread(post_data bytes_read,1, content_length - bytes_read, FCGI_stdin); // 解析JSON /* 解析type */ json_get_string(post_data, \type\, type, sizeof(type)); /* 解析channel */ channel json_get_int(post_data, \channel\); /* 解析value */ value json_get_int(post_data, \value\); } // 处理状态请求GET else if (strcmp(method, GET) 0 strstr(uri, /cgi-bin/app.fcgi)) { ... }调用硬件资源前需要确保硬件环境准备完成包括初始化、配置以及权限在调试过程中发现DO/DI这些资源多涉及到gpio的配置操作需要做export然后才能读写其次是history.fcgi的功能读取历史记录数据库是sqlite3表结构如下CREATE TABLE history( id INTEGER PRIMARY KEY AUTOINCREMENT, time TEXT, volt TEXT, curr TEXT, soc TEXT, loader TEXT);读取的历史记录效果如下

相关新闻