iotagent-node-lib 3.3.0 → 3.4.1

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 (80) hide show
  1. package/CHANGES_NEXT_RELEASE +1 -0
  2. package/README.md +10 -11
  3. package/doc/README.md +16 -0
  4. package/doc/admin.md +565 -0
  5. package/doc/api.md +9 -5
  6. package/doc/deprecated.md +16 -14
  7. package/doc/{architecture.md → devel/architecture.md} +3 -3
  8. package/doc/{Contribution.md → devel/contribution-guidelines.md} +43 -35
  9. package/doc/devel/development.md +1879 -0
  10. package/doc/{northboundinteractions.md → devel/northboundinteractions.md} +18 -33
  11. package/doc/index.md +3 -5
  12. package/docker/Mosquitto/README.md +1 -0
  13. package/lib/commonConfig.js +0 -5
  14. package/lib/fiware-iotagent-lib.js +1 -1
  15. package/lib/jexlTranformsMap.js +2 -1
  16. package/lib/request-shim.js +2 -2
  17. package/lib/services/commands/commandService.js +1 -1
  18. package/lib/services/common/genericMiddleware.js +1 -1
  19. package/lib/services/devices/deviceRegistryMemory.js +2 -2
  20. package/lib/services/devices/deviceRegistryMongoDB.js +22 -9
  21. package/lib/services/devices/deviceService.js +36 -30
  22. package/lib/services/devices/devices-NGSI-LD.js +14 -2
  23. package/lib/services/devices/devices-NGSI-mixed.js +0 -2
  24. package/lib/services/devices/devices-NGSI-v2.js +22 -100
  25. package/lib/services/groups/groupService.js +1 -1
  26. package/lib/services/ngsi/entities-NGSI-v2.js +14 -27
  27. package/lib/services/northBound/deviceProvisioningServer.js +14 -5
  28. package/mkdocs.yml +6 -11
  29. package/package.json +3 -3
  30. package/scripts/legacy_expression_tool/README.md +56 -38
  31. package/test/unit/general/contextBrokerKeystoneSecurityAccess-test.js +2 -2
  32. package/test/unit/mongodb/mongodb-registry-test.js +1 -1
  33. package/test/unit/ngsi-ld/general/contextBrokerOAuthSecurityAccess-test.js +66 -65
  34. package/test/unit/ngsi-ld/general/https-support-test.js +1 -1
  35. package/test/unit/ngsi-ld/lazyAndCommands/command-test.js +8 -7
  36. package/test/unit/ngsi-ld/lazyAndCommands/polling-commands-test.js +12 -11
  37. package/test/unit/ngsi-ld/ngsiService/subscriptions-test.js +41 -39
  38. package/test/unit/ngsi-ld/provisioning/device-provisioning-api_test.js +122 -122
  39. package/test/unit/ngsi-ld/provisioning/device-registration_test.js +28 -28
  40. package/test/unit/ngsi-ld/provisioning/device-update-registration_test.js +18 -17
  41. package/test/unit/ngsi-ld/provisioning/singleConfigurationMode-test.js +7 -7
  42. package/test/unit/ngsi-ld/provisioning/updateProvisionedDevices-test.js +8 -7
  43. package/test/unit/ngsiv2/examples/contextRequests/updateContext6.json +2 -0
  44. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin1.json +0 -12
  45. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin11.json +0 -4
  46. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin12.json +1 -5
  47. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin2.json +0 -12
  48. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin29.json +0 -12
  49. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin3.json +0 -4
  50. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin41.json +0 -10
  51. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin5.json +0 -4
  52. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin6.json +0 -4
  53. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin7.json +0 -4
  54. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin8.json +0 -12
  55. package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin9.json +0 -4
  56. package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin25.json +1 -5
  57. package/test/unit/ngsiv2/expressions/jexlBasedTransformations-test.js +13 -12
  58. package/test/unit/ngsiv2/general/contextBrokerOAuthSecurityAccess-test.js +2 -2
  59. package/test/unit/ngsiv2/general/https-support-test.js +1 -1
  60. package/test/unit/ngsiv2/ngsiService/active-devices-test.js +3 -8
  61. package/test/unit/ngsiv2/ngsiService/subscriptions-test.js +10 -10
  62. package/test/unit/ngsiv2/provisioning/device-provisioning-api_test.js +8 -103
  63. package/test/unit/ngsiv2/provisioning/device-registration_test.js +8 -6
  64. package/test/unit/ngsiv2/provisioning/device-update-registration_test.js +2 -1
  65. package/test/unit/ngsiv2/provisioning/updateProvisionedDevices-test.js +0 -1
  66. package/.nyc_output/33364de2-1199-4ec2-b33c-cae063ef8cc4.json +0 -1
  67. package/.nyc_output/processinfo/33364de2-1199-4ec2-b33c-cae063ef8cc4.json +0 -1
  68. package/.nyc_output/processinfo/index.json +0 -1
  69. package/doc/config-basic-example.js +0 -20
  70. package/doc/development.md +0 -285
  71. package/doc/howto.md +0 -641
  72. package/doc/installationguide.md +0 -365
  73. package/doc/operations.md +0 -127
  74. package/doc/usermanual.md +0 -900
  75. package/lib/plugins/bidirectionalData.js +0 -356
  76. package/test/unit/ngsi-ld/plugins/bidirectional-plugin_test.js +0 -697
  77. package/test/unit/ngsiv2/plugins/bidirectional-plugin_test.js +0 -536
  78. /package/doc/{NorthboundInteractions.postman_collection → devel/NorthboundInteractions.postman_collection} +0 -0
  79. /package/doc/{echo.js → devel/echo.js} +0 -0
  80. /package/doc/{finalResult.js → devel/finalResult.js} +0 -0
@@ -0,0 +1,1879 @@
1
+ # Development documentation
2
+
3
+ - [Preface](#preface)
4
+ - [Contributing](#contributing)
5
+ - [Project management](#project-management)
6
+ - [Installing dependencies](#installing-dependencies)
7
+ - [Project build](#project-build)
8
+ - [Testing](#testing)
9
+ - [Test requirements](#test-requirements)
10
+ - [Debug Test](#debug-test)
11
+ - [Continuous testing](#continuous-testing)
12
+ - [Code Coverage](#code-coverage)
13
+ - [Clean](#clean)
14
+ - [Checking code style](#checking-code-style)
15
+ - [Source code style validation - ESLint](#source-code-style-validation---eslint)
16
+ - [Documentation Markdown validation](#documentation-markdown-validation)
17
+ - [Documentation Spell-checking](#documentation-spell-checking)
18
+ - [Prettify Code](#prettify-code)
19
+ - [Library functions and modules](#library-functions-and-modules)
20
+ - [Stats Registry](#stats-registry)
21
+ - [Alarm module](#alarm-module)
22
+ - [Transactions](#transactions)
23
+ - [Library overview](#library-overview)
24
+ - [Function reference](#function-reference)
25
+ - [Generic middlewares](#generic-middlewares)
26
+ - [DB Models from API document](#db-models-from-api-document)
27
+ - [Service group model](#service-group-model)
28
+ - [Device model](#device-model)
29
+ - [Developing a new IoT Agent](#developing-a-new-iot-agent)
30
+ - [Protocol](#protocol)
31
+ - [Requirements](#requirements)
32
+ - [Basic IOTA](#basic-iot-agent)
33
+ - [IOTA With Active attributes](#iot-agent-with-active-attributes)
34
+ - [IOTA With Lazy attributes](#iota-with-lazy-attributes)
35
+ - [Previous considerations](#previous-considerations)
36
+ - [Implementation](#implementation)
37
+ - [IoT Agent in multi-thread mode](#iot-agent-in-multi-thread-mode)
38
+ - [Configuration management](#configuration-management)
39
+ - [Provisioning handlers](#provisioning-handlers)
40
+
41
+ ## Preface
42
+
43
+ The **IoT Agent node library** as the name suggests is a library that provides a set of functions that can be used by
44
+ IoT Agents to implement the northbound interface. The library is used by several FIWARE IoT Agents, such as:
45
+
46
+ a standalone library that can be used by any IoT Agent to implement the northbound interface,
47
+
48
+ is not a standalone product and should be added as a dependency to `package.json` of the IoT Agent.
49
+
50
+ ```json
51
+ ...
52
+ "dependencies": {
53
+ "iotagent-node-lib": "*",
54
+ }
55
+ ```
56
+
57
+ In order to use the library within your own IoT Agent, you must first you require it before use:
58
+
59
+ ```javascript
60
+ const iotagentLib = require('iotagent-node-lib');
61
+ ```
62
+
63
+ This file contains the documentation for developers who wish to contribute to the **IoT Agent node library** project and
64
+ also for those who wish to use the library within their own IoT Agent project.
65
+
66
+ ## Contributing
67
+
68
+ Contributions to this project are welcome. Developers planning to contribute should follow the
69
+ [Contribution Guidelines](contribution-guidelines.md)
70
+
71
+ ## Project management
72
+
73
+ The **IoT Agent node library** project is managed using [npm](https://www.npmjs.com/). The following sections show the
74
+ available options in detail:
75
+
76
+ ### Installing dependencies
77
+
78
+ This is the first step to be executed after cloning the project. To install them, type the following command:
79
+
80
+ ```bash
81
+ npm install
82
+ ```
83
+
84
+ ### Project build
85
+
86
+ The project is managed using npm.
87
+
88
+ For a list of available task, type
89
+
90
+ ```bash
91
+ npm run
92
+ ```
93
+
94
+ The following sections show the available options in detail.
95
+
96
+ ### Testing
97
+
98
+ [Mocha](https://mochajs.org/) Test Runner + [Should.js](https://shouldjs.github.io/) Assertion Library.
99
+
100
+ The test environment is preconfigured to run BDD testing style.
101
+
102
+ Module mocking during testing can be done with [proxyquire](https://github.com/thlorenz/proxyquire)
103
+
104
+ To run tests, type
105
+
106
+ ```bash
107
+ npm test
108
+ ```
109
+
110
+ There are additional targets starting with `test:` prefix to run specific test subsets isolated. For instance, the
111
+ `test:expressions` target runs the subset of tests related with expression language feature:
112
+
113
+ ```bash
114
+ npm run test:expressions
115
+ ```
116
+
117
+ #### Test requirements
118
+
119
+ A [MongoDB](https://www.mongodb.com/) 3.2+ instance is required to run tests. You can deploy one by using the commodity
120
+ `docker-compose-dev.yml`:
121
+
122
+ ```
123
+ docker-compose -f docker-compose-dev.yml up -d
124
+ ```
125
+
126
+ To run docker compose you will need [docker](https://docs.docker.com/get-docker/) and
127
+ [docker-compose](https://docs.docker.com/compose/install/).
128
+
129
+ #### Debug Test
130
+
131
+ To debug the code while running run tests, type
132
+
133
+ ```bash
134
+ npm run test:debug
135
+ ```
136
+
137
+ In the console the link to the debugger will be provided. You can connect to it via Chrome, for example, by opening the
138
+ following url: `chrome://inspect`.
139
+
140
+ Additional debug clients are listed on [node.js](https://nodejs.org/en/docs/guides/debugging-getting-started/).
141
+
142
+ #### Continuous testing
143
+
144
+ Support for continuous testing by modifying a src file or a test. For continuous testing, type
145
+
146
+ ```bash
147
+ npm run test:watch
148
+ ```
149
+
150
+ If you want to continuously check also source code style, use instead:
151
+
152
+ ```bash
153
+ npm run watch
154
+ ```
155
+
156
+ #### Code Coverage
157
+
158
+ Istanbul
159
+
160
+ Analyze the code coverage of your tests.
161
+
162
+ To generate an HTML coverage report under `site/coverage/` and to print out a summary, type
163
+
164
+ ```bash
165
+ # Use git-bash on Windows
166
+ npm run test:coverage
167
+ ```
168
+
169
+ ### Clean
170
+
171
+ Removes `node_modules` and `coverage` folders, and `package-lock.json` file so that a fresh copy of the project is
172
+ restored.
173
+
174
+ ```bash
175
+ # Use git-bash on Windows
176
+ npm run clean
177
+ ```
178
+
179
+ ### Checking code style
180
+
181
+ #### Source code style validation - ESLint
182
+
183
+ Uses the provided `.eslintrc.json` flag file. To check source code style, type
184
+
185
+ ```bash
186
+ npm run lint
187
+ ```
188
+
189
+ #### Documentation Markdown validation
190
+
191
+ Checks the Markdown documentation for consistency
192
+
193
+ ```bash
194
+ # Use git-bash on Windows
195
+ npm run lint:md
196
+ ```
197
+
198
+ #### Documentation Spell-checking
199
+
200
+ Uses the provided `.textlintrc` flag file. To check the Markdown documentation for spelling and grammar errors, dead
201
+ links & etc.
202
+
203
+ ```bash
204
+ # Use git-bash on Windows
205
+ npm run lint:text
206
+ ```
207
+
208
+ #### Prettify Code
209
+
210
+ Runs the [prettier](https://prettier.io) code formatter to ensure consistent code style (whitespacing, parameter
211
+ placement and breakup of long lines etc.) within the codebase.
212
+
213
+ ```bash
214
+ # Use git-bash on Windows
215
+ npm run prettier
216
+ ```
217
+
218
+ To ensure consistent Markdown formatting run the following:
219
+
220
+ ```bash
221
+ # Use git-bash on Windows
222
+ npm run prettier:text
223
+ ```
224
+
225
+ ## Library functions and modules
226
+
227
+ ### Stats Registry
228
+
229
+ The library provides a mechanism for the periodic reporting of stats related to the library's work. In order to activate
230
+ the use of the periodic stats, it must be configured in the config file, as described in the
231
+ [Configuration](../admin.md#configuration) section.
232
+
233
+ The Stats Registry holds two dictionaries, with the same set of stats. For each stat, one of the dictionaries holds the
234
+ historical global value and the other one stores the value since the last value reporting (or current value).
235
+
236
+ The stats library currently stores only the following values:
237
+
238
+ - **deviceCreationRequests**: number of Device Creation Requests that arrived to the API (no matter the result).
239
+ - **deviceRemovalRequests**: number of Removal Device Requests that arrived to the API (no matter the result).
240
+ - **measureRequests**: number of times the ngsiService.update() function has been invoked (no matter the result).
241
+
242
+ More values will be added in the future to the library. The applications using the library can add values to the Stats
243
+ Registry just by using the following function:
244
+
245
+ ```javascript
246
+ iotagentLib.statsRegistry.add('statName', statIncrementalValue, callback);
247
+ ```
248
+
249
+ The first time this function is invoked, it will add the new stat to the registry. Subsequent calls will add the value
250
+ to the specified stat both to the current and global measures. The stat will be cleared in each interval as usual.
251
+
252
+ ### Alarm module
253
+
254
+ The library provide an alarm module that can be used to track through the logs alarms raised in the IoTAgent. This
255
+ module provides:
256
+
257
+ - Two functions to raise and release and alarm (`raise()` and `release()`): every alarm is identified by a name and a
258
+ description. When the alarm is raised, an error with the text `Raising [%s]` is logged. When the alarm is released,
259
+ the corresponding text, `Releasing [%s]` is logged. If an alarm is raised multiple times, it is only logged once. If
260
+ its released multiple times it is only released once. Releasing a non-existing alarm has no effect.
261
+
262
+ - Functions to list all the raised alarms and clean all the alarms (`list()` and `clean()`).
263
+
264
+ - A function to instrument other functions, so when one of that functions return an error, an alarm is raised, and
265
+ when it returns a success an alarm is ceased (`intercept()`).
266
+
267
+ All this functions can be accessed through the `.alarms` attribute of the library.
268
+
269
+ ### Transactions
270
+
271
+ The library implements a concept of transactions, in order to follow the execution flow the library follows when
272
+ treating requests entering both from the North and the South ports of the IoT Agent.
273
+
274
+ To follow the transactions, a new Domain is created for each incoming request; in the case of requests received on the
275
+ North Port of the IoT Agent, this domain is automatically created by a Express middleware, and no further action is
276
+ needed from the user. For the case of requests received on the South Port of the IoT Agent, the user is responsible of
277
+ creating an stopping the transaction, using the `ensureSouthboundDomain` and `finishSouthBoundTransaction`. In this
278
+ case, the transaction will last from the invocation to the former to the invocation of the latter.
279
+
280
+ The Transaction Correlator is used along all the IoT Platform to follow the trace of a transaction between multiple
281
+ components. To do so, in all the HTTP requests sent to other components of the platform, a custom header named
282
+ `Fiware-Correlator` is sent with the correlator of the transaction that generated the request. If a component of the
283
+ platform receives a request containing this header that starts a transaction, the component will create the transaction
284
+ with the received correlator, instead of creating a new one. If the header is not present or the transaction originates
285
+ in the component, the transaction ID in this component will be used as the correlator.
286
+
287
+ During the duration of a transaction, all the log entries created by the code will write the current Transaction ID and
288
+ correlator for the operation being executed.
289
+
290
+ ### Library overview
291
+
292
+ In order to use the library, add the following dependency to your package.json file:
293
+
294
+ ```json
295
+ "iotagent-node-lib": "*"
296
+ ```
297
+
298
+ In order to use this library, first you must require it:
299
+
300
+ ```javascript
301
+ var iotagentLib = require('iotagent-node-lib');
302
+ ```
303
+
304
+ The library supports four groups of features, one for each direction of the communication: client-to-server and
305
+ server-to-client (and each flow both for the client and the server). Each feature set is defined in the following
306
+ sections.
307
+
308
+ ### Function reference
309
+
310
+ > **WARNING** This section is outdated. Functions described here may be outdated and not reflect the current
311
+ > implementation of the IoT Agent Library. You could have a look to [iotagentLib.js](./lib/iotagentLib.js) file to see
312
+ > the current detail of functions implemented.
313
+
314
+ The following fucntions are available in the library:
315
+
316
+ - [iotagentLib.activate()](#iotagentlibactivate)
317
+ - [iotagentLib.deactivate()](#iotagentlibdeactivate)
318
+ - [iotagentLib.register()](#iotagentlibregister)
319
+ - [iotagentLib.unregister()](#iotagentlibunregister)
320
+ - [iotagentLib.update()](#iotagentlibupdate)
321
+ - [iotagentLib.setCommandResult()](#iotagentlibsetcommandresult)
322
+ - [iotagentLib.listDevices()](#iotagentliblistdevices)
323
+ - [iotagentLib.setDataUpdateHandler()](#iotagentlibsetdataupdatehandler)
324
+ - [iotagentLib.setDataQueryHandler()](#iotagentlibsetdataqueryhandler)
325
+ - [iotagentLib.setNotificationHandler()](#iotagentlibsetnotificationhandler)
326
+ - [iotagentLib.setCommandHandler()](#iotagentlibsetcommandhandler)
327
+ - [iotagentLib.setMergePatchHandler()](#iotagentlibsetmergepatchhandler)
328
+ - [iotagentLib.setProvisioningHandler()](#iotagentlibsetprovisioninghandler)
329
+ - [iotagentLib.setRemoveDeviceHandler()](#iotagentlibsetremovedevicehandler)
330
+ - [iotagentLib.setConfigurationHandler()](#iotagentlibsetconfigurationhandler)
331
+ - [iotagentLib.setRemoveConfigurationHandler()](#iotagentlibsetremoveconfigurationhandler)
332
+ - [iotagentLib.getDevice()](#iotagentlibgetdevice)
333
+ - [iotagentLib.getDeviceByName()](#iotagentlibgetdevicebyname)
334
+ - [iotagentLib.getDevicesByAttribute()](#iotagentlibgetdevicesbyattribute)
335
+ - [iotagentLib.retrieveDevice()](#iotagentlibretrievedevice)
336
+ - [iotagentLib.mergeDeviceWithConfiguration()](#iotagentlibmergedevicewithconfiguration)
337
+ - [iotagentLib.getConfiguration()](#iotagentlibgetconfiguration)
338
+ - [iotagentLib.findConfiguration()](#iotagentlibfindconfiguration)
339
+ - [iotagentLib.getEffectiveApiKey()](#iotagentlibgeteffectiveapikey)
340
+ - [iotagentLib.subscribe()](#iotagentlibsubscribe)
341
+ - [iotagentLib.unsubscribe()](#iotagentlibunsubscribe)
342
+ - [iotagentLib.ensureSouthboundDomain()](#iotagentlibensuresouthbounddomain)
343
+ - [iotagentLib.finishSouthBoundTransaction()](#iotagentlibfinishsouthboundtransaction)
344
+ - [iotagentLib.startServer()](#iotagentlibstartserver)
345
+ - [iotagentLib.request()](#iotagentlibrequest)
346
+
347
+ ##### iotagentLib.activate()
348
+
349
+ ###### Signature
350
+
351
+ ```javascript
352
+ function activate(newConfig, callback)
353
+ ```
354
+
355
+ ###### Description
356
+
357
+ Activates the IoT Agent to start listening for NGSI Calls (acting as a Context Provider). It also creates the device
358
+ registry for the IoT Agent (based on the deviceRegistry.type configuration option).
359
+
360
+ ###### Params
361
+
362
+ - newConfig: Configuration of the Context Server (described in the [Configuration](../admin.md#configuration)
363
+ section).
364
+
365
+ ##### iotagentLib.deactivate()
366
+
367
+ ###### Signature
368
+
369
+ ```javascript
370
+ function deactivate(callback)
371
+ ```
372
+
373
+ ###### Description
374
+
375
+ Stops the HTTP server.
376
+
377
+ ###### Params
378
+
379
+ ##### iotagentLib.register()
380
+
381
+ ###### Signature
382
+
383
+ ```javascript
384
+ function registerDevice(deviceObj, callback)
385
+ ```
386
+
387
+ ###### Description
388
+
389
+ Register a new device in the IoT Agent. This registration will also trigger a Context Provider registration in the
390
+ Context Broker for all its lazy attributes.
391
+
392
+ The device Object can have the following attributes:
393
+
394
+ - `id`: Device ID of the device.
395
+ - `type`: type to be assigned to the device.
396
+ - `name`: name that will be used for the Entity representing the device in the Context Broker.
397
+ - `service`: name of the service associated with the device.
398
+ - `subservice`: name of the subservice associated with th device.
399
+ - `lazy`: list of lazy attributes with their types.
400
+ - `active`: list of active attributes with their types.
401
+ - `staticAttributes`: list of NGSI attributes to add to the device entity 'as is' in updates, queries and
402
+ registrations.
403
+ - `internalAttributes`: optional section with free format, to allow specific IoT Agents to store information along
404
+ with the devices in the Device Registry.
405
+
406
+ The device `id` and `type` are required fields for any registration. The rest of the attributes are optional, but, if
407
+ they are not present in the function call arguments, the type must be registered in the configuration, so the service
408
+ can infer their default values from the configured type. If an optional attribute is not given in the parameter list and
409
+ there isn't a default configuration for the given type, a TypeNotFound error is raised.
410
+
411
+ If the device has been previously preprovisioned, the missing data will be completed with the values from the registered
412
+ device.
413
+
414
+ ###### Params
415
+
416
+ - deviceObj: object containing all the information about the device to be registered (mandatory).
417
+
418
+ ##### iotagentLib.unregister()
419
+
420
+ ###### Signature
421
+
422
+ ```javascript
423
+ function unregisterDevice(id, service, subservice, callback)
424
+ ```
425
+
426
+ ###### Description
427
+
428
+ Unregister a device from the Context broker and the internal registry.
429
+
430
+ ###### Params
431
+
432
+ - id: Device ID of the device to register.
433
+ - service: Service of the device to unregister.
434
+ - subservice: Subservice inside the service for the unregistered device.
435
+
436
+ ##### iotagentLib.update()
437
+
438
+ ###### Signature
439
+
440
+ ```javascript
441
+ function update(entityName, attributes, typeInformation, token, callback)
442
+ ```
443
+
444
+ ###### Description
445
+
446
+ Makes an update in the Device's entity in the context broker, with the values given in the 'attributes' array. This
447
+ array should comply to the NGSI's attribute format.
448
+
449
+ ###### Params
450
+
451
+ - entityName: Name of the entity to register.
452
+ - attributes: Attribute array containing the values to update.
453
+ - typeInformation: Configuration information for the device.
454
+ - token: User token to identify against the PEP Proxies (optional).
455
+
456
+ ##### iotagentLib.setCommandResult()
457
+
458
+ ###### Signature
459
+
460
+ ```javascript
461
+ function setCommandResult(entityName, resource, apikey, commandName, commandResult, status, deviceInformation, callback)
462
+ ```
463
+
464
+ ###### Description
465
+
466
+ Update the result of a command in the Context Broker. The result of the command has two components: the result of the
467
+ command itself will be represented with the suffix `_info` in the entity while the status is updated in the attribute
468
+ with the `_status` suffix.
469
+
470
+ ###### Params
471
+
472
+ - entityName: Name of the entity holding the command.
473
+ - resource: Resource name of the endpoint the device is calling.
474
+ - apikey: Apikey the device is using to send the values (can be the empty string if none is needed).
475
+ - commandName: Name of the command whose result is being updated.
476
+ - commandResult: Result of the command in string format.
477
+ - deviceInformation: Device information, including security and service information. (optional).
478
+
479
+ ##### iotagentLib.listDevices()
480
+
481
+ ###### Signature
482
+
483
+ ```javascript
484
+ function listDevices(callback)
485
+ function listDevices(limit, offset, callback)
486
+ function listDevices(service, subservice, limit, offset, callback)
487
+ ```
488
+
489
+ ###### Description
490
+
491
+ Return a list of all the devices registered in the specified service and subservice. This function can be invoked in
492
+ three different ways:
493
+
494
+ - with just one parameter (the callback)
495
+ - with three parameters (service, subservice and callback)
496
+ - or with five parameters (including limit and offset).
497
+
498
+ ###### Params
499
+
500
+ - service: service from where the devices will be retrieved.
501
+ - subservice: subservice from where the devices will be retrieved.
502
+ - limit: maximum number of results to retrieve (optional).
503
+ - offset: number of results to skip from the listing (optional).
504
+
505
+ ##### iotagentLib.setDataUpdateHandler()
506
+
507
+ ###### Signature
508
+
509
+ ```javascript
510
+ function setDataUpdateHandler(newHandler)
511
+ ```
512
+
513
+ ###### Description
514
+
515
+ Sets the new user handler for Entity update requests. This handler will be called whenever an update request arrives
516
+ with the following parameters: (`id`, `type`, `service`, `subservice`, `attributes`, `callback`). Every object within of
517
+ the `attributes` array contains `name`, `type` and `value` attributes, and may also include additional attributes for
518
+ `metadata` and `datasetId`. The handler is in charge of updating the corresponding values in the devices with the
519
+ appropriate protocol.
520
+
521
+ Once all the updates have taken place, the callback must be invoked with the updated Context Element. E.g.:
522
+
523
+ ```javascript
524
+ callback(null, {
525
+ type: 'TheType',
526
+ isPattern: false,
527
+ id: 'EntityID',
528
+ attributes: [
529
+ {
530
+ name: 'lumniscence',
531
+ type: 'Lumens',
532
+ value: '432'
533
+ }
534
+ ]
535
+ });
536
+ ```
537
+
538
+ In the case of NGSI requests affecting multiple entities, this handler will be called multiple times, one for each
539
+ entity, and all the results will be combined into a single response.
540
+
541
+ ###### Params
542
+
543
+ - newHandler: User handler for update requests
544
+
545
+ ##### iotagentLib.setDataQueryHandler()
546
+
547
+ ###### Signature
548
+
549
+ ```javascript
550
+ function setDataQueryHandler(newHandler)
551
+ ```
552
+
553
+ ###### Description
554
+
555
+ Sets the new user handler for Entity query requests. This handler will be called whenever a query request arrives, with
556
+ the following parameters: (`id`, `type`, `service`, `subservice`, `attributes`, `callback`). The handler must retrieve
557
+ all the corresponding information from the devices and return a NGSI entity with the requested values.
558
+
559
+ The callback must be invoked with the updated Context Element, using the information retrieved from the devices. E.g.:
560
+
561
+ ```javascript
562
+ callback(null, {
563
+ type: 'TheType',
564
+ isPattern: false,
565
+ id: 'EntityID',
566
+ attributes: [
567
+ {
568
+ name: 'lumniscence',
569
+ type: 'Lumens',
570
+ value: '432'
571
+ }
572
+ ]
573
+ });
574
+ ```
575
+
576
+ In the case of NGSI requests affecting multiple entities, this handler will be called multiple times, one for each
577
+ entity, and all the results will be combined into a single response.
578
+
579
+ ###### Params
580
+
581
+ - newHandler: User handler for query requests.
582
+
583
+ ##### iotagentLib.setNotificationHandler()
584
+
585
+ ###### Signature
586
+
587
+ ```javascript
588
+ function setNotificationHandler(newHandler)
589
+ ```
590
+
591
+ ###### Description
592
+
593
+ Sets the new handler for incoming notifications. The notifications are sent by the Context Broker based on the IoT Agent
594
+ subscriptions created with the `subscribe()` function.
595
+
596
+ The handler must adhere to the following signature:
597
+
598
+ ```javascript
599
+ function mockedHandler(device, data, callback)
600
+ ```
601
+
602
+ The `device` parameter contains the device object corresponding to the entity whose changes were notified with the
603
+ incoming notification. Take into account that multiple entities may be modified with each single notification. The
604
+ handler will be called once for each one of those entities.
605
+
606
+ The `data` parameter is an array with all the attributes that were requested in the subscription and its respective
607
+ values.
608
+
609
+ The handler is expected to call its callback once with no parameters (failing to do so may cause unexpected behaviors in
610
+ the IoT Agent).
611
+
612
+ ##### iotagentLib.setCommandHandler()
613
+
614
+ ###### Signature
615
+
616
+ ```javascript
617
+ function setCommandHandler(newHandler)
618
+ ```
619
+
620
+ ###### Description
621
+
622
+ Sets the new user handler for registered entity commands. This handler will be called whenever a command request
623
+ arrives, with the following parameters: (`id`, `type`, `service`, `subservice`, `attributes`, `callback`). The handler
624
+ must retrieve all the corresponding information from the devices and return a NGSI entity with the requested values.
625
+
626
+ The callback must be invoked with the updated Context Element, using the information retrieved from the devices. E.g.:
627
+
628
+ ```javascript
629
+ callback(null, {
630
+ type: 'TheType',
631
+ isPattern: false,
632
+ id: 'EntityID',
633
+ attributes: [
634
+ {
635
+ name: 'lumniscence',
636
+ type: 'Lumens',
637
+ value: '432'
638
+ }
639
+ ]
640
+ });
641
+ ```
642
+
643
+ In the case of NGSI requests affecting multiple entities, this handler will be called multiple times, one for each
644
+ entity, and all the results will be combined into a single response. Only IoT Agents which deal with actuator devices
645
+ will include a handler for commands.
646
+
647
+ ###### Params
648
+
649
+ - newHandler: User handler for command requests.
650
+
651
+ ##### iotagentLib.setMergePatchHandler()
652
+
653
+ ###### Signature
654
+
655
+ ```javascript
656
+ function setMergePatchHandler(newHandler)
657
+ ```
658
+
659
+ ###### Description
660
+
661
+ Sets the new user handler for NGSI-LD Entity [merge-patch](https://datatracker.ietf.org/doc/html/rfc7386) requests. This
662
+ handler will be called whenever a merge-patch request arrives, with the following parameters: (`id`, `type`, `service`,
663
+ `subservice`, `attributes`, `callback`). The handler must retrieve all the corresponding information from the devices
664
+ and return a NGSI entity with the requested values.
665
+
666
+ The callback must be invoked with the updated Context Element, using the information retrieved from the devices. E.g.:
667
+
668
+ ```javascript
669
+ callback(null, {
670
+ type: 'TheType',
671
+ isPattern: false,
672
+ id: 'EntityID',
673
+ attributes: [
674
+ {
675
+ name: 'lumniscence',
676
+ type: 'Lumens',
677
+ value: '432'
678
+ }
679
+ ]
680
+ });
681
+ ```
682
+
683
+ In the case of NGSI-LD requests affecting multiple entities, this handler will be called multiple times. Since
684
+ merge-patch is an advanced function, not all IoT Agents will include a handler for merge-patch.
685
+
686
+ ###### Params
687
+
688
+ - newHandler: User handler for merge-patch requests.
689
+
690
+ ##### iotagentLib.setProvisioningHandler()
691
+
692
+ ###### Signature
693
+
694
+ ```javascript
695
+ function setProvisioningHandler (newHandler)
696
+ ```
697
+
698
+ ###### Description
699
+
700
+ Sets the new user handler for the provisioning of devices. This handler will be called every time a new device is
701
+ created.
702
+
703
+ The handler must adhere to the following signature:
704
+
705
+ ```javascript
706
+ function(newDevice, callback)
707
+ ```
708
+
709
+ The `newDevice` parameter will contain the newly created device. The handler is expected to call its callback with no
710
+ parameters (this handler should only be used for reconfiguration purposes of the IoT Agent).
711
+
712
+ ##### iotagentLib.setRemoveDeviceHandler()
713
+
714
+ ###### Signature
715
+
716
+ ```javascript
717
+ function setRemoveDeviceHandler(newHandler)
718
+ ```
719
+
720
+ ###### Description
721
+
722
+ Sets the new user handler for the removal of a device. This handler will be called every time a device is removed.
723
+
724
+ The handler must adhere to the following signature:
725
+
726
+ ```javascript
727
+ function(deviceToDelete, callback)
728
+ ```
729
+
730
+ The `deviceToDelete` parameter will contain the device to be deleted. The handler is expected to call its callback with
731
+ no parameters (this handler should only be used for reconfiguration purposes of the IoT Agent).
732
+
733
+ ##### iotagentLib.setConfigurationHandler()
734
+
735
+ ###### Signature
736
+
737
+ ```javascript
738
+ function setConfigurationHandler(newHandler)
739
+ ```
740
+
741
+ ###### Description
742
+
743
+ Sets the new user handler for the configuration updates. This handler will be called every time a new configuration is
744
+ created or an old configuration is updated.
745
+
746
+ The handler must adhere to the following signature:
747
+
748
+ ```javascript
749
+ function(newConfiguration, callback)
750
+ ```
751
+
752
+ The `newConfiguration` parameter will contain the newly created configuration. The handler is expected to call its
753
+ callback with no parameters (this handler should only be used for reconfiguration purposes of the IoT Agent).
754
+
755
+ For the cases of multiple updates (a single Device Configuration POST that will create several device groups), the
756
+ handler will be called once for each of the configurations (both in the case of the creations and the updates).
757
+
758
+ The handler will be also called in the case of updates related to configurations. In that situation, the
759
+ `newConfiguration` parameter contains also the fields needed to identify the configuration to be updated, i.e.,
760
+ `service`, `subservice`, `resource` and `apikey`.
761
+
762
+ ##### iotagentLib.setRemoveConfigurationHandler()
763
+
764
+ ###### Signature
765
+
766
+ ```javascript
767
+ function setRemoveConfigurationHandler(newHandler)
768
+ ```
769
+
770
+ ###### Description
771
+
772
+ Sets the new user handler for the removal of configuratios. This handler will be called every time a configuration is
773
+ removed.
774
+
775
+ The handler must adhere to the following signature:
776
+
777
+ ```javascript
778
+ function(configurationToDelete, callback)
779
+ ```
780
+
781
+ The `configurationToDelete` parameter will contain the configuration to be deleted. The handler is expected to call its
782
+ callback with no parameters (this handler should only be used for reconfiguration purposes of the IoT Agent).
783
+
784
+ ##### iotagentLib.getDevice()
785
+
786
+ ###### Signature
787
+
788
+ ```javascript
789
+ function getDevice(deviceId, service, subservice, callback)
790
+ ```
791
+
792
+ ###### Description
793
+
794
+ Retrieve all the information about a device from the device registry.
795
+
796
+ ###### Params
797
+
798
+ - deviceId: ID of the device to be found.
799
+ - service: Service for which the requested device.
800
+ - subservice: Subservice inside the service for which the device is requested.
801
+
802
+ ##### iotagentLib.getDeviceByName()
803
+
804
+ ###### Signature
805
+
806
+ ```javascript
807
+ function getDeviceByName(deviceName, service, subservice, callback)
808
+ ```
809
+
810
+ ###### Description
811
+
812
+ Retrieve a device from the registry based on its entity name.
813
+
814
+ ###### Params
815
+
816
+ - deviceName: Name of the entity associated to a device.
817
+ - service: Service the device belongs to.
818
+ - subservice: Division inside the service.
819
+
820
+ ##### iotagentLib.getDevicesByAttribute()
821
+
822
+ ###### Signature
823
+
824
+ ```javascript
825
+ function getDevicesByAttribute(attributeName, attributeValue, service, subservice, callback)
826
+ ```
827
+
828
+ ###### Description
829
+
830
+ Retrieve all the devices having an attribute named `name` with value `value`.
831
+
832
+ ###### Params
833
+
834
+ - name: name of the attribute to match.
835
+ - value: value to match in the attribute.
836
+ - service: Service the device belongs to.
837
+ - subservice: Division inside the service.
838
+
839
+ ##### iotagentLib.retrieveDevice()
840
+
841
+ ###### Signature
842
+
843
+ ```javascript
844
+ function retrieveDevice(deviceId, apiKey, callback)
845
+ ```
846
+
847
+ ###### Description
848
+
849
+ Retrieve a device from the device repository based on the given APIKey and DeviceID, creating one if none is found for
850
+ the given data.
851
+
852
+ ###### Params
853
+
854
+ - deviceId: Device ID of the device that wants to be retrieved or created.
855
+ - apiKey: APIKey of the Device Group (or default APIKey).
856
+
857
+ ##### iotagentLib.mergeDeviceWithConfiguration()
858
+
859
+ ###### Signature
860
+
861
+ ```javascript
862
+ function mergeDeviceWithConfiguration(fields, defaults, deviceData, configuration, callback)
863
+ ```
864
+
865
+ ###### Description
866
+
867
+ Complete the information of the device with the information in the configuration group (with precedence of the device).
868
+ The first argument indicates what fields would be merged.
869
+
870
+ ###### Params
871
+
872
+ - fields: Fields that will be merged.
873
+ - defaults: Default values fot each of the fields.
874
+ - deviceData: Device data.
875
+ - configuration: Configuration data.
876
+
877
+ ##### iotagentLib.getConfiguration()
878
+
879
+ ###### Signature
880
+
881
+ ```javascript
882
+ function getConfiguration(resource, apikey, callback)
883
+ ```
884
+
885
+ ###### Description
886
+
887
+ Gets the device group identified by the given (`resource`, `apikey`) pair.
888
+
889
+ ###### Params
890
+
891
+ - resource: representation of the configuration in the IoT Agent (dependent on the protocol) .
892
+ - apikey: special key the devices will present to prove they belong to a particular configuration.
893
+
894
+ ##### iotagentLib.findConfiguration()
895
+
896
+ ###### Signature
897
+
898
+ ```javascript
899
+ function findConfiguration(service, subservice, callback)
900
+ ```
901
+
902
+ ###### Description
903
+
904
+ Find a device group based on its service and subservice.
905
+
906
+ ###### Params
907
+
908
+ - service: name of the service of the configuration.
909
+ - subservice: name of the subservice of the configuration.
910
+
911
+ ##### iotagentLib.getEffectiveApiKey()
912
+
913
+ ###### Signature
914
+
915
+ ```javascript
916
+ function getEffectiveApiKey(service, subservice, type, callback)
917
+ ```
918
+
919
+ ###### Description
920
+
921
+ Get the API Key for the selected service if there is any, or the default API Key if a specific one does not exist.
922
+
923
+ ###### Params
924
+
925
+ - service: Name of the service whose API Key we are retrieving.
926
+ - subservice: Name of the subservice whose API Key we are retrieving.
927
+ - type: Type of the device.
928
+
929
+ ##### iotagentLib.subscribe()
930
+
931
+ ###### Signature
932
+
933
+ ```javascript
934
+ function subscribe(device, triggers, content, callback)
935
+ ```
936
+
937
+ ###### Description
938
+
939
+ Creates a subscription for the IoTA to the entity representing the selected device.
940
+
941
+ ###### Params
942
+
943
+ - device: Object containing all the information about a particular device.
944
+ - triggers: Array with the names of the attributes that would trigger the subscription
945
+ - content: Array with the names of the attributes to retrieve in the notification.
946
+
947
+ ##### iotagentLib.unsubscribe()
948
+
949
+ ###### Signature
950
+
951
+ ```javascript
952
+ function unsubscribe(device, id, callback)
953
+ ```
954
+
955
+ ###### Description
956
+
957
+ Removes a single subscription from the selected device, identified by its ID.
958
+
959
+ ###### Params
960
+
961
+ - `device`: Object containing all the information about a particular device.
962
+ - `id`: ID of the subscription to remove.
963
+
964
+ ##### iotagentLib.ensureSouthboundDomain()
965
+
966
+ ###### Signature
967
+
968
+ ```javascript
969
+ function ensureSouthboundTransaction(context, callback)
970
+ ```
971
+
972
+ ###### Description
973
+
974
+ Ensures that the current operation is executed inside a transaction with all the information needed for the appropriate
975
+ platform logging: start date, transaction ID and correlator in case one is needed. If the function is executed in the
976
+ context of a previous transaction, just the context is changed (and the Transaction ID and start time are kept).
977
+
978
+ ###### Params
979
+
980
+ - context: New context data for the transaction.
981
+
982
+ ##### iotagentLib.finishSouthBoundTransaction()
983
+
984
+ ###### Signature
985
+
986
+ ```javascript
987
+ function finishSouthboundTransaction(callback)
988
+ ```
989
+
990
+ ###### Description
991
+
992
+ Terminates the current transaction, if there is any, cleaning its context.
993
+
994
+ ##### iotagentLib.startServer()
995
+
996
+ ###### Signature
997
+
998
+ ```javascript
999
+ function startServer(newConfig, iotAgent, callback)
1000
+ ```
1001
+
1002
+ ###### Description
1003
+
1004
+ Start the HTTP server either in single-thread or multi-thread (multi-core) based on the value of _multiCore_ variable
1005
+ (described in the [Configuration](../admin.md#configuration) section). If the value is `False` (either was directly
1006
+ specified `False` in the `config.js` or it was not specified and by default is assigned `False`), it is a normal
1007
+ (single-thread) behaviour. Nevertheless, if _multiCore_ is `True`, the IoTAgent is executed in multi-thread environment.
1008
+
1009
+ The number of parallel processes is calculated based on the number of available CPUs. In case of some of the process
1010
+ unexpectedly dead, a new process is created automatically to keep always the maximum of them working in parallel.
1011
+
1012
+ > Note: `startServer()` initializes the server but it does not activate the library. The function in the Node Lib will
1013
+ > call the `iotAgent.start()` in order to complete the activation of the library. Therefore, it is expected that the IoT
1014
+ > Agent implement the `iotAgent.start()` function with the proper invocation to the `iotAgentLib.activate()`.
1015
+
1016
+ ###### Params
1017
+
1018
+ - newConfig: Configuration of the Context Server (described in the [Configuration](../admin.md#configuration)
1019
+ section).
1020
+ - iotAgent: The IoT Agent Objects, used to start the agent.
1021
+ - callback: The callback function.
1022
+
1023
+ ##### iotagentLib.request()
1024
+
1025
+ ###### Signature
1026
+
1027
+ ```javascript
1028
+ function request(options, callback)
1029
+ ```
1030
+
1031
+ ###### Description
1032
+
1033
+ Make a direct HTTP request using the underlying request library (currently [got](https://github.com/sindresorhus/got)),
1034
+ this is useful when creating agents which use an HTTP transport for their southbound commands, and removes the need for
1035
+ the custom IoT Agent to import its own additional request library
1036
+
1037
+ ###### Params
1038
+
1039
+ - options: definition of the request (see
1040
+ [got options](https://github.com/sindresorhus/got/blob/main/documentation/2-options.md) for more details). The
1041
+ following attributes are currently exposed.
1042
+ - `method` - HTTP Method
1043
+ - `searchParams` - query string params
1044
+ - `qs` - alias for query string params
1045
+ - `headers`
1046
+ - `responseType` - either `text` or `json`. `json` is the default
1047
+ - `json` - a supplied JSON object as the request body
1048
+ - `body` - any ASCII text as the request body. It takes precedence over `json` if both are provided at the same
1049
+ time (not recommended).
1050
+ - `url` - the request URL
1051
+ - `uri` - alternative alias for the request URL.
1052
+ - callback: The callback currently returns an `error` Object, the `response` and `body`. The `body` is parsed to a
1053
+ JSON object if the `responseType` is JSON.
1054
+
1055
+ #### Generic middlewares
1056
+
1057
+ This collection of utility middlewares is aimed to be used to north of the IoT Agent Library, as well as in other
1058
+ HTTP-based APIs of the IoT Agents. All the middlewares follow the Express convention of `(req, res, next)` objects, so
1059
+ this information will not be repeated in the descriptions for the middleware functions. All the middlewares can be added
1060
+ to the servers using the standard Express mechanisms.
1061
+
1062
+ ##### iotagentLib.middlewares.handleError()
1063
+
1064
+ ###### Signature
1065
+
1066
+ ```javascript
1067
+ function handleError(error, req, res, next)
1068
+ ```
1069
+
1070
+ ###### Description
1071
+
1072
+ Express middleware for handling errors in the IoTAs. It extracts the code information to return from the error itself
1073
+ returning 500 when no error code has been found.
1074
+
1075
+ ##### iotagentLib.middlewares.traceRequest()
1076
+
1077
+ ###### Signature
1078
+
1079
+ ```javascript
1080
+ function traceRequest(req, res, next)
1081
+ ```
1082
+
1083
+ ###### Description
1084
+
1085
+ Express middleware for tracing the complete request arriving to the IoTA in debug mode.
1086
+
1087
+ ##### iotagentLib.middlewares.changeLogLevel()
1088
+
1089
+ ###### Signature
1090
+
1091
+ ```javascript
1092
+ function changeLogLevel(req, res, next)
1093
+ ```
1094
+
1095
+ ###### Description
1096
+
1097
+ Changes the log level to the one specified in the request.
1098
+
1099
+ ##### iotagentLib.middlewares.ensureType()
1100
+
1101
+ ###### Signature
1102
+
1103
+ ```javascript
1104
+ function ensureType(req, res, next)
1105
+ ```
1106
+
1107
+ ###### Description
1108
+
1109
+ Ensures the request type is one of the supported ones.
1110
+
1111
+ ##### iotagentLib.middlewares.validateJson()
1112
+
1113
+ ###### Signature
1114
+
1115
+ ```javascript
1116
+ function validateJson(template)
1117
+ ```
1118
+
1119
+ ###### Description
1120
+
1121
+ Generates a Middleware that validates incoming requests based on the JSON Schema template passed as a parameter.
1122
+
1123
+ Returns an Express middleware used in request validation with the given template.
1124
+
1125
+ ###### Params
1126
+
1127
+ - _template_: JSON Schema template to validate the request.
1128
+
1129
+ ##### iotagentLib.middlewares.retrieveVersion()
1130
+
1131
+ ###### Signature
1132
+
1133
+ ```javascript
1134
+ function retrieveVersion(req, res, next)
1135
+ ```
1136
+
1137
+ ###### Description
1138
+
1139
+ Middleware that returns all the IoTA information stored in the module.
1140
+
1141
+ ##### iotagentLib.middlewares.setIotaInformation()
1142
+
1143
+ ###### Signature
1144
+
1145
+ ```javascript
1146
+ function setIotaInformation(newIoTAInfo)
1147
+ ```
1148
+
1149
+ ###### Description
1150
+
1151
+ Stores the information about the IoTAgent for further use in the `retrieveVersion()` middleware.
1152
+
1153
+ ###### Params
1154
+
1155
+ - _newIoTAInfo_: Object containing all the IoTA Information.
1156
+
1157
+ ## DB Models (from API document)
1158
+
1159
+ > **WARNING** This section is outdated. DB fields described here may be outdated and not reflect the current
1160
+ > implementation of the IoT Agent Library.
1161
+
1162
+ The following sections describe the models used in the database to store the information about the devices and the
1163
+ config groups.
1164
+
1165
+ ### Config group model
1166
+
1167
+ The table below shows the information held in the Config group provisioning resource and the correspondence between the
1168
+ API resource fields and the same fields in the database model.
1169
+
1170
+ You can find the description of the fields in the config group datamodel of the
1171
+ [API document](../api.md#config-group-datamodel).
1172
+
1173
+ | Payload Field | DB Field | Note |
1174
+ | ------------------------------ | ------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------ |
1175
+ | `service` | `service` | |
1176
+ | `subservice` | `subservice` | |
1177
+ | `resource` | `resource` | |
1178
+ | `apikey` | `apikey` | |
1179
+ | `timestamp` | `timestamp` | |
1180
+ | `entity_type` | `entity_type` | |
1181
+ | `trust` | `trust` | |
1182
+ | `cbHost` | `cbHost` | |
1183
+ | `lazy` | `lazy` | |
1184
+ | `commands` | `commands` | |
1185
+ | `attributes` | `attributes` | |
1186
+ | `static_attributes` | `staticAttributes` | |
1187
+ | `internal_attributes` | `internalAttributes` | |
1188
+ | `explicitAttrs` | `explicitAttrs` | |
1189
+ | `entityNameExp` | `entityNameExp` | |
1190
+ | `ngsiVersion` | `ngsiVersion` | |
1191
+ | `defaultEntityNameConjunction` | `defaultEntityNameConjunction` | optional string value to set default conjunction string used to compose a default `entity_name` when is not provided at device provisioning time. |
1192
+ | `autoprovision` | `autoprovision` | |
1193
+
1194
+ ### Device model
1195
+
1196
+ The table below shows the information held in the Device resource. The table also contains the correspondence between
1197
+ the API resource fields and the same fields in the database model.
1198
+
1199
+ You can find the description of the fields in the config group datamodel of the
1200
+ [API document](../api.md#device-datamodel).
1201
+
1202
+ | Payload Field | DB Field | Note |
1203
+ | --------------------- | -------------------- | :----------------------------------------------------------------------------------------------------------------------------------- |
1204
+ | `device_id` | `id` | |
1205
+ | `service` | `service` | |
1206
+ | `service_path` | `subservice` | |
1207
+ | `entity_name` | `name` | |
1208
+ | `entity_type` | `type` | |
1209
+ | `timezone` | `timezone` | |
1210
+ | `timestamp` | `timestamp` | |
1211
+ | `apikey` | `apikey` | |
1212
+ | `endpoint` | `endpoint` | |
1213
+ | `protocol` | `protocol` | Name of the device protocol, for its use with an IoT Manager. IE: IoTA-UL |
1214
+ | `transport` | `transport` | |
1215
+ | `attributes` | `active` | |
1216
+ | `lazy` | `lazy` | |
1217
+ | `commands` | `commands` | |
1218
+ | `internal_attributes` | `internalAttributes` | List of internal attributes with free format for specific IoT Agent configuration. I.E:LWM2M mappings from object URIs to attributes |
1219
+ | `static_attributes` | `staticAttributes` | |
1220
+ | `explicitAttrs` | `explicitAttrs` | |
1221
+ | `ngsiVersion` | `ngsiVersion` | |
1222
+
1223
+ ## Developing a new IoT Agent
1224
+
1225
+ > **WARNING** This section is outdated. Methods and steps described here may be outdated and not reflect the current
1226
+ > implementation of the IoT Agent Library. You could have a look to other IoT Agents developed using the IoT Agent
1227
+ > Library to get a better idea of how to use it, like the
1228
+ > [IoT Agent JSON](http://www.github.com/telefonicaid/iotagent-json)
1229
+
1230
+ This section's goal is to show how to develop a new IoT Agent step by step. To do so, a simple invented HTTP protocol
1231
+ will be used, so it can be tested with simple command-line instructions as `curl` and `nc`.
1232
+
1233
+ ### Protocol
1234
+
1235
+ The invented protocol will be freely adapted from
1236
+ [Ultralight 2.0](https://github.com/telefonicaid/fiware-IoTAgent-Cplusplus/blob/develop/doc/modules.md#ultra-light-agent).
1237
+ Whenever a device wants to send an update, it will send a request as the following:
1238
+
1239
+ ```bash
1240
+ curl -X GET 'http://127.0.0.1:8080/iot/d?i=ULSensor&k=abc&d=t|15,l|19.6' -i
1241
+ ```
1242
+
1243
+ Where:
1244
+
1245
+ - **i**: is the device ID.
1246
+ - **k**: the API Key for the device's service.
1247
+ - **d**: the data payload, consisting of key-value pairs separated by a pipe (`|`), with each pair separated by comma
1248
+ (`,`);
1249
+
1250
+ ### Requirements
1251
+
1252
+ This tutorial expects a Node.js v8 (at least) installed and working on your machine. It also expects you to have access
1253
+ to a Context Broker (without any security proxies).
1254
+
1255
+ ### Basic IoT Agent
1256
+
1257
+ In this first chapter, we will just develop an IoT Agent with a fully connected North Port. This will send and receive
1258
+ NGSI traffic and can be administered using the IoT Agent's Device Provisioning API. The South Port will remain
1259
+ unconnected and no native protocol traffic will be sent to the devices. This may seem useless (and indeed it is) but it
1260
+ will serve us well on showing the basic steps in the creation of an IoT Agent.
1261
+
1262
+ First of all, we have to create the Node project. Create a folder to hold your project and type the following
1263
+ instruction:
1264
+
1265
+ ```bash
1266
+ npm init
1267
+ ```
1268
+
1269
+ This will create the `package.json` file for our project. Now, add the following lines to your project file:
1270
+
1271
+ ```json
1272
+ "dependencies": {
1273
+ "iotagent-node-lib": "*"
1274
+ },
1275
+
1276
+ ```
1277
+
1278
+ And install the dependencies, executing, as usual:
1279
+
1280
+ ```bash
1281
+ npm install
1282
+ ```
1283
+
1284
+ The first step is to write a configuration file, that will be used to tune the behavior of our IOTA. The contents can be
1285
+ copied from the following example:
1286
+
1287
+ ```javascript
1288
+ var config = {
1289
+ logLevel: 'DEBUG',
1290
+ contextBroker: {
1291
+ host: 'localhost',
1292
+ port: '1026'
1293
+ },
1294
+ server: {
1295
+ port: 4041
1296
+ },
1297
+ deviceRegistry: {
1298
+ type: 'memory'
1299
+ },
1300
+ types: {},
1301
+ service: 'howtoService',
1302
+ subservice: '/howto',
1303
+ providerUrl: 'http://localhost:4041',
1304
+ defaultType: 'Thing'
1305
+ };
1306
+
1307
+ module.exports = config;
1308
+ ```
1309
+
1310
+ Create a `config.js` file with it in the root folder of your project. Remember to change the Context Broker IP to your
1311
+ local Context Broker.
1312
+
1313
+ Now we can begin with the code of our IoT Agent. The very minimum code we need to start an IoT Agent is the following:
1314
+
1315
+ ```javascript
1316
+ var iotAgentLib = require('iotagent-node-lib'),
1317
+ config = require('./config');
1318
+
1319
+ iotAgentLib.activate(config, function (error) {
1320
+ if (error) {
1321
+ console.log('There was an error activating the IOTA');
1322
+ process.exit(1);
1323
+ }
1324
+ });
1325
+ ```
1326
+
1327
+ The IoT Agent is now ready to be used. Execute it with the following command:
1328
+
1329
+ ```bash
1330
+ node index.js
1331
+ ```
1332
+
1333
+ The North Port interface should now be fully functional, i.e.: management of device registrations and configurations.
1334
+
1335
+ ### IoT Agent With Active attributes
1336
+
1337
+ In the previous section we created an IoT Agent that exposed just the North Port interface, but that was pretty useless
1338
+ (aside from its didactic use). In this section we are going to create a simple South Port interface. It's important to
1339
+ remark that the nature of the traffic South of the IoT Agent itself has nothing to do with the creation process of an
1340
+ IoT Agent. Each device protocol will use its own mechanisms and it is up to the IoT Agent developer to find any
1341
+ libraries that would help him in its development. In this example, we will use Express as such library.
1342
+
1343
+ In order to add the Express dependency to your project, add the following line to the `dependencies` section of the
1344
+ `package.json`:
1345
+
1346
+ ```json
1347
+ "express": "*",
1348
+ ```
1349
+
1350
+ The require section would end up like this (the standard `http` module is also needed):
1351
+
1352
+ ```javascript
1353
+ var iotAgentLib = require('iotagent-node-lib'),
1354
+ http = require('http'),
1355
+ express = require('express'),
1356
+ config = require('./config');
1357
+ ```
1358
+
1359
+ And install the dependencies as usual with `npm install`. You will have to require both `express` and `http` in your
1360
+ code as well.
1361
+
1362
+ Now, in order to accept connections in our code, we have to start express first. With this purpose in mind, we will
1363
+ create a new function `initSouthbound()`, that will be called from the initialization code of our IoT Agent:
1364
+
1365
+ ```javascript
1366
+ function initSouthbound(callback) {
1367
+ southboundServer = {
1368
+ server: null,
1369
+ app: express(),
1370
+ router: express.Router()
1371
+ };
1372
+
1373
+ southboundServer.app.set('port', 8080);
1374
+ southboundServer.app.set('host', '0.0.0.0');
1375
+
1376
+ southboundServer.router.get('/iot/d', manageULRequest);
1377
+ southboundServer.server = http.createServer(southboundServer.app);
1378
+ southboundServer.app.use('/', southboundServer.router);
1379
+ southboundServer.server.listen(southboundServer.app.get('port'), southboundServer.app.get('host'), callback);
1380
+ }
1381
+ ```
1382
+
1383
+ This Express code sets up a HTTP server, listening in the 8080 port, that will handle incoming requests targeting path
1384
+ `/iot/d` using the middleware `manageULRequest()`. This middleware will contain all the logic south of the IoT Agent,
1385
+ and the library methods we need in order to progress the information to the Context Broker. The code of this middleware
1386
+ would be as follows:
1387
+
1388
+ ```javascript
1389
+ function manageULRequest(req, res, next) {
1390
+ var values;
1391
+
1392
+ iotAgentLib.retrieveDevice(req.query.i, req.query.k, function (error, device) {
1393
+ if (error) {
1394
+ res.status(404).send({
1395
+ message: "Couldn't find the device: " + JSON.stringify(error)
1396
+ });
1397
+ } else {
1398
+ values = parseUl(req.query.d, device);
1399
+ iotAgentLib.update(device.name, device.type, '', values, device, function (error) {
1400
+ if (error) {
1401
+ res.status(500).send({
1402
+ message: 'Error updating the device'
1403
+ });
1404
+ } else {
1405
+ res.status(200).send({
1406
+ message: 'Device successfully updated'
1407
+ });
1408
+ }
1409
+ });
1410
+ }
1411
+ });
1412
+ }
1413
+ ```
1414
+
1415
+ For this middleware we have made use of a function `parseUl()` that parses the data payload and transforms it in the
1416
+ data object expected by the update function (i.e.: an attribute array with NGSI syntax):
1417
+
1418
+ ```javascript
1419
+ function parseUl(data, device) {
1420
+ function findType(name) {
1421
+ for (var i = 0; i < device.active.length; i++) {
1422
+ if (device.active[i].name === name) {
1423
+ return device.active[i].type;
1424
+ }
1425
+ }
1426
+
1427
+ return null;
1428
+ }
1429
+
1430
+ function createAttribute(element) {
1431
+ var pair = element.split('|'),
1432
+ attribute = {
1433
+ name: pair[0],
1434
+ value: pair[1],
1435
+ type: findType(pair[0])
1436
+ };
1437
+
1438
+ return attribute;
1439
+ }
1440
+
1441
+ return data.split(',').map(createAttribute);
1442
+ }
1443
+ ```
1444
+
1445
+ Here as an example of the output of the function return for the UL payload `t|15,l|19.6`:
1446
+
1447
+ ```json
1448
+ [
1449
+ {
1450
+ "name": "t",
1451
+ "type": "celsius",
1452
+ "value": "15"
1453
+ },
1454
+ {
1455
+ "name": "l",
1456
+ "type": "meters",
1457
+ "value": "19.6"
1458
+ }
1459
+ ]
1460
+ ```
1461
+
1462
+ The last thing to do is to invoke the initialization function inside the IoT Agent startup function. The next excerpt
1463
+ show the modifications in the `activate()` function:
1464
+
1465
+ ```javascript
1466
+ iotAgentLib.activate(config, function (error) {
1467
+ if (error) {
1468
+ console.log('There was an error activating the IOTA');
1469
+ process.exit(1);
1470
+ } else {
1471
+ initSouthbound(function (error) {
1472
+ if (error) {
1473
+ console.log('Could not initialize South bound API due to the following error: %s', error);
1474
+ } else {
1475
+ console.log('Both APIs started successfully');
1476
+ }
1477
+ });
1478
+ }
1479
+ });
1480
+ ```
1481
+
1482
+ Some logs were added in this piece of code to help debugging.
1483
+
1484
+ Once the IOTA is finished the last thing to do is to test it. To do so, launch the IoT Agent and provision a new device
1485
+ (an example for provisioning can be found in the `examples/howtoProvisioning1.json` file). Once the device is
1486
+ provisioned, send a new measure by using the example command:
1487
+
1488
+ ```bash
1489
+ curl -X GET 'http://127.0.0.1:8080/iot/d?i=ULSensor&k=abc&d=t|15,l|19.6' -i
1490
+ ```
1491
+
1492
+ Now you should be able to see the measures in the Context Broker entity of the device.
1493
+
1494
+ ### IOTA With Lazy attributes
1495
+
1496
+ #### Previous considerations
1497
+
1498
+ The IoT Agents also give the possibility for the device to be asked about the value of one of its measures, instead of
1499
+ reporting it. In order to do so, the device must be capable of receiving messages of some kind. In this case, we are
1500
+ going to simulate an HTTP server with `nc` in order to see the values sent by the IOTA. We also have to decide a syntax
1501
+ for the protocol request for asking the device about a measure. For clarity, we will use the same HTTP GET request we
1502
+ used to report a measure, but indicating the attribute to ask instead of the data payload. Something like:
1503
+
1504
+ ```bash
1505
+ curl -X GET 'http://127.0.0.1:9999/iot/d?i=ULSensor&k=abc&q=t,l' -i
1506
+ ```
1507
+
1508
+ In a real implementation, the server will need to know the URL and port where the devices are listening, in order to
1509
+ send the request to the appropriate device. For this example, we will assume that the device is listening in port 9999
1510
+ in localhost. For more complex cases, the mechanism to bind devices to addresses would be IoT-Agent-specific (e.g.: the
1511
+ OMA Lightweight M2M IoT Agent captures the address of the device in the device registration, and stores the
1512
+ device-specific information in a MongoDB document).
1513
+
1514
+ Being lazy attributes of a read/write nature, another syntax has to be declared for updating. This syntax will mimic the
1515
+ one used for updating the server:
1516
+
1517
+ ```
1518
+ curl -X GET 'http://127.0.0.1:9999/iot/d?i=ULSensor&k=abc&d=t|15,l|19.6' -i
1519
+ ```
1520
+
1521
+ Both types of calls to the device will be distinguished by the presence or absence of the `d` and `q` attributes.
1522
+
1523
+ A HTTP request library will be needed in order to make those calls. To this extent, `mikeal/request` library will be
1524
+ used. In order to do so, add the following require statement to the initialization code:
1525
+
1526
+ ```javascript
1527
+ request = require('request');
1528
+ ```
1529
+
1530
+ and add the `request` dependency to the `package.json` file:
1531
+
1532
+ ```json
1533
+ "dependencies": [
1534
+ [...]
1535
+
1536
+ "request": "*",
1537
+
1538
+ ]
1539
+ ```
1540
+
1541
+ The require section should now look like this:
1542
+
1543
+ ```javascript
1544
+ var iotAgentLib = require('iotagent-node-lib'),
1545
+ http = require('http'),
1546
+ express = require('express'),
1547
+ request = require('request'),
1548
+ config = require('./config');
1549
+ ```
1550
+
1551
+ #### Implementation
1552
+
1553
+ ##### QueryContext implementation
1554
+
1555
+ The main step to complete in order to implement the Lazy attributes mechanism in the IoT Agent is to provide handlers
1556
+ for the context provisioning requests. At this point, we should provide two handlers: the `/v2/op/update` and the
1557
+ `/v2/op/query` handlers. To do so, we must first define the handlers themselves:
1558
+
1559
+ ```javascript
1560
+ function queryContextHandler(id, type, service, subservice, attributes, callback) {
1561
+ var options = {
1562
+ url: 'http://127.0.0.1:9999/iot/d',
1563
+ method: 'GET',
1564
+ qs: {
1565
+ q: attributes.join()
1566
+ }
1567
+ };
1568
+
1569
+ request(options, function (error, response, body) {
1570
+ if (error) {
1571
+ callback(error);
1572
+ } else {
1573
+ callback(null, createResponse(id, type, attributes, body));
1574
+ }
1575
+ });
1576
+ }
1577
+ ```
1578
+
1579
+ The queryContext handler is called whenever a `/v2/op/query` request arrives at the North port of the IoT Agent. It is
1580
+ invoked once for each entity requested, passing the entity ID and Type as the parameters, as well as a list of the
1581
+ attributes that are requested. In our case, the handler uses this parameters to compose a request to the device. Once
1582
+ the results of the device are returned, the values are returned to the caller, in the NGSI attribute format.
1583
+
1584
+ In order to format the response from the device in a readable way, we created a `createResponse()` function that maps
1585
+ the values to its correspondent attributes. This function assumes the type of all the attributes is "string" (this will
1586
+ not be the case in a real scenario, where the IoT Agent should retrieve the associated device to guess the type of its
1587
+ attributes). Here is the code for the `createResponse()` function:
1588
+
1589
+ ```javascript
1590
+ function createResponse(id, type, attributes, body) {
1591
+ var values = body.split(','),
1592
+ responses = [];
1593
+
1594
+ for (var i = 0; i < attributes.length; i++) {
1595
+ responses.push({
1596
+ name: attributes[i],
1597
+ type: 'string',
1598
+ value: values[i]
1599
+ });
1600
+ }
1601
+
1602
+ return {
1603
+ id: id,
1604
+ type: type,
1605
+ attributes: responses
1606
+ };
1607
+ }
1608
+ ```
1609
+
1610
+ ##### UpdateContext implementation
1611
+
1612
+ ```javascript
1613
+ function updateContextHandler(id, type, service, subservice, attributes, callback) {
1614
+ var options = {
1615
+ url: 'http://127.0.0.1:9999/iot/d',
1616
+ method: 'GET',
1617
+ qs: {
1618
+ d: createQueryFromAttributes(attributes)
1619
+ }
1620
+ };
1621
+
1622
+ request(options, function (error, response, body) {
1623
+ if (error) {
1624
+ callback(error);
1625
+ } else {
1626
+ callback(null, {
1627
+ id: id,
1628
+ type: type,
1629
+ attributes: attributes
1630
+ });
1631
+ }
1632
+ });
1633
+ }
1634
+ ```
1635
+
1636
+ The updateContext handler deals with the modification requests that arrive at the North Port of the IoT Agent via
1637
+ `/v2/op/update`. It is invoked once for each entity requested (note that a single request can contain multiple entity
1638
+ updates), with the same parameters used in the queryContext handler. The only difference is the value of the attributes
1639
+ array, now containing a list of attribute objects, each containing name, type and value. The handler must also make use
1640
+ of the callback to return a list of updated attributes.
1641
+
1642
+ For this handler we have used a helper function called `createQueryFromAttributes()`, that transforms the NGSI
1643
+ representation of the attributes to the UL type expected by the device:
1644
+
1645
+ ```javascript
1646
+ function createQueryFromAttributes(attributes) {
1647
+ var query = '';
1648
+
1649
+ for (var i in attributes) {
1650
+ query += attributes[i].name + '|' + attributes[i].value;
1651
+
1652
+ if (i != attributes.length - 1) {
1653
+ query += ',';
1654
+ }
1655
+ }
1656
+
1657
+ return query;
1658
+ }
1659
+ ```
1660
+
1661
+ ##### Handler registration
1662
+
1663
+ Once both handlers have been defined, they have to be registered in the IoT Agent, adding the following code to the
1664
+ setup function:
1665
+
1666
+ ```javascript
1667
+ iotAgentLib.setDataUpdateHandler(updateContextHandler);
1668
+ iotAgentLib.setDataQueryHandler(queryContextHandler);
1669
+ ```
1670
+
1671
+ Where necessary, additional handlers to deal with command actuations and merge-patch operations may also be added when
1672
+ necessary.
1673
+
1674
+ ```javascript
1675
+ iotAgentLib.setCommandHandler(commandHandler);
1676
+ iotAgentLib.setMergePatchHandler(mergePatchHandler);
1677
+ ```
1678
+
1679
+ ##### IOTA Testing
1680
+
1681
+ In order to test it, we need to create an HTTP server simulating the device. The quickest way to do that may be using
1682
+ netcat. In order to start it just run the following command from the command-line (Linux and Mac only):
1683
+
1684
+ ```bash
1685
+ nc -l 9999
1686
+ ```
1687
+
1688
+ This will open a simple TCP server listening on port `9999`, where the requests from the IoT Agent will be printed. In
1689
+ order for the complete workflow to work (and to receive the response in the application side), the HTTP response has to
1690
+ be written in the `nc` console (although for testing purposes this is not needed).
1691
+
1692
+ While netcat is great to test simple connectivity, you will need something just a bit more complex to get the complete
1693
+ scenario working (at least without the need to be incredibly fast sending your response). In order to do so, a simple
1694
+ echo server was created, that answers 42 to any query to its `/iot/d` path. You can use it to test your attributes one
1695
+ by one (or you can modify it to accept more requests and give more complex responses). Copy the
1696
+ [Echo Server script](echo.js) to the same folder of your IoTAgent (as it uses the same dependencies). In order to run
1697
+ the echo server, just execute the following command:
1698
+
1699
+ ```bash
1700
+ node echo.js
1701
+ ```
1702
+
1703
+ Once the mock server has been started (either `nc` or the `echo` server), proceed with the following steps to test your
1704
+ implementation:
1705
+
1706
+ 1. Provision a device with two lazy attributes. The following request can be used as an example:
1707
+
1708
+ ```text
1709
+ POST /iot/devices HTTP/1.1
1710
+ Host: localhost:4041
1711
+ Content-Type: application/json
1712
+ fiware-service: howtoserv
1713
+ fiware-servicepath: /test
1714
+ Cache-Control: no-cache
1715
+ Postman-Token: 993ac66b-72da-9e96-ab46-779677a5896a
1716
+
1717
+ {
1718
+ "devices": [
1719
+ {
1720
+ "device_id": "ULSensor",
1721
+ "entity_name": "Sensor01",
1722
+ "entity_type": "BasicULSensor",
1723
+ "lazy": [
1724
+ {
1725
+ "name": "t",
1726
+ "type": "celsius"
1727
+ },
1728
+ {
1729
+ "name": "l",
1730
+ "type": "meters"
1731
+ }
1732
+ ],
1733
+ "attributes": [
1734
+ ]
1735
+ }
1736
+ ]
1737
+ }
1738
+ ```
1739
+
1740
+ 2. Execute a `/v2/op/query` or `/v2/op/update` against one of the entity attributes (use a NGSI client of curl command).
1741
+
1742
+ ```text
1743
+ POST /v2/op/query HTTP/1.1
1744
+ Host: localhost:1026
1745
+ Content-Type: application/json
1746
+ Accept: application/json
1747
+ Fiware-Service: howtoserv
1748
+ Fiware-ServicePath: /test
1749
+ Cache-Control: no-cache
1750
+
1751
+ {
1752
+ entities: [
1753
+ {
1754
+ id: 'Light:light1'
1755
+ }
1756
+ ],
1757
+ attrs: ['dimming']
1758
+ }
1759
+ ```
1760
+
1761
+ 3. Check the received request in the nc console is the expected one.
1762
+
1763
+ 4. (In case you use netcat). Answer the request with an appropriate HTTP response and check the result of the
1764
+ `/v2/op/query` or `/v2/op/update` request is the expected one. An example of HTTP response, for a query to the `t`
1765
+ and `l` attributes would be:
1766
+
1767
+ ```text
1768
+ HTTP/1.0 200 OK
1769
+ Content-Type: text/plain
1770
+ Content-Length: 3
1771
+
1772
+ 5,6
1773
+ ```
1774
+
1775
+ This same response can be used both for updates and queries for testing purposes (even though in the former the body
1776
+ won't be read).
1777
+
1778
+ ### IoT Agent in multi-thread mode
1779
+
1780
+ It is possible that an IoT Agent can be executed in multi-thread approach, which will increase the number of
1781
+ request/seconds that can be manage by the server. It's important to remark that the nature of this functionality in
1782
+ included in the IoT Agent Node Lib but it is not mandatory that you activate this functionality. In this example, we
1783
+ will see how to use this functionality to deploy an IoT Agent in multi-thread environment.
1784
+
1785
+ In order to activate the functionality, you have two options, configure the `config.js` file to add the following line:
1786
+
1787
+ ```javascript
1788
+ /**
1789
+ * flag indicating whether the node server will be executed in multi-core option (true) or it will be a
1790
+ * single-thread one (false).
1791
+ */
1792
+ config.multiCore = true;
1793
+ ```
1794
+
1795
+ or you can define the proper IOTA_MULTI_CORE environment variable. By default, the first choice is the environment
1796
+ variable and afterward the value of the multiCore in the `config.js` file. The require section would end up like this
1797
+ (the standard `http` module is also needed):
1798
+
1799
+ ```javascript
1800
+ var iotAgent = require('../lib/iotagent-implementation'),
1801
+ iotAgentLib = require('iotagent-node-lib'),
1802
+ config = require('./config');
1803
+ ```
1804
+
1805
+ It is important to mention the purpose of the `iotAgent` variable. It is the proper implementation of the IoT Agent
1806
+ based on the IoT Agent Node Lib. We will need this variable just to make a callback to the corresponding `start()`
1807
+ process from the library. The variable `config` is used to get details of the configuration file and send that
1808
+ information to the Node Lib. The Node Lib will take the decision of single-thread or multi-thread execution base on the
1809
+ value of `config.multiCore` attribute.
1810
+
1811
+ Finally, we can call the corresponding [iotagentLib.startServer()](#iotagentlibstartserver) like the following code with
1812
+ a callback function to show details about any error during the execution or just print the message about starting the
1813
+ IoTAgent:
1814
+
1815
+ ```javascript
1816
+ iotAgentLib.startServer(config, iotAgent, function (error) {
1817
+ if (error) {
1818
+ console.log(context, 'Error starting IoT Agent: [%s] Exiting process', error);
1819
+ } else {
1820
+ console.log(context, 'IoT Agent started');
1821
+ }
1822
+ });
1823
+ ```
1824
+
1825
+ > Note: `startServer()` initializes the server but it does not activate the library. The function in the Node Lib will
1826
+ > call the `iotAgent.start()` in order to complete the activation of the library. Therefore, it is expected that the IoT
1827
+ > Agent implement the `iotAgent.start()` function with the proper invocation to the `iotAgentLib.activate()`.
1828
+
1829
+ ### Configuration management
1830
+
1831
+ For some IoT Agents, it will be useful to know what devices or configurations were registered in the Agent, or to do
1832
+ some actions whenever a new device is registered. All this configuration and provisioning actions can be performed using
1833
+ two mechanisms: the provisioning handlers and the provisioning API.
1834
+
1835
+ #### Provisioning handlers
1836
+
1837
+ The handlers provide a way for the IoT Agent to act whenever a new device, or configuration is provisioned. This can be
1838
+ used for registering the device in external services, for storing important information about the device, or to listen
1839
+ in new ports in the case of new configuration. For the simple example we are developing, we will just print the
1840
+ information we are receiving whenever a new device or configuration is provisioned.
1841
+
1842
+ We need to complete two further steps to have a working set of provisioning handlers. First of all, defining the
1843
+ handlers themselves. Here we can see the definition of the configuration handler:
1844
+
1845
+ ```javascript
1846
+ function configurationHandler(configuration, callback) {
1847
+ console.log('\n\n* REGISTERING A NEW CONFIGURATION:\n%s\n\n', JSON.stringify(configuration, null, 4));
1848
+ callback(null, configuration);
1849
+ }
1850
+ ```
1851
+
1852
+ As we can see, the handlers receive the device or configuration that is being provisioned, as well as a callback. The
1853
+ handler MUST call the callback once in order for the IOTA to work properly. If an error is passed as a parameter to the
1854
+ callback, the provisioning will be aborted. If no error is passed, the provisioning process will continue. This
1855
+ mechanism can be used to implement security mechanisms or to filter the provisioning of devices to the IoT Agent.
1856
+
1857
+ Note also that the same `device` or `configuration` object is passed along to the callback. This lets the IoT Agent
1858
+ change some of the values provisioned by the user, to add or restrict information in the provisioning. To test this
1859
+ feature, let's use the provisioning handler to change the value of the type of the provisioning device to
1860
+ `CertifiedType` (reflecting some validation process performed on the provisioning):
1861
+
1862
+ ```javascript
1863
+ function provisioningHandler(device, callback) {
1864
+ console.log('\n\n* REGISTERING A NEW DEVICE:\n%s\n\n', JSON.stringify(device, null, 4));
1865
+ device.type = 'CertifiedType';
1866
+ callback(null, device);
1867
+ }
1868
+ ```
1869
+
1870
+ Once the handlers are defined, the new set of handlers has to be registered into the IoT Agent:
1871
+
1872
+ ```javascript
1873
+ iotAgentLib.setConfigurationHandler(configurationHandler);
1874
+ iotAgentLib.setProvisioningHandler(provisioningHandler);
1875
+ ```
1876
+
1877
+ Now we can test our implementation by sending provisioning requests to the North Port of the IoT Agent. If we provision
1878
+ a new device into the platform, and then we ask for the list of provisioned devices, we shall see the type of the
1879
+ provisioned device has changed to `CertifiedType`.