实现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连接设备讲解到此为止,如果依然还有不懂的,可以留言咨询,谢谢希望能帮助到您!