基于BOA的嵌入式Web项目【机房温度监控】
时间:2023-11-29 08:37:00
文章目录
-
- 一、需求分析
- 二、工程结构
- 三、效果图
- 四、数据传输
-
- 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 #include #include #include #include #include #include #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
#include
#include
#include
#include
#include
#include
#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>Hometitle>
<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">
<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 navigationspan>
<span class="icon-bar">span>
<span class="icon-bar">span>
<span class="icon-bar">span>
button>
<a class="navbar-brand" href="#">xxx机房监控a>
div>
<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>
div>
nav>
<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下载了(应该不要钱)