I replaced the Chihiros app entirely with an ESP32-S3 running ESPHome. All devices are exposed to Home Assistant as native entities — no cloud, no phone required.
Supported devices
-
CO2 Controller — Working

-
Magnetic Stirrer (4-channel) — Working

-
Cooling Fan — Working

-
Doctor Mate (TDS/EC meter) — Working

-
WRGB II light — Working

-
Dosing Pump — Working

How it works
All Chihiros devices use the Nordic UART Service (NUS) over BLE. Connections are non-persistent by design: the ESP32 connects, sends commands, then disconnects. Most devices store their schedule on an internal RTC, so you only reconnect when something changes.
A shared chihiros_ble.h header handles the full protocol — framing, CRC, sequence numbers, RTC sync, and per-device command sets. The YAML configs use this as a local ESPHome external component.
The protocol was reverse-engineered from Bluetooth HCI btsnoop logs captured with a rooted Android phone.
Frame format:
[header] [0x01] [len] [0x00] [seq] [cmd] [data...] [XOR-CRC]
What you get in Home Assistant
-
CO2: schedule tied to photoperiod with configurable pre-start offset
-
Stirrer: 4 channels on/off, speed sliders, interval timer, per-channel enable
-
Cooling fan: start/max temperature thresholds, silent mode toggle, live water temp + room temp + humidity sensors
-
Doctor Mate: TDS target (Plant/Fish/Shrimp presets or manual), tank volume, live EC sensor
-
WRGB2: auto schedule (RGB + ramp time + photoperiod) or manual brightness sliders per channel
-
Dosing pump: 3 pumps, per-pump weekly schedule (day/time/volume), manual dose button
Hardware
-
ESP32-S3-N16R8
-
Powered by USB or 5V
BLE 5.0 required — Chihiros devices use BLE 5.0 extended advertising, which is invisible to BLE 4.x hardware. A classic ESP32 will not detect them at all. The S3 is also recommended for its extra RAM when running the BLE scanner alongside multiple client connections.
GitHub: GitHub - BartdeJonge/chihiros-esphome · GitHub
Happy to answer questions about the protocol details. If you have a Chihiros device not on the list, I can help figure out the frames with btsnoop logs.