├── .dockerignore ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── feature_request │ └── help_wanted.md └── workflows │ ├── close_issue.yml │ ├── codeql-analysis.yml │ ├── issue_creation.yml │ ├── reopened_issue.yml │ └── update_issue_in_jira.yml ├── .gitignore ├── .gitmodules ├── LICENSE ├── MANIFEST.in ├── README.md ├── build_latest_docker.sh ├── docker ├── Dockerfile └── docker-compose.yml ├── for_build ├── DEBIAN │ ├── postinst │ ├── preinst │ └── pydist-overrides ├── etc │ └── systemd │ │ └── system │ │ └── thingsboard-gateway.service └── var │ └── log │ └── thingsboard-gateway │ ├── connector.log │ ├── converter.log │ ├── database.log │ ├── extension.log │ ├── service.log │ ├── storage.log │ └── tb_connection.log ├── generate_deb_package.sh ├── make_packages.sh ├── requirements.txt ├── setup.py ├── tests ├── __init__.py ├── base_test.py ├── blackbox │ ├── __init__.py │ ├── connectors │ │ ├── __init__.py │ │ ├── modbus │ │ │ ├── __init__.py │ │ │ ├── test_modbus_attributes_updates.py │ │ │ ├── test_modbus_rpc.py │ │ │ └── test_modbus_uplink_messages.py │ │ └── opcua │ │ │ ├── __init__.py │ │ │ ├── test_base_opcua.py │ │ │ ├── test_opcua_attributes_updates.py │ │ │ ├── test_opcua_rpc.py │ │ │ └── test_opcua_uplink_messages.py │ ├── data │ │ ├── modbus │ │ │ ├── configs │ │ │ │ ├── attrs_update_configs │ │ │ │ │ ├── attrs_update_coils_registers_big.json │ │ │ │ │ ├── attrs_update_coils_registers_little.json │ │ │ │ │ ├── attrs_update_discrete_input_big.json │ │ │ │ │ ├── attrs_update_discrete_input_little.json │ │ │ │ │ ├── attrs_update_holding_registers_big.json │ │ │ │ │ ├── attrs_update_holding_registers_little.json │ │ │ │ │ ├── attrs_update_input_registers_big.json │ │ │ │ │ └── attrs_update_input_registers_little.json │ │ │ │ ├── default_modbus_config.json │ │ │ │ ├── initial_modbus_uplink_converter_report_strategy_on_change.json │ │ │ │ ├── initial_modbus_uplink_converter_report_strategy_on_change_or_report_period_on_period_factor.json │ │ │ │ ├── initial_modbus_uplink_converter_report_strategy_on_received.json │ │ │ │ ├── initial_modbus_uplink_converter_report_strategy_on_report_period.json │ │ │ │ ├── rpc_configs │ │ │ │ │ ├── coils_reading_rpc_big.json │ │ │ │ │ ├── coils_reading_rpc_little.json │ │ │ │ │ ├── coils_writing_rpc_big.json │ │ │ │ │ ├── coils_writing_rpc_little.json │ │ │ │ │ ├── discrete_inputs_reading_rpc_big.json │ │ │ │ │ ├── discrete_inputs_reading_rpc_little.json │ │ │ │ │ ├── discrete_inputs_writing_rpc_big.json │ │ │ │ │ ├── discrete_inputs_writing_rpc_little.json │ │ │ │ │ ├── holding_registers_reading_rpc_big.json │ │ │ │ │ ├── holding_registers_reading_rpc_little.json │ │ │ │ │ ├── holding_registers_writing_rpc_big.json │ │ │ │ │ ├── holding_registers_writing_rpc_little.json │ │ │ │ │ ├── input_registers_reading_rpc_big.json │ │ │ │ │ ├── input_registers_reading_rpc_little.json │ │ │ │ │ ├── input_registers_writing_rpc_big.json │ │ │ │ │ └── input_registers_writing_rpc_little.json │ │ │ │ └── uplink_configs │ │ │ │ │ ├── modbus_uplink_converter_coils_reading_big.json │ │ │ │ │ ├── modbus_uplink_converter_coils_reading_little.json │ │ │ │ │ ├── modbus_uplink_converter_discrete_input_reading_big.json │ │ │ │ │ ├── modbus_uplink_converter_discrete_input_reading_little.json │ │ │ │ │ ├── modbus_uplink_converter_holding_registers_reading_big.json │ │ │ │ │ ├── modbus_uplink_converter_holding_registers_reading_little.json │ │ │ │ │ ├── modbus_uplink_converter_input_registers_reading_big.json │ │ │ │ │ └── modbus_uplink_converter_input_registers_reading_little.json │ │ │ ├── modbus_rename_configs │ │ │ │ ├── default_modbus_config.json │ │ │ │ ├── input_registers_writing_rpc_big.json │ │ │ │ └── modbus_uplink_converter_input_registers_reading_little.json │ │ │ └── test_values │ │ │ │ ├── attrs_update │ │ │ │ ├── discrete_and_coils_registers_values_big.json │ │ │ │ ├── discrete_and_coils_registers_values_little.json │ │ │ │ ├── holding_registers_values_big.json │ │ │ │ ├── holding_registers_values_little.json │ │ │ │ ├── input_registers_values_big.json │ │ │ │ └── input_registers_values_little.json │ │ │ │ ├── default_slave_values.json │ │ │ │ ├── rpc │ │ │ │ ├── discrete_and_coils_registers_values_reading_big.json │ │ │ │ ├── discrete_and_coils_registers_values_reading_little.json │ │ │ │ ├── discrete_and_coils_registers_values_writing_big.json │ │ │ │ ├── discrete_and_coils_registers_values_writing_little.json │ │ │ │ ├── holding_registers_values_reading_big.json │ │ │ │ ├── holding_registers_values_reading_little.json │ │ │ │ ├── holding_registers_values_writing_big.json │ │ │ │ ├── holding_registers_values_writing_little.json │ │ │ │ ├── input_registers_values_reading_big.json │ │ │ │ ├── input_registers_values_reading_little.json │ │ │ │ ├── input_registers_values_writing_big.json │ │ │ │ └── input_registers_values_writing_little.json │ │ │ │ └── uplink │ │ │ │ ├── discrete_and_coils_registers_values_big.json │ │ │ │ ├── discrete_and_coils_registers_values_little.json │ │ │ │ ├── holding_registers_values_big.json │ │ │ │ ├── holding_registers_values_little.json │ │ │ │ ├── input_registers_values_big.json │ │ │ │ └── input_registers_values_little.json │ │ └── opcua │ │ │ ├── configs │ │ │ ├── attrs_update_configs │ │ │ │ └── attrs_update_node.json │ │ │ ├── default_opcua_config.json │ │ │ ├── rpc_configs │ │ │ │ ├── rpc_get_method.json │ │ │ │ ├── rpc_server_method.json │ │ │ │ └── rpc_set_method.json │ │ │ └── uplink_configs │ │ │ │ ├── different_node_finding_methods_config_b.json │ │ │ │ ├── different_node_finding_methods_config_g.json │ │ │ │ ├── different_node_finding_methods_config_i.json │ │ │ │ ├── different_node_finding_methods_config_path.json │ │ │ │ └── different_node_finding_methods_config_s.json │ │ │ └── test_values │ │ │ ├── attrs_update │ │ │ ├── attrs_update_connection_lost_node.json │ │ │ ├── attrs_update_node_values.json │ │ │ └── attrs_update_restart_node_values.json │ │ │ ├── default_node_values.json │ │ │ ├── rpc │ │ │ ├── rpc_get_method_values.json │ │ │ ├── rpc_server_method_values.json │ │ │ └── rpc_set_method_values.json │ │ │ └── uplink │ │ │ └── different_node_finding_methods_values.json │ └── service │ │ ├── __init__.py │ │ └── test_device_renaming.py ├── docker-compose.yml ├── integration │ ├── __init__.py │ ├── connectors │ │ ├── __init__.py │ │ ├── can │ │ │ ├── __init__.py │ │ │ └── test_can_connector.py │ │ ├── connector_integration_base_test.py │ │ ├── modbus │ │ │ ├── __init__.py │ │ │ └── test_modbus_connector.py │ │ ├── odbc │ │ │ ├── __init__.py │ │ │ └── test_odbc_connector.py │ │ └── opcua │ │ │ ├── __init__.py │ │ │ ├── helpers.py │ │ │ ├── opcua_test_server.py │ │ │ ├── test_integration.py │ │ │ └── test_opcua_connector.py │ ├── data │ │ ├── __init__.py │ │ ├── can │ │ │ ├── attribute_updates.json │ │ │ ├── multiple_polling.json │ │ │ ├── polling_always.json │ │ │ ├── polling_once.json │ │ │ ├── rpc.json │ │ │ └── ts_and_attr.json │ │ ├── gateway │ │ │ ├── gateway.json │ │ │ ├── logs.json │ │ │ └── mqtt.json │ │ ├── modbus │ │ │ ├── __init__.py │ │ │ ├── modbus_attribute_updates.json │ │ │ ├── modbus_attributes.json │ │ │ ├── modbus_rpc.json │ │ │ └── modbus_server.py │ │ ├── odbc │ │ │ ├── odbc_attributes.json │ │ │ ├── odbc_iterator.json │ │ │ ├── odbc_rpc.json │ │ │ ├── odbc_timeseries.json │ │ │ ├── postgres.sql │ │ │ └── sqlite3.db │ │ └── opcua │ │ │ ├── connection_test.json │ │ │ └── opcua_test_connection.json │ ├── integration_base_test.py │ └── service │ │ ├── __init__.py │ │ └── test_gateway_client.py ├── requirements.txt ├── start_tests.sh ├── test_utils │ ├── __init__.py │ └── gateway_device_util.py ├── tests.py └── unit │ ├── BaseUnitTest.py │ ├── __init__.py │ ├── connectors │ ├── __init__.py │ ├── bacnet │ │ ├── __init__.py │ │ └── test_device.py │ ├── ftp │ │ ├── __init__.py │ │ ├── data │ │ │ ├── anonym_type │ │ │ │ ├── new_config.json │ │ │ │ └── old_config.json │ │ │ ├── attribute_updates │ │ │ │ ├── new_config.json │ │ │ │ └── old_config.json │ │ │ └── basic_type │ │ │ │ ├── new_config.json │ │ │ │ └── old_config.json │ │ └── test_ftp_backward_compatibility_adapter.py │ ├── mqtt │ │ ├── __init__.py │ │ ├── data │ │ │ ├── attribute_requests │ │ │ │ ├── new_config.json │ │ │ │ └── old_config.json │ │ │ ├── attribute_updates │ │ │ │ ├── new_config.json │ │ │ │ └── old_config.json │ │ │ ├── connect_requests │ │ │ │ ├── new_config.json │ │ │ │ └── old_config.json │ │ │ ├── disconnect_requests │ │ │ │ ├── new_config.json │ │ │ │ └── old_config.json │ │ │ ├── mapping │ │ │ │ ├── new_config.json │ │ │ │ └── old_config.json │ │ │ └── server_side_rpc │ │ │ │ ├── new_config.json │ │ │ │ └── old_config.json │ │ └── test_mqtt_backward_compatibility_adapter.py │ ├── opcua │ │ ├── __init__.py │ │ └── test_check_path.py │ └── socket │ │ ├── __init__.py │ │ ├── data │ │ ├── new_config.json │ │ └── old_config.json │ │ └── test_socket_backward_compatibility_adapter.py │ ├── converters │ ├── __init__.py │ ├── can │ │ ├── __init__.py │ │ ├── test_bytes_can_downlink_converter.py │ │ └── test_bytes_can_uplink_converter.py │ ├── modbus │ │ ├── __init__.py │ │ └── test_bytes_modbus_uplink_converter.py │ ├── mqtt │ │ ├── __init__.py │ │ └── test_mqtt_json_uplink_converter.py │ ├── odbc │ │ ├── __init__.py │ │ └── test_odbc_uplink_converter.py │ └── request │ │ ├── __init__.py │ │ └── test_request_json_uplink_converter.py │ ├── data │ └── __init__.py │ └── service │ ├── __init__.py │ ├── test_storage.py │ └── test_ts_format_resolver.py ├── thingsboard-gateway.spec └── thingsboard_gateway ├── __init__.py ├── config ├── bacnet.json ├── ble.json ├── can.json ├── custom_serial.json ├── ftp.json ├── knx.json ├── list.json ├── logs.json ├── modbus.json ├── modbus_serial.json ├── mqtt.json ├── ocpp.json ├── odbc.json ├── opcua.json ├── request.json ├── rest.json ├── snmp.json ├── socket.json ├── statistics │ ├── statistics_linux.json │ ├── statistics_macos.json │ └── statistics_windows.json ├── tb_gateway.json └── xmpp.json ├── connectors ├── __init__.py ├── bacnet │ ├── __init__.py │ ├── application.py │ ├── application_service_access_point.py │ ├── backward_compatibility_adapter.py │ ├── bacnet_connector.py │ ├── bacnet_converter.py │ ├── bacnet_uplink_converter.py │ ├── device.py │ └── entities │ │ ├── __init__.py │ │ ├── bacnet_device_details.py │ │ ├── device_info.py │ │ ├── device_object_config.py │ │ ├── routers.py │ │ └── uplink_converter_config.py ├── ble │ ├── __init__.py │ ├── ble_connector.py │ ├── ble_uplink_converter.py │ ├── bytes_ble_uplink_converter.py │ ├── device.py │ ├── error_handler.py │ └── hex_bytes_ble_uplink_converter.py ├── can │ ├── __init__.py │ ├── bytes_can_downlink_converter.py │ ├── bytes_can_uplink_converter.py │ ├── can_connector.py │ └── can_converter.py ├── connector.py ├── converter.py ├── ftp │ ├── __init__.py │ ├── backward_compatibility_adapter.py │ ├── file.py │ ├── ftp_connector.py │ ├── ftp_converter.py │ ├── ftp_uplink_converter.py │ └── path.py ├── knx │ ├── __init__.py │ ├── entities │ │ ├── __init__.py │ │ ├── client_config.py │ │ ├── device.py │ │ └── gateways_scanner.py │ ├── knx_connector.py │ ├── knx_converter.py │ └── knx_uplink_converter.py ├── modbus │ ├── __init__.py │ ├── backward_compatibility_adapter.py │ ├── bytes_modbus_downlink_converter.py │ ├── bytes_modbus_uplink_converter.py │ ├── constants.py │ ├── entities │ │ ├── __init__.py │ │ ├── bytes_downlink_converter_config.py │ │ ├── bytes_uplink_converter_config.py │ │ ├── clients.py │ │ └── master.py │ ├── modbus_connector.py │ ├── modbus_converter.py │ ├── server.py │ └── slave.py ├── mqtt │ ├── __init__.py │ ├── backward_compatibility_adapter.py │ ├── bytes_mqtt_uplink_converter.py │ ├── json_mqtt_uplink_converter.py │ ├── mqtt_connector.py │ ├── mqtt_decorators.py │ └── mqtt_uplink_converter.py ├── ocpp │ ├── __init__.py │ ├── charge_point.py │ ├── ocpp_connector.py │ ├── ocpp_converter.py │ └── ocpp_uplink_converter.py ├── odbc │ ├── __init__.py │ ├── odbc_connector.py │ ├── odbc_converter.py │ └── odbc_uplink_converter.py ├── opcua │ ├── __init__.py │ ├── backward_compatibility_adapter.py │ ├── device.py │ ├── opcua_connector.py │ ├── opcua_converter.py │ └── opcua_uplink_converter.py ├── request │ ├── __init__.py │ ├── json_request_downlink_converter.py │ ├── json_request_uplink_converter.py │ ├── request_connector.py │ ├── request_converter.py │ └── request_uplink_converter.py ├── rest │ ├── __init__.py │ ├── backward_compatibility_adapter.py │ ├── json_rest_downlink_converter.py │ ├── json_rest_uplink_converter.py │ ├── rest_connector.py │ ├── rest_converter.py │ └── ssl_generator.py ├── snmp │ ├── __init__.py │ ├── snmp_connector.py │ ├── snmp_downlink_converter.py │ └── snmp_uplink_converter.py ├── socket │ ├── __init__.py │ ├── backward_compatibility_adapter.py │ ├── bytes_socket_uplink_converter.py │ ├── socket_connector.py │ ├── socket_decorators.py │ └── socket_uplink_converter.py └── xmpp │ ├── __init__.py │ ├── device.py │ ├── xmpp_connector.py │ ├── xmpp_converter.py │ └── xmpp_uplink_converter.py ├── extensions ├── __init__.py ├── bacnet │ └── __init__.py ├── bacnet_old │ └── __init__.py ├── ble │ └── __init__.py ├── can │ └── __init__.py ├── ftp │ └── __init__.py ├── knx │ └── __init__.py ├── modbus │ └── __init__.py ├── modbus_old │ └── __init__.py ├── mqtt │ ├── __init__.py │ └── custom_mqtt_uplink_converter.py ├── ocpp │ └── __init__.py ├── odbc │ └── __init__.py ├── opcua │ └── __init__.py ├── request │ └── __init__.py ├── rest │ └── __init__.py ├── serial │ ├── __init__.py │ ├── custom_serial_connector.py │ ├── custom_serial_downlink_converter.py │ └── custom_serial_uplink_converter.py ├── snmp │ └── __init__.py ├── socket │ └── __init__.py └── xmpp │ └── __init__.py ├── gateway ├── __init__.py ├── configuration_wizard.py ├── constant_enums.py ├── constants.py ├── device_filter.py ├── entities │ ├── __init__.py │ ├── attributes.py │ ├── converted_data.py │ ├── datapoint_key.py │ ├── device_event_pack.py │ ├── report_strategy_config.py │ └── telemetry_entry.py ├── grpc_service │ ├── __init__.py │ ├── grpc_connector.py │ ├── grpc_downlink_converter.py │ ├── grpc_uplink_converter.py │ ├── tb_grpc_manager.py │ └── tb_grpc_server.py ├── hot_reloader.py ├── proto │ ├── __init__.py │ ├── messages.proto │ ├── messages_pb2.py │ └── messages_pb2_grpc.py ├── report_strategy │ ├── __init__.py │ ├── report_strategy_data_cache.py │ └── report_strategy_service.py ├── shell │ ├── __init__.py │ ├── proxy.py │ └── shell.py ├── statistics │ ├── __init__.py │ ├── configs.py │ ├── decorators.py │ ├── service_functions.py │ └── statistics_service.py ├── tb_client.py └── tb_gateway_service.py ├── grpc_connectors ├── __init__.py ├── gw_grpc_client.py ├── gw_grpc_connector.py ├── gw_grpc_msg_creator.py ├── gw_msg_callbacks.py ├── modbus │ ├── __init__.py │ ├── bytes_modbus_uplink_converter.py │ ├── modbus_connector.py │ └── slave.py ├── mqtt │ ├── __init__.py │ ├── bytes_mqtt_uplink_converter.py │ ├── json_mqtt_uplink_converter.py │ └── mqtt_connector.py ├── opcua │ ├── __init__.py │ ├── opcua_connector.py │ └── opcua_uplink_converter.py └── socket │ ├── __init__.py │ ├── bytes_socket_uplink_converter.py │ └── socket_connector.py ├── storage ├── __init__.py ├── event_storage.py ├── file │ ├── __init__.py │ ├── event_storage_files.py │ ├── event_storage_reader.py │ ├── event_storage_reader_pointer.py │ ├── event_storage_writer.py │ ├── file_event_storage.py │ └── file_event_storage_settings.py ├── memory │ ├── __init__.py │ └── memory_event_storage.py └── sqlite │ ├── __init__.py │ ├── database.py │ ├── database_connector.py │ ├── sqlite_event_storage.py │ └── storage_settings.py ├── tb_gateway.py ├── tb_utility ├── __init__.py ├── tb_gateway_remote_configurator.py ├── tb_handler.py ├── tb_loader.py ├── tb_logger.py ├── tb_remote_shell.py ├── tb_rotating_file_handler.py ├── tb_updater.py └── tb_utility.py └── version.py /.dockerignore: -------------------------------------------------------------------------------- 1 | # ignore everyhting 2 | * 3 | 4 | # except the following 5 | !/thingsboard_gateway/ 6 | !LICENSE 7 | !README.md 8 | !setup.py 9 | !requirements.txt 10 | 11 | # ignore on every level 12 | **/__pycache__/ 13 | **/*.py[cod] 14 | **/logs/ 15 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "[BUG]" 5 | labels: bug 6 | assignees: imbeacon, samson0v 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | Clear and concise description of what the bug is. 12 | 13 | **Connector name (If bug in the some connector):** 14 | [e.g. OPC-UA Connector] 15 | 16 | **Error traceback (If available):** 17 | ``` 18 | 'deviceName' 19 | Traceback (most recent call last): 20 | File "", line 2, in 21 | KeyError: 'deviceName' 22 | ``` 23 | 24 | **Versions (please complete the following information):** 25 | - OS: [e.g. Ubuntu 18.04] 26 | - Thingsboard IoT Gateway version [e.g. 2.0] 27 | - Python version[e.g. 3.7] 28 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: If you have some suggestion about improvemnts or optimization 4 | title: "[Feature]" 5 | labels: feature 6 | assignees: imbeacon, samson0v 7 | 8 | --- 9 | 10 | **Describe the feature** 11 | Create a description of your idea and describe use cases where this feature can be useful. 12 | 13 | 14 | **Connector name (If you want to improve some connector/converter):** 15 | [e.g. MQTT Connector] 16 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/help_wanted.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Help wanted 3 | about: If you have some issues with configuration 4 | title: "[HELP]" 5 | labels: help wanted 6 | assignees: imbeacon, samson0v 7 | 8 | --- 9 | 10 | **Describe the issue** 11 | Create description about your issue, and your actions to solve it. 12 | 13 | 14 | **Configuration** (Attach your configuration file) 15 | **Notate: Remove Access token from file if you want to attach a tb_gateway.yaml** 16 | 17 | 18 | **Connector name (If you need help with some connector/converter):** 19 | [e.g. MQTT Connector] 20 | 21 | 22 | **Error traceback (If it was raised):** 23 | ``` 24 | 'deviceName' 25 | Traceback (most recent call last): 26 | File "", line 2, in 27 | KeyError: 'deviceName' 28 | ``` 29 | 30 | 31 | **Versions (please complete the following information):** 32 | - OS: [e.g. Ubuntu 20.04] 33 | - Thingsboard IoT Gateway version [e.g. 3.0.1] 34 | - Python version[e.g. 3.9] 35 | -------------------------------------------------------------------------------- /.github/workflows/close_issue.yml: -------------------------------------------------------------------------------- 1 | on: 2 | issues: 3 | types: 4 | - closed 5 | 6 | name: Move ticket to closed 7 | 8 | jobs: 9 | close-ticket-in-jira: 10 | if: ${{ !github.event.issue.pull_request }} 11 | name: Close ticket 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Login 15 | uses: atlassian/gajira-login@master 16 | env: 17 | JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} 18 | JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} 19 | JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} 20 | 21 | - name: Find Comment 22 | uses: peter-evans/find-comment@v2 23 | id: find_comment 24 | with: 25 | issue-number: ${{ github.event.issue.number }} 26 | comment-author: 'github-actions[bot]' 27 | direction: first 28 | nth: 0 29 | 30 | - name: Find Jira ticket 31 | if: steps.find_comment.outputs.comment-id != '' 32 | id: find_ticket 33 | uses: atlassian/gajira-find-issue-key@v3 34 | with: 35 | string: ${{ steps.find_comment.outputs.comment-body }} 36 | 37 | - name: Update Jira ticket 38 | if: steps.find_ticket.outputs.issue != '' 39 | uses: atlassian/gajira-comment@v3 40 | with: 41 | issue: ${{ steps.find_ticket.outputs.issue }} 42 | comment: | 43 | Github issue was closed by *${{ github.event.sender.login }}* 44 | 45 | - name: Move to Done 46 | if: steps.find_ticket.outputs.issue != '' 47 | id: transition 48 | uses: atlassian/gajira-transition@v3 49 | with: 50 | issue: ${{ steps.find_ticket.outputs.issue }} 51 | transition: "Closed" 52 | -------------------------------------------------------------------------------- /.github/workflows/reopened_issue.yml: -------------------------------------------------------------------------------- 1 | on: 2 | issues: 3 | types: 4 | - reopened 5 | 6 | name: Move ticket if it was reopened 7 | 8 | jobs: 9 | close-ticket-in-jira: 10 | if: ${{ !github.event.issue.pull_request }} 11 | name: Move ticket if reopened 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Login 15 | uses: atlassian/gajira-login@master 16 | env: 17 | JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} 18 | JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} 19 | JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} 20 | 21 | - name: Find Comment 22 | uses: peter-evans/find-comment@v2 23 | id: find_comment 24 | with: 25 | issue-number: ${{ github.event.issue.number }} 26 | comment-author: 'github-actions[bot]' 27 | direction: first 28 | nth: 0 29 | 30 | - name: Find Jira ticket 31 | if: steps.find_comment.outputs.comment-id != '' 32 | id: find_ticket 33 | uses: atlassian/gajira-find-issue-key@v3 34 | with: 35 | string: ${{ steps.find_comment.outputs.comment-body }} 36 | 37 | - name: Update Jira ticket 38 | if: steps.find_ticket.outputs.issue != '' 39 | uses: atlassian/gajira-comment@v3 40 | with: 41 | issue: ${{ steps.find_ticket.outputs.issue }} 42 | comment: | 43 | Github issue was reopened by *${{ github.event.sender.login }}* 44 | 45 | - name: Move to Backlog 46 | if: steps.find_ticket.outputs.issue != '' 47 | id: transition_to_backlog 48 | uses: atlassian/gajira-transition@v3 49 | with: 50 | issue: ${{ steps.find_ticket.outputs.issue }} 51 | transition: "task in backlog" 52 | 53 | - name: Move to Backlog 54 | if: steps.find_ticket.outputs.issue != '' 55 | id: transition_to_todo 56 | uses: atlassian/gajira-transition@v3 57 | with: 58 | issue: ${{ steps.find_ticket.outputs.issue }} 59 | transition: "Admin permissions only" 60 | 61 | -------------------------------------------------------------------------------- /.github/workflows/update_issue_in_jira.yml: -------------------------------------------------------------------------------- 1 | on: 2 | issue_comment: 3 | types: 4 | - created 5 | 6 | name: Create a comment for ticket in Jira 7 | 8 | jobs: 9 | create-comment-for-ticket-in-jira: 10 | if: ${{ !github.event.issue.pull_request }} 11 | name: Ticket comment creation 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Login 15 | uses: atlassian/gajira-login@master 16 | env: 17 | JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} 18 | JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} 19 | JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} 20 | 21 | - name: Find Comment 22 | uses: peter-evans/find-comment@v2 23 | id: find_comment 24 | with: 25 | issue-number: ${{ github.event.issue.number }} 26 | comment-author: 'github-actions[bot]' 27 | direction: first 28 | nth: 0 29 | 30 | - name: Find Jira ticket 31 | if: steps.find_comment.outputs.comment-id != '' 32 | id: find_ticket 33 | uses: atlassian/gajira-find-issue-key@v3 34 | with: 35 | string: ${{ steps.find_comment.outputs.comment-body }} 36 | 37 | - name: Update Jira ticket 38 | if: steps.find_ticket.outputs.issue != '' 39 | uses: atlassian/gajira-comment@v3 40 | with: 41 | issue: ${{ steps.find_ticket.outputs.issue }} 42 | comment: | 43 | Github issue was commented by *${{ github.event.comment.user.login }}*: 44 | 45 | ${{ github.event.comment.body }} 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | thingsboard_gateway/venv/ 2 | thingsboard_gateway/logs/* 3 | thingsboard_gateway/config/connected_devices.json 4 | thingsboard_gateway/storage/data/ 5 | .idea/ 6 | .vscode/ 7 | /build/ 8 | /deb_dist/ 9 | /dist/ 10 | *.gz 11 | /logs/ 12 | *.deb 13 | *.rpm 14 | /*.egg-info/ 15 | /data/ 16 | /logs/ 17 | __pycache__ 18 | /thingsboard_gateway/config/ 19 | venv 20 | .venv 21 | .env 22 | /for_build/etc/thingsboard-gateway/config/ 23 | /thingsboard_gateway/logs/ 24 | /tests/storage/ 25 | /tests/blackbox/connectors/opcua/_trial_temp/ 26 | /tests/blackbox/connectors/modbus/_trial_temp/ 27 | *.DS_Store 28 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "tb_mqtt_client"] 2 | path = tb_mqtt_client 3 | url = https://github.com/thingsboard/thingsboard-python-client-sdk.git 4 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | graft thingsboard_gateway/config 2 | include LICENSE 3 | -------------------------------------------------------------------------------- /build_latest_docker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Copyright 2025. ThingsBoard 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | set -e # exit on any error 17 | 18 | # Fetch the current branch name and latest commit ID 19 | BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD | sed 's/[\/]/-/g') 20 | COMMIT_ID=$(git rev-parse --short HEAD) 21 | 22 | # Combine them to create a version tag 23 | VERSION_TAG="${BRANCH_NAME}-${COMMIT_ID}" 24 | 25 | echo "$(date) Building project with version tag $VERSION_TAG ..." 26 | set -x 27 | 28 | # multi arch 29 | DOCKER_CLI_EXPERIMENTAL=enabled \ 30 | docker buildx build . -t tb-gateway:$VERSION_TAG -f docker/Dockerfile --platform=linux/amd64,linux/arm64 -o type=registry 31 | 32 | set +x 33 | echo "$(date) Done." 34 | -------------------------------------------------------------------------------- /docker/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.4' 2 | services: 3 | # ThingsBoard IoT Gateway Service Configuration 4 | tb-gateway: 5 | image: thingsboard/tb-gateway 6 | container_name: tb-gateway 7 | restart: always 8 | 9 | # Ports bindings - required by some connectors 10 | ports: 11 | - "5000:5000" # Comment if you don't use REST connector and change if you use another port 12 | # Uncomment and modify the following ports based on connector usage: 13 | # - "1052:1052" # BACnet connector 14 | # - "5026:5026" # Modbus TCP connector (Modbus Slave) 15 | # - "50000:50000/tcp" # Socket connector with type TCP 16 | # - "50000:50000/udp" # Socket connector with type UDP 17 | 18 | # Necessary mapping for Linux 19 | extra_hosts: 20 | - "host.docker.internal:host-gateway" 21 | 22 | # Environment variables 23 | environment: 24 | - TB_GW_HOST=host.docker.internal 25 | - TB_GW_PORT=1883 26 | - TB_GW_ACCESS_TOKEN=YOUR_ACCESS_TOKEN 27 | - TB_GW_LOGS_PATH=/thingsboard_gateway/logs 28 | 29 | # Volumes bind 30 | volumes: 31 | - tb-gw-config:/thingsboard_gateway/config 32 | - tb-gw-logs:/thingsboard_gateway/logs 33 | - tb-gw-extensions:/thingsboard_gateway/extensions 34 | 35 | # Volumes declaration for configurations, extensions and configuration 36 | volumes: 37 | tb-gw-config: 38 | name: tb-gw-config 39 | tb-gw-logs: 40 | name: tb-gw-logs 41 | tb-gw-extensions: 42 | name: tb-gw-extensions 43 | -------------------------------------------------------------------------------- /for_build/DEBIAN/preinst: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | echo "Preinst: Ensuring required directories exist..." 5 | 6 | for dir in /etc/thingsboard-gateway /var/lib/thingsboard_gateway /var/log/thingsboard-gateway /var/lib/thingsboard_gateway/extensions; do 7 | if [ ! -d "$dir" ]; then 8 | echo "Preinst: Creating directory $dir..." 9 | mkdir -p "$dir" 10 | else 11 | echo "Preinst: Directory $dir already exists." 12 | fi 13 | done 14 | 15 | echo "Preinst: Checking for system user 'thingsboard_gateway'..." 16 | if id "thingsboard_gateway" >/dev/null 2>&1; then 17 | echo "Preinst: User 'thingsboard_gateway' already exists. Skipping creation." 18 | else 19 | adduser --system --gecos "ThingsBoard-Gateway Service" --disabled-password --group --home /var/lib/thingsboard_gateway thingsboard_gateway 20 | echo "Preinst: Created user 'thingsboard_gateway'." 21 | fi 22 | 23 | exit 0 24 | -------------------------------------------------------------------------------- /for_build/DEBIAN/pydist-overrides: -------------------------------------------------------------------------------- 1 | pip python3-pip; PEP386 2 | lxml python3-lxml; PEP386 3 | cryptography python3-cryptography; PEP386 4 | opcua python3-opcua; PEP386 5 | paho-mqtt python3-paho-mqtt; PEP386 6 | pymodbus python3-pymodbus; PEP386 7 | pyserial python3-pyserial; PEP386 8 | pyyaml python3-PyYAML; PEP386 9 | pyrsistent python3-pyrsistent; PEP386 10 | importlib python3-importlib; PEP386 11 | jsonparh-rw python3-jsonpath-rw; PEP386 12 | regex python3-regex; PEP386 13 | requests python3-requests; PEP386 14 | pyinquirer python3-pyinquirer; PEP386 -------------------------------------------------------------------------------- /for_build/etc/systemd/system/thingsboard-gateway.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=ThingsBoard Gateway 3 | After=multi-user.target 4 | ConditionPathExists=/etc/thingsboard-gateway/config/tb_gateway.json 5 | 6 | [Service] 7 | Type=simple 8 | User=thingsboard_gateway 9 | Group=thingsboard_gateway 10 | 11 | WorkingDirectory=/var/lib/thingsboard_gateway 12 | ExecStart=/var/lib/thingsboard_gateway/venv/bin/python3 -c "from thingsboard_gateway.tb_gateway import daemon; daemon()" 13 | ExecStop=/bin/kill -INT $MAINPID 14 | ExecReload=/bin/kill -TERM $MAINPID 15 | 16 | Restart=on-failure 17 | 18 | [Install] 19 | WantedBy=multi-user.target 20 | -------------------------------------------------------------------------------- /for_build/var/log/thingsboard-gateway/connector.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/for_build/var/log/thingsboard-gateway/connector.log -------------------------------------------------------------------------------- /for_build/var/log/thingsboard-gateway/converter.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/for_build/var/log/thingsboard-gateway/converter.log -------------------------------------------------------------------------------- /for_build/var/log/thingsboard-gateway/database.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/for_build/var/log/thingsboard-gateway/database.log -------------------------------------------------------------------------------- /for_build/var/log/thingsboard-gateway/extension.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/for_build/var/log/thingsboard-gateway/extension.log -------------------------------------------------------------------------------- /for_build/var/log/thingsboard-gateway/service.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/for_build/var/log/thingsboard-gateway/service.log -------------------------------------------------------------------------------- /for_build/var/log/thingsboard-gateway/storage.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/for_build/var/log/thingsboard-gateway/storage.log -------------------------------------------------------------------------------- /for_build/var/log/thingsboard-gateway/tb_connection.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/for_build/var/log/thingsboard-gateway/tb_connection.log -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | setuptools 2 | packaging==23.1 3 | jsonpath-rw 4 | regex 5 | pip 6 | PyYAML 7 | simplejson 8 | orjson 9 | pybase64 10 | urllib3>=2.3.0 11 | requests>=2.32.3 12 | questionary 13 | pyfiglet 14 | python-dateutil 15 | termcolor 16 | grpcio 17 | mmh3 18 | protobuf<=3.20.0 19 | cachetools 20 | tb-paho-mqtt-client>=2.1.2 21 | tb-mqtt-client>=1.13.5 22 | service-identity 23 | psutil 24 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | -------------------------------------------------------------------------------- /tests/base_test.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import signal 3 | from sys import platform, stdout 4 | from unittest import TestCase 5 | from tests.test_utils.gateway_device_util import GatewayDeviceUtil 6 | 7 | logging.basicConfig(level=logging.DEBUG, 8 | format='%(asctime)s - %(levelname)s - %(module)s - %(lineno)d - %(message)s', 9 | datefmt='%Y-%m-%d %H:%M:%S') 10 | 11 | LOG = logging.getLogger("TEST") 12 | LOG.level = logging.DEBUG 13 | stream_handler = logging.StreamHandler(stdout) 14 | LOG.addHandler(stream_handler) 15 | LOG.trace = LOG.debug 16 | 17 | 18 | class BaseTest(TestCase): 19 | TIMEOUT = 600 # 10 minutes in seconds 20 | 21 | def __init__(self, *args, **kwargs): 22 | super().__init__(*args, **kwargs) 23 | self.log = LOG 24 | self.log.trace = self.log.debug 25 | 26 | @classmethod 27 | def setUpClass(cls): 28 | GatewayDeviceUtil.get_gateway_device() 29 | 30 | @classmethod 31 | def tearDownClass(cls): 32 | GatewayDeviceUtil.delete_gateway_device() 33 | assert GatewayDeviceUtil.GATEWAY_DEVICE is None 34 | 35 | def setUp(self): 36 | if platform.startswith("win"): 37 | signal.signal(signal.SIGALRM, self._timeout_handler) 38 | signal.alarm(self.TIMEOUT) 39 | 40 | def tearDown(self): 41 | signal.alarm(0) # Disable the alarm 42 | 43 | def _timeout_handler(self, signum, frame): 44 | raise TimeoutError(f"Test exceeded the time limit of {self.TIMEOUT} seconds") -------------------------------------------------------------------------------- /tests/blackbox/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/tests/blackbox/__init__.py -------------------------------------------------------------------------------- /tests/blackbox/connectors/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/tests/blackbox/connectors/__init__.py -------------------------------------------------------------------------------- /tests/blackbox/connectors/modbus/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/tests/blackbox/connectors/modbus/__init__.py -------------------------------------------------------------------------------- /tests/blackbox/connectors/opcua/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/tests/blackbox/connectors/opcua/__init__.py -------------------------------------------------------------------------------- /tests/blackbox/data/modbus/configs/default_modbus_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "Modbus": { 3 | "name": "Modbus", 4 | "type": "modbus", 5 | "logLevel": "DEBUG", 6 | "configuration": "modbus.json", 7 | "configurationJson": { 8 | "name": "Modbus", 9 | "logLevel": "DEBUG", 10 | "master": { 11 | "slaves": [ 12 | { 13 | "host": "localhost", 14 | "port": 5021, 15 | "type": "tcp", 16 | "method": "socket", 17 | "timeout": 35, 18 | "byteOrder": "LITTLE", 19 | "wordOrder": "LITTLE", 20 | "retries": true, 21 | "retryOnEmpty": true, 22 | "retryOnInvalid": true, 23 | "pollPeriod": 1000, 24 | "unitId": 2, 25 | "deviceName": "Temp Sensor", 26 | "sendDataOnlyOnChange": false, 27 | "connectAttemptTimeMs": 5000, 28 | "connectAttemptCount": 5, 29 | "waitAfterFailedAttemptsMs": 300000, 30 | "attributes": [ 31 | { 32 | "tag": "string_read", 33 | "type": "string", 34 | "functionCode": 4, 35 | "objectsCount": 2, 36 | "address": 0 37 | } 38 | ], 39 | "timeseries": [], 40 | "attributeUpdates": [], 41 | "rpc": [] 42 | } 43 | ] 44 | } 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /tests/blackbox/data/modbus/configs/rpc_configs/coils_writing_rpc_big.json: -------------------------------------------------------------------------------- 1 | { 2 | "Modbus": { 3 | "name": "Modbus", 4 | "type": "modbus", 5 | "logLevel": "DEBUG", 6 | "configuration": "modbus.json", 7 | "configurationJson": { 8 | "name": "Modbus", 9 | "logLevel": "DEBUG", 10 | "master": { 11 | "slaves": [ 12 | { 13 | "host": "localhost", 14 | "port": 5021, 15 | "type": "tcp", 16 | "method": "socket", 17 | "timeout": 35, 18 | "byteOrder": "BIG", 19 | "wordOrder": "BIG", 20 | "retries": true, 21 | "retryOnEmpty": true, 22 | "retryOnInvalid": true, 23 | "pollPeriod": 2000, 24 | "unitId": 2, 25 | "deviceName": "Temp Sensor", 26 | "sendDataOnlyOnChange": false, 27 | "connectAttemptTimeMs": 5000, 28 | "connectAttemptCount": 5, 29 | "waitAfterFailedAttemptsMs": 300000, 30 | "attributes": [], 31 | "timeseries": [ 32 | { 33 | "tag": "bits", 34 | "type": "bits", 35 | "functionCode": 1, 36 | "objectsCount": 16, 37 | "address": 0 38 | }, 39 | { 40 | "tag": "bit", 41 | "type": "bit", 42 | "functionCode": 1, 43 | "objectsCount": 1, 44 | "address": 0 45 | } 46 | ], 47 | "attributeUpdates": [], 48 | "rpc": [ 49 | { 50 | "tag": "bits", 51 | "type": "coils", 52 | "functionCode": 15, 53 | "objectsCount": 16, 54 | "address": 0 55 | } 56 | ] 57 | } 58 | ] 59 | } 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /tests/blackbox/data/modbus/configs/rpc_configs/coils_writing_rpc_little.json: -------------------------------------------------------------------------------- 1 | { 2 | "Modbus": { 3 | "name": "Modbus", 4 | "type": "modbus", 5 | "logLevel": "DEBUG", 6 | "configuration": "modbus.json", 7 | "configurationJson": { 8 | "name": "Modbus", 9 | "logLevel": "DEBUG", 10 | "master": { 11 | "slaves": [ 12 | { 13 | "host": "localhost", 14 | "port": 5021, 15 | "type": "tcp", 16 | "method": "socket", 17 | "timeout": 35, 18 | "byteOrder": "LITTLE", 19 | "wordOrder": "LITTLE", 20 | "retries": true, 21 | "retryOnEmpty": true, 22 | "retryOnInvalid": true, 23 | "pollPeriod": 2000, 24 | "unitId": 2, 25 | "deviceName": "Temp Sensor", 26 | "sendDataOnlyOnChange": false, 27 | "connectAttemptTimeMs": 5000, 28 | "connectAttemptCount": 5, 29 | "waitAfterFailedAttemptsMs": 300000, 30 | "attributes": [], 31 | "timeseries": [ 32 | { 33 | "tag": "bits", 34 | "type": "bits", 35 | "functionCode": 1, 36 | "objectsCount": 16, 37 | "address": 0 38 | }, 39 | { 40 | "tag": "bit", 41 | "type": "bit", 42 | "functionCode": 1, 43 | "objectsCount": 1, 44 | "address": 0 45 | } 46 | ], 47 | "attributeUpdates": [], 48 | "rpc": [ 49 | { 50 | "tag": "bits", 51 | "type": "coils", 52 | "functionCode": 15, 53 | "objectsCount": 16, 54 | "address": 0 55 | } 56 | ] 57 | } 58 | ] 59 | } 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /tests/blackbox/data/modbus/configs/rpc_configs/discrete_inputs_writing_rpc_big.json: -------------------------------------------------------------------------------- 1 | { 2 | "Modbus": { 3 | "name": "Modbus", 4 | "type": "modbus", 5 | "logLevel": "DEBUG", 6 | "configuration": "modbus.json", 7 | "configurationJson": { 8 | "name": "Modbus", 9 | "logLevel": "DEBUG", 10 | "master": { 11 | "slaves": [ 12 | { 13 | "host": "localhost", 14 | "port": 5021, 15 | "type": "tcp", 16 | "method": "socket", 17 | "timeout": 35, 18 | "byteOrder": "BIG", 19 | "wordOrder": "BIG", 20 | "retries": true, 21 | "retryOnEmpty": true, 22 | "retryOnInvalid": true, 23 | "pollPeriod": 2000, 24 | "unitId": 2, 25 | "deviceName": "Temp Sensor", 26 | "sendDataOnlyOnChange": false, 27 | "connectAttemptTimeMs": 5000, 28 | "connectAttemptCount": 5, 29 | "waitAfterFailedAttemptsMs": 300000, 30 | "attributes": [], 31 | "timeseries": [ 32 | { 33 | "tag": "bits", 34 | "type": "bits", 35 | "functionCode": 2, 36 | "objectsCount": 16, 37 | "address": 0 38 | }, 39 | { 40 | "tag": "bit", 41 | "type": "bit", 42 | "functionCode": 2, 43 | "objectsCount": 1, 44 | "address": 0 45 | } 46 | ], 47 | "attributeUpdates": [], 48 | "rpc": [ 49 | { 50 | "tag": "bits", 51 | "type": "bits", 52 | "functionCode": 6, 53 | "objectsCount": 16, 54 | "address": 0 55 | } 56 | ] 57 | } 58 | ] 59 | } 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /tests/blackbox/data/modbus/configs/rpc_configs/discrete_inputs_writing_rpc_little.json: -------------------------------------------------------------------------------- 1 | { 2 | "Modbus": { 3 | "name": "Modbus", 4 | "type": "modbus", 5 | "logLevel": "DEBUG", 6 | "configuration": "modbus.json", 7 | "configurationJson": { 8 | "name": "Modbus", 9 | "logLevel": "DEBUG", 10 | "master": { 11 | "slaves": [ 12 | { 13 | "host": "localhost", 14 | "port": 5021, 15 | "type": "tcp", 16 | "method": "socket", 17 | "timeout": 35, 18 | "byteOrder": "LITTLE", 19 | "wordOrder": "LITTLE", 20 | "retries": true, 21 | "retryOnEmpty": true, 22 | "retryOnInvalid": true, 23 | "pollPeriod": 2000, 24 | "unitId": 2, 25 | "deviceName": "Temp Sensor", 26 | "sendDataOnlyOnChange": false, 27 | "connectAttemptTimeMs": 5000, 28 | "connectAttemptCount": 5, 29 | "waitAfterFailedAttemptsMs": 300000, 30 | "attributes": [], 31 | "timeseries": [ 32 | { 33 | "tag": "bits", 34 | "type": "bits", 35 | "functionCode": 2, 36 | "objectsCount": 16, 37 | "address": 0 38 | }, 39 | { 40 | "tag": "bit", 41 | "type": "bit", 42 | "functionCode": 2, 43 | "objectsCount": 1, 44 | "address": 0 45 | } 46 | ], 47 | "attributeUpdates": [], 48 | "rpc": [ 49 | { 50 | "tag": "bits", 51 | "type": "bits", 52 | "functionCode": 6, 53 | "objectsCount": 16, 54 | "address": 0 55 | } 56 | ] 57 | } 58 | ] 59 | } 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /tests/blackbox/data/modbus/configs/uplink_configs/modbus_uplink_converter_coils_reading_big.json: -------------------------------------------------------------------------------- 1 | { 2 | "Modbus": { 3 | "name": "Modbus", 4 | "type": "modbus", 5 | "logLevel": "DEBUG", 6 | "configuration": "modbus.json", 7 | "configurationJson": { 8 | "name": "Modbus", 9 | "logLevel": "DEBUG", 10 | "master": { 11 | "slaves": [ 12 | { 13 | "host": "localhost", 14 | "port": 5021, 15 | "type": "tcp", 16 | "method": "socket", 17 | "timeout": 35, 18 | "byteOrder": "BIG", 19 | "wordOrder": "BIG", 20 | "retries": true, 21 | "retryOnEmpty": true, 22 | "retryOnInvalid": true, 23 | "pollPeriod": 1000, 24 | "unitId": 2, 25 | "deviceName": "Temp Sensor", 26 | "sendDataOnlyOnChange": false, 27 | "connectAttemptTimeMs": 5000, 28 | "connectAttemptCount": 5, 29 | "waitAfterFailedAttemptsMs": 300000, 30 | "attributes": [], 31 | "timeseries": [ 32 | { 33 | "tag": "bits", 34 | "type": "bits", 35 | "functionCode": 1, 36 | "objectsCount": 16, 37 | "address": 0 38 | }, 39 | { 40 | "tag": "bit", 41 | "type": "bit", 42 | "functionCode": 1, 43 | "objectsCount": 1, 44 | "address": 0 45 | } 46 | ], 47 | "attributeUpdates": [], 48 | "rpc": [] 49 | } 50 | ] 51 | } 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /tests/blackbox/data/modbus/configs/uplink_configs/modbus_uplink_converter_coils_reading_little.json: -------------------------------------------------------------------------------- 1 | { 2 | "Modbus": { 3 | "name": "Modbus", 4 | "type": "modbus", 5 | "logLevel": "DEBUG", 6 | "configuration": "modbus.json", 7 | "configurationJson": { 8 | "name": "Modbus", 9 | "logLevel": "DEBUG", 10 | "master": { 11 | "slaves": [ 12 | { 13 | "host": "localhost", 14 | "port": 5021, 15 | "type": "tcp", 16 | "method": "socket", 17 | "timeout": 35, 18 | "byteOrder": "LITTLE", 19 | "wordOrder": "LITTLE", 20 | "retries": true, 21 | "retryOnEmpty": true, 22 | "retryOnInvalid": true, 23 | "pollPeriod": 1000, 24 | "unitId": 2, 25 | "deviceName": "Temp Sensor", 26 | "sendDataOnlyOnChange": false, 27 | "connectAttemptTimeMs": 5000, 28 | "connectAttemptCount": 5, 29 | "waitAfterFailedAttemptsMs": 300000, 30 | "attributes": [], 31 | "timeseries": [ 32 | { 33 | "tag": "bits", 34 | "type": "bits", 35 | "functionCode": 1, 36 | "objectsCount": 16, 37 | "address": 0 38 | }, 39 | { 40 | "tag": "bit", 41 | "type": "bit", 42 | "functionCode": 1, 43 | "objectsCount": 1, 44 | "address": 0 45 | } 46 | ], 47 | "attributeUpdates": [], 48 | "rpc": [] 49 | } 50 | ] 51 | } 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /tests/blackbox/data/modbus/configs/uplink_configs/modbus_uplink_converter_discrete_input_reading_big.json: -------------------------------------------------------------------------------- 1 | { 2 | "Modbus": { 3 | "name": "Modbus", 4 | "type": "modbus", 5 | "logLevel": "DEBUG", 6 | "configuration": "modbus.json", 7 | "configurationJson": { 8 | "name": "Modbus", 9 | "logLevel": "DEBUG", 10 | "master": { 11 | "slaves": [ 12 | { 13 | "host": "localhost", 14 | "port": 5021, 15 | "type": "tcp", 16 | "method": "socket", 17 | "timeout": 35, 18 | "byteOrder": "BIG", 19 | "wordOrder": "BIG", 20 | "retries": true, 21 | "retryOnEmpty": true, 22 | "retryOnInvalid": true, 23 | "pollPeriod": 1000, 24 | "unitId": 2, 25 | "deviceName": "Temp Sensor", 26 | "sendDataOnlyOnChange": false, 27 | "connectAttemptTimeMs": 5000, 28 | "connectAttemptCount": 5, 29 | "waitAfterFailedAttemptsMs": 300000, 30 | "attributes": [], 31 | "timeseries": [ 32 | { 33 | "tag": "bits", 34 | "type": "bits", 35 | "functionCode": 2, 36 | "objectsCount": 16, 37 | "address": 0 38 | }, 39 | { 40 | "tag": "bit", 41 | "type": "bit", 42 | "functionCode": 2, 43 | "objectsCount": 1, 44 | "address": 0 45 | } 46 | ], 47 | "attributeUpdates": [], 48 | "rpc": [] 49 | } 50 | ] 51 | } 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /tests/blackbox/data/modbus/configs/uplink_configs/modbus_uplink_converter_discrete_input_reading_little.json: -------------------------------------------------------------------------------- 1 | { 2 | "Modbus": { 3 | "name": "Modbus", 4 | "type": "modbus", 5 | "logLevel": "DEBUG", 6 | "configuration": "modbus.json", 7 | "configurationJson": { 8 | "name": "Modbus", 9 | "logLevel": "DEBUG", 10 | "master": { 11 | "slaves": [ 12 | { 13 | "host": "localhost", 14 | "port": 5021, 15 | "type": "tcp", 16 | "method": "socket", 17 | "timeout": 35, 18 | "byteOrder": "LITTLE", 19 | "wordOrder": "LITTLE", 20 | "retries": true, 21 | "retryOnEmpty": true, 22 | "retryOnInvalid": true, 23 | "pollPeriod": 1000, 24 | "unitId": 2, 25 | "deviceName": "Temp Sensor", 26 | "sendDataOnlyOnChange": false, 27 | "connectAttemptTimeMs": 5000, 28 | "connectAttemptCount": 5, 29 | "waitAfterFailedAttemptsMs": 300000, 30 | "attributes": [], 31 | "timeseries": [ 32 | { 33 | "tag": "bits", 34 | "type": "bits", 35 | "functionCode": 2, 36 | "objectsCount": 16, 37 | "address": 0 38 | }, 39 | { 40 | "tag": "bit", 41 | "type": "bit", 42 | "functionCode": 2, 43 | "objectsCount": 1, 44 | "address": 0 45 | } 46 | ], 47 | "attributeUpdates": [], 48 | "rpc": [] 49 | } 50 | ] 51 | } 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /tests/blackbox/data/modbus/modbus_rename_configs/default_modbus_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "Modbus": { 3 | "name": "Modbus", 4 | "type": "modbus", 5 | "logLevel": "DEBUG", 6 | "configuration": "modbus.json", 7 | "configurationJson": { 8 | "name": "Modbus", 9 | "logLevel": "DEBUG", 10 | "master": { 11 | "slaves": [ 12 | { 13 | "host": "localhost", 14 | "port": 5021, 15 | "type": "tcp", 16 | "method": "socket", 17 | "timeout": 35, 18 | "byteOrder": "LITTLE", 19 | "wordOrder": "LITTLE", 20 | "retries": true, 21 | "retryOnEmpty": true, 22 | "retryOnInvalid": true, 23 | "pollPeriod": 10000, 24 | "unitId": 2, 25 | "deviceName": "Temp Sensor", 26 | "sendDataOnlyOnChange": false, 27 | "connectAttemptTimeMs": 5000, 28 | "connectAttemptCount": 5, 29 | "waitAfterFailedAttemptsMs": 300000, 30 | "attributes": [ 31 | { 32 | "tag": "string_read", 33 | "type": "string", 34 | "functionCode": 4, 35 | "objectsCount": 2, 36 | "address": 0 37 | } 38 | ], 39 | "timeseries": [], 40 | "attributeUpdates": [], 41 | "rpc": [] 42 | } 43 | ] 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /tests/blackbox/data/modbus/test_values/attrs_update/discrete_and_coils_registers_values_big.json: -------------------------------------------------------------------------------- 1 | { 2 | "bits": [false,true,false,false,false,false,true,true,true,true,false,true,false,false,true,true] 3 | } -------------------------------------------------------------------------------- /tests/blackbox/data/modbus/test_values/attrs_update/discrete_and_coils_registers_values_little.json: -------------------------------------------------------------------------------- 1 | { 2 | "bits": [false,true,false,false,false,false,true,true,true,true,false,true,false,false,true,true] 3 | } -------------------------------------------------------------------------------- /tests/blackbox/data/modbus/test_values/attrs_update/holding_registers_values_big.json: -------------------------------------------------------------------------------- 1 | { 2 | "string": "abcx", 3 | "bits": [false,true,false,true,true,false,true,true,true,true,false,true,false,false,true,true], 4 | "16int": "-30541", 5 | "16uint": "13334", 6 | "16float": "0.0670166015625", 7 | "32int": "-856817645", 8 | "32uint": "2018915246", 9 | "32float": "-0.0000000000000000000000001626903466837544", 10 | "64int": "1243365278113335247", 11 | "64uint": "17275436396653061650", 12 | "64float": "-6065988000872254000000000000000000000000000000000000000000000000000" 13 | } -------------------------------------------------------------------------------- /tests/blackbox/data/modbus/test_values/attrs_update/holding_registers_values_little.json: -------------------------------------------------------------------------------- 1 | { 2 | "string": "abcx", 3 | "bits": [false,true,false,true,true,false,true,true,true,true,false,true,false,false,true,true], 4 | "16int": "-22137", 5 | "16uint": "4661", 6 | "16float": "13.34375", 7 | "32int": "-4661", 8 | "32uint": "305419897", 9 | "32float": "223547.34375", 10 | "64int": "-3735928550", 11 | "64uint": "1311738468603649775", 12 | "64float": "133.45" 13 | } 14 | -------------------------------------------------------------------------------- /tests/blackbox/data/modbus/test_values/attrs_update/input_registers_values_big.json: -------------------------------------------------------------------------------- 1 | { 2 | "string": "abcx", 3 | "bits": [false,true,false,true,true,false,true,true,true,true,false,true,false,false,true,true], 4 | "16int": "-30541", 5 | "16uint": "13334", 6 | "16float": "0.0670166015625", 7 | "32int": "-856817645", 8 | "32uint": "2018915246", 9 | "32float": "-0.0000000000000000000000001626903466837544", 10 | "64int": "1243365278113335247", 11 | "64uint": "17275436396653061650", 12 | "64float": "-6065988000872254000000000000000000000000000000000000000000000000000" 13 | } -------------------------------------------------------------------------------- /tests/blackbox/data/modbus/test_values/attrs_update/input_registers_values_little.json: -------------------------------------------------------------------------------- 1 | { 2 | "string": "abcx", 3 | "bits": [false,true,false,true,true,false,true,true,true,true,false,true,false,false,true,true], 4 | "16int": "-22137", 5 | "16uint": "4661", 6 | "16float": "13.34375", 7 | "32int": "-4661", 8 | "32uint": "305419897", 9 | "32float": "223547.34375", 10 | "64int": "-3735928550", 11 | "64uint": "1311738468603649775", 12 | "64float": "133.45" 13 | } 14 | -------------------------------------------------------------------------------- /tests/blackbox/data/modbus/test_values/default_slave_values.json: -------------------------------------------------------------------------------- 1 | { 2 | "string": "abcd", 3 | "bits": "[false,true,false,true,true,false,true,true,true,true,false,true,false,false,true,false]", 4 | "16int": "-22136", 5 | "16uint": "4660", 6 | "16float": "12.34375", 7 | "32int": "-4660", 8 | "32uint": "305419896", 9 | "32float": "223546.34375", 10 | "64int": "-3735928559", 11 | "64uint": "1311768468603649775", 12 | "64float": "123.45" 13 | } 14 | -------------------------------------------------------------------------------- /tests/blackbox/data/modbus/test_values/rpc/discrete_and_coils_registers_values_reading_big.json: -------------------------------------------------------------------------------- 1 | { 2 | "bits": [false,true,false,true,true,false,true,true,true,true,false,true,false,false,true,false], 3 | "bit": true 4 | } -------------------------------------------------------------------------------- /tests/blackbox/data/modbus/test_values/rpc/discrete_and_coils_registers_values_reading_little.json: -------------------------------------------------------------------------------- 1 | { 2 | "bits": [false,true,false,true,true,false,true,true,true,true,false,true,false,false,true,false], 3 | "bit": true 4 | } -------------------------------------------------------------------------------- /tests/blackbox/data/modbus/test_values/rpc/discrete_and_coils_registers_values_writing_big.json: -------------------------------------------------------------------------------- 1 | { 2 | "bits": [false,true,false,false,false,false,true,true,true,true,false,true,false,false,true,true] 3 | } -------------------------------------------------------------------------------- /tests/blackbox/data/modbus/test_values/rpc/discrete_and_coils_registers_values_writing_little.json: -------------------------------------------------------------------------------- 1 | { 2 | "bits": [false,true,false,false,false,false,true,true,true,true,false,true,false,false,true,true] 3 | } -------------------------------------------------------------------------------- /tests/blackbox/data/modbus/test_values/rpc/holding_registers_values_reading_big.json: -------------------------------------------------------------------------------- 1 | { 2 | "string": "abcd", 3 | "bits": [false,true,false,true,true,false,true,true,true,true,false,true,false,false,true,false], 4 | "16int": -30551, 5 | "16uint": 13330, 6 | "16float": 0.067017, 7 | "32int": -856817665, 8 | "32uint": 2018915346, 9 | "32float": 0.0, 10 | "64int": 1243365278113333247, 11 | "64uint": 17275436391653061650, 12 | "64float": -6.0659880008723545e+66 13 | } -------------------------------------------------------------------------------- /tests/blackbox/data/modbus/test_values/rpc/holding_registers_values_reading_little.json: -------------------------------------------------------------------------------- 1 | { 2 | "string": "abcd", 3 | "bits": [false,true,false,true,true,false,true,true,true,true,false,true,false,false,true,false], 4 | "16int": -22136, 5 | "16uint": 4660, 6 | "16float": 12.34375, 7 | "32int": -4660, 8 | "32uint": 305419896, 9 | "32float": 223546.34375, 10 | "64int": -3735928559, 11 | "64uint": 1311768468603649775, 12 | "64float": 123.45 13 | } -------------------------------------------------------------------------------- /tests/blackbox/data/modbus/test_values/rpc/holding_registers_values_writing_big.json: -------------------------------------------------------------------------------- 1 | { 2 | "string": "abcx", 3 | "bits": [false,true,false,true,true,false,true,true,true,true,false,true,false,false,true,true], 4 | "16int": -30541, 5 | "16uint": 13334, 6 | "16float": 0.067017, 7 | "32int": -856817645, 8 | "32uint": 2018915246, 9 | "32float": -0.020163, 10 | "64int": 1243365278113335247, 11 | "64uint": 17275436396653061650, 12 | "64float": -6065988000872254000000000000000000000000000000000000000000000000000 13 | } -------------------------------------------------------------------------------- /tests/blackbox/data/modbus/test_values/rpc/holding_registers_values_writing_little.json: -------------------------------------------------------------------------------- 1 | { 2 | "string": "abcx", 3 | "bits": [false,true,false,true,true,false,true,true,true,true,false,true,false,false,true,true], 4 | "16int": -22137, 5 | "16uint": 4661, 6 | "16float": 13.34375, 7 | "32int": -4661, 8 | "32uint": 305419897, 9 | "32float": 223547.34375, 10 | "64int": -3735928550, 11 | "64uint": 1311738468603649775, 12 | "64float": 133.45 13 | } 14 | -------------------------------------------------------------------------------- /tests/blackbox/data/modbus/test_values/rpc/input_registers_values_reading_big.json: -------------------------------------------------------------------------------- 1 | { 2 | "string": "abcd", 3 | "bits": [false,true,false,true,true,false,true,true,true,true,false,true,false,false,true,false], 4 | "4bits": [false,false,true,false], 5 | "16int": -30551, 6 | "16uint": 13330, 7 | "16float": 0.067017, 8 | "32int": -856817665, 9 | "32uint": 2018915346, 10 | "32float": 0.0, 11 | "64int": 1243365278113333247, 12 | "64uint": 17275436391653061650, 13 | "64float": -6.0659880008723545e+66 14 | } -------------------------------------------------------------------------------- /tests/blackbox/data/modbus/test_values/rpc/input_registers_values_reading_little.json: -------------------------------------------------------------------------------- 1 | { 2 | "string": "abcd", 3 | "bits": [false,true,false,true,true,false,true,true,true,true,false,true,false,false,true,false], 4 | "4bits": [false,false,true,false], 5 | "16int": -22136, 6 | "16uint": 4660, 7 | "16float": 12.34375, 8 | "32int": -4660, 9 | "32uint": 305419896, 10 | "32float": 223546.34375, 11 | "64int": -3735928559, 12 | "64uint": 1311768468603649775, 13 | "64float": 123.45 14 | } -------------------------------------------------------------------------------- /tests/blackbox/data/modbus/test_values/rpc/input_registers_values_writing_big.json: -------------------------------------------------------------------------------- 1 | { 2 | "string": "abcx", 3 | "bits": [false,true,false,true,true,false,true,true,true,true,false,true,false,false,true,true], 4 | "16int": -30541, 5 | "16uint": 13334, 6 | "16float": 0.067017, 7 | "32int": -856817645, 8 | "32uint": 2018915246, 9 | "32float": -0.020163, 10 | "64int": 1243365278113335247, 11 | "64uint": 17275436396653061650, 12 | "64float": -6065988000872254000000000000000000000000000000000000000000000000000 13 | } -------------------------------------------------------------------------------- /tests/blackbox/data/modbus/test_values/rpc/input_registers_values_writing_little.json: -------------------------------------------------------------------------------- 1 | { 2 | "string": "abcx", 3 | "bits": [false,true,false,true,true,false,true,true,true,true,false,true,false,false,true,true], 4 | "4bits": [false, false, false, false], 5 | "16int": -22137, 6 | "16uint": 4661, 7 | "16float": 13.34375, 8 | "32int": -4661, 9 | "32uint": 305419897, 10 | "32float": 223547.34375, 11 | "64int": -3735928550, 12 | "64uint": 1311738468603649775, 13 | "64float": 133.45 14 | } 15 | -------------------------------------------------------------------------------- /tests/blackbox/data/modbus/test_values/uplink/discrete_and_coils_registers_values_big.json: -------------------------------------------------------------------------------- 1 | { 2 | "bits": "[false,true,false,true,true,false,true,true,true,true,false,true,false,false,true,false]", 3 | "bit": "true" 4 | } -------------------------------------------------------------------------------- /tests/blackbox/data/modbus/test_values/uplink/discrete_and_coils_registers_values_little.json: -------------------------------------------------------------------------------- 1 | { 2 | "bits": "[false,true,false,true,true,false,true,true,true,true,false,true,false,false,true,false]", 3 | "bit": "true" 4 | } -------------------------------------------------------------------------------- /tests/blackbox/data/modbus/test_values/uplink/holding_registers_values_big.json: -------------------------------------------------------------------------------- 1 | { 2 | "string": "abcd", 3 | "bits": "[false,true,false,true,true,false,true,true,true,true,false,true,false,false,true,false]", 4 | "16int": "-30551", 5 | "16uint": "13330", 6 | "16float": "0.067017", 7 | "32int": "-856817665", 8 | "32uint": "2018915346", 9 | "32float": "0.0", 10 | "64int": "1243365278113333247", 11 | "64uint": "17275436391653061650", 12 | "64float": "-6065988000872354500000000000000000000000000000000000000000000000000" 13 | } -------------------------------------------------------------------------------- /tests/blackbox/data/modbus/test_values/uplink/holding_registers_values_little.json: -------------------------------------------------------------------------------- 1 | { 2 | "string": "abcd", 3 | "bits": "[false,true,false,true,true,false,true,true,true,true,false,true,false,false,true,false]", 4 | "16int": "-22136", 5 | "16uint": "4660", 6 | "16float": "12.34375", 7 | "32int": "-4660", 8 | "32uint": "305419896", 9 | "32float": "223546.34375", 10 | "64int": "-3735928559", 11 | "64uint": "1311768468603649775", 12 | "64float": "123.45" 13 | } -------------------------------------------------------------------------------- /tests/blackbox/data/modbus/test_values/uplink/input_registers_values_big.json: -------------------------------------------------------------------------------- 1 | { 2 | "string": "abcd", 3 | "bits": "[false,true,false,true,true,false,true,true,true,true,false,true,false,false,true,false]", 4 | "16int": "-30551", 5 | "16uint": "13330", 6 | "16float": "0.067017", 7 | "32int": "-856817665", 8 | "32uint": "2018915346", 9 | "32float": "0.0", 10 | "64int": "1243365278113333247", 11 | "64uint": "17275436391653061650", 12 | "64float": "-6065988000872354500000000000000000000000000000000000000000000000000" 13 | } -------------------------------------------------------------------------------- /tests/blackbox/data/modbus/test_values/uplink/input_registers_values_little.json: -------------------------------------------------------------------------------- 1 | { 2 | "string": "abcd", 3 | "bits": "[false,true,false,true,true,false,true,true,true,true,false,true,false,false,true,false]", 4 | "16int": "-22136", 5 | "16uint": "4660", 6 | "16float": "12.34375", 7 | "32int": "-4660", 8 | "32uint": "305419896", 9 | "32float": "223546.34375", 10 | "64int": "-3735928559", 11 | "64uint": "1311768468603649775", 12 | "64float": "123.45" 13 | } -------------------------------------------------------------------------------- /tests/blackbox/data/opcua/configs/attrs_update_configs/attrs_update_node.json: -------------------------------------------------------------------------------- 1 | { 2 | "Opcua": { 3 | "name": "Opcua", 4 | "type": "opcua_asyncio", 5 | "logLevel": "DEBUG", 6 | "configuration": "opcua.json", 7 | "configurationJson": { 8 | "server": { 9 | "name": "OPC-UA Demo Server", 10 | "url": "opc.tcp://127.0.0.1:4840/freeopcua/server/", 11 | "timeoutInMillis": 5000, 12 | "scanPeriodInMillis": 1000, 13 | "disableSubscriptions": true, 14 | "subCheckPeriodInMillis": 100, 15 | "showMap": false, 16 | "security": "Basic128Rsa15", 17 | "identity": { 18 | "type": "anonymous" 19 | }, 20 | "mapping": [ 21 | { 22 | "deviceNodePattern": "Root\\.Objects\\.TempSensor", 23 | "deviceNamePattern": "Temp Sensor", 24 | "deviceTypePattern": "default", 25 | "attributes": [], 26 | "timeseries": [ 27 | { 28 | "key": "path", 29 | "path": "${Humidity}" 30 | } 31 | ], 32 | "rpc_methods": [], 33 | "attributes_updates": [ 34 | { 35 | "attributeOnThingsBoard": "path", 36 | "attributeOnDevice": "Humidity" 37 | } 38 | ] 39 | } 40 | ] 41 | } 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /tests/blackbox/data/opcua/configs/default_opcua_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "Opcua": { 3 | "name": "Opcua", 4 | "type": "opcua_asyncio", 5 | "logLevel": "DEBUG", 6 | "configuration": "opcua.json", 7 | "configurationJson": { 8 | "server": { 9 | "name": "OPC-UA Demo Server", 10 | "url": "opc.tcp://127.0.0.1:4840/freeopcua/server/", 11 | "timeoutInMillis": 5000, 12 | "scanPeriodInMillis": 5000, 13 | "disableSubscriptions": true, 14 | "subCheckPeriodInMillis": 100, 15 | "showMap": false, 16 | "security": "Basic128Rsa15", 17 | "identity": { 18 | "type": "anonymous" 19 | }, 20 | "mapping": [ 21 | { 22 | "deviceNodePattern": "Root\\.Objects\\.TempSensor", 23 | "deviceNamePattern": "Temp Sensor", 24 | "deviceTypePattern": "default", 25 | "attributes": [ 26 | { 27 | "key": "path", 28 | "path": "${Humidity}" 29 | } 30 | ], 31 | "timeseries": [], 32 | "rpc_methods": [ 33 | { 34 | "method": "multiply", 35 | "arguments": [ 36 | 2, 37 | 4 38 | ] 39 | } 40 | ], 41 | "attributes_updates": [ 42 | { 43 | "attributeOnThingsBoard": "path", 44 | "attributeOnDevice": ".Humidity" 45 | } 46 | ] 47 | } 48 | ] 49 | } 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /tests/blackbox/data/opcua/configs/rpc_configs/rpc_get_method.json: -------------------------------------------------------------------------------- 1 | { 2 | "Opcua": { 3 | "name": "Opcua", 4 | "type": "opcua_asyncio", 5 | "logLevel": "DEBUG", 6 | "configuration": "opcua.json", 7 | "configurationJson": { 8 | "server": { 9 | "name": "OPC-UA Demo Server", 10 | "url": "opc.tcp://127.0.0.1:4840/freeopcua/server/", 11 | "timeoutInMillis": 5000, 12 | "scanPeriodInMillis": 1000, 13 | "disableSubscriptions": true, 14 | "subCheckPeriodInMillis": 100, 15 | "showMap": false, 16 | "security": "Basic128Rsa15", 17 | "identity": { 18 | "type": "anonymous" 19 | }, 20 | "mapping": [ 21 | { 22 | "deviceNodePattern": "Root\\.Objects\\.TempSensor", 23 | "deviceNamePattern": "Temp Sensor", 24 | "deviceTypePattern": "default", 25 | "attributes": [], 26 | "timeseries": [ 27 | { 28 | "key": "path", 29 | "path": "${Humidity}" 30 | } 31 | ], 32 | "rpc_methods": [], 33 | "attributes_updates": [] 34 | } 35 | ] 36 | } 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /tests/blackbox/data/opcua/configs/rpc_configs/rpc_server_method.json: -------------------------------------------------------------------------------- 1 | { 2 | "Opcua": { 3 | "name": "Opcua", 4 | "type": "opcua_asyncio", 5 | "logLevel": "DEBUG", 6 | "configuration": "opcua.json", 7 | "configurationJson": { 8 | "server": { 9 | "name": "OPC-UA Demo Server", 10 | "url": "opc.tcp://127.0.0.1:4840/freeopcua/server/", 11 | "timeoutInMillis": 5000, 12 | "scanPeriodInMillis": 1000, 13 | "disableSubscriptions": true, 14 | "subCheckPeriodInMillis": 100, 15 | "showMap": false, 16 | "security": "Basic128Rsa15", 17 | "identity": { 18 | "type": "anonymous" 19 | }, 20 | "mapping": [ 21 | { 22 | "deviceNodePattern": "Root\\.Objects\\.TempSensor", 23 | "deviceNamePattern": "Temp Sensor", 24 | "deviceTypePattern": "default", 25 | "attributes": [], 26 | "timeseries": [ 27 | { 28 | "key": "path", 29 | "path": "${Humidity}" 30 | } 31 | ], 32 | "rpc_methods": [ 33 | { 34 | "method": "multiply", 35 | "arguments": [2, 4] 36 | } 37 | ], 38 | "attributes_updates": [] 39 | } 40 | ] 41 | } 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /tests/blackbox/data/opcua/configs/rpc_configs/rpc_set_method.json: -------------------------------------------------------------------------------- 1 | { 2 | "Opcua": { 3 | "name": "Opcua", 4 | "type": "opcua_asyncio", 5 | "logLevel": "DEBUG", 6 | "configuration": "opcua.json", 7 | "configurationJson": { 8 | "server": { 9 | "name": "OPC-UA Demo Server", 10 | "url": "opc.tcp://127.0.0.1:4840/freeopcua/server/", 11 | "timeoutInMillis": 5000, 12 | "scanPeriodInMillis": 1000, 13 | "disableSubscriptions": true, 14 | "subCheckPeriodInMillis": 100, 15 | "showMap": false, 16 | "security": "Basic128Rsa15", 17 | "identity": { 18 | "type": "anonymous" 19 | }, 20 | "mapping": [ 21 | { 22 | "deviceNodePattern": "Root\\.Objects\\.TempSensor", 23 | "deviceNamePattern": "Temp Sensor", 24 | "deviceTypePattern": "default", 25 | "attributes": [], 26 | "timeseries": [ 27 | { 28 | "key": "i", 29 | "path": "${ns=3;i=2}" 30 | } 31 | ], 32 | "rpc_methods": [], 33 | "attributes_updates": [] 34 | } 35 | ] 36 | } 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /tests/blackbox/data/opcua/configs/uplink_configs/different_node_finding_methods_config_b.json: -------------------------------------------------------------------------------- 1 | { 2 | "Opcua": { 3 | "name": "Opcua", 4 | "type": "opcua_asyncio", 5 | "logLevel": "DEBUG", 6 | "configuration": "opcua.json", 7 | "configurationJson": { 8 | "server": { 9 | "name": "OPC-UA Demo Server", 10 | "url": "opc.tcp://127.0.0.1:4840/freeopcua/server/", 11 | "timeoutInMillis": 5000, 12 | "scanPeriodInMillis": 1000, 13 | "disableSubscriptions": true, 14 | "subCheckPeriodInMillis": 100, 15 | "showMap": false, 16 | "security": "Basic128Rsa15", 17 | "identity": { 18 | "type": "anonymous" 19 | }, 20 | "mapping": [ 21 | { 22 | "deviceNodePattern": "${ns=3;b=TestDevice}", 23 | "deviceNamePattern": "Temp Sensor", 24 | "deviceTypePattern": "default", 25 | "attributes": [], 26 | "timeseries": [ 27 | { 28 | "key": "path", 29 | "path": "${Humidity}" 30 | }, 31 | { 32 | "key": "i", 33 | "path": "${ns=3;i=2}" 34 | }, 35 | { 36 | "key": "s", 37 | "path": "${ns=3;s=Humidity_S}" 38 | }, 39 | { 40 | "key": "g", 41 | "path": "${ns=3;g=018dd02c-fd22-754a-b6d3-5fcae91cd38d}" 42 | }, 43 | { 44 | "key": "b", 45 | "path": "${ns=3;b=Status_S}" 46 | } 47 | ], 48 | "rpc_methods": [], 49 | "attributes_updates": [] 50 | } 51 | ] 52 | } 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /tests/blackbox/data/opcua/configs/uplink_configs/different_node_finding_methods_config_g.json: -------------------------------------------------------------------------------- 1 | { 2 | "Opcua": { 3 | "name": "Opcua", 4 | "type": "opcua_asyncio", 5 | "logLevel": "DEBUG", 6 | "configuration": "opcua.json", 7 | "configurationJson": { 8 | "server": { 9 | "name": "OPC-UA Demo Server", 10 | "url": "opc.tcp://127.0.0.1:4840/freeopcua/server/", 11 | "timeoutInMillis": 5000, 12 | "scanPeriodInMillis": 1000, 13 | "disableSubscriptions": true, 14 | "subCheckPeriodInMillis": 100, 15 | "showMap": false, 16 | "security": "Basic128Rsa15", 17 | "identity": { 18 | "type": "anonymous" 19 | }, 20 | "mapping": [ 21 | { 22 | "deviceNodePattern": "${ns=5;g=018dd02c-fd22-754a-b6d3-5fcae91cd39d}", 23 | "deviceNamePattern": "Temp Sensor", 24 | "deviceTypePattern": "default", 25 | "attributes": [], 26 | "timeseries": [ 27 | { 28 | "key": "path", 29 | "path": "${Humidity}" 30 | }, 31 | { 32 | "key": "i", 33 | "path": "${ns=5;i=2}" 34 | }, 35 | { 36 | "key": "s", 37 | "path": "${ns=5;s=Humidity_S}" 38 | }, 39 | { 40 | "key": "g", 41 | "path": "${ns=5;g=018dd02c-fd22-754a-b6d3-5fcae91cd38d}" 42 | }, 43 | { 44 | "key": "b", 45 | "path": "${ns=5;b=Status_S}" 46 | } 47 | ], 48 | "rpc_methods": [], 49 | "attributes_updates": [] 50 | } 51 | ] 52 | } 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /tests/blackbox/data/opcua/configs/uplink_configs/different_node_finding_methods_config_i.json: -------------------------------------------------------------------------------- 1 | { 2 | "Opcua": { 3 | "name": "Opcua", 4 | "type": "opcua_asyncio", 5 | "logLevel": "DEBUG", 6 | "configuration": "opcua.json", 7 | "configurationJson": { 8 | "server": { 9 | "name": "OPC-UA Demo Server", 10 | "url": "opc.tcp://127.0.0.1:4840/freeopcua/server/", 11 | "timeoutInMillis": 5000, 12 | "scanPeriodInMillis": 1000, 13 | "disableSubscriptions": true, 14 | "subCheckPeriodInMillis": 100, 15 | "showMap": false, 16 | "security": "Basic128Rsa15", 17 | "identity": { 18 | "type": "anonymous" 19 | }, 20 | "mapping": [ 21 | { 22 | "deviceNodePattern": "${ns=3;i=1}", 23 | "deviceNamePattern": "Temp Sensor", 24 | "deviceTypePattern": "default", 25 | "attributes": [], 26 | "timeseries": [ 27 | { 28 | "key": "path", 29 | "path": "${Humidity}" 30 | }, 31 | { 32 | "key": "i", 33 | "path": "${ns=3;i=2}" 34 | }, 35 | { 36 | "key": "s", 37 | "path": "${ns=3;s=Humidity_S}" 38 | }, 39 | { 40 | "key": "g", 41 | "path": "${ns=3;g=018dd02c-fd22-754a-b6d3-5fcae91cd38d}" 42 | }, 43 | { 44 | "key": "b", 45 | "path": "${ns=3;b=Status_S}" 46 | } 47 | ], 48 | "rpc_methods": [], 49 | "attributes_updates": [] 50 | } 51 | ] 52 | } 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /tests/blackbox/data/opcua/configs/uplink_configs/different_node_finding_methods_config_path.json: -------------------------------------------------------------------------------- 1 | { 2 | "Opcua": { 3 | "name": "Opcua", 4 | "type": "opcua_asyncio", 5 | "logLevel": "DEBUG", 6 | "configuration": "opcua.json", 7 | "configurationJson": { 8 | "server": { 9 | "name": "OPC-UA Demo Server", 10 | "url": "opc.tcp://127.0.0.1:4840/freeopcua/server/", 11 | "timeoutInMillis": 5000, 12 | "scanPeriodInMillis": 1000, 13 | "disableSubscriptions": true, 14 | "subCheckPeriodInMillis": 100, 15 | "showMap": false, 16 | "security": "Basic128Rsa15", 17 | "identity": { 18 | "type": "anonymous" 19 | }, 20 | "mapping": [ 21 | { 22 | "deviceNodePattern": "Root\\.Objects\\.TempSensor", 23 | "deviceNamePattern": "Temp Sensor", 24 | "deviceTypePattern": "default", 25 | "attributes": [], 26 | "timeseries": [ 27 | { 28 | "key": "path", 29 | "path": "${Humidity}" 30 | }, 31 | { 32 | "key": "i", 33 | "path": "${ns=3;i=2}" 34 | }, 35 | { 36 | "key": "s", 37 | "path": "${ns=3;s=Humidity_S}" 38 | }, 39 | { 40 | "key": "g", 41 | "path": "${ns=3;g=018dd02c-fd22-754a-b6d3-5fcae91cd38d}" 42 | }, 43 | { 44 | "key": "b", 45 | "path": "${ns=3;b=Status_S}" 46 | } 47 | ], 48 | "rpc_methods": [], 49 | "attributes_updates": [] 50 | } 51 | ] 52 | } 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /tests/blackbox/data/opcua/configs/uplink_configs/different_node_finding_methods_config_s.json: -------------------------------------------------------------------------------- 1 | { 2 | "Opcua": { 3 | "name": "Opcua", 4 | "type": "opcua_asyncio", 5 | "logLevel": "DEBUG", 6 | "configuration": "opcua.json", 7 | "configurationJson": { 8 | "server": { 9 | "name": "OPC-UA Demo Server", 10 | "url": "opc.tcp://127.0.0.1:4840/freeopcua/server/", 11 | "timeoutInMillis": 5000, 12 | "scanPeriodInMillis": 1000, 13 | "disableSubscriptions": true, 14 | "subCheckPeriodInMillis": 100, 15 | "showMap": false, 16 | "security": "Basic128Rsa15", 17 | "identity": { 18 | "type": "anonymous" 19 | }, 20 | "mapping": [ 21 | { 22 | "deviceNodePattern": "${ns=4;s=TestDevice}", 23 | "deviceNamePattern": "Temp Sensor", 24 | "deviceTypePattern": "default", 25 | "attributes": [], 26 | "timeseries": [ 27 | { 28 | "key": "path", 29 | "path": "${Humidity}" 30 | }, 31 | { 32 | "key": "i", 33 | "path": "${ns=4;i=2}" 34 | }, 35 | { 36 | "key": "s", 37 | "path": "${ns=4;s=Humidity_S}" 38 | }, 39 | { 40 | "key": "g", 41 | "path": "${ns=4;g=018dd02c-fd22-754a-b6d3-5fcae91cd38d}" 42 | }, 43 | { 44 | "key": "b", 45 | "path": "${ns=4;b=Status_S}" 46 | } 47 | ], 48 | "rpc_methods": [], 49 | "attributes_updates": [] 50 | } 51 | ] 52 | } 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /tests/blackbox/data/opcua/test_values/attrs_update/attrs_update_connection_lost_node.json: -------------------------------------------------------------------------------- 1 | { 2 | "path": "63.2" 3 | } 4 | -------------------------------------------------------------------------------- /tests/blackbox/data/opcua/test_values/attrs_update/attrs_update_node_values.json: -------------------------------------------------------------------------------- 1 | { 2 | "path": 61.2 3 | } 4 | -------------------------------------------------------------------------------- /tests/blackbox/data/opcua/test_values/attrs_update/attrs_update_restart_node_values.json: -------------------------------------------------------------------------------- 1 | { 2 | "path": 61.2 3 | } 4 | -------------------------------------------------------------------------------- /tests/blackbox/data/opcua/test_values/default_node_values.json: -------------------------------------------------------------------------------- 1 | { 2 | "path": "60.5" 3 | } 4 | -------------------------------------------------------------------------------- /tests/blackbox/data/opcua/test_values/rpc/rpc_get_method_values.json: -------------------------------------------------------------------------------- 1 | { 2 | "s": "SomeText" 3 | } -------------------------------------------------------------------------------- /tests/blackbox/data/opcua/test_values/rpc/rpc_server_method_values.json: -------------------------------------------------------------------------------- 1 | { 2 | "multiply": 8 3 | } -------------------------------------------------------------------------------- /tests/blackbox/data/opcua/test_values/rpc/rpc_set_method_values.json: -------------------------------------------------------------------------------- 1 | { 2 | "i": "12" 3 | } -------------------------------------------------------------------------------- /tests/blackbox/data/opcua/test_values/uplink/different_node_finding_methods_values.json: -------------------------------------------------------------------------------- 1 | { 2 | "path": "60.5", 3 | "i": "1013.25", 4 | "s": "243.5", 5 | "g": "true", 6 | "b": 12.2 7 | } 8 | -------------------------------------------------------------------------------- /tests/blackbox/service/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /tests/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.5' 2 | services: 3 | tb: 4 | container_name: tests_tb_1 5 | image: "thingsboard/tb-postgres" 6 | environment: 7 | TB_QUEUE_TYPE: in-memory 8 | volumes: 9 | - tb-data:/data 10 | - tb-logs:/var/log/thingsboard 11 | network_mode: host 12 | gw: 13 | container_name: tests_gw_1 14 | image: "tb-gateway" 15 | environment: 16 | - TB_GW_HOST=127.0.0.1 17 | - TB_GW_PORT=1883 18 | - TB_GW_ACCESS_TOKEN=YOUR_ACCESS_TOKEN 19 | - TB_GW_RATE_LIMITS=0:0 20 | volumes: 21 | - tb-gw-config:/thingsboard_gateway/config 22 | - tb-gw-logs:/thingsboard_gateway/logs 23 | - tb-gw-extensions:/thingsboard_gateway/extensions 24 | network_mode: host 25 | mqtt-broker: 26 | container_name: tests_mqtt_broker_1 27 | image: "thingsboard/tb-gw-mqtt-broker:latest" 28 | network_mode: host 29 | modbus-server: 30 | container_name: tests_modbus_server_1 31 | image: "thingsboard/tb-gw-modbus-server:latest" 32 | network_mode: host 33 | opcua-server: 34 | container_name: tests_opcua_server_1 35 | image: "thingsboard/tb-gw-opcua-server:latest" 36 | network_mode: host 37 | volumes: 38 | tb-data: 39 | name: tb-data 40 | tb-logs: 41 | name: tb-logs 42 | tb-gw-config: 43 | name: tb-gw-config 44 | tb-gw-logs: 45 | name: tb-gw-logs 46 | tb-gw-extensions: 47 | name: tb-gw-extensions 48 | -------------------------------------------------------------------------------- /tests/integration/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/tests/integration/__init__.py -------------------------------------------------------------------------------- /tests/integration/connectors/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/tests/integration/connectors/__init__.py -------------------------------------------------------------------------------- /tests/integration/connectors/can/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/tests/integration/connectors/can/__init__.py -------------------------------------------------------------------------------- /tests/integration/connectors/modbus/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/tests/integration/connectors/modbus/__init__.py -------------------------------------------------------------------------------- /tests/integration/connectors/odbc/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/tests/integration/connectors/odbc/__init__.py -------------------------------------------------------------------------------- /tests/integration/connectors/opcua/__init__.py: -------------------------------------------------------------------------------- 1 | # TODO Configure environment for these tests -------------------------------------------------------------------------------- /tests/integration/data/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/tests/integration/data/__init__.py -------------------------------------------------------------------------------- /tests/integration/data/can/attribute_updates.json: -------------------------------------------------------------------------------- 1 | { 2 | "interface": "virtual", 3 | "channel": "virtual_channel", 4 | "backend": { 5 | "fd": true 6 | }, 7 | "devices": [ 8 | { 9 | "name": "Car", 10 | "strictEval": false, 11 | "attributeUpdates": [ 12 | { 13 | "attributeOnThingsBoard": "boolAttr", 14 | "nodeId": 1 15 | }, 16 | { 17 | "attribute": "intAttr", 18 | "nodeId": 2, 19 | "isExtendedId": true, 20 | "dataLength": 4, 21 | "dataByteorder": "little" 22 | }, 23 | { 24 | "attributeOnThingsBoard": "floatAttr", 25 | "nodeId": 3 26 | }, 27 | { 28 | "attribute": "stringAttr", 29 | "nodeId": 4, 30 | "isFd": true, 31 | "dataExpression": "'Test' + value" 32 | }, 33 | { 34 | "attributeOnThingsBoard": "wrongConfigAttr", 35 | "nodeId": 123456 36 | } 37 | ] 38 | } 39 | ] 40 | } -------------------------------------------------------------------------------- /tests/integration/data/can/multiple_polling.json: -------------------------------------------------------------------------------- 1 | { 2 | "interface": "virtual", 3 | "channel": "virtual_channel", 4 | "devices": [ 5 | { 6 | "name": "TestDevice", 7 | "timeseries": [ 8 | { 9 | "key": "testVar1", 10 | "nodeId": 1, 11 | "value": "4:1:int", 12 | "polling": { 13 | "type": "once", 14 | "dataInHex": "01" 15 | } 16 | }, 17 | { 18 | "key": "testVar2", 19 | "nodeId": 2, 20 | "value": "4:1:int", 21 | "polling": { 22 | "dataInHex": "02", 23 | "period": 2.5 24 | } 25 | }, 26 | { 27 | "key": "testVar3", 28 | "nodeId": 3, 29 | "value": "4:1:int", 30 | "polling": { 31 | "type": "always", 32 | "dataInHex": "03", 33 | "period": 3 34 | } 35 | } 36 | ] 37 | } 38 | ] 39 | } -------------------------------------------------------------------------------- /tests/integration/data/can/polling_always.json: -------------------------------------------------------------------------------- 1 | { 2 | "interface": "virtual", 3 | "channel": "virtual_channel", 4 | "devices": [ 5 | { 6 | "name": "TestDevice", 7 | "attributes": [ 8 | { 9 | "key": "testVar", 10 | "nodeId": 41, 11 | "value": "4:1:int", 12 | "polling": { 13 | "dataInHex": "CC", 14 | "period": 2 15 | } 16 | } 17 | ] 18 | } 19 | ] 20 | } -------------------------------------------------------------------------------- /tests/integration/data/can/polling_once.json: -------------------------------------------------------------------------------- 1 | { 2 | "interface": "virtual", 3 | "channel": "virtual_channel", 4 | "devices": [ 5 | { 6 | "name": "TestDevice", 7 | "attributes": [ 8 | { 9 | "key": "testVar", 10 | "nodeId": 12345, 11 | "isExtendedId": true, 12 | "value": "4:1:int", 13 | "polling": { 14 | "type": "once", 15 | "dataInHex": "AB CD AB CD" 16 | } 17 | } 18 | ] 19 | } 20 | ] 21 | } -------------------------------------------------------------------------------- /tests/integration/data/can/rpc.json: -------------------------------------------------------------------------------- 1 | { 2 | "interface": "virtual", 3 | "channel": "virtual_channel", 4 | "backend": { 5 | "fd": true 6 | }, 7 | "devices": [ 8 | { 9 | "name": "Car1", 10 | "enableUnknownRpc": false, 11 | "serverSideRpc": [ 12 | { 13 | "method": "sendSameData", 14 | "nodeId": 4, 15 | "isExtendedId": true, 16 | "isFd": true, 17 | "bitrateSwitch": true, 18 | "dataInHex": "aa bb cc dd ee ff aa bb aa bb cc dd ee ff" 19 | }, 20 | { 21 | "method": "setSpeed", 22 | "nodeId": 16, 23 | "dataExpression": "userSpeed if maxAllowedSpeed > userSpeed else maxAllowedSpeed", 24 | "dataByteorder": "little", 25 | "dataLength": 2 26 | } 27 | ] 28 | }, 29 | { 30 | "name": "Car2", 31 | "overrideRpcConfig": true, 32 | "serverSideRpc": [ 33 | { 34 | "method": "sendSameData", 35 | "nodeId": 4, 36 | "isExtendedId": true, 37 | "isFd": true, 38 | "bitrateSwitch": true, 39 | "dataInHex": "aa bb cc dd ee ff aa bb aa bb cc dd ee ff" 40 | } 41 | ] 42 | }, 43 | { 44 | "name": "Car3", 45 | "enableUnknownRpc": true, 46 | "serverSideRpc": [ 47 | { 48 | "method": "someMethod", 49 | "nodeId": 4, 50 | "dataInHex": "010203" 51 | } 52 | ] 53 | }, 54 | { 55 | "name": "Car4", 56 | "serverSideRpc": [ 57 | { 58 | "method": "wrongDataMethod", 59 | "nodeId": 4, 60 | "dataInHex": "123", 61 | "response": true 62 | } 63 | ] 64 | } 65 | ] 66 | } -------------------------------------------------------------------------------- /tests/integration/data/gateway/gateway.json: -------------------------------------------------------------------------------- 1 | { 2 | "thingsboard": { 3 | "host": "127.0.0.1", 4 | "port": 1883, 5 | "remoteShell": false, 6 | "remoteConfiguration": false, 7 | "statistics": { 8 | "enable": false, 9 | "statsSendPeriodInSeconds": 3600, 10 | "configuration": "statistics.json" 11 | }, 12 | "minPackSendDelayMS": 0, 13 | "checkConnectorsConfigurationInSeconds": 60, 14 | "handleDeviceRenaming": true, 15 | "checkingDeviceActivity": { 16 | "checkDeviceInactivity": false, 17 | "inactivityTimeoutSeconds": 120, 18 | "inactivityCheckPeriodSeconds": 10 19 | }, 20 | "security": { 21 | "accessToken": "YOUR_ACCESS_TOKEN" 22 | }, 23 | "qos": 1 24 | }, 25 | "storage": { 26 | "type": "memory", 27 | "read_records_count": 100, 28 | "max_records_count": 100000 29 | }, 30 | "connectors": [ 31 | { 32 | "name": "MQTT Broker Connector", 33 | "type": "mqtt", 34 | "configuration": "mqtt.json" 35 | } 36 | ] 37 | } -------------------------------------------------------------------------------- /tests/integration/data/modbus/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/tests/integration/data/modbus/__init__.py -------------------------------------------------------------------------------- /tests/integration/data/odbc/odbc_attributes.json: -------------------------------------------------------------------------------- 1 | { 2 | "connection": { 3 | "str": "DO_NOT_EDIT_THIS_PARAMETER.IT WILL BE OVERRIDDEN BY TESTS." 4 | }, 5 | "polling": { 6 | "query": "SELECT key, bool_v, str_v, dbl_v, long_v, device_id, ts FROM attributes WHERE ts > ? ORDER BY ts ASC LIMIT 10", 7 | "period": 1, 8 | "iterator": { 9 | "column": "ts", 10 | "query": "SELECT MIN(ts) - 1 FROM attributes" 11 | } 12 | }, 13 | "mapping": { 14 | "device": { 15 | "name": "'ODBC ' + str(device_id)" 16 | }, 17 | "attributes": [ 18 | { 19 | "nameExpression": "key", 20 | "value": "[i for i in [str_v, long_v, dbl_v,bool_v] if i is not None][0]" 21 | } 22 | ] 23 | } 24 | } -------------------------------------------------------------------------------- /tests/integration/data/odbc/odbc_iterator.json: -------------------------------------------------------------------------------- 1 | { 2 | "connection": { 3 | "str": "DO_NOT_EDIT_THIS_PARAMETER.IT WILL BE OVERRIDDEN BY TESTS.", 4 | "reconnectPeriod": 3 5 | }, 6 | "polling": { 7 | "query": "SELECT bool_v, str_v, dbl_v, long_v, device_id, ts FROM timeseries WHERE ts > ? ORDER BY ts ASC LIMIT 2", 8 | "period": 5, 9 | "iterator": { 10 | "column": "ts", 11 | "query": "SELECT MIN(ts) - 1 FROM timeseries", 12 | "persistent": true 13 | } 14 | }, 15 | "mapping": { 16 | "sendDataOnlyOnChange": true, 17 | "device": { 18 | "name": "'ODBC ' + str(device_id)" 19 | }, 20 | "timeseries": [ 21 | { 22 | "name": "value", 23 | "value": "[i for i in [str_v, long_v, dbl_v,bool_v] if i is not None][0]" 24 | } 25 | ] 26 | } 27 | } -------------------------------------------------------------------------------- /tests/integration/data/odbc/odbc_rpc.json: -------------------------------------------------------------------------------- 1 | { 2 | "connection": { 3 | "str": "DO_NOT_EDIT_THIS_PARAMETER.IT WILL BE OVERRIDDEN BY TESTS.", 4 | "reconnectPeriod": 5 5 | }, 6 | "polling": { 7 | "query": "SELECT key FROM attributes WHERE ts > ? ORDER BY ts ASC LIMIT 10", 8 | "iterator": { 9 | "column": "ts", 10 | "query": "SELECT MAX(ts) FROM attributes" 11 | } 12 | }, 13 | "mapping": { 14 | "device": { 15 | "name": "'ODBC ' + entity_id" 16 | }, 17 | "timeseries": [ 18 | { 19 | "name": "value", 20 | "value": "[i for i in [str_v, long_v, dbl_v,bool_v] if i is not None][0]" 21 | } 22 | ] 23 | }, 24 | "serverSideRpc": { 25 | "methods": [ 26 | "decrement_value", 27 | { 28 | "name": "increment_value", 29 | "query": "CALL increment_value()" 30 | }, 31 | { 32 | "name": "reset_values", 33 | "params": [ "test", 25 ] 34 | }, 35 | { 36 | "name": "update_values", 37 | "params": [ "hello world", 150 ], 38 | "query": "CALL update_values(?,?)" 39 | }, 40 | "get_values" 41 | ] 42 | } 43 | } -------------------------------------------------------------------------------- /tests/integration/data/odbc/odbc_timeseries.json: -------------------------------------------------------------------------------- 1 | { 2 | "connection": { 3 | "str": "DO_NOT_EDIT_THIS_PARAMETER.IT WILL BE OVERRIDDEN BY TESTS.", 4 | "attributes": { 5 | "autocommit": false, 6 | "timeout": 0 7 | } 8 | }, 9 | "pyodbc": { 10 | "pooling": false, 11 | "native_uuid": true 12 | }, 13 | "polling": { 14 | "query": "SELECT bool_v, str_v, dbl_v, long_v, device_id, ts FROM timeseries WHERE ts > ? ORDER BY ts ASC LIMIT 10", 15 | "period": 1, 16 | "iterator": { 17 | "column": "ts", 18 | "query": "SELECT MIN(ts) - 1 FROM timeseries" 19 | } 20 | }, 21 | "mapping": { 22 | "device": { 23 | "type": "postgres", 24 | "name": "'ODBC ' + str(device_id)" 25 | }, 26 | "timeseries": [ 27 | { 28 | "name": "value", 29 | "value": "[i for i in [str_v, long_v, dbl_v,bool_v] if i is not None][0]" 30 | } 31 | ] 32 | } 33 | } -------------------------------------------------------------------------------- /tests/integration/data/odbc/sqlite3.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/tests/integration/data/odbc/sqlite3.db -------------------------------------------------------------------------------- /tests/integration/data/opcua/connection_test.json: -------------------------------------------------------------------------------- 1 | { 2 | "server": { 3 | "name": "OPC-UA Default Server", 4 | "url": "localhost:4841/freeopcua/server/", 5 | "timeoutInMillis": 5000, 6 | "scanPeriodInMillis": 5000, 7 | "disableSubscriptions":false, 8 | "subCheckPeriodInMillis": 100, 9 | "showMap": false, 10 | "security": "Basic128Rsa15", 11 | "identity": { 12 | "type": "anonymous" 13 | }, 14 | "mapping": [ 15 | { 16 | "deviceNodePattern": "Root\\.Objects\\.Device1", 17 | "deviceNamePattern": "Device ${Root\\.Objects\\.Device1\\.serialNumber}", 18 | "attributes": [ 19 | { 20 | "key": "temperature °C", 21 | "path": "${ns=2;i=5}" 22 | } 23 | ], 24 | "timeseries": [ 25 | { 26 | "key": "humidity", 27 | "path": "${Root\\.Objects\\.Device1\\.TemperatureAndHumiditySensor\\.Humidity}" 28 | }, 29 | { 30 | "key": "batteryLevel", 31 | "path": "${Battery\\.batteryLevel}" 32 | } 33 | ], 34 | "rpc_methods": [ 35 | { 36 | "method": "multiply", 37 | "arguments": [2, 4] 38 | } 39 | ], 40 | "attributes_updates": [ 41 | { 42 | "attributeOnThingsBoard": "deviceName", 43 | "attributeOnDevice": "Root\\.Objects\\.Device1\\.serialNumber" 44 | } 45 | ] 46 | } 47 | ] 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /tests/integration/data/opcua/opcua_test_connection.json: -------------------------------------------------------------------------------- 1 | { 2 | "server": { 3 | "name": "OPC-UA Default Server", 4 | "url": "localhost:4841", 5 | "timeoutInMillis": 5000, 6 | "scanPeriodInMillis": 5000, 7 | "disableSubscriptions":false, 8 | "subCheckPeriodInMillis": 100, 9 | "showMap": false, 10 | "security": "Basic256Sha256", 11 | "identity": { 12 | "type": "anonymous" 13 | }, 14 | "mapping": [ 15 | { 16 | "deviceNodePattern": "Root\\.Objects\\.Machine1", 17 | "deviceNamePattern": "Machine 1", 18 | "attributes": [ 19 | { 20 | "key": "SerialNumber", 21 | "path": "${SerialNumber}" 22 | } 23 | ], 24 | "timeseries": [ 25 | { 26 | "key": "IntState", 27 | "path": "${IntState}" 28 | } 29 | ], 30 | "rpc_methods": [], 31 | "attributes_updates": [ ] 32 | }, 33 | { 34 | "deviceNodePattern": "Root\\.Objects\\.Machine2", 35 | "deviceNamePattern": "Machine 2", 36 | "attributes": [ 37 | { 38 | "key": "SerialNumber", 39 | "path": "${ns=2;i=5}" 40 | } 41 | ], 42 | "timeseries": [ 43 | { 44 | "key": "IntState", 45 | "path": "${ns=2;i=6}" 46 | } 47 | ], 48 | "rpc_methods": [], 49 | "attributes_updates": [ ] 50 | }, 51 | { 52 | "deviceNodePattern": "Root\\.Objects\\.Collection", 53 | "deviceNamePattern": "Machine 3", 54 | "attributes": [ 55 | { 56 | "key": "SerialNumber", 57 | "path": "${Machine3\\.SerialNumber}" 58 | } 59 | ], 60 | "timeseries": [ 61 | { 62 | "key": "IntState", 63 | "path": "${Machine3\\.Int\\State}" 64 | } 65 | ], 66 | "rpc_methods": [], 67 | "attributes_updates": [ ] 68 | } 69 | ] 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /tests/integration/integration_base_test.py: -------------------------------------------------------------------------------- 1 | from tests.base_test import BaseTest 2 | 3 | 4 | class IntegrationBaseTest(BaseTest): 5 | 6 | def setUp(self): 7 | super().setUp() 8 | 9 | def tearDown(self): 10 | super().tearDown() -------------------------------------------------------------------------------- /tests/integration/service/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/tests/integration/service/__init__.py -------------------------------------------------------------------------------- /tests/requirements.txt: -------------------------------------------------------------------------------- 1 | wheel 2 | twine 3 | packaging==23.1 4 | jsonpath-rw 5 | regex 6 | pip 7 | PyYAML 8 | simplejson 9 | urllib3<=1.26.15 10 | requests>=2.31.0 11 | questionary 12 | pyfiglet 13 | termcolor 14 | grpcio==1.58.0 15 | mmh3 16 | protobuf<=3.20.0 17 | cachetools 18 | tb-paho-mqtt-client>=2.1.2 19 | tb-mqtt-client==1.13.5 20 | service-identity 21 | pyjwt==2.6.0 22 | tb-rest-client 23 | pyopenssl 24 | opcua 25 | asyncua 26 | twisted 27 | pymodbus==3.0.0 28 | pyserial 29 | pyserial-asyncio 30 | python-can 31 | python-dateutil 32 | bacpypes3>=0.0.102 33 | aiohttp 34 | puresnmp>=2.0.0 35 | slixmpp 36 | psutil 37 | orjson 38 | pybase64 39 | -------------------------------------------------------------------------------- /tests/start_tests.sh: -------------------------------------------------------------------------------- 1 | export PYTHONPATH="${PYTHONPATH}:$(pwd)" 2 | python3 -m venv venv 3 | source venv/bin/activate 4 | pip install -r tests/requirements.txt --no-cache-dir 5 | pip install pyjwt==2.6.0 --no-cache-dir 6 | pip install tb-rest-client --no-cache-dir 7 | cp docker/Dockerfile . 8 | docker build -t tb-gateway --load . 9 | docker compose --file tests/docker-compose.yml up -d 10 | sleep 60 11 | python3 -m unittest discover -s . -p 'test_*.py' -v 12 | docker compose down 13 | deactivate 14 | rm -rf venv -------------------------------------------------------------------------------- /tests/test_utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/tests/test_utils/__init__.py -------------------------------------------------------------------------------- /tests/tests.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/tests/tests.py -------------------------------------------------------------------------------- /tests/unit/BaseUnitTest.py: -------------------------------------------------------------------------------- 1 | from tests.base_test import BaseTest 2 | 3 | 4 | class BaseUnitTest(BaseTest): 5 | 6 | @classmethod 7 | def setUpClass(cls): 8 | pass 9 | 10 | def setUp(self): 11 | super().setUp() 12 | 13 | def tearDown(self): 14 | super().tearDown() -------------------------------------------------------------------------------- /tests/unit/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/tests/unit/__init__.py -------------------------------------------------------------------------------- /tests/unit/connectors/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/tests/unit/connectors/__init__.py -------------------------------------------------------------------------------- /tests/unit/connectors/bacnet/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /tests/unit/connectors/ftp/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /tests/unit/connectors/ftp/data/anonym_type/new_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "parameters": { 3 | "host": "0.0.0.0", 4 | "port": 21, 5 | "TLSSupport": false, 6 | "security": { 7 | "type": "anonymous" 8 | } 9 | }, 10 | "paths": [ 11 | { 12 | "devicePatternName": "asd", 13 | "devicePatternType": "Device", 14 | "delimiter": ",", 15 | "path": "fol/*_hello*.txt", 16 | "readMode": "FULL", 17 | "maxFileSize": 5, 18 | "pollPeriod": 500, 19 | "txtFileDataView": "SLICED", 20 | "withSortingFiles": true, 21 | "attributes": [ 22 | { 23 | "type": "string", 24 | "key": "temp", 25 | "value": "[1:]" 26 | }, 27 | { 28 | "type": "string", 29 | "key": "tmp", 30 | "value": "[0:1]" 31 | } 32 | ], 33 | "timeseries": [ 34 | { 35 | "type": "integer", 36 | "key": "[0:1]", 37 | "value": "[0:1]" 38 | }, 39 | { 40 | "type": "integer", 41 | "key": "temp", 42 | "value": "[1:]" 43 | } 44 | ] 45 | } 46 | ], 47 | "requestsMapping": { 48 | "attributeUpdates": [ 49 | { 50 | "path": "fol/hello.json", 51 | "deviceNameFilter": ".*", 52 | "writingMode": "WRITE", 53 | "valueExpression": "{'${attributeKey}':'${attributeValue}'}" 54 | } 55 | ], 56 | "serverSideRpc": [ 57 | { 58 | "deviceNameFilter": ".*", 59 | "methodFilter": "read", 60 | "valueExpression": "${params}" 61 | }, 62 | { 63 | "deviceNameFilter": ".*", 64 | "methodFilter": "write", 65 | "valueExpression": "${params}" 66 | } 67 | ] 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /tests/unit/connectors/ftp/data/anonym_type/old_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "host": "0.0.0.0", 3 | "port": 21, 4 | "TLSSupport": false, 5 | "security": { 6 | "type": "anonymous" 7 | }, 8 | "paths": [ 9 | { 10 | "devicePatternName": "asd", 11 | "devicePatternType": "Device", 12 | "delimiter": ",", 13 | "path": "fol/*_hello*.txt", 14 | "readMode": "FULL", 15 | "maxFileSize": 5, 16 | "pollPeriod": 500, 17 | "txtFileDataView": "SLICED", 18 | "withSortingFiles": true, 19 | "attributes": [ 20 | { 21 | "key": "temp", 22 | "value": "[1:]" 23 | }, 24 | { 25 | "key": "tmp", 26 | "value": "[0:1]" 27 | } 28 | ], 29 | "timeseries": [ 30 | { 31 | "type": "int", 32 | "key": "[0:1]", 33 | "value": "[0:1]" 34 | }, 35 | { 36 | "type": "int", 37 | "key": "temp", 38 | "value": "[1:]" 39 | } 40 | ] 41 | } 42 | ], 43 | "attributeUpdates": [ 44 | { 45 | "path": "fol/hello.json", 46 | "deviceNameFilter": ".*", 47 | "writingMode": "WRITE", 48 | "valueExpression": "{'${attributeKey}':'${attributeValue}'}" 49 | } 50 | ], 51 | "serverSideRpc": [ 52 | { 53 | "deviceNameFilter": ".*", 54 | "methodFilter": "read", 55 | "valueExpression": "${params}" 56 | }, 57 | { 58 | "deviceNameFilter": ".*", 59 | "methodFilter": "write", 60 | "valueExpression": "${params}" 61 | } 62 | ] 63 | } 64 | -------------------------------------------------------------------------------- /tests/unit/connectors/ftp/data/attribute_updates/new_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "parameters": { 3 | "host": "0.0.0.0", 4 | "port": 21, 5 | "TLSSupport": false, 6 | "security": { 7 | "type": "basic", 8 | "username": "admin", 9 | "password": "admin" 10 | } 11 | }, 12 | "paths": [ 13 | { 14 | "devicePatternName": "asd", 15 | "devicePatternType": "Device", 16 | "delimiter": ",", 17 | "path": "fol/*_hello*.txt", 18 | "readMode": "FULL", 19 | "maxFileSize": 5, 20 | "pollPeriod": 500, 21 | "txtFileDataView": "SLICED", 22 | "withSortingFiles": true, 23 | "attributes": [ 24 | { 25 | "type": "string", 26 | "key": "temp", 27 | "value": "[1:]" 28 | }, 29 | { 30 | "type": "string", 31 | "key": "tmp", 32 | "value": "[0:1]" 33 | } 34 | ], 35 | "timeseries": [ 36 | { 37 | "type": "integer", 38 | "key": "[0:1]", 39 | "value": "[0:1]" 40 | }, 41 | { 42 | "type": "integer", 43 | "key": "temp", 44 | "value": "[1:]" 45 | } 46 | ] 47 | } 48 | ], 49 | "requestsMapping": { 50 | "attributeUpdates": [ 51 | ], 52 | "serverSideRpc": [ 53 | { 54 | "deviceNameFilter": ".*", 55 | "methodFilter": "read", 56 | "valueExpression": "${params}" 57 | }, 58 | { 59 | "deviceNameFilter": ".*", 60 | "methodFilter": "write", 61 | "valueExpression": "${params}" 62 | } 63 | ] 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /tests/unit/connectors/ftp/data/attribute_updates/old_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "host": "0.0.0.0", 3 | "port": 21, 4 | "TLSSupport": false, 5 | "security": { 6 | "type": "basic", 7 | "username": "admin", 8 | "password": "admin" 9 | }, 10 | "paths": [ 11 | { 12 | "devicePatternName": "asd", 13 | "devicePatternType": "Device", 14 | "delimiter": ",", 15 | "path": "fol/*_hello*.txt", 16 | "readMode": "FULL", 17 | "maxFileSize": 5, 18 | "pollPeriod": 500, 19 | "txtFileDataView": "SLICED", 20 | "withSortingFiles": true, 21 | "attributes": [ 22 | { 23 | "key": "temp", 24 | "value": "[1:]" 25 | }, 26 | { 27 | "key": "tmp", 28 | "value": "[0:1]" 29 | } 30 | ], 31 | "timeseries": [ 32 | { 33 | "type": "int", 34 | "key": "[0:1]", 35 | "value": "[0:1]" 36 | }, 37 | { 38 | "type": "int", 39 | "key": "temp", 40 | "value": "[1:]" 41 | } 42 | ] 43 | } 44 | ], 45 | "attributeUpdates": [ 46 | ], 47 | "serverSideRpc": [ 48 | { 49 | "deviceNameFilter": ".*", 50 | "methodFilter": "read", 51 | "valueExpression": "${params}" 52 | }, 53 | { 54 | "deviceNameFilter": ".*", 55 | "methodFilter": "write", 56 | "valueExpression": "${params}" 57 | } 58 | ] 59 | } 60 | -------------------------------------------------------------------------------- /tests/unit/connectors/ftp/data/basic_type/new_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "parameters": { 3 | "host": "0.0.0.0", 4 | "port": 21, 5 | "TLSSupport": false, 6 | "security": { 7 | "type": "basic", 8 | "username": "admin", 9 | "password": "admin" 10 | } 11 | }, 12 | "paths": [ 13 | { 14 | "devicePatternName": "asd", 15 | "devicePatternType": "Device", 16 | "delimiter": ",", 17 | "path": "fol/*_hello*.txt", 18 | "readMode": "FULL", 19 | "maxFileSize": 5, 20 | "pollPeriod": 500, 21 | "txtFileDataView": "SLICED", 22 | "withSortingFiles": true, 23 | "attributes": [ 24 | { 25 | "type": "string", 26 | "key": "temp", 27 | "value": "[1:]" 28 | }, 29 | { 30 | "type": "string", 31 | "key": "tmp", 32 | "value": "[0:1]" 33 | } 34 | ], 35 | "timeseries": [ 36 | { 37 | "type": "integer", 38 | "key": "[0:1]", 39 | "value": "[0:1]" 40 | }, 41 | { 42 | "type": "integer", 43 | "key": "temp", 44 | "value": "[1:]" 45 | } 46 | ] 47 | } 48 | ], 49 | "requestsMapping": { 50 | "attributeUpdates": [ 51 | { 52 | "path": "fol/hello.json", 53 | "deviceNameFilter": ".*", 54 | "writingMode": "WRITE", 55 | "valueExpression": "{'${attributeKey}':'${attributeValue}'}" 56 | } 57 | ], 58 | "serverSideRpc": [ 59 | { 60 | "deviceNameFilter": ".*", 61 | "methodFilter": "read", 62 | "valueExpression": "${params}" 63 | }, 64 | { 65 | "deviceNameFilter": ".*", 66 | "methodFilter": "write", 67 | "valueExpression": "${params}" 68 | } 69 | ] 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /tests/unit/connectors/ftp/data/basic_type/old_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "host": "0.0.0.0", 3 | "port": 21, 4 | "TLSSupport": false, 5 | "security": { 6 | "type": "basic", 7 | "username": "admin", 8 | "password": "admin" 9 | }, 10 | "paths": [ 11 | { 12 | "devicePatternName": "asd", 13 | "devicePatternType": "Device", 14 | "delimiter": ",", 15 | "path": "fol/*_hello*.txt", 16 | "readMode": "FULL", 17 | "maxFileSize": 5, 18 | "pollPeriod": 500, 19 | "txtFileDataView": "SLICED", 20 | "withSortingFiles": true, 21 | "attributes": [ 22 | { 23 | "key": "temp", 24 | "value": "[1:]" 25 | }, 26 | { 27 | "key": "tmp", 28 | "value": "[0:1]" 29 | } 30 | ], 31 | "timeseries": [ 32 | { 33 | "type": "int", 34 | "key": "[0:1]", 35 | "value": "[0:1]" 36 | }, 37 | { 38 | "type": "int", 39 | "key": "temp", 40 | "value": "[1:]" 41 | } 42 | ] 43 | } 44 | ], 45 | "attributeUpdates": [ 46 | { 47 | "path": "fol/hello.json", 48 | "deviceNameFilter": ".*", 49 | "writingMode": "WRITE", 50 | "valueExpression": "{'${attributeKey}':'${attributeValue}'}" 51 | } 52 | ], 53 | "serverSideRpc": [ 54 | { 55 | "deviceNameFilter": ".*", 56 | "methodFilter": "read", 57 | "valueExpression": "${params}" 58 | }, 59 | { 60 | "deviceNameFilter": ".*", 61 | "methodFilter": "write", 62 | "valueExpression": "${params}" 63 | } 64 | ] 65 | } 66 | -------------------------------------------------------------------------------- /tests/unit/connectors/mqtt/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/tests/unit/connectors/mqtt/__init__.py -------------------------------------------------------------------------------- /tests/unit/connectors/mqtt/data/attribute_requests/new_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "broker": { 3 | "name": "Default Local Broker", 4 | "host": "127.0.0.1", 5 | "port": 1883, 6 | "clientId": "ThingsBoard_gateway", 7 | "version": 5, 8 | "maxMessageNumberPerWorker": 10, 9 | "maxNumberOfWorkers": 100, 10 | "sendDataOnlyOnChange": false, 11 | "security": { 12 | "type": "anonymous" 13 | } 14 | }, 15 | "mapping": [], 16 | "requestsMapping": { 17 | "serverSideRpc": {}, 18 | "connectRequests": {}, 19 | "disconnectRequests": {}, 20 | "attributeRequests": [ 21 | { 22 | "retain": false, 23 | "qos": 0, 24 | "topicFilter": "v1/devices/me/attributes/request", 25 | "deviceInfo": { 26 | "deviceNameExpressionSource": "message", 27 | "deviceNameExpression": "${serialNumber}" 28 | }, 29 | "attributeNameExpressionSource": "message", 30 | "attributeNameExpression": "${versionAttribute}, ${pduAttribute}", 31 | "topicExpression": "devices/${deviceName}/attrs", 32 | "valueExpression": "${attributeKey}: ${attributeValue}" 33 | } 34 | ], 35 | "attributeUpdates": {} 36 | } 37 | } -------------------------------------------------------------------------------- /tests/unit/connectors/mqtt/data/attribute_requests/old_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "broker": { 3 | "name": "Default Local Broker", 4 | "host": "127.0.0.1", 5 | "port": 1883, 6 | "clientId": "ThingsBoard_gateway", 7 | "version": 5, 8 | "maxMessageNumberPerWorker": 10, 9 | "maxNumberOfWorkers": 100, 10 | "sendDataOnlyOnChange": false, 11 | "security": { 12 | "type": "anonymous" 13 | } 14 | }, 15 | "mapping": [], 16 | "attributeRequests": [ 17 | { 18 | "retain": false, 19 | "qos": 0, 20 | "topicFilter": "v1/devices/me/attributes/request", 21 | "deviceNameJsonExpression": "${serialNumber}", 22 | "attributeNameJsonExpression": "${versionAttribute}, ${pduAttribute}", 23 | "topicExpression": "devices/${deviceName}/attrs", 24 | "valueExpression": "${attributeKey}: ${attributeValue}" 25 | } 26 | ] 27 | } -------------------------------------------------------------------------------- /tests/unit/connectors/mqtt/data/attribute_updates/new_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "broker": { 3 | "name": "Default Local Broker", 4 | "host": "127.0.0.1", 5 | "port": 1883, 6 | "clientId": "ThingsBoard_gateway", 7 | "version": 5, 8 | "maxMessageNumberPerWorker": 10, 9 | "maxNumberOfWorkers": 100, 10 | "sendDataOnlyOnChange": false, 11 | "security": { 12 | "type": "anonymous" 13 | } 14 | }, 15 | "mapping": [], 16 | "requestsMapping": { 17 | "serverSideRpc": {}, 18 | "connectRequests": {}, 19 | "disconnectRequests": {}, 20 | "attributeRequests": {}, 21 | "attributeUpdates": [ 22 | { 23 | "retain": true, 24 | "qos": 0, 25 | "deviceNameFilter": ".*", 26 | "attributeFilter": "uploadFrequency", 27 | "topicExpression": "sensor/${deviceName}/${attributeKey}", 28 | "valueExpression": "{\"${attributeKey}\":\"${attributeValue}\"}" 29 | } 30 | ] 31 | } 32 | } -------------------------------------------------------------------------------- /tests/unit/connectors/mqtt/data/attribute_updates/old_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "broker": { 3 | "name": "Default Local Broker", 4 | "host": "127.0.0.1", 5 | "port": 1883, 6 | "clientId": "ThingsBoard_gateway", 7 | "version": 5, 8 | "maxMessageNumberPerWorker": 10, 9 | "maxNumberOfWorkers": 100, 10 | "sendDataOnlyOnChange": false, 11 | "security": { 12 | "type": "anonymous" 13 | } 14 | }, 15 | "mapping": [], 16 | "attributeUpdates": [ 17 | { 18 | "retain": true, 19 | "qos": 0, 20 | "deviceNameFilter": ".*", 21 | "attributeFilter": "uploadFrequency", 22 | "topicExpression": "sensor/${deviceName}/${attributeKey}", 23 | "valueExpression": "{\"${attributeKey}\":\"${attributeValue}\"}" 24 | } 25 | ] 26 | } -------------------------------------------------------------------------------- /tests/unit/connectors/mqtt/data/connect_requests/new_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "broker": { 3 | "name": "Default Local Broker", 4 | "host": "127.0.0.1", 5 | "port": 1883, 6 | "clientId": "ThingsBoard_gateway", 7 | "version": 5, 8 | "maxMessageNumberPerWorker": 10, 9 | "maxNumberOfWorkers": 100, 10 | "sendDataOnlyOnChange": false, 11 | "security": { 12 | "type": "anonymous" 13 | } 14 | }, 15 | "mapping": [], 16 | "requestsMapping": { 17 | "serverSideRpc": {}, 18 | "connectRequests": [ 19 | { 20 | "topicFilter": "sensor/connect", 21 | "deviceInfo": { 22 | "deviceNameExpressionSource": "message", 23 | "deviceNameExpression": "${serialNumber}" 24 | } 25 | }, 26 | { 27 | "topicFilter": "sensor/+/connect", 28 | "deviceInfo": { 29 | "deviceNameExpressionSource": "topic", 30 | "deviceNameExpression": "(?<=sensor/)(.*?)(?=/connect)" 31 | } 32 | } 33 | ], 34 | "disconnectRequests": {}, 35 | "attributeRequests": {}, 36 | "attributeUpdates": {} 37 | } 38 | } -------------------------------------------------------------------------------- /tests/unit/connectors/mqtt/data/connect_requests/old_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "broker": { 3 | "name": "Default Local Broker", 4 | "host": "127.0.0.1", 5 | "port": 1883, 6 | "clientId": "ThingsBoard_gateway", 7 | "version": 5, 8 | "maxMessageNumberPerWorker": 10, 9 | "maxNumberOfWorkers": 100, 10 | "sendDataOnlyOnChange": false, 11 | "security": { 12 | "type": "anonymous" 13 | } 14 | }, 15 | "mapping": [], 16 | "connectRequests": [ 17 | { 18 | "topicFilter": "sensor/connect", 19 | "deviceNameJsonExpression": "${serialNumber}" 20 | }, 21 | { 22 | "topicFilter": "sensor/+/connect", 23 | "deviceNameTopicExpression": "(?<=sensor/)(.*?)(?=/connect)" 24 | } 25 | ] 26 | } -------------------------------------------------------------------------------- /tests/unit/connectors/mqtt/data/disconnect_requests/new_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "broker": { 3 | "name": "Default Local Broker", 4 | "host": "127.0.0.1", 5 | "port": 1883, 6 | "clientId": "ThingsBoard_gateway", 7 | "version": 5, 8 | "maxMessageNumberPerWorker": 10, 9 | "maxNumberOfWorkers": 100, 10 | "sendDataOnlyOnChange": false, 11 | "security": { 12 | "type": "anonymous" 13 | } 14 | }, 15 | "mapping": [], 16 | "requestsMapping": { 17 | "serverSideRpc": {}, 18 | "connectRequests": {}, 19 | "disconnectRequests": [ 20 | { 21 | "topicFilter":"sensor/disconnect", 22 | "deviceInfo":{ 23 | "deviceNameExpressionSource":"message", 24 | "deviceNameExpression":"${serialNumber}" 25 | } 26 | }, 27 | { 28 | "topicFilter":"sensor/+/disconnect", 29 | "deviceInfo":{ 30 | "deviceNameExpressionSource":"topic", 31 | "deviceNameExpression":"(?<=sensor/)(.*?)(?=/disconnect)" 32 | } 33 | } 34 | ], 35 | "attributeRequests": {}, 36 | "attributeUpdates": {} 37 | } 38 | } -------------------------------------------------------------------------------- /tests/unit/connectors/mqtt/data/disconnect_requests/old_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "broker": { 3 | "name": "Default Local Broker", 4 | "host": "127.0.0.1", 5 | "port": 1883, 6 | "clientId": "ThingsBoard_gateway", 7 | "version": 5, 8 | "maxMessageNumberPerWorker": 10, 9 | "maxNumberOfWorkers": 100, 10 | "sendDataOnlyOnChange": false, 11 | "security": { 12 | "type": "anonymous" 13 | } 14 | }, 15 | "mapping": [], 16 | "disconnectRequests": [ 17 | { 18 | "topicFilter": "sensor/disconnect", 19 | "deviceNameJsonExpression": "${serialNumber}" 20 | }, 21 | { 22 | "topicFilter": "sensor/+/disconnect", 23 | "deviceNameTopicExpression": "(?<=sensor/)(.*?)(?=/disconnect)" 24 | } 25 | ] 26 | } -------------------------------------------------------------------------------- /tests/unit/connectors/mqtt/data/server_side_rpc/new_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "broker": { 3 | "name": "Default Local Broker", 4 | "host": "127.0.0.1", 5 | "port": 1883, 6 | "clientId": "ThingsBoard_gateway", 7 | "version": 5, 8 | "maxMessageNumberPerWorker": 10, 9 | "maxNumberOfWorkers": 100, 10 | "sendDataOnlyOnChange": false, 11 | "security": { 12 | "type": "anonymous" 13 | } 14 | }, 15 | "mapping": [], 16 | "requestsMapping": { 17 | "serverSideRpc": [ 18 | { 19 | "deviceNameFilter": ".*", 20 | "methodFilter": "echo", 21 | "requestTopicExpression": "sensor/${deviceName}/request/${methodName}/${requestId}", 22 | "responseTopicExpression": "sensor/${deviceName}/response/${methodName}/${requestId}", 23 | "responseTimeout": 1000, 24 | "valueExpression": "${params}" 25 | }, 26 | { 27 | "deviceNameFilter": ".*", 28 | "methodFilter": "no-reply", 29 | "requestTopicExpression": "sensor/${deviceName}/request/${methodName}/${requestId}", 30 | "valueExpression": "${params}" 31 | } 32 | ], 33 | "connectRequests": {}, 34 | "disconnectRequests": {}, 35 | "attributeRequests": {}, 36 | "attributeUpdates": {} 37 | } 38 | } -------------------------------------------------------------------------------- /tests/unit/connectors/mqtt/data/server_side_rpc/old_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "broker": { 3 | "name": "Default Local Broker", 4 | "host": "127.0.0.1", 5 | "port": 1883, 6 | "clientId": "ThingsBoard_gateway", 7 | "version": 5, 8 | "maxMessageNumberPerWorker": 10, 9 | "maxNumberOfWorkers": 100, 10 | "sendDataOnlyOnChange": false, 11 | "security": { 12 | "type": "anonymous" 13 | } 14 | }, 15 | "mapping": [], 16 | "serverSideRpc": [ 17 | { 18 | "deviceNameFilter": ".*", 19 | "methodFilter": "echo", 20 | "requestTopicExpression": "sensor/${deviceName}/request/${methodName}/${requestId}", 21 | "responseTopicExpression": "sensor/${deviceName}/response/${methodName}/${requestId}", 22 | "responseTimeout": 1000, 23 | "valueExpression": "${params}" 24 | }, 25 | { 26 | "deviceNameFilter": ".*", 27 | "methodFilter": "no-reply", 28 | "requestTopicExpression": "sensor/${deviceName}/request/${methodName}/${requestId}", 29 | "valueExpression": "${params}" 30 | } 31 | ] 32 | } -------------------------------------------------------------------------------- /tests/unit/connectors/opcua/__init__.py: -------------------------------------------------------------------------------- 1 | # TODO Configure environment for these tests -------------------------------------------------------------------------------- /tests/unit/connectors/socket/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/tests/unit/connectors/socket/__init__.py -------------------------------------------------------------------------------- /tests/unit/connectors/socket/data/new_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "socket": { 3 | "type": "TCP", 4 | "address": "127.0.0.1", 5 | "port": 50000, 6 | "bufferSize": 1024 7 | }, 8 | "devices": [ 9 | { 10 | "address": "*:*", 11 | "deviceName": "Device Example", 12 | "deviceType": "default", 13 | "encoding": "utf-8", 14 | "telemetry": [ 15 | { 16 | "key": "temp", 17 | "byteFrom": 0, 18 | "byteTo": -1 19 | }, 20 | { 21 | "key": "hum", 22 | "byteFrom": 0, 23 | "byteTo": 2 24 | } 25 | ], 26 | "attributes": [ 27 | { 28 | "key": "name", 29 | "byteFrom": 0, 30 | "byteTo": -1 31 | }, 32 | { 33 | "key": "num", 34 | "byteFrom": 2, 35 | "byteTo": 4 36 | } 37 | ], 38 | "attributeRequests": [ 39 | { 40 | "type": "shared", 41 | "requestExpressionSource": "expression", 42 | "attributeNameExpressionSource": "expression", 43 | "requestExpression": "${[0:3]==atr}", 44 | "attributeNameExpression": "[3:]" 45 | } 46 | ], 47 | "attributeUpdates": [ 48 | { 49 | "encoding": "utf-16", 50 | "attributeOnThingsBoard": "sharedName" 51 | } 52 | ], 53 | "serverSideRpc": [ 54 | { 55 | "methodRPC": "rpcMethod1", 56 | "withResponse": true, 57 | "encoding": "utf-8" 58 | } 59 | ] 60 | } 61 | ] 62 | } -------------------------------------------------------------------------------- /tests/unit/connectors/socket/data/old_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "TCP", 3 | "address": "127.0.0.1", 4 | "port": 50000, 5 | "bufferSize": 1024, 6 | "devices": [ 7 | { 8 | "addressFilter": "*:*", 9 | "deviceName": "Device Example", 10 | "deviceType": "default", 11 | "encoding": "utf-8", 12 | "telemetry": [ 13 | { 14 | "key": "temp", 15 | "byteFrom": 0, 16 | "byteTo": -1 17 | }, 18 | { 19 | "key": "hum", 20 | "byteFrom": 0, 21 | "byteTo": 2 22 | } 23 | ], 24 | "attributes": [ 25 | { 26 | "key": "name", 27 | "byteFrom": 0, 28 | "byteTo": -1 29 | }, 30 | { 31 | "key": "num", 32 | "byteFrom": 2, 33 | "byteTo": 4 34 | } 35 | ], 36 | "attributeRequests": [ 37 | { 38 | "type": "shared", 39 | "requestExpression": "${[0:3]==atr}", 40 | "attributeNameExpression": "[3:]" 41 | } 42 | ], 43 | "attributeUpdates": [ 44 | { 45 | "encoding": "utf-16", 46 | "attributeOnThingsBoard": "sharedName" 47 | } 48 | ], 49 | "serverSideRpc": [ 50 | { 51 | "methodRPC": "rpcMethod1", 52 | "withResponse": true, 53 | "encoding": "utf-8" 54 | } 55 | ] 56 | } 57 | ] 58 | } 59 | -------------------------------------------------------------------------------- /tests/unit/connectors/socket/test_socket_backward_compatibility_adapter.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from os import path 3 | from tests.unit.BaseUnitTest import BaseUnitTest 4 | from simplejson import load 5 | from thingsboard_gateway.connectors.socket.backward_compatibility_adapter import BackwardCompatibilityAdapter 6 | 7 | 8 | class SocketBackwardCompatibilityAdapterTests(BaseUnitTest): 9 | CONFIG_PATH = path.join(path.dirname(path.dirname(path.dirname(path.abspath(__file__)))), 10 | "connectors" + path.sep + "socket" + path.sep + "data" + path.sep) 11 | 12 | @staticmethod 13 | def convert_json(config_path): 14 | with open(config_path, 'r') as file: 15 | config = load(file) 16 | 17 | return config 18 | 19 | def setUp(self): 20 | self.maxDiff = 8000 21 | self.adapter = BackwardCompatibilityAdapter(config={}) 22 | 23 | def test_is_old_config(self): 24 | is_old_config = self.convert_json(self.CONFIG_PATH + 'old_config.json') 25 | self.assertTrue(is_old_config, True) 26 | 27 | def test_convert_with_empty_config(self): 28 | result = self.adapter.convert() 29 | expected_result = {'socket': 30 | {'address': '127.0.0.1', 31 | 'bufferSize': 1024, 32 | 'port': 50000, 33 | 'type': 'TCP'} 34 | } 35 | self.assertEqual(expected_result, result) 36 | 37 | def test_convert_from_old_to_new_config(self): 38 | self.adapter._config = self.convert_json(self.CONFIG_PATH + 'old_config.json') 39 | result = self.adapter.convert() 40 | expected_result = self.convert_json(self.CONFIG_PATH + 'new_config.json') 41 | self.assertEqual(expected_result, result) 42 | 43 | 44 | if __name__ == '__main__': 45 | unittest.main() 46 | -------------------------------------------------------------------------------- /tests/unit/converters/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022. ThingsBoard 2 | # # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | -------------------------------------------------------------------------------- /tests/unit/converters/can/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/tests/unit/converters/can/__init__.py -------------------------------------------------------------------------------- /tests/unit/converters/modbus/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/tests/unit/converters/modbus/__init__.py -------------------------------------------------------------------------------- /tests/unit/converters/mqtt/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/tests/unit/converters/mqtt/__init__.py -------------------------------------------------------------------------------- /tests/unit/converters/odbc/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/tests/unit/converters/odbc/__init__.py -------------------------------------------------------------------------------- /tests/unit/converters/request/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/tests/unit/converters/request/__init__.py -------------------------------------------------------------------------------- /tests/unit/data/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/tests/unit/data/__init__.py -------------------------------------------------------------------------------- /tests/unit/service/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/tests/unit/service/__init__.py -------------------------------------------------------------------------------- /thingsboard_gateway/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/thingsboard_gateway/__init__.py -------------------------------------------------------------------------------- /thingsboard_gateway/config/custom_serial.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Custom serial connector", 3 | "logLevel": "DEBUG", 4 | "uplinkQueueSize": 100000, 5 | "devices": [ 6 | { 7 | "name": "SerialDevice1", 8 | "type": "default", 9 | "port": "/dev/ttysUSB0", 10 | "baudrate": 9600, 11 | "converter": "SerialUplinkConverter", 12 | "downlink_converter": "SerialDownlinkConverter", 13 | "telemetry": [ 14 | { 15 | "type": "float", 16 | "key": "humidity", 17 | "untilDelimiter": "\r" 18 | } 19 | ], 20 | "attributes": [ 21 | { 22 | "key": "SerialNumber", 23 | "type": "string", 24 | "fromByte": 4, 25 | "toByte": -1 26 | } 27 | ], 28 | "attributeUpdates": [ 29 | { 30 | "attributeOnPlatform": "attr1", 31 | "stringToDevice": "value = ${attr1}\n" 32 | } 33 | ], 34 | "serverSideRpc": [ 35 | { 36 | "method": "setValue", 37 | "type": "int", 38 | "withResponse": true, 39 | "responseType": "string", 40 | "responseUntilDelimiter": "\r", 41 | "responseTimeoutSec": 5 42 | }, 43 | { 44 | "method": "getValue", 45 | "type": "string", 46 | "withResponse": false 47 | } 48 | ] 49 | } 50 | ] 51 | } -------------------------------------------------------------------------------- /thingsboard_gateway/config/ftp.json: -------------------------------------------------------------------------------- 1 | { 2 | "host": "0.0.0.0", 3 | "port": 21, 4 | "TLSSupport": false, 5 | "security": { 6 | "type": "basic", 7 | "username": "admin", 8 | "password": "admin" 9 | }, 10 | "paths": [ 11 | { 12 | "devicePatternName": "asd", 13 | "devicePatternType": "Device", 14 | "delimiter": ",", 15 | "path": "fol/*_hello*.txt", 16 | "readMode": "FULL", 17 | "maxFileSize": 5, 18 | "pollPeriod": 500, 19 | "txtFileDataView": "SLICED", 20 | "withSortingFiles": true, 21 | "attributes": [ 22 | { 23 | "key": "temp", 24 | "value": "[1:]" 25 | }, 26 | { 27 | "key": "tmp", 28 | "value": "[0:1]" 29 | } 30 | ], 31 | "timeseries": [ 32 | { 33 | "type": "int", 34 | "key": "[0:1]", 35 | "value": "[0:1]" 36 | }, 37 | { 38 | "type": "int", 39 | "key": "temp", 40 | "value": "[1:]" 41 | } 42 | ] 43 | } 44 | ], 45 | "attributeUpdates": [ 46 | { 47 | "path": "fol/hello.json", 48 | "deviceNameFilter": ".*", 49 | "writingMode": "WRITE", 50 | "valueExpression": "{'${attributeKey}':'${attributeValue}'}" 51 | } 52 | ], 53 | "serverSideRpc": [ 54 | { 55 | "deviceNameFilter": ".*", 56 | "methodFilter": "read", 57 | "valueExpression": "${params}" 58 | }, 59 | { 60 | "deviceNameFilter": ".*", 61 | "methodFilter": "write", 62 | "valueExpression": "${params}" 63 | } 64 | ] 65 | } 66 | -------------------------------------------------------------------------------- /thingsboard_gateway/config/knx.json: -------------------------------------------------------------------------------- 1 | { 2 | "logLevel": "INFO", 3 | "client": { 4 | "type": "AUTOMATIC", 5 | "addressFormat": "LONG", 6 | "localIp": "0.0.0.0", 7 | "localPort": 3671, 8 | "gatewayIP": "192.168.1.160", 9 | "gatewayPort": 3671, 10 | "individualAddress": "1.0.10", 11 | "rateLimit": 0, 12 | "autoReconnect": true, 13 | "autoReconnectWait": 3, 14 | "gatewaysScanner": { 15 | "enabled": false, 16 | "scanPeriod": 3, 17 | "stopOnFound": false 18 | } 19 | }, 20 | "devices": [ 21 | { 22 | "deviceInfo": { 23 | "deviceNameDataType": "string", 24 | "deviceNameExpressionSource": "expression", 25 | "deviceNameExpression": "Device ${1/0/5}", 26 | "deviceProfileDataType": "none", 27 | "deviceProfileExpressionSource": "constant", 28 | "deviceProfileNameExpression": "default" 29 | }, 30 | "pollPeriod": 5000, 31 | "attributes": [ 32 | { 33 | "type": "temperature", 34 | "key": "temperature", 35 | "groupAddress": "1/0/6" 36 | } 37 | ], 38 | "timeseries": [ 39 | { 40 | "type": "humidity", 41 | "key": "humidity", 42 | "groupAddress": "1/0/7" 43 | } 44 | ] 45 | } 46 | ], 47 | "attributeUpdates": [ 48 | { 49 | "deviceNameFilter": ".*", 50 | "dataType": "precent_U8", 51 | "groupAddress": "1/0/9", 52 | "key": "brightness" 53 | } 54 | ], 55 | "serverSideRpc": [ 56 | { 57 | "requestType": "read", 58 | "deviceNameFilter": ".*", 59 | "method": "get_name", 60 | "dataType": "string", 61 | "groupAddress": "1/0/5" 62 | }, 63 | { 64 | "requestType": "write", 65 | "deviceNameFilter": ".*", 66 | "method": "set_name", 67 | "dataType": "string", 68 | "groupAddress": "1/0/5" 69 | } 70 | ] 71 | } 72 | -------------------------------------------------------------------------------- /thingsboard_gateway/config/list.json: -------------------------------------------------------------------------------- 1 | { 2 | "deny": { 3 | "MQTT Broker Connector": [ 4 | "Temperature Device", 5 | "(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$)" 6 | ], 7 | "Modbus Connector": [ 8 | "My Modbus Device" 9 | ] 10 | }, 11 | "allow": { 12 | "MQTT Broker Connector": [ 13 | "My Temperature Sensor" 14 | ] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /thingsboard_gateway/config/ocpp.json: -------------------------------------------------------------------------------- 1 | { 2 | "centralSystem": { 3 | "name": "Central System", 4 | "host": "127.0.0.1", 5 | "port": 9000, 6 | "connection": { 7 | "type": "insecure" 8 | }, 9 | "security": [ 10 | { 11 | "type": "token", 12 | "tokens": [ 13 | "Bearer ACCESS_TOKEN" 14 | ] 15 | }, 16 | { 17 | "type": "basic", 18 | "credentials": [ 19 | { 20 | "username": "admin", 21 | "password": "admin" 22 | } 23 | ] 24 | } 25 | ] 26 | }, 27 | "chargePoints": [ 28 | { 29 | "idRegexpPattern": "bidon/hello/CP_1", 30 | "deviceNameExpression": "${Vendor} ${Model}", 31 | "deviceTypeExpression": "default", 32 | "attributes": [ 33 | { 34 | "messageTypeFilter": "MeterValues,", 35 | "key": "temp1", 36 | "value": "${meter_value[:].sampled_value[:].value}" 37 | }, 38 | { 39 | "messageTypeFilter": "MeterValues,", 40 | "key": "vendorId", 41 | "value": "${connector_id}" 42 | } 43 | ], 44 | "timeseries": [ 45 | { 46 | "messageTypeFilter": "DataTransfer,", 47 | "key": "temp", 48 | "value": "${data.temp}" 49 | } 50 | ], 51 | "attributeUpdates": [ 52 | { 53 | "attributeOnThingsBoard": "shared", 54 | "valueExpression": "{\"${attributeKey}\":\"${attributeValue}\"}" 55 | } 56 | ], 57 | "serverSideRpc": [ 58 | { 59 | "methodRPC": "rpc1", 60 | "withResponse": true, 61 | "valueExpression": "${params}" 62 | } 63 | ] 64 | } 65 | ] 66 | } -------------------------------------------------------------------------------- /thingsboard_gateway/config/odbc.json: -------------------------------------------------------------------------------- 1 | { 2 | "connection": { 3 | "str": "Driver={PostgreSQL};Server=localhost;Port=5432;Database=thingsboard;Uid=postgres;Pwd=postgres;", 4 | "attributes": { 5 | "autocommit": true, 6 | "timeout": 0 7 | }, 8 | "encoding": "utf-8", 9 | "decoding": { 10 | "char": "utf-8", 11 | "wchar": "utf-8", 12 | "metadata": "utf-16le" 13 | }, 14 | "reconnect": true, 15 | "reconnectPeriod": 60 16 | }, 17 | "pyodbc": { 18 | "pooling": false 19 | }, 20 | "polling": { 21 | "query": "SELECT bool_v, str_v, dbl_v, long_v, entity_id, ts FROM ts_kv WHERE ts > ? ORDER BY ts ASC LIMIT 10", 22 | "period": 10, 23 | "iterator": { 24 | "column": "ts", 25 | "query": "SELECT MIN(ts) - 1 FROM ts_kv", 26 | "persistent": false 27 | } 28 | }, 29 | "mapping": { 30 | "device": { 31 | "type": "postgres", 32 | "name": "'ODBC ' + entity_id" 33 | }, 34 | "attributes": "*", 35 | "timeseries": [ 36 | { 37 | "name": "value", 38 | "value": "[i for i in [str_v, long_v, dbl_v,bool_v] if i is not None][0]" 39 | } 40 | ] 41 | }, 42 | "serverSideRpc": { 43 | "enableUnknownRpc": false, 44 | "overrideRpcConfig": true, 45 | "methods": [ 46 | "procedureOne", 47 | { 48 | "name": "procedureTwo", 49 | "args": [ 50 | "One", 51 | 2, 52 | 3.0 53 | ] 54 | } 55 | ] 56 | } 57 | } -------------------------------------------------------------------------------- /thingsboard_gateway/config/socket.json: -------------------------------------------------------------------------------- 1 | { 2 | "socket": { 3 | "address": "127.0.0.1", 4 | "type": "TCP", 5 | "port": 50000, 6 | "bufferSize": 1024 7 | }, 8 | "devices": [ 9 | { 10 | "address": "*:*", 11 | "addressFilter": "*:*", 12 | "deviceName": "Device Example", 13 | "deviceType": "default", 14 | "encoding": "utf-8", 15 | "telemetry": [ 16 | { 17 | "key": "temp", 18 | "byteFrom": 0, 19 | "byteTo": -1 20 | }, 21 | { 22 | "key": "hum", 23 | "byteFrom": 0, 24 | "byteTo": 2 25 | } 26 | ], 27 | "attributes": [ 28 | { 29 | "key": "name", 30 | "byteFrom": 0, 31 | "byteTo": -1 32 | }, 33 | { 34 | "key": "num", 35 | "byteFrom": 2, 36 | "byteTo": 4 37 | } 38 | ], 39 | "attributeRequests": [ 40 | { 41 | "type": "shared", 42 | "requestExpression": "${[0:3]==atr}", 43 | "attributeNameExpression": "[3:]" 44 | } 45 | ], 46 | "attributeUpdates": [ 47 | { 48 | "encoding": "utf-16", 49 | "attributeOnThingsBoard": "sharedName" 50 | } 51 | ], 52 | "serverSideRpc": [ 53 | { 54 | "methodRPC": "rpcMethod1", 55 | "withResponse": true, 56 | "encoding": "utf-8" 57 | } 58 | ] 59 | } 60 | ] 61 | } 62 | -------------------------------------------------------------------------------- /thingsboard_gateway/config/statistics/statistics_linux.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "timeout": 100, 4 | "command": ["/bin/sh", "-c", "ps -A -o cpu,%mem | awk '{cpu += $1}END{print cpu}'"], 5 | "attributeOnGateway": "CPU" 6 | }, 7 | { 8 | "timeout": 100, 9 | "command": ["/bin/sh", "-c" ,"free -m | grep Swap | awk '{print ($3/$2)*100}'"], 10 | "attributeOnGateway": "Memory" 11 | }, 12 | { 13 | "timeout": 100, 14 | "command": ["/bin/sh", "-c", "hostname -I"], 15 | "attributeOnGateway": "IP address" 16 | }, 17 | { 18 | "timeout": 100, 19 | "command": ["/bin/sh", "-c", "lsb_release -ds"], 20 | "attributeOnGateway": "OS" 21 | }, 22 | { 23 | "timeout": 100, 24 | "command": ["/bin/sh", "-c", "uptime"], 25 | "attributeOnGateway": "Uptime" 26 | }, 27 | { 28 | "timeout": 100, 29 | "command": ["/bin/sh", "-c", "lsusb"], 30 | "attributeOnGateway": "USBs" 31 | } 32 | ] -------------------------------------------------------------------------------- /thingsboard_gateway/config/statistics/statistics_macos.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "timeout": 100, 4 | "command": "ps -A -o cpu,%mem | awk '{cpu += $1}END{print cpu}'", 5 | "attributeOnGateway": "CPU" 6 | }, 7 | { 8 | "timeout": 100, 9 | "command": "ps -A -o %cpu,%mem | awk '{mem += $2}END{print mem}'", 10 | "attributeOnGateway": "Memory" 11 | }, 12 | { 13 | "timeout": 100, 14 | "command": ["/bin/sh", "-c", "hostname -I"], 15 | "attributeOnGateway": "IP address" 16 | }, 17 | { 18 | "timeout": 100, 19 | "command": ["/bin/sh", "-c", "cat /etc/*-release | grep \"PRETTY_NAME\" | sed 's/PRETTY_NAME=//g'"], 20 | "attributeOnGateway": "OS" 21 | }, 22 | { 23 | "timeout": 100, 24 | "command": ["/bin/sh", "-c", "uptime"], 25 | "attributeOnGateway": "Uptime" 26 | }, 27 | { 28 | "timeout": 100, 29 | "command": ["/bin/sh", "-c", "lsusb"], 30 | "attributeOnGateway": "USBs" 31 | } 32 | ] -------------------------------------------------------------------------------- /thingsboard_gateway/config/statistics/statistics_windows.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "timeout": 100, 4 | "command": ["wmic", "cpu", "get", "loadpercentage"], 5 | "attributeOnGateway": "CPU" 6 | }, 7 | { 8 | "timeout": 100, 9 | "command": ["wmic", "OS", "get", "FreeVirtualMemory", "/Value"], 10 | "attributeOnGateway": "Memory" 11 | }, 12 | { 13 | "timeout": 100, 14 | "command": ["ipconfig"], 15 | "attributeOnGateway": "IP address" 16 | }, 17 | { 18 | "timeout": 1000, 19 | "command": ["systeminfo | findstr /B /C:\"OS Name\""], 20 | "attributeOnGateway": "OS" 21 | }, 22 | { 23 | "timeout": 1000, 24 | "command": ["systeminfo | find \"System Boot Time:\""], 25 | "attributeOnGateway": "Uptime" 26 | }, 27 | { 28 | "timeout": 100, 29 | "command": ["wmic", "logicaldisk", "where", "drivetype=2", "get", "deviceid, volumename, description"], 30 | "attributeOnGateway": "USBs" 31 | } 32 | ] -------------------------------------------------------------------------------- /thingsboard_gateway/config/xmpp.json: -------------------------------------------------------------------------------- 1 | { 2 | "server": { 3 | "jid": "gateway@localhost", 4 | "password": "password", 5 | "host": "localhost", 6 | "port": 5222, 7 | "use_ssl": false, 8 | "disable_starttls": false, 9 | "force_starttls": true, 10 | "timeout": 10000, 11 | "plugins": [ 12 | "xep_0030", 13 | "xep_0323", 14 | "xep_0325" 15 | ] 16 | }, 17 | "devices": [ 18 | { 19 | "jid": "device@localhost/TMP_1101", 20 | "deviceNameExpression": "${serialNumber}", 21 | "deviceTypeExpression": "default", 22 | "attributes": [ 23 | { 24 | "key": "temperature", 25 | "value": "${temp}" 26 | } 27 | ], 28 | "timeseries": [ 29 | { 30 | "key": "humidity", 31 | "value": "${hum}" 32 | }, 33 | { 34 | "key": "combination", 35 | "value": "${temp}:${hum}" 36 | } 37 | ], 38 | "attributeUpdates": [ 39 | { 40 | "attributeOnThingsBoard": "shared", 41 | "valueExpression": "{\"${attributeKey}\":\"${attributeValue}\"}" 42 | } 43 | ], 44 | "serverSideRpc": [ 45 | { 46 | "methodRPC": "rpc1", 47 | "withResponse": true, 48 | "valueExpression": "${params}" 49 | } 50 | ] 51 | } 52 | ] 53 | } 54 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/bacnet/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/bacnet/application_service_access_point.py: -------------------------------------------------------------------------------- 1 | from bacpypes3.appservice import ApplicationServiceAccessPoint as AppServiceAccessPoint, ServiceAccessPoint 2 | from bacpypes3.apdu import ( 3 | APCISequence, 4 | APDU, 5 | AbortPDU, 6 | ComplexAckPDU, 7 | ConfirmedRequestPDU, 8 | ErrorPDU, 9 | RejectPDU, 10 | SimpleAckPDU, 11 | UnconfirmedRequestPDU, 12 | ) 13 | 14 | 15 | class ApplicationServiceAccessPoint(AppServiceAccessPoint): 16 | async def sap_response(self, apdu: APDU) -> None: 17 | if isinstance(apdu, SimpleAckPDU): 18 | xpdu = apdu 19 | 20 | elif isinstance( 21 | apdu, (UnconfirmedRequestPDU, ConfirmedRequestPDU, ComplexAckPDU, ErrorPDU) 22 | ): 23 | try: 24 | xpdu = APCISequence.decode(apdu) 25 | except Exception: 26 | if isinstance(apdu, UnconfirmedRequestPDU): 27 | return 28 | 29 | if isinstance(apdu, ConfirmedRequestPDU): 30 | return 31 | 32 | xpdu = apdu 33 | elif isinstance(apdu, (RejectPDU, AbortPDU)): 34 | xpdu = apdu 35 | else: 36 | raise RuntimeError(f"invalid APDU (10): {type(apdu)}") 37 | 38 | await ServiceAccessPoint.sap_response(self, xpdu) 39 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/bacnet/bacnet_converter.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | from abc import abstractmethod 15 | 16 | from thingsboard_gateway.connectors.converter import Converter 17 | 18 | 19 | class AsyncBACnetConverter(Converter): 20 | @abstractmethod 21 | def convert(self, data): 22 | pass 23 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/bacnet/entities/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/thingsboard_gateway/connectors/bacnet/entities/__init__.py -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/bacnet/entities/routers.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from asyncio import Lock 16 | 17 | 18 | class Routers: 19 | def __init__(self): 20 | self.__lock = Lock() 21 | self.__router_info_cache = {} 22 | 23 | async def add_router_info(self, address, info): 24 | await self.__lock.acquire() 25 | try: 26 | if address not in self.__router_info_cache: 27 | self.__router_info_cache[address] = info 28 | finally: 29 | self.__lock.release() 30 | 31 | async def get_router_info_by_address(self, address): 32 | await self.__lock.acquire() 33 | try: 34 | return self.__router_info_cache.get(address) 35 | finally: 36 | self.__lock.release() 37 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/bacnet/entities/uplink_converter_config.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | class UplinkConverterConfig: 16 | def __init__(self, config, device_info, device_details): 17 | self.__config = config 18 | 19 | self.device_details = device_details 20 | self.device_name = device_info.device_name 21 | self.device_type = device_info.device_type 22 | self.__objects_to_read = self.__get_objects_to_read() 23 | self.report_strategy = self.__config.get('reportStrategy', {}) 24 | 25 | def __get_objects_to_read(self): 26 | objects_to_read = [] 27 | 28 | for section in ('attributes', 'timeseries'): 29 | section_config = self.__config.get(section, []) 30 | 31 | if section_config != '*': 32 | for item in section_config: 33 | object_to_read = {**item, 'type': section} 34 | 35 | if item['objectType'] == 'device': 36 | object_to_read['objectId'] = self.device_details.object_id 37 | 38 | objects_to_read.append(object_to_read) 39 | 40 | return objects_to_read 41 | 42 | @property 43 | def objects_to_read(self): 44 | return self.__objects_to_read 45 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/ble/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/ble/ble_uplink_converter.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from thingsboard_gateway.connectors.converter import Converter, abstractmethod 16 | 17 | 18 | class BLEUplinkConverter(Converter): 19 | 20 | @abstractmethod 21 | def convert(self, config, data): 22 | pass 23 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/ble/error_handler.py: -------------------------------------------------------------------------------- 1 | class ErrorHandler: 2 | def __init__(self, e): 3 | self.e = e 4 | 5 | def is_char_not_found(self): 6 | try: 7 | if "could not be found!" in self.e.args[0]: 8 | return True 9 | except IndexError: 10 | return False 11 | 12 | return False 13 | 14 | def is_operation_not_supported(self): 15 | try: 16 | if 'not permitted' in self.e.args[1] or 'not supported' in self.e.args[1]: 17 | return True 18 | except IndexError: 19 | return False 20 | 21 | return False 22 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/can/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/can/can_converter.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from thingsboard_gateway.connectors.converter import ABC, abstractmethod 16 | 17 | 18 | class CanConverter(ABC): 19 | @abstractmethod 20 | def convert(self, config, data): 21 | pass 22 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/connector.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from abc import ABC, abstractmethod 16 | 17 | 18 | class Connector(ABC): 19 | 20 | @abstractmethod 21 | def open(self): 22 | pass 23 | 24 | @abstractmethod 25 | def close(self): 26 | pass 27 | 28 | @abstractmethod 29 | def get_id(self): 30 | pass 31 | 32 | @abstractmethod 33 | def get_name(self): 34 | pass 35 | 36 | @abstractmethod 37 | def get_type(self): 38 | pass 39 | 40 | @abstractmethod 41 | def get_config(self): 42 | pass 43 | 44 | @abstractmethod 45 | def is_connected(self): 46 | pass 47 | 48 | @abstractmethod 49 | def is_stopped(self): 50 | pass 51 | 52 | @abstractmethod 53 | def on_attributes_update(self, content): 54 | pass 55 | 56 | @abstractmethod 57 | def server_side_rpc_handler(self, content): 58 | pass 59 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/converter.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from abc import ABC, abstractmethod 16 | from typing import Union 17 | 18 | from thingsboard_gateway.gateway.entities.converted_data import ConvertedData 19 | 20 | 21 | class Converter(ABC): 22 | 23 | @abstractmethod 24 | def convert(self, config, data) -> Union[dict, ConvertedData]: 25 | pass 26 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/ftp/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/ftp/ftp_converter.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from thingsboard_gateway.connectors.converter import Converter, abstractmethod 16 | 17 | 18 | class FTPConverter(Converter): 19 | @abstractmethod 20 | def convert(self, config, data): 21 | pass 22 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/knx/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/knx/entities/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/knx/knx_converter.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from thingsboard_gateway.connectors.converter import Converter, abstractmethod 16 | 17 | 18 | class KNXConverter(Converter): 19 | @abstractmethod 20 | def convert(self, data): 21 | pass 22 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/modbus/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/thingsboard_gateway/connectors/modbus/__init__.py -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/modbus/entities/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/thingsboard_gateway/connectors/modbus/entities/__init__.py -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/modbus/entities/bytes_downlink_converter_config.py: -------------------------------------------------------------------------------- 1 | from pymodbus.constants import Endian 2 | 3 | 4 | class BytesDownlinkConverterConfig: 5 | def __init__(self, device_name, byte_order, word_order, repack, objects_count, function_code, lower_type, address): 6 | self.device_name = device_name 7 | self.byte_order = Endian.Big if byte_order.upper() == "BIG" else Endian.Little 8 | self.word_order = Endian.Big if word_order.upper() == "BIG" else Endian.Little 9 | self.repack = repack 10 | self.objects_count = objects_count 11 | self.function_code = function_code 12 | self.lower_type = lower_type.lower() 13 | self.address = address 14 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/modbus/entities/bytes_uplink_converter_config.py: -------------------------------------------------------------------------------- 1 | from pymodbus.constants import Endian 2 | 3 | 4 | class BytesUplinkConverterConfig: 5 | def __init__(self, **kwargs): 6 | self.report_strategy = kwargs.get('reportStrategy') 7 | self.device_name = kwargs['deviceName'] 8 | self.device_type = kwargs.get('deviceType', 'default') 9 | self.byte_order = Endian.Big if kwargs.get('byteOrder', 'LITTLE').upper() == "BIG" else Endian.Little 10 | self.word_order = Endian.Big if kwargs.get('wordOrder', 'LITTLE').upper() == "BIG" else Endian.Little 11 | self.telemetry = kwargs.get('timeseries', []) 12 | self.attributes = kwargs.get('attributes', []) 13 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/modbus/modbus_converter.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from thingsboard_gateway.connectors.converter import Converter, abstractmethod 16 | 17 | 18 | class ModbusConverter(Converter): 19 | @abstractmethod 20 | def convert(self, config, data): 21 | pass 22 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/mqtt/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/mqtt/mqtt_decorators.py: -------------------------------------------------------------------------------- 1 | from thingsboard_gateway.gateway.statistics.decorators import CollectStatistics 2 | 3 | 4 | class CustomCollectStatistics(CollectStatistics): 5 | def __call__(self, func): 6 | def inner(*args, **kwargs): 7 | try: 8 | _, __, data, ___ = args 9 | self.collect(self.start_stat_type, data) 10 | except ValueError: 11 | pass 12 | 13 | return func(*args, **kwargs) 14 | 15 | return inner 16 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/mqtt/mqtt_uplink_converter.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from thingsboard_gateway.connectors.converter import Converter, abstractmethod 16 | 17 | 18 | class MqttUplinkConverter(Converter): 19 | 20 | @abstractmethod 21 | def convert(self, config, data): 22 | pass 23 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/ocpp/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/ocpp/ocpp_converter.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from thingsboard_gateway.connectors.converter import Converter, abstractmethod 16 | 17 | 18 | class OcppConverter(Converter): 19 | @abstractmethod 20 | def convert(self, config, data): 21 | pass 22 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/odbc/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/odbc/odbc_converter.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from thingsboard_gateway.connectors.converter import ABC, abstractmethod 16 | 17 | 18 | class OdbcConverter(ABC): 19 | @abstractmethod 20 | def convert(self, config, data): 21 | pass 22 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/opcua/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/thingsboard_gateway/connectors/opcua/__init__.py -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/opcua/opcua_converter.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from typing import Union 16 | 17 | from thingsboard_gateway.connectors.converter import Converter, abstractmethod 18 | from thingsboard_gateway.gateway.entities.converted_data import ConvertedData 19 | 20 | 21 | class OpcUaConverter(Converter): 22 | @abstractmethod 23 | def convert(self, config, val) -> Union[dict, ConvertedData]: 24 | pass 25 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/request/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/request/request_converter.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from thingsboard_gateway.connectors.converter import Converter, abstractmethod 16 | 17 | 18 | class RequestConverter(Converter): 19 | @abstractmethod 20 | def convert(self, config, data): 21 | pass 22 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/request/request_uplink_converter.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from thingsboard_gateway.connectors.converter import Converter, abstractmethod 16 | 17 | 18 | class RequestUplinkConverter(Converter): 19 | 20 | @abstractmethod 21 | def convert(self, config, data): 22 | pass 23 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/rest/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/rest/rest_converter.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from thingsboard_gateway.connectors.converter import Converter 16 | 17 | 18 | class RESTConverter(Converter): 19 | 20 | def convert(self, config, data): 21 | pass 22 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/snmp/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/snmp/snmp_downlink_converter.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from thingsboard_gateway.connectors.converter import Converter 16 | from thingsboard_gateway.gateway.statistics.decorators import CollectStatistics 17 | 18 | 19 | class SNMPDownlinkConverter(Converter): 20 | def __init__(self, config): 21 | self.__config = config 22 | 23 | @CollectStatistics(start_stat_type='allReceivedBytesFromTB', 24 | end_stat_type='allBytesSentToDevices') 25 | def convert(self, config, data): 26 | return data["params"] 27 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/socket/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/socket/backward_compatibility_adapter.py: -------------------------------------------------------------------------------- 1 | from copy import deepcopy 2 | 3 | 4 | class BackwardCompatibilityAdapter: 5 | def __init__(self, config): 6 | self._config = deepcopy(config) 7 | 8 | @staticmethod 9 | def is_old_config(config): 10 | return config.get('socket') is None 11 | 12 | def convert(self): 13 | socket_type = self._config.pop('type', 'TCP') 14 | address = self._config.pop('address', '127.0.0.1') 15 | port = self._config.pop('port', 50000) 16 | buffer_size = self._config.pop('bufferSize', 1024) 17 | 18 | self._config['socket'] = { 19 | 'type': socket_type, 20 | 'address': address, 21 | 'port': port, 22 | 'bufferSize': buffer_size 23 | } 24 | 25 | for device in self._config.get('devices', []): 26 | if device.get('addressFilter'): 27 | address_filter = device.pop('addressFilter') 28 | device['address'] = address_filter 29 | 30 | for attribute_requests in device.get('attributeRequests', []): 31 | attribute_requests['requestExpressionSource'] = 'expression' 32 | attribute_requests['attributeNameExpressionSource'] = 'expression' 33 | 34 | return self._config 35 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/socket/socket_decorators.py: -------------------------------------------------------------------------------- 1 | from thingsboard_gateway.gateway.statistics.decorators import CollectStatistics 2 | 3 | 4 | class CustomCollectStatistics(CollectStatistics): 5 | def __call__(self, func): 6 | def inner(*args, **kwargs): 7 | try: 8 | _, __, ___, data = args 9 | self.collect(self.start_stat_type, data) 10 | except ValueError: 11 | pass 12 | 13 | return func(*args, **kwargs) 14 | 15 | return inner 16 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/socket/socket_uplink_converter.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from thingsboard_gateway.connectors.converter import Converter, abstractmethod 16 | 17 | 18 | class SocketUplinkConverter(Converter): 19 | 20 | @abstractmethod 21 | def convert(self, config, data): 22 | pass 23 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/xmpp/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/xmpp/device.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | from typing import List 3 | 4 | 5 | @dataclass 6 | class Device: 7 | jid: str 8 | device_name_expression: str 9 | device_type_expression: str 10 | attributes: List 11 | timeseries: List 12 | attribute_updates: List 13 | server_side_rpc: List 14 | converter = None 15 | 16 | def set_converter(self, converter): 17 | self.converter = converter 18 | -------------------------------------------------------------------------------- /thingsboard_gateway/connectors/xmpp/xmpp_converter.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from thingsboard_gateway.connectors.converter import Converter, abstractmethod 16 | 17 | 18 | class XmppConverter(Converter): 19 | @abstractmethod 20 | def convert(self, config, val): 21 | pass 22 | -------------------------------------------------------------------------------- /thingsboard_gateway/extensions/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /thingsboard_gateway/extensions/bacnet/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/thingsboard_gateway/extensions/bacnet/__init__.py -------------------------------------------------------------------------------- /thingsboard_gateway/extensions/bacnet_old/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /thingsboard_gateway/extensions/ble/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /thingsboard_gateway/extensions/can/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /thingsboard_gateway/extensions/ftp/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/thingsboard_gateway/extensions/ftp/__init__.py -------------------------------------------------------------------------------- /thingsboard_gateway/extensions/knx/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /thingsboard_gateway/extensions/modbus/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /thingsboard_gateway/extensions/modbus_old/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/thingsboard_gateway/extensions/modbus_old/__init__.py -------------------------------------------------------------------------------- /thingsboard_gateway/extensions/mqtt/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /thingsboard_gateway/extensions/ocpp/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /thingsboard_gateway/extensions/odbc/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /thingsboard_gateway/extensions/opcua/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /thingsboard_gateway/extensions/request/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /thingsboard_gateway/extensions/rest/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /thingsboard_gateway/extensions/serial/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /thingsboard_gateway/extensions/snmp/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | -------------------------------------------------------------------------------- /thingsboard_gateway/extensions/socket/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /thingsboard_gateway/extensions/xmpp/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /thingsboard_gateway/gateway/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /thingsboard_gateway/gateway/constant_enums.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from enum import Enum 16 | 17 | 18 | class DeviceActions(Enum): 19 | UNKNOWN = 0, 20 | CONNECT = 1, 21 | DISCONNECT = 2 22 | 23 | 24 | class DownlinkMessageType(Enum): 25 | Response = 0, 26 | ConnectorConfigurationMsg = 1, 27 | GatewayAttributeUpdateNotificationMsg = 2, 28 | GatewayAttributeResponseMsg = 3, 29 | GatewayDeviceRpcRequestMsg = 4, 30 | UnregisterConnectorMsg = 5, 31 | ConnectorGetConnectedDevicesResponseMsg = 6 32 | 33 | 34 | class Status(Enum): 35 | FAILURE = 1, 36 | NOT_FOUND = 2, 37 | SUCCESS = 3, 38 | NO_NEW_DATA = 4 39 | FORBIDDEN_DEVICE = 5 40 | -------------------------------------------------------------------------------- /thingsboard_gateway/gateway/device_filter.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | import simplejson 4 | 5 | 6 | class DeviceFilter: 7 | def __init__(self, config_path): 8 | self._config_path = config_path 9 | self._config = self._load_config() 10 | 11 | def _load_config(self): 12 | if self._config_path: 13 | with open(self._config_path, 'r') as file: 14 | return simplejson.load(file) 15 | 16 | return {'deny': {}, 'allow': {}} 17 | 18 | def validate_device(self, connector_name, data): 19 | for con_name, device_list in self._config['deny'].items(): 20 | if con_name == connector_name: 21 | for device in device_list: 22 | if re.fullmatch(device, data['deviceName']): 23 | return False 24 | 25 | for con_name, device_list in self._config['allow'].items(): 26 | if con_name == connector_name: 27 | for device in device_list: 28 | if re.fullmatch(device, data['deviceName']): 29 | return True 30 | 31 | return True 32 | -------------------------------------------------------------------------------- /thingsboard_gateway/gateway/entities/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/thingsboard_gateway/gateway/entities/__init__.py -------------------------------------------------------------------------------- /thingsboard_gateway/gateway/entities/attributes.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from typing import Dict, Any, Union 16 | 17 | from thingsboard_gateway.gateway.entities.datapoint_key import DatapointKey 18 | 19 | 20 | class Attributes: 21 | def __init__(self, values: Dict[DatapointKey, Any] = None): 22 | self.values: Dict[DatapointKey, Any] = values or {} 23 | 24 | def __str__(self): 25 | return f"Attributes(values={self.values})" 26 | 27 | def __hash__(self): 28 | return hash(tuple(self.values.items())) 29 | 30 | def to_dict(self) -> Dict[str, Any]: 31 | return {key.key if isinstance(key, DatapointKey) else key: value for key, value in self.values.items()} 32 | 33 | def __getitem__(self, item: DatapointKey) -> Any: 34 | return self.values[item] 35 | 36 | def __iter__(self): 37 | return iter(self.values) 38 | 39 | def __setitem__(self, key: DatapointKey, value): 40 | self.values[key] = value 41 | 42 | def __len__(self): 43 | return len(self.values) 44 | 45 | def update(self, attributes: Union[Dict[DatapointKey, Any], 'Attributes']): 46 | self.values.update(attributes if isinstance(attributes, dict) else attributes.values) 47 | 48 | def items(self): 49 | return self.values.items() 50 | -------------------------------------------------------------------------------- /thingsboard_gateway/gateway/entities/datapoint_key.py: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------ 2 | # Copyright 2025. ThingsBoard 3 | # # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # ------------------------------------------------------------------------------ 17 | 18 | from thingsboard_gateway.gateway.entities.report_strategy_config import ReportStrategyConfig 19 | 20 | 21 | class DatapointKey: 22 | def __init__(self, key, report_strategy: ReportStrategyConfig = None): 23 | self.key = key 24 | self.report_strategy = report_strategy 25 | 26 | def __str__(self): 27 | return f"DatapointKey(key={self.key}, report_strategy={self.report_strategy})" 28 | 29 | def __repr__(self): 30 | return self.__str__() 31 | 32 | def __hash__(self): 33 | return hash((self.key, self.report_strategy)) 34 | 35 | def __eq__(self, other): 36 | if isinstance(other, DatapointKey): 37 | return self.key == other.key and self.report_strategy == other.report_strategy 38 | return False 39 | -------------------------------------------------------------------------------- /thingsboard_gateway/gateway/entities/device_event_pack.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/thingsboard_gateway/gateway/entities/device_event_pack.py -------------------------------------------------------------------------------- /thingsboard_gateway/gateway/grpc_service/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/thingsboard_gateway/gateway/grpc_service/__init__.py -------------------------------------------------------------------------------- /thingsboard_gateway/gateway/proto/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Use the following command to generate python code from proto file; 16 | 17 | #$ python3 -m grpc_tools.protoc -Ithingsboard_gateway/gateway/proto --python_out=thingsboard_gateway/gateway/proto/ --grpc_python_out=thingsboard_gateway/gateway/proto/ thingsboard_gateway/gateway/proto/messages.proto 18 | 19 | # Update file messages_pb2_grpc.py: 20 | 21 | # Replace: 22 | # import messages_pb2 as messages__pb2 23 | # With: 24 | # import thingsboard_gateway.gateway.proto.messages_pb2 as messages__pb2 25 | -------------------------------------------------------------------------------- /thingsboard_gateway/gateway/report_strategy/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/thingsboard_gateway/gateway/report_strategy/__init__.py -------------------------------------------------------------------------------- /thingsboard_gateway/gateway/shell/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/thingsboard_gateway/gateway/shell/__init__.py -------------------------------------------------------------------------------- /thingsboard_gateway/gateway/statistics/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /thingsboard_gateway/grpc_connectors/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/thingsboard_gateway/grpc_connectors/__init__.py -------------------------------------------------------------------------------- /thingsboard_gateway/grpc_connectors/modbus/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /thingsboard_gateway/grpc_connectors/mqtt/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /thingsboard_gateway/grpc_connectors/opcua/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /thingsboard_gateway/grpc_connectors/socket/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/thingsboard_gateway/grpc_connectors/socket/__init__.py -------------------------------------------------------------------------------- /thingsboard_gateway/storage/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /thingsboard_gateway/storage/event_storage.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from abc import ABC, abstractmethod 16 | 17 | 18 | class EventStorage(ABC): 19 | 20 | def __init__(self, config, logger, main_stop_event): 21 | self._config = config 22 | self._main_stop_event = main_stop_event 23 | 24 | @abstractmethod 25 | def put(self, event): 26 | pass 27 | 28 | @abstractmethod 29 | def get_event_pack(self): 30 | # Returns events from pack 31 | pass 32 | 33 | @abstractmethod 34 | def event_pack_processing_done(self): 35 | # Indicates that events from previous "get_event_pack" may be cleared 36 | pass 37 | 38 | @abstractmethod 39 | def stop(self): 40 | # Stop the storage processing 41 | pass 42 | 43 | @abstractmethod 44 | def len(self): 45 | pass 46 | 47 | @abstractmethod 48 | def update_logger(self): 49 | pass 50 | 51 | def get_configuration(self): 52 | return self._config 53 | -------------------------------------------------------------------------------- /thingsboard_gateway/storage/file/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/thingsboard_gateway/storage/file/__init__.py -------------------------------------------------------------------------------- /thingsboard_gateway/storage/file/event_storage_files.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from threading import RLock 16 | from typing import Dict 17 | 18 | 19 | class EventStorageFiles: 20 | def __init__(self, state_file, data_files: Dict[str, bool]): 21 | self.state_file = state_file 22 | self.data_files = data_files 23 | self.__data_files_lock = RLock() 24 | 25 | def get_state_file(self): 26 | return self.state_file 27 | 28 | def get_data_files(self): 29 | with self.__data_files_lock: 30 | return sorted(self.data_files.keys()) 31 | 32 | def add_data_file(self, data_file): 33 | with self.__data_files_lock: 34 | self.data_files[data_file] = False 35 | 36 | def remove_data_file(self, data_file): 37 | with self.__data_files_lock: 38 | del self.data_files[data_file] 39 | 40 | def confirm_file_processed(self, data_file): 41 | with self.__data_files_lock: 42 | self.data_files[data_file] = True 43 | -------------------------------------------------------------------------------- /thingsboard_gateway/storage/file/event_storage_reader_pointer.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | 16 | class EventStorageReaderPointer: 17 | def __init__(self, file, line): 18 | self.file = file 19 | self.line = line 20 | 21 | def __eq__(self, other): 22 | return self.file == other.file and self.line == other.line 23 | 24 | def __hash__(self): 25 | return hash((self.file, self.line)) 26 | 27 | def get_file(self): 28 | return self.file 29 | 30 | def get_line(self): 31 | return self.line 32 | 33 | def set_file(self, file): 34 | self.file = file 35 | 36 | def set_line(self, line): 37 | self.line = line 38 | -------------------------------------------------------------------------------- /thingsboard_gateway/storage/file/file_event_storage_settings.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | 16 | class FileEventStorageSettings: 17 | def __init__(self, config): 18 | self.data_folder_path = config.get("data_folder_path", "./") 19 | self.max_files_count = config.get("max_file_count", 5) 20 | self.max_records_per_file = config.get("max_records_per_file", 3) 21 | self.max_records_between_fsync = config.get("max_records_between_fsync", 1) 22 | self.max_read_records_count = config.get("max_read_records_count", 1000) 23 | 24 | def get_data_folder_path(self): 25 | return self.data_folder_path 26 | 27 | def get_max_files_count(self): 28 | return self.max_files_count 29 | 30 | def get_max_records_per_file(self): 31 | return self.max_records_per_file 32 | 33 | def get_max_records_between_fsync(self): 34 | return self.max_records_between_fsync 35 | 36 | def get_max_read_records_count(self): 37 | return self.max_read_records_count 38 | -------------------------------------------------------------------------------- /thingsboard_gateway/storage/memory/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/thingsboard_gateway/storage/memory/__init__.py -------------------------------------------------------------------------------- /thingsboard_gateway/storage/sqlite/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thingsboard/thingsboard-gateway/af960236f66ee9dadc13c43532168abc90adb40c/thingsboard_gateway/storage/sqlite/__init__.py -------------------------------------------------------------------------------- /thingsboard_gateway/storage/sqlite/storage_settings.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | class StorageSettings: 16 | def __init__(self, config): 17 | self.data_folder_path = config.get("data_file_path", "./") 18 | self.messages_ttl_check_in_hours = config.get('messages_ttl_check_in_hours', 1) * 3600 19 | self.messages_ttl_in_days = config.get('messages_ttl_in_days', 7) 20 | self.max_read_records_count = config.get('max_read_records_count', 1000) 21 | self.batch_size = config.get('writing_batch_size', 1000) 22 | -------------------------------------------------------------------------------- /thingsboard_gateway/tb_utility/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /thingsboard_gateway/version.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025. ThingsBoard 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | VERSION = "3.7.4" 16 | --------------------------------------------------------------------------------