基于BOA的异步环境参数监测及气象预报系统设计
2020-11-06傅玥郭航宇李解谭海洋
傅玥 郭航宇 李解 谭海洋
摘 要:为了让操作者可以通过浏览器维护和管理监测点,方便其查看监测数据,设计利用BOA服务器搭建嵌入式Web控制器、传输层选择有三次握手和超时重传机制的TCP并包含了针对数据发送的防丢失措施。采用AJAX技术实现环境参数异步传输,以JSON格式作为数据交互格式,用CGI实现客户端与服务器端的请求和响应,Shell脚本实现CGI程序动态访问、自动更新环境参数。
关键词:嵌入式Web服务器;BOA;CGI;AJAX数据通信;JSON
中图分类号:TP274;S828 文献标识码:A 文章编号:2096-4706(2020)13-0077-05
Abstract:In order to enable the operator to maintain and manage the monitoring points through the browser,so as to facilitate the operator to view the monitoring data,the BOA server is used to build the embedded Web controller,the TCP with three handshakes and timeout retransmission mechanism is selected in the transport layer,and the anti-loss measures for data transmission are included. AJAX technology is used to realize asynchronous transmission of environment parameters. JSON format is used as data exchange format. CGI is used to realize client-side and server-side request and response. Shell script is used to realize CGI program dynamic access and automatic update of environment parameters.
Keywords:embedded Web server;BOA;CGI;AJAX data communication;JSON
0 引 言
该系统设计通过BOA源码官网下载BOA源码,在Ubuntu下搭建嵌入式BOA服务器,代码打通用户级与内核级之间数据传递问题,方便用户通过浏览器实时获取当前环境气象状况,功能上分为两个板块。第一板块利用jQuery的子集Cheerio进行对天气网气象DOM的爬取,实际运行的时候使用SuperAgent实时抓取网页;第二板块需串口接收外部集成传感器捕获的数据,用户点击“获取数据”按钮触发传感器采集当前环境参数,采集的数据通过外部程序执行通道CGI(通用网关接口)返回至浏览器界面。BOA服务器将传感器检测的环境参数传给CGI,被编译的CGI可执行程序自动调用append()将新数据追加到文档末尾,经BOA服务器送回浏览器显示;AJAX数据异步传输实现动态和静态网页的分离效果,服务器与浏览器只交换更新的数据即每次更新的环境参数,HTML格式的静态网页保持不变。该设计方法大幅降低网络流量、提升运行速度,数据记录基于Echarts生成历史温度曲线统计和湿度曲线统计。
1 Ubuntu安装C语言编译环境
在LINUX嵌入式系统平台VMware Workstation中安装Ubuntu,Ubuntu版本建议:18.04LTS或20.04LTS(安装最小系统即可)。
(1)最小系统没有C语言编译环境,需要另外安装,建议安装软件有GCC、Make、Vim工具。
$ sudo apt install gcc make vim-nox
(2)为了方便后期向虚拟机传送文件和操作LINUX系统,安装SSHD服务。
$ sudo apt install openssh-server
(3)若需要在开发板上进行Web服务的搭建,还需要安装对应开发板的交叉编译器环境,同时配置系统环境变量和交叉编译器所依赖的库。
$ sudo apt install lib32ncurses5 lib32z1
(4)在Windows中可以使用MobaXterm这类软件配置SSH客户端信息,并连接虚拟机的Ubuntu系统。
(5)选择一款自己熟悉的编辑器,比如VS Code、Notepad++、CLion等。
(6)如果需要开发板,配置好串口、虚拟机双网卡(可选)环境。
2 BOA软件服务的移植
BOA服务器是一个小巧高效的Web服务器,是一个运行于UNIX或LINUX下的、支持CGI的、适合于嵌入式系统的、单任务的HTTP服务器,源代码开放、性能高[1]。运行于客户端的浏览器首先需与嵌入式Web服務器BOA端建立连接,打开一个套接字虚拟文件,此文件的建立标志着SOCKET连接建立成功。然后客户端浏览器通过套接字SOCKET以GET或者POST参数传递方式向Web服务器提交请求。Web浏览器提交请求后,通过HTTP协议传送给Web服务器。Web服务器接到请求后,根据请求的不同进行事务处理,返回HTML文件或者通过CGI调用外部应用程序,返回处理结果。服务器通过CGI与外部应用程序、脚本进行交互;根据客户端浏览器在请求时所采用的方法,服务器会搜集客户所提供的信息,将部分信息发送给指定的CGI扩展程序;CGI扩展程序进行信息处理并将结果返回给服务器,接着服务器对信息进行分析,将结果发送回客户端浏览器显示[2]。
嵌入式Web服务器BOA移植步骤:
(1)官网下载好BOA源码压缩文件boa-0.94.13.tar.gz。
(2)编辑TCP Socket连接代码文档,MobaXterm软件中创建tcp_base_server.c。
源代码如下:
#include
#include
#include
#include
#include
#include
#include
#include
/*
* TCP初始化服务器模型代码
* */
int init_socket(unsigned short port){
int tcp_socket;
struct sockaddr_in self;
int ret;
tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
if (tcp_socket == -1) {
perror("socket");
return -1;
}
// 绑定自己开放的IP和端口
memset(&self, 0, sizeof(self));
self.sin_family = AF_INET;
self.sin_port = htons(port);
self.sin_addr.s_addr = INADDR_ANY;
ret = bind(tcp_socket, (struct sockaddr *)&self, sizeof(self));
if (ret == -1) {
perror("bind");
return -1;
}
listen(tcp_socket, 5);
return tcp_socket;
}
int main(){
int listen_fd;
int new_fd;
char buf[1024];
int ret;
char *tmp = "Hello World";
listen_fd = init_socket(8181);
if (listen_fd == -1){
fprintf(stderr, "init socket error!\n");
return -1;
}
printf("listen...\n");
//接收有没有新的连接请求,从listen_fd描述符对应的空间来取出客户端连接
while(1){
new_fd = accept(listen_fd, NULL, NULL);
if (new_fd == -1) {
perror("accept");
return -1;
}
printf("have a new connection!\n");
// 接收新客户端发来的请求
ret = recv(new_fd, buf, sizeof(buf)-1, 0);
buf[ret] = 0;
printf("接收的内容: %s\n", buf);
// 响应客户端的请求
write(new_fd, tmp, strlen(tmp));
// getchar();
close(new_fd);
}
close(listen_fd);
return 0;
}
mkdir -p web_prj/test创建web_prj目录和子目录test,将代码文档tcp_base_server.c移动到test目录下,执行命令gcc -o tcpserver tcp_base_server.c进行编译,直接运行TCPServer程序./tcpserver打印出监听描述符。Web服务器是应用层,TCP服务器是指在傳输层选择了TCP(传输控制协议)。浏览器是客户端,只要Web服务器在传输层采用了TCP协议来传输,我们就将这个Web服务器等效为TCP服务器。如果TCP服务器运行成功,在操作系统上传输层上应该体现出TCP的一个特性(端口号),这个特性属于操作系统内核,不能直接查看。TCPServer程序已经在一个终端运行,在第一个终端按Ctrl+C结束TCPServer程序运行,在另一个终端用netstat -tan查看传输层状态,如果显示“tcp 0 0 0.0.0.0:8181 0.0.0.0:* LISTEN”说明8181端口开启,相当于在运输层TCP上烙下烙印,以保证BOA服务器后续的正常访问。
3 boa.conf的配置
需要核对boa.conf(BOA服务配置文件)里写到的目录是否实际存在,程序根据配置文件里的目录创建文件,如果系统中不存在这些目录就会报错。如果虚拟机上没有变量后面的路径信息目录值,就需要单独创建。mkdir web_prj/sources在web_prj目录下创建sourxes目录,cp boa-0.94.13.tar.gz web_prj/sources/把boa-0.94.13.tar.gz拷到sources目录下,tar-zxvf boa-0.94.13.tar.gz-C../将BOA服务器包解压到上级目录web_prj下。cd boa-0.94.13/进入boa-0.94.13,源代码中没有Makefile,接下来需要配置生成Makefile。
(1)根据目标机器特性配置configure脚本,./configure执行脚本我们就可以看到Makefile的出现。
(2)用Vim Makefile修改Makefile使其支持目标板的工具。修改完成按Esc,命令行下输入“:wq!”保存退出。
(3)在Vim compat.h修改配置文件,打开后处于普通模式。这时按i键进入插入编辑模式,按a键进入追加编辑模式,编辑模式中按Esc又变成普通模式。其中两行添加指针传递值“foo->”修改后#define TIMEZONE_OFFSET(foo) foo->tm_gmtoff、#define TIMEZONE(foo) foo->tm_zone执行Make,stripboa剔除符号表压缩后大小只有80 K。
~/web_prj/boa-0.94.13/src$ strip boa
~/web_prj/boa-0.94.13/src$ -lh boa
-rwxr-xr-x 1 fy fy 80K Jun 8 02:59 boa
4 浏览器访问路径原理和服务配置文件的对应关系
HTTP请求有八种方法:GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT,GET和POST比较常用。Web浏览器把用户的操作解析为标准数据流,将符合HTTP通信协议规范的客户请求向服务器发出。服务器在接收到用户从客户机发送的相关请求后,一般是在后台进行查询和运算等工作,再将结果传回用户端Web浏览器进行显示[3]。一次完整的HTTP请求过程如下:用户访问网站需要在浏览器上输入URL或者域名按下回车,每个网站对应一个服务器进程,它不断地监听TCP端口;一旦监听到连接建立请求并建立了TCP连接,浏览器就向服务器发出浏览某个页面的请求[4],浏览器解析HTML代码并请求代码中的资源(如JS、CSS、图片等),网页访问完毕后释放TCP连接。如果使用输入域名的方式,则在建立连接请求前还需域名解析步骤,将消息从PC端上传到服务器上,需要用到IP协议、ARP协议和OSPF协议。
程序的一次编译,能够在多个不同的環境进行运行。BOA配置文件告诉BOA程序如何进行工作,修改.config之前先备份cp boa.conf boa_bak.conf防止改错后无法恢复。在boa-0.94.13目录下创建目录sudo mkdir/etc/boa,再将boa.conf拷贝到/etc/boa目录里面。sudo vim /etc/boa/boa.conf修改配置文件的用户名User和用户组Group为fy、错误日志ErrorLog路径为/home/fy/boa/error_log、访问日志AccessLog路径为/home/fy/boa/access_log、指定Web根目录DocumentRoot路径为/home/fy/web_prj/works/www、服务器使用alias指令配置虚拟目录Alias /doc /usr/doc、修改CGI查询目录ScriptAlias/cgi-bin//home/fy/web_prj/works/cgi/,正确配置以保证浏览器成功访问BOA服务器。如果BOA没有绑定成功是因为端口号80被占用,修改boa.conf文件配置的Port为8082后再次输入netstat-tan查看传输层状态“tcp 0 0 0.0.0.0:81820.0.0.0:* LISTEN”。非正常关闭Vim编辑器时会生成一个.swp文件和.swo文件,移除.boa.conf.swp和.boa.conf.swo文件。cd /web_prj/boa-0.94.13/src后执行sudo./boa开启BOA服务器,sudocatboa/error_log方便查看BOA服务器报错。
5 BOA服务下Shell脚本实现CGI程序动态访问
CGI(通用网关接口)工作原理可以简单理解为Web服务器和程序动态生成数据之间的一个执行外部程序通道,保证浏览器与服务器之间更灵活地进行交互。调用CGI脚本的信息交互方法有GET和POST两种:GET一般用于获取或者查询资源信息,而POST一般用于更新资源信息;浏览器显示的是动态的数据信息,所以系统采用POST方法[5]。CGI程序可以用任何程序设计语言编写,如Shell脚本语言、Perl、FORTRAN、Pascal、C语言等[6]。简单起见,本系统采用Shell脚本编写的CGI程序动态响应用户在Web上的操作。mkdir home/fy/www再静态网页代码移植到www目录,打开浏览器输入包含完整IP和端口号的Shell绝对路径“http://192.168.117.136:8082/fy/index.html”访问静态页面,访问成功表明静态文件测试通过。编写一个CGI测试程序为后续系统的搭建做准备。sudo mkdir web_prj/cgi创建用来放置动态网页的CGI目录,在CGI目录下创建time文件,输入chmod +x time给time文件增加可执行权限。
HTTP请求是由请求行、请求头部、空行和请求数据四部分组成。图1为浏览器发出HTTP请求的完整格式,请求头部的最后有一个空行表示请求头部结束,后面连接请求正文。程序语言中“\r”表示一个回车符,“\n”表示一个换行符,“\r\n”代表另起一行保证HTTP请求完整的头部信息,缺少会导致浏览器访问网页出现“502 Bad Gateway”错误。CGI程序time中特别注意一行echo“Content-Type:text/html;charset=utf-8\r\n”。Shell编写的CGI程序放在/cgi-bin/目录下,动态数据通过/cgi-bin/boa/home/fy/web_prj/works/cgi/路径查询获取。
6 基于jQuery的AJAX请求JSON格式数据
针对AJAX采用XML作为数据载体存在标签大量冗余、基于DOM的解析复杂导致数据传输量大、服务器与客户端解析效率低的问题,提出一种基于JSON的AJAX数据通信快速算法[7]。AJAX包含JavaScript、XMLHttpRequest、CSS等技术,是一种快速创建交互式动态网页的技术,适合轻量级数据交互频繁的网页。本设计利用Bootstrap框架搭建呈现当前温湿度的网页,用户第一次进入网页会发送浏览器请求,服务器接收到这个请求会返回一套内容,响应的内容会被浏览器重新渲染。之后网页每时每刻只有温度、湿度值在变化,开发人员没有必要因为这一小部分重构页面,而且频繁刷新会导致网络数据量太大。AJAX方法使网页实现异步更新,意味着后台与服务器只进行少量数据交换,可以频繁更新少量数据而不重新加载整个网页。未使用AJAX的传统网页每一次更新内容必须重新加载整个网页页面。
7 环境参数监测的代码实现
前面介绍了服务器搭建、动态网页加载和数据实时获取更新的关键操作后,下面结合程序具体介绍系统在浏览器前端的显示方法。由于Ubuntu不支持数据库,串口外接温湿度传感器获取到的数据将保存在服务器下的指定文件中,前端温湿度显示是利用AJAX请求JSON格式数据,对服务器下文件进行数据查询。Shell脚本编写的CGI程序实现自动刷新当前获取的数据,整个过程没有访问数据库。第一板块编写一个读取该配置文件的接口类Zone.java获取操作系统时区,利用jQuery的子集Cheerio对数值预报气象要素所在路径(天气网)的气象报告和预测进行DOM的爬取。部分代码如下:
TimeZone.getDefault();
// 获取任意指定区域的时区
String[] zoneIDs=TimeZone.getAvailableIDs();
for(String zoneID: zoneIDs) {
TimeZone.getTimeZone(zoneID);
}
引入Cheerio:
var cheerio=require('cheerio'),
$=cheerio.load('
- ...
DOM获取天气网气象數据:
var cheerio=require('cheerio'),
$=cheerio.load('
WIDGET={ID: 'BYUxbXHVQw'};
引入bootstrap.min.js文件将所有插件包含在一个项目中,后续开发仅仅通过data属性API就能使用所有Bootstrap中的插件[8],且不用写JavaScript代码。引入完整版的jQuery库将压缩后的jquery.min.js文件用于前端引用,减小代码冗余度、降低平台流量,提升浏览器访问速度。jquery.min.js文件删除了未压缩的完整jQuery库jquery.js中的空白字符、注释、空行等,并将与逻辑无关的内容进行部分优化,功能与jquery.js完全一样。
JSON是一种可以转换为字符串的数据请求对象,它以异步方式将字符串由客户端传递到Web服务器的应用程序中[9]。一周天气数据统计需要用户串口连接温湿度传感器,将测量的数据封装成JSON格式,由前面的CGI程序实时更新、传输、存储在服务器的相应文件夹下。点击“获取数据”按钮,“$(document).ready(function (){})”等待DOM结构加载完成,执行封装在事件里的函数,调用click方法“$("#btn1").click(function (){})”,触发$.getJSON("",function (){})函数到指定的/cgi-bin/temp_cgi目录读取JSON数据格式;AJAX异步传输更新浏览器数据,以“星期几 温度 湿度 风强光照强度”表格形式显示数据。$().append()功能将新的测量数据累加在表尾。部分代码如下,浏览器访问界面如图2所示。
<!--Brand and toggle get grouped for better mobile display-->
<!-- Collect the nav links, forms, and other content for toggling -->
$(document).ready(function(){
$("#btn1").click(function(){
$.getJSON("/cgi-bin/temp_cgi",function (infos){
console.log(infos);
$("#text tbody").html("");
for (let item in infos.data){
let x=infos.data[item];
varbuf= "
$("#text tbody").append(buf);
}
});
});
});
7 結 论
综上所述,外部架设集成传感器和无线传输模块一体的底层数据采集节点,并构建有线数据采集网络。将Web技术应用在环境参数监测及气象预报系统中,操作者可以通过浏览器实时采集当前环境参数、查看当天气象。基于ECHARTS生成的历史测量数据统计,准确呈现每日环境参数的变化。该设计仅为简化版,希望日后可以将涉及的编程思想和方法应用到更大型的商业项目中去。
参考文献:
[1] 360百科.boa服务器 [EB/OL].(2016-03-24).https://baike.so.com/doc/2157341-2282668.html.
[2] 佚名.嵌入式Web服务器BOA移植与测试设计概述 [EB/OL].(2019-11-01).http://m.elecfans.com/article/1102494.html.
[3] 郑坤.基于Boa服务器的猪舍环境监测系统的设计 [J].现代计算机(专业版),2014(33):56-59.
[4] 谢希仁.计算机网络:第7版 [M].北京:电子工业出版社,2017:268.
[5] 李磊.利用CGI程序实现动态Web的方法 [J].科学技术与工程,2009,9(6):1611-1613.
[6] 肖治延.用C语言进行CGI程序设计 [J].微电脑世界,1997(5):81-83.
[7] 孙光明,王硕.基于JSON的AJAX数据通信快速算法 [J].计算机应用与软件,2015,32(1):263-266.
[8] 范仁义.bootstrap课程1bootstrap为什么这么火 [EB/OL].(2018-07-06).https://www.cnblogs.com/Renyi-Fan/p/9272724.html.
[9] 郭庆燕,张敏,杨贤栋.JQuery AJAX异步处理JSON数据实现气象图片的显示 [J].计算机应用与软件,2016,33(6):20-22+67.
作者简介:傅玥(1999.05—),女,汉族,四川绵阳人,本科,研究方向:计算机嵌入式。