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工作模式配置,相关指令如下:

    "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 指令发送函数设计

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

/*
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。

/*
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配置指令如下:

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配置函数如下:

/*
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 字节内存。

  函数实现如下:

/*消息订阅
形参: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

  函数实现如下:

/*发布内容*/
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. 实时上报数据

  代码示例如下:

#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协议接入云平台和数据订阅、数据发布。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐