您当前的位置: 首页 >  嵌入式

暂无认证

  • 11浏览

    0关注

    94681博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

基于BOA的嵌入式Web项目【机房温度监控】

发布时间:2022-05-14 22:02:54 ,浏览量:11

文章目录
    • 一、需求分析
    • 二、项目结构
    • 三、效果图
    • 四、数据传输
      • 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 代码
 <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 <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)                   <iframe height="740" src="https://ac.yunyoujun.cn" align="right"> 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);             
关注
打赏
1655516835
查看更多评论
立即登录/注册

微信扫码登录

0.0507s