--- title: Installation & Configuration of IoT Gateway tags: thingsboard-gateway image: --- # Getting started with ThingsBoard IoT Gateway :::info **What is Thingsboard IoT Gateway?** * Devices > --- modbus --- > converter / connector > * ... ::: [toc] ## Installation ### Docker + Linux > Prerequisites: docker ce + docker-compose > Docker basics 1. How to Do a Clean Restart of a Docker Instance [details](https://docs.tibco.com/pub/mash-local/4.3.0/doc/html/docker/GUID-BD850566-5B79-4915-987E-430FC38DAAE4.html) * Stop the container(s) using the following command: ``docker-compose down`` * Delete all containers using the following command: ``docker rm -f $(docker ps -a -q) `` * Delete all volumes using the following command: ``docker volume rm $(docker volume ls -q)`` ==Note: Deleting volumes will wipe out their data. Back up any data that you need before deleting a container.== * Restart the containers using the following command: ``docker-compose up -d `` 2. ... > docker-compose.yml (template [here](https://github.com/thingsboard/thingsboard-gateway/blob/master/docker/docker-compose.yml)) ```yaml! version: '3.0' services: gw: restart: always image: "thingsboard/tb-gateway" # Ports (Required for REST connector) ports: - "5000:5000" volumes: - ~/.tb-gateway/config:/thingsboard_gateway/config - ~/.tb-gateway/logs:/thingsboard_gateway/logs - ~/.tb-gateway/extensions:/thingsboard_gateway/extensions devices: - "/dev/ttyS0:/dev/ttyS0" ``` 1. working directory with the file "docker-compose.yml": ``cd ~/workspace/tb`` 2. ``docker-compose up -d`` 3. ``docker-compose logs --tail 10`` 4. ``star@gateway:~/workspace/tb$ docker exec -it tb-gw-1 bash`` ``` root@06154190eb83:/# pip3 install redis Collecting redis Downloading redis-4.4.2-py3-none-any.whl (237 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 237.8/237.8 kB 1.5 MB/s eta 0:00:00 Collecting async-timeout>=4.0.2 Downloading async_timeout-4.0.2-py3-none-any.whl (5.8 kB) Installing collected packages: async-timeout, redis Successfully installed async-timeout-4.0.2 redis-4.4.2 WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv [notice] A new release of pip available: 22.3 -> 23.0 [notice] To update, run: python3 -m pip install --upgrade pip root@06154190eb83:/# pip3 install sqlalchemy Collecting sqlalchemy Downloading SQLAlchemy-2.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.7 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.7/2.7 MB 3.1 MB/s eta 0:00:00 Collecting greenlet!=0.4.17 Downloading greenlet-2.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (613 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 613.7/613.7 kB 4.0 MB/s eta 0:00:00 Requirement already satisfied: typing-extensions>=4.2.0 in /root/.local/lib/python3.10/site-packages (from sqlalchemy) (4.4.0) Installing collected packages: greenlet, sqlalchemy Successfully installed greenlet-2.0.2 sqlalchemy-2.0.0 WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv [notice] A new release of pip available: 22.3 -> 23.0 [notice] To update, run: python3 -m pip install --upgrade pip ``` > console error ``` tb-gw-1 | ""2023-01-31 04:50:23" - |ERROR| - [modbus_connector.py] - modbus_connector - __process_slaves - 342 - int() argument must be a string, a bytes-like object or a real number, not 'NoneType'" tb-gw-1 | Traceback (most recent call last): tb-gw-1 | File "/thingsboard_gateway/connectors/modbus/modbus_connector.py", line 311, in __process_slaves tb-gw-1 | self.__connect_to_current_master(device) tb-gw-1 | File "/thingsboard_gateway/connectors/modbus/modbus_connector.py", line 357, in __connect_to_current_master tb-gw-1 | device.config['master'], device.config['available_functions'] = self.__configure_master(device.config) tb-gw-1 | File "/thingsboard_gateway/connectors/modbus/modbus_connector.py", line 419, in __configure_master tb-gw-1 | master = ModbusSerialClient(method=current_config["method"], tb-gw-1 | File "/root/.local/lib/python3.10/site-packages/pymodbus/client/serial.py", line 196, in __init__ tb-gw-1 | super().__init__(framer=framer, **kwargs) tb-gw-1 | File "/root/.local/lib/python3.10/site-packages/pymodbus/client/base.py", line 120, in __init__ tb-gw-1 | self.params.retries = int(retries) tb-gw-1 | TypeError: int() argument must be a string, a bytes-like object or a real number, not 'NoneType' tb-gw-1 | ""2023-01-31 04:50:28" - |ERROR| - [modbus_connector.py] - modbus_connector - __process_slaves - 342 - int() argument must be a string, a bytes-like object or a real number, not 'NoneType'" tb-gw-1 | Traceback (most recent call last): tb-gw-1 | File "/thingsboard_gateway/connectors/modbus/modbus_connector.py", line 311, in __process_slaves tb-gw-1 | self.__connect_to_current_master(device) tb-gw-1 | File "/thingsboard_gateway/connectors/modbus/modbus_connector.py", line 357, in __connect_to_current_master tb-gw-1 | device.config['master'], device.config['available_functions'] = self.__configure_master(device.config) tb-gw-1 | File "/thingsboard_gateway/connectors/modbus/modbus_connector.py", line 419, in __configure_master tb-gw-1 | master = ModbusSerialClient(method=current_config["method"], tb-gw-1 | File "/root/.local/lib/python3.10/site-packages/pymodbus/client/serial.py", line 196, in __init__ tb-gw-1 | super().__init__(framer=framer, **kwargs) tb-gw-1 | File "/root/.local/lib/python3.10/site-packages/pymodbus/client/base.py", line 120, in __init__ tb-gw-1 | self.params.retries = int(retries) tb-gw-1 | TypeError: int() argument must be a string, a bytes-like object or a real number, not 'NoneType' tb-gw-1 | ""2023-01-31 04:50:33" - |ERROR| - [modbus_connector.py] - modbus_connector - __process_slaves - 342 - int() argument must be a string, a bytes-like object or a real number, not 'NoneType'" tb-gw-1 | Traceback (most recent call last): tb-gw-1 | File "/thingsboard_gateway/connectors/modbus/modbus_connector.py", line 311, in __process_slaves tb-gw-1 | self.__connect_to_current_master(device) tb-gw-1 | File "/thingsboard_gateway/connectors/modbus/modbus_connector.py", line 357, in __connect_to_current_master tb-gw-1 | device.config['master'], device.config['available_functions'] = self.__configure_master(device.config) tb-gw-1 | File "/thingsboard_gateway/connectors/modbus/modbus_connector.py", line 419, in __configure_master tb-gw-1 | master = ModbusSerialClient(method=current_config["method"], tb-gw-1 | File "/root/.local/lib/python3.10/site-packages/pymodbus/client/serial.py", line 196, in __init__ tb-gw-1 | super().__init__(framer=framer, **kwargs) tb-gw-1 | File "/root/.local/lib/python3.10/site-packages/pymodbus/client/base.py", line 120, in __init__ tb-gw-1 | self.params.retries = int(retries) tb-gw-1 | TypeError: int() argument must be a string, a bytes-like object or a real number, not 'NoneType' ``` ``` root@06154190eb83:/# pip3 install protobuf --upgrade Requirement already satisfied: protobuf in /usr/local/lib/python3.10/site-packages (3.20.0) Collecting protobuf Downloading protobuf-4.21.12-cp37-abi3-manylinux2014_x86_64.whl (409 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 409.8/409.8 kB 2.1 MB/s eta 0:00:00 Installing collected packages: protobuf Attempting uninstall: protobuf Found existing installation: protobuf 3.20.0 Uninstalling protobuf-3.20.0: Successfully uninstalled protobuf-3.20.0 Successfully installed protobuf-4.21.12 WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv [notice] A new release of pip available: 22.3 -> 23.0 [notice] To update, run: python3 -m pip install --upgrade pip ``` > try to make freeze and see that versions of libs ``` root@e65a1a2bd181:/# pip3 freeze ``` ### Ubuntu 20 / Debian 11 * (optional but recommended) ``sudo apt update`` #### 1. Download the deb file (/home/swae/workspace/tb-gw) ```! wget https://github.com/thingsboard/thingsboard-gateway/releases/latest/download/python3-thingsboard-gateway.deb ``` #### 2. Install the gateway using apt ``` sudo apt install ./python3-thingsboard-gateway.deb -y ``` #### 3. Check gateway status ``` sudo systemctl status thingsboard-gateway ``` :::spoiler details ``` star@debian-vm:~/workspace/tb-gw$ sudo systemctl status thingsboard-gateway.service ● thingsboard-gateway.service - ThingsBoard Gateway Loaded: loaded (/etc/systemd/system/thingsboard-gateway.service; enabled; vendor preset: enabled) Active: active (running) since Tue 2023-01-17 12:02:18 CST; 20min ago Main PID: 20949 (python3) Tasks: 10 (limit: 2341) Memory: 30.7M CPU: 5.435s CGroup: /system.slice/thingsboard-gateway.service └─20949 /usr/bin/python3 -c from thingsboard_gateway.tb_gateway import daemon; daemon() Jan 17 12:02:19 debian-vm python3[20949]: File "/var/lib/thingsboard_gateway/.local/lib/python3.9/site-packages/paho/mqtt/re> Jan 17 12:02:19 debian-vm python3[20949]: assert identifier in self.names.keys(), identifier Jan 17 12:02:19 debian-vm python3[20949]: AssertionError: 5 Jan 17 12:02:19 debian-vm python3[20949]: ""2023-01-17 12:02:19" - |ERROR| - [tb_device_mqtt.py] - tb_device_mqtt - _on_connec> Jan 17 12:02:19 debian-vm python3[20949]: ""2023-01-17 12:02:19" - |INFO| - [tb_updater.py] - tb_updater - check_for_new_versi> Jan 17 12:02:19 debian-vm python3[20949]: ""2023-01-17 12:02:19" - |INFO| - [tb_updater.py] - tb_updater - check_for_new_versi> Jan 17 12:02:19 debian-vm python3[20949]: [===UPDATE===] Jan 17 12:02:19 debian-vm python3[20949]: New version v3.2 is available! Jan 17 12:02:19 debian-vm python3[20949]: [===UPDATE===] Jan 17 12:02:19 debian-vm python3[20949]: " ``` ::: #### (optional) 4. Hot Reloader > Enable hot reloader to restart Gateway every time when we edit any project file when using ++Gateway for development++. ``python3 ./thingsboard_gateway/tb_gateway.py true`` --- source code ``python3 /usr/lib/python3/dist-packages/thingsboard_gateway/tb_gateway.py true`` ## Configuration ### Directory structure * * path: /etc/thingsboard-gateway/config/* * **tb_gateway.yaml** * modbus_serial.json #### Disable Statistics * tb- ``` ``` * * statistics.json --- /usr/lib/python3/dist-packages/thingsboard_gateway/config/statistics.json * * ... ## Custom ### iAeris20 setting gateway 讀取 iAeris register 的資料經由hex轉換成int時會以4位數呈現小數點後兩位,此呈現方式在顯示上並不符合閱讀邏輯。 暫時解決方案為在 bytes_modbus_uplink_converter.py 檔案中添加下方程式碼強制轉換,後續須考慮新方法以解決不同機型產生的數字所代表的含意。 ``` star@gateway:~/workspace/tb$ docker exec -it tb-gw-1 bash root@abfd2e6c9960:/# cd /thingsboard_gateway/connectors/modbus/ ``` Edit bytes_modbus_uplink_converter.py (+line 83) ```python=83 decoded_data=float(decoded_date)/100 ``` p.s. docker在更新過後需重啟docker才能生效 Result: before: `` tb-gw-1 | ""2023-02-21 03:30:37" - |INFO| - [modbus_connector.py] - modbus_connector - run - 651 - {'deviceName': 'iAeris 20', 'deviceType': 'default', 'telemetry': [{'temperature': 2660}, {'humidity': 3590}], 'attributes': []}" `` after: `` tb-gw-1 | ""2023-02-21 06:41:00" - |INFO| - [modbus_connector.py] - modbus_connector - run - 651 - {'deviceName': 'iAeris 20', 'deviceType': 'default', 'telemetry': [{'temperature': 26.9}, {'humidity': 34.9}], 'attributes': []}" `` ## Troubleshooting > ``sudo stty -a -F /dev/ttyS0`` ``` speed 19200 baud; rows 0; columns 0; line = 0; intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; discard = ^O; min = 0; time = 0; -parenb -parodd -cmspar cs8 -hupcl -cstopb cread clocal -crtscts -ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany -imaxbel -iutf8 -opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0 -isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke -flusho -extproc ``` ``` connectors: # - # name: MQTT Broker Connector # type: mqtt # configuration: mqtt.json # - # name: Modbus Connector # type: modbus # configuration: modbus.json # - name: Modbus Connector type: modbus configuration: modbus_serial.json ``` ``` Jan 17 12:49:25 debian-vm python3[21319]: from pymodbus.constants import Defaults Jan 17 12:49:25 debian-vm python3[21319]: ModuleNotFoundError: No module named 'pymodbus' Jan 17 12:49:25 debian-vm python3[21319]: Modbus library not found - installing... Jan 17 12:49:25 debian-vm python3[21319]: ""2023-01-17 12:49:25" - |ERROR| - [tb_device_mqtt.py] - tb_device_mqtt - _on_connect - 223 - connection FAIL with> Jan 17 12:49:25 debian-vm python3[21319]: ""2023-01-17 12:49:25" - |INFO| - [tb_updater.py] - tb_updater - check_for_new_version - 84 - v3.2" Jan 17 12:49:25 debian-vm python3[21319]: ""2023-01-17 12:49:25" - |INFO| - [tb_updater.py] - tb_updater - check_for_new_version - 86 - ``` ``` Jan 17 12:49:25 debian-vm python3[21319]: [===UPDATE===] Jan 17 12:49:25 debian-vm python3[21319]: New version v3.2 is available! Jan 17 12:49:25 debian-vm python3[21319]: [===UPDATE===] Jan 17 12:49:25 debian-vm python3[21319]: " Jan 17 12:50:27 debian-vm python3[21326]: Collecting pymodbus>=3.0.0 Jan 17 12:50:42 debian-vm python3[21326]: Downloading pymodbus-3.1.0-py2.py3-none-any.whl (163 kB) Jan 17 12:50:43 debian-vm python3[21326]: Installing collected packages: pymodbus Jan 17 12:50:43 debian-vm python3[21326]: WARNING: The scripts pymodbus.console, pymodbus.server and pymodbus.simulator are installed in '/var/lib/thingsb> Jan 17 12:50:43 debian-vm python3[21326]: Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location. Jan 17 12:50:43 debian-vm python3[21326]: Successfully installed pymodbus-3.1.0 ``` * error log: tail -f /var/log/thingsboard-gateway/connector.log ``` Jan 17 13:02:10 debian-vm python3[21319]: self.__connect_to_current_master(device) Jan 17 13:02:10 debian-vm python3[21319]: File "/usr/lib/python3/dist-packages/thingsboard_gateway/connectors/modbus/modbus_connector.py", line 357, in __> Jan 17 13:02:10 debian-vm python3[21319]: device.config['master'], device.config['available_functions'] = self.__configure_master(device.config) Jan 17 13:02:10 debian-vm python3[21319]: File "/usr/lib/python3/dist-packages/thingsboard_gateway/connectors/modbus/modbus_connector.py", line 419, in __> Jan 17 13:02:10 debian-vm python3[21319]: master = ModbusSerialClient(method=current_config["method"], Jan 17 13:02:10 debian-vm python3[21319]: File "/var/lib/thingsboard_gateway/.local/lib/python3.9/site-packages/pymodbus/client/serial.py", line 193, in _> Jan 17 13:02:10 debian-vm python3[21319]: super().__init__(framer=framer, **kwargs) Jan 17 13:02:10 debian-vm python3[21319]: File "/var/lib/thingsboard_gateway/.local/lib/python3.9/site-packages/pymodbus/client/base.py", line 120, in __i> Jan 17 13:02:10 debian-vm python3[21319]: self.params.retries = int(retries) Jan 17 13:02:10 debian-vm python3[21319]: TypeError: int() argument must be a string, a bytes-like object or a number, not 'NoneType' ``` ``sudo pip3 install pymodbus pyserial twisted --upgrade`` ``` Requirement already satisfied: attrs>=19.2.0 in /usr/local/lib/python3.9/dist-packages (from twisted) (22.2.0) Requirement already satisfied: six in /usr/lib/python3/dist-packages (from Automat>=0.8.0->twisted) (1.16.0) Requirement already satisfied: idna>=2.5 in /usr/lib/python3/dist-packages (from hyperlink>=17.1.1->twisted) (2.10) Requirement already satisfied: setuptools in /usr/lib/python3/dist-packages (from zope.interface>=4.4.2->twisted) (52.0.0) Installing collected packages: zope.interface, typing-extensions, incremental, hyperlink, constantly, Automat, twisted, pyserial, pymodbus Successfully installed Automat-22.10.0 constantly-15.1.0 hyperlink-21.0.0 incremental-22.10.0 pymodbus-3.1.0 pyserial-3.5 twisted-22.10.0 typing-extensions-4.4.0 zope.interface-5.5.2 ``` ``` root@gateway:~# python /testmode/_1_Python3_Codes/_5_PySerial-Receive_String.py send:b'\xfe\x03\x00\x1a\x00\x02\xf1\xc3' get:[b'\xfe\x03\x04\t\x06\x16&\x99\x1b'] - id 0xfe 254 any sensor ``` > modpoll ``` ./modpoll -b 19200 -p none -m rtu -a 1 -r 0x1b -c 1 /dev/ttyS0 modpoll 3.10 - FieldTalk(tm) Modbus(R) Master Simulator Copyright (c) 2002-2021 proconX Pty Ltd Visit https://www.modbusdriver.com for Modbus libraries and tools. Protocol configuration: Modbus RTU, FC3 Slave configuration...: address = 1, start reference = 27, count = 1 Communication.........: /dev/ttyS0, 19200, 8, 1, none, t/o 1.00 s, poll rate 1000 ms Data type.............: 16-bit register, output (holding) register table -- Polling slave... (Ctrl-C to stop) [27]: 2320 -- Polling slave... (Ctrl-C to stop) [27]: 2320 -- Polling slave... (Ctrl-C to stop) [27]: 2320 ``` > linux-serial-test (helpless wiht RS-485 mode :<) ``` star@gateway:/testmode$ ./linux-serial-test -q -s -e -p /dev/ttyS0 Linux serial test app Error setting RS-485 mode: Inappropriate ioctl for device /dev/ttyS0: No data received for 2.2s. /dev/ttyS0: No data received for 3.3s. /dev/ttyS0: No data received for 4.3s. /dev/ttyS0: No data received for 5.4s. /dev/ttyS0: No data received for 6.5s. ``` ### Log files * /etc/thingsboard-gateway/config/logs.conf * /var/log/thingsboard-gateway/* ``` sudo journalctl --follow -u thingsboard-gateway.service sudo journalctl -fu thingsboard-gateway.service ``` ## References * [What is ThingsBoard IoT Gateway?](https://thingsboard.io/docs/iot-gateway/what-is-iot-gateway/) * [Getting Started with ThingsBoard IoT Gateway](https://thingsboard.io/docs/iot-gateway/getting-started/) * [tb-gateway config for modbus](https://thingsboard.io/docs/iot-gateway/config/modbus/) --- ==!!!重要!!!== * [mbpoll user manual](https://www.modbustools.com/mbpoll-user-manual.html#_modbus_poll) * https://github.com/thingsboard/thingsboard-gateway/issues/1041 ## Star's Lab (手上沒有硬體的做法) * Windows Modbus slave simulator * Linux Modbus master simulator [here](https://www.modbusdriver.com/modpoll.html)