Complete Modbus, MQTT/SQL, and Rule Engine Demo
This demo starts with a standard Modbus TCP variable, sequentially completing real-time collection, MQTT forwarding, SQLite historical data forwarding, and rule engine threshold checks, verifying the actual results of each segment of the link.
This page has channel type TcpClient, GatewayRuntime actively connects to Modbus TCP slave. The device plug-in DTU ID remains empty, without TCP server listening, DTU registration, or DTU ID connection assignment. For DTU access, please refer to DTU Service.
Actual Verification Environment
The screenshots on this page come from a real-time local debugging environment, not an empty form schematic. The test slave alternately returns values between 950 and 1234 per second to simultaneously verify the threshold's untriggered and triggered states.
| Project | Actual configuration on this page | Verification Objective |
|---|---|---|
| Modbus TCP Slave | 127.0.0.1:15030 | Receives the real Modbus request from GatewayRuntime and returns 950, 1234 |
| Channels | Demo_Modbus_Channel, TcpClient | GatewayRuntime Actively connects slave |
| device | Demo_Modbus_Device, ModbusMaster | Execute collection every 1000 ms Execute collection |
| variables | Demo_Modbus_Value,400001, Int16 | Refresh the true collected values online |
| MQTT Broker | 127.0.0.1:18885 | Receive topic thingsgateway/demo/modbus Release messages |
| SQLite | normal_full_demo.sqlite | Write real history records in historyNumberValue |
| Rule flow | Demo_Modbus_Rule | Judgment Demo_Modbus_Value > 1000 |
| Rule Action | http://127.0.0.1:17502/rule | Receives actual Webhook requests generated by the rule engine. |
127.0.0.1 Only applicable to demo environments where GatewayRuntime, simulated slaves, MQTT Broker, and authentication services are on the same computer. Production deployments must be replaced with IP addresses, ports, and database paths accessible to field devices or servers.
1. Generate Regular Modbus Test Data
Log in to GatewayRuntime Web, go to "Development Configuration → Collection Configuration," and click "Show more → test data" at the top right of the variable list.
- Select "Regular Test Data"; do not select "DTU Test Data".
- Set the number of variables to
1, and the number of devices to1. - Fill in the slave station address
127.0.0.1:15030. - Click "Generate" to create a set of standard Modbus TCP channels, devices, and variables.

After generation, you can directly edit the automatically created object. This demo resets object names to Demo_Modbus_Channel,Demo_Modbus_Device, and Demo_Modbus_Value to facilitate accurate references in forwarding and rule flows.
2. Configuring TCP Client Channels
Go to "Collection Configuration → Channel Management" and edit Demo_Modbus_Channel.
| Configuration Item | Instance Value on This Page | Description |
|---|---|---|
| Channel Name | Demo_Modbus_Channel | Identify this link in collection, logging, and runtime |
| Channel type | TcpClient | GatewayRuntime actively connects to Modbus slave |
| Remote address | 127.0.0.1:15030 | IP and port of Modbus TCP slave |
| Connection timeout: | 3000 ms | Timeout value for establishing and connecting operations |
| Cache timeout: | 500 ms | Protocol data reading and cache window used by package |
| Maximum concurrency | 1 | Maintains Modbus request order to avoid abnormal slave concurrency handling |
| Heart rate | 60000 ms | This demo maintains default values |

The key feature of ordinary Modbus TCP collection is that the channel type is TcpClient and the "remote address" is entered. DTU mode typically uses TcpService listening addresses, with the DTU actively connecting to the gateway.
3. Configure ModbusMaster Device
Go to "Collection Configuration → Device Management" and edit Demo_Modbus_Device.
| Configuration Items | Instance Values on This Page | Description |
|---|---|---|
| Device Name | Demo_Modbus_Device | Forwarding groups and rule nodes filter devices by this name: |
| Device plugin | ModbusMaster | initiates read requests as Modbus masters |
| Associate channels | Demo_Modbus_Channel | Connect using the TCP client from the previous step |
| Execution interval | 1000 | Execute acquisition once per second |
| Enable | Enable | Save, then start device runtime |

Switch to "Plugin Properties" and confirm use of regular Modbus TCP:
| Configuration Items | Instance value on this page | Description |
|---|---|---|
| Modbus type | ModbusTcp | Use Modbus TCP packet |
| Default Station Number | 1 | Use this value when a variable is not specifically assigned Station Number |
| DTU ID | Empty | Ordinary TCP client acquisition does not fill in DTU ID |
| Read/write timeout | 3000 ms | Maximum waiting time for a single Modbus request to respond |
| Data parsing order | ABCD | Multi-register data adjusted byte order by field device |

4. Configure variables and verify acquisition
Return "Variable Display" and edit Demo_Modbus_Value.
| Configuration Items | Example Values on This Page | Description |
|---|---|---|
| Variable Names | Demo_Modbus_Value | Use the name uniformly in MQTT, SQLite, and rule engines |
| Associated device | Demo_Modbus_Device | ModbusMaster device assigned to the previous step |
| Variable address | 400001 | Preserve the first address of the register |
| Data type | Int16 | Retain register from a 16-bit parse value |
| Read and write permissions | Read and write | This demo maintains generation configuration; When only data is collected, set as read-only |
| RPC write | Enable | No direct dependencies for this read, forwarding, or rule verification |

After saving, return to the collection page and accept in the following order:
Demo_Modbus_Channelshows "Online 1/1".Demo_Modbus_DeviceShows green online status.- The current and original values of
Demo_Modbus_Valuefluctuate continuously between950and1234. - Collection time is continuously updated, error messages are empty.

Only after passing the collection status can the forwarding and rule engine be configured. Otherwise, even if subsequent targets appear online, there may be no forwardable data.
5. Create a Dual-Target Data Forwarding Group
Enter "Development Configuration → Data Forwarding" and add a new forwarding group Demo_Modbus_MQTT_SQL.
| Configuration Items | Example values on this page | Description |
|---|---|---|
| Variable range | Collection Device | Select forwarding variables from the collection device |
| Range configuration | Demo_Modbus_Device | Forwarding only this demo Device Data |
| Trigger Mode | Timer or Change | Immediate trigger for value changes, with timed trigger replenished every second |
| Fixed Time Interval | 1000 | Timed Trigger Interval is 1 second |
| Online Filter | Enable | Forward Only Online Variables |
| Batch Mode | No batch | Single-variable demo No need to batch |
| Maximum batch | 1000 | Maintain default limit |

After saving, confirm the forwarding group card shows 1 variable. This demo creates two independent targets within the same group; the online status, logs, and actual data of MQTT and SQLite must be accepted separately.
6. Create an MQTT Client Target
Select Demo_Modbus_MQTT_SQL, click Add in the "Forwarding Target" area, and choose MqttClientProducer.
| Configuration Items | Instance Values on This Page | Description |
|---|---|---|
| Target Name | Demo_MQTT_Target | Unique name of the MQTT target |
| IP address | 127.0.0.1 | local MQTT Broker |
| Port | 18885 | TCP port of this Demo Broker |
| Client ID | DemoGatewayRuntime | Broker to identify the GatewayRuntime client |
| MQTT protocol version | V311 | MQTT 3.1.1 |
| Connection Type | Tcp | Connection Using Ordinary MQTT TCP |
| QoS Level | AtMostOnce | This demo uses QoS 0 |
| detailed logs | Enable | joint debugging phase to facilitate connection and publishing processes |

Enter the "Variable Topic Template" as thingsgateway/demo/modbus. This page does not use device names, so all selected variables are posted to a fixed Demo Topic.

After saving, wait for the target card to display "Online". The message actually received by the broker includes the following key data:
[
{
"Name": "Demo_Modbus_Value",
"DeviceName": "Demo_Modbus_Device",
"Value": 1234,
"IsOnline": true,
"ChannelName": "Demo_Modbus_Channel",
"RegisterAddress": "400001",
"DataType": "Int16"
}
]
In the production environment, username, password, TLS certificate, QoS, message retention, and offline caching should be entered according to the Broker's security policy. Do not directly copy the server's unauthenticated parameters.
7. Create the SQLite Historical Data Target
C ontinue to add new targets in the same forwarding group, select HisDataForwardTarget, and choose Sqlite database type.
| Configuration Items | Instance Value on This Page | Description |
|---|---|---|
| Object Name | Demo_SQLite_Target | Unique Name of SQLite Target |
| Database Type | Sqlite | Validate with Local SQLite File SQL Forwarding |
| Concatenate string | Data Source=E:\tgall\src\.codex-runtime\gateway-full-demo-6125-20260729-01\normal_full_demo.sqlite | For this actual verification of the file path, the production environment must replace |
| numeric historical table_name | historyNumberValue | numeric variable written to the table |
| string historical table_name | historyStringValue | String variable written to the table |
| Time zone offset | +08:00 | Save according to current project time zone |
| Forced insert | Enable | Demo for continuous observation of new records |
| Default sampling strategy | Change | Generate history when variable changes |

Save and wait for Demo_SQLite_Target to display "Online". The actual historyNumberValue record written this time includes fields such as VariableId,DeviceName,VariableName,Value,CollectTime, IsOnline, and CreateTime.
When writing to MySQL, PostgreSQL, or SQL Server, still use the historical data target, switch the "database type," and fill in the corresponding connection string. Table names, sharding strategies, sampling strategies, and historical retention policies should be reconfirmed according to the project database specifications.
8. Separately Accept MQTT and SQLite Forwarding
Return to the data forwarding details page and confirm:
- The forwarded group shows
2 target,2 online,1 variable. Demo_MQTT_TargetandDemo_SQLite_Targetboth show "online."- The recent activity times of the repost group and two targets are continuously updated.

Target online only indicates the target runtime state is started and cannot replace result acceptance. This page also uses the real receiver and database queries to simultaneously check two types of results: the MQTT Topic shows Demo_Modbus_Value, and the SQLite historyNumberValue shows the actual value of the same variable.

| Check Item | Acceptance Criteria |
|---|---|
| Modbus Requests | The request count continues to increase, proving that GatewayRuntime is reading from the standard Modbus TCP slave. |
| MQTT message from a regular Modbus TCP slave | message count greater than 0, topic is thingsgateway/demo/modbus |
| MQTT content | contains Demo_Modbus_Value, Demo_Modbus_Device, and actual values 950 or 1234 |
| SQLite records | historyNumberValue Records continuously increasing |
| SQLite content | The most recent record VariableName is Demo_Modbus_Value , the value matches the value collected at the same time |
9. Configure the Rule Engine
Enter the "Development Configuration → Rule Engine" and create or open Process Demo_Modbus_Rule. This demo uses three nodes:
- "Variable notification rules" listen for changes in
Demo_Modbus_Value. - "Threshold trigger" checks whether the variable value is greater than
1000. - "Webhook push" sends the rule data to the local acceptance end.
The connection relationships are as follows:
| Start | End Point | Purpose |
|---|---|---|
Variable Notification Rules Result | Threshold Trigger Input | Send real-time values to threshold judgment |
Variable Notification Rules VariableBasicData | Webhook push Data | Send complete variable objects into rule actions |
MQTT and SQLite on this page are the two data forwarding targets in the "Data Forwarding" page. Webhooks are only used to demonstrate rule engine actions; they are not the data forwarding examples on this page, nor can they replace MQTT or SQL object acceptance.
Configure variable notification nodes
Select the "variable notification rule" node and fill in the following initial input parameters:
| parameters | instance value | description |
|---|---|---|
DeviceNames | Demo_Modbus_Device | only matches the demo collection device |
VariableNames | Demo_Modbus_Value | only matches the demo variable |
CollectGroups | Empty | No additional filtering by collection group |

Configure threshold nodes
Select the "threshold trigger" node and set:
| parameters | instance values | descriptions |
|---|---|---|
Threshold | 1000 | threshold |
Hysteresis | 0 | This demo does not use backlash |
CompareOperator | > | Triggered when input value exceeds 1000 |
When input is 1234, actual running value shows Triggered=true,RisingEdge=true; When the input restores to 950, it displays Triggered=false, FallingEdge=true.

Configure Rule Action Nodes
Select the "Webhook Push" node and fill in the following parameters:
| Parameter | Instance value | Description |
|---|---|---|
Url | http://127.0.0.1:17502/rule | Local rule acceptance service address |
Enabled | Enable | Enable rule action |
Data | Connect variable notification node VariableBasicData | Pass current variable object |
Request body template as follows:
{"source":"rule-engine","device":"{{DeviceName}}","variable":"{{Name}}","value":{{Value}}}
A t actual runtime, nodes show Success=true, ErrorMessage empty, and continuously update LastPushTime.

After saving and enabling the process, the complete canvas is as follows. Real-time parameters on nodes refresh following the Modbus values.

The actual execution result of the rule action under high value is as follows: input 1234, threshold check triggered, Webhook action returns successfully.

10. Complete Acceptance Checklist
Accept according to the sequence of the link, without skipping the prerequisites:
| Stage | Results that must be met |
|---|---|
| Ordinary Modbus channel | TcpClient online, remote address points to the real slave station, no DTU ID is filled in |
| Modbus device | ModbusMaster online, execution interval remains active |
| variable acquisition | Demo_Modbus_Value at 950. Refresh between 1234, collection time updated with no errors |
| MQTT target | target online, broker actually receives correct topic and variable JSON |
| SQLite target | target online, historyNumberValue Actual new record with correct value |
| rule low value | Enter 950, Triggered=false When the falling edge switches, FallingEdge=true |
| Rule high value | Enter 1234, Triggered=true, when the rising edge switches, RisingEdge=true |
| rule action | Success=true, ErrorMessage is empty, receiver receives /rule Request |
Production Environment Replacement Item
| Demo Configuration | Production Environment Requirements |
|---|---|
127.0.0.1:15030 | Replace with PLC, Instrument, Protocol Gateway, or Real Modbus TCP Slave Address |
Single Variable 400001 | Import all variables as formal point tables and verify address, data type, byte order, and read/write permissions |
MQTT 127.0.0.1:18885 | Replace with formal Broker, configure authentication, TLS, QoS, topic specifications, and offline caching |
| Local SQLite file | Select formal database, table structure, sharding, and retention policies based on capacity and query requirements |
Threshold 1000 | Set thresholds and tolerances according to process meaning, Edge triggering and anti-shake strategies |
| Replace native Webhook | with MES, alert platform, notification service, or other formal rule action addresses |
Troubleshooting
| Phenomena | Focus on checking |
|---|---|
| Channel offline | Test slave IP/port from GatewayRuntime host; Confirm the channel is TcpClient, remote address is not a bound address |
| Device online but variable abnormal | Verify station number, function code address format, data type, byte order, timeout, and slave return packet |
| No variables in the forwarding group | Confirm the variable range is "Collection Device," with the range configuration exactly matching the Demo_Modbus_Device name |
| MQTT target offline | Check Broker listening ports, client ID conflicts, authentication, TLS, Protocol version and target logs |
| MQTT online but no messages | Check forwarding group trigger patterns, online filtering, variable counts, and topic templates, and verify real subscriptions on the broker side |
| SQLite target offline | Check connection strings, directory write permissions, database types, and historical table names |
| SQLite online but no records | Check sampling policies, forced inserts, variable data types, and recent activity time of forwarding groups |
| No input on rule nodes | Check DeviceNames, VariableNames case and spaces to confirm variable changes |
| Thresholds never triggered | Check input lines, thresholds, comparators, value types, and real-time Input Value |
Webhook Success=false | Check URL, receiving service, request body template, network policy, and node ErrorMessage |
Related documentation
- Collection configuration - Complete instructions for channel, device, and variable operation
- Data forwarding - Forwarding groups, targets, logs, and debugging methods
- Rule engine - Nodes, connections Input/Output, and Process Operation Instructions
- Device Debugging - Protocol Read/Write and Variable Joint Debugging Methods
- DTU Service - Independent access method for DTU active connection to GatewayRuntime