Adding SMV streams
This page describes the steps to write a complete working configuration for receiving IEC 61850 Sampled Values (SMV) using the process_bus plugin together with the phasor plugin.
process_bus plugin replaces the old smv_subscriber plugin. It supports single-interface and PRP dual-interface (IEC 62439-3) operation, and adds diagnostic datapoints for conf_rev mismatches, missing samples, and missing frames per LAN.
Manual configuration
Creating the configuration structure
We assume the process_bus plugin and the phasor plugin run in separate runtimes (publisher and subscriber).
-
-
- process_bus_plugin.json
- runtime.json
-
-
-
- phasor_plugin.json
- runtime.json
-
Minimal runtime files:
{ "description": "Runtime for the process_bus plugin", "runtime_name": "publisher" }{ "description": "Runtime for the phasor plugin", "runtime_name": "subscriber" }Minimal plugin skeleton files:
{
"use_concurrent_publisher": false,
"plugin_name": "process_bus",
"plugin_instance_name": "process_bus_plugin_ens2f0np0",
"plugin_specific_config": {
"ethernet_interfaces": [
{ "name": "ens2f0np0" }
],
"smv_subscribers": []
},
"datapoint_subscriptions": [],
"datapoint_publications": []
}{
"use_concurrent_publisher": false,
"plugin_name": "phasor_plugin",
"plugin_instance_name": "phasor_plugin",
"plugin_specific_config": { "streams": [] },
"datapoint_subscriptions": [],
"datapoint_publications": []
}Adding a data stream
The example below adds one SMV stream: 3 currents + 3 voltages, 4800 samples/s, APPID 0x4001.
smv_id field. By convention it equals the APPID as a lowercase hex string (e.g. APPID 0x4001 → svID "4001").
Configure the process_bus plugin
Add a subscriber entry to plugin_specific_config.smv_subscribers. The dataset array describes the IEC 61850 data objects in the frame; datapoint_mappings maps them to gateway datapoints by obj_ref string.
smv_subscribers entry
{
"smv_id": "4001",
"app_id": "4001",
"sample_rate": 4800,
"conf_rev": {
"expected": 1
},
"dataset": [
{ "obj_ref": "IED1MU01/TCTR1.AmpSv.instMag.i", "type": "INT32" },
{ "obj_ref": "IED1MU01/TCTR1.AmpSv.q", "type": "Quality" },
{ "obj_ref": "IED1MU01/TCTR2.AmpSv.instMag.i", "type": "INT32" },
{ "obj_ref": "IED1MU01/TCTR2.AmpSv.q", "type": "Quality" },
{ "obj_ref": "IED1MU01/TCTR3.AmpSv.instMag.i", "type": "INT32" },
{ "obj_ref": "IED1MU01/TCTR3.AmpSv.q", "type": "Quality" },
{ "obj_ref": "IED1MU01/TVTR1.VolSv.instMag.i", "type": "INT32" },
{ "obj_ref": "IED1MU01/TVTR1.VolSv.q", "type": "Quality" },
{ "obj_ref": "IED1MU01/TVTR2.VolSv.instMag.i", "type": "INT32" },
{ "obj_ref": "IED1MU01/TVTR2.VolSv.q", "type": "Quality" },
{ "obj_ref": "IED1MU01/TVTR3.VolSv.instMag.i", "type": "INT32" },
{ "obj_ref": "IED1MU01/TVTR3.VolSv.q", "type": "Quality" }
],
"datapoint_mappings": [
{ "datapoint": "smv_4001_current_a", "value_obj_ref": "IED1MU01/TCTR1.AmpSv.instMag.i", "quality_obj_ref": "IED1MU01/TCTR1.AmpSv.q" },
{ "datapoint": "smv_4001_current_b", "value_obj_ref": "IED1MU01/TCTR2.AmpSv.instMag.i", "quality_obj_ref": "IED1MU01/TCTR2.AmpSv.q" },
{ "datapoint": "smv_4001_current_c", "value_obj_ref": "IED1MU01/TCTR3.AmpSv.instMag.i", "quality_obj_ref": "IED1MU01/TCTR3.AmpSv.q" },
{ "datapoint": "smv_4001_voltage_a", "value_obj_ref": "IED1MU01/TVTR1.VolSv.instMag.i", "quality_obj_ref": "IED1MU01/TVTR1.VolSv.q" },
{ "datapoint": "smv_4001_voltage_b", "value_obj_ref": "IED1MU01/TVTR2.VolSv.instMag.i", "quality_obj_ref": "IED1MU01/TVTR2.VolSv.q" },
{ "datapoint": "smv_4001_voltage_c", "value_obj_ref": "IED1MU01/TVTR3.VolSv.instMag.i", "quality_obj_ref": "IED1MU01/TVTR3.VolSv.q" }
]
}Then declare the published datapoints:
"datapoint_publications": [
{ "name": "smv_4001_current_a" },
{ "name": "smv_4001_current_b" },
{ "name": "smv_4001_current_c" },
{ "name": "smv_4001_voltage_a" },
{ "name": "smv_4001_voltage_b" },
{ "name": "smv_4001_voltage_c" }
]Full process_bus_plugin.json
{
"use_concurrent_publisher": false,
"plugin_name": "process_bus",
"plugin_instance_name": "process_bus_plugin_ens2f0np0",
"plugin_specific_config": {
"ethernet_interfaces": [
{ "name": "ens2f0np0" }
],
"smv_subscribers": [
{
"smv_id": "4001",
"app_id": "4001",
"sample_rate": 4800,
"conf_rev": { "expected": 1 },
"dataset": [
{ "obj_ref": "IED1MU01/TCTR1.AmpSv.instMag.i", "type": "INT32" },
{ "obj_ref": "IED1MU01/TCTR1.AmpSv.q", "type": "Quality" },
{ "obj_ref": "IED1MU01/TCTR2.AmpSv.instMag.i", "type": "INT32" },
{ "obj_ref": "IED1MU01/TCTR2.AmpSv.q", "type": "Quality" },
{ "obj_ref": "IED1MU01/TCTR3.AmpSv.instMag.i", "type": "INT32" },
{ "obj_ref": "IED1MU01/TCTR3.AmpSv.q", "type": "Quality" },
{ "obj_ref": "IED1MU01/TVTR1.VolSv.instMag.i", "type": "INT32" },
{ "obj_ref": "IED1MU01/TVTR1.VolSv.q", "type": "Quality" },
{ "obj_ref": "IED1MU01/TVTR2.VolSv.instMag.i", "type": "INT32" },
{ "obj_ref": "IED1MU01/TVTR2.VolSv.q", "type": "Quality" },
{ "obj_ref": "IED1MU01/TVTR3.VolSv.instMag.i", "type": "INT32" },
{ "obj_ref": "IED1MU01/TVTR3.VolSv.q", "type": "Quality" }
],
"datapoint_mappings": [
{ "datapoint": "smv_4001_current_a", "value_obj_ref": "IED1MU01/TCTR1.AmpSv.instMag.i", "quality_obj_ref": "IED1MU01/TCTR1.AmpSv.q" },
{ "datapoint": "smv_4001_current_b", "value_obj_ref": "IED1MU01/TCTR2.AmpSv.instMag.i", "quality_obj_ref": "IED1MU01/TCTR2.AmpSv.q" },
{ "datapoint": "smv_4001_current_c", "value_obj_ref": "IED1MU01/TCTR3.AmpSv.instMag.i", "quality_obj_ref": "IED1MU01/TCTR3.AmpSv.q" },
{ "datapoint": "smv_4001_voltage_a", "value_obj_ref": "IED1MU01/TVTR1.VolSv.instMag.i", "quality_obj_ref": "IED1MU01/TVTR1.VolSv.q" },
{ "datapoint": "smv_4001_voltage_b", "value_obj_ref": "IED1MU01/TVTR2.VolSv.instMag.i", "quality_obj_ref": "IED1MU01/TVTR2.VolSv.q" },
{ "datapoint": "smv_4001_voltage_c", "value_obj_ref": "IED1MU01/TVTR3.VolSv.instMag.i", "quality_obj_ref": "IED1MU01/TVTR3.VolSv.q" }
]
}
]
},
"datapoint_subscriptions": [],
"datapoint_publications": [
{ "name": "smv_4001_current_a" },
{ "name": "smv_4001_current_b" },
{ "name": "smv_4001_current_c" },
{ "name": "smv_4001_voltage_a" },
{ "name": "smv_4001_voltage_b" },
{ "name": "smv_4001_voltage_c" }
]
}For the full schema see process_bus plugin specification.
Configure the Phasor plugin
Map each raw datapoint to three output datapoints: RMS magnitude, phase angle, and frequency.
Full phasor_plugin.json
{
"use_concurrent_publisher": false,
"plugin_name": "phasor_plugin",
"plugin_instance_name": "phasor_plugin",
"plugin_specific_config": {
"streams": [
{
"smv_datapoint_name": "smv_4001_current_a",
"smv_sample_rate": 4800,
"smv_data_type": "INT32",
"phasor_frequency": 50,
"cycles_per_phasor_sample": 1,
"rms_datapoint_name": "smv_4001_current_a_rms",
"freq_datapoint_name": "smv_4001_current_a_freq",
"phase_datapoint_name": "smv_4001_current_a_phase"
},
{
"smv_datapoint_name": "smv_4001_current_b",
"smv_sample_rate": 4800,
"smv_data_type": "INT32",
"phasor_frequency": 50,
"cycles_per_phasor_sample": 1,
"rms_datapoint_name": "smv_4001_current_b_rms",
"freq_datapoint_name": "smv_4001_current_b_freq",
"phase_datapoint_name": "smv_4001_current_b_phase"
},
{
"smv_datapoint_name": "smv_4001_current_c",
"smv_sample_rate": 4800,
"smv_data_type": "INT32",
"phasor_frequency": 50,
"cycles_per_phasor_sample": 1,
"rms_datapoint_name": "smv_4001_current_c_rms",
"freq_datapoint_name": "smv_4001_current_c_freq",
"phase_datapoint_name": "smv_4001_current_c_phase"
},
{
"smv_datapoint_name": "smv_4001_voltage_a",
"smv_sample_rate": 4800,
"smv_data_type": "INT32",
"phasor_frequency": 50,
"cycles_per_phasor_sample": 1,
"rms_datapoint_name": "smv_4001_voltage_a_rms",
"freq_datapoint_name": "smv_4001_voltage_a_freq",
"phase_datapoint_name": "smv_4001_voltage_a_phase"
},
{
"smv_datapoint_name": "smv_4001_voltage_b",
"smv_sample_rate": 4800,
"smv_data_type": "INT32",
"phasor_frequency": 50,
"cycles_per_phasor_sample": 1,
"rms_datapoint_name": "smv_4001_voltage_b_rms",
"freq_datapoint_name": "smv_4001_voltage_b_freq",
"phase_datapoint_name": "smv_4001_voltage_b_phase"
},
{
"smv_datapoint_name": "smv_4001_voltage_c",
"smv_sample_rate": 4800,
"smv_data_type": "INT32",
"phasor_frequency": 50,
"cycles_per_phasor_sample": 1,
"rms_datapoint_name": "smv_4001_voltage_c_rms",
"freq_datapoint_name": "smv_4001_voltage_c_freq",
"phase_datapoint_name": "smv_4001_voltage_c_phase"
}
]
},
"datapoint_subscriptions": [
{ "name": "smv_4001_current_a", "mode": "SYNC" },
{ "name": "smv_4001_current_b", "mode": "SYNC" },
{ "name": "smv_4001_current_c", "mode": "SYNC" },
{ "name": "smv_4001_voltage_a", "mode": "SYNC" },
{ "name": "smv_4001_voltage_b", "mode": "SYNC" },
{ "name": "smv_4001_voltage_c", "mode": "SYNC" }
],
"datapoint_publications": [
{ "name": "smv_4001_current_a_rms" },
{ "name": "smv_4001_current_a_freq" },
{ "name": "smv_4001_current_a_phase" },
{ "name": "smv_4001_current_b_rms" },
{ "name": "smv_4001_current_b_freq" },
{ "name": "smv_4001_current_b_phase" },
{ "name": "smv_4001_current_c_rms" },
{ "name": "smv_4001_current_c_freq" },
{ "name": "smv_4001_current_c_phase" },
{ "name": "smv_4001_voltage_a_rms" },
{ "name": "smv_4001_voltage_a_freq" },
{ "name": "smv_4001_voltage_a_phase" },
{ "name": "smv_4001_voltage_b_rms" },
{ "name": "smv_4001_voltage_b_freq" },
{ "name": "smv_4001_voltage_b_phase" },
{ "name": "smv_4001_voltage_c_rms" },
{ "name": "smv_4001_voltage_c_freq" },
{ "name": "smv_4001_voltage_c_phase" }
]
}For more details see Phasor plugin specification.
Add datapoints to config.json
All datapoints referenced in the plugin configs must be declared in config.json. Raw waveform datapoints should have a buffer_size equal to at least one cycle at the configured sample rate (1000 for 4800 Hz / 50 Hz).
config.json
{
"datapoints": [
{ "name": "smv_4001_current_a", "description": "Current A raw samples", "unit": "mA", "buffer_size": 1000 },
{ "name": "smv_4001_current_b", "description": "Current B raw samples", "unit": "mA", "buffer_size": 1000 },
{ "name": "smv_4001_current_c", "description": "Current C raw samples", "unit": "mA", "buffer_size": 1000 },
{ "name": "smv_4001_voltage_a", "description": "Voltage A raw samples", "unit": "V", "buffer_size": 1000 },
{ "name": "smv_4001_voltage_b", "description": "Voltage B raw samples", "unit": "V", "buffer_size": 1000 },
{ "name": "smv_4001_voltage_c", "description": "Voltage C raw samples", "unit": "V", "buffer_size": 1000 },
{ "name": "smv_4001_current_a_rms", "description": "Current A RMS", "unit": "mA" },
{ "name": "smv_4001_current_a_freq", "description": "Current A frequency", "unit": "Hz" },
{ "name": "smv_4001_current_a_phase", "description": "Current A phase", "unit": "rad" },
{ "name": "smv_4001_current_b_rms", "description": "Current B RMS", "unit": "mA" },
{ "name": "smv_4001_current_b_freq", "description": "Current B frequency", "unit": "Hz" },
{ "name": "smv_4001_current_b_phase", "description": "Current B phase", "unit": "rad" },
{ "name": "smv_4001_current_c_rms", "description": "Current C RMS", "unit": "mA" },
{ "name": "smv_4001_current_c_freq", "description": "Current C frequency", "unit": "Hz" },
{ "name": "smv_4001_current_c_phase", "description": "Current C phase", "unit": "rad" },
{ "name": "smv_4001_voltage_a_rms", "description": "Voltage A RMS", "unit": "V" },
{ "name": "smv_4001_voltage_a_freq", "description": "Voltage A frequency", "unit": "Hz" },
{ "name": "smv_4001_voltage_a_phase", "description": "Voltage A phase", "unit": "rad" },
{ "name": "smv_4001_voltage_b_rms", "description": "Voltage B RMS", "unit": "V" },
{ "name": "smv_4001_voltage_b_freq", "description": "Voltage B frequency", "unit": "Hz" },
{ "name": "smv_4001_voltage_b_phase", "description": "Voltage B phase", "unit": "rad" },
{ "name": "smv_4001_voltage_c_rms", "description": "Voltage C RMS", "unit": "V" },
{ "name": "smv_4001_voltage_c_freq", "description": "Voltage C frequency", "unit": "Hz" },
{ "name": "smv_4001_voltage_c_phase", "description": "Voltage C phase", "unit": "rad" }
]
}More details: Datapoint configuration specification.
PRP redundancy
PRP provides seamless failover by sending every SMV frame over two independent LANs. The process_bus plugin deduplicates frames using the sequence number, so each frame is published exactly once regardless of which LAN delivers it first. Per-LAN missing-frame counts are tracked independently.
To enable PRP, provide two entries in ethernet_interfaces instead of one:
"ethernet_interfaces": [
{ "name": "eth0", "on_missing_frame_datapoint": "missing_frames_eth0" },
{ "name": "eth1", "on_missing_frame_datapoint": "missing_frames_eth1" }
]The on_missing_frame_datapoint fields are optional but recommended: the plugin writes the number of frames that arrived on one LAN but not the other (within the deduplication window) to those datapoints. They are per-interface counters — one shared across all subscribers on that plugin instance.
These datapoints must be added to config.json and datapoint_publications:
{ "name": "missing_frames_eth0", "description": "Missing frames on LAN A", "unit": "" },
{ "name": "missing_frames_eth1", "description": "Missing frames on LAN B", "unit": "" }Diagnostic datapoints
The following optional diagnostic datapoints can be configured per SMV subscriber to monitor stream health.
Missing samples
on_missing_sample_datapoint is updated whenever expected samples are not received within a cycle. Useful for detecting merging unit issues or network congestion.
{
"smv_id": "4001",
"app_id": "4001",
"sample_rate": 4800,
"conf_rev": { "expected": 1 },
"on_missing_sample_datapoint": "smv_4001_missing_samples",
"dataset": [ ... ],
"datapoint_mappings": [ ... ]
}Configuration revision mismatch
conf_rev.on_conf_rev_mismatch_datapoint is set to a non-zero value when a received frame carries a confRev that does not match the configured expected value. This indicates the merging unit dataset definition has changed.
"conf_rev": {
"expected": 1,
"on_conf_rev_mismatch_datapoint": "smv_4001_conf_rev_mismatch"
}Complete example with all diagnostics
The following shows a subscriber with all diagnostic datapoints enabled and PRP:
process_bus_plugin.json (with PRP + diagnostics)
{
"use_concurrent_publisher": false,
"plugin_name": "process_bus",
"plugin_instance_name": "process_bus_plugin_eth0_eth1",
"plugin_specific_config": {
"ethernet_interfaces": [
{ "name": "eth0", "on_missing_frame_datapoint": "missing_frames_eth0" },
{ "name": "eth1", "on_missing_frame_datapoint": "missing_frames_eth1" }
],
"smv_subscribers": [
{
"smv_id": "4001",
"app_id": "4001",
"sample_rate": 4800,
"conf_rev": {
"expected": 1,
"on_conf_rev_mismatch_datapoint": "smv_4001_conf_rev_mismatch"
},
"on_missing_sample_datapoint": "smv_4001_missing_samples",
"dataset": [
{ "obj_ref": "IED1MU01/TCTR1.AmpSv.instMag.i", "type": "INT32" },
{ "obj_ref": "IED1MU01/TCTR1.AmpSv.q", "type": "Quality" },
{ "obj_ref": "IED1MU01/TVTR1.VolSv.instMag.i", "type": "INT32" },
{ "obj_ref": "IED1MU01/TVTR1.VolSv.q", "type": "Quality" }
],
"datapoint_mappings": [
{ "datapoint": "smv_4001_current_a", "value_obj_ref": "IED1MU01/TCTR1.AmpSv.instMag.i", "quality_obj_ref": "IED1MU01/TCTR1.AmpSv.q" },
{ "datapoint": "smv_4001_voltage_a", "value_obj_ref": "IED1MU01/TVTR1.VolSv.instMag.i", "quality_obj_ref": "IED1MU01/TVTR1.VolSv.q" }
]
}
]
},
"datapoint_subscriptions": [],
"datapoint_publications": [
{ "name": "missing_frames_eth0" },
{ "name": "missing_frames_eth1" },
{ "name": "smv_4001_current_a" },
{ "name": "smv_4001_voltage_a" },
{ "name": "smv_4001_conf_rev_mismatch" },
{ "name": "smv_4001_missing_samples" }
]
}All diagnostic datapoints must be declared in config.json:
{ "name": "missing_frames_eth0", "description": "Missing frames on LAN A", "unit": "" },
{ "name": "missing_frames_eth1", "description": "Missing frames on LAN B", "unit": "" },
{ "name": "smv_4001_conf_rev_mismatch", "description": "confRev mismatch stream 4001", "unit": "" },
{ "name": "smv_4001_missing_samples", "description": "Missing samples stream 4001", "unit": "" }