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

telefonicaid / iotagent-json / 15191019223

22 May 2025 03:44PM UTC coverage: 79.555% (-0.5%) from 80.079%
15191019223

Pull #800

github

web-flow
Merge 605ff0463 into 5034c81f3
Pull Request #800: allow receive command notifications from CB

526 of 750 branches covered (70.13%)

Branch coverage included in aggregate %.

28 of 30 new or added lines in 2 files covered. (93.33%)

13 existing lines in 3 files now uncovered.

1120 of 1319 relevant lines covered (84.91%)

135.83 hits per line

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

65.71
/lib/iotagent-json.js
1
/*
2
 * Copyright 2015 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
const iotAgentLib = require('iotagent-node-lib');
1✔
25
const transportSelector = require('./transportSelector');
1✔
26
const commandHandler = require('./commandHandler');
1✔
27
const iotaUtils = require('./iotaUtils');
1✔
28
const async = require('async');
1✔
29
const errors = require('./errors');
1✔
30
const apply = async.apply;
1✔
31
const context = {
1✔
32
    op: 'IoTAgentJSON.Agent'
33
};
34
const config = require('./configService');
1✔
35

36
/**
37
 * Handler for incoming notifications for the configuration subscription mechanism.
38
 *
39
 * @param {Object} device           Object containing all the device information.
40
 * @param {Array} updates           List of all the updated attributes.
41

42
 */
43
function configurationNotificationHandler(device, updates, callback) {
NEW
44
    config.getLogger().debug(context, 'configurationNotificationHandler command %j and device %j', updates, device);
×
45
    function invokeConfiguration(apiKey, callback) {
UNCOV
46
        let group = {};
×
UNCOV
47
        iotAgentLib.getConfigurationSilently(config.getConfig().iota.defaultResource || '', apiKey, function (
×
48
            error,
49
            foundGroup
50
        ) {
UNCOV
51
            if (!error) {
×
52
                group = foundGroup;
×
53
            }
54

UNCOV
55
            transportSelector.applyFunctionFromBinding(
×
56
                [apiKey, group, device.id, updates],
57
                'sendConfigurationToDevice',
58
                device.transport ||
×
59
                    (group && group.transport ? group.transport : undefined) ||
×
60
                    config.getConfig().defaultTransport,
61
                callback
62
            );
63
        });
64
    }
65

UNCOV
66
    async.waterfall(
×
67
        [apply(iotaUtils.getEffectiveApiKey, device.service, device.subservice, device), invokeConfiguration],
68
        callback
69
    );
70
}
71

72
function configurationHandler(configuration, callback) {
73
    if (
123✔
74
        configuration.resource &&
248✔
75
        config.getConfig().iota.iotManager &&
76
        config.getConfig().iota.defaultResource &&
77
        configuration.resource !== config.getConfig().iota.defaultResource
78
    ) {
79
        callback(new errors.InvalidResource());
1✔
80
    } else {
81
        callback();
122✔
82
    }
83
}
84

85
/**
86
 * Calls all the command execution handlers for each transport protocol binding whenever a new notification request
87
 * arrives from the Context Broker.
88
 *
89
 * @param {Object} device               Device data object containing all stored information about the device.
90
 * @param {Array} values                Values recieved in the notification.
91
 */
92
function notificationHandler(device, values, callback) {
93
    config.getLogger().debug(context, 'notificationHandler command %j and device %j', values, device);
1✔
94
    function invokeWithConfiguration(apiKey, callback) {
95
        let group = {};
1✔
96
        iotAgentLib.getConfigurationSilently(config.getConfig().iota.defaultResource || '', apiKey, function (
1!
97
            error,
98
            foundGroup
99
        ) {
100
            if (!error) {
1!
101
                group = foundGroup;
1✔
102
            }
103
            transportSelector.applyFunctionFromBinding(
1✔
104
                [device, values],
105
                'notificationHandler',
106
                device.transport ||
2!
107
                    (group && group.transport ? group.transport : undefined) ||
3!
108
                    config.getConfig().defaultTransport,
109
                callback
110
            );
111
        });
112
    }
113

114
    async.waterfall(
1✔
115
        [apply(iotaUtils.getEffectiveApiKey, device.service, device.subservice, device), invokeWithConfiguration],
116
        callback
117
    );
118
}
119

120
/**
121
 * Handles incoming updateContext requests related with lazy attributes. This handler is still just registered,
122
 * but empty.
123
 *
124
 * @param {String} id               ID of the entity for which the update was issued.
125
 * @param {String} type             Type of the entity for which the update was issued.
126
 * @param {Array} attributes        List of NGSI attributes to update.
127
 */
128
function updateHandler(id, type, attributes, service, subservice, callback) {
129
    config.getLogger().debug(context, 'updateHandler');
36✔
130
    callback();
36✔
131
}
132

133
/**
134
 * Calls all the device provisioning handlers for each transport protocol binding whenever a new device is provisioned
135
 * in the Agent.
136
 *
137
 * @param {Object} device           Device provisioning information.
138
 */
139
function deviceProvisioningHandler(device, callback) {
140
    config.getLogger().debug(context, 'deviceProvisioningHandler for device %j', device);
159✔
141
    transportSelector.applyFunctionFromBinding([device], 'deviceProvisioningHandler', null, function (error, devices) {
159✔
142
        if (error) {
159!
143
            callback(error);
×
144
        } else {
145
            callback(null, devices[0]);
159✔
146
        }
147
    });
148
}
149

150
/**
151
 * Calls all the device updating handlers for each transport protocol binding whenever a device is updated
152
 * in the Agent.
153
 *
154
 * @param {Object} device           Device updating information.
155
 */
156
function deviceUpdatingHandler(newDevice, oldDevice, callback) {
157
    config.getLogger().debug(context, 'deviceUpdatingHandler for newDevice %j oldDevice %j', newDevice, oldDevice);
4✔
158
    transportSelector.applyFunctionFromBinding([newDevice, oldDevice], 'deviceUpdatingHandler', null, function (
4✔
159
        error,
160
        devices
161
    ) {
162
        if (error) {
4!
163
            callback(error);
×
164
        } else {
165
            callback(null, devices[0]);
4✔
166
        }
167
    });
168
}
169

170
/**
171
 * Starts the IOTA with the given configuration.
172
 *
173
 * @param {Object} newConfig        New configuration object.
174
 */
175
function start(newConfig, callback) {
176
    config.setLogger(iotAgentLib.logModule);
262✔
177
    config.setConfig(newConfig);
262✔
178

179
    iotAgentLib.activate(config.getConfig().iota, function (error) {
262✔
180
        if (error) {
262!
181
            callback(error);
×
182
        } else {
183
            config.getLogger().info(context, 'IoT Agent services activated');
262✔
184
            //append config JEXL transformation to built in transformations
185
            iotAgentLib.dataPlugins.expressionTransformation.setJEXLTransforms(newConfig.jexlTransformations);
262✔
186

187
            iotAgentLib.setConfigurationHandler(configurationHandler);
262✔
188
            iotAgentLib.setCommandHandler(commandHandler.handler);
262✔
189
            iotAgentLib.setProvisioningHandler(deviceProvisioningHandler);
262✔
190
            iotAgentLib.setUpdatingHandler(deviceUpdatingHandler);
262✔
191
            iotAgentLib.setDataUpdateHandler(updateHandler);
262✔
192

193
            if (config.getConfig().configRetrieval === true) {
262✔
194
                iotAgentLib.setNotificationHandler(configurationNotificationHandler);
6✔
195
            } else {
196
                iotAgentLib.setNotificationHandler(notificationHandler);
256✔
197
            }
198

199
            transportSelector.startTransportBindings(newConfig, callback);
262✔
200
        }
201
    });
202
}
203

204
/**
205
 * Stops the current IoT Agent.
206
 *
207
 */
208
function stop(callback) {
209
    config.getLogger().info(context, 'Stopping IoT Agent');
262✔
210
    async.series(
262✔
211
        [transportSelector.stopTransportBindings, iotAgentLib.resetMiddlewares, iotAgentLib.deactivate],
212
        callback
213
    );
214
}
215

216
/**
217
 * Shuts down the IoT Agent in a graceful manner
218
 *
219
 */
220
function handleShutdown(signal) {
221
    config.getLogger().info(context, 'Received %s, starting shutdown processs', signal);
×
222
    stop((err) => {
×
223
        if (err) {
×
224
            config.getLogger().error(context, err);
×
225
            return process.exit(1);
×
226
        }
227
        return process.exit(0);
×
228
    });
229
}
230

231
process.on('SIGINT', handleShutdown);
1✔
232
process.on('SIGTERM', handleShutdown);
1✔
233
process.on('SIGHUP', handleShutdown);
1✔
234

235
exports.start = start;
1✔
236
exports.stop = stop;
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