基于BOA的嵌入式Web项目【机房温度监控】
文章目录
- 一、需求分析
- 二、项目结构
- 三、效果图
- 四、数据传输
- 4.1 采集端数据传输到CGI进程
- 4.2 CGI进程数据传输到Web服务器
- 4.3 Web服务器传输给浏览器
- 五、 采集端
- 5.1 思路
- 5.2 代码
- 六、CGI进程
- 6.1 思路
- 6.2 代码
- 七、Web界面
- 7.1 思路
- 7.2 代码
- 八、最后
- 8.1 项目结构
- 8.2 感受
- 8.3 项目下载连接
一、需求分析
我们的需求很简单,采集端不断的通过温度传感器采集温度,然后传输到web
前端页面进行显示,超过一定温度进行预警或者变化操作,如果后续还有什么需求可以直接添加。
二、项目结构
采集端采集数据 ==> CGI进程 ==> Web服务器 ==> 浏览器显示
更加详细的结构参考下图:
三、效果图
我们动态加载机房温度,并且当机房的温度超过90°的时候我们的监控就会出现红条警告,右边我们内嵌了一个空调
四、数据传输
4.1 采集端数据传输到CGI进程
对于这两个端口的数据传输,我们选择使用共享内存
的方式,此时我们的数据采集端就作为了写入端,不断的往共享内存中写入数据,然后我们的CGI
进程就不断的读取数据,这里目前不考虑原子性操作,于是没有写入信号量相关的代码限制
这里可以查看我之前写的关于共享内存的简单解析:https://acmer.blog.csdn.net/article/details/124708423
4.2 CGI进程数据传输到Web服务器
这里的话就是前端知识了,我们的CGI
每次调用返回一个json
数据,然后用ajax
解析这个数据,并且通过jquery.js
的动态制图绘制出机房五台电脑的温度变化
4.3 Web服务器传输给浏览器
这里的这一步就是Boa
服务器帮我们完成的啦,这里只需要简单配置一下Boa服务器就好了,可以跟着我的这篇博客配置:
https://acmer.blog.csdn.net/article/details/124388148
注意的是这里CGI路径并未配置,当然你也可以将你的cgi
程序放在它默认的地方,但为了方便管理我们还是更改了一下cgi
的读取位置,在最后一行的cgi-bin
:ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
将后面的位置改为你项目存放cgi
程序的位置,我这里的话是存放在/home/mangata/webpro/cgi
五、 采集端
5.1 思路
对于采集端,由于没有硬件的设备,我们这里就造一些随机数字就好了,于是我们只需要随机化五个机房的温度,并且写入共享内存中即可
5.2 代码
我们这里给这个命名为sim_catch.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "task.h"static struct task_infos *tasks;
static char* task_lables[]={"机房1","机房2","机房3","机房4","机房5"};
//获取随机数据
void get_data(int num){tasks->num = num;//设置机房的数量for(int i = 0;i < num; ++i) {tasks->data[i].temp = (rand() % 9000 + 1000)/100.0;//将数据限制在(0,100.0)的浮点数据snprintf(tasks->data[i].label,sizeof(tasks->data[i].label),"%s",task_lables[i]);//像共享内存写入数据}
}
//数据打印在控制台显示
void show_data(){for(int i = 0;i < tasks->num; ++i) {printf("the label is: %s,the temp is %.2lf\n",tasks->data[i].label,tasks->data[i].temp);}
}int main()
{srand(time(NULL));//随机数播种tasks = (struct task_infos *)init_shm();//初始化共享内存while(1){//每隔2s获取一次温度数据get_data(5);sleep(2);}return 0;
}
六、CGI进程
6.1 思路
通过共享内存我们可以获取到sim_catch.c
在共享内存中写入的温度数据,这里要构造成json
字符串,我们需要借助一个外部的库,cJSON
通过这个文件我们就能很容易构造出我们想要的JSON
字符串了,这里想要学习如何构造可以去网上搜一些资料,当然也可直接看项目中的readme
文件,通过官方的几个小例子也可以快速学会(这里留个坑,后面有时间精读一下项目)
6.2 代码
然后我们就能构造出我们需要的JSON
字符串了,这个CGI
进程我们取名temo_cgi.c
//
// Created by Mangata on 2022/5/10.
//#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "task.h"
#include "cJSON.h"static task_infos *tasks;void send_json(){int num;char temp[32];char *string;cJSON *infos = NULL;cJSON *info = NULL;cJSON *monitor = cJSON_CreateObject();if (monitor == NULL){goto end;}num = tasks->num;cJSON_AddItemToObject(monitor,"num", cJSON_CreateNumber(num));infos = cJSON_CreateArray();if(infos == NULL){goto end;}cJSON_AddItemToObject(monitor,"data",infos);for(int i = 0;i < num; ++i) {info = cJSON_CreateObject();if(info == NULL) {goto end;}cJSON_AddItemToArray(infos,info);cJSON_AddItemToObject(info,"label", cJSON_CreateString(tasks->data[i].label));snprintf(temp,sizeof temp,"%.2lf",tasks->data[i].temp);cJSON_AddItemToObject(info,"temp", cJSON_CreateString(temp));}string = cJSON_Print(monitor);if (string == NULL){fprintf(stderr, "Failed to print monitor.\n");} else {printf("%s",string);}free(string);
end:cJSON_Delete(monitor);return;
}int main()
{printf("Content-Type:text/html;charset=utf-8\r\n");printf("\r\n");tasks = (task_infos*)init_shm();if(tasks == NULL) {return -1;}send_json();return 0;
}
七、Web界面
7.1 思路
这里使用了bootstrap
框架,简单绘制了一下,只用到了几个控件,就没有什么好讲的,中间有一些注释的语句,那些是另一种刷新方式,手动刷新,没有使用定时器,另外界面的右侧,嵌入了一个在线空调(虽然感觉没什么用)
7.2 代码
<!DOCTYPE html>
<html lang="en">
<head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Home</title><link rel="stylesheet" href="css/bootstrap.min.css"><script src="js/bootstrap.min.js"></script><script src="js/jquery.min.js"></script><script src="js/echarts.common.min.js"></script>
</head>
<body>
<nav class="navbar navbar-inverse"><div class="container-fluid container"><!-- Brand and toggle get grouped for better mobile display --><div class="navbar-header"><button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"><span class="sr-only">Toggle navigation</span><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></button><a class="navbar-brand" href="#">xxx机房监控</a></div><!-- Collect the nav links, forms, and other content for toggling --><div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"><ul class="nav navbar-nav"><li class="active"><a href="#">温度监控<span class="sr-only">(current)</span></a></li><li><a href="#">机房电脑</a></li></ul></div><!-- /.navbar-collapse --></div><!-- /.container-fluid -->
</nav><!--<div class="container">-->
<!-- <h1 class="text-center">机房管理</h1>-->
<!-- <table class="table table-bordered table-hover" id="tab_ctx">-->
<!-- <thead>-->
<!-- <tr>-->
<!-- <td>编号</td>-->
<!-- <td>机器名</td>-->
<!-- <td>温度</td>-->
<!-- </tr>-->
<!-- </thead>-->
<!-- <tbody>-->
<!-- </tbody>-->
<!-- </table>-->
<!-- <hr>-->
<!-- <button type="button" id="bt1">添加任务</button>--><!--</div>-->
<!--<script>-->
<!-- $(document).ready(function (){-->
<!-- $("#bt1").click(function (){-->
<!-- $.getJSON("cgi-bin/temp_cgi",function (info){-->
<!-- $("#tab_ctx tbody").html('');-->
<!-- // console.log(info);-->
<!-- for(let idx in info.data){-->
<!-- let context = "<tr><td>"+idx+"</td>"-->
<!-- +"<td>" + info.data[idx].label + "</td>"-->
<!-- +"<td>" + info.data[idx].temp +"℃"+ "</td></tr>";-->
<!-- $("#tab_ctx tbody").append(context);-->
<!-- }--><!-- });-->
<!-- });-->
<!-- });-->
<!--</script>--><iframe height="740" src="https://ac.yunyoujun.cn" align="right"></iframe>
<div id="main" style="width: 1000px;height:600px;"></div><script type="text/javascript">// 基于准备好的dom,初始化echarts实例let myChart = echarts.init(document.getElementById('main'));let data = [];for (let i = 0; i < 5; ++i) {data.push(Math.round(Math.random() * 100));}option = {color: ['#dd6b66','#759aa0','#e69d87','#8dc1a9','#ea7e53','#eedd78','#73a373','#73b9bc','#7289ab','#91ca8c','#f49f42','#129'],xAxis: {max: 100.0},yAxis: {type: 'category',data: ['机房一', '机房二', '机房三', '机房四', '机房五'],inverse: true,animationDuration: 300,animationDurationUpdate: 300,max: 4 // only the largest 3 bars will be displayed},series: [{realtimeSort: true,name: '机房温度实时监控℃',type: 'bar',data: data,label: {borderRadius: 14,show: true,position: 'right',valueAnimation: true},itemStyle: {borderRadius: [0, 5, 5, 0],color: '#129',opacity: 0.5}}],legend: {show: true},animationDuration: 2000,animationDurationUpdate: 2000,animationEasing: 'linear',animationEasingUpdate: 'linear'};function update() {let data = option.series[0].data;$.getJSON("cgi-bin/temp_cgi",function (info){let fg = Number(0);for(let idx = 0;idx < data.length; ++idx){let temp = Number(info.data[idx].temp);if(parseFloat(temp) > parseFloat(90.0)){fg = Number(1);console.log("temp ok");}data[idx] = temp;//Math.round(Math.random() * 2000);// Number(info.data[idx].temp);}// console.log(option.series[0].itemStyle.color);if(fg === 1) {option.series[0].itemStyle.color = option.color[0];} else {option.series[0].itemStyle.color = option.color[11];}})myChart.setOption(option);}setInterval(function() {update();}, 2000);</script></body>
</html>
八、最后
8.1 项目结构
有一些文件只是用来测试学习的,所以看起来有一点冗余
8.2 感受
这次写完这个项目的感受是,难度不高甚至可以说很低了,但是生知识比较多,原理也都挺简单,感觉用C语言写Web
项目还是有一点麻烦,不过通过这次的学习,弄清楚了进程间的通信、CGI程序等知识,也了解了cgic
和cjson
这两个外部库的方便之处,希望有朝一日能够更加深入学习。
8.3 项目下载连接
https://download.csdn.net/download/m0_46201544/85374880
这里由于项目功能单一,技术难度较低我就不传Github
了,感兴趣的同学可以直接在CSDN下载了(应该不要钱)
基于BOA的嵌入式Web项目【机房温度监控】相关推荐
- 【ARM】在NUC977上搭建基于boa的嵌入式web服务器
一.实验目的 搭建基于arm开发板的web服务端程序,通过网页控制开发板LED状态 二.boa简介 Boa服务器是一个小巧高效的web服务器,是一个运行于unix或linux下的,支持CGI的.适合于 ...
- 基于PC与单片机串口通信的温度监控系统程序设计
基于PC与单片机串口通信的温度监控系统程序设计 1.系统介绍 1)本系统主要讲解基于PC与单片机串口通信的温度监控系统程序设计(如图1),上位机采用常用的PC机,下位机使用的是STC89C52单片机, ...
- 基于ESP8266的阿里云远程实时温度监控
基于ESP8266的阿里云远程实时温度监控 基于ESP8266的远程实时温度监控 基于ESP8266的远程实时温度监控系统,通过ESP8266开发板采集DHT11温湿度传感器的数据,在连接WIFI接入 ...
- 嵌入式实践项目(二)——机房温度监控系统
文章目录 项目环境 IDE 其他 项目效果 源码结构 Qt back-end 阅读代码的Tips Qt界面 back-end Tisp 源码下载地址 项目环境 IDE qt-opensource-wi ...
- 基于IntelliJIdea2020.3创建web项目
最近开始从eclipse编辑器转到IntelliJIdea编辑器.采用的IntelliJIdea的版本是IntelliJIdea2020.3.下面是记录创建一个web项目的过程.这个只是利用Intel ...
- java web 项目整合javamelody监控插件
第一种:普通javaweb项目 导入jar包: 启动项目的时候监控系统自动启动,无需配置(jdk1.7,tomcat 7 环境下): 访问:http://主机地址:端口号/项目名/monitoring ...
- 嵌入式Web项目(一)——Web服务器的引入
文章目录 网络模型 TCP服务器的概念 Wed服务器的概念 netstate 工具 嵌入式系统,常用开源Web服务器 移植BOA到Ubuntu 下载BOA源码 传输到虚拟机进行解压 编译BOA 修改B ...
- 嵌入式Web项目(二)——CGI的引入
文章目录 静态网页工作原理 动态网页工作原理 CGI的概念 CGI工作原理 boa配置静态文件与CGI文件访问路径 静态文件 CGIPath 动态网页 以shell语言,实现动态网页案例 第一次访问测 ...
- 基于springcloud构建一个web项目
日子还很长,技术沉淀得一步步的来.先会用,然后再看实现原理 本篇博客有点长,个人觉得还是比较细致,希望对入手spring cloud的朋友能有所帮助 本来一直都想实践一下zookeeper的,但是看了 ...
最新文章
- 利用OTP为odoo增强安全访问
- nginx限制ip,只允许域名访问
- 路由器交换机命令总结
- mysql主从复制自增_关于mysql主从复制自增长列
- MySql恢复密码的过程
- [转]IPython介绍
- 程序无法启动ALL_BUILD 拒绝访问
- 导致Oracle性能抖动的参数提醒
- python变量类型之间转换_【Python】Python 变量类型(变量赋值,数据类型,数据转换)...
- gcc编译ceres-solver报错‘is_trivially_default_constructible’ is not a member of ‘std’
- group by with cube
- 怎样打开android设备,在app中打开android设备的存储
- PMP第六节:项目进度管理
- 判断闰年简单逻辑运算符
- python大数据运维工程师待遇_什么是大数据运维工程师
- 南柯服务器压力,南柯梦崇洋(十一)
- 非常有意思的网页版在线PS
- 电工结业试卷_修补电工结业论文
- Python学习:图片数据归一化处理
- python加密安装方法_安装Python加密错误
热门文章
- Zabbix监控系统的搭建
- R语言如何合并Excel多行的重复数据
- 实训十七:交换机单端口环路检测配置
- web前端学习到什么程度可以面试工作
- HUAWEI 机试题:工厂流水线调度
- hadoop支持lzo完整过程
- 《Flutter入门疑难杂症》imagepicker ImagePicker().getVideo()返回.jpg
- 狗狗的年龄的python编程_狗狗与人年龄换算表,终于知道狗狗多大了!
- java程序license验证_基于TrueLicense实现产品License验证功能
- 用html做相册需要什么,如何快速有效的生成HTML相册?