- ESP8266:串口2
- TX-----------PA3
- RX------------PA2
- 火焰传感器:
- IO----------PA1
- DHT11:
- IO----------PB10
至于MQTT是怎么通信的这里就不再赘述了,还是去百度一下吧。当然了不懂里面的规则也是无所谓的。流程都是一样的。
初始化ESP8266
首先需要配置ESP8266为AP模式,连接上家里的路由器,才能与外部网络进行通信。 ssid, pswd分别为路由器的名称和密码。后面才能开始进行阿里云的连接通信了,使用的TCP的通信模式。
- uint8_t ESP8266_ConnectAP(char* ssid,char* pswd)
- {
- uint8_t cnt=5;
- while(cnt--)
- {
- memset(usart2_rxbuf,0,sizeof(usart2_rxbuf));
- ESP8266_ATSendString("AT+CWMODE_CUR=1\r\n"); //设置为STATION模式
- if(FindStr((char*)usart2_rxbuf,"OK",200) != 0)
- {
- break;
- }
- }
- if(cnt == 0)
- return 0;
- cnt=2;
- while(cnt--)
- {
- memset(usart2_txbuf,0,sizeof(usart2_txbuf));//清空发送缓冲
- memset(usart2_rxbuf,0,sizeof(usart2_rxbuf));//清空接收缓冲
- sprintf((char*)usart2_txbuf,"AT+CWJAP_CUR="%s","%s"\r\n",ssid,pswd);//连接目标AP
- ESP8266_ATSendString((char*)usart2_txbuf);
- if(FindStr((char*)usart2_rxbuf,"OK",8000)!=0) //连接成功且分配到IP
- {
- return 1;
- }
- }
- return 0;
- }
MQTT通信阿里云需要明确是阿里云的三元素,就是加密的部分。
- char ClientID[128];
- char Username[128];
- char Passward[128];
密码就是用户名和产品,加上DeviceSecret的组合。
接入域名为 ${YourProductKey}.iot-as-mqtt.${YourRegionId}.aliyuncs.com,端口固定为1883
ClientId由客户端ID(clientId)、安全模式(securemode)、签名算法类型(signmethod)和时间戳(timestamp)拼接而成。
例如${YourProductKey}|securemode=3,signmethod=hmacmd5|
来看个列表
在这里进行http://encode.chahuo.com/加密的过程。
获得的ID 用户名称和密码都填写到 ClientID Username Passward三个里面
使用的ESP8266的AT进行TCP的连接
- ESP8266_ConnectServer("TCP",ServerIP,1883)
具体AT的操作代码如下所示,使用的透传方式,就是需要在发送send指令了。
- uint8_t ESP8266_ConnectServer(char* mode,char* ip,uint16_t port)
- {
- uint8_t cnt;
- ESP8266_ExitUnvarnishedTrans(); //多次连接需退出透传
- Delay_Ms(500);
- //连接服务器
- cnt=2;
- while(cnt--)
- {
- memset(usart2_txbuf,0,sizeof(usart2_txbuf));//清空发送缓冲
- memset(usart2_rxbuf,0,sizeof(usart2_rxbuf));//清空接收缓冲
- sprintf((char*)usart2_txbuf,"AT+CIPSTART="%s","%s",%d\r\n",mode,ip,port);
- ESP8266_ATSendString((char*)usart2_txbuf);
- if(FindStr((char*)usart2_rxbuf,"CONNECT",8000) !=0 )
- {
- printf("%s",(char*)usart2_rxbuf);
- break;
- }
- }
- if(cnt == 0)
- return 0;
- //设置透传模式
- if(ESP8266_OpenTransmission()==0) return 0;
- //开启发送状态
- cnt=2;
- while(cnt--)
- {
- memset(usart2_rxbuf,0,sizeof(usart2_rxbuf)); //清空接收缓冲
- ESP8266_ATSendString("AT+CIPSEND\r\n");//开始处于透传发送状态
- if(FindStr((char*)usart2_rxbuf,">",200)!=0)
- {
- return 1;
- }
- }
- return 0;
- }
TCP通信以后,需要进行MQTT通信录。
- MQTT_Connect(ClientID, Username, Passward)
MQTT的连接代码
- //MQTT连接服务器的打包函数
- uint8_t MQTT_Connect(char *ClientID,char *Username,char *Password)
- {
- //char temp[200];
- int ClientIDLen = strlen(ClientID);
- int UsernameLen = strlen(Username);
- int PasswordLen = strlen(Password);
- int DataLen;
- MQTT_TxLen=0;
- //可变报头+Payload 每个字段包含两个字节的长度标识
- DataLen = 10 + (ClientIDLen+2) + (UsernameLen+2) + (PasswordLen+2);
- //固定报头
- //控制报文类型
- usart2_txbuf[MQTT_TxLen++] = 0x10; //MQTT Message Type CONNECT
- //剩余长度(不包括固定头部)
- do{
- uint8_t encodedByte = DataLen % 128;
- DataLen = DataLen / 128;
- // if there are more data to encode, set the top bit of this byte
- if ( DataLen > 0 )
- encodedByte = encodedByte | 128;
- usart2_txbuf[MQTT_TxLen++] = encodedByte;
- }while ( DataLen > 0 );
- //可变报头
- //协议名
- usart2_txbuf[MQTT_TxLen++] = 0; // Protocol Name Length MSB
- usart2_txbuf[MQTT_TxLen++] = 4; // Protocol Name Length LSB
- usart2_txbuf[MQTT_TxLen++] = 'M'; // ASCII Code for M
- usart2_txbuf[MQTT_TxLen++] = 'Q'; // ASCII Code for Q
- usart2_txbuf[MQTT_TxLen++] = 'T'; // ASCII Code for T
- usart2_txbuf[MQTT_TxLen++] = 'T'; // ASCII Code for T
- //协议级别
- usart2_txbuf[MQTT_TxLen++] = 4; // MQTT Protocol version = 4
- //连接标志
- usart2_txbuf[MQTT_TxLen++] = 0xc2; // conn flags
- usart2_txbuf[MQTT_TxLen++] = 0; // Keep-alive Time Length MSB
- usart2_txbuf[MQTT_TxLen++] = 60; // Keep-alive Time Length LSB 60S心跳包
- usart2_txbuf[MQTT_TxLen++] = BYTE1(ClientIDLen);// Client ID length MSB
- usart2_txbuf[MQTT_TxLen++] = BYTE0(ClientIDLen);// Client ID length LSB
- memcpy(&usart2_txbuf[MQTT_TxLen],ClientID,ClientIDLen);
- MQTT_TxLen += ClientIDLen;
- if(UsernameLen > 0)
- {
- usart2_txbuf[MQTT_TxLen++] = BYTE1(UsernameLen); //username length MSB
- usart2_txbuf[MQTT_TxLen++] = BYTE0(UsernameLen); //username length LSB
- memcpy(&usart2_txbuf[MQTT_TxLen],Username,UsernameLen);
- MQTT_TxLen += UsernameLen;
- }
- if(PasswordLen > 0){
- usart2_txbuf[MQTT_TxLen++] = BYTE1(PasswordLen); //password length MSB
- usart2_txbuf[MQTT_TxLen++] = BYTE0(PasswordLen); //password length LSB
- memcpy(&usart2_txbuf[MQTT_TxLen],Password,PasswordLen);
- MQTT_TxLen += PasswordLen;
- }
- uint8_t cnt=2;
- uint8_t wait;
- while(cnt--){
- memset(usart2_rxbuf,0,sizeof(usart2_rxbuf));
- MQTT_SendBuf(usart2_txbuf,MQTT_TxLen);
- wait=30;//等待3s时间
- while(wait--){
- //CONNECT
- if(usart2_rxbuf[0]==parket_connetAck[0] && usart2_rxbuf[1]==parket_connetAck[1]) //连接成功
建立连接以后,就是需要发布话题了。发布话题的代码如下所示:
- uint8_t MQTT_PublishData(char *topic, char *message, uint8_t qos)
- {
- int topicLength = strlen(topic);
- int messageLength = strlen(message);
- static uint16_t id=0;
- int DataLen;
- MQTT_TxLen=0;
- //有效载荷的长度这样计算:用固定报头中的剩余长度字段的值减去可变报头的长度
- //QOS为0时没有标识符
- //数据长度 主题名 报文标识符 有效载荷
- if(qos) DataLen = (2+topicLength) + 2 + messageLength;
- else DataLen = (2+topicLength) + messageLength;
- //固定报头
- //控制报文类型
- usart2_txbuf[MQTT_TxLen++] = 0x30; // MQTT Message Type PUBLISH
- //剩余长度
- do
- {
- uint8_t encodedByte = DataLen % 128;
- DataLen = DataLen / 128;
- // if there are more data to encode, set the top bit of this byte
- if ( DataLen > 0 )
- encodedByte = encodedByte | 128;
- usart2_txbuf[MQTT_TxLen++] = encodedByte;
- }while ( DataLen > 0 );
-
- usart2_txbuf[MQTT_TxLen++] = BYTE1(topicLength);//主题长度MSB
- usart2_txbuf[MQTT_TxLen++] = BYTE0(topicLength);//主题长度LSB
- memcpy(&usart2_txbuf[MQTT_TxLen],topic,topicLength);//拷贝主题
- MQTT_TxLen += topicLength;
-
- //报文标识符
- if(qos)
- {
- usart2_txbuf[MQTT_TxLen++] = BYTE1(id);
- usart2_txbuf[MQTT_TxLen++] = BYTE0(id);
- id++;
- }
- memcpy(&usart2_txbuf[MQTT_TxLen],message,messageLength);
- MQTT_TxLen += messageLength;
-
- MQTT_SendBuf(usart2_txbuf,MQTT_TxLen);
- return MQTT_TxLen;
- }
这个就是整个的操作过程。
最后需要在代码里面进行发布的操作。使用一个sprintf函数,把所有的代码转换到字符串中,然后发送出去。
- sprintf(s_temp,"{"id":1,"params":{"CurrentTemperature":%d,"CurrentHumidity":%d,"warning":%d},"version":"1.0","method":"thing.event.property.post"}",
- temperature,humidity,cnt>0?1:0);
- MQTT_PublishData(P_TOPIC_NAME, s_temp, 0);// 发送数据到服务器
最终的显示效果如图所示。
最后附上源代码