This patch adds a new MQTT configuration to generate Sparkplug B telemetry as detailed in these blog posts and videos
This screenshot shows a sample run
To run this simulation, you must have installed the following optional modules as documented in the online documentation:
You should be familiar with MQTT, how to run MQTT simulations as documented in our MQTT Get Started page.
To run the Sparkplug simulation, for a configured MQTT agent with the Bosch sensor, invoke the Edit->Configure->MQTT->Config File... menu from the MIMICView GUI, and select the sparkplug/mqtt-sparkplug.cfg file.
Start the agent using the Agent->Start menu item.
You should see published telemetry according to the Sparkplug standard. From any subscriber, you should see binary payload under the spBv1.0/# topic hierarchy. If you don't configure anything else, the simulated EON node has one sensor behind it, with one metric with tag XDK/temp of value 0, eg. in our demo Sparkplug client:
DEBUG 2020-07-08 11:05:51,349 (sparkplug-demo) - Device 20:19:AB:F4:2D:CF/sensor1 metric XDK/temp = 0
The simulation is mostly data-driven via Variable Store variables as detailed in the mqtt-sparkplug.cfg file.
These are the store variables that control the Sparkplug simulation:
# Sparkplug MQTT publisher action script # # Everything is data driven as documented in the action script # action_sparkplug.cc. # # Section numbers referenced (in []) in the specification at # https://s3.amazonaws.com/cirrus-link-com/Sparkplug+Topic+Namespace+and+State+ManagementV2.1+Apendix++Payload+B+format.pdf # # This configuration simulates an edge of network (EON) node [3, 3.2], # or MQTT Enabled Device(Sparkplug) [3.4] for each agent. # # Currently, we simulate a configurable number of devices behind each EON # node [3, 3.3]. MIMIC cycles through each device in sequence per it's # configured message frequency (interval configurable). # The Sparkplug topic namespace is followed [6]. # # A set of metrics can be defined per device of the name # DEVICE,METRIC,TYPE # where # DEVICE is the device name, eg. sensor1, or *, the wildcard # METRIC is the metric name of the form system/tag # system is some system name, eg. XDK # tag is some tag, eg. temp # TYPE is a Sparkplug data type, eg. INT32 # The set of metrics is space separated. # # Each metric is published per device and its value is gotten from the # agent store variable "DEVICE,METRIC", where DEVICE is the device name, # METRIC is the metric name of the form "system/tag". # system is some system name, eg. XDK # tag is some tag, eg. temp # TYPE is a Sparkplug data type, eg. INT32 # The set of metrics is space separated. # # Each metric is published per device and its value is gotten from the # agent store variable "DEVICE,METRIC", where DEVICE is the device name, # METRIC is the metric name of the form "system/tag". # # The EON goes through the Sparkplug state machine as detailed for # SPARKPLUG_STATE below [7]. # # Relies on these agent store variables # # SPARKPLUG_EON serial number of the EON, could be persistent # # if it is not set, this defaults to mimic-AGENTNO # # SPARKPLUG_STATE current state of the EON, should be non-persistent, # one of # INITIAL initial state, next to send NBIRTH # NBIRTH NBIRTH sent, next to send DBIRTH for each device # DBIRTH DBIRTH sent, next to send DDATA for each device # END end state, next to send DDEATH for each device # DDEATH DDEATH sent, next to send NDEATH # DEAD NDEATH sent, should disconnect from here # # SPARKPLUG_DEVICES number of devices behind the EON node, could be persistent # if it is not set, this defaults to 1 # The simulated EON will cycle through the devices # in sequence one each per update cycle. # Thus, the frequency of device messages is the # frequency per agent (EON) divided by number of devices. # # SPARKPLUG_NEXTDEV iterates over the devices, should be non-persistent # indicates the next device number to publish, and # post-increments after publishing this message # # SPARKPLUG_METRICS the set of metrics for each device of the form # DEVICE,system/tag,TYPE[,optional-property,property-value] # as detailed above. # These metrics will be sent in DBIRTH and DDATA messages. # # SPARKPLUG_METRICS_MASK defines the subset of the metrics to be # sent in this interval for the current device. # This is expected to be a small subset of the total set. # If this is not defined (default), all metrics are sent. # If set, only the specified metrics are sent in the # order specified for the current device. # This value is cleared after the metrics are sent. # The best way to set the value is to append to it. # Should be non-persistent. # This is meant to work only on "sporadic" messages, # ie. under the control of # mimic agent protocol msg MQTT client message set ... count ... # else there could be empty payloads sent in PUBLISH. # # SPARKPLUG_TEMPLATES the set of templates for each device of the form # DEVICE,template-name,parameter-name,parameter-value # to add a single template with single parameter and # the first 2 metrics above. # # SPARKPLUG_DATASETS the set of datasets for each device of the form # DEVICE,columns,colkey1,TYPE1,colkey2,TYPE2,...,rows # to add a single dataset with given columns and rows # # SPARKPLUG_FUDGE make the metrics unpredictable by specified +/- value # # Global store variables: # # SPARKPLUG_DEBUG turns debugging on or off. Only detected once. # if it is not set, defaults to off # # SPARKPLUG_UUID UUID [15.1.1] # if it is not set, defaults to MyUUID # # SPARKPLUG_GROUP_ID group_id [6.1.1] # # SPARKPLUG_SENSOR_NAME global sensor name # it defines the edge_node_id in [6.1] # if it is not set, defaults to sensor1 # the device name is then "sensor"+AGENTNO # Can be overriden per agent (EON). # # SPARKPLUG_METRICS the global set of metrics by default of the form # system/tag,TYPE # for all devices as above. Is overridden per device.
To see more detailed payload you'll need a Sparkplug-compliant subscriber client as detailed below.
You can then build on this, by defining the variables via the Agent -> Variable Store... dialog for that agent. If you open that dialog for that selected device, then you will see the default values filled in, eg.:
SPARKPLUG_DEVICES = 1 SPARKPLUG_EON = the serial number of the device etc.
If you want to have a value for XDK/temp, then you would define a variable, by selecting the agent node in that dialog, then press Add..., eg.
XDK/temp = 10000
gives in our client
DEBUG 2020-07-08 11:16:05,483 (sparkplug-demo) - Device 20:19:AB:F4:2D:CF/sensor1 metric XDK/temp = 10000
If you want to scale to more, say 10, sensors behind the EON, you would double-click on SPARKPLUG_DEVICES and change
SPARKPLUG_DEVICES = 10
which will define sensors sensor11 to sensor110 (sensor1 is the default sensor type name, and the sensor number just gets appended), which you can override with the global store variable SPARKPLUG_SENSOR_NAME in Edit -> Variable Store..., eg.
SPARKPLUG_SENSOR_NAME = mysensor
If you wanted other metrics, then you would add to the default, eg.
SPARKPLUG_METRICS = *,XDK/temp,INT32
for the single metric to be sent with tag XDK/temp of type INT32.
We ship a sample lab configuration sparkplug-sample.cfg that configures a couple of EON nodes with different cases. To try it:
The Sparkplug simulation is the basis of our on-demand cloud-based MQTT Lab.
We have interoperated with
This assumes you have configured the MQTT Engine module in Ignition to subscribe to messages from a MQTT broker as detailed in this video from Induction Automation. You need to configure that broker for the simulated devices, just as you would for real devices.
You can see more short videos in our Ignition Simulator Youtube playlist.
% ./sparkplug-thresh.py --host mqtt.eclipse.org -v DEBUG 2020-07-16 13:25:55,150 (sparkplug-thresh) - NBIRTH --> EON GAM01 online DEBUG 2020-07-16 13:25:56,152 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25heartbeat = 123.0 DEBUG 2020-07-16 13:25:56,152 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25heartbeat DEBUG 2020-07-16 13:25:56,152 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25setptp = 123.0 DEBUG 2020-07-16 13:25:56,152 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25setptp DEBUG 2020-07-16 13:25:56,152 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25discp = 123.0 DEBUG 2020-07-16 13:25:56,152 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25discp DEBUG 2020-07-16 13:25:56,152 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25casep = 123.0 DEBUG 2020-07-16 13:25:56,152 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25casep DEBUG 2020-07-16 13:25:56,152 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25j10suctp = 123.0 DEBUG 2020-07-16 13:25:56,152 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25j10suctp DEBUG 2020-07-16 13:25:56,153 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25dra = 50.0 DEBUG 2020-07-16 13:25:56,153 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25dra DEBUG 2020-07-16 13:25:56,153 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25draflo = 123.0 DEBUG 2020-07-16 13:25:56,153 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25draflo DEBUG 2020-07-16 13:25:56,153 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25drasetpt = 123.0 DEBUG 2020-07-16 13:25:56,153 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25drasetpt DEBUG 2020-07-16 13:25:56,153 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25tkdra = 123.0 DEBUG 2020-07-16 13:25:56,153 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25tkdra DEBUG 2020-07-16 13:25:56,153 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25vfdspeed = 123.0 DEBUG 2020-07-16 13:25:56,153 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25vfdspeed DEBUG 2020-07-16 13:25:56,153 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25vfdamps = 123.0 DEBUG 2020-07-16 13:25:56,153 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25vfdamps DEBUG 2020-07-16 13:25:56,153 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25vfdcurrent = 123.0 DEBUG 2020-07-16 13:25:56,153 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25vfdcurrent DEBUG 2020-07-16 13:25:56,153 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25vfdvolts = 123.0 DEBUG 2020-07-16 13:25:56,154 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25vfdvolts DEBUG 2020-07-16 13:25:56,154 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25vfdhp = 123.0 DEBUG 2020-07-16 13:25:56,154 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25vfdhp DEBUG 2020-07-16 13:25:56,154 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25vfdpower = 123.0 DEBUG 2020-07-16 13:25:56,154 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25vfdpower DEBUG 2020-07-16 13:25:56,154 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25vfdinvolts = 123.0 DEBUG 2020-07-16 13:25:56,154 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25vfdinvolts DEBUG 2020-07-16 13:25:56,154 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25vfdinamps = 123.0 DEBUG 2020-07-16 13:25:56,154 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25vfdinamps DEBUG 2020-07-16 13:25:56,154 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25vfdcspeed = 123.0 DEBUG 2020-07-16 13:25:56,154 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25vfdcspeed DEBUG 2020-07-16 13:25:56,154 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25u1strtimr = 123.0 DEBUG 2020-07-16 13:25:56,154 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25u1strtimr DEBUG 2020-07-16 13:25:56,154 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25u2strtimr = 123.0 DEBUG 2020-07-16 13:25:56,155 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25u2strtimr DEBUG 2020-07-16 13:25:56,155 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25u1vibib = 123.0 DEBUG 2020-07-16 13:25:56,155 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25u1vibib DEBUG 2020-07-16 13:25:56,155 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25u2vibob = 123.0 DEBUG 2020-07-16 13:25:56,155 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25u2vibob DEBUG 2020-07-16 13:25:56,155 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25plcpwrf = True DEBUG 2020-07-16 13:25:56,155 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25plcpwrf DEBUG 2020-07-16 13:25:56,155 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25plcfault = True DEBUG 2020-07-16 13:25:56,155 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25plcfault DEBUG 2020-07-16 13:25:56,155 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25moderemacc = True DEBUG 2020-07-16 13:25:56,155 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25moderemacc DEBUG 2020-07-16 13:25:56,155 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25rack1comm = True DEBUG 2020-07-16 13:25:56,155 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25rack1comm DEBUG 2020-07-16 13:25:56,155 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25rack2comm = True DEBUG 2020-07-16 13:25:56,156 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25rack2comm DEBUG 2020-07-16 13:25:56,156 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25rack3comm = True DEBUG 2020-07-16 13:25:56,156 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25rack3comm DEBUG 2020-07-16 13:25:56,156 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25siteman = True DEBUG 2020-07-16 13:25:56,156 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25siteman DEBUG 2020-07-16 13:25:56,156 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25hismp = True DEBUG 2020-07-16 13:25:56,156 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25hismp DEBUG 2020-07-16 13:25:56,156 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25maxsmp = True DEBUG 2020-07-16 13:25:56,156 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25maxsmp DEBUG 2020-07-16 13:25:56,156 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25ows = True DEBUG 2020-07-16 13:25:56,156 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25ows DEBUG 2020-07-16 13:25:56,156 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25hiupstrp = True DEBUG 2020-07-16 13:25:56,156 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25hiupstrp DEBUG 2020-07-16 13:25:56,156 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25charger = True DEBUG 2020-07-16 13:25:56,156 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25charger DEBUG 2020-07-16 13:25:56,157 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25lobat = True DEBUG 2020-07-16 13:25:56,157 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25lobat DEBUG 2020-07-16 13:25:56,157 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25dcinvrtrf = True DEBUG 2020-07-16 13:25:56,157 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25dcinvrtrf DEBUG 2020-07-16 13:25:56,157 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25pwrf = True DEBUG 2020-07-16 13:25:56,157 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25pwrf DEBUG 2020-07-16 13:25:56,157 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25mbtrip = True DEBUG 2020-07-16 13:25:56,157 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25mbtrip DEBUG 2020-07-16 13:25:56,157 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25loopcl = True DEBUG 2020-07-16 13:25:56,157 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25loopcl DEBUG 2020-07-16 13:25:56,157 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25gpelowp = True DEBUG 2020-07-16 13:25:56,157 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25gpelowp DEBUG 2020-07-16 13:25:56,157 (sparkplug-thresh) - DBIRTH --> Device GAM01/GAM01_test_PLC metric gam25cvpct = True DEBUG 2020-07-16 13:25:56,157 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25cvpct DEBUG 2020-07-16 13:26:59,493 (sparkplug-thresh) - DDATA --> Device GAM01/GAM01_test_PLC metric gam25dra = 100.0 DEBUG 2020-07-16 13:26:59,493 (sparkplug-thresh) - Device GAM01/GAM01_test_PLC ignored metric gam25dra