目录

前言

一、阿里云平台配置

1.1 创建产品

1.2 添加设备

1.3 定义物模型

二、ESP32代码实现

2.1 核心代码

2.2 代码中需修改部分

三、测试结果

结语

程序源码


前言

在物联网开发中,将设备数据上传至云端并通过 App 远程控制,是极为常见的应用场景。本文以 ESP32-S3 为核心硬件,基于 VS Code + PlatformIO 开发环境(Arduino 框架),从零开始手把手带你连接阿里云物联网平台,实现温湿度数据上报和灯光远程开关控制。全文贯穿实战,附完整代码与避坑指南,助你快速上手。

一、阿里云平台配置

1.1 创建产品

首先,登录阿里云物联网平台,申请一个免费的公共实例,进入实例管理页面。

创建产品

填写产品名称,选择自定义品类

创建完成后,在产品列表中即可看到刚刚建立的产品。

1.2 添加设备

在产品页,点击“管理设备”。

添加设备,添加的设备就是我们ESP32要连接的设备。

起个设备名

点击确认,可以看到设备已创建。

1.3 定义物模型

物模型定义了设备与云端的交互数据规范。这里我们添加温度、湿度、灯的属性。

在产品页,进入“查看” → “功能定义” → “前往编辑草稿” 。

添加自定义功能

添加温度属性。

  • 温度(Temperature):数据类型 float,读写类型“读写”。

添加湿度属性。

  • 湿度(Humidity):数据类型 int,读写类型“读写”。

添加灯属性。

  • 灯光开关(light):数据类型 bool(取值范围 0/1),读写类型“读写”。

注意:属性标识符严格区分大小写,后续代码中需完全一致。

二、ESP32代码实现

2.1 核心代码

本项目使用 VS Code + PlatformIO 开发,基于 Arduino 框架编写。

main.cpp

#include <Arduino.h>
#include "mywifi.h"
#include "mqtt.h"

extern PubSubClient client;

float temp = 24.4;
int humi = 60;
uint8_t light_state = 0;

void setup() 
{
  pinMode(led_pin, OUTPUT);
  Serial.begin(9600);
  mqtt_paramsinit();
  wifi_connect();
  mqtt_init();
  mqtt_connect(); 
}

void loop() 
{
  // 保持 MQTT 连接
  if (!client.connected()) 
  {
    mqtt_connect();
  }
  // 处理 MQTT 消息
  client.loop();

  // 定期上报(每 5 秒一次)
  static unsigned long lastReport = 0;
  if (millis() - lastReport > 5000) 
  {
    mqtt_send_telemetry();
    lastReport = millis();
  }

  delay(10);
}
  

mywifi.cpp

#include "mywifi.h"

const char* ssid = "你的WiFi名";
const char* password = "你的WiFi密码";

void wifi_connect() 
{
  WiFi.begin(ssid, password);

  Serial.println("Connecting to WiFi...");
  while (WiFi.status() != WL_CONNECTED);
  Serial.println("WiFi Connected!");
  
  Serial.print("IP Address: ");
  Serial.println(WiFi.localIP());
}

mywifi.h

#ifndef __MYWIFI_H__
#define __MYWIFI_H__

#include <Arduino.h>
#include <WiFi.h>

void wifi_connect();

#endif

mqtt.cpp

#include "mqtt.h"

WiFiClient espClient;                // 创建WiFi客户端对象
PubSubClient client(espClient);      // 创建MQTT客户端对象

extern float temp;
extern int humi;
extern uint8_t light_state;

// 阿里云配置
// 阿里云三元组
const char* PRODUCT_KEY   = "你的ProductKey";   // 你的ProductKey
const char* DEVICE_NAME   = "你的DeviceName";       // 你的DeviceName
const char* DEVICE_SECRET = "你的DeviceSecret";    // 你的DeviceSecret
// 阿里云 MQTT 服务器地址
const char* MQTT_SERVER   = "你的ProductKey.iot-as-mqtt.cn-shanghai.aliyuncs.com";   // 你的ProductKey.iot-as-mqtt.cn-shanghai.aliyuncs.com
const int   MQTT_PORT     = 1883;  
// Topic
String pubTopic;   // 上报,属性上报
String subTopic;   // 订阅,属性设置

// MQTT 连接参数(由三元组计算得出)
String mqttClientId;
String mqttUsername;
String mqttPassword;

// HMAC-SHA1 工具函数
String mqtt_hmacSha1(const String& data, const String& key) 
{
    byte hmacResult[20];
    mbedtls_md_context_t ctx;
    mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1;

    mbedtls_md_init(&ctx);
    mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(md_type), 1);
    mbedtls_md_hmac_starts(&ctx, (const unsigned char*)key.c_str(), key.length());
    mbedtls_md_hmac_update(&ctx, (const unsigned char*)data.c_str(), data.length());
    mbedtls_md_hmac_finish(&ctx, hmacResult);
    mbedtls_md_free(&ctx);

    String hex = "";
    for (int i = 0; i < 20; i++) 
    {
        char buf[3];
        sprintf(buf, "%02x", hmacResult[i]);
        hex += buf;
    }

    return hex;
}

// 设置初始化参数
void mqtt_paramsinit() 
{
    mqttClientId = String(DEVICE_NAME) + "|securemode=3,signmethod=hmacsha1|";
    mqttUsername = String(DEVICE_NAME) + "&" + String(PRODUCT_KEY);
    String signData = "clientId" + String(DEVICE_NAME) +
                      "deviceName" + String(DEVICE_NAME) +
                      "productKey" + String(PRODUCT_KEY);
    mqttPassword = mqtt_hmacSha1(signData, String(DEVICE_SECRET));

    pubTopic = "/sys/" + String(PRODUCT_KEY) + "/" + String(DEVICE_NAME) + "/thing/event/property/post";
    subTopic = "/sys/" + String(PRODUCT_KEY) + "/" + String(DEVICE_NAME) + "/thing/service/property/set";
}

void mqtt_init()
{
    // 设置MQTT服务器和回调函数
    client.setServer(MQTT_SERVER, MQTT_PORT);
    client.setCallback(mqtt_callback);
    client.setKeepAlive(60);
}

// MQTT连接函数,负责与阿里云IoT平台建立连接,并在连接成功后订阅指定主题
void mqtt_connect() 
{
    while (!client.connected()) 
    {
        Serial.println("尝试连接阿里云MQTT...");
        // 使用客户端ID、用户名和密码尝试连接MQTT服务器
        if (client.connect(mqttClientId.c_str(), mqttUsername.c_str(), mqttPassword.c_str())) 
        {
            Serial.println("已连接到阿里云MQTT服务器");

            // 订阅主题
            client.subscribe(subTopic.c_str());
            Serial.print("已订阅: ");
            Serial.println(subTopic);
        } 
        else 
        {
            Serial.print("连接失败, 状态码=");
            Serial.print(client.state());
            Serial.println(",5秒后重试");
            delay(5000);
        }
    }
}

// MQTT消息回调函数
void mqtt_callback(char* topic, byte* payload, unsigned int length) 
{
    String message = "";
    for (int i = 0; i < length; i++) 
    {
        message += (char)payload[i];
    }
    Serial.print("回调message: ");
    Serial.println(message);

    JsonDocument doc;
    DeserializationError error = deserializeJson(doc, message);
    if (error) 
    {
        Serial.print("JSON解析失败: ");
        Serial.println(error.f_str());
        return;
    }

    // 解析 params 中的 light
    JsonObject params = doc["params"].as<JsonObject>();
    if (!params["light"].isNull()) 
    {
        bool light_status = params["light"];
        if (light_status) 
        {
            digitalWrite(led_pin, HIGH);
            Serial.println("light_on");
        } 
        else 
        {
            digitalWrite(led_pin, LOW);
            Serial.println("light_off");
        }
    }
}

// 上报设备遥测数据(温度和湿度)到阿里云IoT平台
void mqtt_send_telemetry()
{
    JsonDocument doc;
    doc["method"] = "thing.event.property.post";
    JsonObject params = doc["params"].to<JsonObject>();
    params["Temperature"] = temp;
    params["Humidity"] = humi;

    String jsonStr;
    serializeJson(doc, jsonStr);

    if (client.publish(pubTopic.c_str(), jsonStr.c_str())) 
    {
        Serial.print("上报数据: ");
        Serial.println(jsonStr);
    } 
    else 
    {
        Serial.println("上报失败");
    }
}

mqtt.h

#ifndef MQTT_H__
#define MQTT_H__

#include <Arduino.h>
#include <PubSubClient.h>  
#include "WiFi.h"
#include <ArduinoJson.h>
#include <mbedtls/md.h>

#define led_pin   2

String mqtt_hmacSha1(const String& data, const String& key);
void mqtt_paramsinit();

void mqtt_init();
void mqtt_connect();
void mqtt_callback(char* topic, byte* payload, unsigned int length);
void mqtt_send_telemetry();
void mqtt_send_attributes(String attribute);

#endif

2.2 代码中需修改部分

在 mywifi.cpp 中,将 ssid 和 password 替换为你的实际 WiFi 名称和密码。

在 mqtt.cpp 中,将 PRODUCT_KEY , DEVICE_NAME , DEVICE_SECRET 替换为你的ProductKey,DeviceName,DeviceSecret。

ProductKey,DeviceName,DeviceSecret可在阿里云控制台的“设备”页中查看。

三、测试结果

烧录程序后,ESP32 会自动连接 WiFi 和阿里云 MQTT 服务器,并开始周期性上报温湿度数据。在控制台的“设备 → 物模型数据 → 运行状态”中,可以看到实时更新的温度、湿度数值。

在“监控运维 → 在线调试”中选择该设备,进入“属性调试”页,对 light 属性进行设置(输入 1 或 0),点击“设置”下发指令。

看看结果

 

结语

本文通过一个完整的Demo,展示了ESP32如何快速接入阿里云物联网平台,实现温湿度数据上报和远程灯光控制。核心步骤包括:

  • 阿里云端产品和物模型配置

  • ESP32端使用MQTT+HMAC-SHA1认证连接

  • 上报数据遵循Alink标准格式

  • 接收并解析云端下发的属性设置指令

整个过程无需编写复杂的服务器代码,完全依赖阿里云托管服务,非常适合个人开发者和小型项目快速落地。

由于水平有限,文中难免存在疏漏或不当之处,欢迎大家批评指正。如果你在尝试的过程中遇到问题,欢迎留言交流、共同探讨。

程序源码

ESP32s3 + 阿里云IOT + MQTT

更多推荐