###### Modbus ###### ================================= Modbus dataSource and dataTargets ================================= Modbus datasources and -targets (laters just dataurls) consists of multiple parts, just like regular http-urls do. Here is an example of ``modbusrtu`` dataSource: ``modbusrtu://ioPorts%2FmodbusRTU%2FP1/1/holding/337&datatype=int16`` The dataurl can be split into parts which are separated by ``/`` character. protocol ``modbusrtu://`` This part tells the modbus library which protocol to use. Possible values for modbus are ``modbusrtu`` and ``modbustcp`` ioPort ``ioPorts%2FmodbusRTU%2FP1`` This is the point name to the ioPort we want to use. The ``/`` in point name needs to be replaced with ``%2F`` (*urlencoding*) address ``1`` This is the slave address of the device we're reading from register type ``holding`` This is the type of the register we're interested in possible values are ``holding``, ``input``, ``coil``, ``discrete`` register number ``337`` This is the register we're reading Actiweb does not use 1-4 prefixes for different register umbers Actiweb starts counting registers from 0. i.e. the 'first' register is in address 0 .. _modbus parameters: parameters Optional parameters can be used to manipulate the raw register value. First parameter is separated form the register with the character ``?`` and subsequent parameters with ``&`` Syntax for parameters is ``parameterName=value``, e.g. ``scale=0.1`` Some useful parameters :scale: multiplies the raw value with scale value. e.g. value of ``0.1`` makes ``100->10`` :datatype: datatype for the register value, e.g. ``int16`` or ``float32`` :offset: sets offset for raw value :invert: invert (raw value is subtracted from this value. Mainly useful for binary data) :x1,y1,x2,y2..xn,yn: set scaling curve for raw value. Excel or other assistive tools are recommended :hilimit, lolimit: set high or low limit for the pv value :damping: floating average between reading rounds :bitmask: bitmask to select/unselect individual bits from raw. On **dataSource**, when raw value is read from register, bitwise AND operation is performed between bitmask parameter and raw value, and result is written to pv. For **dataTarget**, bitmask value is used as raw value, and bitwise OR operation is performed between raw values of all datapoints pointing to this register and has pv greater than zero. :ondelay, offdelay: Time in milliseconds between raw<->pv change It's *rarely* meaningful to build these dataurls by hand. Excel, IO-profiles or other means are strongly recommended to be used when importing dataUrls to database. Imagination is the only limiting factor :) Manually editing dataUrls makes sense mainly when debugging or testing new devices and finding out the registers. ================================= Modbus-task logic ================================= When Actiweb9 core (re)starts, modbus-task scans the database and finds all datapoints that have modbus related dataSources and -targets. It then matches the points to ioPorts and every ioPort starts its own parallel task. This means that reading different modbus busses happens concurrently and if one modbus task hangs it does not affect other modbus tasks. This also means that if any changes are made to the dataSources or dataTargets the core needs to be restarted for the changes to apply. ---------------- Gathering points ---------------- When modbus task has all the points gathered it will build a tree-like structure of the registers. It tries to bundle adjacent registers to same queries so that they can be requested in same modbus frame. This behavior reduces the amount of modbus queries and thus makes communication faster. Keeping this in mind, sometimes it might be beneficial to read 'useless' registers if it allows registers to be bundled together. However bundling only applies to **reading registers**. All dataTargets are written individually for better compatibility for slave devices. ---------------------- After reading register ---------------------- When modbus task has read the register it will push that *raw* value to a field called ``raw``. If the dataUrl has any parameters configured it will then apply those to the raw value. Order of the parameters is as follows: 1. scale + offset 2. inline curve 3. bitmask 4. datatype casting The result value will then be stored in `pv` field. For **dataTarget** the order is reversed. .. admonition:: Recap For reading: ``modbus peripheral device -> raw -> pv`` For writing: ``pv -> raw -> modbus peripheral device`` .. tip:: **Overriding pv value** If user wants to override the value of the database point it can be done by first adding `priority` field and then setting it to `8` and writing wanted value to the `pv` field. If using graphical UI this behaviour will automated in the value setting dialog when `priority` field is present