Selsyn Gauge MQTT Controller
MQTT-based gauge controller for ESP32 / MicroPython. Drives a VID28/BKA30D/X25 stepper gauge and integrates with Home Assistant via MQTT.
Files
| File |
Description |
boot.py |
WiFi connect + OTA trigger |
ota.py |
Gitea API poller for OTA updates |
ota_config.json |
OTA config (create from ota_config.example.json) |
ota_config.example.json |
OTA config template |
gaugemqttcontinuous.py |
Main MQTT controller |
gauge_vid6008.py |
Stepper driver for VID28/BKA30D/X25 gauges |
main.py |
Entry point, calls ota.mark_ok() on success |
config.json |
Application config (create from config.example.json) |
config.example.json |
Template with all options |
Deployment
MQTT Topics
All topics are prefixed with mqtt_prefix:
| Topic |
Direction |
Description |
/set |
← |
Target value from HA |
/state |
→ |
Current value |
/status |
→ |
online/offline |
/zero |
← |
Trigger zero calibration |
/led/red/set |
← |
ON/OFF |
/led/red/state |
→ |
ON/OFF |
/led/green/set |
← |
ON/OFF |
/led/green/state |
→ |
ON/OFF |
/led/backlight/set |
← |
{"state": "ON"/"OFF", "color": {"r","g","b"}, "brightness": 0-255} |
/led/backlight/state |
→ |
Current backlight state |
Configuration
Copy config.example.json to config.json and ota_config.example.json to ota_config.json and edit:
WiFi
WiFi credentials are in ota_config.json (shared with OTA settings), not config.json.
MQTT
| Key |
Default |
Description |
mqtt_broker |
— |
Broker IP/hostname |
mqtt_port |
1883 |
Broker port |
mqtt_user |
— |
MQTT username |
mqtt_password |
— |
MQTT password |
mqtt_client_id |
— |
Unique client ID |
mqtt_prefix |
— |
Topic prefix for all MQTT messages |
Gauge
| Key |
Default |
Description |
gauge_pins |
[12, 13] |
GPIO pins (4phase: IN1-4, stepdir: DIR, STEP) |
gauge_mode |
stepdir |
Driver mode: stepdir (DIR+STEP) or 4phase (full-wave) |
gauge_min |
0 |
Minimum value |
gauge_max |
7300 |
Maximum value |
gauge_pulse |
4 |
Pulse width in milliseconds |
gauge_half_step |
false |
Use 8-phase half-step mode (1200 steps, smoother) |
smooth_step_ms |
50 |
Smooth movement interval |
idle_release_ms |
3000 |
Release coils after idle (ms) |
rezero_interval_ms |
3600000 |
Auto-rezero interval (ms, default 1hr) |
OTA
| Key |
Default |
Description |
gitea_base |
— |
Gitea server URL (no trailing slash) |
repo_owner |
— |
Repository owner |
repo_name |
— |
Repository name |
repo_folder |
— |
Folder inside repo to sync |
repo_branch |
main |
Branch to track |
api_token |
— |
API token for private repos |
wifi_ssid |
— |
WiFi network name |
wifi_password |
— |
WiFi password |
LEDs
| Key |
Default |
Description |
led_red_pin |
33 |
Red LED GPIO pin |
led_green_pin |
32 |
Green LED GPIO pin |
led_bl_pin |
23 |
RGB backlight (WS2812/NeoPixel) GPIO pin |
Home Assistant Discovery
| Key |
Default |
Description |
device_name |
"Selsyn 1" |
Device name in HA |
device_model |
"Chernobyl Selsyn-inspired gauge" |
Device model |
device_manufacturer |
"AdeBaumann" |
Device manufacturer |
device_area |
"Control Panels" |
Suggested area in HA |
gauge_entity_name |
"Selsyn 1 Power" |
Gauge entity name |
gauge_unit |
"W" |
Unit of measurement for gauge |
red_led_entity_name |
"Selsyn 1 Red LED" |
Red LED entity name |
green_led_entity_name |
"Selsyn 1 Green LED" |
Green LED entity name |
backlight_entity_name |
"Selsyn 1 Backlight" |
Backlight entity name |
backlight_unit |
"%" |
Unit for backlight |
Timing
| Key |
Default |
Description |
heartbeat_ms |
10000 |
State publish interval (ms) |
OTA Updates
On each boot, boot.py connects WiFi and runs ota.update(). The updater:
- If last boot was good and commit unchanged → skip file check entirely
- Otherwise, compares file SHA1 hashes with local manifest
- Downloads changed/missing files to
.tmp, then renames into place
- On success, saves manifest with commit SHA;
main.py writes OK flag
Manifest
Create ota_manifest.txt in your repo root to specify which files to sync: