【参考资料】
【1】https://blog.csdn.net/IoT_Club/article/details/85263023
【2】https://help.aliyun.com/document_detail/73742.html?spm=a2c4g.11186623.6.648.3c9b3f86rxCIIf
本文在上一篇博客的基础上接入阿里云IOT平台,仍然采用AT命令透传,不使用其SDK。
一、产品及设备添加
- 新增产品,获得产品的ProductKey和ProductSecret;
- 新增产品时可以直接选择产品模型,该产品模型将决定MQTT消息中JSON业务包的字段;
- 在产品品类里增加设备,获取DeviceName;
二、设备连接
- MQTT的域名:
产品key加所在区域的URL,端口仍然是默认MQTT的1883
PRODUCT_KEY".iot-as-mqtt.cn-shanghai.aliyuncs.com"
- MQTT用户名
采用设备名&产品key
DEVICE_NAME "&" PRODUCT_KEY
- 连接MQTT的clientId
clientId+"|securemode=3,signmethod=hmacsha1,timestamp=132323232|"
这里clientId阿里平台建议是MAC地址;时间戳可以随便填写;加密方式采用hmacsha1
- MQTT的连接密码
将上述设备名称、产品key按如下拼接后:
clientIdtestdeviceNamearduinoTestproductKeya1NPVBYVPlMtimestamp123456789,用DeviceSecret进行hmacsha1加密
- 此时可以进行MQTT的连接,一旦连接成功,IOT平台会显示设备在线。
三、数据上报
- 参考平台给出的topic列表:
- 参考平台给出的功能定义:
- 采用MQTT工具测试接口如下:
这里也直接可以用平台自带的调试工具调试,实际上就是一个MQTT客户端:)
本文用的工具是MAC下的mqttlens
四、利用Ardiono+ESP测试Alink接口
源码如下,在上一篇博客代码的基础上做了修改,居然也花了将近3个小时才调通,还是靠着wireshark抓包比对16进制数据。。。。
#include <SoftwareSerial.h>
#include <ArduinoJson.h>
SoftwareSerial sofrserial(13, 12);
#define PRODUCT_KEY "a1NPVBYVPlM"
#define DEVICE_NAME "arduinoTest"
#define DEVICE_SECRET "XXXXX"
#define MQTT_SERVER PRODUCT_KEY".iot-as-mqtt.cn-shanghai.aliyuncs.com"
#define MQTT_PORT 1883
#define MQTT_USRNAME DEVICE_NAME "&" PRODUCT_KEY
// HMACSHA1_SRC clientIdtestdeviceNamearduinoTestproductKeya1NPVBYVPlMtimestamp123456789
// 加密秘钥为 DEVICE_SECRET
#define CLIENT_ID "test|securemode=3,timestamp=123456789,signmethod=hmacsha1|"
#define MQTT_PASSWD "XXXXXXXX"
#define ALINK_BODY_FORMAT "{\"id\":\"123\",\"version\":\"1.0\",\"method\":\"%s\",\"params\":%s}"
#define ALINK_TOPIC_PROP_POST "/sys/" PRODUCT_KEY "/" DEVICE_NAME "/thing/event/property/post"
#define ALINK_TOPIC_PROP_POSTRSP "/sys/" PRODUCT_KEY "/" DEVICE_NAME "/thing/event/property/post_reply"
#define ALINK_TOPIC_PROP_SET "/sys/" PRODUCT_KEY "/" DEVICE_NAME "/thing/service/property/set"
#define ALINK_METHOD_PROP_POST "thing.event.property.post"
void setup()
{
delay(5000);
pinMode(0, INPUT_PULLUP);
pinMode(1, INPUT_PULLUP);
Serial.begin(115200);
while (!Serial) {}
Serial.println("serial ok!");
sofrserial.begin(9600);
while (!sofrserial) {}
Serial.println("sofrserial ok!");
sofrserial.listen();
sofrserial.println("AT");
delay(500);
if(sofrserial.find("OK")){
Serial.println("ready to conncet!");
connect_wifi();
delay(4000);
clear_buffer();
_test_send_mqtt_publish_msg();
}
}
void loop() {
}
void connect_wifi(){
sofrserial.println("AT+RST");
delay(1000);
sofrserial.println("AT+CWMODE=1");
delay(500);
sofrserial.println("\"XXXX-24G\",\"XXXXX@XX\"");
sofrserial.listen();
delay(3000);
if(sofrserial.find("OK")){
Serial.println("wifi connected!");
sofrserial.println("AT+CIPMUX=0");
delay(1000);
clear_buffer();
mqtt_connect();
}
}
void mqtt_connect(){
clear_buffer();
//esp的tcp连接好像直接用域名不行,必须用ip地址
sofrserial.println("AT+CIPSTART=\"TCP\",\"XXXX\",1883");
//sofrserial.println("AT+CIPSTART=\"TCP\",\"192.168.1.18\",1883");
sofrserial.listen();
delay(3000);
if(sofrserial.find("OK")){
Serial.println("tcp connected!");
}else{
Serial.println("tcp connect failed!");
}
_test_send_mqtt_connect_msg();
}
void _test_send_mqtt_connect_msg(){
u8 mqtt_message[200]={0};
u8 packetLen;
u8 baseIndex = 0;
u8 client_id_length = strlen(CLIENT_ID);
u8 username_length = strlen(MQTT_USRNAME);
u8 password_length = strlen(MQTT_PASSWD);
packetLen = 17 + client_id_length + username_length + 2 + password_length;
mqtt_message[0] = 16;
mqtt_message[1] = packetLen - 3;
mqtt_message[2] = 1;
mqtt_message[3] = 0;
mqtt_message[4] = 4; // Protocol Name Length LSB
mqtt_message[5] = 77; // ASCII Code for M
mqtt_message[6] = 81; // ASCII Code for Q
mqtt_message[7] = 84; // ASCII Code for T
mqtt_message[8] = 84; // ASCII Code for T
mqtt_message[9] = 4; // MQTT Protocol version = 4
mqtt_message[10] = 194; // conn flags
mqtt_message[11] = 0; // Keep-alive Time Length MSB
mqtt_message[12] = 120; // Keep-alive Time Length LSB
mqtt_message[13] = (0xff00&client_id_length)>>8;// Client ID length MSB
mqtt_message[14] = 0xff&client_id_length;
for(u8 i = 0; i < client_id_length; i++){
mqtt_message[15 + i] = *((u8*)CLIENT_ID + i);
}
baseIndex = 15 + client_id_length;
mqtt_message[baseIndex++] = (0xff00 & username_length)>>8; //username length MSB
mqtt_message[baseIndex++] = 0xff & username_length; //username length LSB
for(u8 i = 0; i < username_length ; i++){
mqtt_message[baseIndex + i] = *((u8*)MQTT_USRNAME + i);
}
baseIndex += username_length;
mqtt_message[baseIndex++] = (0xff00&password_length)>>8;//password length MSB
mqtt_message[baseIndex++] = 0xff&password_length; //password length LSB
for(u8 i = 0; i < password_length ; i++){
mqtt_message[baseIndex + i] = *((u8*)MQTT_PASSWD + i);
}
send_tcp_package(mqtt_message, packetLen);
}
void _test_send_mqtt_publish_msg(){
u8 mqtt_message[200]={0};
u16 i,index=0;
u16 topic_length = strlen(ALINK_TOPIC_PROP_POST);
char param[32];
char mqtt_data[128]={0};
sprintf(param, "{\"LightSwitch\":%d}", 1);
sprintf(mqtt_data, ALINK_BODY_FORMAT, ALINK_METHOD_PROP_POST, param);
String data="";
for(int i = 0; i < sizeof(mqtt_data); i++){
if(mqtt_data[i] != 0){
data += mqtt_data[i];
}
}
u16 message_length = data.length();
mqtt_message[index++] = 50;// 增加了QOS
mqtt_message[index++] = 4 + topic_length + message_length;
mqtt_message[index++] = 1;//长度大于127
mqtt_message[index++] = (0xff00 & topic_length)>>8;
mqtt_message[index++] = 0xff & topic_length;
for(i = 0; i < topic_length; i++)
{
mqtt_message[index + i] = *((u8 *)ALINK_TOPIC_PROP_POST + i);
}
index += topic_length;
mqtt_message[index++] = (0xff00&1)>>8;
mqtt_message[index++] = 0xff&1;
for(i = 0; i < message_length; i++)
{
mqtt_message[index + i] = mqtt_data[i];
}
send_tcp_package(mqtt_message, 7 + topic_length + message_length);
}
void send_tcp_package(u8 *data,u16 len){
clear_buffer();
sofrserial.listen();
sofrserial.print("AT+CIPSEND=");
sofrserial.println(len);
delay(1000);
if(sofrserial.find( ">" ) )
{
Serial.println("start to send data.....");
Serial.println(len);
u16 i;
for(i=0; i<len; i++)
{
sofrserial.write(data[i]);
Serial.print(data[i]);
}
sofrserial.listen();
sofrserial.println();
delay(500);
}else{
Serial.println("send AT+CIPSEND failed");
}
if( sofrserial.find("OK")){
Serial.println("send succfful!!");
}else{
Serial.println("send wrong");
}
}
void clear_buffer(){
while(sofrserial.read()>= 0){}
while(Serial.read()>= 0){}
}