Skip to content

29. Modbus Device

This project provides SolarNode plugin that can collect arbitrary data from Modbus enabled devices. This is an advanced plugin that requires specific low-level knowledge of the device you want to collect data from.

This datum source is provided by the Modbus Datum Source plugin, which is included in the solarnode-app-modbus package in SolarNodeOS.

29.1 Use

Once installed, a new Modbus Device component will appear on the Settings > Components page on your SolarNode. Click on the Manage button to configure devices. You'll need to add one configuration for each Modbus device you want to collect data from.

You can also configure components with the CSV Configurer, detailed in the following section.

29.2 CSV Configurer

This plugin provides a Modbus Device CSV Configurer service will appear on the Settings > Services page. This service lets you upload a Modbus CSV Configuration file to configure all Modbus Device components, without having to use the settings form directly.

CSV Configurer settings

29.2.1 Modbus CSV Configuration Format

The Modbus CSV Configuration uses the column structure detailed below, with each row representing an individual datum property to read from the Modbus device. A header row is required. Comment lines are allowed, just start the line with a # character (i.e. the first cell value). The entire comment line will be ignored.

Here's an example screen shot of a configuration in a spreadsheet application. It is for two devices:

  1. Device P1 with 4 datum properties: error, current, voltage, and wattHours
  2. Device P2 with 2 datum properties: frequency and watts

Spreadsheet applications generally allows you to export the sheet in the CSV format, which can then be loaded into SolarNode via the CSV Configurer.

CSV Configuration example

Tip

You can copy this example sheet to get started.

29.2.1.1 Instance identifiers

Individual Modbus Device components are defined by the first column (Instance ID). You can assign any identifier you like (such as Meter, Inverter, and so on) or configure as a single dash character - to have SolarNode assign a simple number identifier. Once an Instance ID has been assigned on a given row, subsequent rows will use that value if the corresponding cell value is left empty.

Here's an example of how 3 custom instance IDs Meter, Pyranometer, and Weather appear in the SolarNode UI:

Modbus Device instance names

29.2.1.2 CSV column definition

The following table defines all the CSV columns used by Modbus Device CSV Configuration. Columns A - H apply to the entire Modbus Device configuration, and only the values from the row that defines a new Instance ID will be used to configure the device. Thus you can omit the values from these columns when defining more than one property for a given device.

Columns I - Q define the mapping of Modbus registers to datum properties: each row defines an individual datum property.

Col Name Type Default Description
A Instance ID string The unique identifier for a single Modbus Device component. Can specify - to automatically assign a simple number value, which will start at 1.
B Source ID string The SolarNetwork datum source ID to use for the datum stream generated by this device configuration.
C Schedule string 0 * * * * * The schedule at which to poll the Modbus device for data. Can be either a cron value or a millisecond frequency.
D Connection string Modbus Port The Service Name of the Modbus connection to use.
E Unit ID integer 1 The Modbus unit ID of the device to collect data from (1 - 255).
F Sample Cache integer 5000 A minimum time to cache captured Modbus data, in milliseconds.
G Max Read integer 64 The maximum number of Modbus registers to request at once.
H Word Order enum Most to least For multi-register data types, the ordering to use when combining them. Must be either Most to least or Least to most, and can be shortened to just m or l.
I Property string The name of the datum property to save the Modbus value as.
J Property Type enum Instantaneous The type of datum property to use. Must be one of Instantaneous, Accumulating, Status, Tag, or Metadata, and can be shortened to just i, a, s, t, or m.
K Register integer The register address to read Modbus data from (zero-based). For multi-register data types this is the first register to read from.
L Register Type enum Holding The Modbus read function to execute. Must be one of Coil, Discrete Input, Holding, or Input.
M Data Type enum 32-bit float The type of data to expect from the read Modbus register(s). Must be one of Boolean or bit, 16-bit float or f16, 32-bit float or f32, 16-bit signed int or i16, 16-bit unsigned int or u16, 32-bit signed int or i32, 32-bit unsigned int or u32, 64-bit signed int or i64, 64-bit unsigned int or u16, Bytes or b, String UTF-8 or s, String ASCII or a.
N Data Length integer For variable length data types such as strings, the number of Modbus registers to read.
O Multiplier decimal 1 For numeric data types, a multiplier to apply to the Modbus value to normalize it into a standard unit.
P Decimal Scale integer 0 For numeric data types, a maximum number of decimal places to round decimal numbers to, or -1 to not do any rounding.
Q Expression string An expression. If configured, columns K - P are ignored.

29.2.2 Example CSV

Here is the CSV as shown in the example configuration screen shot above (comments have been removed for brevity):

Instance ID,Source ID,Schedule,Connection,Unit ID,Sample Cache,Max Read,Word Order,Property,Property Type,Register,Register Type,Data Type,Data Length,Multiplier,Decimal Scale,Expression
P1,power/1,0 * * * * *,Modbus Port,1,5000,64,Most to least,,,,,,,,,
,,,,,,,,error,Status,1000,Holding,String ASCII,16,,,
,,,,,,,,current,Instantaneous,0,Holding,32-bit float,,1,-1,
,,,,,,,,voltage,Instantaneous,2,Holding,32-bit float,,1,1,
,,,,,,,,wattHours,Accumulating,70,Holding,64-bit unsigned int,,,,
P2,power/2,0 * * * * *,Modbus Port,2,5000,64,Most to least,frequency,Instantaneous,10,Input,16-bit unsigned int,,0.01,,
,,,,,,,,watts,Instantaneous,11,Input,32-bit unsigned int,,,,

29.3 Settings

Modbus Device Datum Source settings

Each configuration contains the following overall settings:

Setting Description
Schedule A cron schedule that determines when data is collected, or millisecond frequency.
Service Name A unique name to identify this data source with.
Service Group A group name to associate this data source with.
Modbus Connection The Service Name of the Modbus connection to use.
Modbus Unit ID The ID of the Modbus device to collect data from, from 1 - 255.
Source ID The SolarNetwork unique source ID to assign to datum collected from this device.
Sample Maximum Age A minimum time to cache captured Modbus data, in milliseconds.
Max Read Length The maximum number of Modbus registers to request at once.
Word Order For multi-register data types, the ordering to use when combining them.
Datum Filter Service The Service Name of a datum filter to apply. Note that configuring global datum filters is generally more flexible.
Sub-sample Frequency If configured, the frequency at which samples should be collected from the device, in milliseconds. Set to 0 (or empty) to disable. Typically this would be combined with a Datum Filter Service to transform the sub-samples. See the Sub-sampling section for more information. Note that the Downsample Filter can be used to accomplish the same thing.

29.3.1 Overall settings notes

Modbus Port
This is the Service Name of the Modbus component configured elsewhere in SolarNode. You must configure that component with the proper connection settings for your Modbus network, configure a unique service name on that component, and then enter that same service name here.
Source ID
This value unique identifies the data collected from this device, by this node, on SolarNetwork. Each configured device should use a different value.
Sample Maximum Age
SolarNode will cache the data collected from the Modbus device for at least this amount of time before refreshing data from the device again. Some devices do not refresh their values more than a fixed interval, so this setting can be used to avoid reading data unnecessarily. This setting also helps in highly dynamic configurations where other plugins request the current values from the device frequently.
Max Read Length
This plugin will try to read as many adjacent Modbus registers as possible when requesting data from the device. Some devices have trouble returning large numbers of registers at once, however. Configuring this setting to a smaller value will cause the plugin to make multiple smaller requests for data when necessary to work better with those devices.

29.3.2 Metadata settings

Metadata settings allow you to add datum source metadata to the configured datum stream.

Metadata settings

Each metadata configuration contains the following settings:

Setting Description
Name The metadata key. If starts with a / then will be treated as a key-path. Valid paths start with one of /m/, /pm/, and /t.
Value The metadata value.

29.3.3 Datum property settings

You must configure settings for each datum property you want to collect from each device. You can configure as many property settings as you like, using the + and - buttons to add/remove property configurations.

Property settings

Each property configuration contains the following settings:

Setting Description
Property The name of the datum property to save the Modbus value as. Property names represent what the associated data value is, and SolarNetwork has many standardized names that you should consider using. For example the EnergyDatum class defines properties such as watts and wattHours for electrical energy. ⚠ See the note about the Metadata property type for more information about the property name syntax for that type.
Property Type The type of datum property to use. Each property must be categorized as Accumulating, Instantaneous, Status, or Metadata. Accumulating is used for properties that record a value that accumulates over time, such as wattHours captured from a power meter. Instantaneous is used for properties that capture values that record independent values over time, such as watts. Status is used for non-numeric values such as string status messages. Metadata is for mostly unchanging data, like a device serial number or firmware version. The property names for metadata should be a metadata path, for example /pm/deviceInfo/serialNumber.
Modbus Address The starting register address to read Modbus data from (zero-based).
Modbus Function The Modbus read function to execute.
Data Type The type of data to expect from the read Modbus register(s). The data type to interpret the values captured from the Modbus registers as. Note that only the Status and Metadata property types can accept non-numeric data types such as strings.
Data Length For variable length data types such as strings, the number of Modbus registers to read.
Unit Multiplier For numeric data types, a multiplier to apply to the Modbus value to normalize it into a standard unit. The property values stored in SolarNetwork should be normalized into standard base units if possible. For example if a power meter reports power in kilowattts then a unit multiplier of 1000 can be used to convert the values into watts.
Decimal Scale For numeric data types, a maximum number of decimal places to round decimal numbers to, or -1 to not do any rounding. This setting will round decimal numbers to at most this number of decimal places. Setting to 0 rounds decimals to whole numbers. Setting to -1 disables rounding completely.

29.3.4 Expressions

Properties can be defined using expressions. Expressions allow you to configure datum properties that are dynamically calculated from other properties or raw Modbus register values.

Expressions settings

29.3.4.1 Expression root object

The root object is a DatumExpressionRoot that lets you treat all datum properties as expression variables directly. See the SolarNode Expressions guide for more information. In addition, the following properties are available:

Property Type Description
datum GeneralNodeDatum A GeneralNodeDatum object, populated with data from all property and virtual meter configurations.
props Map<String,Object> Simple Map based access to the data in datum, to simplify expressions.
sample ModbusData A ModbusData object, populated with the raw Modbus holding register data read from the device.
regs Map<Integer,Integer> Simple Map based access to the register data in sample, to simplify expressions all register values are returned as unsigned 16-bit integers.

Any Modbus registers referenced via reg[x] expressions will be automatically read via the Modbus read holding register function, unless that same register is referenced also in a normal property configuration, in which case the Modus function defined there will be used.

29.3.4.2 Expression examples

Given raw Modbus holding register data like the following:

[000]: 0xfc1e, 0xf0c3, 0x02e3, 0x68e7, 0x0002, 0x1376, 0x1512, 0xdfee
[200]: 0x44f6, 0xc651, 0x4172, 0xd3d1, 0x6328, 0x8ce7

and assuming a property config that maps register 202 to a 64-bit floating point property bigFloat:

Then here are some example expressions and the results they would produce:

Expression Result Comment
regs[0] 64542 Returns register 0 directly, which is 0xfc1e.
sample.getInt32(2) 48457959 Returns holding registers 2 and 3 combined as a unsigned 32-bit integer 0x02e368e7.
sample.getFloat32(200) 1974.1974 Returns holding registers 200 and 201 as a IEEE-754 32-bit floating point: 0x44f6c651.
props['bigFloat'] - regs[0] 19677432.1974 Returns difference of register 0 (0xfc1e) from datum property bigFloat (0x4172d3d163288ce7).

29.4 Sub-sampling

The Sub-sample Frequency setting allows you to configure the datum source to generate datum (referred to as a sample here) at a higher rate than the normal Schedule dictates. This would typically be combined with the Datum Filter Service setting, to enable filtering the sub-sample datum into some sort of aggregate at the "normal" sample rate.

For example, you might want to collect datum at a rate of once per minute but achieve better accuracy in each property value by capturing several values per minute and only saving the average of those captured values in SolarNetwork.

Tip

Note that this type of average sub-sampling can be achieved more simply by configuring the Schedule of this (or any datum source) to the desired "sub-sample" rate and adding a Downsample Filter with an appropriate Count value to reduce the frequency to your desired "normal" rate.

Here is an example of the settings you would configure to do this, with a sub-sample rate of once per second:

Setting Value Description
Schedule 60000 Capture "normal" datum once per minute
Sub-sample Frequency 1000 Capture "sub-sample" datum once per second
Datum Filter Service My Sub-Sample Downsample Filter The service name of the filter to apply.

In this example, My Sub-Sample Throttle Filter is a Downsample Filter configured with these settings:

Setting Value Description
Service Name My Sub-Sample Downsample Filter Same service name used also in the Modbus Device settings
Sample Count 60 Aggregate 60 samples into 1 output, because we expect 60 samples per minute

29.4.1 Sub-sample filter properties

The configured Datum Filter Service will be passed every datum captured, both sub-samples and "normal" samples. Each sub-sample datum will be passed a special subsample=true parameter, however, so the filter "knows" which datum are sub-samples and which are "normal" samples.