之前只做過類似的但是以為這種爛大街的功能應該不難結果還是踩了不少坑,記錄幾個需要注意的點
首先貼一個非常有用的視頻,里面講的很詳細,給的資料也很全【【新版OneNet云平臺】STM32+ESP8266上傳數據,簡單易上手!】?https://www.bilibili.com/video/BV1jS421A7Bk/?share_source=copy_web&vd_source=cfdb072e82eccc98495802cc5b56a05c
1、創建產品的時候選擇onejson,自定義方案。這樣選擇的就是物模型,之后可以去使用物模型的API調試。
2、設置物模型
大概有以下幾種比較常用的,int32,float,enum。enum設置的屬性都是到時候用來做指令下發的,其余是上傳傳感器數據的。要注意onenet平臺接受的是json格式數據,而且上傳的數據格式必須與你設置的對應上。下面給了個OneNet_FillBuf示例。id不用改,主要是temper標識符和value后面的格式 %d 需要和你設置的物模型對應上
unsigned char OneNet_FillBuf(char *buf)
{char text[48];strcpy(buf,"{\"id\":\"1124\",\"params\":{");memset(text,0,sizeof(text));sprintf(text,"\"temper\":{\"value\":%d},",sensorData.temp);strcat(buf,text);memset(text,0,sizeof(text));sprintf(text,"\"humidity\":{\"value\":%.2f},",sensorData.humidity);strcat(buf,text);memset(text,0,sizeof(text));sprintf(text,"\"tvoc\":{\"value\":%d},",sensorData.tvoc);strcat(buf,text);memset(text,0,sizeof(text));sprintf(text,"\"light\":{\"value\":%d},",sensorData.light);strcat(buf,text);memset(text,0,sizeof(text));sprintf(text,"\"water_level\":{\"value\":%.2f}",sensorData.water_level);strcat(buf,text);strcat(buf,"}}");return strlen(buf);}//==========================================================
// 函數名稱: OneNet_SendData
//
// 函數功能: 上傳數據到平臺
//
// 入口參數: type:發送數據的格式
//
// 返回參數: 無
//
// 說明:
//==========================================================
void OneNet_SendData(void)
{MQTT_PACKET_STRUCTURE mqttPacket = {NULL, 0, 0, 0}; //協議包char buf[256];short body_len = 0, i = 0;memset(buf, 0, sizeof(buf));//清空數組內容body_len = OneNet_FillBuf(buf); //獲取當前需要發送的數據流的總長度//printf("%s\r\n",buf);if(body_len){if(MQTT_PacketSaveData(DEVICE_NAME, body_len, NULL, 5, &mqttPacket) == 0) //封包{for(; i < body_len; i++){mqttPacket._data[mqttPacket._len++] = buf[i];}ESP8266_SendData(mqttPacket._data, mqttPacket._len); //上傳數據到平臺MQTT_DeleteBuffer(&mqttPacket); //刪包}else;
// //printf( "WARN:EDP_NewBuffer Failed\r\n");}}
3、微信小程序實現傳感器數據的同步顯示和指令下發(微信小程序代碼)
這里主要用了這兩個API,可以現在onenet云平臺上調試一下,看正確的返回格式是什么樣。
設備屬性最新數據查詢示例代碼如下:
//OneNet接入信息配置
const MQTT_Product_Id = "";
const MQTT_Device_Name = "";// MQTT API配置
const MQTT_GET_URL = "https://iot-api.heclouds.com/thingmodel/query-device-property?product_id=" + MQTT_Product_Id + "&device_name=" + MQTT_Device_Name;const MQTT_POST_URL = "https://iot-api.heclouds.com/thingmodel/set-device-desired-property";//使用token工具生成
const MQTT_Authorization = "";onLoad: function() {// 頁面加載時立即獲取一次數據this.getinfo();// 設置定時器,每5秒獲取一次數據this.setData({timer: setInterval(() => {this.getinfo();}, 5000)});},getinfo: function() {var that = this;wx.request({url: MQTT_GET_URL,header: {"authorization": MQTT_Authorization},method: "GET",success: function(res) {console.log("獲取成功", res);if (res.data && res.data.code === 0) {// 解析設備數據const deviceData = {};res.data.data.forEach(item => {if (item && item.identifier) {deviceData[item.identifier] = item.value;}});// 更新頁面數據that.setData({soilHumidity: deviceData['humidity'] + '%',waterLevel: deviceData['water_level'] + 'm',lightIntensity: deviceData['light'] + 'lux',airQuality: deviceData['tvoc'],envTemper: deviceData['temper'] + '℃',lastUpdateTime: new Date().toLocaleTimeString()});}},fail: function(err) {console.error('獲取數據失敗:', err);}});}
指令下發的示例代碼如下:
toggleMode() {const newMode = !this.data.autoMode;const modeValue = newMode ? 0 : 2;wx.request({url: MQTT_POST_URL,method: 'POST',header: {"authorization": MQTT_Authorization},data: {"product_id": MQTT_Product_Id,"device_name": MQTT_Device_Name,"params": {"mode": modeValue}},success: res => {console.log("模式切換成功:", res);this.setData({autoMode: newMode});},fail: err => {console.error("模式切換失敗:", err);wx.showToast({title: '模式切換失敗',icon: 'none'});}});},
4、微信小程序指令下發之后,單片機那邊進行數據解析(單片機端代碼)
單片機收到的數據是json格式的,所以只需要去尋找目標字段,然后讀取后面的數值即可
void OneNet_RevPro(unsigned char *cmd)
{char *req_payload = NULL;char *cmdid_topic = NULL;unsigned short topic_len = 0;unsigned short req_len = 0;unsigned char qos = 0;static unsigned short pkt_id = 0;unsigned char type = 0;short result = 0;type = MQTT_UnPacketRecv(cmd);switch(type){case MQTT_PKT_PUBLISH: //接收的Publish消息result = MQTT_UnPacketPublish(cmd, &cmdid_topic, &topic_len, &req_payload, &req_len, &qos, &pkt_id);if(result == 0){// printf( "topic: %s, topic_len: %d, payload: %s, payload_len: %d\r\n",
// cmdid_topic, topic_len, req_payload, req_len); }case MQTT_PKT_PUBACK: //發送Publish消息,平臺回復的Ackif(MQTT_UnPacketPublishAck(cmd) == 0){//printf( "Tips: MQTT Publish Send OK\r\n");}break;case MQTT_PKT_SUBACK: //發送Subscribe消息的Ackif(MQTT_UnPacketSubscribe(cmd) == 0){//printf( "Tips: MQTT Subscribe OK\r\n");}else{//printf( "Tips: MQTT Subscribe Err\r\n");}break;default:result = -1;break;}ESP8266_Clear(); //清空緩存if(result == -1)return;//解析req_payload數組中的值即可char *pump_ptr = strstr(req_payload, "\"pump\":");if (pump_ptr != NULL) {}if(type == MQTT_PKT_CMD || type == MQTT_PKT_PUBLISH){MQTT_FreeBuffer(cmdid_topic);MQTT_FreeBuffer(req_payload);}}
5、(補充)如何使用token生成需要的MQTT鑒權信息
需要使用到這個token計算工具(上文的視頻提供的資料里有)
需要填寫的內容分別是:
res:products/你的產品id/devices/你的設備id
et:時間戳 盡量往后填就行了,可以使用這個網址轉換https://www.beijing-time.org/shijianchuo/
key:設備密鑰
method我使用的sha1,version不需要改
?
最后祝大家都調試順利~后續可能還會隨緣更新一些實現細節