0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

从零搭建W55MH32以太网环境空气质量检测系统:MQTT阿里云平台监测+内置Web网页显示+代码全解析

胡沛源 ? 来源:jf_43373790 ? 作者:jf_43373790 ? 2025-08-12 09:44 ? 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

1 前言

我是个挺爱琢磨生活细节的人,在不同的场所我总是会觉得我鼻子不舒服,嗓子也有点干。但是有的地方也挺干净整洁的呀,我心里时常想:“这也没人抽烟,也没刮大风啊?难道是空气不行?”可空气好不好,看不见摸不着啊!PM2.5:那些比头发丝还细几十倍的灰尘颗粒,吸进去就赖在肺里不走了,长期下来可不是闹着玩的。家里有老人小孩的,更得注意这个。二氧化碳:你以为人多的地方只是“闷”?那是CO2超标了!在教室、会议室甚至自己关着门的卧室待久了,头晕、犯困、注意力不集中,很可能就是它在捣鬼。办公室下午集体犯困?搞不好就是通风不够,CO2爆表了!空气干不干净?不知道! 全凭感觉,鼻子嗓子不舒服了才后知后觉。开不开窗?很纠结! 外面看着天挺好,开了窗结果可能进来一堆灰(PM2.5);关窗吧,屋里人一多,CO2蹭蹭涨,闷得慌。净化器/新风开不开?开多久?纯靠猜!电费哗哗流,效果怎么样?心里没底。我就想:能不能做个简单、便宜又能联网的小玩意儿,让我随时知道身边的空气“底细”?

既然要“随时知道”,那肯定得联网!把数据发到手机或者网页上才方便。自己做网络协议?想想就头大!直到我发现了 W55MH32 这块板子,简直是量身定做:“自带网卡”的MCU: 它最牛的地方就是 芯片里直接集成了硬件TCP/IP协议栈、以太网MAC和PHY!这意味着什么?我不需要再外接复杂的WiFi模块或者额外跑协议栈消耗宝贵的CPU资源。硬件搞定网络底层,开发更简单! 我只需要关心怎么读取传感器数据,然后把数据打包发出去就行。成本低、连线少: 基本上,加个网络变压器和RJ45网口,插根网线,它就能直接上网了!稳定性也比很多WiFi方案靠谱。性能够用: 处理几个传感器的数据,做点简单计算,再通过网络发出去,W55MH32的性能绰绰有余。

基于以上,我决定动手搞这个项目:本项目以W55MH32 以太网开发板为核心,通过JW01-CO2传感器(实时监测二氧化碳浓度)与DC01红外PM2.5传感器(精准检测空气中细颗粒物含量),构建了一套智能环境监测解决方案。系统通过MQTT协议与阿里云物联网平台建立稳定通信链路,实现监测数据的云端远程传输、存储与分析,支持用户通过移动端或Web端实时查看数据历史趋势与告警信息。
创新性地开发了本地实时数据可视化网页,设备内置轻量级Web服务器,用户可直接通过浏览器访问设备IP地址,获取传感器数据的动态刷新显示(5秒更新一次)。最终达到让“看不见”的空气变得“看得见、摸得着、管得住”,用数据指导生活,呼吸得更明白、更健康!

开源项目源码:https://gitee.com/hupeiyuan0218/w55mh32_aircheck.git

视频演示:https://www.bilibili.com/video/BV162tzzaEcg/?vd_source=0e464ab43d68457de7bac889723ef284

2 项目环境

2.1 硬件环境

W55MH32开发板

JW01-CO2传感器

DC01红外PM2.5传感器

网线

若干杜邦线

2.2 软件准备

开发环境:Keil uVision 5

Wiznet串口助手(其他串口工具也可以)

阿里云服务器

浏览器

2.3 方案图示

wKgZPGiVYhyAP1oeAArxn9C9TrI734.png

3 注册阿里云账号以及建立物模型

注册账号在这里不进行赘述,下面我们看如何建立物模型。

3.1 创建产品

搜索物联网平台 → 点击物联网平台 → 点击公共实例

wKgZO2iVYiWAdXp8ABj8N6p_KIk230.png

选择设备管理 → 点击产品 → 点击创建产品

wKgZPGiVYi2AY7IWABaVPu1qT6M599.png

设置产品名称、所属品类、节点类型、连网方式、数据格式

wKgZO2iVYjWAJo1yABaVPpKI99Y074.png

3.2 添加设备

创建成功产品后点击添加设备 → 输入DeviceName

wKgZO2iVYj2AcWS1ABaVPoQmH1I132.png

3.3 创建物模型

定义物联网模型,选择产品 → 点击功能定义 → 点击前往编辑草稿

wKgZO2iVYkqAPnPmABaVPpbZrtg441.png

点击添加自定义功能 → 选择功能类型 → 输入功能名称 → 设置标识符 → 设置数据类型 → 设置取值范围 → 设置步长 → 设置单位 → 设置读写类型

wKgZPGiVYlCANaraABaVPjdbUqA314.png

3.4 获取设备连接信息

点击产品 → 选择创建的产品 → 点击Topic类列表 → 选择物模型通信

wKgZO2iVYlaAAk13ABDaj0Pm0WM721.png

订阅平台下发消息的主题:
/sys/a1QsjDLF7Rq/${deviceName}/thing/service/property/set
设备发布消息主题:
/sys/a1QsjDLF7Rq/${deviceName}/thing/event/property/post

注:两个主题中的{device_id}需要更改为自己设备的ID

点击设备管理 → 选择设备 → 点击查看

wKgZPGiVYmKAca9mABDajw3qPQk880.png


点击查看DeviceSecret,获取到设备证书

{
    "ProductKey": "a1QsjDLF7Rq",
    "DeviceName": "W55MH32",
    "DeviceSecret": "5a2b4550d9a3e7a8c19c1c8943d8f710"
}
wKgZPGiVYoGAU11vABDaj94HZmM828.png

获取MQTT连接参数

wKgZO2iVYomABvIDABDaj0Em_gk332.png

4 例程修改

本次以MQTT&Aliyun为例:

找到do_mqtt.c文件,把上述中的参数更换为自己阿里云的参数,这些参数我们在上面都有讲到,可以自行替换。

mqttconn mqtt_params = {
    .mqttHostUrl = "a1QsjDLF7Rq.iot-as-mqtt.cn-shanghai.aliyuncs.com",
    .server_ip =
        {
            0,
        },        /*Define the Connection Server IP*/
    .port = 1883, /*Define the connection service port number*/
    .clientid = "a1QsjDLF7Rq.W55MH32|securemode=2,signmethod=hmacsha256,"
                "timestamp=1752545118110|", /*Define the client ID*/
    .username = "W55MH32&a1QsjDLF7Rq",      /*Define the user name*/
    .passwd = "f0dcd6ce4df2493438e42dbd9dd789d348309201ac18f18dd158ddceea45fc5"
              "d", /*Define user passwords*/
    .pubtopic =
        "/sys/a1QsjDLF7Rq/W55MH32/thing/event/property/post", /*Define the
                                                                 publication
                                                                 message*/
    .subtopic =
        "/sys/a1QsjDLF7Rq/W55MH32/thing/service/property/set", /*Define
                                                                  subscription
                                                                  messages*/
    .pubQoS = QOS0, /*Defines the class of service for publishing messages*/
};

先发送订阅主题{device_id}的数据包
/sys/a1QsjDLF7Rq/W55MH32/thing/service/property/set订阅成功后,接收到来自主题的信息SUCCESS。

case SUB: {
    ret = MQTTSubscribe(&c, mqtt_params.subtopic,mqtt_params.subQoS,
                        messageArrived); /* Subscribe to Topics */
    printf("Subscribing to %srn", mqtt_params.subtopic);
    printf("Subscribed:%srnrn", ret == SUCCESSS ? "success" : "failed");
    if (ret != SUCCESSS) {
      run_status = ERR;
    } else {
      run_status = PUB_MESSAGE;
    }
    break;
  }

接下来进行数据发布,这一步请确保服务ID(Temperature)和属性名(CurrentTemperature)与您在阿里云上定义的产品模型完全一致(包括大小写)。发布成功后更新状态为保持连接状态。

case PUB_MESSAGE: {
    // 动态构建JSON负载
    snprintf(payload_buffer, PAYLOAD_BUFFER_SIZE,
             "{"id":"123","version":"1.0","
             ""params":{"co2":%d,"PM2_5":%d},"
             ""method":"thing.event.property.post"}",
             co2_concentration, concentration);

    pubmessage.qos = QOS0;
    pubmessage.payload = payload_buffer;
    pubmessage.payloadlen = strlen(payload_buffer);
    ret = MQTTPublish(&c, (char *)&(mqtt_params.pubtopic),
                      &pubmessage); /* Publish message */
    if (ret != SUCCESSS) {
      run_status = ERR;
    } else {
      printf("publish:%s,%srnrn", mqtt_params.pubtopic, payload_buffer);
      run_status = KEEPALIVE;
    }
    break;
  }

完成这两步就可以成功连接阿里云,并上传数据到阿里云。

采集数据采用的传感器采用的是JW01-CO2传感器、DC01红外PM2.5传感器,这两个传感器都是通过串口通信,首先进行串口初始化,然后传感器每秒自动将采集到的数据通过串口发送。DC01红外PM2.5传感器通过串口二连接,JW01-CO2传感器通过串口三连接。

初始化串口二、串口三

// 串口2初始化函数
void pm25_usart2_init(uint32_t baudrate)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef  NVIC_InitStructure;

    // 使能时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

    // 配置TX引脚 (PA0)
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // 配置RX引脚 (PA3)
    GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // 配置串口参数
    USART_InitStructure.USART_BaudRate            = baudrate;
    USART_InitStructure.USART_WordLength          = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits            = USART_StopBits_1;
    USART_InitStructure.USART_Parity              = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode                = USART_Mode_Rx | USART_Mode_Tx;

    USART_Init(USART2, &USART_InitStructure);
    
    // 使能接收中断
    USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
    
    // 配置NVIC
    NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    
    // 使能串口
    USART_Cmd(USART2, ENABLE);
}
 
// 串口3初始化
void co2_usart3_init(uint32_t baudrate)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    // 使能时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);

    // 配置USART3 TX (PB10) 为复用推挽输出
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    // 配置USART3 RX (PB11) 为浮空输入
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    // USART参数配置
    USART_InitStructure.USART_BaudRate = baudrate;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART3, &USART_InitStructure);

    // 使能接收中断
    USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);

    // 配置USART3中断
    NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; // 优先级低于串口2
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    // 使能串口
    USART_Cmd(USART3, ENABLE);
}

初始化完成之后,通过数据格式进行解析,将PM2.5浓度、二氧化碳浓度计算出来

//解析计算PM2.5浓度
void pm25_data_process_usart2(void)
{
    // 计算校验和:前三字节的低7位之和
    uint8_t calculated_checksum = (rx_buffer[0] & 0x7F) + 
                                  (rx_buffer[1] & 0x7F) + 
                                  (rx_buffer[2] & 0x7F);
    calculated_checksum &= 0x7F; // 保留低7位
    
    // 获取接收到的校验位(第四字节)
    uint8_t received_checksum = rx_buffer[3] & 0x7F;
    
    // 校验检查
    if (calculated_checksum != received_checksum)
    {
        checksum_error = 1;
        return; // 校验失败,丢弃数据
    }
    
    checksum_error = 0;
    
    // 计算浓度值
    // 浓度值 = (DATAH[6:0] 

这样我们就获取到了环境空气质量数据,再创建一个网页,将PM2.5浓度、CO2浓度进行显示出来,每五秒刷新一次。

int32_t loopback_tcps(uint8_t sn, uint8_t *buf, uint16_t port) {
  int32_t ret;
  uint16_t size = 0, sentsize = 0;

  switch (getSn_SR(sn)) {
  case SOCK_ESTABLISHED:
    if (getSn_IR(sn) & Sn_IR_CON) {

      setSn_IR(sn, Sn_IR_CON);
    }
    if ((size = getSn_RX_RSR(sn)) >
        0) // Don't need to check SOCKERR_BUSY because it doesn't not occur.
    {
      if (size > DATA_BUF_SIZE)
        size = DATA_BUF_SIZE;
      ret = recv(sn, buf, size);

      if (ret <= 0)
        return ret; // check SOCKERR_BUSY & SOCKERR_XXX. For showing the
                    // occurrence of SOCKERR_BUSY.
      size = (uint16_t)ret;
      sentsize = 0;
      buf[size] = 0x00;
      printf("rece data:%srn", buf);

      HttpRequestLine req_line;
      if (parse_request_line((char *)buf, &req_line) == 0) {
        printf("Method: %sn", req_line.method);   // 输出: GET
        printf("URI: %sn", req_line.uri);         // 输出: /
        printf("Version: %sn", req_line.version); // 输出: HTTP/1.1

        if (strcmp(req_line.method, "GET") == 0 &&
            strcmp(req_line.uri, "/") == 0) {
          char html_buffer[2048]; // 确保缓冲区足够大
          snprintf(html_buffer, sizeof(html_buffer), index_page,
                   g_co2_concentration, g_pm25_concentration);

          uint16_t content_len = strlen(html_buffer);
          sentsize = 0;
          while (content_len != sentsize) {
            ret = send(sn, (uint8_t *)html_buffer + sentsize,
                       content_len - sentsize);
            if (ret < 0) {
              close(sn);
              return ret;
            }
            sentsize += ret;
          }
          disconnect(sn);
          close(sn);
        } else if (strcmp(req_line.method, "GET") == 0 &&
                   strcmp(req_line.uri, "/api/sensor") == 0) {
          char sensor_data[64];
          sprintf(sensor_data, "{"pm25":%u,"co2":%u}", g_co2_concentration,
                  g_pm25_concentration);
          char response[128];
          sprintf(response,
                  "HTTP/1.1 200 OKrn"
                  "Content-Type: application/jsonrn"
                  "Connection: closern"
                  "rn"
                  "%s",
                  sensor_data);
          send(sn, (uint8_t *)response, strlen(response));
          disconnect(sn);
          close(sn);
        } else {
          send(sn, (uint8_t *)HTTP_RESPONSE_404, strlen(HTTP_RESPONSE_404));
          disconnect(sn);
          close(sn);
        }
      }

      else {
        printf("解析失败!n");
      }
    }
    break;
  case SOCK_CLOSE_WAIT:
    if ((ret = disconnect(sn)) != SOCK_OK)
      return ret;
    break;
  case SOCK_INIT:
    if ((ret = listen(sn)) != SOCK_OK)
      return ret;
    break;
  case SOCK_CLOSED:
    if ((ret = socket(sn, Sn_MR_TCP, port, 0x00)) != sn)
      return ret;
    break;
  default:
    break;
  }
  return 1;
}

最后在主函数中添加初始化并在while函数中添加函数

    pm25_usart2_init(9600);
    co2_usart3_init(9600);
    while (1) {
    do_mqtt();
    pm25_data_process_usart2();
    co2_data_process_usart3();
    loopback_tcps(1, ethernet_buf, 80);
    }

5 功能验证

程序烧录完毕,硬件连接完成如下图所示:

wKgZO2iVY1OAQGMaABIyV2RXrGg638.png

硬件连接完毕,上电通过串口助手打印如下信息:

wKgZPGiVY12AG9aeACjJffcH22g114.png

二氧化碳传感器需要预热5-10分钟进行测试,预热完成之后即可测试出环境空气中CO2和PM2.5浓度含量,同步上传到阿里云服务器和在本地网页,每五秒刷新一次。

wKgZO2iVY4aAWNg1ACJ33fAoH1Y351.png

6 总结


本项目通过整合硬件资源、通信协议与云平台能力,成功实现环境空气质量检测功能,验证了 W55MH32 在物联网的实用性,感谢大家的耐心阅读!如果您在阅读过程中有任何疑问,或者希望进一步了解这款产品及其应用,欢迎随时通过私信或评论区留言。我们会尽快回复您的消息,为您提供更详细的解答和帮助!

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 以太网
    +关注

    关注

    41

    文章

    5738

    浏览量

    176766
  • 服务器
    +关注

    关注

    13

    文章

    9850

    浏览量

    88361
  • 开发板
    +关注

    关注

    25

    文章

    5758

    浏览量

    106183
  • 阿里云
    +关注

    关注

    3

    文章

    1016

    浏览量

    44371
  • MQTT
    +关注

    关注

    5

    文章

    697

    浏览量

    23840
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    汽车空气质量检测与改善方案简介

    吹到汽车里的空气质量。该系统能自动判断并地适应各种驾驶环境,如城市、乡村、交通阻塞路口或隧道等。另外,该系统还有自学习和自我检测功能以适应不
    发表于 07-19 14:09

    STM32空气质量检测应用教程

    应用,即微控制器采集空气质量传感器的数据,通过WIFI上报到机智服务器,然后我们通过手机端APP即可远程查看监测值。有图有真相: 1.图文PDF教程: STM32L432 Nucleo-32案例-3
    发表于 12-29 14:36

    【OneNET麒麟座试用申请】空气质量数据监测

    项目名称:空气质量数据监测站试用计划:空气质量数据监测站用于测试空气质量监测及数据采集,实现野外
    发表于 04-05 15:03

    【Thunderboard Sense试用申请】移动空气质量监测

    模式,空气质量传感器监测当前空气质量状况并通过LED分色显示,陀螺仪记录使用者运动状态,以上数据通过2.4G wireless soc 上传至网络
    发表于 05-19 17:10

    什么是空气质量网格化监测

    近几年,环境污染问题一直都困扰着人们的生活,尤其是大气污染问题不仅严重威胁着人类的生命健康,而且也造成了生态破坏。随着城市大气污染的日益恶化,城市管理部门为了实时采集各区域范围内的空气质量数据,都会选择部署空气
    发表于 11-24 06:07

    怎样去设计基于STM32的空气质量监测系统

    基于STM32的空气质量监测系统简单案例系统简介软硬件介绍STM32F103开发板MQ135空气质量传感器DS18B20温度传感器设计流程硬
    发表于 08-11 07:38

    基于单片机的环境空气质量检测系统的设计

    【资源下载】下载地址如下:设计简介:本设计是基于单片机的环境空气质量检测系统的设计,主要实现以下功能:实现通过甲烷气体传感器检测室内甲烷浓度
    发表于 11-19 07:03

    基于单片机的空气质量监测的设计资料分享

    设计简介:本设计是基于单片机的空气质量监测,主要实现以下功能:可实现LCD1602显示DS1302时间以及空气质量值可通过按键对时间进行设置可通过按键对
    发表于 12-13 07:26

    网格化空气质量监测站的特点

    网格化空气质量监测站【霍尔德仪器HED-AQ1】空气质量检测仪有哪些强大功能呢?以前我们只顾及科技的快速进步,工业生产的加快发展,往往忽视了我们的生活
    发表于 08-11 16:12 ?545次阅读

    空气质量监测仪:了解您周围空气质量的最佳选择

    监测仪的种类 空气质量监测仪有多种类型,包括室内空气质量监测仪、室外空气质量
    的头像 发表于 06-21 11:15 ?1114次阅读

    空气质量监测仪:掌控空气质量

    是作为空气质量监测仪的核心部件,它能够监测空气中的污染物,如:PM2.5、PM10、二氧化碳、氨气、臭氧、甲醛等等,然后将检测结果转换成电信
    的头像 发表于 07-21 13:50 ?1163次阅读

    空气质量监测系统介绍

    环境保护已经成为全球的重要议题,而空气质量监测和管理是其中的重要一环。在这个过程中,空气质量监测系统
    的头像 发表于 08-15 10:51 ?2100次阅读

    空气质量监测系统:保护我们的环境和健康

    空气质量的变化情况,制定有效的环境保护策略,并评估这些策略的效果。 空气质量监测系统是如何工作的? 一般来说,
    的头像 发表于 08-16 11:39 ?871次阅读

    即刻启程,踏上W55MH32高性能以太网单片机学习之路!

    即刻启程,踏上W55MH32高性能以太网单片机学习之路!即刻开启W55MH32学习之旅!本教系列程配套官方手册与W55MH32L开发板,
    的头像 发表于 05-07 18:51 ?491次阅读
    即刻启程,踏上<b class='flag-5'>W55MH32</b>高性能<b class='flag-5'>以太网</b>单片机学习之路!

    智能农业监控系统MQTT阿里平台监测+内置Web网页控制+代码解析

    该智能农业监控系统基于W55MH32以太网单片机搭建,核心实现土壤湿度、光照数据采集与水泵智能灌溉控制。硬件采用W55MH32L-EVB主控
    的头像 发表于 08-08 11:07 ?251次阅读
    智能农业监控<b class='flag-5'>系统</b>:<b class='flag-5'>MQTT</b><b class='flag-5'>阿里</b><b class='flag-5'>云</b><b class='flag-5'>平台</b><b class='flag-5'>监测</b>+<b class='flag-5'>内置</b><b class='flag-5'>Web</b><b class='flag-5'>网页</b>控制+<b class='flag-5'>代码</b><b class='flag-5'>解析</b>