An implementation of the Tigo TAP protocol
MIT License
taptap
This project implements the Tigo TAP protocol, especially for the purpose of monitoring a Tigo TAP and the associated solar array using the TAP's communication cable. This allows 100% local offline data collection.
The TAP protocol is described at docs/protocol.md
.
This system uses two networks, a wired "gateway network" and a wireless "PV network":
Gateway PV device
device (TAP) (optimizer)
┌─────────────────┐ ┌─────────────────┐
PV ┌─▶│ Application │ │ Application │ Proprietary
network │ ├─────────────────┤ ├─────────────────┤ │
│ │ Network │ │ Network │ │
│ ├─────────────────┤ ├─────────────────┤
│ │ Link │ │ Link │ 802.15.4
│ ├─────────────────┤ ├─────────────────┤ │
│ │ Physical │ │ Physical │ │
│ └─────────────────┘ └─────────────────┘
│ ▲ ▲
│ └ ─ ─ ─ ─ ┘
│ ┌─────────────────┐
Gateway └─▶│ Transport │ Proprietary
network ├─────────────────┤ │
│ Link │ │
├─────────────────┤
│ Physical │ RS-485
└─────────────────┘
The gateway network runs over RS-485 and can support more than two connections. An owner may therefore connect a USB RS-485 adapter, or an RS-485 hat, or any other RS-485 interface without interrupting communication.
The gateway network supports a single controller. Most owners use a Tigo Cloud Connect Advanced (CCA), but there are
alternatives, including older Tigo products and similar controllers embedded in GoodWe inverters. taptap
can observe
the controller's communication, without ever transmitting anything; as far as the other components are concerned, it
does not exist. This allows owners to gather real-time information from their own hardware without going through Tigo's
cloud platform and without modifying the controller, their TAPs, or any other hardware in any way.
┌─────────────────────────────────────┐ ┌────────────────────────────┐
│ CCA │ │ TAP │
│ │ │ │
│ AUX RS485-1 GATEWAY RS485-2 POWER│ │ ┌~┐ │
│┌─┬─┐ ┌─┬─┬─┐ ┌─┬─┬─┬─┐ ┌─┬─┬─┐ ┌─┬─┐│ │ ┌─┬─┬─┬─┐ ┌─┬─┬│┬│┐ │
││/│_│ │-│B│A│ │-│+│B│A│ │-│B│A│ │-│+││ │ │-│+│B│A│ │-│+│B│A│ │
│└─┴─┘ └─┴─┴─┘ └│┴│┴│┴│┘ └─┴─┴─┘ └─┴─┘│ │ └│┴│┴│┴│┘ └─┴─┴─┴─┘ │
└───────────────│─│─│─│───────────────┘ └────│─│─│─│─────────────────┘
│ │ │ │ │ │ │ │
│ │ │ ┃───────────────────────────│─│─│─┘
│ │ ┃─┃───────────────────────────│─│─┘
│ └─┃─┃───────────────────────────│─┘
┃───┃─┃───────────────────────────┘
┗━┓ ┃ ┃
┌───┃─┃─┃───┐
│ ┌┃┬┃┬┃┐ │
│ │-│B│A│ │
│ └─┴─┴─┘ │
│ Monitor │
└───────────┘
taptap
consists of a library and an executable. The executable is a CLI:
% taptap
Usage: taptap <COMMAND>
Commands:
observe Observe the system, extracting data as it runs
list-serial-ports List `--serial` ports
peek-bytes Peek at the raw data flowing at the gateway physical layer
peek-frames Peek at the assembled frames at the gateway link layer
peek-activity Peek at the gateway transport and PV application layer activity
help Print this message or the help of the given subcommand(s)
Options:
-h, --help Print help
-V, --version Print version
% taptap observe --tcp 172.21.3.44
{"gateway":{"id":4609},"node":{"id":116},"timestamp":"2024-08-24T09:16:41.686961-05:00","voltage_in":30.6,"voltage_out":30.2,"current":6.94,"dc_dc_duty_cycle":1.0,"temperature":26.8,"rssi":132}
{"gateway":{"id":4609},"node":{"id":116},"timestamp":"2024-08-24T09:17:01.691683-05:00","voltage_in":30.75,"voltage_out":30.4,"current":6.895,"dc_dc_duty_cycle":1.0,"temperature":26.8,"rssi":132}
{"gateway":{"id":4609},"node":{"id":82},"timestamp":"2024-08-24T09:16:41.686961-05:00","voltage_in":30.55,"voltage_out":30.2,"current":6.845,"dc_dc_duty_cycle":1.0,"temperature":29.3,"rssi":147}
{"gateway":{"id":4609},"node":{"id":82},"timestamp":"2024-08-24T09:17:01.691683-05:00","voltage_in":30.95,"voltage_out":30.6,"current":6.765,"dc_dc_duty_cycle":1.0,"temperature":29.3,"rssi":147}
{"gateway":{"id":4609},"node":{"id":19},"timestamp":"2024-08-24T09:16:41.686961-05:00","voltage_in":30.35,"voltage_out":29.9,"current":6.865,"dc_dc_duty_cycle":1.0,"temperature":28.7,"rssi":147}
{"gateway":{"id":4609},"node":{"id":19},"timestamp":"2024-08-24T09:17:01.691683-05:00","voltage_in":29.85,"voltage_out":29.4,"current":7.005,"dc_dc_duty_cycle":1.0,"temperature":28.7,"rssi":147}
{"gateway":{"id":4609},"node":{"id":121},"timestamp":"2024-08-24T09:16:41.686961-05:00","voltage_in":29.8,"voltage_out":21.9,"current":5.25,"dc_dc_duty_cycle":0.7607843137254902,"temperature":29.8,"rssi":120}
{"gateway":{"id":4609},"node":{"id":121},"timestamp":"2024-08-24T09:17:01.691683-05:00","voltage_in":30.55,"voltage_out":22.8,"current":5.3,"dc_dc_duty_cycle":0.7725490196078432,"temperature":29.8,"rssi":120}
As of this initial version, the observe
subcommand emits taptap::observer::Event
s to standard output as JSON rather
than emitting metrics for InfluxDB or Prometheus, and it does not persist its own state, meaning the gateway and nodes
are identified by their internal IDs rather than by barcode. These are the next two features to add.