While largely similar in architectures, the IIoT SDK version 3.0 has certain differences from earlier versions. The major changes are in the use of NATS instead of MQTT and runtime updates of application configuration through Twin Properties instead of files on disk.


In earlier versions of the SDK, the primary message broker was MQTT. And even though NATS could be used to send and recieve messages, this was done indirectly via MQTT. Starting with version 3.0, the primary, and only, message broker is NATS while MQTT was completely removed. This enhances clarity and provides applications more granular control of topics to which they wish to subscribe. Furthermore, this removes the need to use the AEA Broker and its accompanying routes.json which were required.
Application configurations files, such as the AEA.json, were updated by uploading a new version to a directory in a docker volume where applications listened for changes. In SDK 3.0, this is no longer the case. Now, at runtime, if an application wishes to update the initial configuration file it is bundled with, it can simply use the cloud Twins REST API to set the configuration in Redis. Applications will no longer have to update configuration files on disk, nor would they be able to use the FileKey or Commandline mechanisms of updating configuration files. This allows a frictionless update of configuration files at runtime.
The following Twins cloud REST API is used to push the new configuration:

An example invocation is shown below:
curl -X 'PUT' \
'https://api-iiot-cloud.app.evd-2.lightops.slb.com/api/twin-properties/v1/slb/evd/SE10i-MJ0LENW3/twin-properties' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer 'Token' \
-d '{
"group": "config",
"twins": [
{
"name": "model_text",
"value": "{\"head_model_text\":\"Testing New Test\",\"pi_model_text\":\"Sample Text\",\"WellTestWaterCut_pct\":54,\"WellTestGOR_raw\":24,\"WellTestAPI_dAPI\":13,\"HeadCalibrationThreshold_pct\":3,\"PICalibrationThreshold_pct\":3}"
}
]
}Once the property is set, the following Redis key will hold the new configuration:
twin_properties/config/desired/model_text
And since the SDK has a subscription on this key, whenever its value is updated, the application is notified of the new configuration.
Application configuration has been streamlined by removing the dependency on the AEA Broker. Consequently, message routing information previously stored in routes.json is now consolidated in the single AEA.json config file.
Below are examples of configuration files in SDK 2.0.
Route.json
{
"Routes": [
"/AgoraCoreBusSender/RequestOut TO /aea2-file-manager/RequestIn",
"/aea2-file-manager/RequestOut TO /AgoraCoreBusSender/RequestIn",
"/aea2-twin-property-mapper/RequestOut TO /AgoraCoreBusSender/RequestIn",
"/AgoraCoreBusSender/RequestOut TO /aea2-twin-property-mapper/RequestIn",
"/AgoraCoreBusSender/RequestOut TO /AEAOpsAgent/RequestIn",
"/AEAOpsAgent/RequestOut TO /AgoraCoreBusSender/RequestIn",
"/AEAOpsAgent/EventOut TO /PassThroughHandler/EventIn",
"/PassThroughHandler/DataOut TO /AgoraCoreBusSender/DataIn"
]
}AEA.json
{
"Name": "chemical_injection",
"AEA2": {
"LogLevel": "Info",
"BusClient": {
"Server": "mqtt-net-server",
"Port": 707,
"Subscriptions": [
"RequestIn",
"DataIn"
]
}
}
}In SDK 3.0, both files are now consolidated in a single config file as shown below.
AEA.json
{
"Name": "MyApp",
"AEA2": {
"RedisClient": {
"Server": "localhost",
"Port": "6379",
},
"BusClient": {
"Server": "nats://localhost:4222",
"Subscriptions": [
{
"DataIn": [
"slbapps.MyApp.DataIn",
"slbapps.events.DataIn"
]
},
{
"RequestIn": [
"slbapps.MyApp.RequestIn"
]
},
{
"EventIn": [
"slbapps.MyApp.EventIn"
]
}
],
"Targets": [
{
"DataOut": [
"slbapps.app1.DataIn",
"slbapps.app2.DataIn",
]
},
{
"RequestOut": [
"slbapps.app1.RequestIn",
"slbapps.app2.RequestIn",
]
},
{
"EventOut": [
"slbapps.app1.EventIn",
"slbapps.app2.EventIn",
]
}
]
}
}
}A Metadata field was added to SDK 3.0 and also backported to SDK 2.0. The optional field, which is a dictionary of name/value pairs, can be used by applications to propagate any additional information about the point. For example, and since the SDK is not units aware, any information about units of measure may be stored in the Metadata field.
Represents an individual Input/Output (IO) point. Contains information about the value represented
as either a flow or a str, quality, and timestamp of the point.
"""
def __init__(self,
value: float = None,
value_str: str = None,
quality_code: int = None,
timestamp: float = None,
metadata: dict = None):
"""
Initialize an IoPoint instance.In general, all versions of the SDK are units unaware. This means applications may send data with or without units, and even with incorrect units. The SDK does not validate nor convert a unit to or from any other unit. With this flexibility there is potential for issues arising during integration with downstream systems.
In order to reduce the likelihood of such issues, it is recommended that applications use the Metadata field in IoPoint to propagate unit of measure information using the key uom. For example, a wellhead pressure measurement may be sent in Metadata as follows:
Metadata
{
"uom": "pressure:psi",
"prop": "value"
}Applications can propagate unit of measure information according to the unit catalogs used by downstream systems with which they wish to integrate.