这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界» 论坛首页» 嵌入式开发» STM32» STM32G070RB探测38-MQTT协议剖析4SUBSCRIBE

共10条 1/1 1 跳转至

STM32G070RB探测38-MQTT协议剖析4SUBSCRIBE

高工
2021-05-30 01:40:13 打赏
前几篇写完了上传,这篇写一下接收(当然是点灯了),有来有回才对嘛。mqtt的接收一般是通过订阅topic,然后接收topic内的消息,需要提前订阅一个topic才能收到,继续看协议

跟以上基本都是大差不差的,就不详细分析了

直接贴程序吧

//========================================================== // 函数名称: MQTT_PacketSubscribe // // 函数功能: Subscribe消息组包 // // 入口参数: pkt_id:pkt_id // qos:消息重发次数 // topics:订阅的消息 // topics_cnt:订阅的消息个数 // mqttPacket:包指针 // // 返回参数: 0-成功 其他-失败 // // 说明: //========================================================== uint8 MQTT_PacketSubscribe(uint16 pkt_id, enum MqttQosLevel qos, const int8 *topics[], uint8 topics_cnt, MQTT_PACKET_STRUCTURE *mqttPacket) { uint32 topic_len = 0, remain_len = 0; int16 len = 0; uint8 i = 0; if(pkt_id == 0) return 1; //计算topic长度------------------------------------------------------------------------- for(; i < topics_cnt; i++) { if(topics[i] == NULL) return 2; topic_len += strlen(topics[i]); } //2 bytes packet id + topic filter(2 bytes topic + topic length + 1 byte reserve)------ remain_len = 2 + 3 * topics_cnt + topic_len; //分配内存------------------------------------------------------------------------------ MQTT_NewBuffer(mqttPacket, remain_len + 5); if(mqttPacket->_data == NULL) return 3; /*************************************固定头部***********************************************/ //固定头部----------------------头部消息------------------------------------------------- mqttPacket->_data[mqttPacket->_len++] = MQTT_PKT_SUBSCRIBE << 4 | 0x02; //固定头部----------------------剩余长度值----------------------------------------------- len = MQTT_DumpLength(remain_len, mqttPacket->_data + mqttPacket->_len); if(len < 0) { MQTT_DeleteBuffer(mqttPacket); return 4; } else mqttPacket->_len += len; /*************************************payload***********************************************/ //payload----------------------pkt_id--------------------------------------------------- mqttPacket->_data[mqttPacket->_len++] = MOSQ_MSB(pkt_id); mqttPacket->_data[mqttPacket->_len++] = MOSQ_LSB(pkt_id); //payload----------------------topic_name----------------------------------------------- for(i = 0; i < topics_cnt; i++) { topic_len = strlen(topics[i]); mqttPacket->_data[mqttPacket->_len++] = MOSQ_MSB(topic_len); mqttPacket->_data[mqttPacket->_len++] = MOSQ_LSB(topic_len); strncat((int8 *)mqttPacket->_data + mqttPacket->_len, topics[i], topic_len); mqttPacket->_len += topic_len; mqttPacket->_data[mqttPacket->_len++] = qos & 0xFF; } return 0; }
//========================================================== // 函数名称: OneNet_Subscribe // // 函数功能: 订阅 // // 入口参数: topics:订阅的topic // topic_cnt:topic个数 // // 返回参数: SEND_TYPE_OK-成功 SEND_TYPE_SUBSCRIBE-需要重发 // // 说明: //========================================================== void OneNet_Subscribe(const char *topics[], unsigned char topic_cnt) { unsigned char i = 0; MQTT_PACKET_STRUCTURE mqttPacket = {NULL, 0, 0, 0}; //协议包 for(; i < topic_cnt; i++) UsartPrintf("Subscribe Topic: %s\r\n", topics[i]); if(MQTT_PacketSubscribe(MQTT_SUBSCRIBE_ID, MQTT_QOS_LEVEL0, topics, topic_cnt, &mqttPacket) == 0) { ESP8266_SendData(mqttPacket._data, mqttPacket._len); //向平台发送订阅请求 MQTT_DeleteBuffer(&mqttPacket); //删包 } }
需要在连接平台之后就订阅这个topic,但是,是哪个topic呢?不知道就看文档,看下onenet的文档

const char *devSubTopic[] = {"$sys/407529/G0701/cmd/#"};
在CONNECT之后订阅,然后根据文档,下发指令
OneNet_Subscribe(devSubTopic, 1);

照抄官方的写一个接收加判断函数,放在主程序中

OneNet_DevLink(); HAL_Delay(500); Clear_Usart(&usart1_rx); OneNet_Subscribe(devSubTopic, 1); Clear_Usart(&usart1_rx); time6_count = 110; /* USER CODE END 2 */


/* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { if(time6_count1>10) { time6_count1 = 0; AHT10ReadData(&pv.tem,&pv.hum); BH1750_Read_Dat(pv.lux);//读取数据 pv.lux_16 = BH1750_Dat_To_Lux(pv.lux);//转换数据 printf("lux:%d\r\n",pv.lux_16); printf("tem:%.1f\r\nhum:%d%%\r\n",pv.tem,pv.hum); BH1750_Send_Cmd(ONCE_H_MODE);//单次模式 sprintf(buf,"tem:%.1f",pv.tem); OLED_P8x16Str(0u,4u,(uint8_t *)buf); sprintf(buf,"hum:%d%%",pv.hum); OLED_P8x16Str(64u,4u,(uint8_t *)buf); sprintf(buf,"lux:%d ",pv.lux_16); OLED_P8x16Str(0u,6u,(uint8_t *)buf); } if(time6_count>120) { time6_count = 0; memset(PUB_BUF, 0, sizeof(PUB_BUF)); OneNet_FillBuf(PUB_BUF); printf("PUB_BUF:%s\r\n",PUB_BUF); OneNet_Publish(devPubTopic, PUB_BUF); } one_ipd_rx = ESP8266_GetIPD(); if(one_ipd_rx.len > 0 ) { OneNet_RevPro(one_ipd_rx.IPD_buff); } /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ }


void OneNet_RevPro(unsigned char *cmd) { MQTT_PACKET_STRUCTURE mqttPacket = {NULL, 0, 0, 0}; char *req_payload = NULL; char *cmdid_topic = NULL; unsigned short topic_len = 0; unsigned short req_len = 0; unsigned char type = 0; unsigned char qos = 0; static unsigned short pkt_id = 0; short result = 0; //char *dataPtr = NULL; type = MQTT_UnPacketRecv(cmd); switch(type) { case MQTT_PKT_CMD://命令下发 result = MQTT_UnPacketCmd(cmd, &cmdid_topic, &req_payload, &req_len); if(result == 0) { UsartPrintf("cmdid: %s, req: %s, req_len: %d\r\n", cmdid_topic, req_payload, req_len); MQTT_DeleteBuffer(&mqttPacket); } break; case MQTT_PKT_PUBLISH://接收的Publish消息 result = MQTT_UnPacketPublish(cmd, &cmdid_topic, &topic_len, &req_payload, &req_len, &qos, &pkt_id); if(result == 0) { UsartPrintf("topic: %s, topic_len: %d, payload: %s, payload_len: %d\r\n", cmdid_topic, topic_len, req_payload, req_len); if(strstr(req_payload, "led_close") != NULL) { HAL_GPIO_WritePin(LED_GREEN_GPIO_Port,LED_GREEN_Pin,GPIO_PIN_RESET); UsartPrintf("LED_OFF\r\n"); } else if(strstr(req_payload, "led_open") != NULL) { HAL_GPIO_WritePin(LED_GREEN_GPIO_Port,LED_GREEN_Pin,GPIO_PIN_SET); UsartPrintf("LED_ON\r\n"); } } break; case MQTT_PKT_PUBACK: //发送Publish消息,平台回复的Ack if(MQTT_UnPacketPublishAck(cmd) == 0) UsartPrintf("Tips: MQTT Publish Send OK\r\n"); break; case MQTT_PKT_PUBREC://发送Publish消息,平台回复的Rec,设备需回复Rel消息 if(MQTT_UnPacketPublishRec(cmd) == 0) { UsartPrintf("Tips: Rev PublishRec\r\n"); if(MQTT_PacketPublishRel(MQTT_PUBLISH_ID, &mqttPacket) == 0) { UsartPrintf("Tips: Send PublishRel\r\n"); ESP8266_SendData(mqttPacket._data, mqttPacket._len); MQTT_DeleteBuffer(&mqttPacket); } } break; case MQTT_PKT_PUBREL://收到Publish消息,设备回复Rec后,平台回复的Rel,设备需再回复Comp if(MQTT_UnPacketPublishRel(cmd, pkt_id) == 0) { UsartPrintf( "Tips: Rev PublishRel\r\n"); if(MQTT_PacketPublishComp(MQTT_PUBLISH_ID, &mqttPacket) == 0) { UsartPrintf("Tips: Send PublishComp\r\n"); ESP8266_SendData(mqttPacket._data, mqttPacket._len); MQTT_DeleteBuffer(&mqttPacket); } } break; case MQTT_PKT_PUBCOMP://发送Publish消息,平台返回Rec,设备回复Rel,平台再返回的Comp if(MQTT_UnPacketPublishComp(cmd) == 0) { UsartPrintf("Tips: Rev PublishComp\r\n"); } break; case MQTT_PKT_SUBACK://发送Subscribe消息的Ack if(MQTT_UnPacketSubscribe(cmd) == 0) UsartPrintf("Tips: MQTT Subscribe OK\r\n"); else UsartPrintf("Tips: MQTT Subscribe Err\r\n"); break; case MQTT_PKT_UNSUBACK: //发送UnSubscribe消息的Ack if(MQTT_UnPacketUnSubscribe(cmd) == 0) UsartPrintf("Tips: MQTT UnSubscribe OK\r\n"); else UsartPrintf("Tips: MQTT UnSubscribe Err\r\n"); break; default: result = -1; break; } Clear_Usart(&usart1_rx); if(result == -1) return; if(type == MQTT_PKT_CMD || type == MQTT_PKT_PUBLISH) { MQTT_FreeBuffer(cmdid_topic); MQTT_FreeBuffer(req_payload); } }

下发 led_close 关灯 下发 led_open 开灯

完成



专家
2021-05-30 07:25:48 打赏
2楼

收藏


高工
2021-05-30 11:33:30 打赏
3楼

Very Nice


助工
2021-05-30 15:33:09 打赏
4楼

q


高工
2021-05-30 23:46:49 打赏
5楼

感谢分享


专家
2021-05-31 00:03:05 打赏
6楼

感谢楼主的分享,很实用了。


工程师
2021-05-31 00:11:32 打赏
7楼

感谢楼主的分享,很实用了。


专家
2021-05-31 06:29:04 打赏
8楼
谢谢分享!



高工
2021-06-04 23:45:30 打赏
9楼

剖析做的蛮不错的


工程师
2021-06-05 23:42:29 打赏
10楼

协议搞得蛮不错的


共10条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册]