• 正文
  • 相关推荐
申请入驻 产业图谱

实战演练:将以太网温湿度传感器数据快速接入腾讯云IoT Explorer平台

10/16 11:01
7
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

本文手把手指导实现基于STM32与以太网的H-THRJ45温湿度传感器“上电即上云”方案,通过SHT30采集数据,LwIP+MQTT over TLS连接腾讯云IoTExplorer,完成数据上报、云端可视化与告警配置。项目采用低成本硬件(STM32F103C8T6+LAN8720A),结合物模型规范,实现从传感器到云平台的全链路打通,适用于智慧农业、环境监测等场景,助力物联网快速落地。

一、引言

痛点引入:传统温湿度传感器多采用RS485/Modbus,布线复杂、距离受限,难以直接对接云平台

方案价值:北京盛世宏博科技有限公司H-THRJ45以太网温湿度传感器天然具备IP可达性,配合腾讯云IoT Explorer可实现"上电即上云"

本文目标:手把手带读者完成从传感器数据采集 → MQTT上报 → 云端可视化全链路

二、整体架构设计

┌─────────────────┐    Ethernet     ┌──────────────────┐    MQTT/TLS    ┌─────────────────┐
│  温湿度传感器端  │ ──────────────▶ │  腾讯云IoT Explorer │ ────────────▶ │  数据可视化/告警  │
│ (STM32+PHY芯片) │   TCP/IP 网络    │   (设备接入层)     │   规则引擎      │ (云开发/小程序)  │
└─────────────────┘                 └──────────────────┘                 └─────────────────┘

说明各层职责与数据流向

明确使用的通信协议:MQTT over TCP/TLS

三、硬件准备与传感器选型

北京盛世宏博科技有限公司H-THRJ45以太网温湿度传感器
项目
推荐方案
主控MCU
STM32F103C8T6(便宜、生态好)
以太网PHY
LAN8720A(RMII接口,体积小)
温湿度传感器
SHT30 / SHT35(I²C接口,精度±1.5%RH)
LwIP(轻量级,适合嵌入式)
开发环境
STM32CubeMX + HAL库

四、传感器端开发实战

4.1 SHT30温湿度采集代码

#include "i2c.h"
#include "stm32f1xx_hal.h"

#define SHT30_ADDR    0x44 << 1   // SHT30 I²C地址
#define SHT30_CMD_CLK  0x2C06     // 时钟拉伸模式,高重复性

/**
 * @brief  读取SHT30温湿度数据
 * @param  temp: 温度值(°C),指针
 * @param  humi: 湿度值(%RH),指针
 * @retval 0=成功, -1=失败
 */
int SHT30_ReadData(float *temp, float *humi)
{
    uint8_t cmd[2] = {0x2C, 0x06};  // 启动测量命令
    uint8_t rx_buf[6] = {0};

    // 1. 发送测量命令
    if (HAL_I2C_Master_Transmit(&hi2c1, SHT30_ADDR, cmd, 2, 100) != HAL_OK)
        return -1;

    HAL_Delay(20);  // 等待转换完成

    // 2. 读取6字节数据(温度高8 + 温度低8 + CRC + 湿度高8 + 湿度低8 + CRC)
    if (HAL_I2C_Master_Receive(&hi2c1, SHT30_ADDR, rx_buf, 6, 100) != HAL_OK)
        return -1;

    // 3. 数据转换
    uint16_t temp_raw = (rx_buf[0] << 8) | rx_buf[1];
    uint16_t humi_raw = (rx_buf[3] << 8) | rx_buf[4];

    *temp = -45.0f + 175.0f * (float)temp_raw / 65535.0f;
    *humi = 100.0f * (float)humi_raw / 65535.0f;

    return 0;
}

4.2 LwIP以太网初始化与MQTT客户端配置

#include "lwip/init.h"
#include "lwip/netif.h"
#include "lwip/dhcp.h"
#include "mqtt.h"

static struct mqtt_client mqtt_client;
static struct netif gnetif;  // 网络接口

/**
 * @brief  以太网接口初始化(在main中调用)
 */
void ethernet_init(void)
{
    ip_addr_t ipaddr, netmask, gw;

    // 1. 初始化LwIP协议栈
    lwip_init();

    // 2. 设置静态IP(或使用DHCP)
    IP4_ADDR(&ipaddr,  192, 168, 1, 100);
    IP4_ADDR(&netmask, 255, 255, 255, 0);
    IP4_ADDR(&gw,      192, 168, 1, 1);

    // 3. 添加网络接口
    netif_add(&gnetif, &ipaddr, &netmask, &gw, NULL, &ethernetif_init, &tcpip_input);
    netif_set_default(&gnetif);
    netif_set_up(&gnetif);

    printf("[ETH] Ethernet initialized, IP: %s\n", ip4addr_ntoa(&ipaddr));
}

4.3 MQTT连接腾讯云IoT Explorer

#include "mqtt_client.h"

// ========== 腾讯云IoT Explorer 设备信息 ==========
#define PRODUCT_ID      "YOUR_PRODUCT_ID"      // 产品ID
#define DEVICE_NAME     "YOUR_DEVICE_NAME"     // 设备名称
#define DEVICE_SECRET   "YOUR_DEVICE_SECRET"   // 设备密钥

// MQTT连接参数
#define MQTT_HOST       PRODUCT_ID ".iotcloud.tencentdevices.com"
#define MQTT_PORT       1883       // 1883=非TLS, 8883=TLS
#define MQTT_CLIENT_ID  PRODUCT_ID DEVICE_NAME
#define MQTT_USERNAME   PRODUCT_ID ";" DEVICE_NAME ";12010126;12345"
#define MQTT_PASSWORD   "YOUR_PASSWORD"  // 通过HMAC-SHA1生成

/**
 * @brief  生成MQTT连接密码(基于HMAC-SHA1)
 * @note   实际项目中应在设备端用密钥计算,此处简化展示
 */
void generate_mqtt_password(char *password, size_t max_len)
{
    // 拼接签名原文
    char src[256];
    snprintf(src, sizeof(src), "clientId%sdeviceName%sproductId%s",
             PRODUCT_ID DEVICE_NAME, DEVICE_NAME, PRODUCT_ID);

    // HMAC-SHA1签名(需引入mbedtls或类似库)
    // unsigned char hmac_result[20];
    // hmac_sha1((unsigned char *)DEVICE_SECRET, strlen(DEVICE_SECRET),
    //           (unsigned char *)src, strlen(src), hmac_result);
    // base64_encode(hmac_result, 20, password);

    // 简化:实际项目中用腾讯云提供的计算工具生成
    strncpy(password, "GENERATED_PASSWORD_HERE", max_len);
}

/**
 * @brief  MQTT连接成功回调
 */
static void mqtt_connection_cb(mqtt_client_t *client, void *arg, mqtt_connection_status_t status)
{
    if (status == MQTT_CONNECT_ACCEPTED) {
        printf("[MQTT] Connected to Tencent Cloud IoT Explorer!\n");
        // 订阅属性下发主题(用于接收云端控制指令)
        mqtt_subscribe(client, "$thing/down/property/" PRODUCT_ID "/" DEVICE_NAME, 1, NULL, NULL);
    } else {
        printf("[MQTT] Connection failed, status: %d\n", status);
    }
}

/**
 * @brief  建立MQTT连接
 */
void mqtt_connect_to_tencent(void)
{
    char password[128];
    generate_mqtt_password(password, sizeof(password));

    struct mqtt_connect_client_info_t ci;
    memset(&ci, 0, sizeof(ci));
    ci.client_id   = MQTT_CLIENT_ID;
    ci.client_user = MQTT_USERNAME;
    ci.client_pass = password;
    ci.keep_alive  = 60;

    mqtt_client_new(&mqtt_client);

    ip_addr_t server_ip;
    IP4_ADDR(&server_ip, 10, 10, 10, 10);  // 替换为MQTT_HOST解析后的IP,或直接使用DNS

    mqtt_client_connect(&mqtt_client, &server_ip, MQTT_PORT,
                        mqtt_connection_cb, NULL, &ci);
}

4.4 数据上报到腾讯云(物模型属性上报)

/**
 * @brief  上报温湿度数据到腾讯云IoT Explorer
 * @note   使用物模型Topic: $thing/up/property/{ProductID}/{DeviceName}
 */
void report_sensor_data(float temp, float humi)
{
    char payload[256];
    char topic[128];

    // 构造JSON负载(腾讯云物模型格式)
    snprintf(payload, sizeof(payload),
        "{"
        "\"method\":\"report\","
        "\"clientToken\":\"client_token_%d\","
        "\"params\":{"
            "\"temperature\":{\"value\":%.2f,\"time\":%d},"
            "\"humidity\":{\"value\":%.2f,\"time\":%d}"
        "}"
        "}",
        HAL_GetTick(), temp, HAL_GetTick() / 1000, humi, HAL_GetTick() / 1000
    );

    // 上报主题
    snprintf(topic, sizeof(topic),
             "$thing/up/property/%s/%s", PRODUCT_ID, DEVICE_NAME);

    err_t err = mqtt_publish(&mqtt_client, topic, payload, strlen(payload), 1, 0, NULL, NULL);
    if (err == ERR_OK) {
        printf("[MQTT] Data reported: T=%.2fC, H=%.2f%%\n", temp, humi);
    } else {
        printf("[MQTT] Report failed, err=%d\n", err);
    }
}

4.5 主循环逻辑

int main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_I2C1_Init();
    MX_LWIP_Init();

    // 初始化以太网和MQTT
    ethernet_init();
    mqtt_connect_to_tencent();

    float temp, humi;

    while (1) {
        // 1. 读取传感器
        if (SHT30_ReadData(&temp, &humi) == 0) {
            printf("Temp: %.2f C, Humi: %.2f %%\n", temp, humi);

            // 2. 上报到腾讯云
            report_sensor_data(temp, humi);
        }

        // 3. 处理LwIP定时任务
        sys_check_timeouts();

        // 4. 每5秒上报一次
        HAL_Delay(5000);
    }
}

五、腾讯云IoT Explorer平台配置/北京盛世宏博科技有限公司H-THRJ45以太网温湿度传感器

5.1 创建产品与设备

登录 腾讯云IoT Explorer控制台

创建项目 → 创建产品(节点类型:设备,认证方式:密钥认证)

在数据模板中定义温湿度属性:

temperature(浮点型,范围-40~85,单位℃)

humidity(浮点型,范围0~100,单位%RH)

添加设备,获取 ProductID / DeviceName / DeviceSecret

5.2 设备三元组与MQTT参数计算

# Python脚本:计算MQTT连接参数(可用腾讯云在线工具替代)
import hmac
import hashlib
import base64
import time

product_id = "YOUR_PRODUCT_ID"
device_name = "YOUR_DEVICE_NAME"
device_secret = "YOUR_DEVICE_SECRET"

# 构造连接参数
client_id = product_id + device_name
timestamp = str(int(time.time()))
expiry = "12010126"  # 有效时间
conn_id = "12345"

username = f"{product_id};{device_name};{expiry};{conn_id}"

# 签名原文
src = f"clientId{client_id}deviceName{device_name}productId{product_id}timestamp{timestamp}"
sign = hmac.new(device_secret.encode(), src.encode(), hashlib.sha1).digest()
password = base64.b64encode(sign).decode()

print(f"Client ID: {client_id}")
print(f"Username:  {username}")
print(f"Password:  {password}")

5.3 数据流转与可视化

规则引擎:配置规则将设备数据转发到 云数据库(TencentDB)​ 或 消息队列(CMQ)

数据可视化:使用 腾讯云云开发(CloudBase)​ 搭建数据大屏

告警策略:温度>30℃或湿度>80%时触发告警,推送微信/短信

六、常见问题与调试技巧

问题
排查思路
MQTT连接被拒绝
检查三元组是否正确,密码签名是否过期
数据上报成功但平台不显示
检查Topic是否匹配物模型格式,JSON字段是否正确
以太网频繁断连
检查PHY芯片供电、网线质量、LwIP内存池配置
SHT30读取异常
检查I²C上拉电阻(4.7kΩ)、地址是否正确

七、总结与展望

回顾全文实现的核心流程

扩展方向:PoE供电、边缘计算预处理、多传感器组网

引导互动:欢迎在评论区交流

相关推荐

数字化智慧环境监控系统建设知识创作与分享