Azure IoT Hub消息延迟/延迟/丢弃

时间:2018-03-30 12:23:17

标签: node.js azure iot azure-iot-hub

服务器端的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"}]

0 个答案:

没有答案