A Home Assistant custom integration for "Mobius"-protocol aquarium equipment (EcoTech Marine VorTech/Radion, AquaIllumination, NYOS Quantum, etc.)
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Carlos Mogas da Silva 7bffe43f4e
All checks were successful
Release / test-1 (push) Successful in 5m10s
Release / test (push) Successful in 0s
Release / hacs (push) Successful in 40s
Release / hassfest (push) Successful in 1m45s
Release / validate (push) Successful in 0s
Validate / hacs (push) Successful in 40s
Validate / hassfest (push) Successful in 2m1s
Test / test (push) Successful in 4m23s
Release / release (push) Successful in 51s
release 0.7.0
2026-09-02 09:27:55 +01:00
.forgejo install python-mobius from git in CI 2026-09-01 10:10:19 +01:00
.github/ISSUE_TEMPLATE add GitHub issue template config redirecting issues to the actual Forgejo repository 2026-08-05 10:19:49 +01:00
custom_components/mobius release 0.7.0 2026-09-02 09:27:55 +01:00
esphome add missing bt-proxy example 2026-08-23 22:54:39 +01:00
tests add scene selection and configured-scenes entities 2026-09-01 23:45:29 +01:00
.gitignore initial import 2026-07-31 00:19:04 +01:00
CHANGELOG.md release 0.7.0 2026-09-02 09:27:55 +01:00
hacs.json fix newly-discovered devices sometimes never appearing; bump min HA version to 2026.7.0 2026-08-12 21:29:58 +01:00
LICENSE Add GPLv2 LICENSE 2026-07-31 00:24:22 +01:00
pytest.ini suppress known pytest-socket BlueZ warning 2026-08-13 23:22:21 +01:00
README.md fix ESP32-S3 quantity wording 2026-08-23 22:07:11 +01:00
requirements_test.txt fix newly-discovered devices sometimes never appearing; bump min HA version to 2026.7.0 2026-08-12 21:29:58 +01:00

ha-mobius

A Home Assistant custom integration for "Mobius"-protocol aquarium equipment (EcoTech Marine VorTech/Radion, AquaIllumination, NYOS Quantum, etc.), built on python-mobius.

Not affiliated with or endorsed by any of these companies. See python-mobius's own documentation for the full protocol writeup this is built on.

Status

This integration does discovery and status reporting for every supported device, plus two narrow write operations: a reboot button for every device, and an automatic hourly clock sync for each tank. General control (starting scenes, changing schedules) isn't implemented yet — that's a deliberate choice, not a limitation of the underlying library: control support is being kept in lockstep with python-mobius itself as it grows write capabilities, rather than getting ahead of it.

Development / running the tests

git clone https://code.r3pek.org/r3pek/ha-mobius
cd ha-mobius
pip install -r requirements_test.txt
pip install python-mobius bleak-retry-connector
pytest tests/

requirements_test.txt pins the exact pytest-homeassistant-custom-component version this integration's own CI is confirmed to pass against (see that file's own comments for why); CI (.forgejo/workflows/test.yml) additionally reads custom_components/mobius/manifest.json's own requirements at test time, so runtime dependencies never have to be duplicated by hand.

What it does

  • Autodiscovery: Home Assistant's own Bluetooth integration triggers setup automatically when it sees a device advertising as MOBIUS (or matching the confirmed manufacturer ID 0x0202) — no manual scanning needed. Manual setup (picking from already-seen-but-unconfigured devices) is also available via Settings → Devices & Services → Add Integration. A device split across multiple advertisement packets that don't all carry the identifying data (confirmed real, not hypothetical) is still found once the fuller packet arrives, rather than being silently missed.
  • Multi-device tanks: several devices sharing one Thread mesh are set up as a single tank, not one entry per device — one device relays for the others rather than each opening its own connection.
  • One Home Assistant device per physical device, with model, manufacturer, serial number, and firmware version ("Product OS" — confirmed via real hardware to be the most meaningful single "what firmware is this" answer, ported from the app's own display labels; see python-mobius's get_firmware_versions()) populated in the device registry.
  • Sensors (all read-only, diagnostic entities unless noted):
    • Every device: support tier, error state, schedule point count, mesh address (this device's own Thread mesh-local IPv6 address, with the time it was last heard from on the mesh as an attribute), firmware version (full per-component breakdown as attributes), hardware revision (full breakdown as attributes).
    • Pumps (all main entities, not diagnostic): operation state, motor speed, estimated flow, current pump mode.
    • Lights: one intensity sensor per channel (main entities, not diagnostic), reflecting the same client-side schedule interpolation python-mobius replicates from the official app — not a live device read (there isn't one; see python-mobius's docs on why). Also a diagnostic calibration sensor (completed True/False, plus last-calibration-date as an attribute) — confirmed via real hardware and the app's own UI gating to be light-specific; not added for pumps, which don't support it.
    • Per tank (a synthetic device, not any one physical one): which device currently holds the gateway role, and the mesh's own shared prefix.
  • Debug logging: enabling it (Settings → Devices & Services → Mobius → Enable debug logging) surfaces connection attempts, gateway elections and failovers, and mesh scans in detail — built specifically to make a real "why isn't this connecting" report diagnosable from the logs alone, not something to enable blind and hope helps.
  • Diagnostics download (entry's own three-dot menu → Download diagnostics) includes registry/coordinator state per device, and, critically, whether Home Assistant's own Bluetooth stack currently sees each device at all — independent of what this integration itself has cached — to tell "our own cached state is stale" apart from "Home Assistant hasn't seen this device recently" when nothing's connecting.

Polling design

Each device is polled every POLL_INTERVAL (30s) — the gateway's own direct read, or a relayed read through it, depending on role. A separate, much less frequent per-tank task handles maintenance that doesn't need to happen every poll cycle.

Install

Manual (works today, no GitHub/HACS needed)

Copy custom_components/mobius/ into your Home Assistant config/custom_components/ directory, then restart Home Assistant.

HACS

Open your Home Assistant instance and open a repository inside the Home Assistant Community Store.

Or manually: in HACS, Settings → Custom repositories → add https://github.com/r3pek/ha-mobius (type: Integration).

Bluetooth proxy hardware

Every Mobius device needs to be within Bluetooth range of something Home Assistant can talk to — either the HA host's own adapter, or an ESPHome Bluetooth proxy. A tank is rarely right next to the server, so a proxy placed near the tank itself is the practical way to get reliable connections and RSSI-based gateway election (see "Polling design" above).

What's actually been used and confirmed working, for reference — not the only option, just one that works:

(Amazon affiliate links)

An example ESPHome configuration for the ESP32-S3 board as a Bluetooth proxy is in esphome/mobius-bt-proxy.yaml. The important setting in it is bluetooth_proxy: active: true — this integration needs actual GATT connections (reading/writing attributes), not just advertisement forwarding, so a proxy in passive-only mode isn't enough.

Dependencies

python-mobius and bleak-retry-connector are declared in manifest.json and installed automatically by Home Assistant when the integration loads — no separate pip install needed.

License

GPLv2 — see LICENSE.