π A reliable ESP32-based gateway that bridges your Hoymiles solar inverter to smart home systems like Home Assistant, openHAB, and MQTT.
| What you need | What you get |
|---|---|
| ESP32 board + Hoymiles HMS-xxxxW-2T | Real-time solar data in your smart home |
| 5 minutes setup | Power monitoring, remote control, automatic updates |
| Any smartphone/tablet/laptop | Zero-configuration setup with universal captive portal |
Ready to start? β 5-Minute Setup Guide
Love dtuGateway? Consider supporting its development:
π β Become a Sponsor β Help keep this project active, maintained, and continuously improved!
Or contribute code β We welcome PRs and community feedback!
- Compatibility Check
- Troubleshooting
- API Reference
- Advanced Configuration
- Developer Information
- π Changelog - View project history and recent updates
π New User-Friendly Documentation
This README has been restructured for easier navigation and first-time setup. Looking for the original technical documentation? Find it inreadme_old.md.
Transform your Hoymiles HMS-xxxW-2T solar inverter with integrated Wi-Fi DTU into a smart home powerhouse!
dtuGateway provides a reliable, dedicated gateway to your Hoymiles DTU where no direct API is available. Instead of relying on Hoymiles' unstable interface or waiting for official smart home integration, you get a rock-solid bridge that connects your inverter to any smart home system.
Important: Only compatible with HMS inverters that have built-in Wi-Fi DTU (integrated Wi-Fi). External DTU models (DTU-Lite, DTU-Pro sticks) are not supported.
- β No official API: Hoymiles provides no direct smart home integration
- β Unreliable DTU interface: Connection timeouts and 30+ minute downtimes
- β Manual intervention required: DTU connections fail and need manual recovery
- β Inconsistent data access: No reliable way to get real-time solar data
- β Dedicated reliable gateway: ESP32-based bridge with automatic DTU recovery
- β Multiple APIs provided: MQTT, REST JSON, openHAB integration where none existed
- β Consistent data delivery: Real-time monitoring with guaranteed updates
- β Remote control capabilities: Power limiting and inverter management via API
- β Comprehensive diagnostics: DTU/inverter firmware version detection and system monitoring
- β Intelligent connection handling: Automatic WiFi reconnection and weak signal management
- β Set-and-forget operation: Automatic recovery from DTU connection issues
- β Zero-configuration setup: Universal captive portal works on any device without manual browser navigation
- Real-time metrics: Power (W), voltage (V), current (A) for both PV panels and grid
- Energy tracking: Daily and total energy counters (kWh)
- System health: Inverter temperature, Wi-Fi signal strength, warnings
- Device information: Automatic DTU and inverter firmware/hardware version detection plus model identification and serial number extraction (available via REST API)
- Automatic timezone/DST: Built-in daylight saving time handling
- π‘ Home Assistant: Auto-discovery via MQTT, instant setup
- π openHAB: Direct REST API integration with configurable items
- π‘ MQTT: Full broker support with TLS encryption
- π JSON API: Direct HTTP access for custom integrations
- π OpenDTU Compatible: Drop-in replacement with OpenDTU MQTT topic structure
- Power limiting: Set inverter output from 0-100% remotely
- Inverter control: Turn inverter on/off from your smart home
- System management: Reboot DTU, inverter, or gateway remotely
- Automatic recovery: Detects and fixes connection issues automatically
- Built-in web interface: Configure and monitor via browser
- OLED display: 1.3" 128x64 with screensaver and brightness control
- Round TFT display: 1.28" 240x240 with night mode and gauges
- Remote monitoring: Act as display for another dtuGateway
- Universal captive portal: Automatic configuration page detection on Android, iOS, and Windows devices
- Device diagnostics: Real-time DTU and inverter firmware version monitoring
- Intelligent connection management: Automatic WiFi reconnection for weak signal scenarios
- OTA updates: Manual firmware updates via web interface
- Factory reset: Easy recovery from any configuration issues
- Warning system: Real-time DTU alerts and error monitoring
- Cloud pause: Configurable Hoymiles cloud update coordination
-
ESP32 microcontroller
- ESP-WROOM-32 NodeMCU-32S (tested, recommended)
- ESP32-S3 (standard build:
esp32_S3, tested by community users) - ESP32-S3 16MB N16R8 (build target:
esp32_S3_16MB_N16R8, tested by community) - ESP32-S3 with 1.28" round TFT (special build target:
esp32_S3_lcd_128, for pre-mounted round GC9A01 displays, e.g. Waveshare board)Most common: Waveshare ESP32-S3 1.28 inch IPS LCD (GC9A01 driver, 240x240). Widely available as a single board with display and supported by the
esp32_S3_lcd_128build target.
Buy: Waveshare Β· Amazon (search) Β· Aliexpress (search)
-
Hoymiles HMS-xxxxW-2T solar inverter with built-in Wi-Fi DTU
- β Supported: HMS-600W-2T, HMS-700W-2T, HMS-800W-2T, HMS-900W-2T, HMS-1000W-2T
- β Confirmed: All HMS-600W/700W/800W/900W/1000W-2T inverters (single phase, 2 MPPT channels, Wi-Fi integrated)
- β Accurate Detection: Automatic model identification via serial number analysis
- β NOT Supported: External DTU models (DTU-Lite stick, DTU-Pro external units)
| Display Type | Size | Features | Wiring |
|---|---|---|---|
| OLED | 1.3" 128x64 | SSH1106, screensaver, brightness | 4 wires (VCC, GND, SCL, SDA) |
| Round TFT (standard) | 1.28" 240x240 | GC9A01, night mode, backlight | 8 wires (see standard pinout below) |
| Round TFT (pre-mounted/128) | 1.28" 240x240 | GC9A01, night mode, backlight | 8 wires (see special pinout for esp32_S3_lcd_128 below) |
Need wiring help? β Hardware Setup Guide
What works:
- HMS inverters with integrated Wi-Fi DTU (built into the inverter)
- These models have Wi-Fi connectivity built directly into the inverter unit
- Communication happens directly to the inverter's internal DTU over Wi-Fi
What doesn't work:
- HMS inverters that require external DTU units (DTU-Lite stick, DTU-Pro, etc.)
- These systems use a separate physical DTU device for communication
- dtuGateway connects directly to the inverter, not external DTU hardware
Not sure about your setup? Check if your inverter has its own Wi-Fi network or connects directly to your home Wi-Fi. If it does, you have a compatible integrated Wi-Fi DTU model.
Model naming explained:
HM= HoymilesS= S - single phase inverterxxx' / 'xxxx= wattage (e.g., 800, 1000)W= Wi-Fi version2= 2 channels (for 2 PV panels)T= MPPT (Maximum Power Point Tracking)Example: HMS-1000W-2T means a 1000W inverter, Wi-Fi version, 2 MPPT channels.
Choose your version:
- Stable: Latest tested release (recommended for most users)
- Snapshot: Latest development features (for testing and early adopters)
πΎ Factory Flash Packages Available:
Each release now includes complete factory flash ZIP packages with all required files (bootloader, partitions, boot_app0, firmware) plus flashing instructions for easy setup.
Snapshot releases contain the latest development code before it's released as stable:
- π₯ Download Snapshot
β οΈ Use with caution: May contain bugs or incomplete features- π Manual updates: Check for newer snapshots via web interface
- π‘ Help development: Report issues to improve the project
Perfect for: Advanced users who want to test new features and help with development.
Using ESP Download Tool:
-
Download required files:
- Use factory flash ZIP package from the release (recommended)
- Required files:
bootloader.binβ Address:0x1000 partitions.binβ Address:0x8000boot_app0.binβ Address:0xE000firmware.binβ Address:0x10000
-
Flash settings:
- SPI Speed: 40 MHz
- SPI Mode: QIO
- Baud rate: 921600
-
Press Start and wait for completion
β οΈ Factory Flash Required:
- New installations: First-time ESP32 setup
- Version 2.2.0017+: Partition changes prevent OTA updates from older versions
- Recovery: After failed OTA or corrupted firmware
Alternative: Use esptool.py (community guide)
- Connect to setup Wi-Fi:
dtuGateway_XXXXXX - Automatic captive portal: Your device should automatically open the configuration page
- Android: Automatic redirect notification appears
- iOS/iPad: "Sign in to Wi-Fi" popup opens browser automatically
- Windows: Automatic browser popup with configuration page
- Manual access: Navigate to
http://192.168.4.1orhttp://dtugateway.localif automatic detection fails
- Configure network:
- Select your home Wi-Fi
- Enter Wi-Fi password
- Set your DTU's IP address
For Home Assistant users:
- Enable MQTT with auto-discovery
- Set MQTT broker details
- Devices appear automatically in HA
For openHAB users:
- Set openHAB IP address
- Configure item prefix
- Items created automatically
For other systems:
- Use JSON API at
http://your-device-ip/api/data.json - Or configure custom MQTT topics
Your solar data is now flowing into your smart home system. The device will:
- β Update data every 31 seconds
- β Automatically handle DTU connection issues
- β
Provide web interface at
http://your-device-ip - β Manual firmware updates via web interface (auto-update planned for future)
Next steps: Set up displays β’ Explore advanced features
| Display Pin | ESP32 Pin | Description |
|---|---|---|
| VCC | 3.3V | Power supply |
| GND | GND | Ground |
| SCL | GPIO22 (D22) | I2C Clock |
| SDA | GPIO21 (D21) | I2C Data |
Standard wiring (for esp32, esp32_S3, esp32_S3_16MB_N16R8):
| Display Pin | ESP32 Pin | Description |
|---|---|---|
| VCC | 3.3V | Power supply |
| GND | GND | Ground |
| SCL | GPIO18 (D18) | SPI Clock |
| SDA | GPIO23 (D23) | SPI Data (MOSI) |
| DC | GPIO2 (D2) | Data/Command |
| CS | GPIO15 (D15) | Chip Select |
| RST | 3.3V | Reset (pulled high) |
| BLK | GPIO4 (D4) | Backlight control (ESP32) / GPIO12 (ESP8266) |
Special wiring for pre-mounted round TFT (for esp32_S3_lcd_128):
| Display Pin | ESP32 Pin | Description |
|---|---|---|
| VCC | 3.3V | Power supply |
| GND | GND | Ground |
| SCL | GPIO10 | SPI Clock |
| SDA | GPIO11 | SPI Data (MOSI) |
| DC | GPIO8 | Data/Command |
| CS | GPIO9 | Chip Select |
| RST | GPIO12 | Reset |
| BLK | GPIO40 | Backlight control |
- OLED: Simple 4-wire connection, plug and play
- TFT (standard): 8 wires required, PWM backlight control enables night mode and smooth brightness
- TFT (pre-mounted/128): Use the special wiring and
esp32_S3_lcd_128build target for pre-mounted round TFT modules. Backlight is always ON (no brightness/PWM control). - Both displays: Factory mode alternates between OLED/TFT config on each reboot until configured
- No display: Gateway works perfectly via web interface only
- OLED pins: Uses default I2C pins (GPIO21/SDA, GPIO22/SCL) for ESP32
- esp32_S3_lcd_128: Use only with pre-mounted round TFT hardware (see above pinout and build target). This build excludes all OLED code and optimizes memory for the TFT display.
- Download ESP32 Download Tool
- Get firmware files from latest release
- Flash according to 5-Minute Setup
When to use: Command-line users, automated scripts, or when ESP Download Tool doesn't work
esptool.py --chip esp32 --baud 921600 --before default_reset --after hard_reset write_flash \
0x1000 bootloader.bin \
0x8000 partitions.bin \
0xe000 boot_app0.bin \
0x10000 firmware.binπ Community Resources:
- Detailed esptool.py Guide by @netzbasteln - Step-by-step tutorial with troubleshooting tips
- Installation help: GitHub Discussions - Community support for flashing issues
- Official esptool docs: Espressif esptool documentation
- With display: Alternates between OLED/TFT on each reboot until configured
- No display: Starts access point immediately
- LED indicator: Built-in LED shows activity status
- Serial output: 115200 baud for debugging (optional)
- Captive portal: Universal cross-platform automatic configuration detection
- Android: Shows "Sign in to network" notification with automatic redirect
- iOS/iPad: Displays "Sign in to Wi-Fi" popup that opens configuration page
- Windows: Automatic browser popup with configuration interface
- Manual access: Navigate to
http://192.168.4.1if automatic detection doesn't work
If something goes wrong:
- Connect via serial terminal (115200 baud)
- Type:
resetToFactory 1 - Device reboots to factory settings
- Reconnect to setup Wi-Fi and reconfigure
- Network:
dtuGateway_<ChipID> - URL:
http://192.168.4.1orhttp://dtuGateway.local - Password: None (open network)
- Captive Portal: Automatic configuration page detection
- Cross-platform compatibility: Works with Android, iOS, Windows, and macOS
- Automatic detection: Most devices show captive portal popup automatically
- Manual fallback: Direct browser navigation if automatic detection fails
- URL:
http://<device-ip>(check your router for IP) - Port: Default 80 (configurable in advanced settings)
- Security: Optional password protection via serial command
- Wi-Fi Selection: Scan and select your network
- DTU Connection: Set your inverter's IP address
- Advanced: Custom ports, timeouts, cloud pause settings
- Type Selection: OLED (0) or Round TFT (1)
- Orientation: 0Β°, 90Β°, 180Β°, 270Β° (TFT only)
- Brightness: Day/night levels (0-255)
- Night Mode: Scheduled dimming with time ranges
- Screensaver: Anti-burn-in for OLED displays
- openHAB: IP address and item prefix configuration
- MQTT: Broker settings, TLS, auto-discovery options
- Remote Display: Use as monitor for another dtuGateway
Access expert mode at http://<device-ip>/config:
- Timezone: Automatic DST handling with offset configuration
- Update Channel: Stable vs. snapshot releases
- Debug Settings: Polling intervals, cloud coordination
- Security: Settings protection and access control
Features:
- Segmented layout: Header (Wi-Fi status, time), main (power data), footer (energy totals)
- Screensaver: 1-pixel shift every minute to prevent burn-in
- Brightness control: Smooth transitions when values change
- Status indicators: Connection quality for both gateway and DTU
Data shown:
- Current power output and limit
- Daily and total energy yield
- Real-time clock with automatic DST
- Wi-Fi signal strength indicators
Build targets:
esp32,esp32_S3,esp32_S3_16MB_N16R8: Standard round TFT wiring (see table above)esp32_S3_lcd_128: For pre-mounted round TFT modules (special wiring, memory config, and display code optimization)
Conditional compilation:
- The firmware uses conditional compilation to optimize memory and code for each display type. When building for
esp32_S3_lcd_128, all OLED code is excluded, and the TFT code is optimized for the mounted display.
Features:
- Gauge-style display: Analog power meter with digital readouts
- Night mode: Automatic dimming or clock-only display
- Backlight control: PWM brightness adjustment (standard builds only; pre-mounted/128 is always ON)
- Status rings: Visual indicators for system status
Modes:
- Normal: Full power and energy display
- Night: Clock only or dimmed display
- Remote Display: Full dashboard mirror (displays all inverter data)
- Solar Monitor: Multi-source power aggregation display
- Battery Monitor: Battery state of charge display
- Solar + Battery: Combined power and battery display
dtuGateway can operate in three distinct modes, each with different capabilities:
| Aspect | Normal Mode | Remote Display | Monitor Modes (Solar/Battery) |
|---|---|---|---|
| DTU Connection | β Direct to inverter | β Receives from source | β Disabled (MQTT only) |
| Data Source | Local inverter | MQTT mirror of another device | MQTT subscribed topics |
| Web Dashboard | β Full monitoring & control | β Mirrors main gateway | β Shows only aggregated data |
| Power Limiting | β Control inverter output | β Full control available | β Not available |
| MQTT Required | Optional | β Yes (both devices) | β Yes (required) |
| Display Types | OLED + TFT | TFT only | TFT only |
| Best For | Direct solar monitoring | Multi-location display mirror | Aggregating from multiple sources |
Mode Selection (mutually exclusive - choose only ONE):
- β Normal mode (default) + DTU connection enabled
- β Remote display mode
- β Solar monitor mode
- β Battery monitor mode
- β Solar + Battery combined (check both boxes)
These modes allow one dtuGateway to act as a display terminal for aggregated solar and/or battery data from other dtuGateway instances or external sources via MQTT. When enabled, the device disables direct DTU connection and subscribes to specific MQTT topics to receive data. Perfect for monitoring multiple inverters or battery systems in one place.
- Normal mode: Actively monitors your inverter, can control it
- Monitor modes: Passive display only, receives data via MQTT (no DTU connection)
Displays aggregated solar power and daily energy from multiple sources.
- Features: Power gauge, daily yield, real-time clock with blinking colon.
- MQTT Topics Required (subscribed under the configured main topic path):
<main-topic>/PV_Power_Sum/state: Current aggregated power (e.g., total watts from all sources).<main-topic>/PV_Energy_Sum_Day/state: Daily aggregated energy (e.g., total kWh produced today).
- Display Logic: Updates
lastDisplayData.totalPowerandlastDisplayData.totalYieldDayfrom received MQTT data. Resets max power daily at midnight.
Displays battery state of charge (SOC) and stored energy.
- Features: SOC gauge, stored energy value, real-time clock.
- MQTT Topics Required (subscribed under the configured main topic path):
<main-topic>/Battery_SOC/state: Battery state of charge (e.g., percentage, 0-100).<main-topic>/Battery_Stored_Energy/state: Stored energy in the battery (e.g., kWh).
- Display Logic: Updates
lastDisplayData.battery_SOCandlastDisplayData.battery_StoredEnergyfrom received MQTT data. Limits SOC to 100% and handles invalid values.
π‘ Tip: Ensure your MQTT data source publishes valid battery values. See Troubleshooting Monitor Modes if display shows no data.
Combines solar power monitoring with battery status for a comprehensive view.
- Features: Power gauge with SOC ring overlay, daily yield, stored energy, real-time clock.
- MQTT Topics Required (subscribed under the configured main topic path; all topics from Solar and Battery Monitor above):
<main-topic>/PV_Power_Sum/state: Current aggregated power.<main-topic>/PV_Energy_Sum_Day/state: Daily aggregated energy.<main-topic>/Battery_SOC/state: Battery SOC.<main-topic>/Battery_Stored_Energy/state: Stored energy.
- Display Logic: Merges solar and battery data into a single screen (e.g., power ring with SOC arc in
drawGauge_SolarBatteryMonitor). Updates both solar and battery display data structures.
Configuration:
- Go to DTU Settings in the web interface
- Find Display modes section
- Choose exactly one mode (mutually exclusive):
- Solar monitor β Displays aggregated solar power and daily yield
- Battery monitor β Displays battery SOC and stored energy
- Solar & Battery combined β Both gauges on one display (check both checkboxes)
- Click Save DTU β Device will restart
- Configure MQTT broker connection in Bindings settings (same broker as data source)
- Set main topic path to match your data source (other dtuGateway instance or Home Assistant)
- Verify data source is publishing to required MQTT topics
MQTT Requirements:
- β No DTU connection β only receives data via MQTT
- β Requires MQTT broker β won't work without it
- β Requires data source β another dtuGateway or external system publishing data
Data Flow:
- Data source (Device A) β publishes to MQTT broker
- Display node (Device B) β subscribes to MQTT topics
- Both must use same MQTT broker and topic path
Notes:
- Monitor modes disable DTU connection automatically
- If both Solar and Battery Monitor are checked, the display combines elements (implementation in
drawScreen_monitorSolarBattery) - Night mode, brightness, and orientation apply as configured for the TFT display
- To return to normal mode: uncheck monitor checkboxes and re-enable DTU connection
Use this when you want another dtuGateway to show the exact same dashboard as your main gateway.
Architecture:
Inverter ββ Main Gateway (normal mode, publishes all data)
β (MQTT broker)
Display Gateway (remote display mode, subscribes to all topics)
Setup Steps:
Device A (Main Gateway):
- Configure normally with DTU connection β DTU IP address
- Enable MQTT and configure broker details
- Note the main MQTT topic (e.g.,
dtu_12345678)
Device B (Display Gateway):
- Connect to WiFi (same network or accessible to same MQTT broker)
- Go to DTU Settings β Display modes
- Check Remote display (full dashboard mirror)
- Click Save DTU β Device restarts
- Go to Bindings settings
- Enable MQTT with same broker settings as Device A
- Set main topic to match Device A's topic
- Click Save Bindings β Device reboots
Verification:
- Device B's web dashboard should mirror Device A's data
- TFT display shows all gauges and readings from Device A
- If blank: check MQTT connection and topic names match exactly
Use this when you want to display total solar power from multiple sources (e.g., multiple inverters or a home energy system).
Architecture:
Inverter 1 } ββ dtuGateway instances β
Inverter 2 } ββ (publish to MQTT) βββ MQTT Broker ββ Solar Monitor Display
Home Energy } ββ or Home Assistant β (aggregates data)
System
Required MQTT Topics (published by data source):
<main-topic>/PV_Power_Sum/stateβ Current total power in watts<main-topic>/PV_Energy_Sum_Day/stateβ Daily total energy in kWh
Setup Steps:
Step 1: Configure Data Sources
- Each inverter device publishes solar data to MQTT under a common topic
- Example: If you have 2 dtuGateway instances publishing to:
inverter1/grid/powerandinverter1/grid/dailyinverter2/grid/powerandinverter2/grid/daily
- Use Home Assistant or automation script to aggregate these into single topics:
solar_aggregate/PV_Power_Sum/statesolar_aggregate/PV_Energy_Sum_Day/state
Step 2: Configure Solar Monitor Device
- Go to DTU Settings β Display modes
- Check Solar monitor (uncheck Remote display if was enabled)
- Click Save DTU β Device restarts
- Go to Bindings settings
- Enable MQTT with broker that has aggregated topics
- Set main topic to match aggregation topic (e.g.,
solar_aggregate) - Click Save Bindings β Device reboots
Verification:
- TFT display shows power gauge and daily yield
- Gauge updates every ~30 seconds
- If blank: verify aggregated MQTT topics are being published
Use this when you want to display battery state of charge from external sources (e.g., battery system, BMS, Home Assistant).
Required MQTT Topics (published by data source):
<main-topic>/Battery_SOC/stateβ Battery state of charge (0-100%)<main-topic>/Battery_Stored_Energy/stateβ Stored energy in kWh
Setup Steps:
Step 1: Configure Data Source
- Your battery system (Powerwall, BYD, Growatt, etc.) must publish SOC and energy to MQTT
- Or use Home Assistant to read battery state and publish to MQTT
Step 2: Configure Battery Monitor Device
- Go to DTU Settings β Display modes
- Check Battery monitor (uncheck others)
- Click Save DTU β Device restarts
- Go to Bindings settings
- Enable MQTT with broker that has battery topics
- Set main topic to match battery data topic (e.g.,
battery_system) - Click Save Bindings β Device reboots
Verification:
- TFT display shows SOC gauge and stored energy value
- Updates when battery data changes on source
- If blank: verify MQTT topics are being published with correct values
Display aggregated solar power and battery status on a single screen.
Required MQTT Topics:
<main-topic>/PV_Power_Sum/stateβ Current solar power (watts)<main-topic>/PV_Energy_Sum_Day/stateβ Daily solar energy (kWh)<main-topic>/Battery_SOC/stateβ Battery state of charge (%)<main-topic>/Battery_Stored_Energy/stateβ Stored energy (kWh)
Setup Steps:
- Go to DTU Settings β Display modes
- Check both Solar monitor AND Battery monitor
- Click Save DTU β Device restarts
- Configure MQTT same as above (both solar and battery topics must be available)
Display:
- Power gauge with SOC ring overlay
- Daily yield and stored energy indicators
- Single-screen monitoring of both systems
Possible causes:
-
MQTT not configured or not connected
- Check: Bindings β Is MQTT enabled?
- Check: Broker IP and port are correct
- Check: Username and password (if required)
- Fix: Go to Bindings, re-enter MQTT settings, click Save
-
Wrong MQTT topic path
- Symptom: MQTT is connected but display stays blank
- Check: Main topic in Bindings matches your data source
- Example: If data publishes to
home/solar/PV_Power_Sum/state, your topic should behome/solar - Fix: Edit topic in Bindings settings, click Save
-
Data source not publishing MQTT topics
- Check: Other dtuGateway or system is actually publishing data
- Test: Use MQTT client app to verify topics exist and have values
- Fix: Verify data source device is running and configured
-
Wrong display mode selected
- Check: DTU Settings β Display modes
- Make sure correct mode is checked (Solar, Battery, or both)
- Fix: Select correct mode, click Save DTU, wait for restart
Possible causes:
-
Data source stopped publishing
- Check: Source device is still running
- Fix: Restart source device
-
MQTT connection lost
- Check: MQTT broker still running and accessible
- Fix: Restart MQTT broker or reconfigure connection
-
Device in sleep/offline mode
- Fix: Restart display device
Possible causes:
-
Different MQTT brokers
- Check: Both devices connected to same broker?
- Fix: Configure both to use same broker IP and port
-
Different MQTT topics
- Check: Main topic in Bindings matches exactly
- Example:
dtu_12345678notdtu_12345679 - Fix: Verify topic names character-by-character
-
Network connectivity issue
- Check: Both devices can see each other (ping test)
- Fix: Check WiFi network, firewall rules, MQTT broker accessibility
This is normal β device restarts to reconfigure MQTT subscriptions and display rendering. Wait 30-60 seconds for device to come back online.
- Enable MQTT in dtuGateway web interface
- Configure broker: IP, port, username, password
- Enable auto-discovery: Toggle "HomeAssistant Auto Discovery"
- Restart dtuGateway: Devices appear automatically in HA
Important: Home Assistant auto-discovery is not available in OpenDTU mode.
For OpenDTU topic structure compatibility:
- Enable OpenDTU mode in MQTT settings
- Manual sensor configuration required in Home Assistant
- Use OpenDTU topic structure in your configuration.yaml
# Example sensors for OpenDTU topic structure
mqtt:
sensor:
- name: "Solar Power"
state_topic: "your-topic-prefix/0/power"
unit_of_measurement: "W"
device_class: "power"
- name: "Solar Daily Energy"
state_topic: "your-topic-prefix/0/yieldday"
unit_of_measurement: "kWh"
device_class: "energy"
- name: "Panel 1 Power"
state_topic: "your-topic-prefix/1/power"
unit_of_measurement: "W"
device_class: "power"
- name: "Panel 2 Power"
state_topic: "your-topic-prefix/2/power"
unit_of_measurement: "W"
device_class: "power"
- name: "Inverter Temperature"
state_topic: "your-topic-prefix/0/temperatur"
unit_of_measurement: "Β°C"
device_class: "temperature"
- name: "Power Limit"
state_topic: "your-topic-prefix/status/limit_relative"
unit_of_measurement: "%"What You Get (with auto-discovery enabled in standard mode): Sensors automatically created:
sensor.dtugateway_xxxxx_grid_power- Current grid powersensor.dtugateway_xxxxx_pv0_power- Panel 1 powersensor.dtugateway_xxxxx_pv1_power- Panel 2 powersensor.dtugateway_xxxxx_grid_daily_energy- Today's energysensor.dtugateway_xxxxx_inverter_temp- Inverter temperature- ... and many more
Device identifier: Appears as "HMS-xxxxW-2T" in Home Assistant Controls automatically created:
number.dtugateway_xxxxx_power_limit- Set power limit (0-100%)button.dtugateway_xxxxx_reboot_dtu- Reboot DTUbutton.dtugateway_xxxxx_reboot_inverter- Reboot inverter
type: entities
title: Solar System
entities:
- entity: sensor.dtugateway_xxxxx_grid_power
name: Current Power
- entity: sensor.dtugateway_xxxxx_grid_daily_energy
name: Today's Energy
- entity: number.dtugateway_xxxxx_power_limit
name: Power Limit
- entity: sensor.dtugateway_xxxxx_inverter_temp
name: Temperature# Custom main topic (optional)
dtu_12345678/grid/P # Power values
dtu_12345678/grid/dailyEnergy # Energy values
dtu_12345678/inverter/Temp # Temperature
dtu_12345678/timestamp # Last update time
# Control topics
dtu_12345678/inverter/PowerLimitSet/set # Set power limit
dtu_12345678/inverter/RebootDtu/set # Reboot DTU
dtu_12345678/inverter/RebootMi/set # Reboot inverter- Set openHAB IP in dtuGateway web interface
- Configure item prefix (e.g., "inverter")
- Create items in your openHAB items file
// Read power limit setting from openHAB
Number inverter_PowerLimitSet "Power Limit Set [%d %%]"
// Grid data
Number inverterGrid_U "Grid Voltage [%.1f V]"
Number inverterGrid_I "Grid Current [%.2f A]"
Number inverterGrid_P "Grid Power [%.0f W]"
Number inverterPV_E_day "Daily Energy [%.3f kWh]"
Number inverterPV_E_total "Total Energy [%.3f kWh]"
// Panel 1 data
Number inverterPV1_U "PV1 Voltage [%.1f V]"
Number inverterPV1_I "PV1 Current [%.2f A]"
Number inverterPV1_P "PV1 Power [%.0f W]"
Number inverterPV1_E_day "PV1 Daily Energy [%.3f kWh]"
Number inverterPV1_E_total "PV1 Total Energy [%.3f kWh]"
// Panel 2 data
Number inverterPV2_U "PV2 Voltage [%.1f V]"
Number inverterPV2_I "PV2 Current [%.2f A]"
Number inverterPV2_P "PV2 Power [%.0f W]"
Number inverterPV2_E_day "PV2 Daily Energy [%.3f kWh]"
Number inverterPV2_E_total "PV2 Total Energy [%.3f kWh]"
// Inverter status
Number inverter_Temp "Inverter Temperature [%.1f Β°C]"
Number inverter_PowerLimit "Current Power Limit [%d %%]"
Number inverter_WifiRSSI "DTU Wi-Fi Signal [%d %%]"- Data flow: dtuGateway β openHAB REST API β Items updated
- Control flow: openHAB item change β dtuGateway reads β DTU updated
- Update interval: Every 31 seconds (configurable)
- API endpoint:
http://openhab-ip:8080/rest/items/<itemName>/state
Broker Settings:
Host: your-mqtt-broker.local
Port: 1883 (or 8883 for TLS)
Username: your-mqtt-user
Password: your-mqtt-password
Main Topic: dtuGateway_12345678NEW: OpenDTU Compatibility Mode π
dtuGateway can publish data using OpenDTU-compatible MQTT topic structure, making it a drop-in replacement for existing OpenDTU setups.
- Web Interface: Navigate to MQTT settings
- Enable Option: Check "OpenDTU Topics Structure"
- Important: Home Assistant auto-discovery is automatically disabled in OpenDTU mode
- Restart: Device restarts to apply new topic structure
When OpenDTU mode is enabled, dtuGateway publishes to these topics:
your-topic-prefix/
βββ 0/ # Grid/AC output data
β βββ power # Grid power (W)
β βββ voltage # Grid voltage (V)
β βββ current # Grid current (A)
β βββ frequency # Grid frequency (Hz)
β βββ yieldday # Daily energy (kWh)
β βββ yieldtotal # Total energy (kWh)
β βββ temperatur # Inverter temperature (Β°C)
βββ 1/ # PV Panel 1 data
β βββ power # Panel 1 power (W)
β βββ voltage # Panel 1 voltage (V)
β βββ current # Panel 1 current (A)
β βββ yieldday # Panel 1 daily energy (kWh)
β βββ yieldtotal # Panel 1 total energy (kWh)
βββ 2/ # PV Panel 2 data
β βββ power # Panel 2 power (W)
β βββ voltage # Panel 2 voltage (V)
β βββ current # Panel 2 current (A)
β βββ yieldday # Panel 2 daily energy (kWh)
β βββ yieldtotal # Panel 2 total energy (kWh)
βββ status/
β βββ limit_relative # Current power limit (%)
βββ radio/
βββ rssi # DTU Wi-Fi signal strength (dBm)
- Drop-in replacement: Use existing OpenDTU dashboards and automation
- Standard structure: Compatible with OpenDTU-based Home Assistant integrations
- Familiar topics: Same topic names as OpenDTU for easy migration
- Existing tools: Works with existing OpenDTU monitoring tools
- Same main topic: Use your existing OpenDTU main topic prefix
- Update device: Flash dtuGateway firmware to your ESP32
- Enable OpenDTU mode: Check the option in MQTT settings
- Keep automations: Your existing Home Assistant automations continue working
- Dashboard compatibility: Existing OpenDTU dashboards work unchanged
- Home Assistant Auto-Discovery: Automatically disabled in OpenDTU mode (not compatible)
- Manual HA Setup: Configure Home Assistant sensors manually using OpenDTU topic structure
- No discovery conflicts: Prevents topic structure conflicts between modes
- Standard vs OpenDTU: Choose one topic structure, not both simultaneously
dtuGateway supports three distinct MQTT modes. Choose the one that matches your setup:
| Feature | Mode 1: Standard + HA | Mode 2: OpenDTU | Mode 3: Standard Only |
|---|---|---|---|
| Web UI Setting | HA Auto-discovery: β, OpenDTU: β | HA Auto-discovery: β, OpenDTU: β | HA Auto-discovery: β, OpenDTU: β |
| Topic Structure | dtuGateway_XXXXX/grid/power |
prefix/0/power |
dtuGateway_XXXXX/grid/power |
| Home Assistant | Auto-discovery enabled | Manual setup required | Manual setup required |
| Use Case | Standard HA setups | OpenDTU migrations | Custom integrations |
| Best For | Home Assistant users | Replacing OpenDTU | Existing custom config |
How to Switch Modes:
- Go to Web Interface β Settings β MQTT
- Adjust these checkboxes:
- β "HomeAssistant auto-discovery" = Enable HA discovery
- β "OpenDTU topic structure" = Use OpenDTU topic format
- Note: Enabling both checkboxes automatically selects Mode 1 (HA discovery takes priority)
- Click Save - device will restart to apply new topic structure
When using the standard topic structure (default), dtuGateway publishes to:
dtuGateway_12345678/
βββ timestamp # Last update timestamp
βββ grid/
β βββ U # Voltage (V)
β βββ I # Current (A)
β βββ P # Power (W)
β βββ dailyEnergy # Daily energy (kWh)
β βββ totalEnergy # Total energy (kWh)
βββ pv0/ (same structure as grid)
βββ pv1/ (same structure as grid)
βββ inverter/
βββ PowerLimit # Current limit (%)
βββ PowerLimitSet # Target limit (%)
βββ Temp # Temperature (Β°C)
βββ WifiRSSI # Signal strength
βββ cloudPause # Cloud update status
βββ dtuConnectState # Connection status
βββ dtuConnectionOnline # Online status
βββ inverterControlStateOn # Inverter state
βββ warningsActive # Warning count
dtuGateway_12345678/inverter/PowerLimitSet/set # Set power limit (2-100)
dtuGateway_12345678/inverter/RebootMi/set # Reboot inverter (send 1)
dtuGateway_12345678/inverter/RebootDtu/set # Reboot DTU (send 1)
dtuGateway_12345678/inverter/RebootDtuGw/set # Reboot gateway (send 1)
These additional topics are available in both Standard and OpenDTU modes for advanced monitoring and control:
Standard Mode Extended Topics:
dtuGateway_12345678/
βββ dtuGW_special/
β βββ limit_relative_set # Current power limit setting (%)
β βββ cloud_pause # Cloud update pause status (0/1)
β βββ dtu_connect_state # DTU connection state code
β βββ dtu_connection_online # DTU online status (0/1)
β βββ inverter_control_state_on # Inverter control enabled (0/1)
β βββ warnings_active # Active warning count
βββ timestamp # Last data update (Unix timestamp)
OpenDTU Mode Extended Topics:
your-topic-prefix/
βββ dtuGW_special/
β βββ limit_relative_set # Current power limit setting (%)
β βββ cloud_pause # Cloud update pause status (0/1)
β βββ dtu_connect_state # DTU connection state code
β βββ dtu_connection_online # DTU online status (0/1)
β βββ inverter_control_state_on # Inverter control enabled (0/1)
β βββ warnings_active # Active warning count
βββ status/
βββ last_update # Last data update (Unix timestamp)
Extended Topic Details:
limit_relative_set: The configured power limit percentage (2-100, 101 = no limit)cloud_pause: Whether Hoymiles cloud updates are paused (0 = active, 1 = paused)dtu_connect_state: Internal DTU connection state (0 = searching, 1 = connected)dtu_connection_online: Whether DTU is actively online (0 = offline, 1 = online)inverter_control_state_on: Whether inverter control is enabled (0 = disabled, 1 = enabled)warnings_active: Number of active warnings/faults from the invertertimestamp/last_update: Unix timestamp of last successful data publication
For secure connections (e.g., HiveMQ Cloud):
- Enable TLS: Check "Use TLS" in MQTT settings
- Port: Usually 8883 for TLS
- Certificates: Uses ESP32 built-in CA certificates
- Note: TLS only available on ESP32 (not ESP8266)
Understanding the difference is critical for setting up monitor modes correctly.
In Normal Mode: dtuGateway actively connects to your inverter's DTU and publishes real-time data to the MQTT broker.
Published Topics (dtuGateway sends these):
dtuGateway_XXXXX/grid/Pβ Power output from inverter (W)dtuGateway_XXXXX/grid/dailyEnergyβ Energy produced today (kWh)dtuGateway_XXXXX/inverter/Tempβ Inverter temperature (Β°C)dtuGateway_XXXXX/pv0/P,dtuGateway_XXXXX/pv1/Pβ Panel powers (W)- ...and many more (see "Standard dtuGateway Topics" section above)
What this means: Your home automation system (HA, openHAB, etc.) receives these topics and displays the data.
In Monitor Mode: dtuGateway disables DTU connection and instead listens for specific MQTT topics to display aggregated data.
Monitor mode expects to RECEIVE these specific topics:
<main-topic>/PV_Power_Sum/stateβ Must receive current solar power (watts)<main-topic>/PV_Energy_Sum_Day/stateβ Must receive daily solar energy (kWh)
Where this data comes from (data source could be):
- Another dtuGateway device publishing its
grid/Pvalues - Home Assistant aggregating multiple devices
- A solar system with MQTT integration
- Custom automation script summing multiple sources
<main-topic>/Battery_SOC/stateβ Must receive battery state of charge (0-100%)<main-topic>/Battery_Stored_Energy/stateβ Must receive stored energy (kWh)
Where this data comes from (data source could be):
- External battery system with MQTT output
- Home Assistant reading from battery BMS
- Smart battery management system
- Inverter with battery capabilities
- All topics from the main gateway (mirrors everything)
- Same as what the main gateway publishes
- Both devices must connect to same MQTT broker
SCENARIO 1: NORMAL GATEWAY (Publishes)
βββββββββββββββββββββββββββββββββββββββ
Inverter
β (Wi-Fi connection)
dtuGateway (Normal Mode)
β (Publishes MQTT topics)
MQTT Broker
β (Subscribes to topics)
Home Assistant / openHAB / Dashboard
SCENARIO 2: MONITOR MODE (Subscribes)
ββββββββββββββββββββββββββββββββββββββ
Data Source(s): Inverter(s), Battery, HA, etc.
β (Publish MQTT topics: PV_Power_Sum, Battery_SOC, etc.)
MQTT Broker
β (Monitor device subscribes to specific topics)
dtuGateway (Monitor Mode)
β (Displays aggregated data on TFT)
Local Display (Solar/Battery gauge)
SCENARIO 3: REMOTE DISPLAY (Subscribes to All)
βββββββββββββββββββββββββββββββββββββββββββββββ
Inverter
β (Wi-Fi)
Main dtuGateway (Normal Mode, publishes all topics)
β (MQTT Broker)
Display dtuGateway (Remote Display Mode, subscribes to all)
β
Two identical dashboards / TFT displays
β Mistake #1: Wrong topic path
- User sets monitor mode main topic as
dtuGateway_123/grid/P - But the aggregator publishes to
solar_monitor/PV_Power_Sum/state - Result: Monitor display stays blank
- Fix: Main topic should be
solar_monitor, notdtuGateway_123/grid/P
β Mistake #2: Forgetting to configure data source
- User enables battery monitor mode
- Expects data to appear automatically
- But no system is publishing to
Battery_SOC/stateandBattery_Stored_Energy/state - Result: Display shows 0% SOC, 0 kWh
- Fix: Set up Home Assistant or system to publish battery data first
β Mistake #3: Using topic before the path separator
- User needs aggregated power from multiple inverters
- Publishes individual inverter data to
inverter1/grid/P,inverter2/grid/P - Tries to subscribe to
inverter1as monitor topic - But aggregated topics are at
combined_solar/PV_Power_Sum/state - Result: Monitor doesn't find the aggregated data
- Fix: Publish aggregated data to correct topics first, then monitor subscribes to aggregated path
URL: http://<device-ip>/api/data.json
Click to see example response
{
"localtime": 1704110892,
"ntpStamp": 1707640484,
"lastResponse": 1704063600,
"dtuConnState": 1,
"dtuErrorState": 0,
"starttime": 1707593197,
"inverter": {
"pLim": 80,
"pLimSet": 101,
"temp": 24.5,
"active": 1,
"uptodate": 1
},
"grid": {
"v": 230.2,
"c": 2.45,
"p": 564.0,
"dE": 12.456,
"tE": 1234.567
},
"pv0": {
"v": 35.8,
"c": 8.2,
"p": 293.0,
"dE": 6.123,
"tE": 567.890
},
"pv1": {
"v": 36.1,
"c": 7.9,
"p": 285.0,
"dE": 6.333,
"tE": 666.677
}
}URL: http://<device-ip>/api/info.json
Includes: System status, network information, DTU/inverter firmware versions, inverter model detection, and device diagnostics
Click to see example response
{
"chipid": 123456,
"chipType": "ESP32",
"host": "dtuGateway_123456",
"initMode": 0,
"protectSettings": 0,
"firmware": {
"version": "2.1.0",
"versiondate": "13.07.2025 - 12:00:00",
"updateAvailable": 0
},
"dtuConnection": {
"dtuHostIpDomain": "192.168.1.100",
"dtuRssi": 48,
"dtuDataCycle": 31,
"dtuResetRequested": 2,
"dtuCloudPause": 1,
"dtuCloudPauseTime": 30,
"dtuRemoteDisplay": 0,
"dtuRemoteDisplay_SolarMonitor": 0,
"deviceData": {
"dtu_version": 4097,
"dtu_version_string": "01.00.01",
"dtu_serial": "123456789011",
"inverter_version": 10008,
"inverter_version_string": "01.00.08",
"inverter_model": "HMS-800W-2T",
"inverter_serial": "141241234567"
}
},
"wifiConnection": {
"wifiSsid": "MyHomeWiFi",
"rssiGW": 85,
"networkCount": 3
}
}Python:
import requests
import json
# Get current data
response = requests.get('http://192.168.1.50/api/data.json')
data = response.json()
current_power = data['grid']['p']
daily_energy = data['grid']['dE']
inverter_temp = data['inverter']['temp']
print(f"Current power: {current_power}W")
print(f"Today's energy: {daily_energy}kWh")
print(f"Inverter temp: {inverter_temp}Β°C")
# Get device information including firmware versions
info_response = requests.get('http://192.168.1.50/api/info.json')
info_data = info_response.json()
if 'deviceData' in info_data['dtuConnection']:
deviceData = info_data['dtuConnection']['deviceData']
print(f"DTU firmware: {deviceData['dtu_version_string']}")
print(f"Inverter firmware: {deviceData['inverter_version_string']}")
if 'inverter_model' in deviceData:
print(f"Inverter model: {deviceData['inverter_model']}")
print(f"Serial number: {deviceData['inverter_serial']}")Node.js:
const axios = require('axios');
async function getSolarData() {
try {
const response = await axios.get('http://192.168.1.50/api/data.json');
const data = response.data;
console.log(`Power: ${data.grid.p}W`);
console.log(`Energy: ${data.grid.dE}kWh`);
console.log(`Temperature: ${data.inverter.temp}Β°C`);
} catch (error) {
console.error('Error fetching data:', error);
}
}
setInterval(getSolarData, 30000); // Every 30 secondscurl:
# Get current data
curl http://192.168.1.50/api/data.json | jq '.grid.p'
# Monitor power output
watch -n 30 'curl -s http://192.168.1.50/api/data.json | jq ".grid.p"'Quick Check: Can you connect directly to your inverter's Wi-Fi network?
-
Look for inverter Wi-Fi network:
- Should appear as
HMS-XXXXXXorAP_HMS_XXXXXX - If you see this, you have a compatible integrated Wi-Fi DTU
- Should appear as
-
Connect using S-Miles app:
- If the app connects directly to your inverter via Wi-Fi, you're compatible
- If you need a separate DTU device between app and inverter, you're not compatible
-
Physical check:
- Compatible: Single inverter unit with antenna (no separate DTU box)
- Not Compatible: Inverter + separate DTU device (stick/box)
External DTU Models (not supported):
- DTU-Lite (stick-style external DTU)
- DTU-Pro (external DTU box)
- DTU-W100 (external DTU)
- Any setup where DTU is separate from inverter
Why these don't work: dtuGateway communicates directly with the inverter's built-in DTU. External DTU devices use different communication protocols.
Post your inverter model and setup photos in GitHub Discussions for compatibility confirmation.
Problem: Can't connect to dtuGateway_XXXXXX Wi-Fi
- Solution: Power cycle the ESP32, wait 30 seconds for boot
- Check: LED should blink during startup
- Note: On mobile, accept "no internet" connection warning
Problem: Captive portal not opening automatically
- Android: Look for "Sign in to network" notification, tap to open
- iOS/iPad: Check for "Sign in to Wi-Fi" popup, tap to configure
- Windows: Wait for automatic browser popup (may take 10-30 seconds)
- Manual: Open browser and navigate to
http://192.168.4.1 - Alternative: Try
http://dtugateway.local(if device supports mDNS)
Problem: DTU connection fails
- Check: DTU IP address is correct in settings
- Test: Ping DTU IP from same network:
ping 192.168.1.100 - Fix: Ensure DTU is connected to same Wi-Fi network
Problem: Smart home integration not working
- MQTT: Verify broker settings, test with MQTT client
- openHAB: Check item names match exactly (case sensitive)
- API: Test endpoints directly in browser first
Problem: No power data showing
- Check: Inverter is producing power (sunny day, panels connected)
- Verify: DTU shows data in Hoymiles app
- Wait: Initial connection can take 2-3 update cycles (2 minutes)
Problem: Inconsistent data updates
- Normal: DTU connection issues happen, gateway auto-recovers
- Check: DTU signal strength in web interface
- Automatic: Gateway detects weak WiFi signals (< -75 dBm) and attempts reconnection
- Fix: Improve DTU Wi-Fi signal or move gateway closer
Problem: MQTT updates only appear every 15 minutes (just before cloudPause)
- Cause: Power limit was not set in the Hoymiles mobile app
- Solution: Open Hoymiles app β Device settings β Set power limit to any value (e.g., 100%)
- Result: After setting power limit, MQTT updates should appear every ~30 seconds with real-time data
- Technical Note: Power limit initialization is used as a synchronization point for data updates
Problem: Wrong timezone/time
- Fix: Set timezone offset in advanced config
- Note: DST adjusts automatically based on configured timezone
- Format: Seconds from UTC (3600 = +1h, -21600 = -6h)
Problem: Display not working
- Check: Wiring matches pinout tables exactly
- Test: Display type setting (OLED=0, TFT=1)
- Try: Factory reset and reconfigure display type
Problem: Display too dim/bright
- Fix: Adjust brightness in web interface (0-255)
- Night mode: Check night mode schedule settings
- TFT: Verify backlight wire connected to correct GPIO (GPIO4 for ESP32, GPIO12 for ESP8266)
Problem: Firmware update fails
- Check: Wi-Fi signal >50% during update
- Try: Stable release instead of snapshot
- Recovery: Factory flash complete firmware if device won't boot (see Step 2)
Problem: Settings corrupted/lost
- Fix: Serial connection β
resetToFactory 1 - Prevent: Don't power off during updates or config saves
Problem: Can't access web interface
- Find IP: Check router DHCP client list
- Try:
http://dtugateway.local(if mDNS works) - Reset: Factory reset and reconfigure
- Connect USB-to-serial adapter (115200 baud)
- Monitor debug output during operation
- Available Commands (send via serial terminal):
Basic Control:
setPower <watts>- Set power limit (e.g.,setPower 600)getDataAuto 1/0- Enable/disable automatic data collectiongetDataOnce 1/0- Trigger single data collectiondataFormatJSON 1/0- Toggle JSON format for data outputsetWifi 1/0- Enable/disable Wi-Fi connection
System Management:
resetToFactory 1- Factory reset (clears all settings)rebootDevice 1- Restart the ESP32 deviceprotectSettings 1/0- Enable/disable web interface settings protection
DTU/Inverter Control:
rebootDTU 1- Request DTU device rebootrebootMi 1- Request inverter microcontroller rebootdtuInverter 1/0- Turn inverter ON/OFF (1=ON, 0=OFF)getDtuAlarms 1- Request DTU alarm information
Configuration:
setInterval <seconds>- Set DTU update interval (minimum 31s)getInterval- Display current update intervalsetCloudSave 1/0- Enable/disable cloud error preventionselectDisplay 0/1- Choose display type (0=OLED, 1=Round TFT)
Example Usage:
setPower 400 # Set power limit to 400W
getDataAuto 1 # Enable auto data collection
resetToFactory 1 # Factory reset device
# Find device IP
nmap -sn 192.168.1.0/24 | grep -B2 "dtuGateway"
# Test API endpoints
curl http://DEVICE-IP/api/info.json
curl http://DEVICE-IP/api/data.json
# Test MQTT (if using mosquitto)
mosquitto_sub -h BROKER-IP -t "dtuGateway_+/+/+"- Web interface β DTU tab β Check connection status
- Look for "DTU reboots" counter (should be low)
- Check "last response" timestamp (should update every ~31 seconds)
- Check firmware versions: Verify DTU and inverter firmware versions in system info (
/api/info.json) - Warning icon shows DTU alerts if any
- Check logs: Serial console output helps diagnose issues
- Test basics: API endpoints, ping tests, LED indicators
- Community: GitHub Discussions
- Bug reports: GitHub Issues with serial logs
Test snapshot releases and report issues to help development:
- Try new features: Enable snapshot updates in advanced config
- Report bugs: Include serial logs and detailed steps to reproduce
- Share feedback: What works well? What could be improved?
- Community support: Help other users in GitHub Discussions
Your testing helps make the next stable release better for everyone!
Access advanced settings at: http://<device-ip>/config
Webserver Port: 80 # Change web interface port
DTU Data Cycle: 31 # Seconds between DTU requests (min 31)
Cloud Pause: 30 # Hoymiles cloud coordination time
Connection Timeout: 10 # DTU connection timeoutDisplay Type: 0/1 # 0=OLED, 1=Round TFT
Display Orientation: 0-270 # Rotation angle (TFT only)
Brightness Day: 150 # Day brightness (0-255)
Brightness Night: 30 # Night brightness (0-255)
Night Mode: true/false # Enable scheduled dimming
Night Mode Start: 1320 # Minutes from local midnight (22:00)
Night Mode End: 360 # Minutes from local midnight (06:00)
Night Clock: true/false # Show clock during night mode
Offline Trigger: true/false # Night mode when DTU offline
TFT Seconds Ring: true/false # Show red seconds ring (TFT)Timezone Offset: 3600 # Seconds from UTC
# Examples:
# 3600 = UTC+1 (CET)
# 7200 = UTC+2 (CEST)
# -21600 = UTC-6 (CST)
# 0 = UTCNote: DST (Daylight Saving Time) adjusts automatically based on timezone. Night mode times are automatically adjusted for DST - set times in local time and the system will handle DST transitions.
Update Channel: 0/1 # 0=Stable, 1=Snapshot
Auto Check Updates: true/false # Currently disabled due to ongoing refactoringUpdate Channel Details:
-
Stable (0): Only stable, thoroughly tested releases
- Recommended: For production use and most users
- Frequency: Every few weeks to months
- Quality: Extensively tested, minimal risk
-
Snapshot (1): Latest development builds
- For: Advanced users and testers
- Frequency: Multiple times per week
- Quality: May contain bugs, use with caution
- Benefits: Access to latest features and improvements
Update Behavior:
- Currently: Manual updates only via web interface
- Auto-check: Temporarily disabled during ongoing refactoring
- Manual process: Check for updates β Download β Flash via web interface
- Safety: All updates require manual confirmation (never automatic)
- Future: Automatic update notifications will be re-enabled after refactoring
# Via serial console only (115200 baud):
protectSettings 1 # Enable settings protection
protectSettings 0 # Disable settings protectionFor comprehensive setup guides, see Remote Display Setup Guide section above.
The Advanced Configuration section below provides quick reference for the API endpoints used by remote display modes.
Quick Reference (Full guides in main section):
- Remote Display (full mirror): See Scenario 1: Full Dashboard Mirror
- Solar Monitor: See Scenario 2: Solar Monitor
- Battery Monitor: See Scenario 3: Battery Monitor
- Combined Solar+Battery: See Scenario 4: Combined Solar + Battery Monitor
See the Solar Monitor subsection under Solar / Battery Monitor Mode for full details on aggregating solar sources, required MQTT topics, and configuration.
Override default topic structure:
Main Topic: custom_solar_123 # Instead of dtuGateway_XXXXX
HA Auto Discovery: ON/OFF # HomeAssistant integration
TLS Connection: ON/OFF # Secure MQTT (ESP32 only)
OpenDTU Topics: ON/OFF # Use OpenDTU-compatible topic structureOpenDTU Mode Effects:
- Topic Structure: Changes to OpenDTU-compatible format
- Auto-Discovery: Automatically disabled (not compatible with OpenDTU topics)
- Migration: Enables drop-in replacement for existing OpenDTU setups
- Manual Setup: Requires manual Home Assistant sensor configuration
# Optimize for your setup:
DTU Data Cycle: 31-300 # Faster updates = more DTU stress
DTU Timeout: 30 seconds # Extended timeout for weak connections
WiFi Signal Threshold: -75 dBm # Automatic reconnection trigger for poor signal
Cloud Pause Time: 0-60 # Coordinate with Hoymiles cloud
Connection Retries: 3-10 # DTU connection attempts
Wi-Fi Power: 20.5dBm # Reduce if interference issuesFor users wanting to run dtuGateway as a reliable background service without displays or manual monitoring.
dtuGateway is designed to run continuously in the background, providing real-time solar data to your smart home system with minimal manual intervention. Once configured, it handles all DTU connection issues automatically and recovers from network interruptions.
- No display required β Works perfectly without OLED or TFT displays
- Just ESP32 + DTU connection (Wi-Fi)
- Optional: Outdoor placement, weatherproof enclosure
- Flash firmware to ESP32
- Connect to setup Wi-Fi:
dtuGateway_XXXXXX - Configure:
- Home WiFi SSID and password
- DTU IP address
- MQTT broker IP (or openHAB IP)
- Device connects automatically and starts publishing data
- Device automatically polls DTU every ~31 seconds
- Publishes data to MQTT broker
- Handles DTU reconnections automatically
- No manual monitoring needed
DTU Connection Loss:
- Automatically detects when DTU stops responding
- Waits for DTU to come back online
- Retries connection every 30 seconds (configurable)
- No manual restart needed
WiFi Disconnection:
- Automatically reconnects to WiFi
- Weak signal detection and recovery
- Stays connected even with intermittent connectivity
Power Loss:
- Restarts automatically when power returns
- Resumes polling and data publishing without intervention
Inverter Reboot:
- DTU automatically re-establishes connection
- Gateway continues sending data within ~1 minute
| Scenario | Behavior | Recovery Time |
|---|---|---|
| DTU offline 10 min | Stops polling, waits | <1 minute after DTU returns |
| WiFi drops 30 sec | Buffers/stops MQTT | <1 minute reconnection |
| Inverter reboots | Pauses polling | <2 minutes reconnection |
| Hoymiles cloud issues | Uses cloud pause feature | ~30 sec retry |
| Power failure | Restarts device | Full restart ~20 sec |
DTU Update Cycle: 31 # Default, proven stable
DTU Connection Timeout: 10 # Reasonable timeout
Cloud Pause: 30 # Coordinate with cloud
Retry Strategy: Aggressive # Default settings
WiFi Power Level: 20.5 dBm # Full powerDTU Update Cycle: 60-120 # Polling every 1-2 minutes instead of 31s
Display: Disable # No display = less power
WiFi Power Level: 10 dBm # Lower (may reduce range slightly)DTU Connection Timeout: 15-20 # Extended timeout
DTU Retry Count: 5-10 # More aggressive retries
Cloud Pause: 60 # Longer coordination windowdtuGateway (no display, no web access needed)
β (Polls DTU every ~31s)
Your Hoymiles Inverter
β
MQTT Broker
β (Subscribed by)
Home Assistant / openHAB / Node-RED / etc.
β
Your automations and dashboards
What you can do (from Home Assistant/openHAB):
- β Monitor real-time power
- β Set power limits
- β Reboot DTU/inverter
- β Check system health
- β Create automations (e.g., "alert if offline")
What you can't do (without web interface):
- β Change WiFi network (need to factory reset)
- β Adjust polling interval (need to factory reset)
- β Update firmware over-the-air (need web interface)
Subscribe to these topics to monitor device health:
dtuGateway_XXXXX/dtuGW_special/
βββ dtu_connection_online β 0=offline, 1=online
βββ dtu_connect_state β Connection state code
βββ inverter_control_state_on β Inverter power state
βββ warnings_active β Active warning count
βββ timestamp β Last update time
Example Home Assistant automation (alert if offline):
- alias: Solar System Offline Alert
trigger:
- platform: state
entity_id: binary_sensor.dtugateway_dtu_online
to: "off"
for:
minutes: 5
action:
- service: notify.mobile_app_yourphone
data:
message: "Solar system offline for 5 minutes"dtuGateway publishes timestamp every time DTU responds:
- No timestamp update for >2 minutes = DTU offline
- Use this for automations or monitoring
If using openHAB:
- Items automatically populate with inverter data
- Monitor using openHAB rules and persistence
- Create sitemaps without web interface access
βββββββββββββββββββββββ
β ESP32 (no case) β
β (no display) β
β (powered 5V USB) β
ββββββββββββ¬βββββββββββ
β WiFi
Your Home Network
β
MQTT Broker (or HA)
βββββββββββββββββββββββββββ
β ESP32 in weatherproof β
β enclosure β
β (outdoor placement) β
β (5V power supply) β
ββββββββββββ¬βββββββββββββββ
β WiFi (directed antenna)
Your Home Network (mesh or AP nearby)
β
HA/openHAB with MQTT
β
Cloud backup (HA Cloud, etc.)
- Placement: Inside (near router) or outside (weatherproof enclosure)
- Power: USB power supply (usually in garage/attic)
- WiFi: Should see signal >-75 dBm (device shows in logs/MQTT)
- MQTT Broker: Can be on same home server as HA/openHAB
- Check MQTT timestamp topic hasn't changed
- Check DTU connection status via MQTT (
dtu_connection_online) - Check WiFi signal (MQTT topic:
inverter/WifiRSSI) - If DTU offline: restart inverter or check DTU WiFi
- If WiFi offline: check home network status
- Check DTU IP is correct (Device settings β DTU section)
- Check DTU WiFi signal (may need to move ESP32 closer)
- Increase DTU connection timeout (Advanced settings)
- Check if DTU is in power-saving mode
- Verify MQTT broker is running
- Check MQTT broker IP and port are correct
- Check username/password if required
- Verify ESP32 can reach MQTT broker (WiFi network)
- Check firewall rules for MQTT port
- Check power supply voltage (must be stable 5V)
- Check for WiFi disconnections (reduce WiFi power if interference)
- Check DTU for errors (may be crashing)
- Monitor serial output if accessible
Via Serial Console (if attached):
- Connect serial monitor at 115200 baud
- See all connection attempts and errors
- Useful for diagnostics
Via MQTT:
- All status visible in MQTT topics
- Home Assistant shows all entities
- Can create history/graphs for long-term monitoring
No centralized log file (by design for low-memory ESP32):
- Logs are ephemeral
- Best monitoring is via MQTT status and HA history
Fully automated with GitHub Actions
- Develop branch: Latest development code with new features
- Automatic builds: Every push to
developtriggers snapshot release - Snapshot releases: Available for testing before stable release
- Stable releases: Thoroughly tested production releases
- Issue Creation: Start with a GitHub issue describing the feature/bug
- Feature Branch: Create issue-based branch from latest
developusing GitHub's "Create a branch" button - Development: Implement changes in the feature branch (e.g.,
feature/123-add-new-display-support) - Pull Request: Submit PR from feature branch β
developbranch - Review & Merge: Code review, testing, then merge to
develop - Auto-build: GitHub Actions automatically builds and creates snapshot release
- Community Testing: Snapshot available for testing and feedback
- Stable Release: After validation period,
developβmainfor stable release
- Manual updates: Check for updates via web interface
- OTA support: Over-the-air updates when available
- Future enhancement: Automatic update notifications planned
- Manual control: All updates require user confirmation
# Install PlatformIO
pip install platformio
# Clone repository
git clone https://github.com/ohAnd/dtuGateway.git
cd dtuGateway# Create version file (required for local builds)
echo "localDev" > include/buildnumber.txt
# Build for ESP32
pio run -e esp32
# Upload to device
pio run -e esp32 -t upload
# Monitor serial output
pio device monitordtuGateway/
βββ src/ # Main source code
β βββ dtuGateway.ino # Main firmware file
β βββ Config.cpp # Configuration management
β βββ dtuInterface.cpp # DTU communication
β βββ mqttHandler.cpp # MQTT functionality
βββ include/ # Header files and web assets
β βββ web/ # Web interface files
β βββ proto/ # Protocol buffer definitions
β βββ base/ # Base functionality
βββ platformio.ini # Build configuration
βββ doc/ # Documentation and assets
The device exposes REST endpoints for integration:
GET /api/data.json # Real-time solar data
GET /api/info.json # System information
GET /style.css # Web interface styles
GET /jquery.min.js # JavaScript dependencies
POST /config # Configuration updatesWe welcome contributions and testing from the community!
- Download snapshot release: Get latest development build
- Test thoroughly: Check all functions you use regularly
- Report issues: Use GitHub Issues with detailed logs
- Share feedback: Discuss in GitHub Discussions
- Create/Find Issue: Start with a GitHub issue describing the feature or bug
- Fork the repository to your GitHub account
- Create Feature Branch:
- Use GitHub's "Create a branch" button on the issue page
- Branch from latest
develop(notmain) - Use descriptive names:
feature/issue-number-descriptionorbugfix/issue-number-description
- Develop & Test:
- Make changes in your feature branch
- Test locally with PlatformIO:
pio run -e esp32 - Ensure code follows project conventions
- Pull Request:
- Submit PR from your feature branch β
developbranch - Reference the original issue in PR description
- Include testing details and any breaking changes
- Submit PR from your feature branch β
- Review Process: Maintainer review, community feedback, automated testing
- Merge: After approval, branch gets merged into
developand triggers snapshot build
When reporting bugs, please include:
- Device info: ESP32 model, display type
- Firmware version: Stable or snapshot with version number
- Serial logs: Connect via USB and capture debug output (115200 baud)
- Steps to reproduce: Detailed description of the issue
- Configuration: Relevant settings (remove sensitive data)
- DTU Communication: Protocol Buffers over HTTP
- Data Format: JSON REST API and MQTT
- Update Mechanism: OTA via HTTP with checksum verification
- Configuration: JSON storage in ESP32 flash filesystem
- Captive Portal: Universal cross-platform detection with comprehensive endpoint coverage
- DNS Server: Redirects all DNS queries to ESP32 AP IP (192.168.4.1)
- Platform Detection: Automatic handling of Android, iOS, Windows, and macOS captive portal probes
- Endpoint Coverage:
/generate_204,/hotspot-detect.html,/connecttest.txt,/wpad.dat,/autodiscover/autodiscover.xml - Fallback Handling: Graceful redirect to configuration page for unrecognized requests
Older ESP8266 version maintained at: https://github.com/ohAnd/dtuGateway/tree/esp8266_maintenance
Limitations: Basic functionality only, no advanced features.
- v2.x: ESP32 with advanced features, displays, TLS, device info extraction, intelligent WiFi management
- v1.x: ESP8266 basic functionality (maintenance only)
- Snapshot: Latest development features including DTU/inverter firmware version detection and weak connection handling
- Memory: Occasional resets after extended operation (days/weeks) - optimized code reduces RAM usage
- DTU Stability: ~31 second minimum polling to avoid DTU hangs
- Connection Management: Automatic WiFi reconnection for signals below -75 dBm RSSI
- TLS: Only available on ESP32 platform
- Display: Factory mode alternates display types until configured
- Development: Features added to
developbranch - Testing: Snapshot releases for community testing
- Validation: Stable operation across different setups
- Release: Tagged stable release with documentation
- Distribution: Automatic binary builds via GitHub Actions
- Documentation: This README and inline code comments
- Community: GitHub Discussions
- Bug Reports: GitHub Issues
- Development: Pull requests welcome with tests
Note: The project originally supported ESP8266, but due to memory and feature limitations, a maintenance branch is available for basic functionality only.
Repository: esp8266_maintenance
Features available:
- β Basic DTU connection and data reading
- β Simple web interface
- β Basic MQTT publishing
- β openHAB integration
Not available on ESP8266:
- β TLS/SSL connections
- β Advanced display support
- β Home Assistant auto-discovery
- β OTA updates
- β Advanced configuration options
Recommended: Upgrade to ESP32 for full feature set and continued development support.
Benefits of ESP32:
- More memory and processing power
- TLS support for secure MQTT
- Advanced display options with night mode
- Home Assistant auto-discovery
- OTA updates and recovery options
- Active development and new features
Thank you for choosing dtuGateway! πβ‘ Transform your solar setup into a smart, connected system.
This user-friendly README was created collaboratively between the project maintainer and GitHub Copilot to provide better onboarding and support for dtuGateway users. The goal was to transform technical documentation into an accessible, step-by-step guide that helps users successfully set up and integrate their solar monitoring system.
Feedback welcome! If you find areas for improvement or have suggestions for making this documentation even better, please share them in GitHub Discussions.






