1. Describes the MQTT protocol
1.1 the MQTT protocol
MQTT (Message Queue Telemetry Transmission) is a messaging protocol based on TCP/IP protocol stack to support asynchronous communication between parties. MQTT separates the sender from the receiver spatially and spatially, so it can scale in an unreliable network environment. Although called message queue telemetry transport, it has nothing to do with message queues and uses a publish and subscribe (Pub/Sub) model.
MQTT is a lightweight, flexible networking protocol dedicated to achieving the right balance for IoT developers:
- This lightweight protocol can be implemented over severely limited device hardware and high latency/limited bandwidth networks.
- Its flexibility makes it possible to support diverse application scenarios for IoT devices and services.
1.2 the MQTT Client library
The MQTT Client library is implemented in many languages, including Embedded C, C, Java, JavaScript, Python, C++, C#, Go, iOS, Android, etc. Eclipse Paho MQTT library download address: www.eclipse.org/paho/downlo…
The following development practices based on Nodejs version MQTT, access the address www.npmjs.com/package/mqt…
1.3 the MQTT messages
1.3.1 Fixed header
Bit
|
7
|
6
|
5
|
4
|
3
|
2
|
1
|
0
|
byte 1
|
MQTT Controls the type of packets
|
Flag bit used to specify the type of control message
|
||||||
Byte 2 5-tetrafluorobenzoic
|
Remaining length, maximum 4 bytes
|
Control message Type
The name | value | Direction of packet Flow | describe |
---|---|---|---|
Reserved | 0 | ban | keep |
CONNECT | 1 | Client -> Broker | Device Connects to the IoT platform |
CONNACK | 2 | Broker -> Client | The IoT platform confirms the connection result |
PUBLISH | 3 | two-way | news |
PUBACK | 4 | two-way | QoS=1 Indicates that the message is received |
SUBSCRIBE | 8 | Client -> Broker | Device subscribes to IoT Platform Topic |
SUBACK | 9 | Broker -> Client | IoT platform confirms subscription results |
UNSUBSCRIBE | 10 | Client -> Broker | Device unsubscribes to IoT Platform Topic |
UNSUBACK | 11 | Broker -> Client | IoT platform confirms the result of unsubscription |
PINGREQ | 12 | Client -> Broker | The device sends a heartbeat request to the IoT platform |
PINGRESP | 13 | Broker -> Client | The IoT platform responds to the device heartbeat |
DISCONNECT | 14 | Client -> Broker | Device Disconnects from the IoT platform |
Reserved | 15 | ban | keep |
Flag bit that controls the packet type
Control message | Fixed masthead logo | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
---|---|---|---|---|---|
PUBLISH | MQTT 3.1.1 use | DUP | QoS | QoS | RETAIN |
The length of the remaining
The number of bytes | The minimum value | The maximum |
---|---|---|
1 | 0 (0x00) | 127 (0x7F) |
2 | 128 (0x80, 0x01) | 16 383 (0xFF, 0x7F) |
3 | 16 384 (0x80, 0x80, 0x01) | 2 097 151 (0xFF, 0xFF, 0x7F) |
4 | 2 097 152 (0x80, 0x80, 0x80, 0x01) | 268 435 455 (0xFF, 0xFF, 0xFF, 0x7F) |
Note: The maximum payload of aliyun IoT is 256K
1.3.2 Variable Header
Some MQTT control messages contain a variable header section. It is between the fixed header and the load. The content of the mutable header varies according to the message type. The variable header Packet Identifier field exists in multiple types of packets.
Packet Identifier Bytes
Bit | 7 – 0 |
---|---|
byte 1 | Message identifier MSB |
byte 2 | Packet identifier LSB |
Control message | Message identifier |
---|---|
PUBLISH | Required (if QoS = 1,2) |
PUBACK | Need to be |
PUBREC | Need to be |
PUBREL | Need to be |
PUBCOMP | Need to be |
SUBSCRIBE | Need to be |
SUBACK | Need to be |
UNSUBSCRIBE | Need to be |
UNSUBACK | Need to be |
1.3.3 Payload
The following MQTT control message contains a payload at the end of the message. For PUBLISH, the payload is a business message.
Control message | The payload |
---|---|
CONNECT | Need to be |
PUBLISH | optional |
SUBSCRIBE | Need to be |
SUBACK | Need to be |
UNSUBSCRIBE | Need to be |
2. Establish a connection with Aliyun IoT platform
2.1 the CONNECT
MQTT protocol of Aliyun IoT platform does not support will message, and the content parameters of CONNECT message are as follows:
parameter
|
instructions
|
cleanSession
|
This flag specifies whether the connection is persistent.
0 indicates a persistent session, and the message will not be lost if QoS=1.
1 indicates a non-persistent session and clears offline messages.
|
clientId
|
Client identifier
|
username
|
Authentication and authorization credentials for the agent.
|
password
|
Authentication and authorization credentials for the agent.
|
keepAlive
|
Heartbeat time. The heartbeat range of the IoT platform is 30 seconds to 1200 seconds
|
ClientId, username, password by equipment triples (productKey, deviceName, deviceSecret) generated in accordance with the rules, the specific rules are as follows:
clientId
|
id+”|securemode=3,signmethod=hmacsha1,timestamp=”+timestamp+”|”
|
Id: indicates the client ID. The value is a string of 64 characters. The | | to extension within parameters.
Securemode: securemode. 2 indicates TLS encryption, and 3 indicates non-encryption
Signmethod: indicates the type of the signature algorithm. Timestamp: milliseconds of the current time.
|
username
|
deviceName+”&”+productKey
|
|
password
|
sign_hmac(deviceSecret,content)
|
Sign_hmac indicates the signmethod algorithm type in clientId
Content: “clientId${ID}deviceName${deviceName}productKey${productKey}timestamp${timestamp}”
|
Official documentation: help.aliyun.com/document_de…
Device-side code example (Nodejs version) client.js
/**
"dependencies": { "mqtt": "2.18.8" }
*/
const crypto = require('crypto');
const mqtt = require('mqtt');
// Device identity triplet + region
const deviceConfig = {
productKey: "Replacement".deviceName: "Replacement".deviceSecret: "Replacement".regionId: "cn-shanghai"
};
// Generate MQTT connection parameters based on triples
const options = initMqttOptions(deviceConfig);
const url = `tcp://${deviceConfig.productKey}.iot-as-mqtt.${deviceConfig.regionId}.aliyuncs.com:1883`;
//2. Establish a 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)
})
//IoT platform MQTT connection parameters initialized
function initMqttOptions(deviceConfig) {
const params = {
productKey: deviceConfig.productKey,
deviceName: deviceConfig.deviceName,
timestamp: Date.now(),
clientId: Math.random().toString(36).substr(2),}/ / CONNECT parameters
const options = {
keepalive: 60.//60s
clean: false.//cleanSession keeps the conversation going
protocolVersion: 4 / / the 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;
}
/ * generated password based on HmacSha1 reference documentation: 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');
}
Copy the code
2.2 CONNACK
receive connack packet => Packet {
cmd: 'connack'.retain: false.qos: 0.dup: false.length: 2.topic: null.payload: null.sessionPresent: false.returnCode: 0
}
Copy the code
2.4 PINGRESP
send pingreq packet => { cmd: 'pingreq' }
Copy the code
2.5 PINGRESP
receive pingresp packet => Packet {
cmd: 'pingresp'.retain: false.qos: 0.dup: false.length: 0.topic: null.payload: null
}
Copy the code
2.6 DISCONNECT
3. Publish data
3.1 the PUBLISH
//3. Attribute data reporting
const topic = `/sys/${deviceConfig.productKey}/${deviceConfig.deviceName}/thing/event/property/post`;
setInterval(function() {
// Publish data to 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);
}
Copy the code
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
}
Copy the code
3.2 PUBACK
receive puback packet => Packet {
cmd: 'puback'.retain: false.qos: 0.dup: false.length: 2.topic: null.payload: null.messageId: 38850
}
Copy the code
4. Receive data
4.1 the SUBSCRIBE
//4. Subscribe to the topic and receive instructions
const subTopic = ` /${deviceConfig.productKey}/${deviceConfig.deviceName}/control`;
client.subscribe(subTopic)
client.on('message'.function(topic, message) {
console.log("topic " + topic)
console.log("message " + message)
})
Copy the code
The SUBSCRIBE message body
send subscribe packet => { cmd: 'subscribe'.subscriptions: [{topic: '/a1hQSwFledE/eud1jXfEgCsAiP2eId9Q/control'.qos: 0}].qos: 1.retain: false.dup: false.messageId: 38851
}
Copy the code
4.2 SUBACK
SUBACK message body
receive suback packet => Packet {
cmd: 'suback'.retain: false.qos: 0.dup: false.length: 3.topic: null.payload: null.granted: [ 128].messageId: 38851
}
Copy the code
4.3 UNSUBSCRIBE
send unsubscribe packet => { cmd: 'unsubscribe'.qos: 1.messageId: 34323.unsubscriptions: [ '/a1hQSwFledE/eud1jXfEgCsAiP2eId9Q/control']}Copy the code
4.4 UNSUBACK
receive unsuback packet => Packet {
cmd: 'unsuback'.retain: false.qos: 0.dup: false.length: 2.topic: null.payload: null.messageId: 34323
}
Copy the code
5. Quality of service QoS
The quality of service
Quality of Service
|
describe
|
Ali cloud IoT
|
QoS=0
|
At most one transmission, the message may not be received
|
support
|
QoS=1
|
For at least one transmission, a message must be received, possibly repeated
|
support
|
QoS=2
|
There is one and only one transfer
|
Does not support
|
6. The device is disconnected and reconnected
The subscription relationship between the device and Ali Cloud IoT is maintained in the cloud, unless the device actively unsubscribe, the subscription relationship will not be cleared. After the device is reconnected, the subscription relationship remains, and the subscription does not need to be repeated.
7. Transport layer security TLS1.2
The link between the device and the IoT platform can be encrypted using TLS V1.2. If TLS encryption is used, you need to download the root certificate. In the CONNECT parameter, the Securemode of clientId is 2
Help.aliyun.com/document_de…