• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

telefonicaid / iotagent-json / 6586588210

20 Oct 2023 10:32AM UTC coverage: 77.27% (+0.03%) from 77.24%
6586588210

push

github

web-flow
Merge pull request #772 from telefonicaid/task/remove_placeholders_logs

remove placeholders in logs and \n

364 of 540 branches covered (0.0%)

Branch coverage included in aggregate %.

10 of 10 new or added lines in 3 files covered. (100.0%)

836 of 1013 relevant lines covered (82.53%)

69.62 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

72.79
/lib/bindings/HTTPBinding.js
1
/*
2
 * Copyright 2016 Telefonica Investigación y Desarrollo, S.A.U
3
 *
4
 * This file is part of iotagent-json
5
 *
6
 * iotagent-json is free software: you can redistribute it and/or
7
 * modify it under the terms of the GNU Affero General Public License as
8
 * published by the Free Software Foundation, either version 3 of the License,
9
 * or (at your option) any later version.
10
 *
11
 * iotagent-json is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
 * See the GNU Affero General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Affero General Public
17
 * License along with iotagent-json.
18
 * If not, seehttp://www.gnu.org/licenses/.
19
 *
20
 * For those usages not covered by the GNU Affero General Public License
21
 * please contact with::[contacto@tid.es]
22
 */
23

24
/* eslint-disable no-unused-vars */
25

26
const fs = require('fs');
1✔
27
const iotAgentLib = require('iotagent-node-lib');
1✔
28
const regenerateTransid = iotAgentLib.regenerateTransid;
1✔
29
const finishSouthBoundTransaction = iotAgentLib.finishSouthBoundTransaction;
1✔
30
const fillService = iotAgentLib.fillService;
1✔
31
const intoTrans = iotAgentLib.intoTrans;
1✔
32
const _ = require('underscore');
1✔
33
const commandHandler = require('../commandHandler');
1✔
34
const async = require('async');
1✔
35
const apply = async.apply;
1✔
36
const request = iotAgentLib.request;
1✔
37
const errors = require('../errors');
1✔
38
const express = require('express');
1✔
39
const iotaUtils = require('../iotaUtils');
1✔
40
const http = require('http');
1✔
41
const https = require('https');
1✔
42
const commonBindings = require('../commonBindings');
1✔
43
const bodyParser = require('body-parser');
1✔
44
const constants = require('../constants');
1✔
45
let context = {
1✔
46
    op: 'IOTAJSON.HTTP.Binding'
47
};
48
const config = require('../configService');
1✔
49
let httpBindingServer;
50
const transport = 'HTTP';
1✔
51

52
const { promisify } = require('util');
1✔
53
const json = promisify(bodyParser.json({ strict: false })); // accept anything JSON.parse accepts.
1✔
54
const text = promisify(bodyParser.text());
1✔
55
const raw = promisify(bodyParser.raw());
1✔
56

57
function parserBody() {
58
    // generic bodyParser
59
    return function (req, res, next) {
119✔
60
        if (req.is('text/plain')) {
6✔
61
            text(req, res).then(() => next(), next);
2✔
62
        } else if (req.is('application/octet-stream')) {
4✔
63
            raw(req, res).then(() => next(), next);
2✔
64
        } else {
65
            // req.is('json')
66
            json(req, res).then(() => next(), next);
2✔
67
        }
68
    };
69
}
70

71
function checkMandatoryParams(queryPayload) {
72
    return function (req, res, next) {
595✔
73
        const notFoundParams = [];
48✔
74
        let error;
75

76
        req.apiKey = req.query.k;
48✔
77
        req.deviceId = req.query.i;
48✔
78
        req.attr = req.params ? req.params.attrValue : undefined;
48!
79

80
        if (!req.apiKey) {
48!
81
            notFoundParams.push('API Key');
×
82
        }
83

84
        if (!req.deviceId) {
48!
85
            notFoundParams.push('Device Id');
×
86
        }
87

88
        // Check if retrievingParam
89
        if (queryPayload && !req.query.d && req.query.getCmd !== '1') {
48!
90
            notFoundParams.push('Payload');
×
91
        }
92
        if (req.method === 'POST' && !req.is('json') && !req.is('text/plain') && !req.is('application/octet-stream')) {
48!
93
            error = new errors.UnsupportedType('application/json, text/plain, application/octet-stream');
×
94
        }
95

96
        if (notFoundParams.length !== 0) {
48!
97
            next(new errors.MandatoryParamsNotFound(notFoundParams));
×
98
        } else {
99
            next(error);
48✔
100
        }
101
    };
102
}
103

104
function parseData(req, res, next) {
105
    let data;
106
    let error;
107
    let payload;
108

109
    if (req.body) {
13✔
110
        config.getLogger().debug(context, 'Using body %s', req.body);
12✔
111
        data = req.body;
12✔
112
        regenerateTransid(data);
12✔
113
    } else {
114
        payload = req.query.d;
1✔
115
        regenerateTransid(payload);
1✔
116
        config.getLogger().debug(context, 'Parsing payload %s', payload);
1✔
117

118
        try {
1✔
119
            if (payload) {
1!
120
                data = JSON.parse(payload);
×
121
            }
122
        } catch (e) {
123
            error = e;
×
124
        }
125
    }
126

127
    if (error) {
13!
128
        next(error);
×
129
    } else {
130
        req.jsonPayload = data;
13✔
131
        if (req.body !== undefined) {
13✔
132
            try {
12✔
133
                // This is just for log data
134
                data = data.toString('hex');
12✔
135
            } catch (e) {
136
                // no error should be reported
137
            }
138
        }
139
        config.getLogger().debug(context, 'Parsed data: %j', data);
13✔
140
        next();
13✔
141
    }
142
}
143

144
function parseDataMultipleMeasure(req, res, next) {
145
    let data;
146
    let error;
147
    let payload;
148
    let dataArray;
149
    dataArray = [];
35✔
150
    if (req.body) {
35!
151
        config.getLogger().debug(context, 'Using body %s', req.body);
35✔
152
        if (!Array.isArray(req.body)) {
35✔
153
            dataArray.push(req.body);
29✔
154
        } else {
155
            dataArray = req.body;
6✔
156
        }
157
        regenerateTransid(dataArray);
35✔
158
    } else {
159
        payload = req.query.d;
×
160
        regenerateTransid(payload);
×
161
        config.getLogger().debug(context, 'Parsing payload %s', payload);
×
162
        try {
×
163
            if (payload) {
×
164
                data = JSON.parse(payload);
×
165
                dataArray.push(data);
×
166
            }
167
        } catch (e) {
168
            error = e;
×
169
        }
170
    }
171
    if (error) {
35!
172
        next(error);
×
173
    } else {
174
        req.jsonPayload = dataArray;
35✔
175
        config.getLogger().debug(context, 'Parsed data array: %j', dataArray);
35✔
176
        next();
35✔
177
    }
178
}
179

180
function executeCommand(apiKey, device, cmdName, serializedPayload, contentType, callback) {
181
    const options = {
6✔
182
        url: device.endpoint,
183
        method: 'POST',
184
        body: serializedPayload,
185
        headers: {
186
            'fiware-service': device.service,
187
            'fiware-servicepath': device.subservice,
188
            'content-type': contentType
189
        }
190
    };
191
    if (device.endpoint) {
6!
192
        // device.endpoint or another field like device.endpointExp ?
193
        const parser = iotAgentLib.dataPlugins.expressionTransformation;
6✔
194
        let attrList = iotAgentLib.dataPlugins.utils.getIdTypeServSubServiceFromDevice(device);
6✔
195
        attrList = device.staticAttributes ? attrList.concat(device.staticAttributes) : attrList.concat([]);
6!
196
        const ctxt = parser.extractContext(attrList, device);
6✔
197
        config.getLogger().debug(context, 'attrList %j for device %j', attrList, device);
6✔
198
        // expression result will be the full command payload
199
        let endpointRes = null;
6✔
200
        try {
6✔
201
            endpointRes = parser.applyExpression(device.endpoint, ctxt, device);
6✔
202
        } catch (e) {
203
            // no error should be reported
204
        }
205
        options.url = endpointRes ? endpointRes : device.endpoint;
6!
206
    }
207
    if (config.getConfig().http.timeout) {
6!
208
        options.timeout = config.getConfig().http.timeout;
×
209
    }
210
    config
6✔
211
        .getLogger()
212
        .debug(
213
            context,
214
            'Sending command %s with payload %s and with http options %j',
215
            cmdName,
216
            serializedPayload,
217
            options
218
        );
219
    request(options, function (error, response, body) {
6✔
220
        if (error || !response || (response.statusCode !== 200 && response.statusCode !== 201)) {
6!
221
            callback(new errors.HTTPCommandResponseError(response ? response.statusCode : 400, error));
×
222
        } else if (apiKey) {
6!
223
            config
6✔
224
                .getLogger()
225
                .info(
226
                    context,
227
                    'Cmd: %j was sent to the device %s with http options %j',
228
                    serializedPayload,
229
                    cmdName,
230
                    options
231
                );
232
            process.nextTick(commandHandler.updateCommand.bind(null, apiKey, device.id, device, body));
6✔
233
            callback();
6✔
234
        } else {
235
            config
×
236
                .getLogger()
237
                .info(
238
                    context,
239
                    'Cmd: %j was sent to the device %s with http options %j',
240
                    serializedPayload,
241
                    cmdName,
242
                    options
243
                );
244
            callback();
×
245
        }
246
    });
247
}
248

249
function addTimestamp(req, res, next) {
250
    const arr = req.jsonPayload;
43✔
251
    let timeStampData;
252
    for (const i in arr) {
43✔
253
        if (req.query.t && arr[i]) {
244✔
254
            timeStampData = arr[i];
4✔
255
            timeStampData[constants.TIMESTAMP_ATTRIBUTE] = req.query.t;
4✔
256
        }
257
    }
258
    next();
43✔
259
}
260

261
function handleIncomingMeasure(req, res, next) {
262
    let values;
263
    context = fillService(context, { service: 'n/a', subservice: 'n/a' });
43✔
264
    config
43✔
265
        .getLogger()
266
        .debug(context, 'Processing multiple HTTP measures for device %s with apiKey %s', req.deviceId, req.apiKey);
267

268
    function updateCommandHandler(error) {
269
        if (error) {
48!
270
            next(error);
×
271
            config.getLogger().error(
×
272
                context,
273
                /*jshint quotmark: double */
274
                "MEASURES-002: Couldn't send the updated values to the Context Broker due to an error: %j",
275
                /*jshint quotmark: single */
276
                error
277
            );
278
        } else {
279
            config
48✔
280
                .getLogger()
281
                .info(
282
                    context,
283
                    'Multiple measures for device %s with apiKey %s successfully updated',
284
                    req.deviceId,
285
                    req.apiKey
286
                );
287

288
            finishSouthBoundTransaction(next);
48✔
289
        }
290
    }
291

292
    function processHTTPWithDevice(device) {
293
        let payloadDataArr;
294
        let attributeArr;
295
        let attributeValues;
296
        attributeArr = [];
43✔
297
        payloadDataArr = [];
43✔
298

299
        if (req.attr && req.jsonPayload) {
43✔
300
            config.getLogger().debug(context, 'Parsing attr %s with value %s', req.attr, req.jsonPayload);
6✔
301
            try {
6✔
302
                req.jsonPayload = req.jsonPayload.toString('hex');
6✔
303
            } catch (e) {
304
                // no error should be reported
305
            }
306
            const theAttr = [{ name: req.attr, value: req.jsonPayload, type: 'None' }];
6✔
307
            attributeArr.push(theAttr);
6✔
308
        } else {
309
            if (!Array.isArray(req.jsonPayload)) {
37✔
310
                payloadDataArr.push(req.jsonPayload);
2✔
311
            } else {
312
                payloadDataArr = req.jsonPayload;
35✔
313
            }
314
            if (req.jsonPayload) {
37✔
315
                for (const i in payloadDataArr) {
36✔
316
                    values = commonBindings.extractAttributes(device, payloadDataArr[i]);
42✔
317
                    attributeArr.push(values);
42✔
318
                }
319
            } else {
320
                attributeArr = [];
1✔
321
            }
322
        }
323

324
        if (attributeArr.length === 0) {
43✔
325
            finishSouthBoundTransaction(next);
1✔
326
        } else {
327
            for (const j in attributeArr) {
42✔
328
                attributeValues = attributeArr[j];
48✔
329
                config
48✔
330
                    .getLogger()
331
                    .debug(
332
                        context,
333
                        'Processing measure device %s with attributeArr %j attributeValues %j',
334
                        device.name,
335
                        attributeArr,
336
                        attributeValues
337
                    );
338
                if (req.isCommand) {
48✔
339
                    const executions = [];
1✔
340
                    for (const k in attributeValues) {
1✔
341
                        executions.push(
1✔
342
                            iotAgentLib.setCommandResult.bind(
343
                                null,
344
                                device.name,
345
                                config.getConfig().iota.defaultResource,
346
                                req.apiKey,
347
                                attributeValues[k].name,
348
                                attributeValues[k].value,
349
                                constants.COMMAND_STATUS_COMPLETED,
350
                                device
351
                            )
352
                        );
353
                    }
354
                    async.parallel(executions, updateCommandHandler);
1✔
355
                } else if (attributeValues.length > 0) {
47!
356
                    iotAgentLib.update(device.name, device.type, '', attributeValues, device, updateCommandHandler);
47✔
357
                } else {
358
                    finishSouthBoundTransaction(next);
×
359
                }
360
            }
361
        }
362
    }
363

364
    function processDeviceMeasure(error, device) {
365
        if (error) {
43!
366
            next(error);
×
367
        } else {
368
            const localContext = _.clone(context);
43✔
369
            req.device = device;
43✔
370
            localContext.service = device.service;
43✔
371
            localContext.subservice = device.subservice;
43✔
372
            intoTrans(localContext, processHTTPWithDevice)(device);
43✔
373
        }
374
    }
375

376
    iotaUtils.retrieveDevice(req.deviceId, req.apiKey, transport, processDeviceMeasure);
43✔
377
}
378

379
function isCommand(req, res, next) {
380
    if (
1!
381
        req.path ===
382
        (config.getConfig().iota.defaultResource || constants.HTTP_MEASURE_PATH) + constants.HTTP_COMMANDS_PATH
1!
383
    ) {
384
        req.isCommand = true;
1✔
385
    }
386

387
    next();
1✔
388
}
389

390
function sendConfigurationToDevice(apiKey, deviceId, results, callback) {
391
    function handleDeviceResponse(innerCallback) {
392
        return function (error, response, body) {
4✔
393
            if (error) {
4!
394
                innerCallback(error);
×
395
            } else if (response && response.statusCode !== 200) {
4!
396
                innerCallback(new errors.DeviceEndpointError(response.statusCode, body));
×
397
            } else {
398
                innerCallback();
4✔
399
            }
400
        };
401
    }
402

403
    function sendRequest(device, results, innerCallback) {
404
        const resultRequest = {
4✔
405
            url: device.endpoint + constants.HTTP_CONFIGURATION_PATH,
406
            method: 'POST',
407
            json: iotaUtils.createConfigurationNotification(results),
408
            headers: {
409
                'fiware-service': device.service,
410
                'fiware-servicepath': device.subservice,
411
                'content-type': 'application/json'
412
            }
413
        };
414

415
        request(resultRequest, handleDeviceResponse(innerCallback));
4✔
416
    }
417
    iotaUtils.retrieveDevice(deviceId, apiKey, transport, function (error, device) {
4✔
418
        if (error) {
4!
419
            callback(error);
×
420
        } else if (!device.endpoint) {
4!
421
            callback(new errors.EndpointNotFound(device.id));
×
422
        } else {
423
            sendRequest(device, results, callback);
4✔
424
        }
425
    });
426
}
427

428
function handleConfigurationRequest(req, res, next) {
429
    function replyToDevice(error) {
430
        if (error) {
5!
431
            res.status(error.code).json(error);
×
432
        } else {
433
            res.status(200).json({});
5✔
434
        }
435
    }
436
    iotaUtils.retrieveDevice(req.deviceId, req.apiKey, transport, function (error, device) {
5✔
437
        if (error) {
5!
438
            next(error);
×
439
        } else {
440
            iotaUtils.manageConfiguration(
5✔
441
                req.apiKey,
442
                req.deviceId,
443
                device,
444
                req.jsonPayload,
445
                sendConfigurationToDevice,
446
                replyToDevice
447
            );
448
        }
449
    });
450
}
451

452
function handleError(error, req, res, next) {
453
    let code = 500;
×
454

455
    config.getLogger().debug(context, 'Error %s handling request: %s', error.name, error.message);
×
456

457
    if (error.code && String(error.code).match(/^[2345]\d\d$/)) {
×
458
        code = error.code;
×
459
    }
460

461
    res.status(code).json({
×
462
        name: error.name,
463
        message: error.message
464
    });
465
}
466

467
/**
468
 * Just fills in the transport protocol in case there is none and polling if endpoint.
469
 *
470
 * @param {Object} device           Device object containing all the information about the device.
471
 */
472
function setPollingAndDefaultTransport(device, callback) {
473
    if (!device.transport) {
115✔
474
        device.transport = 'HTTP';
45✔
475
    }
476

477
    if (device.transport === 'HTTP') {
115✔
478
        if (device.endpoint) {
65✔
479
            device.polling = false;
37✔
480
        } else {
481
            device.polling = true;
28✔
482
        }
483
    }
484

485
    callback(null, device);
115✔
486
}
487

488
/**
489
 * Device provisioning handler.
490
 *
491
 * @param {Object} device           Device object containing all the information about the provisioned device.
492
 */
493
function deviceProvisioningHandler(device, callback) {
494
    config.getLogger().debug(context, 'httpbinding.deviceProvisioningHandler %j', device);
113✔
495
    setPollingAndDefaultTransport(device, callback);
113✔
496
}
497

498
/**
499
 * Device updating handler. This handler just fills in the transport protocol in case there is none.
500
 *
501
 * @param {Object} device           Device object containing all the information about the updated device.
502
 */
503
function deviceUpdatingHandler(device, callback) {
504
    config.getLogger().debug(context, 'httpbinding.deviceUpdatingHandler %j', device);
2✔
505
    setPollingAndDefaultTransport(device, callback);
2✔
506
}
507

508
/**
509
 * This middleware checks whether there is any polling command pending to be sent to the device. If there is some,
510
 * add the command information to the return payload. Otherwise it returns an empty payload.
511
 */
512
function returnCommands(req, res, next) {
513
    function updateCommandStatus(device, commandList) {
514
        context = fillService(context, device);
6✔
515
        function createCommandUpdate(command) {
516
            return apply(
6✔
517
                iotAgentLib.setCommandResult,
518
                device.name,
519
                device.resource,
520
                req.query.k,
521
                command.name,
522
                ' ',
523
                'DELIVERED',
524
                device
525
            );
526
        }
527

528
        function cleanCommand(command) {
529
            return apply(iotAgentLib.removeCommand, device.service, device.subservice, device.id, command.name);
6✔
530
        }
531

532
        const updates = commandList.map(createCommandUpdate);
6✔
533
        const cleanCommands = commandList.map(cleanCommand);
6✔
534
        if (updates) {
6!
535
            async.parallel(updates.concat(cleanCommands), function (error, results) {
6✔
536
                if (error) {
6!
537
                    config
×
538
                        .getLogger()
539
                        .error(
540
                            context,
541
                            'Error updating command status after delivering commands for device %s',
542
                            device.id
543
                        );
544
                } else {
545
                    config
6✔
546
                        .getLogger()
547
                        .debug(
548
                            context,
549
                            'Command status updated successfully after delivering command list to device %s',
550
                            device.id
551
                        );
552
                }
553
            });
554
        }
555
    }
556

557
    function parseCommand(item) {
558
        const result = {};
6✔
559
        const cleanedValue = String(item.value).trim();
6✔
560

561
        if (cleanedValue !== '') {
6!
562
            result[item.name] = item.value;
6✔
563
        }
564
        return result;
6✔
565
    }
566

567
    function concatCommand(previous, current) {
568
        if (previous === {}) {
6!
569
            return current;
×
570
        }
571
        return _.extend(previous, current);
6✔
572
    }
573
    if (req.query && req.query.getCmd === '1') {
43✔
574
        iotAgentLib.commandQueue(req.device.service, req.device.subservice, req.deviceId, function (error, list) {
6✔
575
            if (error || !list || list.count === 0) {
6!
576
                if (req.accepts('json')) {
×
577
                    res.status(200).send({});
×
578
                } else {
579
                    res.status(200).send('');
×
580
                }
581
            } else {
582
                if (req.accepts('json')) {
6!
583
                    res.status(200).send(list.commands.map(parseCommand).reduce(concatCommand, {}));
6✔
584
                } else {
585
                    res.status(200).send(JSON.stringify(list.commands.map(parseCommand).reduce(concatCommand, {})));
×
586
                }
587
                process.nextTick(updateCommandStatus.bind(null, req.device, list.commands));
6✔
588
            }
589
        });
590
    } else if (req.accepts('json')) {
37!
591
        res.status(200).send({});
37✔
592
    } else {
593
        res.status(200).send('');
×
594
    }
595
}
596

597
function start(callback) {
598
    const baseRoot = '/';
119✔
599

600
    httpBindingServer = {
119✔
601
        server: null,
602
        app: express(),
603
        router: express.Router()
604
    };
605

606
    if (!config.getConfig().http) {
119!
607
        config
×
608
            .getLogger()
609
            .fatal(context, 'GLOBAL-002: Configuration error. Configuration object [config.http] is missing');
610
        callback(new errors.ConfigurationError('config.http'));
×
611
        return;
×
612
    }
613

614
    httpBindingServer.app.set('port', config.getConfig().http.port);
119✔
615
    httpBindingServer.app.set('host', config.getConfig().http.host || '0.0.0.0');
119!
616

617
    httpBindingServer.router.get(
119✔
618
        config.getConfig().iota.defaultResource || constants.HTTP_MEASURE_PATH,
119!
619
        checkMandatoryParams(true),
620
        parseData,
621
        addTimestamp,
622
        handleIncomingMeasure,
623
        returnCommands
624
    );
625

626
    httpBindingServer.router.post(
119✔
627
        config.getConfig().iota.defaultResource || constants.HTTP_MEASURE_PATH,
119!
628
        bodyParser.json({ strict: false }), // accept anything JSON.parse accepts
629
        checkMandatoryParams(false),
630
        parseDataMultipleMeasure,
631
        addTimestamp,
632
        handleIncomingMeasure,
633
        returnCommands
634
    );
635

636
    httpBindingServer.router.post(
119✔
637
        (config.getConfig().iota.defaultResource || constants.HTTP_MEASURE_PATH) +
119!
638
            '/' +
639
            constants.MEASURES_SUFIX +
640
            '/:attrValue',
641
        parserBody(),
642
        checkMandatoryParams(false),
643
        parseData, // non multiple measures are expected in this route
644
        addTimestamp,
645
        handleIncomingMeasure,
646
        returnCommands
647
    );
648

649
    httpBindingServer.router.post(
119✔
650
        (config.getConfig().iota.defaultResource || constants.HTTP_MEASURE_PATH) + constants.HTTP_COMMANDS_PATH,
119!
651
        bodyParser.json({ strict: false }), // accept anything JSON.parse accepts.
652
        checkMandatoryParams(false),
653
        parseData,
654
        addTimestamp,
655
        isCommand,
656
        handleIncomingMeasure,
657
        returnCommands
658
    );
659

660
    httpBindingServer.router.post(
119✔
661
        (config.getConfig().iota.defaultResource || constants.HTTP_MEASURE_PATH) + constants.HTTP_CONFIGURATION_PATH,
119!
662
        bodyParser.json({ strict: false }), // accept anything JSON.parse accepts.
663
        checkMandatoryParams(false),
664
        parseData,
665
        handleConfigurationRequest
666
    );
667

668
    httpBindingServer.app.use(baseRoot, httpBindingServer.router);
119✔
669
    httpBindingServer.app.use(handleError);
119✔
670

671
    if (config.getConfig().http && config.getConfig().http.key && config.getConfig().http.cert) {
119!
672
        const privateKey = fs.readFileSync(config.getConfig().http.key, 'utf8');
×
673
        const certificate = fs.readFileSync(config.getConfig().http.cert, 'utf8');
×
674
        const credentials = { key: privateKey, cert: certificate };
×
675

676
        config.getLogger().info(context, 'HTTPS Binding listening on port %s', config.getConfig().http.port);
×
677
        httpBindingServer.server = https.createServer(credentials, httpBindingServer.app);
×
678
    } else {
679
        config.getLogger().info(context, 'HTTP Binding listening on port %s', config.getConfig().http.port);
119✔
680
        httpBindingServer.server = http.createServer(httpBindingServer.app);
119✔
681
    }
682

683
    httpBindingServer.server.listen(httpBindingServer.app.get('port'), httpBindingServer.app.get('host'), callback);
119✔
684
}
685

686
function stop(callback) {
687
    config.getLogger().info(context, 'Stopping JSON HTTP Binding: ');
119✔
688

689
    if (httpBindingServer) {
119!
690
        httpBindingServer.server.close(function () {
119✔
691
            config.getLogger().info(context, 'HTTP Binding Stopped');
119✔
692
            callback();
119✔
693
        });
694
    } else {
695
        callback();
×
696
    }
697
}
698

699
function sendPushNotifications(device, values, callback) {
700
    const executions = _.flatten(values.map(commandHandler.generateCommandExecution.bind(null, null, device)));
×
701

702
    async.series(executions, function (error) {
×
703
        callback(error);
×
704
    });
705
}
706

707
function storePollNotifications(device, values, callback) {
708
    function addPollNotification(item, innerCallback) {
709
        iotAgentLib.addCommand(device.service, device.subservice, device.id, item, innerCallback);
×
710
    }
711

712
    async.map(values, addPollNotification, callback);
×
713
}
714

715
function notificationHandler(device, values, callback) {
716
    if (device.endpoint) {
×
717
        sendPushNotifications(device, values, callback);
×
718
    } else {
719
        storePollNotifications(device, values, callback);
×
720
    }
721
}
722

723
exports.start = start;
1✔
724
exports.stop = stop;
1✔
725
exports.sendConfigurationToDevice = sendConfigurationToDevice;
1✔
726
exports.deviceProvisioningHandler = deviceProvisioningHandler;
1✔
727
exports.deviceUpdatingHandler = deviceUpdatingHandler;
1✔
728
exports.notificationHandler = notificationHandler;
1✔
729
exports.executeCommand = executeCommand;
1✔
730
exports.protocol = 'HTTP';
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc