Async worker for Overkiz DHW schedule enforcement with Prometheus metrics.
  • Python 86.2%
  • Makefile 10.8%
  • Dockerfile 3%
Find a file
François Schmidts 8c487f57cd
Some checks failed
Docker / lint (push) Has been cancelled
Docker / push (push) Has been cancelled
docs: add no co-author commit rule
2026-03-09 23:13:25 +01:00
.claude fix(config): rename server_type to servertype 2026-02-24 11:05:09 +01:00
.forgejo/workflows feat(ci): add Forgejo Actions workflow and release target 2026-03-03 12:07:44 +01:00
overkiz_worker feat(schedule): add configurable default_state 2026-02-24 14:20:04 +01:00
tests feat(schedule): add configurable default_state 2026-02-24 14:20:04 +01:00
.gitignore feat(worker): merge runner + exporter into overkiz-worker 2026-02-24 10:48:11 +01:00
CLAUDE.md docs: add no co-author commit rule 2026-03-09 23:13:25 +01:00
Dockerfile feat(ci): add Forgejo Actions workflow and release target 2026-03-03 12:07:44 +01:00
Makefile feat(ci): add Forgejo Actions workflow and release target 2026-03-03 12:07:44 +01:00
poetry.lock feat(worker): merge runner + exporter into overkiz-worker 2026-02-24 10:48:11 +01:00
pyproject.toml feat(worker): merge runner + exporter into overkiz-worker 2026-02-24 10:48:11 +01:00
README.md docs: add Overkiz API states reference 2026-03-09 23:12:27 +01:00

overkiz-worker

Async service for Overkiz DHW (Domestic Hot Water) appliances: schedule-based state enforcement and Prometheus metrics exporter.

Features

  • Schedule enforcement -- define time-of-day periods with target shower counts or absence mode; the worker reconciles actual device state every N seconds
  • Prometheus exporter -- all Overkiz device states exposed as gauges at /metrics
  • REST API -- manual absence override via POST /DELETE /api/absence
  • Health check -- /health liveness probe

Configuration

Single JSON file at ~/.config/overkiz_worker.json or /etc/overkiz-worker/config.json:

{
  "credentials": [
    {"username": "...", "password": "...", "servertype": "ATLANTIC_COZYTOUCH"}
  ],
  "appliance": "io://xxxx-xxxx-xxxx/yyyyy",
  "schedule": {
    "timezone": "Europe/Paris",
    "default_state": 0,
    "periods": [
      {"start": "05:30", "end": "06:30", "state": 3},
      {"start": "17:00", "end": "22:00", "state": 3}
    ]
  },
  "enforcement": {"interval": 300},
  "exporter": {"poll_interval": 60},
  "api": {"port": 8000, "username": "admin", "password": "secret"}
}

Running

python3 -m overkiz_worker

Docker

make build
docker run -v /path/to/config.json:/etc/overkiz-worker/config.json -p 8000:8000 overkiz-worker:main

Build

make build

Release

Bump the version, commit, and tag in one step:

make release

Docker tags

Trigger Tags
Push to main :latest
Semver tag (e.g. 1.2.3) :v1, :v1.2, :v1.2.3
Other tag :{tag}

CI/CD

The Forgejo Actions workflow (.forgejo/workflows/docker.yaml) runs linting and pushes Docker images on every push to main or any tag.

Repository configuration

Name Type Description
DOCKER_REGISTRY Variable Registry URL (e.g. registry.example.com/user)
DOCKER_USERNAME Secret Registry username
DOCKER_PASSWORD Secret Registry password/token

Overkiz API States Reference

The Overkiz cloud API exposes device states whose names and semantics are not officially documented. Everything below is derived from community reverse-engineering (pyoverkiz, ha-overkiz, Cozytouch traffic analysis) and observed behaviour on Atlantic/Thermor heat-pump water heaters.

Naming convention

Pattern Meaning
XxxState Read-only sensor or calculated value
ControlXxxState Writable command to change the corresponding value

Temperature states

State Type Description
MiddleWaterTemperatureState sensor Actual water temperature from the mid-tank probe
MiddleWaterTemperatureInState sensor Incoming cold water (inlet) temperature — affects heat-pump COP
TargetDHWTemperatureState setpoint User-configured comfort target (e.g. 55 °C), persists across mode changes
WaterTargetTemperatureState effective setpoint Target the controller is actually aiming for right now — may differ from TargetDHW in absence, eco, or boost mode
ControlWaterTargetTemperatureState command Writable: send a new target temperature to the device

Volume & shower states

State Type Description
V40WaterVolumeEstimationState calculated Estimated litres of usable water at 40 °C (hot water mixed with cold)
RemainingHotWaterState calculated Remaining hot water as a percentage (0100)
ExpectedNumberOfShowerState calculated Estimated showers available (based on V40 and a per-shower volume assumption ~40 L)
NumberOfShowerRemainingState calculated Similar to above, may update in real-time as water is drawn
NumberControlShowerRequestState command Writable: number of showers you request the heater to prepare for

Energy consumption states

State Type Description
ElectricEnergyConsumptionState sensor Total cumulative energy consumed (Wh)
ConsumptionTariff1State sensor Energy consumed during tariff 1 (off-peak / heures creuses)
ConsumptionTariff2State sensor Energy consumed during tariff 2 (peak / heures pleines)

Tariff1 + Tariff2 ≈ ElectricEnergyConsumption. On a single-rate contract, all consumption lands in Tariff1 while Tariff2 stays at 0. These are monotonically increasing counters — diff over time to compute periodic consumption.

Note: Exact semantics may vary by device model (Aqueo ACI, Calypso, Lydos, etc.). When in doubt, toggle a mode (absence, boost) and observe which states change.

DWH State Model

State Meaning
0 Absence mode (fake +1yr vacation)
1-5 Expected shower count