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

telefonicaid / iotagent-node-lib / 22948149498

11 Mar 2026 10:29AM UTC coverage: 79.43% (+0.03%) from 79.404%
22948149498

Pull #1764

github

web-flow
Merge 29812ecc7 into 803e0ad74
Pull Request #1764: Task/add health check to /iot/about /metrics and /ready

2163 of 2908 branches covered (74.38%)

Branch coverage included in aggregate %.

204 of 265 new or added lines in 5 files covered. (76.98%)

1 existing line in 1 file now uncovered.

4166 of 5060 relevant lines covered (82.33%)

279.9 hits per line

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

78.69
/lib/services/commands/commandRegistryMongoDB.js
1
/*
2
 * Copyright 2016 Telefonica Investigación y Desarrollo, S.A.U
3
 *
4
 * This file is part of fiware-iotagent-lib
5
 *
6
 * fiware-iotagent-lib 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
 * fiware-iotagent-lib 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 fiware-iotagent-lib.
18
 * If not, see http://www.gnu.org/licenses/.
19
 *
20
 * For those usages not covered by the GNU Affero General Public License
21
 * please contact with::daniel.moranjimenez@telefonica.com
22
 */
23

24
const logger = require('logops');
1✔
25
const mongoose = require('mongoose');
1✔
26
const intoTrans = require('../common/domain').intoTrans;
1✔
27
const errors = require('../../errors');
1✔
28
const Command = require('../../model/Command');
1✔
29
const async = require('async');
1✔
30
const context = {
1✔
31
    op: 'IoTAgentNGSI.MongoDBCommandRegister'
32
};
33

34
function findCommand(service, subservice, deviceId, name, callback) {
35
    const queryObj = {
54✔
36
        service,
37
        subservice,
38
        deviceId,
39
        name
40
    };
41

42
    logger.debug(context, 'Looking for command [%s] for device [%s] with [%j]', name, deviceId, queryObj);
54✔
43

44
    const query = Command.model.findOne(queryObj);
54✔
45

46
    query.select({ __v: 0 });
54✔
47

48
    query
54✔
49
        .exec({})
50
        .then((data) => {
51
            if (data) {
54✔
52
                callback(null, data);
5✔
53
            } else {
54
                logger.debug(
49✔
55
                    context,
56
                    'Command for DeviceID [%j] with name [%j] not found with [%j]',
57
                    deviceId,
58
                    name,
59
                    queryObj
60
                );
61
                callback(new errors.CommandNotFound(name, queryObj));
49✔
62
            }
63
        })
64
        .catch((error) => {
65
            logger.debug(context, 'Internal MongoDB Error getting command: %s', error);
×
66
            callback(new errors.InternalDbError(error));
×
67
        });
68
}
69

70
function updateCommand(service, subservice, deviceId, command, callback) {
71
    findCommand(service, subservice, deviceId, command.name, function (error, commandDAO) {
2✔
72
        if (error) {
2!
73
            callback(error);
×
74
        } else {
75
            commandDAO.value = command.value;
2✔
76

77
            commandDAO
2✔
78
                .save({})
79
                .then((commandDAOs) => {
80
                    callback(null, commandDAOs.toObject());
2✔
81
                })
82
                .catch((error) => {
83
                    callback(error);
×
84
                });
85
        }
86
    });
87
}
88

89
function createCommand(service, subservice, deviceId, command, callback) {
90
    /* eslint-disable-next-line new-cap */
91
    const commandObj = new Command.model();
49✔
92
    const attributeList = [
49✔
93
        'name',
94
        'type',
95
        'value',
96
        // new Command fields
97
        'execTs',
98
        'status',
99
        'info',
100
        'onDelivered',
101
        'onOk',
102
        'onError',
103
        'onInfo',
104
        'cmdExecution',
105
        'dateExpiration'
106
    ];
107

108
    for (let i = 0; i < attributeList.length; i++) {
49✔
109
        commandObj[attributeList[i]] = command[attributeList[i]];
588✔
110
    }
111

112
    commandObj.deviceId = deviceId;
49✔
113
    commandObj.service = service;
49✔
114
    commandObj.subservice = subservice;
49✔
115

116
    logger.debug(context, 'Storing command for deviceId [%s] with name [%s]', deviceId, command.name);
49✔
117

118
    commandObj
49✔
119
        .save({})
120
        .then((commandDAO) => {
121
            callback(null, commandDAO.toObject());
49✔
122
        })
123
        .catch((error) => {
124
            logger.debug(context, 'Error storing command information: %s', error);
×
125
            callback(new errors.InternalDbError(error));
×
126
        });
127
}
128

129
function addCommand(service, subservice, deviceId, command, callback) {
130
    findCommand(service, subservice, deviceId, command.name, function (error) {
51✔
131
        if (error && error.name === 'COMMAND_NOT_FOUND') {
51✔
132
            createCommand(service, subservice, deviceId, command, callback);
49✔
133
        } else if (!error) {
2!
134
            updateCommand(service, subservice, deviceId, command, callback);
2✔
135
        } else {
136
            callback(error);
×
137
        }
138
    });
139
}
140

141
function listCommands(service, subservice, deviceId, callback) {
142
    const condition = {};
11✔
143

144
    function toObjectFn(obj) {
145
        return obj.toObject();
18✔
146
    }
147

148
    condition.service = service;
11✔
149
    condition.subservice = subservice;
11✔
150
    condition.deviceId = deviceId;
11✔
151

152
    const query = Command.model.find(condition).sort();
11✔
153
    const queryCount = Command.model.countDocuments(condition);
11✔
154
    function funcQuery(cb) {
155
        query
11✔
156
            .exec({})
157
            .then((res) => {
158
                cb(null, res);
11✔
159
            })
160
            .catch((error) => {
161
                cb(error);
×
162
            });
163
    }
164
    function funcQueryCount(cb) {
165
        queryCount
11✔
166
            .exec({})
167
            .then((res) => {
168
                cb(null, res);
11✔
169
            })
170
            .catch((error) => {
171
                cb(error);
×
172
            });
173
    }
174
    async.series([funcQuery, funcQueryCount], function (error, results) {
11✔
175
        callback(error, {
11✔
176
            count: results[1],
177
            commands: results[0].map(toObjectFn)
178
        });
179
    });
180
}
181

182
function remove(service, subservice, deviceId, name, callback) {
183
    logger.debug(
1✔
184
        context,
185
        'Removing command for service [%s] subservice [%s] and DeviceID [%s] with name [%s]',
186
        service,
187
        subservice,
188
        deviceId,
189
        name
190
    );
191

192
    findCommand(service, subservice, deviceId, name, function (error, command) {
1✔
193
        if (error) {
1!
194
            callback(error);
×
195
        } else {
196
            const query = Command.model.deleteOne({ _id: command._id });
1✔
197
            query
1✔
198
                .exec({})
199
                .then((commandResult) => {
200
                    if (commandResult && commandResult.result && commandResult.result.n === 1) {
1!
201
                        logger.debug(context, 'Command [%s] successfully removed.', name);
×
202

203
                        callback(null, commandResult);
×
204
                    } else {
205
                        const deviceInfo = {
1✔
206
                            service,
207
                            subservice,
208
                            deviceId,
209
                            name
210
                        };
211
                        logger.debug(context, 'Command [%s] not found for removal with %j', name, deviceInfo);
1✔
212
                        callback(new errors.CommandNotFound(name, deviceInfo));
1✔
213
                    }
214
                })
215
                .catch((error) => {
216
                    logger.debug(context, 'Internal MongoDB Error getting command: %s', error);
×
217
                    callback(new errors.InternalDbError(error));
×
218
                });
219
        }
220
    });
221
}
222

223
function listToObject(commandList) {
224
    const result = [];
3✔
225

226
    for (let i = 0; i < commandList.length; i++) {
3✔
227
        result.push(commandList[i].toObject());
3✔
228
    }
229

230
    return result;
3✔
231
}
232

233
function removeFromDate(creationDate, callback) {
234
    const condition = { creationDate: { $lt: creationDate } };
106✔
235

236
    if (Command.model) {
106!
237
        const query = Command.model.find(condition);
106✔
238
        query
106✔
239
            .exec({})
240
            .then((commandList) => {
241
                if (commandList && commandList.length > 0) {
106✔
242
                    const queryDel = Command.model.deleteOne(condition);
3✔
243
                    queryDel
3✔
244
                        .exec({})
245
                        .then(() => {
246
                            logger.debug(
3✔
247
                                context,
248
                                'Expired commands successfully removed from MongoDB for date [%s]',
249
                                creationDate
250
                            );
251
                            callback(null, listToObject(commandList));
3✔
252
                        })
253
                        .catch((error) => {
254
                            logger.debug(context, 'Internal MongoDB Error removing expired commands: %s', error);
×
255
                            callback(new errors.InternalDbError(error));
×
256
                        });
257
                }
258
            })
259
            .catch((error) => {
260
                logger.debug(context, 'Internal MongoDB Error looking for expired commands: %s', error);
×
261
            });
262
    } else {
UNCOV
263
        callback(null, []);
×
264
    }
265
}
266

267
function clear(callback) {
268
    mongoose.connection
27✔
269
        .dropDatabase()
270
        .then(() => {
271
            callback(null);
27✔
272
        })
273
        .catch((error) => {
274
            callback(error);
×
275
        });
276
}
277

278
function init(newConfig, callback) {
279
    callback(null);
×
280
}
281

282
exports.init = intoTrans(context, init);
1✔
283
exports.add = intoTrans(context, addCommand);
1✔
284
exports.list = intoTrans(context, listCommands);
1✔
285
exports.remove = intoTrans(context, remove);
1✔
286
exports.clear = intoTrans(context, clear);
1✔
287
exports.removeFromDate = intoTrans(context, removeFromDate);
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