iotagent-node-lib 3.2.0 → 3.4.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.
- package/.github/ISSUE_TEMPLATE/bug_report.yml +134 -0
- package/.github/ISSUE_TEMPLATE/config.yml +16 -0
- package/.github/ISSUE_TEMPLATE/feature_request.yml +55 -0
- package/.github/advanced-issue-labeler.yml +30 -0
- package/.github/workflows/issue-labeler.yml +43 -0
- package/README.md +10 -11
- package/doc/README.md +16 -0
- package/doc/admin.md +565 -0
- package/doc/api.md +32 -85
- package/doc/deprecated.md +16 -10
- package/doc/{architecture.md → devel/architecture.md} +3 -3
- package/doc/{Contribution.md → devel/contribution-guidelines.md} +43 -35
- package/doc/devel/development.md +1879 -0
- package/doc/{northboundinteractions.md → devel/northboundinteractions.md} +18 -33
- package/doc/index.md +3 -5
- package/doc/requirements.txt +1 -1
- package/docker/Mosquitto/Dockerfile +1 -1
- package/docker/Mosquitto/README.md +1 -0
- package/lib/commonConfig.js +0 -5
- package/lib/fiware-iotagent-lib.js +1 -1
- package/lib/jexlTranformsMap.js +2 -1
- package/lib/model/Device.js +0 -1
- package/lib/model/Group.js +0 -1
- package/lib/model/dbConn.js +1 -7
- package/lib/plugins/jexlParser.js +1 -1
- package/lib/request-shim.js +2 -2
- package/lib/services/commands/commandService.js +1 -1
- package/lib/services/common/genericMiddleware.js +1 -1
- package/lib/services/common/iotManagerService.js +0 -1
- package/lib/services/devices/deviceRegistryMemory.js +2 -2
- package/lib/services/devices/deviceRegistryMongoDB.js +32 -19
- package/lib/services/devices/deviceService.js +44 -43
- package/lib/services/devices/devices-NGSI-LD.js +14 -2
- package/lib/services/devices/devices-NGSI-mixed.js +0 -2
- package/lib/services/devices/devices-NGSI-v2.js +23 -104
- package/lib/services/groups/groupService.js +1 -1
- package/lib/services/ngsi/entities-NGSI-LD.js +3 -3
- package/lib/services/ngsi/entities-NGSI-v2.js +28 -19
- package/lib/services/northBound/deviceProvisioningServer.js +14 -8
- package/lib/templates/createDevice.json +0 -4
- package/lib/templates/createDeviceLax.json +0 -4
- package/lib/templates/deviceGroup.json +1 -5
- package/lib/templates/updateDevice.json +4 -0
- package/lib/templates/updateDeviceLax.json +11 -0
- package/mkdocs.yml +6 -11
- package/package.json +3 -3
- package/scripts/legacy_expression_tool/README.md +280 -0
- package/scripts/legacy_expression_tool/legacy_expression_tool.py +423 -0
- package/scripts/legacy_expression_tool/requirements.txt +3 -0
- package/test/unit/examples/deviceProvisioningRequests/provisionMinimumDevice4.json +0 -1
- package/test/unit/general/contextBrokerKeystoneSecurityAccess-test.js +5 -15
- package/test/unit/mongodb/mongodb-registry-test.js +1 -1
- package/test/unit/ngsi-ld/general/contextBrokerOAuthSecurityAccess-test.js +66 -65
- package/test/unit/ngsi-ld/general/https-support-test.js +1 -1
- package/test/unit/ngsi-ld/lazyAndCommands/command-test.js +8 -7
- package/test/unit/ngsi-ld/lazyAndCommands/merge-patch-test.js +31 -30
- package/test/unit/ngsi-ld/lazyAndCommands/polling-commands-test.js +12 -11
- package/test/unit/ngsi-ld/ngsiService/subscriptions-test.js +41 -39
- package/test/unit/ngsi-ld/provisioning/device-provisioning-api_test.js +122 -122
- package/test/unit/ngsi-ld/provisioning/device-registration_test.js +28 -28
- package/test/unit/ngsi-ld/provisioning/device-update-registration_test.js +18 -17
- package/test/unit/ngsi-ld/provisioning/singleConfigurationMode-test.js +7 -7
- package/test/unit/ngsi-ld/provisioning/updateProvisionedDevices-test.js +8 -7
- package/test/unit/ngsi-mixed/provisioning/ngsi-versioning-test.js +33 -37
- package/test/unit/ngsiv2/examples/contextRequests/updateContext.json +2 -0
- package/test/unit/ngsiv2/examples/contextRequests/updateContext1.json +3 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContext3WithStatic.json +2 -0
- package/test/unit/ngsiv2/examples/contextRequests/updateContext4.json +4 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContext5.json +12 -0
- package/test/unit/ngsiv2/examples/contextRequests/updateContext6.json +12 -0
- package/test/unit/ngsiv2/examples/contextRequests/updateContextAliasPlugin1.json +2 -0
- package/test/unit/ngsiv2/examples/contextRequests/updateContextAliasPlugin2.json +3 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextAliasPlugin3.json +3 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextAliasPlugin4.json +3 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextAliasPlugin5.json +3 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextAliasPlugin6.json +3 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextAliasPlugin7.json +3 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextAliasPlugin8.json +3 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextAliasPlugin9.json +3 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextAutocast1.json +2 -0
- package/test/unit/ngsiv2/examples/contextRequests/updateContextAutocast2.json +2 -0
- package/test/unit/ngsiv2/examples/contextRequests/updateContextAutocast3.json +3 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextAutocast4.json +3 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextAutocast5.json +3 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextAutocast6.json +3 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextAutocast7.json +3 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextCommandError.json +3 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextCommandExpired.json +3 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextCommandFinish.json +3 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextCommandStatus.json +2 -0
- package/test/unit/ngsiv2/examples/contextRequests/updateContextCommandStatus2.json +2 -0
- package/test/unit/ngsiv2/examples/contextRequests/updateContextCompressTimestamp1.json +3 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextCompressTimestamp2.json +3 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin1.json +2 -12
- package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin11.json +2 -4
- package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin12.json +2 -4
- package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin13.json +3 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin2.json +2 -12
- package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin29.json +2 -12
- package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin3.json +2 -4
- package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin30.json +2 -0
- package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin31.json +2 -0
- package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin32.json +2 -0
- package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin33.json +2 -0
- package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin34.json +2 -0
- package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin35.json +2 -0
- package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin36.json +1 -0
- package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin4.json +2 -0
- package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin40.json +1 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin41.json +1 -10
- package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin5.json +2 -4
- package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin6.json +2 -4
- package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin7.json +2 -4
- package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin8.json +2 -12
- package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin9.json +2 -4
- package/test/unit/ngsiv2/examples/contextRequests/updateContextExpressionSkip.json +12 -0
- package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityJexlExpressionPlugin1.json +1 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin1.json +1 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin10.json +1 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin11.json +1 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin12.json +1 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin13.json +1 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin14.json +1 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin15.json +1 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin16.json +1 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin17.json +1 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin2.json +1 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin25.json +2 -6
- package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin3.json +1 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin4.json +1 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin5.json +1 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin6.json +1 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin7.json +1 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin8.json +1 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin9.json +1 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityTimestampPlugin1.json +1 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityTimestampPlugin2.json +1 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityTimestampPlugin3.json +1 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextMultientityTimestampPlugin4.json +2 -0
- package/test/unit/ngsiv2/examples/contextRequests/updateContextProcessTimestamp.json +2 -0
- package/test/unit/ngsiv2/examples/contextRequests/updateContextStaticAttributes.json +2 -0
- package/test/unit/ngsiv2/examples/contextRequests/updateContextStaticAttributesMetadata.json +3 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextTimestamp.json +3 -1
- package/test/unit/ngsiv2/examples/contextRequests/updateContextTimestampFalse.json +12 -0
- package/test/unit/ngsiv2/examples/contextRequests/updateContextTimestampFalseTimeInstant.json +12 -0
- package/test/unit/ngsiv2/examples/contextRequests/updateContextTimestampOverride.json +2 -0
- package/test/unit/ngsiv2/examples/contextRequests/updateContextTimestampOverrideWithoutMilis.json +2 -0
- package/test/unit/ngsiv2/examples/contextRequests/updateContextTimestampTimezone.json +3 -1
- package/test/unit/ngsiv2/expressions/jexlBasedTransformations-test.js +144 -85
- package/test/unit/ngsiv2/general/contextBrokerOAuthSecurityAccess-test.js +20 -53
- package/test/unit/ngsiv2/general/https-support-test.js +2 -6
- package/test/unit/ngsiv2/lazyAndCommands/command-test.js +4 -10
- package/test/unit/ngsiv2/lazyAndCommands/polling-commands-test.js +8 -24
- package/test/unit/ngsiv2/ngsiService/active-devices-test.js +146 -65
- package/test/unit/ngsiv2/ngsiService/autocast-test.js +14 -21
- package/test/unit/ngsiv2/ngsiService/staticAttributes-test.js +3 -5
- package/test/unit/ngsiv2/ngsiService/subscriptions-test.js +11 -20
- package/test/unit/ngsiv2/plugins/alias-plugin_test.js +20 -30
- package/test/unit/ngsiv2/plugins/compress-timestamp-plugin_test.js +4 -6
- package/test/unit/ngsiv2/plugins/custom-plugin_test.js +1 -2
- package/test/unit/ngsiv2/plugins/multientity-plugin_test.js +3 -5
- package/test/unit/ngsiv2/plugins/timestamp-processing-plugin_test.js +2 -3
- package/test/unit/ngsiv2/provisioning/device-group-api-test.js +2 -3
- package/test/unit/ngsiv2/provisioning/device-provisioning-api_test.js +13 -156
- package/test/unit/ngsiv2/provisioning/device-registration_test.js +9 -13
- package/test/unit/ngsiv2/provisioning/device-update-registration_test.js +4 -10
- package/test/unit/ngsiv2/provisioning/singleConfigurationMode-test.js +0 -11
- package/test/unit/ngsiv2/provisioning/updateProvisionedDevices-test.js +0 -8
- package/test/unit/plugins/capture-provision-inPlugins_test.js +0 -6
- package/.nyc_output/33364de2-1199-4ec2-b33c-cae063ef8cc4.json +0 -1
- package/.nyc_output/processinfo/33364de2-1199-4ec2-b33c-cae063ef8cc4.json +0 -1
- package/.nyc_output/processinfo/index.json +0 -1
- package/doc/config-basic-example.js +0 -20
- package/doc/development.md +0 -285
- package/doc/howto.md +0 -645
- package/doc/installationguide.md +0 -370
- package/doc/operations.md +0 -127
- package/doc/usermanual.md +0 -900
- package/lib/plugins/bidirectionalData.js +0 -356
- package/test/unit/ngsi-ld/plugins/bidirectional-plugin_test.js +0 -697
- package/test/unit/ngsiv2/plugins/bidirectional-plugin_test.js +0 -599
- /package/doc/{NorthboundInteractions.postman_collection → devel/NorthboundInteractions.postman_collection} +0 -0
- /package/doc/{echo.js → devel/echo.js} +0 -0
- /package/doc/{finalResult.js → devel/finalResult.js} +0 -0
|
@@ -145,7 +145,7 @@ This **NGSI-v2** payload is associated to an update operation (POST `/v2/op/upda
|
|
|
145
145
|
}
|
|
146
146
|
}
|
|
147
147
|
],
|
|
148
|
-
"actionType": "
|
|
148
|
+
"actionType": "append"
|
|
149
149
|
}
|
|
150
150
|
```
|
|
151
151
|
|
|
@@ -155,9 +155,8 @@ As it can be seen in the example, the payload is a JSON Object with the followin
|
|
|
155
155
|
with the information needed to identify the target entity `id` and `type` attributes. The `entities` attribute is an
|
|
156
156
|
array, so a single update context batch operation can be used to update multiple devices
|
|
157
157
|
|
|
158
|
-
- An `actionType` indicating the type of update
|
|
159
|
-
|
|
160
|
-
resources don't exist.
|
|
158
|
+
- An `actionType` indicating the type of update. It has the value `"append"` the appropriate entity and attributes
|
|
159
|
+
will be created if the don't exist.
|
|
161
160
|
|
|
162
161
|
The equivalent **NGSI-LD** payload is associated to an update operation (PATCH `/ngsi-ld/v1/entities/<entity>/attrs/`).
|
|
163
162
|
|
|
@@ -427,7 +426,7 @@ Be sure to understand how each scenario works (as shown in the theory section) b
|
|
|
427
426
|
Along this document, IP addresses and passwords will be concealed. Substitute the concealed passwords by your own.
|
|
428
427
|
|
|
429
428
|
A postman collection is available alongside this document to help in reproducing this examples. It can be found
|
|
430
|
-
[here](
|
|
429
|
+
[here](NorthboundInteractions.postman_collection).
|
|
431
430
|
|
|
432
431
|
### Retrieving a token
|
|
433
432
|
|
|
@@ -507,8 +506,8 @@ curl -X POST -H "Content-Type: application/json" -H "Accept: application/json" -
|
|
|
507
506
|
}
|
|
508
507
|
}
|
|
509
508
|
],
|
|
510
|
-
"actionType": "
|
|
511
|
-
} ' "https://<platform-ip>:
|
|
509
|
+
"actionType": "append"
|
|
510
|
+
} ' "https://<platform-ip>:1026/v2/op/update"
|
|
512
511
|
```
|
|
513
512
|
|
|
514
513
|
If the request is correct, the Context Broker will reply with the following R1 response (200 OK):
|
|
@@ -554,7 +553,7 @@ curl -X POST -H "Content-Type: application/json" -H "Accept: application/json" -
|
|
|
554
553
|
}
|
|
555
554
|
],
|
|
556
555
|
"attrs": ["temperature","pressure"]
|
|
557
|
-
}' "https://<platform-ip>:
|
|
556
|
+
}' "https://<platform-ip>:1026/v2/op/query"
|
|
558
557
|
```
|
|
559
558
|
|
|
560
559
|
The Context Broker will reply with the updated data values in R2 format (200 OK):
|
|
@@ -600,20 +599,6 @@ It is worth mentioning that the Context Broker will reply with a 200 OK status c
|
|
|
600
599
|
refer to transport protocol level errors, while the status codes inside of a payload give information about the
|
|
601
600
|
application level protocol.
|
|
602
601
|
|
|
603
|
-
The example shows an error updating an non-existent attribute (due to the use of UPDATE instead of APPEND).
|
|
604
|
-
|
|
605
|
-
The following error payload is also valid in standard NGSI:
|
|
606
|
-
|
|
607
|
-
```json
|
|
608
|
-
{
|
|
609
|
-
"error": "NotFound",
|
|
610
|
-
"description": "The requested entity has not been found. Check type and id"
|
|
611
|
-
}
|
|
612
|
-
```
|
|
613
|
-
|
|
614
|
-
Different kinds of errors can return their information in different formats, so NGSI implementations should check for
|
|
615
|
-
the existence of both.
|
|
616
|
-
|
|
617
602
|
### Scenario 2: lazy attributes (happy path)
|
|
618
603
|
|
|
619
604
|
Scenario 2 relies on the Context Provider mechanism of the Context Broker. For this scenario to work, the IoTAgent must
|
|
@@ -639,7 +624,7 @@ curl -X POST -H "Content-Type: application/json" -H "Accept: application/json" -
|
|
|
639
624
|
}
|
|
640
625
|
}
|
|
641
626
|
}
|
|
642
|
-
' "https://<platform-ip>:
|
|
627
|
+
' "https://<platform-ip>:1026/v2/registrations"
|
|
643
628
|
```
|
|
644
629
|
|
|
645
630
|
If everything has gone OK, the Context Broker will return the following payload:
|
|
@@ -669,7 +654,7 @@ curl -X POST -H "Content-Type: application/json" -H "Accept: application/json" -
|
|
|
669
654
|
}
|
|
670
655
|
],
|
|
671
656
|
"attrs": ["batteryLevel"]
|
|
672
|
-
}' "https://<platform-ip>:
|
|
657
|
+
}' "https://<platform-ip>:1026/v2/op/query"
|
|
673
658
|
```
|
|
674
659
|
|
|
675
660
|
The Context Broker receives this request and detects that it can be served by a Context Provider (the IoT Agent), so it
|
|
@@ -772,7 +757,7 @@ curl -X POST -H "Content-Type: application/json" -H "Accept: application/json" -
|
|
|
772
757
|
}
|
|
773
758
|
],
|
|
774
759
|
"duration": "P1M"
|
|
775
|
-
}' "https://<platform-ip>:
|
|
760
|
+
}' "https://<platform-ip>:1026/v2/registrations"
|
|
776
761
|
```
|
|
777
762
|
|
|
778
763
|
If everything has gone OK, the Context Broker will return the following payload:
|
|
@@ -806,8 +791,8 @@ curl -X POST -H "Content-Type: application/json" -H "Accept: application/json" -
|
|
|
806
791
|
}
|
|
807
792
|
}
|
|
808
793
|
],
|
|
809
|
-
"updateAction": "
|
|
810
|
-
} ' "https://<platform-ip>:
|
|
794
|
+
"updateAction": "append"
|
|
795
|
+
} ' "https://<platform-ip>:1026/v2/op/update"
|
|
811
796
|
```
|
|
812
797
|
|
|
813
798
|
The Context Broker receives this command and detects that it can be served by a Context Provider (the IoT Agent), so it
|
|
@@ -836,7 +821,7 @@ Fiware-Correlator: 9cae9496-8ec7-11e6-80fc-fa163e734aab
|
|
|
836
821
|
}
|
|
837
822
|
}
|
|
838
823
|
],
|
|
839
|
-
"updateAction" : "
|
|
824
|
+
"updateAction" : "append"
|
|
840
825
|
}
|
|
841
826
|
```
|
|
842
827
|
|
|
@@ -900,8 +885,8 @@ curl -X POST -H "Content-Type: application/json" -H "Accept: application/json" -
|
|
|
900
885
|
}
|
|
901
886
|
}
|
|
902
887
|
],
|
|
903
|
-
"actionType": "
|
|
904
|
-
} ' "https://<platform-ip>:
|
|
888
|
+
"actionType": "append"
|
|
889
|
+
} ' "https://<platform-ip>:1026/v2/op/update"
|
|
905
890
|
```
|
|
906
891
|
|
|
907
892
|
This update does not modify the original command attribute, but two auxiliary attributes, that are not provided by the
|
|
@@ -948,7 +933,7 @@ curl -X POST -H "Content-Type: application/json" -H "Accept: application/json" -
|
|
|
948
933
|
"switch_info",
|
|
949
934
|
"switch_status"
|
|
950
935
|
]
|
|
951
|
-
}' "https://<platform-ip>:
|
|
936
|
+
}' "https://<platform-ip>:1026/v2/op/query"
|
|
952
937
|
```
|
|
953
938
|
|
|
954
939
|
The Context Broker replies with all the desired data, in R2 format (200 OK):
|
|
@@ -994,8 +979,8 @@ curl -X POST -H "Content-Type: application/json" -H "Accept: application/json" -
|
|
|
994
979
|
}
|
|
995
980
|
}
|
|
996
981
|
],
|
|
997
|
-
"actionType": "
|
|
998
|
-
} ' "https://<platform-ip>:
|
|
982
|
+
"actionType": "append"
|
|
983
|
+
} ' "https://<platform-ip>:1026/v2/op/update"
|
|
999
984
|
```
|
|
1000
985
|
|
|
1001
986
|
In this case, the Context Broker reply with the following response (200 OK):
|
package/doc/index.md
CHANGED
|
@@ -11,8 +11,8 @@ Broker using their own native protocols. IoT Agents should also be able to deal
|
|
|
11
11
|
platform (authentication and authorization of the channel) and provide other common services to the device programmer.
|
|
12
12
|
|
|
13
13
|
Github's [README.md](https://github.com/telefonicaid/iotagent-node-lib/blob/master/README.md) provides a good
|
|
14
|
-
documentation summary. The [
|
|
15
|
-
topics.
|
|
14
|
+
documentation summary. The [API reference](doc/api.md) and the [Development documentation](devel/development.md) cover
|
|
15
|
+
more advanced topics.
|
|
16
16
|
|
|
17
17
|
## Background
|
|
18
18
|
|
|
@@ -26,8 +26,6 @@ functions.
|
|
|
26
26
|
communications are left to the library.
|
|
27
27
|
- Standardized OAuth2-based security is available to enable each IoT Agent to connect to several common Identity
|
|
28
28
|
Managers (e.g. Keystone and Keyrock) so that communications can be restricted to trusted components.
|
|
29
|
-
- A series of additional plugins are offered where necessary to allow for expression parsing, attribute aliasing and
|
|
30
|
-
the processing of timestamp metadata.
|
|
31
29
|
|
|
32
30
|
Each individual IoT Agent offers is driven by a `config.js` configuration file contains explicit custom settings based
|
|
33
31
|
on the protocol and payload the IoT Agent is translating. It will also contain some common flags for common
|
|
@@ -51,5 +49,5 @@ IoT Agent
|
|
|
51
49
|
In order to use the library within your own IoT Agent, you must first you require it before use:
|
|
52
50
|
|
|
53
51
|
```javascript
|
|
54
|
-
const iotagentLib = require(
|
|
52
|
+
const iotagentLib = require('iotagent-node-lib');
|
|
55
53
|
```
|
package/doc/requirements.txt
CHANGED
|
@@ -2,6 +2,7 @@ Thi directory containts the Dockerfile (and associated files) for a container of
|
|
|
2
2
|
This container is provide as a help for users to test with MQTT, but it is just an auxiliary material in this repository.
|
|
3
3
|
|
|
4
4
|
The following releases matches with eclipse-mosquitto version:
|
|
5
|
+
- 2.1.0 uses mosquitto-2.0.11 from Debian 12
|
|
5
6
|
- 2.0.0 uses mosquitto-2.0.11 from Debian 11
|
|
6
7
|
- 1.6.0 uses mosquitto-1.6.10-1.el7.x86_64 (from Centos7)
|
|
7
8
|
- 1.5.0 uses mosquitto-1.6.10-1.el7.x86_64 (from Centos7)
|
package/lib/commonConfig.js
CHANGED
|
@@ -149,7 +149,6 @@ function processEnvironmentVariables() {
|
|
|
149
149
|
'IOTA_MONGO_USER',
|
|
150
150
|
'IOTA_MONGO_RETRY_TIME',
|
|
151
151
|
'IOTA_SINGLE_MODE',
|
|
152
|
-
'IOTA_APPEND_MODE',
|
|
153
152
|
'IOTA_POLLING_EXPIRATION',
|
|
154
153
|
'IOTA_POLLING_DAEMON_FREQ',
|
|
155
154
|
'IOTA_MULTI_CORE',
|
|
@@ -450,10 +449,6 @@ function processEnvironmentVariables() {
|
|
|
450
449
|
config.singleConfigurationMode = process.env.IOTA_SINGLE_MODE === 'true';
|
|
451
450
|
}
|
|
452
451
|
|
|
453
|
-
if (process.env.IOTA_APPEND_MODE) {
|
|
454
|
-
config.appendMode = process.env.IOTA_APPEND_MODE === 'true';
|
|
455
|
-
}
|
|
456
|
-
|
|
457
452
|
if (process.env.IOTA_POLLING_EXPIRATION) {
|
|
458
453
|
config.pollingExpiration = process.env.IOTA_POLLING_EXPIRATION;
|
|
459
454
|
}
|
|
@@ -302,6 +302,7 @@ exports.update = ngsi.update;
|
|
|
302
302
|
exports.setCommandResult = ngsi.setCommandResult;
|
|
303
303
|
exports.listDevices = deviceService.listDevices;
|
|
304
304
|
exports.getDevice = deviceService.getDevice;
|
|
305
|
+
exports.updateDevice = deviceService.updateDevice;
|
|
305
306
|
exports.getDeviceSilently = deviceService.getDeviceSilently;
|
|
306
307
|
exports.getDeviceByName = deviceService.getDeviceByName;
|
|
307
308
|
exports.getDeviceByNameAndType = deviceService.getDeviceByNameAndType;
|
|
@@ -349,7 +350,6 @@ exports.middlewares = middlewares;
|
|
|
349
350
|
|
|
350
351
|
exports.dataPlugins = {
|
|
351
352
|
expressionTransformation: require('./plugins/expressionPlugin'),
|
|
352
|
-
bidirectionalData: require('./plugins/bidirectionalData'),
|
|
353
353
|
utils: require('./plugins/pluginUtils')
|
|
354
354
|
};
|
|
355
355
|
|
package/lib/jexlTranformsMap.js
CHANGED
|
@@ -79,7 +79,8 @@ const map = {
|
|
|
79
79
|
// https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString
|
|
80
80
|
localestring: (d, timezone, options) => new Date(d).toLocaleString(timezone, options),
|
|
81
81
|
now: () => Date.now(),
|
|
82
|
-
hextostring: (val) =>
|
|
82
|
+
hextostring: (val) =>
|
|
83
|
+
new TextDecoder().decode(new Uint8Array(val.match(/.{1,2}/g).map((byte) => parseInt(byte, 16))))
|
|
83
84
|
};
|
|
84
85
|
|
|
85
86
|
exports.map = map;
|
package/lib/model/Device.js
CHANGED
package/lib/model/Group.js
CHANGED
package/lib/model/dbConn.js
CHANGED
|
@@ -106,13 +106,7 @@ function init(host, db, port, options, callback) {
|
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
function connectionAttempt(url, options, callback) {
|
|
109
|
-
logger.info(
|
|
110
|
-
context,
|
|
111
|
-
'Attempting to connect to MongoDB instance with url %j and options %j. Attempt %d',
|
|
112
|
-
url,
|
|
113
|
-
options,
|
|
114
|
-
retries
|
|
115
|
-
);
|
|
109
|
+
logger.info(context, 'Attempting to connect to MongoDB instance with url %j. Attempt %d', url, retries);
|
|
116
110
|
// FIXME: useNewUrlParser is no longer used in underlying mongodb driver 4.x
|
|
117
111
|
// (see https://github.com/mongodb/node-mongodb-native/blob/HEAD/etc/notes/CHANGES_4.0.0.md)
|
|
118
112
|
// but not sure if current mongoose version is still using mongodb 3.x internally
|
|
@@ -77,7 +77,7 @@ function extractVariables(expression) {
|
|
|
77
77
|
variables = tokens.filter(function (token, index, array) {
|
|
78
78
|
return (
|
|
79
79
|
(token.type === ' ' && array[index - 1].type !== 'dot') ||
|
|
80
|
-
(token.type === 'identifier' && array[index + 1].type !== 'openParen')
|
|
80
|
+
(token.type === 'identifier' && array[index + 1] && array[index + 1].type !== 'openParen')
|
|
81
81
|
);
|
|
82
82
|
});
|
|
83
83
|
|
package/lib/request-shim.js
CHANGED
|
@@ -59,7 +59,7 @@ function getOptions(options) {
|
|
|
59
59
|
// got library is not properly documented, so it is not clear which takes precedence
|
|
60
60
|
// among body, json and form (see https://stackoverflow.com/q/70754880/1485926).
|
|
61
61
|
// Thus, we are enforcing our own precedence with the "else if" chain below.
|
|
62
|
-
// Behaviour is consistent with the one described at
|
|
62
|
+
// Behaviour is consistent with the one described at development.md#iotagentlibrequest
|
|
63
63
|
|
|
64
64
|
if (options.method === 'GET' || options.method === 'HEAD' || options.method === 'OPTIONS') {
|
|
65
65
|
// Do nothing - Never add a body
|
|
@@ -70,7 +70,7 @@ function getOptions(options) {
|
|
|
70
70
|
// json takes precedence over form
|
|
71
71
|
httpOptions.json = options.json;
|
|
72
72
|
} else if (options.form) {
|
|
73
|
-
// Note that we don't consider 'form' part of the function API (check
|
|
73
|
+
// Note that we don't consider 'form' part of the function API (check development.md#iotagentlibrequest)
|
|
74
74
|
// but we are preparing the code anyway as a safe measure
|
|
75
75
|
httpOptions.form = options.form;
|
|
76
76
|
}
|
|
@@ -120,7 +120,7 @@ function markAsExpired(command) {
|
|
|
120
120
|
|
|
121
121
|
async.waterfall(
|
|
122
122
|
[
|
|
123
|
-
apply(deviceService.getDevice, command.deviceId, command.service, command.subservice),
|
|
123
|
+
apply(deviceService.getDevice, command.deviceId, null, command.service, command.subservice),
|
|
124
124
|
getGroup,
|
|
125
125
|
calculateTypeInformation,
|
|
126
126
|
updateExpiredCommand
|
|
@@ -56,7 +56,7 @@ function handleError(error, req, res, next) {
|
|
|
56
56
|
* Express middleware for tracing the complete request arriving to the IoTA in debug mode.
|
|
57
57
|
*/
|
|
58
58
|
function traceRequest(req, res, next) {
|
|
59
|
-
logger.debug(context, 'Request for path [%s] from [%s]', req.path, req.get('host'));
|
|
59
|
+
logger.debug(context, 'Request for path [%s] query [%j] from [%s]', req.path, req.query, req.get('host'));
|
|
60
60
|
|
|
61
61
|
if (req.is('json') || req.is('application/ld+json')) {
|
|
62
62
|
logger.debug(context, 'Body:\n\n%s\n\n', JSON.stringify(req.body, null, 4));
|
|
@@ -58,7 +58,6 @@ function register(callback) {
|
|
|
58
58
|
timestamp: service.timestamp,
|
|
59
59
|
autoprovision: service.autoprovision,
|
|
60
60
|
explicitAttrs: service.explicitAttrs,
|
|
61
|
-
expressionLanguage: service.expressionLanguage,
|
|
62
61
|
defaultEntityNameConjunction: service.defaultEntityNameConjunction,
|
|
63
62
|
ngsiVersion: service.ngsiVersion,
|
|
64
63
|
entityNameExp: service.entityNameExp
|
|
@@ -71,7 +71,7 @@ function storeDevice(newDevice, callback) {
|
|
|
71
71
|
* @param {String} service Service of the device to remove.
|
|
72
72
|
* @param {String} subservice Subservice inside the service for the removed device.
|
|
73
73
|
*/
|
|
74
|
-
function removeDevice(id, service, subservice, callback) {
|
|
74
|
+
function removeDevice(id, apikey, service, subservice, callback) {
|
|
75
75
|
const services = Object.keys(registeredDevices);
|
|
76
76
|
|
|
77
77
|
for (let i = 0; i < services.length; i++) {
|
|
@@ -141,7 +141,7 @@ function listDevices(type, service, subservice, limit, offset, callback) {
|
|
|
141
141
|
});
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
-
function getDevice(id, service, subservice, callback) {
|
|
144
|
+
function getDevice(id, apikey, service, subservice, callback) {
|
|
145
145
|
if (registeredDevices[service] && registeredDevices[service][id]) {
|
|
146
146
|
callback(null, registeredDevices[service][id]);
|
|
147
147
|
} else {
|
|
@@ -55,7 +55,6 @@ const attributeList = [
|
|
|
55
55
|
'polling',
|
|
56
56
|
'timestamp',
|
|
57
57
|
'explicitAttrs',
|
|
58
|
-
'expressionLanguage',
|
|
59
58
|
'ngsiVersion'
|
|
60
59
|
];
|
|
61
60
|
|
|
@@ -120,13 +119,15 @@ function storeDevice(newDevice, callback) {
|
|
|
120
119
|
* @param {String} service Service of the device to remove.
|
|
121
120
|
* @param {String} subservice Subservice inside the service for the removed device.
|
|
122
121
|
*/
|
|
123
|
-
function removeDevice(id, service, subservice, callback) {
|
|
122
|
+
function removeDevice(id, apikey, service, subservice, callback) {
|
|
124
123
|
const condition = {
|
|
125
124
|
id,
|
|
126
125
|
service,
|
|
127
126
|
subservice
|
|
128
127
|
};
|
|
129
|
-
|
|
128
|
+
if (apikey) {
|
|
129
|
+
condition.apikey = apikey;
|
|
130
|
+
}
|
|
130
131
|
logger.debug(context, 'Removing device with id [%s]', id);
|
|
131
132
|
|
|
132
133
|
Device.model.deleteOne(condition, function (error) {
|
|
@@ -176,15 +177,15 @@ function listDevices(type, service, subservice, limit, offset, callback) {
|
|
|
176
177
|
query.skip(parseInt(offset, 10));
|
|
177
178
|
}
|
|
178
179
|
|
|
179
|
-
async.series(
|
|
180
|
-
|
|
181
|
-
results
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
}
|
|
187
|
-
|
|
180
|
+
async.series(
|
|
181
|
+
[query.exec.bind(query), Device.model.countDocuments.bind(Device.model, condition)],
|
|
182
|
+
function (error, results) {
|
|
183
|
+
callback(error, {
|
|
184
|
+
count: results[1],
|
|
185
|
+
devices: results[0]
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
);
|
|
188
189
|
}
|
|
189
190
|
|
|
190
191
|
function findOneInMongoDB(queryParams, id, callback) {
|
|
@@ -212,17 +213,21 @@ function findOneInMongoDB(queryParams, id, callback) {
|
|
|
212
213
|
* Internal function used to find a device in the DB.
|
|
213
214
|
*
|
|
214
215
|
* @param {String} id ID of the Device to find.
|
|
216
|
+
* @param {String} Apikey Apikey of the Device to find.
|
|
215
217
|
* @param {String} service Service the device belongs to (optional).
|
|
216
218
|
* @param {String} subservice Division inside the service (optional).
|
|
217
219
|
*/
|
|
218
|
-
function getDeviceById(id, service, subservice, callback) {
|
|
219
|
-
|
|
220
|
+
function getDeviceById(id, apikey, service, subservice, callback) {
|
|
221
|
+
let queryParams = {
|
|
220
222
|
id,
|
|
221
223
|
service,
|
|
222
224
|
subservice
|
|
223
225
|
};
|
|
226
|
+
if (apikey) {
|
|
227
|
+
queryParams.apikey = apikey;
|
|
228
|
+
}
|
|
224
229
|
context = fillService(context, queryParams);
|
|
225
|
-
logger.debug(context, 'Looking for device with id [%s].', id);
|
|
230
|
+
logger.debug(context, 'Looking for device with id [%s] and queryParams [%j].', id, queryParams);
|
|
226
231
|
findOneInMongoDB(queryParams, id, callback);
|
|
227
232
|
}
|
|
228
233
|
|
|
@@ -233,10 +238,17 @@ function getDeviceById(id, service, subservice, callback) {
|
|
|
233
238
|
* @param {String} service Service the device belongs to.
|
|
234
239
|
* @param {String} subservice Division inside the service.
|
|
235
240
|
*/
|
|
236
|
-
function getDevice(id, service, subservice, callback) {
|
|
237
|
-
getDeviceById(id, service, subservice, function (error, data) {
|
|
241
|
+
function getDevice(id, apikey, service, subservice, callback) {
|
|
242
|
+
getDeviceById(id, apikey, service, subservice, function (error, data) {
|
|
238
243
|
if (error) {
|
|
239
|
-
|
|
244
|
+
// Try without apikey: apikey will be added to device later
|
|
245
|
+
getDeviceById(id, null, service, subservice, function (error, data) {
|
|
246
|
+
if (error) {
|
|
247
|
+
callback(error);
|
|
248
|
+
} else {
|
|
249
|
+
callback(null, data);
|
|
250
|
+
}
|
|
251
|
+
});
|
|
240
252
|
} else {
|
|
241
253
|
callback(null, data);
|
|
242
254
|
}
|
|
@@ -285,7 +297,7 @@ function getByName(name, service, servicepath, callback) {
|
|
|
285
297
|
*/
|
|
286
298
|
function update(device, callback) {
|
|
287
299
|
logger.debug(context, 'Storing updated values for device [%s]:\n%s', device.id, JSON.stringify(device, null, 4));
|
|
288
|
-
|
|
300
|
+
getDevice(device.id, device.apikey, device.service, device.subservice, function (error, data) {
|
|
289
301
|
if (error) {
|
|
290
302
|
callback(error);
|
|
291
303
|
} else {
|
|
@@ -303,6 +315,7 @@ function update(device, callback) {
|
|
|
303
315
|
data.registrationId = device.registrationId;
|
|
304
316
|
data.explicitAttrs = device.explicitAttrs;
|
|
305
317
|
data.ngsiVersion = device.ngsiVersion;
|
|
318
|
+
data.timestamp = device.timestamp;
|
|
306
319
|
|
|
307
320
|
/* eslint-disable-next-line new-cap */
|
|
308
321
|
const deviceObj = new Device.model(data);
|