iotagent-node-lib 4.6.0 → 4.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/.github/workflows/ci.yml +0 -1
  2. package/Changelog +12 -0
  3. package/config.js +3 -1
  4. package/doc/admin.md +39 -5
  5. package/doc/api.md +67 -6
  6. package/doc/requirements.txt +1 -1
  7. package/lib/commonConfig.js +21 -2
  8. package/lib/model/Command.js +2 -2
  9. package/lib/model/Device.js +7 -3
  10. package/lib/model/Group.js +5 -3
  11. package/lib/model/dbConn.js +53 -112
  12. package/lib/services/commands/commandRegistryMongoDB.js +115 -75
  13. package/lib/services/common/iotManagerService.js +3 -1
  14. package/lib/services/devices/deviceRegistryMemory.js +36 -0
  15. package/lib/services/devices/deviceRegistryMongoDB.js +160 -87
  16. package/lib/services/devices/deviceService.js +33 -3
  17. package/lib/services/devices/devices-NGSI-v2.js +6 -1
  18. package/lib/services/groups/groupRegistryMongoDB.js +120 -83
  19. package/lib/services/ngsi/entities-NGSI-v2.js +14 -1
  20. package/lib/services/ngsi/ngsiService.js +32 -1
  21. package/lib/services/northBound/deviceProvisioningServer.js +12 -3
  22. package/lib/templates/updateDevice.json +12 -0
  23. package/lib/templates/updateDeviceLax.json +12 -0
  24. package/package.json +4 -4
  25. package/test/functional/config-test.js +3 -2
  26. package/test/functional/testUtils.js +2 -2
  27. package/test/unit/examples/groupProvisioningRequests/provisionFullGroup.json +1 -0
  28. package/test/unit/general/config-multi-core-test.js +1 -2
  29. package/test/unit/general/contextBrokerKeystoneSecurityAccess-test.js +5 -4
  30. package/test/unit/general/deviceService-test.js +6 -5
  31. package/test/unit/memoryRegistry/deviceRegistryMemory_test.js +6 -5
  32. package/test/unit/mongodb/mongodb-connectionoptions-test.js +7 -39
  33. package/test/unit/ngsi-ld/expressions/jexlBasedTransformations-test.js +1 -2
  34. package/test/unit/ngsi-ld/general/config-jsonld-contexts-test.js +1 -2
  35. package/test/unit/ngsi-mixed/provisioning/ngsi-versioning-test.js +8 -5
  36. package/test/unit/ngsiv2/expressions/jexlBasedTransformations-test.js +42 -41
  37. package/test/unit/ngsiv2/general/contextBrokerOAuthSecurityAccess-test.js +11 -10
  38. package/test/unit/ngsiv2/general/deviceService-test.js +6 -5
  39. package/test/unit/ngsiv2/general/https-support-test.js +1 -1
  40. package/test/unit/ngsiv2/lazyAndCommands/active-devices-attribute-update-test.js +4 -3
  41. package/test/unit/ngsiv2/lazyAndCommands/command-test.js +6 -5
  42. package/test/unit/ngsiv2/lazyAndCommands/lazy-devices-test.js +17 -16
  43. package/test/unit/ngsiv2/lazyAndCommands/polling-commands-test.js +10 -18
  44. package/test/unit/ngsiv2/ngsiService/active-devices-test.js +21 -20
  45. package/test/unit/ngsiv2/ngsiService/staticAttributes-test.js +8 -7
  46. package/test/unit/ngsiv2/plugins/alias-plugin_test.js +12 -11
  47. package/test/unit/ngsiv2/plugins/custom-plugin_test.js +3 -2
  48. package/test/unit/ngsiv2/plugins/multientity-plugin_test.js +28 -27
  49. package/test/unit/ngsiv2/provisioning/device-group-api-test.js +6 -4
  50. package/test/unit/ngsiv2/provisioning/device-provisioning-api_test.js +12 -11
  51. package/test/unit/ngsiv2/provisioning/device-provisioning-configGroup-api_test.js +11 -10
  52. package/test/unit/ngsiv2/provisioning/device-registration_test.js +5 -4
  53. package/test/unit/ngsiv2/provisioning/listProvisionedDevices-test.js +6 -5
  54. package/test/unit/ngsiv2/provisioning/provisionDeviceMultientity-test.js +1 -1
  55. package/test/unit/ngsiv2/provisioning/removeProvisionedDevice-test.js +5 -4
  56. package/test/unit/ngsiv2/provisioning/updateProvisionedDevices-test.js +8 -7
@@ -22,7 +22,7 @@
22
22
  */
23
23
 
24
24
  const logger = require('logops');
25
- const dbService = require('../../model/dbConn');
25
+ const mongoose = require('mongoose');
26
26
  const intoTrans = require('../common/domain').intoTrans;
27
27
  const errors = require('../../errors');
28
28
  const Command = require('../../model/Command');
@@ -45,24 +45,26 @@ function findCommand(service, subservice, deviceId, name, callback) {
45
45
 
46
46
  query.select({ __v: 0 });
47
47
 
48
- query.exec(function handleGet(error, data) {
49
- if (error) {
48
+ query
49
+ .exec({})
50
+ .then((data) => {
51
+ if (data) {
52
+ callback(null, data);
53
+ } else {
54
+ logger.debug(
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));
62
+ }
63
+ })
64
+ .catch((error) => {
50
65
  logger.debug(context, 'Internal MongoDB Error getting command: %s', error);
51
-
52
66
  callback(new errors.InternalDbError(error));
53
- } else if (data) {
54
- callback(null, data);
55
- } else {
56
- logger.debug(
57
- context,
58
- 'Command for DeviceID [%j] with name [%j] not found with [%j]',
59
- deviceId,
60
- name,
61
- queryObj
62
- );
63
- callback(new errors.CommandNotFound(name, queryObj));
64
- }
65
- });
67
+ });
66
68
  }
67
69
 
68
70
  function updateCommand(service, subservice, deviceId, command, callback) {
@@ -72,9 +74,14 @@ function updateCommand(service, subservice, deviceId, command, callback) {
72
74
  } else {
73
75
  commandDAO.value = command.value;
74
76
 
75
- commandDAO.save(function (error) {
76
- callback(error, commandDAO.toObject());
77
- });
77
+ commandDAO
78
+ .save({})
79
+ .then((commandDAOs) => {
80
+ callback(null, commandDAOs.toObject());
81
+ })
82
+ .catch((error) => {
83
+ callback(error);
84
+ });
78
85
  }
79
86
  });
80
87
  }
@@ -94,15 +101,15 @@ function createCommand(service, subservice, deviceId, command, callback) {
94
101
 
95
102
  logger.debug(context, 'Storing command for deviceId [%s] with name [%s]', deviceId, command.name);
96
103
 
97
- commandObj.save(function saveHandler(error, commandDAO) {
98
- if (error) {
104
+ commandObj
105
+ .save({})
106
+ .then((commandDAO) => {
107
+ callback(null, commandDAO.toObject());
108
+ })
109
+ .catch((error) => {
99
110
  logger.debug(context, 'Error storing command information: %s', error);
100
-
101
111
  callback(new errors.InternalDbError(error));
102
- } else {
103
- callback(null, commandDAO.toObject());
104
- }
105
- });
112
+ });
106
113
  }
107
114
 
108
115
  function addCommand(service, subservice, deviceId, command, callback) {
@@ -129,16 +136,33 @@ function listCommands(service, subservice, deviceId, callback) {
129
136
  condition.deviceId = deviceId;
130
137
 
131
138
  const query = Command.model.find(condition).sort();
132
-
133
- async.series(
134
- [query.exec.bind(query), Command.model.countDocuments.bind(Command.model, condition)],
135
- function (error, results) {
136
- callback(error, {
137
- count: results[1],
138
- commands: results[0].map(toObjectFn)
139
+ const queryCount = Command.model.countDocuments(condition);
140
+ function funcQuery(cb) {
141
+ query
142
+ .exec({})
143
+ .then((res) => {
144
+ cb(null, res);
145
+ })
146
+ .catch((error) => {
147
+ cb(error);
139
148
  });
140
- }
141
- );
149
+ }
150
+ function funcQueryCount(cb) {
151
+ queryCount
152
+ .exec({})
153
+ .then((res) => {
154
+ cb(null, res);
155
+ })
156
+ .catch((error) => {
157
+ cb(error);
158
+ });
159
+ }
160
+ async.series([funcQuery, funcQueryCount], function (error, results) {
161
+ callback(error, {
162
+ count: results[1],
163
+ commands: results[0].map(toObjectFn)
164
+ });
165
+ });
142
166
  }
143
167
 
144
168
  function remove(service, subservice, deviceId, name, callback) {
@@ -155,26 +179,29 @@ function remove(service, subservice, deviceId, name, callback) {
155
179
  if (error) {
156
180
  callback(error);
157
181
  } else {
158
- Command.model.deleteOne({ _id: command._id }, function (error, commandResult) {
159
- if (error) {
182
+ const query = Command.model.deleteOne({ _id: command._id });
183
+ query
184
+ .exec({})
185
+ .then((commandResult) => {
186
+ if (commandResult && commandResult.result && commandResult.result.n === 1) {
187
+ logger.debug(context, 'Command [%s] successfully removed.', name);
188
+
189
+ callback(null, commandResult);
190
+ } else {
191
+ const deviceInfo = {
192
+ service,
193
+ subservice,
194
+ deviceId,
195
+ name
196
+ };
197
+ logger.debug(context, 'Command [%s] not found for removal with %j', name, deviceInfo);
198
+ callback(new errors.CommandNotFound(name, deviceInfo));
199
+ }
200
+ })
201
+ .catch((error) => {
160
202
  logger.debug(context, 'Internal MongoDB Error getting command: %s', error);
161
-
162
203
  callback(new errors.InternalDbError(error));
163
- } else if (commandResult && commandResult.result && commandResult.result.n === 1) {
164
- logger.debug(context, 'Command [%s] successfully removed.', name);
165
-
166
- callback(null, commandResult);
167
- } else {
168
- const deviceInfo = {
169
- service,
170
- subservice,
171
- deviceId,
172
- name
173
- };
174
- logger.debug(context, 'Command [%s] not found for removal with %j', name, deviceInfo);
175
- callback(new errors.CommandNotFound(name, deviceInfo));
176
- }
177
- });
204
+ });
178
205
  }
179
206
  });
180
207
  }
@@ -190,35 +217,48 @@ function listToObject(commandList) {
190
217
  }
191
218
 
192
219
  function removeFromDate(creationDate, callback) {
193
- const query = { creationDate: { $lt: creationDate } };
220
+ const condition = { creationDate: { $lt: creationDate } };
194
221
 
195
222
  if (Command.model) {
196
- Command.model.find(query).exec(function (error, commandList) {
197
- if (!error && commandList && commandList.length > 0) {
198
- Command.model.deleteOne(query, function (error) {
199
- if (error) {
200
- logger.debug(context, 'Internal MongoDB Error removing expired commands: %s', error);
201
-
202
- callback(new errors.InternalDbError(error));
203
- } else {
204
- logger.debug(
205
- context,
206
- 'Expired commands successfully removed from MongoDB for date [%s]',
207
- creationDate
208
- );
209
-
210
- callback(null, listToObject(commandList));
211
- }
212
- });
213
- }
214
- });
223
+ const query = Command.model.find(condition);
224
+ query
225
+ .exec({})
226
+ .then((commandList) => {
227
+ if (commandList && commandList.length > 0) {
228
+ const queryDel = Command.model.deleteOne(condition);
229
+ queryDel
230
+ .exec({})
231
+ .then(() => {
232
+ logger.debug(
233
+ context,
234
+ 'Expired commands successfully removed from MongoDB for date [%s]',
235
+ creationDate
236
+ );
237
+ callback(null, listToObject(commandList));
238
+ })
239
+ .catch((error) => {
240
+ logger.debug(context, 'Internal MongoDB Error removing expired commands: %s', error);
241
+ callback(new errors.InternalDbError(error));
242
+ });
243
+ }
244
+ })
245
+ .catch((error) => {
246
+ logger.debug(context, 'Internal MongoDB Error looking for expired commands: %s', error);
247
+ });
215
248
  } else {
216
249
  callback(null, []);
217
250
  }
218
251
  }
219
252
 
220
253
  function clear(callback) {
221
- dbService.db.db.dropDatabase(callback);
254
+ mongoose.connection
255
+ .dropDatabase()
256
+ .then(() => {
257
+ callback(null);
258
+ })
259
+ .catch((error) => {
260
+ callback(error);
261
+ });
222
262
  }
223
263
 
224
264
  function init(newConfig, callback) {
@@ -63,7 +63,9 @@ function register(callback) {
63
63
  entityNameExp: service.entityNameExp,
64
64
  payloadType: service.payloadType,
65
65
  endpoint: service.endpoint,
66
- transport: service.transport
66
+ transport: service.transport,
67
+ useCBflowControl: service.useCBflowControl,
68
+ storeLastMeasure: service.storeLastMeasure
67
69
  };
68
70
  }
69
71
 
@@ -210,8 +210,44 @@ function getDevicesByAttribute(name, value, service, subservice, callback) {
210
210
  }
211
211
  }
212
212
 
213
+ function storeDeviceField(fieldName, fieldValue, typeInformation, callback) {
214
+ if (
215
+ typeInformation &&
216
+ typeInformation.id &&
217
+ typeInformation.apikey &&
218
+ typeInformation.service &&
219
+ typeInformation.subservice
220
+ ) {
221
+ getDevice(
222
+ typeInformation.id,
223
+ typeInformation.apikey,
224
+ typeInformation.service,
225
+ typeInformation.subservice,
226
+ function (error, data) {
227
+ if (!error) {
228
+ if (data) {
229
+ if (fieldName === 'lastMeasure') {
230
+ data.lastMeasure = { timestamp: new Date().toISOString(), measure: fieldValue };
231
+ } else {
232
+ data[fieldName] = fieldValue;
233
+ }
234
+ }
235
+ if (callback) {
236
+ callback(null, data);
237
+ }
238
+ } else {
239
+ callback(error, null);
240
+ }
241
+ }
242
+ );
243
+ } else {
244
+ callback(null, null);
245
+ }
246
+ }
247
+
213
248
  exports.getDevicesByAttribute = getDevicesByAttribute;
214
249
  exports.store = storeDevice;
250
+ exports.storeDeviceField = storeDeviceField;
215
251
  exports.update = update;
216
252
  exports.remove = removeDevice;
217
253
  exports.list = listDevices;
@@ -22,7 +22,7 @@
22
22
  */
23
23
 
24
24
  const logger = require('logops');
25
- const dbService = require('../../model/dbConn');
25
+ const mongoose = require('mongoose');
26
26
  const config = require('../../commonConfig');
27
27
  const fillService = require('./../common/domain').fillService;
28
28
  const alarmsInt = require('../common/alarmManagement').intercept;
@@ -57,27 +57,11 @@ const attributeList = [
57
57
  'explicitAttrs',
58
58
  'ngsiVersion',
59
59
  'subscriptions',
60
- 'payloadType'
60
+ 'payloadType',
61
+ 'useCBflowControl',
62
+ 'storeLastMeasure'
61
63
  ];
62
64
 
63
- /**
64
- * Generates a handler for the save device operations. The handler will take the customary error and the saved device
65
- * as the parameters (and pass the serialized DAO as the callback value).
66
- *
67
- * @return {Function} The generated handler.
68
- */
69
- function saveDeviceHandler(callback) {
70
- return function saveHandler(error, deviceDAO) {
71
- if (error) {
72
- logger.debug(fillService(context, deviceDAO), 'Error storing device information: %s', error);
73
-
74
- callback(new errors.InternalDbError(error));
75
- } else {
76
- callback(null, deviceDAO.toObject());
77
- }
78
- };
79
- }
80
-
81
65
  /**
82
66
  * Create a new register for a device. The device object should contain the id, type and registrationId
83
67
  *
@@ -97,8 +81,12 @@ function storeDevice(newDevice, callback) {
97
81
 
98
82
  logger.debug(context, 'Storing device with id [%s] and type [%s]', newDevice.id, newDevice.type);
99
83
 
100
- deviceObj.save(function saveHandler(error, deviceDAO) {
101
- if (error) {
84
+ deviceObj
85
+ .save({})
86
+ .then((deviceDAO) => {
87
+ callback(null, deviceDAO.toObject());
88
+ })
89
+ .catch((error) => {
102
90
  if (error.code === 11000) {
103
91
  logger.debug(context, 'Tried to insert a device with duplicate ID in the database: %s', error);
104
92
 
@@ -108,10 +96,7 @@ function storeDevice(newDevice, callback) {
108
96
 
109
97
  callback(new errors.InternalDbError(error));
110
98
  }
111
- } else {
112
- callback(null, deviceDAO.toObject());
113
- }
114
- });
99
+ });
115
100
  }
116
101
 
117
102
  /**
@@ -132,17 +117,17 @@ function removeDevice(id, apikey, service, subservice, callback) {
132
117
  }
133
118
  logger.debug(context, 'Removing device with id [%s]', id);
134
119
 
135
- Device.model.deleteOne(condition, function (error) {
136
- if (error) {
137
- logger.debug(context, 'Internal MongoDB Error getting device: %s', error);
138
-
139
- callback(new errors.InternalDbError(error));
140
- } else {
120
+ const query = Device.model.deleteOne(condition);
121
+ query
122
+ .exec({})
123
+ .then(() => {
141
124
  logger.debug(context, 'Device [%s] successfully removed.', id);
142
-
143
125
  callback(null);
144
- }
145
- });
126
+ })
127
+ .catch((error) => {
128
+ logger.debug(context, 'Internal MongoDB Error getting device: %s', error);
129
+ callback(new errors.InternalDbError(error));
130
+ });
146
131
  }
147
132
 
148
133
  /**
@@ -170,7 +155,7 @@ function listDevices(type, service, subservice, limit, offset, callback) {
170
155
  }
171
156
 
172
157
  const query = Device.model.find(condition).sort();
173
-
158
+ const queryCount = Device.model.countDocuments(condition);
174
159
  if (limit) {
175
160
  query.limit(parseInt(limit, 10));
176
161
  }
@@ -179,36 +164,55 @@ function listDevices(type, service, subservice, limit, offset, callback) {
179
164
  query.skip(parseInt(offset, 10));
180
165
  }
181
166
 
182
- async.series(
183
- [query.exec.bind(query), Device.model.countDocuments.bind(Device.model, condition)],
184
- function (error, results) {
185
- callback(error, {
186
- count: results[1],
187
- devices: results[0]
167
+ function funcQuery(cb) {
168
+ query
169
+ .exec({})
170
+ .then((res) => {
171
+ cb(null, res);
172
+ })
173
+ .catch((error) => {
174
+ cb(error);
188
175
  });
189
- }
190
- );
176
+ }
177
+ function funcQueryCount(cb) {
178
+ queryCount
179
+ .exec({})
180
+ .then((res) => {
181
+ cb(null, res);
182
+ })
183
+ .catch((error) => {
184
+ cb(error);
185
+ });
186
+ }
187
+ async.series([funcQuery, funcQueryCount], function (error, results) {
188
+ callback(error, {
189
+ count: results[1],
190
+ devices: results[0]
191
+ });
192
+ });
191
193
  }
192
194
 
193
195
  function findOneInMongoDB(queryParams, id, callback) {
194
196
  const query = Device.model.findOne(queryParams);
195
197
  query.select({ __v: 0 });
196
-
197
- query.lean().exec(function handleGet(error, data) {
198
- if (error) {
198
+ query.lean();
199
+
200
+ query
201
+ .exec({})
202
+ .then((data) => {
203
+ if (data) {
204
+ context = fillService(context, data);
205
+ logger.debug(context, 'Device data found: %j', data);
206
+ callback(null, data);
207
+ } else {
208
+ logger.debug(context, 'Device [%s] not found.', id);
209
+ callback(new errors.DeviceNotFound(id, queryParams));
210
+ }
211
+ })
212
+ .catch((error) => {
199
213
  logger.debug(context, 'Internal MongoDB Error getting device: %s', error);
200
-
201
214
  callback(new errors.InternalDbError(error));
202
- } else if (data) {
203
- context = fillService(context, data);
204
- logger.debug(context, 'Device data found: %j', data);
205
- callback(null, data);
206
- } else {
207
- logger.debug(context, 'Device [%s] not found.', id);
208
-
209
- callback(new errors.DeviceNotFound(id, queryParams));
210
- }
211
- });
215
+ });
212
216
  }
213
217
 
214
218
  /**
@@ -220,7 +224,7 @@ function findOneInMongoDB(queryParams, id, callback) {
220
224
  * @param {String} subservice Division inside the service (optional).
221
225
  */
222
226
  function getDeviceById(id, apikey, service, subservice, callback) {
223
- let queryParams = {
227
+ const queryParams = {
224
228
  id,
225
229
  service,
226
230
  subservice
@@ -252,9 +256,9 @@ function getDevice(id, apikey, service, subservice, callback) {
252
256
 
253
257
  function getByNameAndType(name, type, service, servicepath, callback) {
254
258
  context = fillService(context, { service, subservice: servicepath });
255
- let optionsQuery = {
256
- name: name,
257
- service: service,
259
+ const optionsQuery = {
260
+ name,
261
+ service,
258
262
  subservice: servicepath
259
263
  };
260
264
  if (type) {
@@ -264,20 +268,23 @@ function getByNameAndType(name, type, service, servicepath, callback) {
264
268
  const query = Device.model.findOne(optionsQuery);
265
269
 
266
270
  query.select({ __v: 0 });
267
-
268
- query.lean().exec(function handleGet(error, data) {
269
- if (error) {
271
+ query.lean();
272
+ query
273
+ .exec({})
274
+ .then((data) => {
275
+ if (data) {
276
+ context = fillService(context, data);
277
+ logger.debug(context, 'Device data found: %j', data);
278
+ callback(null, data);
279
+ } else {
280
+ logger.debug(context, 'Device [%s] not found.', name);
281
+ callback(new errors.DeviceNotFound(name, optionsQuery));
282
+ }
283
+ })
284
+ .catch((error) => {
270
285
  logger.debug(context, 'Internal MongoDB Error getting device: %s', error);
271
-
272
286
  callback(new errors.InternalDbError(error));
273
- } else if (data) {
274
- callback(null, data);
275
- } else {
276
- logger.debug(context, 'Device [%s] not found.', name);
277
-
278
- callback(new errors.DeviceNotFound(name, optionsQuery));
279
- }
280
- });
287
+ });
281
288
  }
282
289
 
283
290
  function getByName(name, service, servicepath, callback) {
@@ -314,11 +321,22 @@ function update(previousDevice, device, callback) {
314
321
  data.timestamp = device.timestamp;
315
322
  data.subscriptions = device.subscriptions;
316
323
  data.payloadType = device.payloadType;
324
+ data.useCBflowControl = device.useCBflowControl;
325
+ data.storeLastMeasure = device.storeLastMeasure;
326
+ data.lastMeasure = device.lastMeasure;
317
327
 
318
328
  /* eslint-disable-next-line new-cap */
319
329
  const deviceObj = new Device.model(data);
320
330
  deviceObj.isNew = false;
321
- deviceObj.save(saveDeviceHandler(callback));
331
+ deviceObj
332
+ .save({})
333
+ .then((deviceDAO) => {
334
+ callback(null, deviceDAO.toObject());
335
+ })
336
+ .catch((error) => {
337
+ logger.debug(fillService(context, device), 'Error storing device information: %s', error);
338
+ callback(new errors.InternalDbError(error));
339
+ });
322
340
  }
323
341
  });
324
342
  }
@@ -327,7 +345,14 @@ function update(previousDevice, device, callback) {
327
345
  * Cleans all the information in the database, leaving it in a clean state.
328
346
  */
329
347
  function clear(callback) {
330
- dbService.db.db.dropDatabase(callback);
348
+ mongoose.connection
349
+ .dropDatabase()
350
+ .then(() => {
351
+ callback(null);
352
+ })
353
+ .catch((error) => {
354
+ callback(error);
355
+ });
331
356
  }
332
357
 
333
358
  function itemToObject(i) {
@@ -355,24 +380,72 @@ function getDevicesByAttribute(name, value, service, subservice, callback) {
355
380
 
356
381
  const query = Device.model.find(filter);
357
382
  query.select({ __v: 0 });
358
-
359
- query.exec(function handleGet(error, devices) {
360
- if (error) {
383
+ query.lean();
384
+ query
385
+ .exec({})
386
+ .then((devices) => {
387
+ if (devices) {
388
+ callback(null, devices.map(itemToObject));
389
+ } else {
390
+ logger.debug(context, 'Device [%s] not found.', name);
391
+ callback(new errors.DeviceNotFound(name, filter));
392
+ }
393
+ })
394
+ .catch((error) => {
361
395
  logger.debug(context, 'Internal MongoDB Error getting device: %s', error);
362
-
363
396
  callback(new errors.InternalDbError(error));
364
- } else if (devices) {
365
- callback(null, devices.map(itemToObject));
366
- } else {
367
- logger.debug(context, 'Device [%s] not found.', name);
397
+ });
398
+ }
368
399
 
369
- callback(new errors.DeviceNotFound(name, filter));
370
- }
371
- });
400
+ function storeDeviceField(fieldName, fieldValue, typeInformation, callback) {
401
+ if (
402
+ typeInformation &&
403
+ typeInformation.id &&
404
+ typeInformation.apikey &&
405
+ typeInformation.service &&
406
+ typeInformation.subservice
407
+ ) {
408
+ getDevice(
409
+ typeInformation.id,
410
+ typeInformation.apikey,
411
+ typeInformation.service,
412
+ typeInformation.subservice,
413
+ function (error, data) {
414
+ if (error) {
415
+ callback(error);
416
+ } else {
417
+ if (fieldName === 'lastMeasure') {
418
+ data.lastMeasure = { timestamp: new Date().toISOString(), measure: fieldValue };
419
+ } else {
420
+ data[fieldName] = fieldValue;
421
+ }
422
+ /* eslint-disable-next-line new-cap */
423
+ const deviceObj = new Device.model(data);
424
+ deviceObj.isNew = false;
425
+ deviceObj
426
+ .save({})
427
+ .then((deviceDao) => {
428
+ callback(null, deviceDao.toObject());
429
+ })
430
+ .catch((error) => {
431
+ logger.debug(
432
+ fillService(context, deviceObj),
433
+ 'Error storing device information: %s',
434
+ error
435
+ );
436
+ callback(new errors.InternalDbError(error));
437
+ });
438
+ }
439
+ }
440
+ );
441
+ } else {
442
+ callback(null, null);
443
+ }
372
444
  }
373
445
 
374
446
  exports.getDevicesByAttribute = alarmsInt(constants.MONGO_ALARM, getDevicesByAttribute);
375
447
  exports.store = alarmsInt(constants.MONGO_ALARM, storeDevice);
448
+ exports.storeDeviceField = alarmsInt(constants.MONGO_ALARM, storeDeviceField);
376
449
  exports.update = alarmsInt(constants.MONGO_ALARM, update);
377
450
  exports.remove = alarmsInt(constants.MONGO_ALARM, removeDevice);
378
451
  exports.list = alarmsInt(constants.MONGO_ALARM, listDevices);