實現Google IOT Core核心連接到物聯網設備(MQTT)具體過程:
- 通過函數API創建返回公/私鑰值,保存到雲存儲;(上一篇有詳細講解如何調用API公/私鑰)。
- 讀取雲存儲公/私鑰,判斷是否註冊以及是否過期,如果過期,再次註冊API公/私鑰。
- 檢查公/私鑰值是否正確導入項目,RSA256或RSA_X256。
- 私鑰創建JWT身份驗證。
- 通過JWT以及私鑰串與設備名連接到MQTT。
一:導入項目mqtt包(Nodejs)
1.package.json
"jsonwebtoken": "^8.5.1",
"mqtt": "^3.0.0",
2.mqtt.js
'use strict';
// [START iot_mqtt_include]
const fs = require('fs');
const jwt = require('jsonwebtoken');
const mqtt = require('mqtt');
// [END iot_mqtt_include]
// The initial backoff time after a disconnection occurs, in seconds.
const MINIMUM_BACKOFF_TIME = 1;
// The maximum backoff time before giving up, in seconds.
const MAXIMUM_BACKOFF_TIME = 32;
// Whether to wait with exponential backoff before publishing.
let shouldBackoff = false;
// The current backoff time.
let backoffTime = 1;
// Whether an asynchronous publish chain is in progress.
let publishChainInProgress = false;
console.log('Google Cloud IoT Core MQTT example.');
const deviceId = "你的設備名";
const registryId = "註冊表";
const projectId = "項目名";
const region = "us-central1";//區域
const algorithm = "RS256";//密鑰類型
const privateKeyFile = "rsa_private.pem";//文件
const mqttBridgeHostname = "mqtt.googleapis.com";
const mqttBridgePort = "443";//或者8883(國外)
const messageType = "events";
const numMessages = "50";
const tokenExpMins = "20";
const gatewayId = "my-region-001";//網關id
const clientDuration = "6000";
//創建JWT函數
const createJwt = (projectId, privateKeyFile, algorithm) => {
const token = {
iat: parseInt(Date.now() / 1000),
exp: parseInt(Date.now() / 1000) + 20 * 60, // 20 minutes
aud: projectId,
};
const privateKey = fs.readFileSync(privateKeyFile);
console.log("privateKey:",privateKey.toString());
console.log("createJwt yes:",jwt.sign(token, privateKey, {algorithm: algorithm}));
return jwt.sign(token, privateKey, {algorithm: algorithm});
};
3.MQTT連接的函數實現:
//mqtt的連接
const mqttDeviceDemo = (
deviceId,
registryId,
projectId,
region,
algorithm,
privateKeyFile,
mqttBridgeHostname,
mqttBridgePort,
messageType,
numMessages
) => {
// The mqttClientId is a unique string that identifies this device. For Google
// Cloud IoT Core, it must be in the format below.
const mqttClientId = `projects/${projectId}/locations/${region}/registries/${registryId}/devices/${deviceId}`;
console.log("000++",mqttClientId);
const connectionArgs = {
host: mqttBridgeHostname,
port: mqttBridgePort,
clientId: mqttClientId,
username: 'unused',
password: createJwt(projectId, privateKeyFile, algorithm),
protocol: 'mqtts',
secureProtocol: 'TLSv1_2_method',
};
console.log("001++",connectionArgs);
// Create a client, and connect to the Google MQTT bridge.
const iatTime = parseInt(Date.now() / 1000);
const client = mqtt.connect(connectionArgs);
client.subscribe(`/devices/${deviceId}/config`, {qos: 1});
client.subscribe(`/devices/${deviceId}/commands/#`, {qos: 0});
console.log('client002======',client);
const mqttTopic = `/devices/${deviceId}/${messageType}`;
console.log('mqttTopic003======',mqttTopic);
client.on('connect', success => {
console.log('connect004');
if (!success) {
console.log('Client not connected005...');
} else if (!publishChainInProgress) {
console.log('connected...666999999');
//publishAsync(mqttTopic, client, iatTime, 1, numMessages, connectionArgs);
}
});
client.on('close', () => {
console.log('close');
shouldBackoff = true;
});
client.on('error', err => {
console.log('error', err);
});
client.on('message', (topic, message) => {
let messageStr = 'Message received: ';
if (topic === `/devices/${deviceId}/config`) {
messageStr = 'Config message received: ';
} else if (topic.startsWith(`/devices/${deviceId}/commands`)) {
messageStr = 'Command message received: ';
}
messageStr += Buffer.from(message, 'base64').toString('ascii');
console.log(messageStr);
});
client.on('packetsend', () => {
// Note: logging packet send is very verbose
});
// Once all of the messages have been published, the connection to Google Cloud
// IoT will be closed and the process will exit. See the publishAsync method.
// [END iot_mqtt_run]
};
4.調用雲函數功能:
exports.tmwrilmqtt_conent = async (req,res) => {
mqttDeviceDemo(
deviceId,
registryId,
projectId,
region,
algorithm,
privateKeyFile,
mqttBridgeHostname,
mqttBridgePort,
messageType,
numMessages
);
}
二:部署到Google Function雲函數,可通過PostMan進行調試。
1.cd~ 項目名
2.gcloud functions deploy (函數的名稱) --runtime nodejs8 --trigger-http
三:調試樣本:
四:通過命令發佈消息到設備
const SendDevice = async(
projectId,
cloudRegion,
registryId,
deviceId,
sendevicedata,
res
) => {
const iot = require('@google-cloud/iot');
const client = new iot.v1.DeviceManagerClient({
// optional auth parameters.
});
const binaryData = Buffer.from(sendevicedata).toString('base64');
const formattedName = client.devicePath(projectId,cloudRegion,registryId,deviceId);
// const binaryData = Buffer.from('wo shi ming ling device 001');
const request = {
name:formattedName,
binaryData:binaryData,
};
client.sendCommandToDevice(request)
.then(responses => {
const response = responses[0];
res.send(response);
// doThingsWith(response)
})
.catch(err => {
console.error(err);
res.send(err);
});
}
五:MQTT連接設備錯誤排除:
- Error: Connection refused: Not authorized at
解決辦法:仔細檢查客戶端的私鑰Key,是否是RSA256官方創建的,並不是帶X509。
MQTT連接設備講解到此爲止,如果依然還有不懂的,可以留言諮詢,謝謝希望能幫助到您!