Add new IP to BACRouter

We are often faced with third-party devices in the field whose IP cannot be modified and whose IP is not in the same subnet as the BACRouter or other BIP devices.
The solution already in place is to add an IP router, which will result in increased cost and complexity.
Usually we only need the BACRouter to communicate with this third party device using Modbus TCP or BACnet IP protocol, so the easiest way is to add an IP to the BACRouter dedicated to communicate with this device

For example, local IP subnet is 192.168.100.0/24,  BACRouter’s IP is 192.168.100.1;  Third-party device has a IP of 172.16.1.20, its netmask is 255.255.255.0

We will add IP of 172.16.1.1 to BACRouter
Original /etc/rc.local:

root@OpenWrt:~# cat /etc/rc.local
# Put your custom commands here that should be executed once
# the system init finished. By default this file does nothing.

cd /root
./webui&
exit 0

Modify /etc/rc.local: (vi is available too)

root@OpenWrt:~# cat>/etc/rc.local
# Put your custom commands here that should be executed once
# the system init finished. By default this file does nothing.

ifconfig br-lan:1 172.16.1.1 netmask 255.255.255.0
cd /root
./webui&
exit 0
CTRL+D

The ifconfig command will create a br-lan:1 interface with IP 172.16.1.1; if we connect to the third-party device by BIP protocol, we have to add new interface to BACRouter configuration.

Original /root/resource.conf:

~#cat /root/resource.conf
{ “eth0”: { “type”: “ETH”, “ifname”: “br-lan” }, “RS485-1”: { “type”: “USB”, “ifname”: “0:0” }, “RS485-2”: { “type”: “USB”, “ifname”: “0:1” } }

Modify /root/resource.conf: (vi is available too)

~#cat >/root/resource.conf
{ “eth0”: { “type”: “ETH”, “ifname”: “br-lan” }, “eth1”:{“type”:”ETH”, “ifname”:”br-lan:1″}, “RS485-1”: { “type”: “USB”, “ifname”: “0:0” }, “RS485-2”: { “type”: “USB”, “ifname”: “0:1” } }
CTRL+D

now restart BACRouter!

Modbus Devices Config & Lua Scripts & Conversion

Modbus Device Config

Siemens_RDF302.jsonSiemens RD302 Thermostat
Schneider_TC500.jsonSchneider TC500 Thermostat
JCI_T8600.jsonJCI T8600 Thermostat
JCI_T7000.jsonJCI T7000 Series Thermostat
ABB_ACS510.jsonABB ACS510 VFD

Lua Script

bcd.luaEach byte is 0-9, for example: 0x05090702 = 5972
Endian is defined by “big integer”
compat_bcd.luaEach half byte is 0-9, for example: 0x78695231 = 78695231
Endian is defined by “big integer”
m10k.luaEach register is -9999~9999, for example: 0x1f740a69 = 0x1f74*10000 + 0x0a69 = 80522665
Endian is defined by “big integer”
low10th.luaOnly 1 register, low byte is one tenth, the range is 0.0 to 255.9 for example: 0x0503 = 5.3
Endian is defined by “single integer”.
This is found in York TMS2100 FCU thermostat.

Conversion

Convert BASgatewayLX CSV Configuration

Convert BASgatewayLX CSV Configuration To BACRouter JSON

BASgatewayLX (Hereinafter referred to as LX) supports CSV configuration file. There are decent documents about the format and dozens of configuration samples for vary devices on their website. The convert tool we provided could convert the CSV file to JSON file which could be imported in BACRounter’s WebUI to create a Modbus slave station.

Convert on our website

Download and extract it to disk, open index.html by your web browser

Matters need attention:

Though LX claims the object name should be unique, but the accessory “Profile Checker” does not check duplicated object name. We found a lots duplicated object names in the samples. So we decided to disable object with duplicated name in converting.

Some CSV files have characters out of UTF8 code page, we guess they are ISO-8859-1 encoding. So if we fail to decode CSV by UTF8, we fall back to ISO-8859-1.

LX supports maximum 64 bytes of object name and description (With ISO-8859-1 encoding?). BACRouter supports 64 bytes too, but with UTF8 encoding. There has possibility that 64 bytes in ISO-8859-1 is larger than 64 bytes when encoding as UTF8. We will tail-cut too long name and description and promote to user.

BACRouter doesn’t allow 2 output objects mapped to overlapped Modbus address, but LX seems to allow it. We will disable the conflicted object in converting.

LX defines register order for every 32 bits data, but BACRouter has to set unitary byte order for all objects. If the consistent byte order definitions are found when converting, the previous definition will be accepted, the conflict will be promoted to user.

BACRouter has object instance range of 0~999 for every slave, but LX seems no limitation. If instance larger than 999 is found, the object will be auto assigned a new instance.

Offline configuration and import/export

From firmware v4.x,Offline configuration had been introduced. Now user could configure a BACRouter without device on hand, then export configuration to a file. When commissioning on the field, user just need to import previously exported file, “Save&Reboot” to take effect the configuration.

From v4.04,The object definitions for Modbus gateway could be import/export as CSV format. User could effectively setup object to Modbus address mapping In batches with Excel/WPS/Libreoffice, then import it to WebUI for detailed modify.

Offline configure on our website  (IE will not work now)

Download and extract it to disk, open index.html by your web browser (Because IE/Edge doesn’t support Local Storage for file:// URL, the user library for binary text and most used engineering unit will not be kept after leaving the web page)

There are 3 types of configuration file:

BACRouter Configuration File

This type of configuration file keeps all settings in BACRouter. If the firmware version of exporting one is same to importing one, WebUI should not complain of the configuration file.

Modbus Master Configuration File

This type of configuration file keeps setting under the scope of Modbus master.  When importing it, collision detecting logic based on current mapping mode will check every enabled slave in this master, if collision is found, the slave will be disabled.

If the master is RTU/ASCII type, it may also be disabled if there are contention for RS485 port.

With these problem, WebUI will prompt user to re-check configuration.

Modbus Slave Configuration File

This type of configuration file keeps setting under the scope of Modbus slave.  When importing it, if collision detecting logic based on current mapping mode found problem, the slave will be disabled.

It is allowed to import TCP salve configuration file in RTU/ASCII master, and vice versa, but the slave may be disabled if Modbus parameter setting do not work.

With these problem, WebUI will prompt user to re-check configuration.

Modbus Gateway in BACRouter

Update on 2023-03-07  for version 4.26

From firmware version 4.x,  BACRouter has builtin Modbus gateway functionality. This article will try to explain the underlying mechanism.

Modbus Read

BACRouter will periodically read point’s value and cache it.  “Update interval” defines how often BACRouter update the value.

To improve performance, BACRouter will read as more as possible data in one transcation. In Modbus standard, at most 2000 bits (coil or discrete) or 125 registers (input or holding register) could be read in one request, but specific Modbus slave device may only support a lower value.  In BACRouter’s WebUI, there is a Modbus parameter edit dialog in “Slave Settings”, “Multiply read bits” and “Multiply read registers” parameters define the ability of the slave device.

BACRouter will not segment reading of single point even the “Multiply read registers” is less than registers used by the point.

Usually the data we care for has discontinuous Modbus address, for example, We only care for coils on address 1 and 2000, though we could read coil data from address 1 to 2000 in one request and skip returned data from address 2 to 1999,  sending two requests independently for coil on address 1 and coil on address 2000 maybe more efficient. “Bits skipped” and “Registers skipped” parameter define how many unused data units between 2 cared data units are allowed to be skipped. As previous example, if “Bits skipped” is set to 1998, the BACRouter will try to read coil 1 and 2000 in single request. If “Bits skipped” is set to 1997, then BACRouter will read Coil 1 first, then Coil  2000, because bits skipped is 1998 and is greater than the setting of 1997.

On the WebUI page for slave, the “Read Group” button will show how the BACRouter will group the reading and test it. User should pay special attention on server exception of “Illegal data address”.

Modbus Write

BACRouter will not combine multiple writing demand into one writing request. It always queue write request immediately after receiving command.

For writing single data unit, there are two Modbus function codes available. For example, function code 5 is writing single coil,  function code 15 is writing multiple coils but the quantity of coil to write could be assigned to 1. Some devices only support one of them.  “Coil write singly” parameter will specify which function code is used.

In the same way, “Register write singly” is applied to register writing. If any BACnet output object maps to multiple holding registers, it implies the slave device support function code 16 for write multiple registers, “Register write singly” will be automatically disabled, function code 16 will be used for writing any register.

Offline

If any read/write request failed, BACRouter will retry it, when the continuous fail count reachs 3, BACRouter will regard the slave device as offline. In offline state, BACRouter will retry the request every “Offline update interval”.

The BACnet side reaction for offline event will be described later.

Modbus Serial Bus

BACRouter supports serial slave devices with different baudrate, parity, RTU/ASCII mode on same RS485 bus. Before sending request, BACRouter will change it serial port parameter based on slave device’s settings.

It should be safe to have 2 devices with same slave address but different baudrate or RTU/ASCII  mode, but preventing collision based on different parity might not be enough, because some devices do not examine parity error.

Single Device Mapping Mode

If VBUS network port is not enabled, BACRouter will work in single device mapping mode, every Modbus slave device will be mapped into exclusive object instance space of 1000 in the only BACnet device defined in “Application Settings”.

The actual BACnet object name will be organized as “master_name|slave_name|object_name”,  The “|” is name delimiter which could be selected from dozen of characters by user.

As recommended by standard, BACRouter will create one StructuredView object for each slave device.

When the slave device turn to offline in this mode, all points’ reliability will be set to “COMMUNICATION_FAILURE”, if slave device is back to online, upon updating of point value, the point’s reliability will be set back to “NO_FAULT_DETECTED”.

Virtual Device Mapping Mode

If VBUS network port is enabled. Each slave device will be mapped to a virtual BACnet device on VBUS network. The MAC address will start from 1.

In this mode, each slave shall has a unique “Device instance”. The BACnet device name of the slave will be “master_name|slave_name”, The delimiter “|” is select-able.

When the slave device turn to offline in this mode, as recommended by standard, the virtual BACnet device will stop sending/receiving any packet to simulate offline state. if slave device is back to online, after updating all point’s value, the virtual BACnet device will quite offline state.

Slave Device’s Status

For every slave device, BACRouter will create 3 objects in gateway device, one object is Binary_Input with name of “online”, which represents online/offline status of slave device. another object is Analog_Input with name of “update_delay”, which is recently average update time delayed over “”Update interval”, the last one is Analog_Input with name of “fail_rate”,  which count a relative long time fail rate on Modbus side.

Those objects’ name have prefix of “master_name|slave_name|comm|”, where “|” is select-able delimiter.

Object Instance Assignment

Object Instance is defined for every object. When the editor dialog for a object is submitted and the object is enabled, the object instance claimed by the object will be assigned, if that assigning fail, a automatically selected instance will be used.

Value Object

AV/BV/MV is behaving same as AI/BI/MI, except that when AV/BV/MV is mapped to writable Modbus address (0X or 4X), the present value of the object is writable, the writing will be forwarded to Modbus side (See below 2 exceptions).

Exception 1:  If AV is mapped to holding register, its data type is customized, but the binding script doesn’t support output, that AV will be read only.

Exception 2:  If AV is mapped to multiple holding registers, but the”Register write singly” option is enabled, that implies output will not be supported, so the AV will be read only.

Output Object

The value of output object is still being polled from Modbus side and set to object’s Relinguish_Default property. If the value read back does not match last value written, BACRouter will set the reliability of that object to “UNRELIABLE_OTHER”,  and BACRouter will queue another write after a certain time. When “Tolerate unmatch” option is enabled, If the value read back does not match last value written, the reliability of that object keeps unchanged, and BACRouter will re-write the value on “Offline update interval”. (Update for v4.34)

Because of above verifying mechanism,  the BACRouter will prevent defining two output objects with overlaping Modbus writable address.

NaN For Float And Double

NaN is a special value defined by IEEE-754, BACRouter does not accept NaN (Infinite is still valid for BACRouter).

When a point is defined as Float and Double, but NaN is read from slave, BACRouter will set the reliability to “UNRELIABLE_OTHER”.

Unsupported value for script

When a analog object is customized, but the Modbus to BACnet conversion reports unsupported value from the script,  that object’s reliability will be set to “UNRELIABLE_OTHER”.

For a Analog Output object, when the BACnet to Modbus conversion reports unsupported value from the script, the object’s reliability will be set to  “PROCESS_ERROR”

For a Analog Value object, when the BACnet to Modbus conversion reports unsupported value from the script, that output attempt will be dropped, the object’s reliability will be unchanged.