国产ARM/RISCV与OpenHarmony物联网项目(二)网关数据显示

本文需要Web服务器开发基础,可参考下述博文:

物联网网关Web服务器--lighttpd服务器部署与应用测试

物联网网关Web服务器--CGI开发接口

一、数据显示界面与功能设计

1、功能设计说明

程序代码结构如下,调用关系见彩色部分标示。

数据显示界面功能通过以下2个程序实现:

data_show.html 程序文件

数据显示界面用于展示各种环境数据(温度、湿度、光强和气体浓度)的可视化界面。它使用了 Bootstrap 框架来进行页面布局,ECharts 库来绘制图表,并通过 AJAX 请求从服务器端的 cgi-bin/node_data.cgi 获取实时数据。

node_data.c 程序文件

主要实现了与共享内存交互,并将共享内存中的部分数据以 JSON 格式作为 HTTP 响应输出的功能。程序会创建或连接到一个共享内存段,读取其中的数据,修改部分数据,然后将温度、湿度、光照强度和气体浓度等信息以 JSON 格式输出,最后分离共享内存。

2、界面功能运行

程序编译完成后,上传到飞腾派开发板的https服务器的文件目录/var/www/,PC机浏览器访问开发板IP地址,显示如下界面。

注意:开发板如果没有通过网络连接到节点板,界面是没有相关数据显示。

完成后续终端节点开发,开发板服务器连接到节点板后,界面会显示实时采集到的环境数据。

二、data_show.html 程序分析与设计

1、程序流程分析与设计

2、程序功能分析与设计

  • HTML 头部部分

    数据显示

设置文档类型和字符编码。

引入 Bootstrap 样式表和相关 JavaScript 库,以及 ECharts 库。

  • HTML 主体部分

使用 Bootstrap 的网格系统创建页面布局。

包含温度、湿度、光强的仪表盘和气体浓度的折线图。

每个面板都有一个连接状态图标,初始状态为断开连接。

  1. JavaScript 部分

  1. 初始化变量,用于存储数据和 ECharts 实例。
  2. 根据页面宽度调整气体浓度折线图的高度。
  3. 每秒发送一次 AJAX 请求,从服务器获取实时数据,并更新连接状态图标。
  4. 初始化温度、湿度、光强仪表盘和气体浓度折线图。
  5. 每秒更新一次仪表盘和折线图的数据。
  6. 窗口大小改变时,调整所有图表的大小。

三、node_data.c 程序分析与设计

程序主要实现了与共享内存交互,并将共享内存中的部分数据以 JSON 格式作为 HTTP 响应输出的功能。程序会创建或连接到一个共享内存段,读取其中的数据,修改部分数据,然后将温度、湿度、光照强度和气体浓度等信息以 JSON 格式输出,最后分离共享内存。

1、程序流程分析与设计

这个流程图展示了程序的主要执行流程,包括共享内存的设置、数据的读取和修改、HTTP 响应的输出以及共享内存的分离等步骤。如果在任何步骤中出现错误,程序会输出相应的错误信息并终止。

2、程序功能分析与设计

  • 头文件包含部分

    #include <unistd.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <sys/ipc.h>
    #include <sys/shm.h>
    #include <signal.h>
    #include <time.h>

这些头文件包含了程序所需的基本函数和数据类型定义,例如标准输入输出、内存管理、系统调用、信号处理等。

  • 宏定义部分

    #define CMD_DATA 0x01
    #define CMD_CTL 0x02
    #define CMD_SET 0x03

    #define E53_IA1 0x01
    #define E53_SF1 0x02

定义了一些常量,用于表示命令类型和节点类型。

  • 共享内存数据结构定义

    struct st_sys {
    unsigned char temp_val; // 温度值
    unsigned char humi_val; // 湿度值
    unsigned char light_sw; // 灯光开关状态
    unsigned char buzz_sw; // 蜂鸣器开关状态
    unsigned int ill_val; // 光照强度值
    unsigned int gas_val; // 气体浓度值
    unsigned int ill_max; // 光照强度最大值
    unsigned int gas_max; // 气体浓度最大值
    unsigned char msg_type; //请求类型
    unsigned char node_id; //节点ID
    unsigned char data_flag;//数据更新标记
    unsigned char control_flag;//控制更新标记
    unsigned char set_flag;//设置更新标记
    };

定义了一个结构体 st_sys,用于表示共享内存中的数据结构,包含了温度、湿度、光照、气体浓度等信息,以及请求类型、节点 ID 和更新标记。

  • 共享内存地址指针和全局变量

    struct st_sys* shm_dev;
    struct st_sys g_dev[1];

shm_dev 是一个指向共享内存的指针,g_dev 是一个用于存储从共享内存中读取的数据的数组。

  • 设置共享内存函数 set_web_shm

    void* set_web_shm(void) {
    int shmid;
    void* shmaddr = (void*)0;

    复制代码
      // 创建或获取共享内存段
      if ((shmid = shmget((key_t)3456, sizeof(struct st_sys), 0666 | IPC_CREAT)) < 0) {
          perror("shmget error");
          return NULL;
      }
      // 将共享内存段附加到当前进程的地址空间
      if ((shmaddr = shmat(shmid, (void*)0, 0)) == (char*)-1) {
          perror("shmat error");
          return NULL;
      }
      return shmaddr;

    }

该函数用于创建或获取一个共享内存段,并将其附加到当前进程的地址空间。如果创建或附加失败,会输出错误信息并返回 NULL

  • 信号处理函数 signal_handler

    void signal_handler(int signum) {
    if (shmdt(shm_dev) == -1) {
    perror("shmdt error");
    }
    exit(0);
    }

当程序接收到信号时,该函数会尝试分离共享内存,并退出程序。如果分离失败,会输出错误信息。

  • 主函数 main

    int main() {

    复制代码
      // 构建 JSON 格式的响应数据
      char response[100];
    
      // 设置共享内存
      if ((shm_dev = (struct st_sys*)set_web_shm()) == NULL) {
          fprintf(stderr, "Failed to set up shared memory.\n");
          return 1;
      }
      // 从共享内存中读取数据
      memcpy(g_dev, shm_dev, sizeof(struct st_sys));
      shm_dev->msg_type = CMD_DATA;//命令类型
      shm_dev->node_id = E53_IA1;//节点类型
      shm_dev->data_flag++;//更新次数加1
      // 设置 HTTP 响应头
      printf("Content-type: application/json\n\n");
      snprintf(response, sizeof(response), "{\"temp\": %d, \"humi\": %d, \"light\": %d, \"gas\": %d}", g_dev->temp_val, g_dev->humi_val,g_dev->ill_val, g_dev->gas_val);
      // 输出响应数据
      printf("%s", response);
      //分离共享内存
      if (shmdt(shm_dev) == -1) {
          perror("shmdt error");
      }
      return 0;

    }

主函数的主要流程如下:

  1. 定义一个字符数组 response 用于存储 JSON 格式的响应数据。

  2. 调用 set_web_shm 函数设置共享内存,如果失败则输出错误信息并返回。

  3. 从共享内存中读取数据到 g_dev 数组。

  4. 修改共享内存中的请求类型、节点 ID 和更新标记。

  5. 设置 HTTP 响应头。

  6. 使用 snprintf 函数将温度、湿度、光照强度和气体浓度信息格式化为 JSON 字符串。

  7. 输出 JSON 响应数据。

  8. 分离共享内存,如果失败则输出错误信息。

  9. 返回 0 表示程序正常结束。

相关推荐
世人万千丶5 天前
桌面便签小应用 - HarmonyOS ArkUI 开发实战-TextArea与Flex布局-PC版本
华为·harmonyos·鸿蒙·鸿蒙系统
Inhand陈工5 天前
基于台达PLC与映翰通IG502的智慧水产养殖精准投喂与远程运维解决方案
运维·人工智能·物联网·阿里云·信息与通信
大鱼>5 天前
大语言模型+物联网:LLM理解物理世界
物联网·struts·语言模型·多模态·aiot
果丁智能5 天前
物联网智能锁赋能集中式住宿:身份核验与远程权限管控的全链路技术实践
大数据·人工智能·物联网·智能家居
YM52e5 天前
买菜计算器小应用 - HarmonyOS ArkUI 开发实战-PC版本
学习·华为·harmonyos·鸿蒙·鸿蒙系统
国产化创客5 天前
ESP32 CameraWebServer 原生摄像头项目全解析
物联网·开源·嵌入式·实时音视频·智能硬件
谁似人间西林客5 天前
数据智能怎么赋能工业制造?物联网场景落地方法解析
物联网·制造
InHand云飞小白5 天前
无人值守站点网络困境?工业级路由器IR315破解连接难题
网络·物联网·4g·工业路由器·4g路由器·iiot·蜂窝路由器
MetrixAeroCore5 天前
Metrix 国际物联网卡资费方案|多场景共享流量池·按需扩容
物联网
by————组态5 天前
Ricon组态系统 - 新一代Web可视化组态平台
前端·后端·物联网·架构·组态·组态软件