服务器端的Azure IoT Hub和设备端的Azure IoT Client SDK,我们发现延迟60-65秒 设备之间的丢弃通过MQTT发送状态消息,IoT Hub收到消息。 在某些情况下,当IoT Hub将消息排队时,我们会看到1-2分钟的延迟。
以下是与设备进行通信的代码
//'use strict';
//DeviceToCloudMessages libraries
var EventHubClient = require('azure-event-hubs').Client;
//var base64 = require('base-64');
//*NK+1 19-02-18 CloudToDeviceMessage Libraries
var Registry = require('azure-iothub').Registry;
//CloudToDeviceMessage libraries
var Client = require('azure-iothub').Client;
var Message = require('azure-iot-common').Message;
//*NK+1 13-03-18 Get constant values stored in GlobalConstants js
var constant = require('./GlobalConstants');
var connectionString = constant.connectionString;
var serviceClient = Client.fromConnectionString(connectionString);
//*NK+ 16-03-18 Open service cline
serviceClient.open(function (err) {
if (err) {
console.error('Could not connect: ' + err.message);
} else {
console.log('Open connection: ');
}
});
//*NK+1 19-02-18 Create registry for connection string
var registry = Registry.fromConnectionString(connectionString);
//To prevent memory leak
require('events').EventEmitter.defaultMaxListeners = Infinity;
//To check device connection state
var request = require('request');
auth = constant.authorization;
//Datetime library
date = require('date-and-time');
var moment = require("moment");
//For log
const fs = require('fs');
var datetime = require('node-datetime');
//For database connection
var sql = require('mssql');
var config =
{
user: constant.sUsername, // update me
password: constant.sPassword, // update me
server: constant.sServer, // update me
database: constant.sDatabase,
options: {
encrypt: true
},
//*start 30-01-18 set resource request timeout
connectionTimeout: 0,
requestTimeout: 0,
pool: {
max: 100,
min: 1,
idleTimeoutMillis: 30000
}
//*end 30-01-18 set resource request timeout
}
//*NK+1 23-03-18 declare flag false
//var isLog = false;
// sql.close();
//SQL starts
sql.connect(config).then(function (err) {
if (err) {
//console.log('sql CONNECTION ERROR');
console.log(err);
}
console.log('Opening connection');
var printError = function (err) {
logmsg(err.message);
logmsg('Error from event hub:', err.message);
startReceiver();
};
function logmsg(msg)
{
//if(isLog){
try {
//console.log(msg);
var dt = datetime.create();
var formatted = dt.format('Y-m-d H:M:S');
var date = dt.format('Y-m-d');
var checkhr = dt.format('H');
var filepath = 'D:/home/site/wwwroot/WebJobLogs/SendD2DMsgLog_' +date +'_' +checkhr + '-00-00' +'.txt';
fs.appendFile(filepath, formatted + " " + msg + "\n");
} catch(error) {
//console.log(error);
}
//}
}
function printResultFor(op) {
try {
return function printResult(err, res) {
if (err)
{
logmsg(op + ' error: ' + err.toString());
}
if (res)
{
logmsg(op + ' status: ' + res.constructor.name);
}
};
} catch (exception) {
logmsg("Print result function " + exception)
}
}
function receiveFeedback(err, receiver) {
receiver.on('message', function (msg) {
logmsg('IOT Feedback message:')
logmsg(msg.getData().toString('utf-8'));
});
}
//*NK+start 19-02-18 for firmware update
function queryTwinFWUpdateReported(deviceToUpdate) {
logmsg('deviceToUpdate : ' + deviceToUpdate);
logmsg('deviceToUpdate : ' + deviceToUpdate);
registry.getTwin(deviceToUpdate, function(err, twin){
if (err) {
//console.error('Could not query twins: ' + err.constructor.name + ': ' + err.message);
logmsg('Could not query twins: ' + err.constructor.name + ': ' + err.message);
} else {
//console.log('queryTwinFWUpdateReported: ' + (JSON.stringify(twin.properties.reported.iothubDM.firmwareUpdate)) + "\n");
//logmsg((JSON.stringify(twin.properties.reported.iothubDM.firmwareUpdate)) + "\n");
}
});
}
function startFirmwareUpdateDevice (linkString, deviceToUpdate) {
//console.log('linkString: ' + linkString);
var params = {
FwPackageUri: linkString
};
var methodName1 = "FirmwareUpdate";
var payloadData = JSON.stringify(params);
var payloadData1 = JSON.parse(payloadData);
logmsg('payloadData : ' + payloadData1);
var methodParams = {
methodName: methodName1,
payload: payloadData1,
timeoutInSeconds: 3600//,
//responseTimeoutInSeconds: 3600
};
//var methodParamsTest = JSON.stringify(methodParams);
//var objmethodParams = JSON.parse(methodParamsTest);
logmsg('methodParams : ' + JSON.stringify(methodParams));
//console.log('methodParams : ' + JSON.stringify(methodParams));
serviceClient.invokeDeviceMethod(deviceToUpdate, methodParams, function(err, result) {
if (err) {
//console.log('Could not start the firmware update on the device: ' + err.message);
//console.log('Device: ' + err.stack);
logmsg('Could not start the firmware update on the device: ' + err.message);
}else{
logmsg('success result : ' + JSON.stringify(result));
//console.log('success result : ' + JSON.stringify(result));
}
});
}
//*NK+end 19-02-18 for firmware update
var printMessage = function (message) {
logmsg('Message received: ');
try {
var chunk_msg = JSON.stringify(message.body);
logmsg(chunk_msg);
var obj = JSON.parse(chunk_msg);
//*NK+start 19-02-18 firmware update code
if(obj.hasOwnProperty('firmwareUpdate')){
var firmwaretype= obj.controllerName;
var firmwaremodel= obj.modelNumber;
var firmwareDeviceId = obj.firmwareUpdate;
var appDeviceId = obj.appDeviceId;
new sql.Request()
.query("SELECT f.fw_version, f.[loc] FROM <<table>> f WHERE f.[Type] = '" + firmwaretype + "' ").then(function (recordset) {
var statusLocation = JSON.stringify(recordset);
var obj = JSON.parse(statusLocation);
var result = obj.recordset;
logmsg('result: ' + result);
console.log('result: ' + result);
if(result.length > 0){
console.log('fw_version: ' + result[0].fw_version);
console.log('loc: ' + result[0].loc);
console.log('obj.firmwareUpdate : ' + firmwareDeviceId);
console.log('obj.appDeviceId : ' + appDeviceId);
new sql.Request()
.query("select TOP 1 * from <<table>> where Id = '" + firmwareDeviceId + "' order by id desc ").then(function (recordset) {
var status = JSON.stringify(recordset);
var objstatus = JSON.parse(status);
var resultstatus = objstatus.recordset;
var datastatus = resultstatus[0];
var chunkstatus = JSON.stringify(datastatus);
var objnewstatus = JSON.parse(chunkstatus);
var endDate = objnewstatus.last_update;
logmsg('controller last status date ' + endDate);
console.log('controller last status date ' + endDate);
now = new Date();
var currentDate = date.format(now, 'YYYY-MM-DD HH:mm:ss');
logmsg('server current date ' + currentDate);
console.log('server current date ' + currentDate);
var start_date = moment(currentDate, 'YYYY-MM-DD HH:mm:ss');
var end_date = moment(endDate, 'YYYY-MM-DD HH:mm:ss');
var duration = moment.duration(start_date.diff(end_date));
var hours = duration.asHours();
//var seconds = Math.abs(hours * 3600);
var seconds = Math.abs(hours * 3600);
logmsg('difference in seconds ' + seconds);
console.log('difference in seconds ' + seconds);
if (seconds < 40)
{
logmsg('fw_version: ' + result[0].fw_version);
logmsg('loc: ' + result[0].loc);
console.log('fw_version: ' + result[0].fw_version);
console.log('loc: ' + result[0].loc);
startFirmwareUpdateDevice(result[0].loc, firmwareDeviceId);
setInterval(function() {queryTwinFWUpdateReported(firmwareDeviceId);}, 1000);
}
else{
//format failure msg to send to app
var result = '{"response_status":"true","device_id":"' + firmwareDeviceId + '"}';
logmsg('Sending message to app:' + result);
console.log('Sending message to app:' + result);
var message = new Message(result);
serviceClient.send(appDeviceId, message, printResultFor('send'));
logmsg('Feedback Message for firmware upgrade failure sent to app ' + appDeviceId);
console.log('Feedback Message for firmware upgrade failure sent to app ' + appDeviceId);
}
}).catch(function (err) {
logmsg('firmware upgrade: ' + err);
});
}
}).catch(function (err) {
logmsg(err);
});
}
//*NK+end 19-02-18
if (obj.hasOwnProperty('command'))
{
logmsg('command exist');
console.log('command exist');
//Send Msg to device
//serviceClient.open(function (err) {
//if (err) {
// console.error('Could not connect: ' + err.message);
//} else {
// logmsg('Service client connected');
//*NK+1 23-03-18 Commented feedback receiver
//serviceClient.getFeedbackReceiver(receiveFeedback);
message.ack = 'full';
//message.messageId = "My Message ID";
//*NK+1 20-02-18 Update messageId
console.log('obj.messageId : ' + obj.messageId);
message.messageId = obj.messageId;
//Check the status of controller before sending message and return message to user in case of failure
var targetDevice = obj.deviceId;
new sql.Request()
.query("select TOP 1 * from <<table>> where Id = '" + targetDevice + "' order by id desc ").then(function (recordset) {
var status = JSON.stringify(recordset);
var objstatus = JSON.parse(status);
var resultstatus = objstatus.recordset;
var datastatus = resultstatus[0];
var chunkstatus = JSON.stringify(datastatus);
var objnewstatus = JSON.parse(chunkstatus);
var endDate = objnewstatus.last_update;
logmsg('controller last status date ' + endDate);
console.log('controller last status date ' + endDate);
now = new Date();
var currentDate = date.format(now, 'YYYY-MM-DD HH:mm:ss');
logmsg('server current date ' + currentDate);
console.log('server current date ' + currentDate);
var start_date = moment(currentDate, 'YYYY-MM-DD HH:mm:ss');
var end_date = moment(endDate, 'YYYY-MM-DD HH:mm:ss');
var duration = moment.duration(start_date.diff(end_date));
var hours = duration.asHours();
//var seconds = Math.abs(hours * 3600);
var seconds = Math.abs(hours * 3600);
logmsg('difference in seconds ' + seconds);
console.log('difference in seconds ' + seconds);
if (seconds <= 65)
{
var data = obj.command;
//format msg to send to controller
var str1 = '{"Name":"Play","Parameters":{"Data":"';
var res = str1.concat(data);
var str2 = '"}}';
var result = res.concat(str2);
var message = new Message(result);
logmsg('Sending message to controller: ' + message.getData());
console.log('Sending message to controller: ' + message.getData());
serviceClient.send(targetDevice, message, printResultFor('send'));
logmsg('Message sent to controller ' + targetDevice);
console.log('Message sent to controller ' + targetDevice);
}
else
{
//*NK+start 29-03-18 Check reset command and send to the server
var data_command = obj.command;
if(data_command == "<<RESETDEVICECOMMAD>>"){
//format msg to send to controller
var str1 = '{"Name":"Play","Parameters":{"Data":"';
var res = str1.concat(data_command);
var str2 = '"}}';
var result = res.concat(str2);
var message = new Message(result);
logmsg('Reset message is: ' + message.getData());
console.log('Reset message is: ' + message.getData());
serviceClient.send(targetDevice, message, printResultFor('send'));
logmsg('Reset message sent to controller ' + targetDevice);
console.log('Reset message sent to controller ' + targetDevice);
}
//*NK+start 29-03-18 Check reset command and send to the server
if (obj.hasOwnProperty('appDeviceId'))
{
//Get app device id
var AppDeviceId = obj.appDeviceId;
//format failure msg to send to app
var result = '{"response_status":"false","device_id":"' + targetDevice + '"}';
logmsg('Sending message to app:' + result);
console.log('Sending message to app:' + result);
var message = new Message(result);
serviceClient.send(AppDeviceId, message, printResultFor('send'));
logmsg('Feedback Message for command failure sent to app ' + AppDeviceId);
console.log('Feedback Message for command failure sent to app ' + AppDeviceId);
}
}
}).catch(function (err) {
logmsg(err);
});
// }
//});
}
else if (obj.hasOwnProperty('u32SH'))
{
// console.log('json exist');
var deviceId = obj.deviceId;
var data = chunk_msg;
var datetime = new Date();
//SQL to get list of device ids
new sql.Request()
.query("select * from <<table>> where id in (select id from <<table>> where id in (select id from <<table>> where Id = '" + deviceId + "')) and connectionState = 'Connected' ").then(function (recordset) {
var chunk = JSON.stringify(recordset);
var obj = JSON.parse(chunk);
var result = obj.recordset;
var message = new Message(chunk_msg);
message.ack = 'full';
message.messageId = "My Message ID";
logmsg('Sending message: ' + message.getData());
for (var i = 0, len = result.length; i < len; i++)
{
var data = result[i];
var chunk1 = JSON.stringify(data);
var obj1 = JSON.parse(chunk1);
//Get device id of user
var targetDevice = obj1.device_id;
serviceClient.send(targetDevice, message, printResultFor('send'));
logmsg('Message sent to user ' + targetDevice);
} //for loop ends
}).catch(function (err) {
logmsg(err);
}); //1st sql ends
} //else if for json object check ends
//*NK++ 06-03-18 update controller table
var macId = obj.deviceId;
updateControllerFirmwareVersion(macId);
} catch (exception) {
logmsg("Handling exception....");
logmsg(exception);
}
}; //printMessage function ends
//*NK+start 05-03-18 update controller firmware version
function updateControllerFirmwareVersion(deviceId){
registry.getTwin(deviceId, function(err, twin){
if (err) {
//console.log('Could not query twins: ' + err.constructor.name + ': ' + err.message);
console.error('Could not query twins: ' + err.constructor.name + ': ' + err.message);
} else {
logmsg((JSON.stringify(twin.properties.reported.AzureFwVersion)) + "\n");
//console.log((JSON.stringify(twin.properties.reported.AzureFwVersion)) + "\n");
//var azureFwVersion = twin.properties.reported.AzureFwVersion.replace('Azure_Sns_DM V','');
var azureFwVersion = twin.properties.reported.AzureFwVersion;
var s = azureFwVersion.lastIndexOf(".");
var res = azureFwVersion.substring(s+1, azureFwVersion.length);
//console.log('azureFwVersion: ' + res);
var firmwareV = Number(res).toString(16).toUpperCase() + '00';
//console.log('hex : ' + firmwareV);
logmsg('hex : ' + firmwareV);
new sql.Request()
.query("select fw_version from <<table>> where Id = '" + deviceId + "'").then(function (recordset) {
logmsg('Get current controller table firmware version');
var currentData = JSON.stringify(recordset);
var obj = JSON.parse(currentData);
var resultstatus = obj.recordset;
var datastatus = resultstatus[0];
var chunkstatus = JSON.stringify(datastatus);
var objnewstatus = JSON.parse(chunkstatus);
if(objnewstatus.fw_version != firmwareV){
console.log('Available firmware is ' + firmwareV);
logmsg('Available firmware is ' + firmwareV);
new sql.Request()
.query("UPDATE <<table>> SET fw_version = '" + firmwareV + "' where Id = '" + deviceId + "'").then(function (recordset) {
logmsg('Updated Controller table for firmware');
//console.log('Updated Controller table for firmware');
}).catch(function (err) {
logmsg('Qry to update Controller table for firmware' + err);
//console.log('Qry to update Controller table for firmware' + err);
});
}
}).catch(function (err) {
logmsg('Qry to update Controller table for firmware' + err);
//console.log('Qry to update Controller table for firmware' + err);
});
}
});
}
//*NK+end 05-03-18 update controller firmware version
var startReceiver = function () {
try {
logmsg('Receiver on');
var client = EventHubClient.fromConnectionString(connectionString);
client.open()
.then(client.getPartitionIds.bind(client))
.then(function (partitionIds) {
return partitionIds.map(function (partitionId) {
return client.createReceiver('$Default', partitionId, {'startAfterTime': Date.now()}).then(function (receiver) {
logmsg('Created partition receiver: ' + partitionId)
// receiver.on('errorReceived', printError);
// receiver.on('message', printMessage);
receiver.on('errorReceived', function callback() {
// console.log('Error Received in receiver');
client.close()
startReceiver()
});
receiver.on('message', printMessage);
});
})
})
// .catch(printError);
.catch(function callback() {
logmsg('Error Received in catch');
client.close()
startReceiver()
});
} catch (exception) {
logmsg("startReceiver function " + exception)
}
};
startReceiver();
}); //sql connection ends
问题: 1.邮件延迟/延迟/丢失到达IoT Hub的原因是什么? 2.节点js代码有问题吗?
我正在使用以下节点js包:
{
"name": "Haven",
"version": "1.0.0",
"description": "",
"main": "AppToServerToDevice.js",
"dependencies": {
"azure-event-hubs": "0.0.8",
"azure-iot-device": "^1.2.1",
"azure-iot-device-mqtt": "^1.2.2",
"azure-iothub": "^1.2.3",
"base-64": "^0.1.0",
"date-and-time": "^0.6.2",
"heapdump": "^0.3.9",
"moment": "^2.20.1",
"mssql": "^4.1.0",
"tedious": "^2.1.1"
},
"devDependencies": {},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
物联网中心详情:
IoT Hub详细信息: 定价等级:S2标准 物联网枢纽单位:1
SQL数据库定价层是标准:S3
请建议。
请参阅下面的示例日志。
2018-04-02 14:00:18 Message received:
2018-04-02 14:00:23 send status: MessageEnqueued
2018-04-02 14:00:23 send status: MessageEnqueued
2018-04-02 14:00:23 send status: MessageEnqueued
2018-04-02 14:00:23 send status: MessageEnqueued
2018-04-02 14:00:25 {"deviceId":"<<FAKE_ID>>","messageId":54,"u32SH":1094861843,"u32SVN":1215,"u32CVN":645,"u32SRS":2,"u32EVT_ID":9,"u8RSSI":94,"u8C1TID":0,"u8C1ETID":1,"u8C1STId":0,"u8C1ATId":1,"u8C1Rt":3,"u8C1B":36,"u8C1WL":0,"u8C1WB":36,"u8C1SB":68,"u8C1PB":0,"u8C2TID":0,"u8C2ETID":1,"u8C2STId":0,"u8C2ATId":2,"u8C2Rt":11,"u8C2B":99,"u8C2WL":11,"u8C2WB":99,"u8C2SB":99,"u8C2PB":99,"ts":"2018-04-02T14:00:23Z"}
2018-04-02 14:00:25 Message sent to user <<FAKE_ID>>
2018-04-02 14:00:25 Message sent to user <<FAKE_ID>>
2018-04-02 14:00:26 IOT Feedback message:
2018-04-02 14:00:26 [{"originalMessageId":"My Message ID","description":"Success","deviceGenerationId":"636573862820707504","deviceId":"34cebb0dd9eab292","enqueuedTimeUtc":"2018-04-02T14:00:18.6513817Z","statusCode":"Success"},{"originalMessageId":"My Message ID","description":"Success","deviceGenerationId":"636573862820707504","deviceId":"34cebb0dd9eab292","enqueuedTimeUtc":"2018-04-02T14:00:22.9953077Z","statusCode":"Success"}]