For the complete documentation index, see llms.txt. This page is also available as Markdown.

Modbus Plugin

Purpose

Purpose of this plugin is to read from Modbus Servers.

Usage

You run a log to send data to the cloud, or a discover to only display information. There must be a config file when running log or a discover. The config file defines which variables need to be collected, what names they appear on the the Ardexa cloud, units and scaling, what table(s) they variables will be sent to, and the source name(s). Example config file as follows. Always verify data accuracy by running a discover first, before committing the plugin to collect data. Also note carefully: The configuration file specifies the use of the mbpoll command. However, this new version of Modbus Ardexa is based on the Rust language and does not use mbpoll. It remains for compatibility purposes.

    #
    # This is the Modbus config file
    #
    # Commands
    # These are the commands to run
    _cmd, mbpoll -m rtu -r 1101 -c 110 -t 4 -1 -p {PORT} {ENDPOINT}
    _cmd, mbpoll -m tcp -r 1275 -c 10  -t 4 -1 -p {PORT} {ENDPOINT} --translate 50000
    _cmd, mbpoll -m {TCP_RTU} -r 1275 -c 10  -t 4 -1 -p {PORT} {ENDPOINT} --translate 50000
    _cmd, mbpoll -m enc -r 1275 -c 10  -t 4 -1 -p {PORT} {ENDPOINT} --translate 50000


    # Table,    Source Name,    Variable Name,      Register,   Num of Regs,   Type,        Units,  Scale,  RO/RW/INV,      Lookup Table,                   Sum/Conditional Registers,      Conditional Bit
    solar,      inverter,       AC Voltage 1,       1101,       1,             dec,         V,      1+10,   RO, 
    solar,      inverter,       Grid Freq,          1104,       1,             dec,         Hz,     0.01,   RO, 
    solar,      inverter,       Cos Phi,            1111,       1,             dec,         .,      100,    RO, 
    solar,      inverter,       Temperature,        1167,       1,             udec,        C,      1,      RO, 

    turbine,    eng,            Status,             1275,       1,             int8,        ,       1,      RO,             /home/ardexa/status.dict
    turbine,    eng,            Minutes,            75,         1,             lo8,         ,       1,      RO,
    turbine,    eng,            Seconds,            76,         1,             hi8,         ,       1,      RO,
    turbine,    eng,            Total Hours,        1208,       1,             ge_fix,      h,      0.1,    RO, 
    turbine,    eng,            Total Hours,        1208,       1,             dec,         h,      0.1,    RO, 
    turbine,    eng,            DC Current 1,       1221,       1,             dec,         A,      1,      RO, 
    turbine,    eng,            DC Current 17,      21,         4e,            dec,         A,      1,      RO, 

    PLC_710,    hec,            DC Current Sum,     0,          1,             sum,         A,      1,      RO,             ,                               1221 1222 1223 1224 1225
    PLC_710,    hec,            Total Energy,       0,          1,             after,       Wh,     1,      RO,             ,                               1194 1196
    PLC_710,    hec,            Setpoint Mode,      77,         1,             bitb,        bool,   1,      RO,             1
    PLC_710,    hec,            Run Auto,           71,         1,             bitb,        bool,   1,      RO,             2
    PLC_710,    hec,            Run Manual,         71,         1,             bitb_int,    bool,   1,      RO,             3
    PLC_710,    hec,            Key Switch,         30227,      1,             str,         ,       1,      RO,             /home/ardexa/sma_central/mode.dict
    PLC_710,    hec,            Brand Name,         1133,       1,             str,         ,       10,     RO,
    PLC_710,    hec,            Key Switch2,        30227,      1,             str_rep,     ,       1,      RO,             /home/ardexa/sma_central/mode.dict
    PLC_710,    ibm,            Key Switch543,      312,        8,             str_rev,     ,       1,      RO,             /home/ardexa/sma_central/reverse.dict
    PLC_710,    pid_box,        Voltage,            17,         1,             int,         V,      1,      RO, 
    PLC_710,    pid_box,        Current,            18,         1,             int,         mA,     1,      RO,

    Station,    alarm,          Alarm 0 Keyword,    4000,       1,             bit,         ,       1,      RO,             /home/ardexa/ess_modbus/dict/container_alarm0.dict
    Station,    alarm,          Alarm 1 Keyword,    4001,       1,             bit,         ,       1,      RO,             /home/ardexa/ess_modbus/dict/container_alarm1.dict
    Station,    alarm,          Alarm 2 Keyword,    4002,       1,             bit,         ,       1,      RO,             /home/ardexa/ess_modbus/dict/container_alarm2.dict
    Station,    alarm,          Alarm 3 Keyword,    4003,       1,             bit,         ,       1,      RO,             /home/ardexa/ess_modbus/dict/container_alarm3.dict
    Station,    alarm,          Alarm 1,            4001,       1,             bool,        ,       1,      RO,
    Station,    alarm,          Alarm 2,            4002,       1,             bool,        ,       1,      RO, 
    Station,    alarm,          Alarm 3,            4003,       1,             bool,        ,       1,      RO,
    Station,    alarm,          Alarm 4,            4004,       1,             int_bool,    ,       1,      RO,
    PLC_710,    hec,            DC Current 2,       1222,       1,             swap16,      A,      0.1,    RO, 

    weather,    status,         Status1,            35,         1,             cond_bit,    ,       1,      RO,             /home/ardexa/conditional.dict,  45,                             1
    weather,    status,         Status2,            36,         1,             cond_bit,    ,       1,      RO,             /home/ardexa/conditional.dict,  45,                             2
    weather,    status,         Status3,            37,         1,             cond_bit,    ,       1,      RO,             /home/ardexa/conditional.dict,  45,                             3
    weather,    status,         Daytime Status,     309,        1,             mask,        ,       1,      RO,             /home/ardexa/daytime.dict,      2,                              4
    weather,    hyc,            Total Current,      12,         1,             dec,         h,      0.1,    >100000,
    weather,    status,         Binary Status Raw,  356,        1,             bin,         ,       1,      RO,
    weather,    ATC,            AC Power 1,         365,        1,             log_scale,   W,      3,      RO,             569
    weather,    ATC,            AC Power 4,         365,        1,             reg_scale,   W,      0.1,    RO,             565
    weather,    ATC,            AC Power 5,         365,        1,             reg_scale,   W,      0.1,    RO,             565,    /home/ardexa/reg_scale_lookup.dict

    battery,    module,         DC Current 1,       64,         1,             depend,      A,      0.1,    RO,             2456,       1
    battery,    module,         DC Current 2,       65,         1,             depend,      A,      0.1,    RO,             2457,       2
    battery,    module,         DC Current 3,       66,         1,             depend,      A,      0.1,    RO,             2458,       1
    battery,    module,         DC Current 4,       67,         1,             depend,      A,      0.1,    RO,             2459,       2
    battery,    module,         AC Power,           87,         1,             master,      W,      1,      RO,             111
    battery,    module,         AC Power,           97,         1,             slave,       W,      1,      RO,             111
  • Notes:

  1. _cmd is the commands to run. Also note carefully: The configuration file specifies the use of the mbpoll or modpoll commands ot collect data. However, this Modbus plugin is based on the Rust language and does not use either tool. It remains for compatibility purposes only. If the token {TCP_RTU} is used in the type ('m) argument, then the plugin will automatically work with type is required. If the command is hardtype (ie; using tcp or rtu or enc, then the plugin WILL NOT work out which type is required. Note using the keyword enc means RTU encapsulated over TCP. The registers being collected MUST MATCH the registers listed in the configuration items. If not, you will have empty fields when running a discover. If the registers in _cmd commands overlap, then there could be unexpected errors. Make sure each output of the _cmd commands do not overlap. The phrase --translate can be included in a modbus command. It MUST appear in lower case and at the end of the command. If used, it will scale (by adding), all the register values. It will hence have the effect of translating them to another set of registers, so as they do not "collide" with the registers from another command.

  2. Scale will only be used for decimal and integer types. An error will be reported if you try and divide an integer, or multiply by anything other than a whole number. The scale can also be a value such as 0.75-9, where the -9 is a BIAS value (addition or subtraction). In which case it will FIRST subtract the 9, THEN multiply by 0.75. If using a bias value, then it can ONLY be used with a decimal type.

  3. RO/RW/INV. This column will only do the following task": If an entry starts with >, it will invalidate ALL entries in a configuration file, if the absolute value (+ or -) for this entry is greater than the specified amount. For example; if the RO/RW/INV column entry is >10000, then a value of 12,000 will ensure ALL readings in the configuration file are invalidated. Use this item with caution. Also, it will ONLY work on dec values. This invalidation feature is intended for those machines that have poor quality control, and sometimes transmit wildly wrong values.

  4. In Num of Regs; Sometimes you may need to read two (32 bit) or four (64 bit) consecutive registers, to form a floating point or integer number, rather than a single register (16 bit) or a double (32 bit) register. You can use the :int or :float arguments in mbpoll to get 32 bit numbers. Another way to get 2 registers, OR to get 4 registers (64 bits) together, then include 2 or 4 in the Num of Regs columns. Note that if you use a number value of 2e or 4e, it will reverse the endianess. This is applicable ONLY for dec and int value types. Also, be very careful to note the following: You must call in the registers as 16 bit register. That is to say; DO NOT use the :float or :int (32 bit) arguments in the mbpoll command. eg DO NOT USE something like this: mbpoll -m rtu -r 1101 -c 110 -t 4:float -1 -p {PORT} {ENDPOINT}. Make sure you craft the mbpoll command as something like this: mbpoll -m rtu -r 1101 -c 110 -t 4 -1 -p {PORT} {ENDPOINT}.

  5. In Lookup Table; Sometimes you want to convert an INT to a keyword, through a lookup table. Or you may want to get a register bit and convert it to a keyword.

  6. Allowable Type are as follows:

  • dec ... Converts the modbus register to a decimal. Can be scaled (including division).

  • swap16 ... Swaps the modbus register's endianess and converts it to a decimal. Can be scaled (including division).

  • udec ... This will convert the register to unsigned first, then convert the modbus register to a decimal. Can be scaled (including division). Only works on 16 bit registers.

  • int ... Converts the modbus register to an integer. Can only be scaled upwards (not divided). So a scale value that is not a whole number will be rejected. See also the explanation for scale above, since it can include a bias and scale factor.

  • bit ... Used with a lookup table (in the Lookup Table column) to define a bit being turned or off. See example contents of file below. Bits start at "1" (not "0"), and are defined in the Lookup Table column. This function will accept a 32 bit number, so long as the number is read as a 32:int (32 bit integer) number.

  • bitb ... If a bit in the modbus register is turned on/off, it will reflect a boolean ("True"/"False") output. Bits start at "1" (not "0"). This function will accept a 32 bit number, so long as the number is read as a 32:int (32 bit integer) number.

  • bitb_int ... If a bit in the modbus register is turned on/off, it will reflect a boolean ("1"/"0") output. Bits start at "1" (not "0"). This function will accept a 32 bit number, so long as the number is read as a 32:int (32 bit integer) number.

  • str ... Treated as an ASCII character. If it can't be converted, it will output an empty field. If this field is NOT used with a dict file, then the ASCII characters will be displayed. See the example above. If a dict file is included, the resultant string will be looked up using the dict file. If the str cannot be found, the raw value will be displayed.

  • str_rep ... Same as str, but it will clear \0 values in the resultant string.

  • str_rev ... Treated as an ASCII character. If it can't be converted, it will output an empty field. If this field is NOT used with a dict file, then the ASCII characters will be displayed. See the example above. If a dict file is included, the resultant string will be looked up using the dict file. If the str cannot be found, the raw value will be displayed. In the str_rev dictionary lookup, BOTH the key and value are treated as strings. So there is no conversion being done. See the section below called "## Example of "str_rev" lookup"

  • bool ... Modbus register is converted to an INT. This value is then check as follows: Anything other than 0 will output a True. Else, output will be False.

  • int_bool ... Modbus register is converted to an INT. This value is then check as follows: Anything other than 0 will output a 1. Else, output will be 0.

  • bin ... Converts the modbus register to an integer, then to a binary representation. This function will accept a 32 bit number, so long as the number is read as a 32:int (32 bit integer) number. Also note that the final binary display will always be a 32 bit long binary representation, regardless of the input

  • int8 ... Mask out the first 8 bits of an Modbus integer, then use a lookup file

  • hi8 ... Mask out the first (low) 8 bits of an Modbus integer

  • lo8 ... Mask out the last (high) 8 bits of an Modbus integer

  • sum ... This is to sum the values of specific registers. In this case the Register field MUST be set to 0 and the registers to sum is a list in Summation Registers separated by spaces only

  • after ... This is the same as sum, but each register is added AFTER the scale and bias line. You MUST have the register set to 0 This means 2 things: a. The register to be added must exist as a separate line, and b. The after line must appear AFTER ALL the registers to be added.

  • cond_bit ... This type will use the CONTENTS of the register listed in the Sum/Conditional Registers and whether the bit detailed in the Register and Conditional Bit column are 1 to then display the result of the lookup table. See the entry below on how this feature works.

  • mask ... Mask out the Modbus integer based on the bits listed in the last 2 entries (bits 2 to 4 in the example - Bits start at "1" (not "0")) And use the resultant integer to lookup up and keyword

  • log_scale ... This will log scale the register, based on the contents of another register. In the example above, the final result will be:result = scale * (contents_of_register(365) * 10 ** (contents_of_register(569)-3)))

  • reg_scale ... This will scale the register, based on the contents of another register. In the example above, the final result will be:result = scale * (contents_of_register(365) * contents_of_register(569)) This item can have a lookup file, as per the examples above. The reg scale lookup file example is shown below in "## Example of "reg_scale" lookup file" Remember: In the case of a reg_Scale lookup file, the final number is calculated as follows:result = scale * (contents_of_register(365) * ( contents_of_register(569) looked up pin the file /home/ardexa/reg_scale_lookup.dict) If the value of the contents_of_register(569) does not exist in the lookup file, then the value of contents_of_register(569) will be used

  • depend ... This will read the contents of the Lookup Table, the "depend register" (2456/7/8/9 in the above example). If the depend number, which is the next column in the config file, exceeds the value of the contents of the "depend register", then the particular line will be ignored. Otherwise it will collect the data and treat it as a DECIMAL value.

  • master ... This will read the contents of the Lookup Table, the "master register" (110 in the above example). If the master register content is 1, it will collect the data and treat it as a DECIMAL value. If it is 0, then the particular line will be ignored.note. When doing a discovery using a MASTER/SLAVE type, it will show BOTH TYPES, but only one will be populated.

  • slave ... This will read the contents of the Lookup Table, the "master register" (111 in the above example). If the master register content is 0, it will collect the data and treat it as a DECIMAL value. If it is 1, then the particular line will be ignored.note. When doing a discovery using a MASTER/SLAVE type, it will show BOTH TYPES, but only one will be populated.

  • ge_fix ... This is used to convert a modbus integer to a signed integer using the "Signed Magnitude Method" discussed in: https://www.geeksforgeeks.org/representation-of-negative-binary-numbers/ The conversion will be handled during the early parts of processing, and then the value will be converted to DECIMAL

  1. There are up to 11 columns. Only the first 8 (up to and including the RO/RW column) are required.

  2. A lookup file must be defined for the type bit and cond_bit

Arguments

Arguments are as follows:

  • discover or log. This is the action as to whether discover data or log the data (send it to the cloud)

  • config_path. This is the path to the configuration file

  • endpoint. This is either a serial device like /dev/ttyS0 or an IP or DNS like 192.168.1.15

  • --bus_addresses. A Modbus address in the range 2-255. This can be a hyphenated list like 3-10 or a list like 2,5,7,9. The default is 1

  • --port. This is an optional parameter used in an Ethernet gateway, and is the TCP port used for the gateway. Default is 502

  • --attempts. This is an optional parameter, and determines how many times to times to attempt to read an inverter value. Default is 3

  • --delay. This is the delay in seconds between modbus commands (if there are more than 1) AND ONLY if the first attempts fails. Fractions like 0.3 can be used. Default is 0.1 (seconds)

  • --timeout. This is the modbus command timeout in milliseconds. Default is 1000. This is only the timeout value in event of the modbus server not responding. If a modbus server responds sooner, then this value is ignored.

  • --serial_lock. This argument is included for compatibility with older versions, but it is not used.

  • --socket_delay. Some Huawei equipment needs a delay between establishing a TCP socket and getting data. This feature allows this delay. It is defined in milliseconds.

Example of "bit" lookup

  • Bit starts at 1. Include a 0 value to display something (or blank) if no bits are turned on

  • This function accepts a 32 bit number. If a 32 bit map is required, ENSURE the number is read as a 32 bit integer (that is; the number must be read as -t3:int or -t4:int)

Example of "str" lookup file

  • Numbers can be anything, since they are read from a single modbus (16 bit) register

Example of "str_rev" lookup file

  • One entry per line. Where an entry is two values separated by a colon :

  • Each side can be anything. A string or a number

  • PLEASE NOTE THE ENTRIES ARE CASE SENSITIVE

Example of "reg_scale" lookup file

  • One entry per line. Where an entry is two values separated by a colon :

  • Left side can be an integer up to 65535 (unsigned 16 bit).

  • Right side can be any floating point number up to 32 bit

Example of a "conditional lookup" file

  • This is a lookup file used by the cond_bit type. It operates by using the CONTENTS of the register listed in the Sum/Conditional Registers, and whether the bit detailed in the Register and Conditional Bitcolumn are 1/true, to then display the result of the lookup table. The file contents example is as below. There are 2 keys separated by a colon ":". The first item is the contents of the Sum/Conditional Registers, and the second key is the bit detailed in the Register and Conditional Bitcolumn. If this bit is true, then the third item is displayed.

Troubleshooting

If the plugin doesn't seem to be working, then try the following:

  1. In task mode (that is; when NOT running the plugin as a service), run the command to collect data. Any obvious errors should be reported to Ardexa. If additional debugging information is required, use the -v argument (for Debug Level 1), or -vv for Debug Level 2.

  2. In service mode, run the command systemctl status modbus-plugin.service. This will provide an output similar to the following. Check that the Time elapsed is entries are reporting values that are LOWER than the required frequency. For example, if the service mode is set to collect data every 2 seconds, but the Time elapsed is entries are showing values greater than 2 seconds, then data will not be able to be collected.

Was this helpful?