MQTT Application Overview
The WIZio-SEN MQTT application initializes the board hardware, configures the WIZnet Ethernet interface, connects to the MQTT broker, subscribes to the registered command topics, publishes the initial device state, and then starts its polling loop.
Board boots
|
v
Initialize hardware and Ethernet
|
v
Load mqtt.json
|
v
Connect to MQTT broker
|
v
Subscribe to command topics
|
v
Publish initial states
|
v
Poll hardware and process MQTT messages
The MQTT loop performs:
self.poll()
self.check_msg()
time.sleep_ms(100)
The device therefore checks peripherals and incoming MQTT messages approximately every 100 ms, excluding processing and network time.
Network and Broker Configuration
The Ethernet interface is initialized by setup.py using the WIZnet network interface with these pins:
Signal |
Pin |
|---|---|
SPI bus |
|
SPI baud rate |
|
CS |
|
RST |
|
PWR / enable |
|
The supplied config.py enables DHCP:
DHCP = True
If DHCP is disabled or fails, the fallback static configuration in setup.py is:
Field |
Default value |
|---|---|
IP address |
|
Subnet mask |
|
Gateway |
|
DNS |
|
MQTT broker settings are loaded from mqtt.json:
{
"host": "10.0.1.238",
"username": null,
"password": null,
"port": 1883
}
To create mqtt.json, copy mqtt.default.json and enter the broker address and authentication settings for your network.
If a value is missing, device_mqtt.py uses these fallbacks:
Field |
Fallback value |
|---|---|
Host |
|
Username |
|
Password |
|
Port |
|
The MQTT client ID is generated from the WIZnet chip MAC address. If umqtt.simple is unavailable, the application attempts to install it into /flash using mip after the network is connected.
MQTT Topic Summary
The application uses command topics for requests received by the device and state or response topics for data published by the device.
Subscribed command topics
Topic |
Payload |
Description |
|---|---|---|
|
JSON |
Changes the Ethernet configuration. |
|
JSON |
Changes one relay output. |
|
JSON |
Handler exists, but no analog-output channels are configured by default. |
|
UTF-8 data |
Sends data through the RS485/UART interface. |
|
UTF-8 data |
Writes data to EEPROM at index |
|
JSON |
Requests EEPROM data from an index. |
|
Text |
Wipes EEPROM when the payload is exactly |
Published state and response topics
Topic |
Payload |
Description |
|---|---|---|
|
JSON |
Current Ethernet configuration. |
|
JSON |
Current digital input value for |
|
JSON |
Resulting relay output value for |
|
JSON |
Analog values and input modes for |
|
JSON |
Reports |
|
UTF-8 data |
Data received from the RS485/UART interface. |
|
Raw bytes |
EEPROM data returned after a read request. |
|
Text number |
Averaged load-cell weight in kilograms. |
|
Text number |
Optional K-type channel 1 temperature in degrees Celsius. |
|
Text number |
Optional K-type channel 2 temperature in degrees Celsius. |
Topics are registered with the add_topic() decorator. The current wildcard dispatcher gives the captured pin to handlers for digital_output/+/set and analog_output/+/set:
@client.add_topic("digital_output/+/set")
def handle_digital_output(pin, msg):
pass
For normal topics, the handler receives only the payload:
@client.add_topic("uart/write")
def write_to_uart(msg):
pass
Initial State and Retained Messages
After connecting, the device publishes:
Current network configuration.
Both digital input states.
Both relay output states.
The analog input state.
Initial analog-output states if analog-output channels are configured.
The selected serial mode.
The general publish() helper uses retain=True, so state messages published through that helper are retained by the broker. This includes topics such as:
network_config/state
digital_input/IN1/state
digital_output/RY1/state
analog_input/state
serial_mode
loadcell/weight
temp/k1
temp/k2
UART receive data is published directly through umqtt.simple and is not explicitly retained. Command topics should normally not be retained because a retained command may be delivered again when the device reconnects.
Network Configuration Topics
Read the current network state
The device publishes its current Ethernet configuration to:
network_config/state
Example payload:
{
"ip": "192.168.1.50",
"mask": "255.255.255.0",
"gateway": "192.168.1.1",
"dns": "192.168.1.1",
"dhcp": false
}
Change the network configuration
Publish to:
network_config/set
Use DHCP:
{
"dhcp": true
}
Use a static address:
{
"dhcp": false,
"ip": "192.168.1.50",
"mask": "255.255.255.0",
"gateway": "192.168.1.1",
"dns": "192.168.1.1"
}
The handler validates each IPv4 address, disconnects MQTT, reinitializes the WIZnet interface, sets the restart flag, and reconnects using the new network settings.
Digital I/O Topics
The supplied device configuration supports:
Type |
Names |
|---|---|
Digital inputs |
|
Relay outputs |
|
Set a relay output
Topic pattern:
digital_output/<pin>/set
Example:
digital_output/RY1/set
Payload:
{
"value": 1
}
Use 0 to turn the relay off. If value is missing, the handler uses 0. The resulting state is published to:
digital_output/RY1/state
Monitor digital inputs
Digital inputs are published to:
digital_input/<pin>/state
Example payload:
{
"value": 1
}
The device publishes a new input message only when the physical input value changes. The MQTT layer publishes the physical pin value without inverting active-low inputs.
Analog Input Topics
The supplied device configuration supports two analog inputs:
Input |
Mode |
Unit |
|---|---|---|
|
Current |
mA |
|
Current |
mA |
The mode values are:
Value |
Meaning |
|---|---|
|
Voltage mode |
|
Current mode |
All analog inputs are published together on:
analog_input/state
Example payload:
{
"AI0": {
"value": 12.3,
"mode": 1
},
"AI1": {
"value": 11.8,
"mode": 1
}
}
The application collects ten readings before publishing an average. Current-mode readings are calculated with:
current_ma = (voltage / 120) * 1000
Voltage-mode readings are calculated with:
input_voltage = (voltage * 14.7) / 4.7
Reported values are limited to 20 mA in current mode and 10 V in voltage mode.
The MQTT handler includes analog_output/+/set, but MAX_AO is 0 in device.py, so the supplied WIZio-SEN application has no analog-output channels by default.
Serial UART Topics
device.py initializes UART4 from config.py. The supplied config.py contains:
Field |
Value |
|---|---|
Baud rate |
|
Data bits |
|
Parity |
|
Stop bits |
|
The selected interface is reported during startup on:
serial_mode
Example payload:
{
"Mode": "RS485"
}
Send UART data
Publish UTF-8 data to:
uart/write
Example:
hello from MQTT
Receive UART data
Data received from UART4 is published to:
uart/read
The device reads available bytes during each polling cycle and decodes them as UTF-8 with replacement characters when necessary.
EEPROM Topics
The onboard EEPROM uses software I2C:
Signal |
Pin |
|---|---|
SCL |
|
SDA |
|
The EEPROM driver is initialized when the expected EEPROM addresses are detected. Each read and write is limited to 1000 bytes.
Write data
Publish UTF-8 data to:
eeprom/write
Example:
board-name=WIZio-SEN
The supplied handler writes at index 0.
Read data
Publish a JSON request to:
eeprom/read/request
Payload:
{
"index": 0
}
If index is missing, the handler uses 0. The result is published as raw bytes to:
eeprom/read/response
Wipe data
Publish to:
eeprom/wipe
Required payload:
True
The comparison is case-sensitive.
Warning
Wiping the EEPROM removes its stored contents and normally cannot be undone.
Load-Cell Topic
Load-cell support is enabled by the supplied configuration:
LOADCELL_CAPACITY_KG = 10.0
LOADCELL_RATED_OUTPUT = 2.0
The application expects a 10 kg, 2 mV/V load cell with 10 V excitation. Update these values in config.py for a different sensor.
The device averages load-cell readings and publishes the result in kilograms to:
loadcell/weight
Thermocouple Topics
The runtime contains non-blocking CS1237/CS1238 support for two K-type channels. When the temperature settings are defined in config.py, the device publishes readings to:
temp/k1
temp/k2
The readings are published in degrees Celsius after cold-junction compensation.
The supplied config.py does not define CELSIUS_MIN, CELSIUS_MAX, or CELSIUS_PGA, so thermocouple support is disabled in the supplied configuration.
Runtime, Restart, and Error Behavior
When the network configuration changes, the application:
Disconnects from MQTT.
Reinitializes Ethernet.
Sets
client.restart = True.Exits the current MQTT loop.
Starts the MQTT runtime again.
Common behavior:
Situation |
Behavior |
|---|---|
MQTT connection fails |
The MQTT run raises a connection error and disconnects. |
Unknown topic is received |
The message is ignored. |
Invalid JSON command payload |
The handler returns without applying the command. |
Invalid relay pin |
The device reports an error and returns |
EEPROM is unavailable |
EEPROM operations cannot complete. |
Runtime exception |
The error is printed, MQTT disconnects, and the application exits. |
|
MQTT disconnects and the application exits. |
Debug output is controlled by:
DEBUG = True
Set it to False to disable dprint() output.
Customizing the MQTT Application
Edit mqtt_app.py to add, remove, or change subscribed command topics and their handlers.
Example:
@client.add_topic("custom/topic")
def handle_custom_topic(msg):
print("Received:", msg)
Use device_mqtt.py only when changing lower-level behavior such as MQTT connection handling, subscription dispatch, polling intervals, automatic state publication, or retained-message behavior.
Use device.py when changing the underlying GPIO, ADC, UART, I2C, EEPROM, load-cell, or thermocouple behavior.
The main files have these responsibilities:
mqtt_app.pydefines subscribed command topics and their handlers.device_mqtt.pymanages the MQTT connection, subscriptions, polling, and published state topics.device.pyprovides the WIZio-SEN hardware functions.setup.pyinitializes the WIZnet Ethernet interface.mqtt.jsonstores the broker connection settings.main.pystarts the MQTT application.
Example Usage With Mosquitto
Replace 10.0.1.238 with your broker address.
Monitor all topics:
mosquitto_sub -h 10.0.1.238 -t "#" -v
Turn on RY1:
mosquitto_pub -h 10.0.1.238 \
-t "digital_output/RY1/set" \
-m '{"value":1}'
Monitor digital input states:
mosquitto_sub -h 10.0.1.238 \
-t "digital_input/+/state" -v
Monitor analog inputs:
mosquitto_sub -h 10.0.1.238 \
-t "analog_input/state" -v
Send RS485 data:
mosquitto_pub -h 10.0.1.238 \
-t "uart/write" \
-m "hello"
Write EEPROM data:
mosquitto_pub -h 10.0.1.238 \
-t "eeprom/write" \
-m "hello from WIZio-SEN"
Request EEPROM data:
mosquitto_pub -h 10.0.1.238 \
-t "eeprom/read/request" \
-m '{"index":0}'
Request DHCP:
mosquitto_pub -h 10.0.1.238 \
-t "network_config/set" \
-m '{"dhcp":true}'