基于STM32的智慧物联网系统板---thingscloud平台连接

1.thingscloud平台简介

ThingsCloud 是一个专注于物联网(IoT)设备连接、管理与应用开发的一站式云平台,旨在为企业和开发者提供高效、灵活且低成本的物联网解决方案,推动传统行业与新兴领域的智能化转型。作为物联网云平台的新标准,ThingsCloud 支持全球超过500亿设备的互联互通,已服务超过5000家大型企业,涵盖从初创公司到世界500强的广泛客户群体,覆盖智能电表、智能家居、工业网关、农业传感器、能源管理等多个领域。

其核心功能围绕设备接入、数据处理、应用开发与系统集成展开。平台支持多种通信协议,包括MQTT、HTTP、TCP、CoAP、LoRa、Zigbee、WiFi、BLE等,兼容不同品牌和类型的物联网设备,实现跨厂商设备的统一接入与管理。设备生命周期管理功能涵盖注册、配置、监控、OTA升级等环节,降低异构系统整合难度。数据采集模块可实时获取传感器数据、状态信息,并通过内置规则引擎支持数据过滤、转换、报警触发等操作,同时对接第三方云服务或本地数据库(如MySQL、InfluxDB),满足复杂场景需求。可视化与监控工具提供拖拽式仪表盘,用户可自定义数据看板,通过图表、地图、控件等形式直观展示设备状态,实时监控与异常告警功能通过邮件、短信、钉钉、企业微信、微信公众号等多渠道通知,确保问题及时响应。低代码开发环境则通过API和SDK支持快速应用开发,集成企业现有系统(如ERP、CRM)或构建新业务逻辑,显著缩短项目交付周期。

平台的技术架构采用分层设计,涵盖设备、数据、应用等核心要素。设备层通过统一接入协议与全球接入点,支持公有区、专有区、私有区等多种部署方式,确保海量设备的高并发连接与数据互通。数据层提供时序数据库与历史数据分析功能,支持10余种聚合算法,挖掘数据价值并导出分析结果。应用层通过零代码开发工具生成项目SaaS与用户App,公版ThingsX App支持iOS、Android、微信小程序、WebApp等多平台,定制App可绑定独立域名、设置品牌视觉元素,并内置用户账号体系与设备认领功能。此外,ThingsCloud 提供完善的设备地图、SQL查询、扩展信息维护、OTA固件升级等辅助功能,进一步增强设备管理能力。

2.thingscloud云配置

1.注册账号登录平台。thingscloud地址

进入控制台,创建项目

创建项目

2.创建设备


3.创建设备类型

4.关联设备

5.添加功能

6.创建用户

7.创建用户应用


8.配置应用UI

9.接入平台

10.数据上报与下发

3.安信可AI-WB2-12F应用

处理器搭载BL602芯片,内置低功耗32位RISC CPU,配备276KB RAM,支持复杂运算与多任务处理。支持802.11b/g/n协议,最高速率72.2Mbps,兼容20MHz带宽。支持BLE 5.0与Bluetooth Mesh,实现低功耗短距离通信。

安全性能上支持WPS/WEP/WPA/WPA2 Personal/WPA3安全协议,保障数据传输安全。内置安全启动功能,支持ECC-256签名镜像验证,防止固件篡改。

提供AES 128/192/256位加密引擎与SHA-1/224/256哈希算法,强化数据加密能力。

Wi-Fi接收灵敏度:-98dBm(11b模式,1Mbps速率),确保弱信号环境下的稳定连接。BLE输出功率:1Mbps速率下典型值9dBm,支持远距离通信。

支持AT指令集开发,串口通讯方式,帧格式为:115200、8、N、1

3.1 WIFI模式配置AT指令集

AI-WB2-12F可通过AT指令解析WIFI工作模式配置,相关指令如下:

c 复制代码
    "AT\r\n",
    "AT+WMODE=1,1\r\n",//设置STA模式,并保存到FLSH
    "AT+WSDHCP?\r\n",//查询STA模式下参数信息
    "AT+WJAP=nfj_wifi,asdfghjkl\r\n", //-->WIFI名和密码"
    "AT+STAINFO?\r\n",//查询连接信息
    "AT+WAUTOCONN=1,nfj_wifi,asdfghjkl\r\n",//保存wifi信息,上电自动重连
    "AT+SOCKET=4,192.168.43.5,8080\r\n",//连接服务器
    "AT+SOCKETTT\r\n",//进入透传 

3.2 指令发送函数设计

为便于相关指令发送,并保证指令发送成功,设计指令发送函数如下:

c 复制代码
/*
WIFI发送命令,检查命令返状态信息
形参:
  cmd  --要发送的命令
  stat  --命令的返回状态
返回值:0--成功,其它值--失败
*/
static u8 ESP8266_SendCmd(const char *cmd,const char *stat)
{
  u8 i=0;
  u16 j=0;
  for(i=0;i<3;i++)
  {
    usart3_cnt=0;
    usart3_flag=0;
    USARTx_SendStr(USART3,(u8*)cmd);//发送命令
    for(j=0;j<5000;j++)
    {
      if(usart3_flag)
      {
        usart3_buffer[usart3_cnt]='\0';
        if(strstr((char *)usart3_buffer,stat))
        {
          usart3_cnt=0;
          usart3_flag=0;  
          return 0;//发送成功
        }
        else
        {
          usart3_cnt=0;
          usart3_flag=0;
          //memset(usart3_buffer,sizeof(usart3_buffer),0);
        }
      }
      Delay_Ms(1);
    }
    Delay_Ms(100);
  }
  return 1;//命令发送失败
}

为保证指令成功率,采用循环发送方式,若多次发送仍不成功,则直接返回1。

3.3 配置WIFI工作模式为STA

封装函数,设置WIFI工作模式为STA。

c 复制代码
/*
STA模式TCP_Clinet初始化
形参:wifi_name --wifi名字
      wifi_key  --wifi密码
      server_ip  --服务器ip
      port --服务器端口号
//保存发出的指令
const char *wifi_cmd[]={
    "AT\r\n",
    "AT+WMODE=1,1\r\n",//设置STA模式,并保存到FLSH
    "AT+WSDHCP?\r\n",//查询STA模式下参数信息
    "AT+WJAP=nfj_wifi,asdfghjkl\r\n", //-->WIFI名和密码"
    "AT+STAINFO?\r\n",//查询连接信息
    "AT+WAUTOCONN=1,nfj_wifi,asdfghjkl\r\n",//保存wifi信息,上电自动重连
    "AT+SOCKET=4,192.168.43.5,8080\r\n",//连接服务器
    "AT+SOCKETTT\r\n",//进入透传 
};
*/
u8 ESP8266_STA_Init(const char *wifi_name,const char *wifi_key)
{
  //1.退出透传模式
  int i=0;
  for(i=0;i<3;i++)
  {
     if(ESP8266_SendCmd("AT\r\n","OK\r\n")==0)
    {
        i=0;
        break;
    }
    printf("第%d次退出透传\r\n",i+1);
    USARTx_SendStr(USART3,(u8 *)"+++\r\n");//退出透传模式
    Delay_Ms(500);
  }
  if(i>=3)return 1;//退出透传失败
  char buffer[100];
  printf("2.关回显ATE0\r\n");
  if(ESP8266_SendCmd("ATE0\r\n","OK"))return 2;
  printf("3.查询WIF自动连接:\r\n");
  if(ESP8266_SendCmd("AT+WAUTOCONN?\r\n","+WAUTOCONN")==0){
      printf("rx3=%s\n",usart3_buffer);
      if(strstr((char *)usart3_buffer,"+WAUTOCONN:0")){
        printf("3.1 设置WIFI自动重连:\r\n");
        snprintf(buffer,sizeof(buffer),"AT+WAUTOCONN=1,%s,%s\r\n",wifi_name,wifi_key);
        if(ESP8266_SendCmd(buffer,"OK\r\n"))return 3;
        printf("3.2重启WIFI模块\r\n");
        if(ESP8266_SendCmd("AT+RST\r\n","ready"))return 4;  
      }
  }
    printf("等待WIFI连接成功\r\n");
    if(ESP8266_WaitConnect()){
    printf("4.查询连接WIFI信息:\r\n");
    u8 ret=ESP8266_CheckStaInfo();
    if(ret==0  || ret==4){//wifi信息错误  
        printf("ret=%d\n",ret);
        printf("4.1 关闭WIFI自动重连:\r\n");
        //snprintf(buffer,sizeof(buffer),"AT+WAUTOCONN=1,%s,%s\r\n",wifi_name,wifi_key);
        if(ESP8266_SendCmd("AT+WAUTOCONN=0\r\n","OK\r\n"))return 3;
        printf("3.2重启WIFI模块\r\n");
        if(ESP8266_SendCmd("AT+RST\r\n","ready"))return 4;
        
        //-->设置WIFI模式为STA并保存到flash
        printf("4.1设置WIFI为STA模式\r\n");
        if(ESP8266_SendCmd("AT+WMODE=1,1\r\n","OK\r\n"))return 5;//连接WIFI失败
        //设置WIFI连接 AT+WJAP=wbyq_wifi,12345678\r\n  //-->WIFI名和密码
        printf("4.2 设置WIFI连信息\r\n");
        snprintf(buffer,sizeof(buffer),"AT+WJAP=%s,%s\r\n",wifi_name,wifi_key); 
        printf("buffer=%s",buffer);
        if(ESP8266_SendCmd(buffer,"WIFI_GOT_IP")){
            printf("err=%s\n",usart3_buffer);
            return 6;
        }//连接WIFI失败 
    }
  }
  return 0;
}

4.MQTT接入hingscloud云

4.1 配置MQTT指令

AI-WB2-12F模组支持MQTT指令集,相关MQTT配置指令如下:

c 复制代码
AT+MQTT MQTT 的配置和连接
AT+MQTT=1,192.168.202.10 //设置域名
OK
#AT+MQTT=2,1883 //设置端口号
OK
#AT+MQTT=3,1 //设置连接方式
OK
#AT+MQTT=4,client_id //设置用户 ID
OK
#AT+MQTT=5,admin //设置 MQTT 用户名
OK
#AT+MQTT=6,public //设置 MQTT 密码
OK
#AT+MQTT? //查询 MQTT 连接和配置情况
+MQTT:0,192.168.202.10,1883,1,client_id,admin,public
OK
#AT+MQTT //连接 MQTT
OK
#
+EVENT:MQTT_CONNECT //MQTT 连接成功

封装MQTT配置函数如下:

c 复制代码
/*
MQTT连接物联网平台
*/
u8 MQTT_Config(const char *ip,u16 port,const char *client_id,const char *user_name,const char *password)
{
     char buffer[200];
    //断开连接
    
    ESP8266_SendCmd("AT+MQTTDISCONN\r\n","OK\r\n");
    //1.设置心跳间隔
    //if(ESP8266_SendCmd("AT+MQTTKEEPALIVE=120,10\r\n","OK\r\n"))return 1;
    //1.设置域名
    snprintf(buffer,sizeof(buffer),"AT+MQTT=1,%s\r\n",ip);
    if(ESP8266_SendCmd(buffer,"OK\r\n"))return 2;
    //2.设置端口号
    snprintf(buffer,sizeof(buffer),"AT+MQTT=2,%d\r\n",port);
    if(ESP8266_SendCmd(buffer,"OK\r\n"))return 3;   
    //3.设置连接方式1为TCP、2为SSL
    if(ESP8266_SendCmd("AT+MQTT=3,1\r\n","OK\r\n"))return 4; 
    //4.设置用户ID
    snprintf(buffer,sizeof(buffer),"AT+MQTT=4,%s\r\n",client_id);
    printf("设置客户端id:%s,len=%d\n",buffer,strlen(buffer));
    if(ESP8266_SendCmd(buffer,"OK\r\n"))return 5;
    
    //5.设置用户名
    snprintf(buffer,sizeof(buffer),"AT+MQTT=5,%s\r\n",user_name);
    
    if(ESP8266_SendCmd(buffer,"OK\r\n"))return 6;   
    //6.设置密码
    snprintf(buffer,sizeof(buffer),"AT+MQTT=6,%s\r\n",password);
    if(ESP8266_SendCmd(buffer,"OK\r\n"))return 7;
    //7.MQTT接入
    snprintf(buffer,sizeof(buffer),"AT+MQTT\r\n");
    if(ESP8266_SendCmd(buffer,"MQTT_CONNECT")){
        printf("rx3=%s\n",usart3_buffer);
        return 8;
    }
    return 0;
}

4.2 消息订阅

消息订阅指令:

AT+MQTTSUB?

描述:查询已经订阅的主题和主题状态

响应 <status>,<Topic>

...

OK

//状态描述

status:订阅状态

0:初始化状态

1:订阅中(首次订阅)

2:订阅中(断线重连后重新订阅)

3:订阅成功

Topic:订阅的主题

AT+MQTTSUB=<topic>,<qos>

描述:订阅主题

参数 topic:要订阅的主题

qos:qos 等级(0,1,2)

响应 OK

示例 AT+MQTTSUB=testtopic0,0

OK

HELP 中的描述信息

响应 Subscribe MQTT Topic

注释 可以订阅的主题条数默认最多为 5 条,每条订阅大概消耗 100 字节内存。

函数实现如下:

c 复制代码
/*消息订阅
形参:topic --要订阅的topic
       qos  --消息质量等级,0,1,2
        flag --1为订阅,0为取消订阅
返回值:成功返回0,失败返回其他值
*/

u8 MQTT_SubTopic(const char *topic,int qos,int flag)
{
    char buffer[200];
    if(flag)
        snprintf(buffer,sizeof(buffer),"AT+MQTTSUB=%s,%d\r\n",topic,qos);
    else //取消订阅
        snprintf(buffer,sizeof(buffer),"AT+MQTTUNSUB=%s\r\n",topic); 
    if(ESP8266_SendCmd(buffer,"OK"))return 1;
    return 0;
}

4.2 消息发布

消息发布指令:

AT+MQTTPUBRAW=<topic>,<qos>,<Retained>,<length>

描述:发布 MQTT 消息

参数 topic:要发布的主题

qos:qos 等级(0,1,2)

Retained:是否为 Retained 消息 0 表示普通消息 1 表示 Retained 消息

length:要发送的数据长度

响应:OK

示例 AT+MQTTPUBRAW=testtopic,1,0,10 //向 testtopic 发送 10 字节的数据

> //收到这个字符之后开始输入要发送的数据

OK //当收到 10 字节数据后就会发送数据(可以是任意数据),发送完成会显示 OK

HELP 中的描述信息

响应 :Publish long MQTT message

函数实现如下:

c 复制代码
/*发布内容*/
u8 MQTT_PublishMesg(const char *topic,int qos,const char *msg)
{
    char buffer[512];
    int len=strlen(msg);
    //AT+MQTTPUBRAW=<topic>,<qos>,<Retained>,<length>
    snprintf(buffer,sizeof(buffer),"AT+MQTTPUBRAW=%s,%d,0,%d\r\n",topic,qos,len);
    if(ESP8266_SendCmd(buffer,">"))return 1;
    if(ESP8266_SendCmd(msg,"OK"))return 2;
    return 0;
}

5.主体函数

本案例运行流程如下:

  1. 初始硬件,如串口、RTC、OLED屏幕等;
  2. 配置WIFI模式为STA,连接wifi热点;
  3. 通过HTTP实现网络时间校准;
  4. 通过MQTT接入事物云平台;
  5. 实现数据订阅
  6. 实时上报数据

代码示例如下:

c 复制代码
#include "stm32f10x.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "usart1.h"
#include "timer.h"
#include "esp8266.h"
#include "oled.h"
#include "rtc.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define WIFI_NAME "nfj_wifi"
#define PASSWORD "asdfghjkl"

#define SERVER_IP "sh-3-mqtt.iot-api.com"//服务器IP
#define SERVER_PORT 1883 //端口号
//客户端ID:随便填写
#define ClientID "smart_home"
//用户名和密码可使用密码生成工具完成
#define Username "bi3g04ioqcadc9wz"
#define Password "qyJfsdfsLChMuT"//密文 

#define SET_TOPIC  "attributes/push"//订阅
#define POST_TOPIC "attributes"//发布
u8 g_rtcflag=0;

/******************解析 天气数据****************
形参:u8* buff原始数据
			u8 *Weather_stat天气数据标志
			u8 *data解析获取到的数据
返回值:0---成功,其他值---失败
************************************************/
u8 Weather_analysis(u8* buff,u8 *Weather_stat,u8 *data)
{
	char *p=NULL;
	u16 i=0;
	p=strstr((char *)buff,(char *)Weather_stat);//获取温度
	if(p)
	{
		p+=strlen((char *)Weather_stat)+2;
		i=0;
		while(*p!='\"' && *p!='\0')
		{
			data[i++]=*p++;
		}
		data[i]='\0';
		return 0;
	}
	else return 1;
}
int main()
{
    LED_Init();//LED
    Key_Init();
    USARTx_Init(USART1,115200);//一个字符的收发时间:1s/(115200/10)=86us
    USARTx_Init(USART2,115200);
    USARTx_Init(USART3,115200);
    OLED_Init();
    OLED_DispalyFont(16,40,16,font_16[4]);
    OLED_DispalyFont(16+16,40,16,font_16[5]);
    OLED_DisplayStr(16+32,40,16,"|");
    OLED_DispalyFont(16+40,40,16,font_16[6]);
    OLED_DisplayStr(16+56,40,16,"|");
    OLED_DisplayStr(16+64,40,16,"10");
    OLED_DispalyFont(16+80,40,16,font_16[7]);
    OLED_Refresh();
    RTC_Init();
    g_rtcflag=1;
    u8 ret=1;
    while(ret)
    {
        ret=ESP8266_STA_Init(WIFI_NAME,PASSWORD);
        printf("ret=%d\n",ret);
        if(ret==0)break;
        USARTx_SendStr(USART3,"AT+RST\r\n");
        Delay_Ms(2000);
    }
    // https://sapi.k780.com/
    //AT+HTTPCLIENTLINE=2,2,,sapi.k780.com,,,?app=life.time&appkey=25273&sign=eae95a712a66e7a97dfd39534e24ffb1&format=json\r\n
    //网络校时
      USARTx_SendStr(USART3,(u8*)"AT+HTTPCLIENTLINE=2,2,,sapi.k780.com,,,?app=life.time&appkey=25273&sign=eae95a712a66e7a97dfd39534e24ffb1&format=json\r\n");
      u16 time2=0;
  while(1)
  {
    if(usart3_flag)
    {
      usart3_buffer[usart3_cnt]='\0';
      /*
      返回的数据格式:JSon
        rx3={"success":"1",
            "result":{
      "timestamp":"1727487843", -->1970/1/1 0:0:0
                "timestamp_ms":"1727487843658",
                 "datetime_1":"2024-09-28 09:44:03",
                  "datetime_2":"2024骞?9??28??09??4??03绉?",
                    "week_1":"6","week_2":"??????,"week_3":"?ㄥ??,"week_4":"Saturday"}}
        解析内容:"timestamp":"1727487843",  --当前秒单位时间 
        需要自行实现:将秒时间转化为:年月日时分秒 
      */
      printf("rx3=%s\r\n",usart3_buffer);
      char data[30];
      if(Weather_analysis(usart3_buffer,"\"timestamp\"",(u8*)data))
      {
        printf("获取网络时间失败\r\n");
        break;
      }
      printf("data=%s\n",data);
      u32 time_sec=atoi(data)+8*60*60;
      //将秒时间写入到RTC计数器中
      //3.配置RTC寄存器
      RTC->CRH&=~(1<<0);//关闭秒中断
      u8 stat=0;
      while(!(RTC->CRL&1<<5))//等待上一次写操作完成
      {
        stat++;
        Delay_Ms(1);
        if(stat>=255)break;
      }
      if(stat>=255)
      {
        printf("RTC初始化失败,无法进入配置模式\r\n");
      }
      RTC->CRL|=1<<4;//进入配置模式  
      //写入秒时间
      RTC->CNTH=(time_sec>>16);//写入高16位
      RTC->CNTL=time_sec;//写入低16位
      //退出配置模式
      RTC->CRL&=~(1<<4);//清除配置模式
      stat=0;
      while(!(RTC->CRL&1<<5))//等待写操作完成
      {
        stat++;
        Delay_Ms(1);
        if(stat>=255)
        {
            printf("RTC初始化失败,退出配置模式失败\r\n");
        }
      }  
      RTC->CRH|=1<<0;//开启秒中断
      STM32_SetNVICPriority(3,3,RTC_IRQn);//设置优先级    
      usart3_cnt=0;
      usart3_flag=0;
      break;
    }  
    time2++;
    Delay_Ms(1);
    if(time2>=65535){
        time2=0;
        break;
    }
  } 
    printf("时间校准完成\r\n");
    ret=1;
    while(ret)
    {
        ret=MQTT_Config(SERVER_IP,SERVER_PORT,ClientID,Username,Password);
        printf("连接:ret=%d\n",ret);
        if(ret==0)break;
        Delay_Ms(3000);
    }
    ret=MQTT_SubTopic(SET_TOPIC,0,1);//消息订阅
    printf("消息订阅ret=%d\n",ret);
    u32 time=0;
    time2=5000;
    char mqtt_message[256];
    float temp=26;
    int light=300;
    while(1)
    {
        time++;
        time2++;
        Delay_Ms(1);
        if(time2>=5000)
        {
            time2=0;
            temp+=1.5;
            light+=5;
            sprintf(mqtt_message,"{\"temperature\":%.1f,\"luminosity\":%d}",temp,light);//温度
            ret=MQTT_PublishMesg(POST_TOPIC,0,mqtt_message);
            printf("消息发布ret=%d\n",ret);
        }
        if(usart3_flag)
        {
            usart3_buffer[usart3_cnt]='\0';
            printf("rx3=%s\n",usart3_buffer);
            //rx3=+EVENT:MQTT_SUB,attributes/push,20,{"alarm_state":true}
            if(strstr((char *)usart3_buffer,"\"state\":true"))
            {
                LED1=0;
                printf("开灯\n");
            }
            else if(strstr((char *)usart3_buffer,"\"state\":false"))
            {
                LED1=1;
                printf("关灯\n");
            }
            usart3_cnt=0;
            usart3_flag=0;
        }
    
        if(usart1_flag)
        {
            usart1_buffer[usart1_cnt]='\0';
            printf("rx1=%s",usart1_buffer);
            USARTx_SendStr(USART3,usart1_buffer);
            usart1_cnt=0;
            usart1_flag=0;
        }
    }
}

5.1 运行效果:

1.系统调试信息,WIFI模式配置和时间校准;

2.MQTT协议接入云平台和数据订阅、数据发布。

相关推荐
飞睿科技9 分钟前
乐鑫ESP32-S3-BOX-3,面向AIoT与边缘智能的新一代开发套件
人工智能·嵌入式硬件·esp32·智能家居·乐鑫科技
Y1rong17 分钟前
STM32之SPI
stm32·单片机·嵌入式硬件
p666666666819 分钟前
STM32(基于 ARM Cortex-M 内核)中函数调用栈帧的开辟 销毁过程
arm开发·stm32·嵌入式硬件
普马萨特20 分钟前
移动网络信号指标与单位整理(2G/3G/4G/5G Android vs IoT)
android·网络·物联网
码咔吧咔27 分钟前
DMA1和DMA2是什么?DMA总线与Dcode总线有区别?SDIO又是干嘛的,system干嘛的?总线矩阵干嘛的?
stm32·单片机·嵌入式硬件
小郭团队31 分钟前
未来PLC会消失吗?会被嵌入式系统取代吗?
c语言·人工智能·python·嵌入式硬件·架构
Aaron158831 分钟前
全频段SDR干扰源模块设计
人工智能·嵌入式硬件·算法·fpga开发·硬件架构·信息与通信·基带工程
星图易码38 分钟前
星图云开发者平台功能详解 | IoT物联网平台:工业设备全链路智能管控中枢
分布式·物联网·低代码·低代码平台
The_superstar638 分钟前
视觉模块与STM32进行串口通讯(匠心制作)
stm32·嵌入式硬件·mongodb·计算机视觉·串口通讯·视觉模块
Dillon Dong1 小时前
STM32嵌入式:如何使用VSCode EIDE来获取flash块数据并转换成可视化的数据 来判断源头数据是否错误
vscode·stm32·嵌入式硬件