概述
距离上一次更新还是在上一次,这段时间一直在学习网络相关的知识。这次带来的小项目是一个基于Modbus、TCP、HTTP协议的设备数据采集和控制程序,可以实现类似智能家居的效果,实时采集温湿度和控制设备功能的开关,但是硬件知识还没有学习,只能用软件工具来模拟硬件。
实现原理
这里贴一张我们老师画的图,原理就是采集控制程序会不断读取设备存放温湿度的寄存器(输入寄存器或保持寄存器),将温湿度数据放入共享内存,当用户在浏览器请求获取温湿度时,服务器就会从共享内存中读取温湿度并发送给浏览器;当用户发送控制设备请求时,服务器会将控制数据(数据格式自定义)发送到消息队列,采集控制程序不断接收消息队列发送的控制数据对相应的外设寄存器(线圈)赋值,从而达到控制设备的目的。
关键代码
网页端
前端的代码就不多解释了,界面的设计是AI写的,但是AI的代码不能直接用,多多少少会有一些BUG导致无法实现功能,所以不但要弄懂实现的原理,还要有一些html的语法基础。
服务器
服务器的创建无非就是服务器三件套:创建套接字、绑定、监听,关键在于http协议的解析和用户请求处理。协议分析就是获取请求方法和请求数据,这部分的代码比较冗杂,就不在这里展示了,所有的源码我会放到文章下方,有需要的朋友可以下载。
int parse_and_process(int sock, const char *query_string, const char *input)
{
shm_msg_init();
if (strstr(input, "bit=") && strstr(input, "value="))
{
int number1, number2;
sscanf(input, "\"bit=%dvalue=%d\"", &number1, &number2);
msg.data[0] = number1;
msg.data[1] = number2;
msg.type = 1;
printf("bit:%d,value:%d\n", msg.data[0], msg.data[1]);
int length = sizeof(msg) - sizeof(long);
int ret = msgsnd(msgid, &msg, length, 0);
if (ret != 0)
{
perror("msgsend error");
return -1;
}
}
if (strstr(input, "get") != NULL)
{
char buf[32] = "";
sprintf(buf, "%d°C@%dRH", data[0], data[1]);
send(sock, buf, strlen(buf), 0);
}
return 0;
}
这个函数用于处理用户请求,sock是用户与服务器通信的套接字,服务器是多线程并发,每有一个用户与服务器建立通信就会创建一个线程和套接字。
query_string用于存放get请求携带的数据,input用于存放post请求存放的数据,因为这个项目的用户端获取温湿度和控制外设都不需要刷新网页,所以只会用到post请求。
用户的控制请求是以bit=%dvalue=%d(对应的寄存器和值)的形式发送到服务器,服务器会分别将寄存器地址和要修改的值放到消息队列的结构体中并发送到消息队列。
用户获取温湿度的请求会向服务器发送"get",服务器识别到"get"后会直接读取共享内存并将数据以"%d°C@%dRH"的形式发送到浏览器,浏览器会以@为分隔将温湿度分别填入文本框中。
Modbus数据采集和控制程序
该程序采用多线程编程,主线程读取温湿度,子线程修改寄存器的状态值。相比服务器,这个程序简单得多,因为使用了第三方Modbus库,很多操作可以通过直接调用函数来实现,节省了类似于读寄存器和写寄存器这样的繁琐的步骤,如果不使用这个第三方库,就得自己根据Modbus的协议格式拼接字符串。
效果展示
功能展示可空降视频1分50秒处观看。
B站视频点我查看