ESP32-C6 based Tigo CCA replacement for local TAP polling, MQTT export and Home Assistant integration.
Reverse engineering, firmware and tooling for local Tigo TS4 monitoring over the TAP RS485 interface, including a live-validated CCA-compatible startup replay.
Unofficial community project, not affiliated with or endorsed by Tigo.
openTAPtoX runs on an ESP32-C6, talks directly to the Tigo TAP over RS485, decodes optimizer telemetry and republishes it locally via MQTT and a built-in web UI. The original Tigo CCA is no longer required for normal operation.
The project is currently in field-test status. Local monitoring, MQTT export and the web UI are usable. TAP/optimizer provisioning is implemented as a guarded recovery state machine, but full commissioning across arbitrary existing installations is not yet considered proven. The firmware records the TAP version, raw pending/confirmed node state, network status, and a redacted fingerprint of the persistent RF profile.
The repository currently contains:
- CCA-free gateway firmware for
ESP32-C6 - MQTT export for live per-node and summary telemetry
Home Assistantintegration via MQTT discovery- a local web UI for status, runtime control, discovery and label assignment
- a live frame view, MQTT runtime settings and web-triggered ESP reboot control
- TAP firmware/version readout in the web UI header once TAP communication is established
- RF channel/PAN/profile diagnostics with explicit, persisted apply/rollback safeguards
- runtime polling control via web UI/API and MQTT command topic
- protocol-analysis notes, captures and hardware documentation
- a small regression check under
tools/
firmware/openTAPtoX_esp32c6/ESP32-C6build using native UART andPreferences/ NVS. RS485 is wired asGPIO20= RX andGPIO19= TX.
Practical sizing guidance with the current firmware architecture:
the stable target range is roughly 32-48 optimizers with the current feature set. The firmware limit is 64, with headroom depending on traffic level, MQTT usage and how much web/UI activity is happening.
These counts are practical estimates based on current RAM usage and data structures, not protocol-imposed limits.
The ESP32-C6 controller connects to the TAP-side RS485 bus and your local network. The TAP still handles the wireless link to the TS4 optimizers, while openTAPtoX replaces the CCA-side controller role for polling, decoding and publishing telemetry.
The required hardware is compact enough to fit inside the existing TAP enclosure: the ESP32-C6 controller, RS485 converter and DC/DC power module can be placed inside the TAP housing instead of leaving external electronics dangling outside. This allows a clean installation within the TAP's existing IP68 enclosure. A documentation photo of this installation will be added later.
- replaces the Tigo CCA for day-to-day local monitoring
- receives and processes TAP traffic on
ESP32-C6 - decodes live telemetry such as voltage, current, real input power (
vin * iin), temperature, RSSI and duty cycle - auto-discovers optimizer node IDs and long addresses from TAP traffic and node-table exchanges
- publishes retained MQTT state and per-value telemetry topics
- publishes retained MQTT discovery topics for
Home Assistant - exposes a local web UI for status, firmware/TAP version, detected nodes and panel label assignment
- shows the decoded TAP version near the top of the web UI, for example
Mgate Version H1.0004, build timestamp andGW-H158.7.00 - exposes live last-frame decoding, MQTT server settings and reboot controls in the web UI
- allows RS485 polling to be enabled or disabled at runtime via web UI/API or MQTT, and persists the setting
- can automatically enumerate a factory-fresh TAP onto the desired gateway ID when polling gets no TAP responses
- replays the captured CCA STORE/address/radio/learn/join startup order and maintains profile-bound
0x41state for unattended restarts - runs a state-based commissioning flow with exact node-table readback, pending/confirmed tracking and timed learn-window maintenance
- detects stale TAP RF profiles and blocks automatic table changes until an operator explicitly resolves the mismatch
- publishes discovered-node status entries even before a panel label is assigned
- persists panel mappings locally on the controller
- only writes persistent controller state when durable data actually changes
- keeps reverse-engineering reference material under
docs/anddata/
If no panel label is configured yet, nodes are published with fallback names such as Tigo Node 8.
Published power is the real measured input power vin * iin.
Vout is not considered for the power calculation.
- Tested with two TAP units on the bench. Both reported the same version payload:
Mgate Version H1.0004,Mar 3 2023,09:56:23,GW-H158.7.00. - The firmware can query that TAP version with command
0x000Aand display the decoded0x000Bresponse in the web UI. - CCA node-table writes use raw IDs
0x8002through0x800B; bit 15 means pending/unconfirmed. Healthy tables normally contain low IDs, but a low-ID table can still be stale, so0x2Fconfirmation and real0x31telemetry remain the success criteria. - TAP
04C05B3000069613was provisioned onto channel 16 and later carried all ten optimizers. TAP04C05B300006B064retained an older channel-12 RF profile; the CCA read but did not replace it during the failed second-TAP setup. - Correct RF profile is necessary but not sufficient: the profile-correct TAP also spent time at
0/10and later1/10, proving that each optimizer still has to complete the learn/authentication transition. 0x2B BABEis now identified as table clear/reset,0x29as EUI-64/node-ID table write, and0x2D BABE020384...0100as a 900-second learn-window operation.0x41is site-specific maintenance/transition traffic, not a universal discovery command.- On TAP
04C05B3000069613, the complete replay restored Growatt string output repeatedly. A controlled profile-B recovery reached333.8 Vand resumed inverter output after about 91 seconds. A later direct field run then produced topology and more than 4,000 real0x31power reports for A1. This proves the profile-B replay and A1's RF relationship; the remaining nine pending optimizers still need their own discovery/authentication transition. 0x0146/0002and matching0x0B10envelopes are TAP-level acknowledgements, not optimizer RF receipts. The firmware now marks these asRF unconfirmed; a topology report or a real0x31packet is required as RF evidence.- A live profile A/B test ruled out the second TAP's older channel-12 profile: profile A produced
3.5 V / 0 Wand no joins, while restoring profile B on channel 16 immediately restored the full string voltage. The correct RF profile is therefore proven electrically even though optimizer authentication remains incomplete. - The complete corpus-wide evidence, confidence levels and reversible B064 A/B procedure are in
docs/analysis/tap_startup_protocol_reverse_engineering_2026-07-16.md.
firmware/Controller-specific firmware builds, shared firmware headers underfirmware/common/, and target-specific notesdocs/analysis/Reverse-engineering reports, decoded timelines and mapping notesdocs/hardware/Wiring and controller notesdata/captures/Raw TAP captures used during protocol analysisdata/telemetry/Historical telemetry datasets used for validationtools/Small repository checks and helper scripts
firmware/openTAPtoX_esp32c6/config.hMain build-time settings: firmware version, WiFi/AP defaults, MQTT defaults, RS485 pins, polling intervals and optimizer limits.firmware/openTAPtoX_esp32c6/openTAPtoX_esp32c6.inoTiny Arduino sketch entry point. Start here to see how setup and loop hand control to the application.firmware/openTAPtoX_esp32c6/opentaptox_esp32c6_app.cppMain controller implementation: WiFi, web API, MQTT, TAP polling, frame handling, persistence and runtime state.firmware/common/protocol.hTAP frame parser and wire-format helpers. Useful when trying to understand how raw RS485 bytes become decoded frames.firmware/common/models.hShared data structures for frames, node mappings, power reports, events and persisted controller state.tools/check_repo.shOne-command sanity check that runs the power-semantics regression and compiles the ESP32-C6 firmware.tools/decoder/tigo_tap_decoder_v2.pyandtools/decoder/analyze_tap_corpus.pyMulti-format protocol decoder and reproducible whole-corpus indexer, including compressed and support-logger captures.docs/handover_2026-05-23_tap_cca_rs485_session.mdCurrent field handover for the 2026-05-23 to 2026-05-25 TAP/CCA/RS485 sessions, including OTA notes, capture findings and next test steps.
The shared firmware headers are provided as a local Arduino library under firmware/common/.
When building with arduino-cli, pass this path as an additional library, for example:
arduino-cli compile --libraries /abs/path/openTAPtoX/firmware/common --fqbn esp32:esp32:esp32c6 firmware/openTAPtoX_esp32c6
bash tools/check_repo.shIf the ESP32-C6 cannot connect to the configured WiFi network, it starts a fallback access point:
- SSID:
openTAPtoX-setup - Password:
opentaptox
This default password is intended as a basic guard against accidental access, not as strong site security.
This project is licensed under the MIT license. See LICENSE.
Parts of the protocol understanding behind openTAPtoX were informed by
willglynn/taptap, which documents and implements local
monitoring over the Tigo TAP communication cable.




