Join us at the Alibaba Cloud ACtivate Online Conference on March 5-6 to challenge assumptions, exchange ideas, and explore what is possible through digital transformation.
MQTT (Message Queuing Telemetry Transport) is a message protocol based on the TCP/IP protocol stack and supports asynchronous communication between the parties. MQTT separates the sender from the receiver in space and time, so it can be expanded in an unreliable network environment. Although it is called Message Queuing Telemetry Transport, it does not involve message queuing. It uses the publication and subscription model.
MQTT is a lightweight and flexible network protocol designed to achieve the right balance for IoT developers:
The MQTT Client library is implemented in many languages, including Embedded C, C, Java, JavaScript, Python, C++, C#, Go, iOS, Android, and so on. Download address of the MQTT library for Eclipse Paho:https://www.eclipse.org/paho/downloads.php
The following development practice is based on the MQTT for Node.js, and the address is https://www.npmjs.com/package/mqtt
Fixed Header
Control packet type
The flag bit of control packet type
Remaining length
Note: A single payload of Alibaba Cloud IoT is up to 256 K
Variable Header
Some MQTT control packets contain a variable header. It is between the fixed header and the payload. The content of the variable header varies depending on the packet type. The Packet Identifier field of the variable header exists in multiple types of packets.
Packet identifier bytes
Bit | 7 - 0 |
byte 1 | Packet identifier MSB |
byte 2 | Packet identifier LSB |
Payload
The following MQTT control packets contain a payload at the end of the packets. For PUBLISH, a payload is a business message.
Control packet | Payload |
CONNECT | Required |
PUBLISH | Optional |
SUBSCRIBE | Required |
SUBACK | Required |
UNSUBSCRIBE | Required |
The MQTT protocol of the Alibaba Cloud IoT Platform does not support "will" messages, and the CONNECT message content parameters are as follows:
clientId, username, and password are generated by the device trituples (productKey, deviceName, deviceSecret) in accordance with the following rules:
Official documents: https://www.alibabacloud.com/help/doc-detail/73742.htm
Example of device code (Node.js) client.js
/**
"dependencies": { "mqtt": "2.18.8" }
*/
const crypto = require('crypto');
const mqtt = require('mqtt');
// The trituples of the device identity + region
const deviceConfig = {
productKey: "replace",
deviceName: "replace",
deviceSecret: "replace",
regionId: "cn-shanghai"
};
//Generate mqtt connection parameters from the trituples
const options = initMqttOptions(deviceConfig);
const url = `tcp://${deviceConfig.productKey}.iot-as-mqtt.${deviceConfig.regionId}.aliyuncs.com:1883`;
//2. Establish the connection
const client = mqtt.connect(url, options);
client.on('packetsend', function (packet){
console.log('send '+packet.cmd+' packet =>',packet)
})
client.on('packetreceive', function (packet){
console.log('receive '+packet.cmd+' packet =>',packet)
})
//Initialization of mqtt connection parameters for IoT Platform
function initMqttOptions(deviceConfig) {
const params = {
productKey: deviceConfig.productKey,
deviceName: deviceConfig.deviceName,
timestamp: Date.now(),
clientId: Math.random().toString(36).substr(2),
}
// CONNECT parameter
const options = {
keepalive: 60, //60s
clean: false, //cleanSession maintains a persistent session
protocolVersion: 4 //MQTT v3.1.1
}
//1. Generate clientid, username, password
options.password = signHmacSha1(params, deviceConfig.deviceSecret);
options.clientId = `${params.clientId}|securemode=3,signmethod=hmacsha1,timestamp=${params.timestamp}|`;
options.username = `${params.deviceName}&${params.productKey}`;
return options;
}
/*
Generate a password based on HmacSha1
Reference documents: https://help.aliyun.com/document_detail/73742.html?#h2-url-1
*/
function signHmacSha1(params, deviceSecret) {
let keys = Object.keys(params).sort();
// Sort by lexicographical order
keys = keys.sort();
const list = [];
keys.map((key) => {
list.push(`${key}${params[key]}`);
});
const contentStr = list.join('');
return crypto.createHmac('sha1', deviceSecret)
.update(contentStr)
.digest('hex');
}
receive connack packet => Packet {
cmd: 'connack',
retain: false,
qos: 0,
dup: false,
length: 2,
topic: null,
payload: null,
sessionPresent: false,
returnCode: 0
}
send pingreq packet => { cmd: 'pingreq' }
receive pingresp packet => Packet {
cmd: 'pingresp',
retain: false,
qos: 0,
dup: false,
length: 0,
topic: null,
payload: null
}
//3. Report attribute data
const topic = `/sys/${deviceConfig.productKey}/${deviceConfig.deviceName}/thing/event/property/post`;
setInterval(function() {
//Publish data to the topic
client.publish(topic, getPostData(),{qos:1});
}, 5 * 1000);
function getPostData() {
const payloadJson = {
id: Date.now(),
params: {
temperature: Math.floor((Math.random() * 20) + 10),
humidity: Math.floor((Math.random() * 20) + 60)
},
method: "thing.event.property.post"
}
console.log("===postData\n topic=" + topic)
console.log(payloadJson)
return JSON.stringify(payloadJson);
}
send publish packet => { cmd: 'publish',
topic: '/sys/a1hQSwFledE/eud1jXfEgCsAiP2eId9Q/thing/event/property/post',
payload: '{"id":1543896481106,"params":{"temperature":23,"humidity":73},"method":"thing.event.property.post"}',
qos: 1,
retain: false,
messageId: 38850,
dup: false
}
receive puback packet => Packet {
cmd: 'puback',
retain: false,
qos: 0,
dup: false,
length: 2,
topic: null,
payload: null,
messageId: 38850
}
//4. Subscribe to topics and receive commands
const subTopic = `/${deviceConfig.productKey}/${deviceConfig.deviceName}/control`;
client.subscribe(subTopic)
client.on('message', function(topic, message) {
console.log("topic " + topic)
console.log("message " + message)
})
SUBSCRIBE to messages
send subscribe packet => { cmd: 'subscribe',
subscriptions:
[ { topic: '/a1hQSwFledE/eud1jXfEgCsAiP2eId9Q/control', qos: 0 } ],
qos: 1,
retain: false,
dup: false,
messageId: 38851
}
SUBACK messages
receive suback packet => Packet {
cmd: 'suback',
retain: false,
qos: 0,
dup: false,
length: 3,
topic: null,
payload: null,
granted: [ 128 ],
messageId: 38851
}
send unsubscribe packet => { cmd: 'unsubscribe',
qos: 1,
messageId: 34323,
unsubscriptions: [ '/a1hQSwFledE/eud1jXfEgCsAiP2eId9Q/control' ]
}
receive unsuback packet => Packet {
cmd: 'unsuback',
retain: false,
qos: 0,
dup: false,
length: 2,
topic: null,
payload: null,
messageId: 34323
}
The subscription relationship between the device and Alibaba Cloud IoT is maintained in the cloud. Unless the device actively unsubscribes, the subscription relationship is not cleaned up. Once the device is reconnected, it still maintains the previous subscription relationship and does not need to repeat the subscription.
The link between the device and the IoT Platform can be encrypted with TLS v1.2. If you are using TLS for encryption, you must download a root certificate. In the CONNECT parameter, the securemode of clientId is 2.
To learn more about establishing MQTT connections on Alibaba Cloud IoT Platform, visit https://www.alibabacloud.com/help/doc-detail/73742.htm
Connecting Raspberry Pi to the Alibaba Cloud IoT Platform Using Python
Completing a Smart Home System with 30 Lines of JavaScript Code
Alibaba Clouder - September 18, 2019
Alibaba Clouder - November 28, 2019
Alibaba Clouder - September 24, 2019
Alibaba Cloud Native - November 13, 2024
Alibaba Cloud Native - June 12, 2024
GeekHouse - October 19, 2018
A message service designed for IoT and mobile Internet (MI).
Learn MoreProvides secure and reliable communication between devices and the IoT Platform which allows you to manage a large number of devices on a single IoT Platform.
Learn MoreA cloud solution for smart technology providers to quickly build stable, cost-efficient, and reliable ubiquitous platforms
Learn MoreApsaraMQ for RocketMQ is a distributed message queue service that supports reliable message-based asynchronous communication among microservices, distributed systems, and serverless applications.
Learn MoreMore Posts by GXIC