Ticket #96: Versions: Upgrade MQTT Client SL to the one that installs with IIoT Libraries SL 1.3.0.0
co⚡e: Sparkplug™ MQTT edge and host
tickets
(Ticket)
Upgrade to the latest version of the MQTT Client SL. This contains bug fixes, as well as improved performance. The TLS mechanism has changed, so must be considered in the upgrade. https://store.codesys.com/iiot-libraries-sl.html#All%20versions2021-04-30 13:34:43.538000 Ticket #96: Versions: Upgrade MQTT Client SL to the one that installs with IIoT Libraries SL 1.3.0.0 co⚡e: Sparkplug™ MQTT edge and host cobolt tickets tickets False /lib/cobolt/tickets/96/ Ticket Versions: Upgrade MQTT Client SL to the one that installs with IIoT Libraries SL 1.3.0.0 False 0 2020-11-23 22:19:40.974000 96 Versions: Upgrade MQTT Client SL to the one that installs with IIoT Libraries SL 1.3.0.0 closed Upgrade to the latest version of the MQTT Client SL. This contains bug fixes, as well as improved performance. The TLS mechanism has changed, so must be considered in the upgrade. https://store.codesys.com/iiot-libraries-sl.html#All%20versions False False 0 0 0 96 2.0.0.0: Edge i-campbell hermsen
Last updated: 2021-04-30
Ticket #107: Subscribe to "STATE" of Primary Application
co⚡e: Sparkplug™ MQTT edge and host
tickets
(Ticket)
Subscribe to "STATE" topic Primary Application and show it in the log2021-04-30 13:34:43.539000 Ticket #107: Subscribe to "STATE" of Primary Application co⚡e: Sparkplug™ MQTT edge and host cobolt tickets tickets False /lib/cobolt/tickets/107/ Ticket Subscribe to "STATE" of Primary Application False 0 2020-12-21 17:44:20.593000 107 Subscribe to "STATE" of Primary Application closed Subscribe to "STATE" topic Primary Application and show it in the log False False 0 0 0 107 2.0.0.0: Edge hermsen None
Last updated: 2021-04-30
Ticket #127: Edge / Device BUG SeqNums
co⚡e: Sparkplug™ MQTT edge and host
tickets
(Ticket)
Requires -> [#128] new implementation of FB_EdgeMQTT client Requires -> [#129] SFC itterator 2021-04-30 13:34:43.541000 Ticket #127: Edge / Device BUG SeqNums co⚡e: Sparkplug™ MQTT edge and host cobolt tickets tickets False /lib/cobolt/tickets/127/ Ticket Edge / Device BUG SeqNums False 0 2021-03-20 22:38:33.336000 127 Edge / Device BUG SeqNums closed Requires -> [#128] new implementation of FB_EdgeMQTT client Requires -> [#129] SFC itterator False False 0 0 0 127 2.0.0.0: Edge hermsen i-campbell
Last updated: 2021-04-30
Ticket #128: new implementation of FB_EdgeMQTT client
co⚡e: Sparkplug™ MQTT edge and host
tickets
(Ticket)
FB_DeviceMQTTClient publisher code will be phased out and integrated into a single FB_EdgeMQTTClient. Subscriber code will stay intact 2021-04-30 13:34:43.539000 Ticket #128: new implementation of FB_EdgeMQTT client co⚡e: Sparkplug™ MQTT edge and host cobolt tickets tickets False /lib/cobolt/tickets/128/ Ticket new implementation of FB_EdgeMQTT client False 0 2021-03-20 22:40:21.684000 128 new implementation of FB_EdgeMQTT client closed FB_DeviceMQTTClient publisher code will be phased out and integrated into a single FB_EdgeMQTTClient. Subscriber code will stay intact False False 0 0 0 128 2.0.0.0: Edge hermsen hermsen
Last updated: 2021-04-30
Ticket #129: Edge: SFC itterator
co⚡e: Sparkplug™ MQTT edge and host
tickets
(Ticket)
It is a requirement to have things published in order FB_Edge will receive an itterator which in a single scan, it will itterate until it finds an (Edge or Device) which wants to publish. The state machine then goes to PUBLISH and waits until the publisher is done. It then returns to the ITTERATION state to complete (does not restart) if the itteration completes without finding anyone who wants to publish, it ends the state and restarts the ittetration. The "not restarting the itterator" may be crucial for not favouring a particularly busy device over others. Effectively the itterator is normally a "looper".2021-04-30 13:34:43.540000 Ticket #129: Edge: SFC itterator co⚡e: Sparkplug™ MQTT edge and host cobolt tickets tickets False /lib/cobolt/tickets/129/ Ticket Edge: SFC itterator False 0 2021-03-20 22:44:30.845000 129 Edge: SFC itterator closed It is a requirement to have things published in order FB_Edge will receive an itterator which in a single scan, it will itterate until it finds an (Edge or Device) which wants to publish. The state machine then goes to PUBLISH and waits until the publisher is done. It then returns to the ITTERATION state to complete (does not restart) if the itteration completes without finding anyone who wants to publish, it ends the state and restarts the ittetration. The "not restarting the itterator" may be crucial for not favouring a particularly busy device over others. Effectively the itterator is normally a "looper". False False 0 0 0 129 2.0.0.0: Edge hermsen i-campbell
Last updated: 2021-04-30
Ticket #137: Edge: Not obeying max publish rate
co⚡e: Sparkplug™ MQTT edge and host
tickets
(Ticket)
If set to a publish rate of 2000 (ms) the edge publishes NDATA faster than one every 2 seconds. NDATA should be limited to the publish rate.2021-05-10 20:46:14.849000 Ticket #137: Edge: Not obeying max publish rate co⚡e: Sparkplug™ MQTT edge and host cobolt tickets tickets False /lib/cobolt/tickets/137/ Ticket Edge: Not obeying max publish rate False 0 2021-05-10 19:24:14.371000 137 Edge: Not obeying max publish rate closed If set to a publish rate of 2000 (ms) the edge publishes NDATA faster than one every 2 seconds. NDATA should be limited to the publish rate. False False 0 0 0 137 2.0.0.0: Edge i-campbell hermsen
Last updated: 2021-05-10
Ticket #1: Create Introductionpage
co⚡e: Sparkplug™ MQTT edge and host
tickets
(Ticket)
Create Introduction page with all relevant definitions of the protocol2020-11-01 19:08:55.617000 Ticket #1: Create Introductionpage co⚡e: Sparkplug™ MQTT edge and host cobolt tickets tickets False /lib/cobolt/tickets/1/ Ticket Create Introductionpage False 0 2020-03-26 15:39:56.515000 1 Create Introductionpage closed Create Introduction page with all relevant definitions of the protocol False False 0 0 0 1 2.0.0.0: Example aliazzz aliazzz
Last updated: 2020-11-01
Ticket #14: Example project for a Node
co⚡e: Sparkplug™ MQTT edge and host
tickets
(Ticket)
Instructions on how to setup the project a CODESYS EoN should connect to a third party MQTT Broker, send Data and accept Commands Describe how to set up read tags, write tags, and read/write tags2021-01-24 09:21:10.505000 Ticket #14: Example project for a Node co⚡e: Sparkplug™ MQTT edge and host cobolt tickets tickets False /lib/cobolt/tickets/14/ Ticket Example project for a Node False 0 2020-03-29 00:22:59.293000 14 Example project for a Node closed Instructions on how to setup the project a CODESYS EoN should connect to a third party MQTT Broker, send Data and accept Commands * Describe how to set up read tags, write tags, and read/write tags False False 0 0 0 14 2.0.0.0: Example i-campbell None
Last updated: 2021-01-24
Ticket #15: Example project for a SCADA
co⚡e: Sparkplug™ MQTT edge and host
tickets
(Ticket)
create installation and usage instructions A CODESYS SCADA / IIoT Host should connect to a third party MQTT_Broker and receive data from an EoN and send commands to an EoN, and indicate the EoN connection status. This CODESYS SCADA (PLC) application is the so called 'Primary Application' (see SparkplugB specs page 20 and beyond) and can reside on any CODESYS PLC. The primary application is effectivly decoupled from the infrastructure via the use of the MQTT broker.2021-02-07 20:35:19.705000 Ticket #15: Example project for a SCADA co⚡e: Sparkplug™ MQTT edge and host cobolt tickets tickets False /lib/cobolt/tickets/15/ Ticket Example project for a SCADA False 0 2020-03-29 00:25:53.919000 15 Example project for a SCADA closed create installation and usage instructions A CODESYS SCADA / IIoT Host should connect to a third party MQTT_Broker and receive data from an EoN and send commands to an EoN, and indicate the EoN connection status. * This CODESYS SCADA (PLC) application is the so called 'Primary Application' (see SparkplugB specs page 20 and beyond) and can reside on any CODESYS PLC. The primary application is effectivly decoupled from the infrastructure via the use of the MQTT broker. False False 0 0 0 15 2.0.0.0: Example i-campbell None
Last updated: 2021-02-07
Ticket #30: Define User Story for setting up sparkplug with CODESYS
co⚡e: Sparkplug™ MQTT edge and host
tickets
(Ticket)
This is a draft user story, and will be modified as we settle on an implementation. EoN Node User creates a CODESYS project as normal, with no heed of SparkplugB. This could also be any existing project. User sets up a list of Variables they want to make readable / writeable over Sparkplug B. This could be similar to, or make use of Symbol Config The user then "imports" this symbol config to their own project, generating the required code to use SparkplugB User defines the Saprkplug connnection parameters (Group Name, EoN name, Device Name, MQTT Server URL, etc etc) There is a mechanism to define the Quality of each CODESYS Variable (Sparkplug: is_null) and a method to define the timestamp if wanting to define this seperately to time the payload is sent. SCADA Node User "imports" the EoN symbolconfig to the SCADA project, specifying the GroupName, EoN name, Device Name. a structure is created, allowing the SCADA Node access to all the variables as GroupName.EoNName.DeviceName.TagName(s) There is also a Scan Network option, which can generate all SparkplugB symbols available on the network, and their associated EoN/Device Names. User then creates whichever HMI graphics, supervisory control logic, alarms whatever they want.2021-05-16 00:04:41.754000 Ticket #30: Define User Story for setting up sparkplug with CODESYS co⚡e: Sparkplug™ MQTT edge and host cobolt tickets tickets False /lib/cobolt/tickets/30/ Ticket Define User Story for setting up sparkplug with CODESYS False 0 2020-05-18 22:18:43.972000 30 Define User Story for setting up sparkplug with CODESYS closed This is a draft user story, and will be modified as we settle on an implementation. EoN Node User creates a CODESYS project as normal, with no heed of SparkplugB. This could also be any existing project. User sets up a list of Variables they want to make readable / writeable over Sparkplug B. This could be similar to, or make use of Symbol Config The user then "imports" this symbol config to their own project, generating the required code to use SparkplugB User defines the Saprkplug connnection parameters (Group Name, EoN name, Device Name, MQTT Server URL, etc etc) There is a mechanism to define the Quality of each CODESYS Variable (Sparkplug: is_null) and a method to define the timestamp if wanting to define this seperately to time the payload is sent. SCADA Node User "imports" the EoN symbolconfig to the SCADA project, specifying the GroupName, EoN name, Device Name. a structure is created, allowing the SCADA Node access to all the variables as GroupName.EoNName.DeviceName.TagName(s) There is also a Scan Network option, which can generate all SparkplugB symbols available on the network, and their associated EoN/Device Names. User then creates whichever HMI graphics, supervisory control logic, alarms whatever they want. False False 0 0 0 30 2.0.0.0: Example i-campbell None
Last updated: 2021-05-16
Ticket #135: Project Homepage: Update guides
co⚡e: Sparkplug™ MQTT edge and host
tickets
(Ticket)
Proof and Update the following to match latest library: [x] Add to existing [x] Set up Test Server - rename to setup a test system with Ignition Primary Host Add the following guides: [x] setting up a test environment with a co⚡e primary host2021-05-15 22:48:45.171000 Ticket #135: Project Homepage: Update guides co⚡e: Sparkplug™ MQTT edge and host cobolt tickets tickets False /lib/cobolt/tickets/135/ Ticket Project Homepage: Update guides False 0 2021-04-24 20:23:49.792000 135 Project Homepage: Update guides closed Proof and Update the following to match latest library: [x] Add to existing [x] Set up Test Server - rename to setup a test system with Ignition Primary Host Add the following guides: [x] setting up a test environment with a co⚡e primary host False False 0 0 0 135 2.0.0.0: Example i-campbell hermsen
Last updated: 2021-05-15
Ticket #11: FB_Payload
co⚡e: Sparkplug™ MQTT edge and host
tickets
(Ticket)
Initial Implementation of FB_Payload: User Project will manage pools of each of the elements of arrays. FB_EoNNode will first generate a structure using the Initialize, Set and Add methods, and secondly Encode the FB_Payload when it wants to send a payload. FB_EoNNode will first Decode the FB_Payload, then use the Get and Read methods to determine the structure. Progress (Implemented, not tested): Get Set Encode Decode [x] [x] [x] [x] Payload.timestamp [x] [x] [x] [x] Payload.metrics[].name [x] [x] [x] [x] Payload.metrics[].alias [x] [x] [x] [x] Payload.metrics[].timestamp [x] [x] [x] [x] Payload.metrics[].datatype [x] [x] [x] [x] Payload.metrics[].is_historical [x] [x] [x] [x] Payload.metrics[].is_transient [x] [x] [x] [x] Payload.metrics[].is_null [x] [x] [x] [x] Payload.metrics[].metadata.is_multi_part [x] [x] [x] [x] Payload.metrics[].metadata.content_type [x] [x] [x] [x] Payload.metrics[].metadata.size [x] [x] [x] [x] Payload.metrics[].metadata.seq [x] [x] [x] [x] Payload.metrics[].metadata.file_name [x] [x] [x] [x] Payload.metrics[].metadata.file_type [x] [x] [x] [x] Payload.metrics[].metadata.md5 [x] [x] [x] [x] Payload.metrics[].metadata.description Payload.metrics[].metadata.extensions[] //none [x] [x] [x] [x] Payload.metrics[].properties.keys[] [x] [x] [x] [x] Payload.metrics[].properties.values[].type [x] [x] [x] [x] Payload.metrics[].properties.values[].is_null [x] [x] [x] [x] Payload.metrics[].properties.values[].int_value [x] [x] [x] [x] Payload.metrics[].properties.values[].long_value [x] [x] [x] [x] Payload.metrics[].properties.values[].float_value [x] [x] [x] [x] Payload.metrics[].properties.values[].double_value [x] [x] [x] [x] Payload.metrics[].properties.values[].boolean_value [x] [x] [x] [x] Payload.metrics[].properties.values[].string_value [x] [x] [x] [x] Payload.metrics[].properties.values[].propertyset_value. //(RECURSIVE PROPERTIES) [x] [x] [x] [x] Payload.metrics[].properties.values[].propertysets_value.propertyset[]. //(RECURSIVE PROPERTIES) Payload.metrics[].properties.values[].extension_value //none Payload.metrics[].properties.extensions[] //none [x] [x] [x] [x] Payload.metrics[].int_value [x] [x] [x] [x] Payload.metrics[].long_value [x] [x] [x] [x] Payload.metrics[].float_value [x] [x] [x] [x] Payload.metrics[].double_value [x] [x] [x] [x] Payload.metrics[].boolean_value [x] [x] [x] [x] Payload.metrics[].string_value [x] [x] [x] [x] Payload.metrics[].bytes_value [x] [x] [x] [x] Payload.metrics[].dataset_value.num_of_columns [x] [x] [x] [x] Payload.metrics[].dataset_value.columns[] [x] [x] [x] [x] Payload.metrics[].dataset_value.types[] [x] [x] [x] [x] Payload.metrics[].dataset_value.rows[].elements[].int_value [x] [x] [x] [x] Payload.metrics[].dataset_value.rows[].elements[].long_value [x] [x] [x] [x] Payload.metrics[].dataset_value.rows[].elements[].float_value [x] [x] [x] [x] Payload.metrics[].dataset_value.rows[].elements[].double_value [x] [x] [x] [x] Payload.metrics[].dataset_value.rows[].elements[].boolean_value [x] [x] [x] [x] Payload.metrics[].dataset_value.rows[].elements[].string_value Payload.metrics[].dataset_value.rows[].elements[].extension_value //none Payload.metrics[].dataset_value.rows[].extensions[] //none Payload.metrics[].dataset_value.extensions[] //none [x] [x] [x] [x] Payload.metrics[].template_value.version [x] [x] [x] [x] Payload.metrics[].template_value.metrics[]. //(RECURSIVE Metrics) [x] [x] [x] [x] Payload.metrics[].template_value.parameters[].name [x] [x] [x] [x] Payload.metrics[].template_value.parameters[].type [x] [x] [x] [x] Payload.metrics[].template_value.parameters[].int_value [x] [x] [x] [x] Payload.metrics[].template_value.parameters[].long_value [x] [x] [x] [x] Payload.metrics[].template_value.parameters[].float_value [x] [x] [x] [x] Payload.metrics[].template_value.parameters[].double_value [x] [x] [x] [x] Payload.metrics[].template_value.parameters[].boolean_value [x] [x] [x] [x] Payload.metrics[].template_value.parameters[].string_value Payload.metrics[].template_value.parameters[].extension_value //none [x] [x] [x] [x] Payload.metrics[].template_value.template_ref [x] [x] [x] [x] Payload.metrics[].template_value.is_definition Payload.metrics[].template_value.extensions[] //none Payload.metrics[].extension_value.extensions[] //none [x] [x] [x] [x] Payload.seq [x] [x] [x] [x] Payload.uuid [x] [x] [x] [x] Payload.body Payload.extensions[] //none The following is not intended to be implemented: extensions2020-12-19 17:07:47.547000 Ticket #11: FB_Payload co⚡e: Sparkplug™ MQTT edge and host cobolt tickets tickets False /lib/cobolt/tickets/11/ Ticket FB_Payload False 0 2020-03-28 12:14:37.158000 11 FB_Payload closed Initial Implementation of FB_Payload: User Project will manage pools of each of the elements of arrays. FB_EoNNode will first generate a structure using the Initialize, Set and Add methods, and secondly Encode the FB_Payload when it wants to send a payload. FB_EoNNode will first Decode the FB_Payload, then use the Get and Read methods to determine the structure. Progress (Implemented, not tested): Get Set Encode Decode [x] [x] [x] [x] Payload.timestamp [x] [x] [x] [x] Payload.metrics[].name [x] [x] [x] [x] Payload.metrics[].alias [x] [x] [x] [x] Payload.metrics[].timestamp [x] [x] [x] [x] Payload.metrics[].datatype [x] [x] [x] [x] Payload.metrics[].is_historical [x] [x] [x] [x] Payload.metrics[].is_transient [x] [x] [x] [x] Payload.metrics[].is_null [x] [x] [x] [x] Payload.metrics[].metadata.is_multi_part [x] [x] [x] [x] Payload.metrics[].metadata.content_type [x] [x] [x] [x] Payload.metrics[].metadata.size [x] [x] [x] [x] Payload.metrics[].metadata.seq [x] [x] [x] [x] Payload.metrics[].metadata.file_name [x] [x] [x] [x] Payload.metrics[].metadata.file_type [x] [x] [x] [x] Payload.metrics[].metadata.md5 [x] [x] [x] [x] Payload.metrics[].metadata.description Payload.metrics[].metadata.extensions[] //none [x] [x] [x] [x] Payload.metrics[].properties.keys[] [x] [x] [x] [x] Payload.metrics[].properties.values[].type [x] [x] [x] [x] Payload.metrics[].properties.values[].is_null [x] [x] [x] [x] Payload.metrics[].properties.values[].int_value [x] [x] [x] [x] Payload.metrics[].properties.values[].long_value [x] [x] [x] [x] Payload.metrics[].properties.values[].float_value [x] [x] [x] [x] Payload.metrics[].properties.values[].double_value [x] [x] [x] [x] Payload.metrics[].properties.values[].boolean_value [x] [x] [x] [x] Payload.metrics[].properties.values[].string_value [x] [x] [x] [x] Payload.metrics[].properties.values[].propertyset_value. //(RECURSIVE PROPERTIES) [x] [x] [x] [x] Payload.metrics[].properties.values[].propertysets_value.propertyset[]. //(RECURSIVE PROPERTIES) Payload.metrics[].properties.values[].extension_value //none Payload.metrics[].properties.extensions[] //none [x] [x] [x] [x] Payload.metrics[].int_value [x] [x] [x] [x] Payload.metrics[].long_value [x] [x] [x] [x] Payload.metrics[].float_value [x] [x] [x] [x] Payload.metrics[].double_value [x] [x] [x] [x] Payload.metrics[].boolean_value [x] [x] [x] [x] Payload.metrics[].string_value [x] [x] [x] [x] Payload.metrics[].bytes_value [x] [x] [x] [x] Payload.metrics[].dataset_value.num_of_columns [x] [x] [x] [x] Payload.metrics[].dataset_value.columns[] [x] [x] [x] [x] Payload.metrics[].dataset_value.types[] [x] [x] [x] [x] Payload.metrics[].dataset_value.rows[].elements[].int_value [x] [x] [x] [x] Payload.metrics[].dataset_value.rows[].elements[].long_value [x] [x] [x] [x] Payload.metrics[].dataset_value.rows[].elements[].float_value [x] [x] [x] [x] Payload.metrics[].dataset_value.rows[].elements[].double_value [x] [x] [x] [x] Payload.metrics[].dataset_value.rows[].elements[].boolean_value [x] [x] [x] [x] Payload.metrics[].dataset_value.rows[].elements[].string_value Payload.metrics[].dataset_value.rows[].elements[].extension_value //none Payload.metrics[].dataset_value.rows[].extensions[] //none Payload.metrics[].dataset_value.extensions[] //none [x] [x] [x] [x] Payload.metrics[].template_value.version [x] [x] [x] [x] Payload.metrics[].template_value.metrics[]. //(RECURSIVE Metrics) [x] [x] [x] [x] Payload.metrics[].template_value.parameters[].name [x] [x] [x] [x] Payload.metrics[].template_value.parameters[].type [x] [x] [x] [x] Payload.metrics[].template_value.parameters[].int_value [x] [x] [x] [x] Payload.metrics[].template_value.parameters[].long_value [x] [x] [x] [x] Payload.metrics[].template_value.parameters[].float_value [x] [x] [x] [x] Payload.metrics[].template_value.parameters[].double_value [x] [x] [x] [x] Payload.metrics[].template_value.parameters[].boolean_value [x] [x] [x] [x] Payload.metrics[].template_value.parameters[].string_value Payload.metrics[].template_value.parameters[].extension_value //none [x] [x] [x] [x] Payload.metrics[].template_value.template_ref [x] [x] [x] [x] Payload.metrics[].template_value.is_definition Payload.metrics[].template_value.extensions[] //none Payload.metrics[].extension_value.extensions[] //none [x] [x] [x] [x] Payload.seq [x] [x] [x] [x] Payload.uuid [x] [x] [x] [x] Payload.body Payload.extensions[] //none The following is not intended to be implemented: extensions False False 0 0 0 11 2.0.0.0: Protobufs full aliazzz i-campbell
Last updated: 2020-12-19
Ticket #46: FB_SimplePayloadEncoder/Decoder: Implement simple File metric
co⚡e: Sparkplug™ MQTT edge and host
tickets
(Ticket)
Find out which metrics and metadata etc are needed for a simple file. Allow a simple file metric similar to existing simple metrics. 2020-11-16 19:48:56.313000 Ticket #46: FB_SimplePayloadEncoder/Decoder: Implement simple File metric co⚡e: Sparkplug™ MQTT edge and host cobolt tickets tickets False /lib/cobolt/tickets/46/ Ticket FB_SimplePayloadEncoder/Decoder: Implement simple File metric False 0 2020-08-17 20:47:06.218000 46 FB_SimplePayloadEncoder/Decoder: Implement simple File metric wont-fix Find out which metrics and metadata etc are needed for a simple file. Allow a simple file metric similar to existing simple metrics. False False 0 0 0 46 2.0.0.0: Protobufs full i-campbell i-campbell
Last updated: 2020-11-16
Ticket #91: Protobufs: support communicating to buggy implementations
co⚡e: Sparkplug™ MQTT edge and host
tickets
(Ticket)
Due to a bug in eclipse Tahu, most current Sparkplug Implementations cannot parse correctly formed Uint32 Metrics, Uint32 Parameters, Uint32 PropertyValues nor Uint32 DataSetValues. It is not possible to communicate to devices with the buggy implementation at the same time as communicating according to the specification. As such we need a toggle to "conform to spec" or "work around Uint32 bugs in certain Sparkplug implementations". Ignition MQTT Engine currently exhibits this bug (MQTT Engine 4.0.5 (b2020062917)) As workaround, don't use Uint32, use Uint64. Perhaps a warning can be given in the log if any Uint32s are detected.2021-05-15 23:58:08.597000 Ticket #91: Protobufs: support communicating to buggy implementations co⚡e: Sparkplug™ MQTT edge and host cobolt tickets tickets False /lib/cobolt/tickets/91/ Ticket Protobufs: support communicating to buggy implementations False 0 2020-11-17 23:12:39.139000 91 Protobufs: support communicating to buggy implementations closed Due to a bug in eclipse Tahu, most current Sparkplug Implementations cannot parse correctly formed Uint32 Metrics, Uint32 Parameters, Uint32 PropertyValues nor Uint32 DataSetValues. It is not possible to communicate to devices with the buggy implementation at the same time as communicating according to the specification. As such we need a toggle to "conform to spec" or "work around Uint32 bugs in certain Sparkplug implementations". Ignition MQTT Engine currently exhibits this bug (MQTT Engine 4.0.5 (b2020062917)) As workaround, don't use Uint32, use Uint64. Perhaps a warning can be given in the log if any Uint32s are detected. False False 0 0 0 91 2.0.0.0: Protobufs full i-campbell i-campbell
Last updated: 2021-05-15
Ticket #102: Paylaod: refactor
co⚡e: Sparkplug™ MQTT edge and host
tickets
(Ticket)
At the moment, there is a relatively complex structure for adding metrics and its subobjects to a Device, and then later to a payload. You have to add all of the pools of objects, and pass these between the FB's. Some issues: 1. The calls for each Object are quite a lot of lines of code, with up to 10 different pools needed. 2. Some people might accidentally add a metric to two different owners. So the proposal is for each object to have an interface to register its children. The children then use this interface as an input, and register themselves. Note that a Metric may have two owners, a Device and a Payload. Payload Implements IPaylaod Metric.itfOwner := Payload; Or myMetric : Metric := (itfOwner := Paylaod); or myMetric(itfOwner := Payload); Also take into consideration that the SCADA node might actually want the freedom of Pool Objects, ie it might still want MetricsPool. This might mean making two seperate calls available.2021-05-15 23:45:24.689000 Ticket #102: Paylaod: refactor co⚡e: Sparkplug™ MQTT edge and host cobolt tickets tickets False /lib/cobolt/tickets/102/ Ticket Paylaod: refactor False 0 2020-12-18 13:12:37.921000 102 Paylaod: refactor closed At the moment, there is a relatively complex structure for adding metrics and its subobjects to a Device, and then later to a payload. You have to add all of the pools of objects, and pass these between the FB's. Some issues: 1. The calls for each Object are quite a lot of lines of code, with up to 10 different pools needed. 2. Some people might accidentally add a metric to two different owners. So the proposal is for each object to have an interface to register its children. The children then use this interface as an input, and register themselves. Note that a Metric may have two owners, a Device and a Payload. Payload Implements IPaylaod Metric.itfOwner := Payload; Or myMetric : Metric := (itfOwner := Paylaod); or myMetric(itfOwner := Payload); Also take into consideration that the SCADA node might actually want the freedom of Pool Objects, ie it might still want MetricsPool. This might mean making two seperate calls available. False False 0 0 0 102 2.0.0.0: Protobufs full i-campbell i-campbell
Last updated: 2021-05-15
Ticket #140: Remove FB_Payload_OLD from library
co⚡e: Sparkplug™ MQTT edge and host
tickets
(Ticket)
Remove FB_Payload_OLD from library2021-07-11 17:42:43.322000 Ticket #140: Remove FB_Payload_OLD from library co⚡e: Sparkplug™ MQTT edge and host cobolt tickets tickets False /lib/cobolt/tickets/140/ Ticket Remove FB_Payload_OLD from library False 0 2021-07-03 21:11:17.396000 140 Remove FB_Payload_OLD from library closed Remove FB_Payload_OLD from library False False 0 0 0 140 2.0.0.0: Protobufs full i-campbell hermsen
Last updated: 2021-07-11
Ticket #3: Build a SparkplugB scada in CODESYS
co⚡e: Sparkplug™ MQTT edge and host
tickets
(Ticket)
Build an application which can consume/produce Sparkplug-B messages for testing and debug purposes. This application should demonstrate the usage and power of the sparkplug. This Ticket should be implemented after the FB_EoN_Node is done.2020-12-23 22:29:05.564000 Ticket #3: Build a SparkplugB scada in CODESYS co⚡e: Sparkplug™ MQTT edge and host cobolt tickets tickets False /lib/cobolt/tickets/3/ Ticket Consumer SCADA Duplicate Build a SparkplugB scada in CODESYS False 0 2020-03-26 15:50:02.956000 3 Build a SparkplugB scada in CODESYS wont-fix Build an application which can consume/produce Sparkplug-B messages for testing and debug purposes. This application should demonstrate the usage and power of the sparkplug. This Ticket should be implemented after the FB_EoN_Node is done. False False 1 0 1 3 2.0.0.0: SparkplugB Primary Node aliazzz i-campbell
Last updated: 2020-12-23
Ticket #110: Primary Host: Connect, publish state, subscribe
co⚡e: Sparkplug™ MQTT edge and host
tickets
(Ticket)
Create an FB_PrimaryHost. It should connect (with last will state). It should disconnect. It should subscribe to: namespace/+/NBIRTH/+ namespace/+/NDEATH/+ namespace/+/DBIRTH/# namespace/+/DDEATH/# namespace/+/NDATA/+ namespace/+/DDATA/# namespace/+/NCMD/+ namespace/+/DCMD/# STATE/+ it should provide the following methods, which will be used to handle the payloads: onNBIRTH() onNDEATH() onDBIRTH() onDDEATH() onNDATA() onDDATA() onNCMD() onDCMD() onSTATE() it should publish STATE.2021-02-07 15:44:14.079000 Ticket #110: Primary Host: Connect, publish state, subscribe co⚡e: Sparkplug™ MQTT edge and host cobolt tickets tickets False /lib/cobolt/tickets/110/ Ticket Primary Host: Connect, publish state, subscribe False 0 2021-01-09 23:38:46.445000 110 Primary Host: Connect, publish state, subscribe closed Create an FB_PrimaryHost. It should connect (with last will state). It should disconnect. It should subscribe to: namespace/+/NBIRTH/+ namespace/+/NDEATH/+ namespace/+/DBIRTH/# namespace/+/DDEATH/# namespace/+/NDATA/+ namespace/+/DDATA/# namespace/+/NCMD/+ namespace/+/DCMD/# STATE/+ it should provide the following methods, which will be used to handle the payloads: onNBIRTH() onNDEATH() onDBIRTH() onDDEATH() onNDATA() onDDATA() onNCMD() onDCMD() onSTATE() it should publish STATE. False False 0 0 0 110 2.0.0.0: SparkplugB Primary Node i-campbell hermsen
Last updated: 2021-02-07
Ticket #111: FB_PrimaryHost: Construct "Dynamic" Structure of Edge Nodes
co⚡e: Sparkplug™ MQTT edge and host
tickets
(Ticket)
Using these methods, construct a tree of groups / edges / devices / Metrics under a PrimaryHost: onNBIRTH() onNDEATH() onDBIRTH() onDDEATH() onNDATA() onDDATA() onNCMD() onDCMD() onSTATE() it should use the following FB's: FB_GroupID FB_RemoteEdge FB_RemoteDevice FB_Metric2021-05-15 23:44:22.993000 Ticket #111: FB_PrimaryHost: Construct "Dynamic" Structure of Edge Nodes co⚡e: Sparkplug™ MQTT edge and host cobolt tickets tickets False /lib/cobolt/tickets/111/ Ticket FB_PrimaryHost: Construct "Dynamic" Structure of Edge Nodes False 0 2021-01-09 23:47:23.705000 111 FB_PrimaryHost: Construct "Dynamic" Structure of Edge Nodes closed Using these methods, construct a tree of groups / edges / devices / Metrics under a PrimaryHost: onNBIRTH() onNDEATH() onDBIRTH() onDDEATH() onNDATA() onDDATA() onNCMD() onDCMD() onSTATE() it should use the following FB's: FB_GroupID FB_RemoteEdge FB_RemoteDevice FB_Metric False False 0 0 0 111 2.0.0.0: SparkplugB Primary Node i-campbell i-campbell
Last updated: 2021-05-15
Ticket #123: PrimaryHost: Investigate suitability of FBFactory for dynamic structure
co⚡e: Sparkplug™ MQTT edge and host
tickets
(Ticket)
Investigate if FBFactory will be useful for creating a dynamic metric tree: https://help.codesys.com/webapp/fb_factory;product=LibDevSummary;version=3.5.15.02021-04-30 13:25:06.459000 Ticket #123: PrimaryHost: Investigate suitability of FBFactory for dynamic structure co⚡e: Sparkplug™ MQTT edge and host cobolt tickets tickets False /lib/cobolt/tickets/123/ Ticket PrimaryHost: Investigate suitability of FBFactory for dynamic structure False 0 2021-02-16 21:45:41.599000 123 PrimaryHost: Investigate suitability of FBFactory for dynamic structure closed Investigate if FBFactory will be useful for creating a dynamic metric tree: https://help.codesys.com/webapp/fb_factory;product=LibDevSummary;version=3.5.15.0 False False 0 0 0 123 2.0.0.0: SparkplugB Primary Node i-campbell i-campbell
Last updated: 2021-04-30
Ticket #124: Replace Payload.ClaimNextFree*() with FB_Factory.Create*()
co⚡e: Sparkplug™ MQTT edge and host
tickets
(Ticket)
Replace Payload.ClaimNextFree() with FB_Factory.Create() Should be self explaining enough! This should at some point also replace the pre-defined pool sizes for Groups, Edges, Devices and Metrics2021-05-15 23:42:12.717000 Ticket #124: Replace Payload.ClaimNextFree() with FB_Factory.Create() co⚡e: Sparkplug™ MQTT edge and host cobolt tickets tickets False /lib/cobolt/tickets/124/ Ticket Replace Payload.ClaimNextFree() with FB_Factory.Create() False 0 2021-02-19 20:50:44.930000 124 Replace Payload.ClaimNextFree() with FB_Factory.Create() closed Replace Payload.ClaimNextFree() with FB_Factory.Create() Should be self explaining enough! This should at some point also replace the pre-defined pool sizes for Groups, Edges, Devices and Metrics False False 0 0 0 124 2.0.0.0: SparkplugB Primary Node hermsen None
Last updated: 2021-05-15
Ticket #125: PrimaryHost: proces & publish messages
co⚡e: Sparkplug™ MQTT edge and host
tickets
(Ticket)
Primary Host subscribe and process the incoming certificates and payloads; Process NBIRTH Process NDATA Process NDEATH Process DBIRTH Process DDATA Process DDEATH publish it's STATE and, if applicable, issue commands Publish STATE Issue NCMD's (Node REBIRTH) Issue DCMD's2021-03-06 14:10:36.102000 Ticket #125: PrimaryHost: proces & publish messages co⚡e: Sparkplug™ MQTT edge and host cobolt tickets tickets False /lib/cobolt/tickets/125/ Ticket PrimaryHost: proces & publish messages False 0 2021-02-28 20:46:56.643000 125 PrimaryHost: proces & publish messages pending Primary Host subscribe and process the incoming certificates and payloads; Process NBIRTH Process NDATA Process NDEATH Process DBIRTH Process DDATA Process DDEATH publish it's STATE and, if applicable, issue commands Publish STATE Issue NCMD's (Node REBIRTH) Issue DCMD's False False 0 0 0 125 2.0.0.0: SparkplugB Primary Node hermsen None
Last updated: 2021-03-06
Ticket #130: PrimaryHost: Itterator
co⚡e: Sparkplug™ MQTT edge and host
tickets
(Ticket)
The host needs to scan for items which need published (xCMDs). This itterator may later be expanded to include metrics, properties and so forth. xCMD crawler: 1. loop all Groups 2. loop all Edges 3. loop all Devices //Will Cycle through the Groups.Edges.devices. 1st it will find the first edge of the first group. Then it will either go deeper (G1/E1/D1) or down if there are no devices (either G1/E2, or G2/E1) // Bool: OnlyOnline := TRUE will skip offline things // Bool: EndOfList := TRUE indicates the end of list has been reached FB_DeeperAndDown() Continuously call FB_DeeperAndDown() until EOL or you find a DeviceOrEdge which wants to publish => then publish it. FB_DeeperAndDown( Groups := _Groups , OnlyOnline := TRUE , itfXcmdSender => itfXcmdSender , EndOfList => EOL ); IF (NOT EOL) AND itfXcmdSender <> 0 THEN IF itfXcmdSender.getXcmd(itfPayload => xcmdPayload ) THEN Publish(xcmdPayload); Published := TRUE; THEN END_IF;2021-03-30 20:21:09.435000 Ticket #130: PrimaryHost: Itterator co⚡e: Sparkplug™ MQTT edge and host cobolt tickets tickets False /lib/cobolt/tickets/130/ Ticket PrimaryHost: Itterator False 0 2021-03-20 22:57:49.630000 130 PrimaryHost: Itterator closed The host needs to scan for items which need published (xCMDs). This itterator may later be expanded to include metrics, properties and so forth. xCMD crawler: 1. loop all Groups 2. loop all Edges 3. loop all Devices //Will Cycle through the Groups.Edges.devices. 1st it will find the first edge of the first group. Then it will either go deeper (G1/E1/D1) or down if there are no devices (either G1/E2, or G2/E1) // Bool: OnlyOnline := TRUE will skip offline things // Bool: EndOfList := TRUE indicates the end of list has been reached FB_DeeperAndDown() Continuously call FB_DeeperAndDown() until EOL or you find a DeviceOrEdge which wants to publish => then publish it. FB_DeeperAndDown( Groups := _Groups , OnlyOnline := TRUE , itfXcmdSender => itfXcmdSender , EndOfList => EOL ); IF (NOT EOL) AND itfXcmdSender <> 0 THEN IF itfXcmdSender.getXcmd(itfPayload => xcmdPayload ) THEN Publish(xcmdPayload); Published := TRUE; THEN END_IF; False False 0 0 0 130 2.0.0.0: SparkplugB Primary Node i-campbell i-campbell
Last updated: 2021-03-30
Ticket #10: Secure testing MQTT broker
co⚡e: Sparkplug™ MQTT edge and host
tickets
(Ticket)
Requirement: certificates. perhaps MQTT username and password also possible Replaces [#9]2020-11-01 17:22:37.537000 Ticket #10: Secure testing MQTT broker co⚡e: Sparkplug™ MQTT edge and host cobolt tickets tickets False /lib/cobolt/tickets/10/ Ticket Secure testing MQTT broker False 0 2020-03-28 01:54:44.887000 10 Secure testing MQTT broker closed Requirement: certificates. perhaps MQTT username and password also possible Replaces [#9] False False 0 0 0 10 2.0.0.0: TLS i-campbell i-campbell
Last updated: 2020-11-01
Ticket #19: Add certificate generation to the library
co⚡e: Sparkplug™ MQTT edge and host
tickets
(Ticket)
Initial implementation will be suitable for an AWS IoT Core MQTT, but can be expanded as needed. TODO: How to get trusted certificates in there? i.e. AWS's public certificates TODO: Update with pictures of UI TODO: renew certificate when it expires Three CODESYS applications: On three seperate devices: EoN Node SCADA / IIoT Host * Authenticator EoN Node check if he has a private key yet. If not, generate a private key and CSR. check if he has a Certificate yet. If not check if he has a CSR yet. If notgenerate a CSR. The CSR is not a secret, so publish the text of the CSR on a visualization. have a text entry field on the visu to receive the signed certificate and install it for use. CODESYS Lib: CmpX509Cert CODESYS Example project: CryptoCertDemo SCADA / IIoT Host check if he has a private key yet. If not, generate a private key and CSR. check if he has a Certificate yet. If not check if he has a CSR yet. If notgenerate a CSR. The CSR is not a secret, so publish the text of the CSR on a visualization. have a text entry field on the visu to receive the signed certificate and install it for use. Authenticator Authenticator's only job is to take Certificate Signing Requests, and send them to AWS to register the device. Interface: 3 text fields, same for all nodes / hosts: copy and paste your super secret amazon API key (from AWS) copy and paste the AWS arn (copy it from AWS) * copy and paste the sparkplugB group_id then for each MQTT Client: copy and paste the text of the csr copy and paste the EoN Node name or SCADA / IIoT Host name (user's responsibility to assign unique names. AWS will probably give an error, if you assign a duplicate name) select wether EoN Node or SCADA / IIoT Host (OR BOTH!) Hit "register" This info is then sent via this API, which returns the signed public certificate: https://docs.aws.amazon.com/iot/latest/apireference/API_RegisterThing.html https://docs.aws.amazon.com/iot/latest/developerguide/provision-template.html#bulk-template-example will display the response from AWS (eg. SUCCESS) Note: it would be trivial to add application node, (same as SCADA / IIoT, but accept a list of allowed Nodes to read from, allowed nodes to write from, and whether it is allowed to publish its state) Note: I am not a security expert, so this implementation will need to be risk assessed for suitability in what the user wants to run it.2020-11-01 19:07:25.701000 Ticket #19: Add certificate generation to the library co⚡e: Sparkplug™ MQTT edge and host cobolt tickets tickets False /lib/cobolt/tickets/19/ Ticket Add certificate generation to the library False 0 2020-03-29 20:01:22.986000 19 Add certificate generation to the library closed Initial implementation will be suitable for an AWS IoT Core MQTT, but can be expanded as needed. TODO: How to get trusted certificates in there? i.e. AWS's public certificates TODO: Update with pictures of UI TODO: renew certificate when it expires Three CODESYS applications: On three seperate devices: EoN Node SCADA / IIoT Host * Authenticator EoN Node check if he has a private key yet. If not, generate a private key and CSR. check if he has a Certificate yet. If not check if he has a CSR yet. If notgenerate a CSR. The CSR is not a secret, so publish the text of the CSR on a visualization. have a text entry field on the visu to receive the signed certificate and install it for use. CODESYS Lib: CmpX509Cert CODESYS Example project: CryptoCertDemo SCADA / IIoT Host check if he has a private key yet. If not, generate a private key and CSR. check if he has a Certificate yet. If not check if he has a CSR yet. If notgenerate a CSR. The CSR is not a secret, so publish the text of the CSR on a visualization. have a text entry field on the visu to receive the signed certificate and install it for use. Authenticator Authenticator's only job is to take Certificate Signing Requests, and send them to AWS to register the device. Interface: 3 text fields, same for all nodes / hosts: copy and paste your super secret amazon API key (from AWS) copy and paste the AWS arn (copy it from AWS) * copy and paste the sparkplugB group_id then for each MQTT Client: copy and paste the text of the csr copy and paste the EoN Node name or SCADA / IIoT Host name (user's responsibility to assign unique names. AWS will probably give an error, if you assign a duplicate name) select wether EoN Node or SCADA / IIoT Host (OR BOTH!) Hit "register" This info is then sent via this API, which returns the signed public certificate: https://docs.aws.amazon.com/iot/latest/apireference/API_RegisterThing.html https://docs.aws.amazon.com/iot/latest/developerguide/provision-template.html#bulk-template-example will display the response from AWS (eg. SUCCESS) Note: it would be trivial to add application node, (same as SCADA / IIoT, but accept a list of allowed Nodes to read from, allowed nodes to write from, and whether it is allowed to publish its state) Note: I am not a security expert, so this implementation will need to be risk assessed for suitability in what the user wants to run it. False False 0 0 0 19 2.0.0.0: TLS i-campbell i-campbell
Last updated: 2020-11-01