2026-09-30 12:02:28 +09:00
2026-09-30 12:02:28 +09:00
Fix
2026-09-25 21:20:34 +09:00

ZONT Prometheus Exporter

Экспортер телеметрии отопительных контроллеров ZONT (H-1V, H-1V.02, H1V02_PRO, H-1000, H-2000 и др.) в формате Prometheus.

Собирает текущее состояние устройства через облачное API my.zont.online и отдаёт метрики на HTTP-эндпоинт /metrics. Подходит для мониторинга в Grafana, алертинга в Alertmanager и любого стека, совместимого с Prometheus.


📋 Содержание


🚀 Возможности

  • Текущее состояние контроллера: онлайн-статус, напряжение питания, память, источник питания.
  • Связь: уровень GSM, состояние регистрации в сети, RSSI Wi-Fi, наличие связи с сервером ZONT.
  • Температуры: проводные и аналоговые датчики (в т.ч. «Погода из интернета»), статус исправности.
  • Отопление: целевая и заданная температура по каждому отопительному контуру, время работы.
  • Котёл / OpenTherm: расчётная температура теплоносителя, уставка ГВС, наличие связи с котлом, аварии.
  • Погода: температура с внешнего источника.
  • Аналоговые входы: напряжение на входах (например, контроль питания).

Работает как отдельный контейнер, не требует установки чего-либо на хост.


✅ Требования

  • Docker (или Docker Compose)
  • Аккаунт в личном кабинете my.zont.online с добавленным устройством ZONT
  • Сетевая доступность my.zont.online:443 из контейнера
  • Prometheus (опционально) для сбора метрик

🏁 Быстрый старт

1. Создайте файлы

Вам нужны два файла:

  • zont_exporter.py — код экспортера
  • Dockerfile — сборка образа

2. Соберите образ

docker build -t zont-exporter .

3. Запустите контейнер

docker run -d \
  --name zont-exporter \
  --restart unless-stopped \
  -p 9101:9101 \
  -e ZONT_LOGIN='your_login' \
  -e ZONT_PASSWORD='your_password' \
  -e ZONT_DEVICE_ID='554007' \
  -e ZONT_CLIENT='you@example.com' \
  zont-exporter

4. Проверьте

curl http://localhost:9101/metrics | grep zont_

Вы должны увидеть метрики вида:

zont_device_online{device_id="554007"} 1.0
zont_voltage_volts{device_id="554007"} 12.1
zont_gsm_level{device_id="554007"} 17.0
zont_temperature_celsius{device_id="554007",name="Температура гаража 150",object_id="8200"} 18.8
zont_boiler_connected{adapter_id="4096",device_id="554007"} 0.0

🔧 Переменные окружения

Переменная Обязательна По умолчанию Описание
ZONT_LOGIN ✅ — Логин от личного кабинета my.zont.online
ZONT_PASSWORD ✅ — Пароль от личного кабинета
ZONT_DEVICE_ID ✅ — Числовой ID устройства (см. ниже, как узнать)
ZONT_CLIENT ❌ my_exporter@example.com Контактный email для заголовка X-ZONT-Client. ZONT использует его для связи при изменениях API. Укажите свой.
SCRAPE_INTERVAL ❌ 60 Интервал сбора метрик, секунды. Не имеет смысла ставить меньше 30 — API не успевает обновлять данные.
EXPORTER_PORT ❌ 9101 Порт, на котором экспортер слушает /metrics внутри контейнера
LOG_LEVEL ❌ INFO Уровень логирования: DEBUG, INFO, WARNING, ERROR, CRITICAL. Регистр не важен.

Как узнать ZONT_DEVICE_ID

Способ 1. Через API (рекомендуется)

curl -s -X POST 'https://my.zont.online/api/devices' \
  -u 'login:password' \
  -H 'X-ZONT-Client: you@example.com' \
  -H 'Content-Type: application/json' \
  -d '{"load_io": true}' | python3 -m json.tool | grep -E '"id"|"name"|"serial"'

В ответе найдите блок своего устройства — поле "id" и есть ZONT_DEVICE_ID.

Способ 2. Через личный кабинет

Откройте устройство в веб-интерфейсе my.zont.online — ID обычно видно в URL страницы устройства.

Пример запуска с нестандартным портом и отладкой

docker run -d \
  --name zont-exporter \
  --restart unless-stopped \
  -p 9200:9200 \
  -e ZONT_LOGIN='your_login' \
  -e ZONT_PASSWORD='your_password' \
  -e ZONT_DEVICE_ID='554007' \
  -e ZONT_CLIENT='you@example.com' \
  -e EXPORTER_PORT='9200' \
  -e LOG_LEVEL='DEBUG' \
  zont-exporter

⚠️ Номера портов в -p <хост>:<контейнер> и EXPORTER_PORT должны совпадать по контейнерной части. Пример выше: EXPORTER_PORT=9200 и -p 9200:9200. Если хост-порт занят — используйте -p 8080:9200.


📊 Метрики

Все метрики имеют префикс zont_ и label device_id. Для удобства читаемые имена объектов (датчиков, контуров) добавляются как label name.

Общие

Метрика Тип Labels Описание
zont_device_online gauge device_id 1 — устройство на связи, 0 — offline
zont_device_last_receive_time gauge device_id Unix-время последнего пакета от устройства
zont_voltage_volts gauge device_id Напряжение основного питания, В
zont_power_source gauge device_id 1 — основное питание, 0 — иное
zont_memory_used_percent gauge device_id Использование памяти контроллера, %
zont_memory_used_bytes gauge device_id Использование памяти, байт
zont_internet_weather_celsius gauge device_id Температура с внешнего источника погоды, °C

Связь

Метрика Тип Labels Описание
zont_gsm_level gauge device_id Уровень сигнала GSM, 0–31
zont_gsm_state gauge device_id 0=not-registered, 1=home-network, 2=searching, 3=rejected, 5=roaming
zont_wifi_rssi gauge device_id Уровень сигнала Wi-Fi
zont_server_connected gauge device_id 1 — есть связь с сервером ZONT

Датчики температуры и аналоговые входы

Метрика Тип Labels Описание
zont_temperature_celsius gauge device_id, object_id, name Текущая температура, °C
zont_temperature_sensor_ok gauge device_id, object_id, name 1 — датчик исправен
zont_analog_voltage_volts gauge device_id, object_id, name Напряжение на аналоговом входе, В

Отопление

Метрика Тип Labels Описание
zont_heating_target_temp_celsius gauge device_id, circuit_id, name Фактическая целевая температура контура
zont_heating_setpoint_temp_celsius gauge device_id, circuit_id, name Заданная температура (уставка)
zont_heating_worktime_seconds gauge device_id, circuit_id, name Время работы контура за последнюю минуту, сек
zont_heating_status gauge device_id, circuit_id, name Код статуса контура

Котёл / OpenTherm

Метрика Тип Labels Описание
zont_boiler_cs_celsius gauge device_id, adapter_id Расчётная температура теплоносителя, °C
zont_boiler_ds_celsius gauge device_id, adapter_id Уставка температуры ГВС, °C
zont_boiler_connected gauge device_id, adapter_id 1 — котёл на связи, 0 — нет
zont_boiler_fail gauge device_id, adapter_id 1 — авария котла

🔌 Интеграция с Prometheus

Добавьте в prometheus.yml:

scrape_configs:
  - job_name: 'zont'
    scrape_interval: 60s
    scrape_timeout: 20s
    static_configs:
      - targets: ['zont-exporter:9101']
        labels:
          instance: 'home-boiler'

Если Prometheus работает в том же Docker-сети, используйте имя контейнера. Если на хосте — host.docker.internal:9101 (Windows/macOS) или IP хоста (Linux).

Docker Compose (пример)

services:
  zont-exporter:
    build: .
    container_name: zont-exporter
    restart: unless-stopped
    ports:
      - "9101:9101"
    environment:
      ZONT_LOGIN: "your_login"
      ZONT_PASSWORD: "your_password"
      ZONT_DEVICE_ID: "554007"
      ZONT_CLIENT: "you@example.com"
      SCRAPE_INTERVAL: "60"
      EXPORTER_PORT: "9101"
      LOG_LEVEL: "INFO"

🚨 Пример алертов

prometheus/rules/zont.yml:

groups:
  - name: zont
    rules:
      - alert: ZontDeviceOffline
        expr: zont_device_online == 0
        for: 10m
        labels:
          severity: critical
        annotations:
          summary: "ZONT {{ $labels.device_id }} offline"
          description: "Устройство не выходит на связь более 10 минут."

      - alert: ZontServerDisconnected
        expr: zont_server_connected == 0
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "ZONT {{ $labels.device_id }} потерял связь с сервером"

      - alert: ZontBoilerDisconnected
        expr: zont_boiler_connected == 0
        for: 15m
        labels:
          severity: warning
        annotations:
          summary: "ZONT {{ $labels.device_id }}: нет связи с котлом (адаптер {{ $labels.adapter_id }})"

      - alert: ZontBoilerFail
        expr: zont_boiler_fail == 1
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "ZONT {{ $labels.device_id }}: авария котла"

      - alert: ZontLowVoltage
        expr: zont_voltage_volts < 10
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "ZONT {{ $labels.device_id }}: низкое напряжение питания {{ $value }} В"

      - alert: ZontWeakGSM
        expr: zont_gsm_level < 5
        for: 15m
        labels:
          severity: warning
        annotations:
          summary: "ZONT {{ $labels.device_id }}: слабый сигнал GSM ({{ $value }})"

      - alert: ZontHighMemory
        expr: zont_memory_used_percent > 85
        for: 30m
        labels:
          severity: info
        annotations:
          summary: "ZONT {{ $labels.device_id }}: высокая загрузка памяти {{ $value }}%"

🩺 Диагностика

Метрики пустые или /metrics отдаёт только python_*

  1. Проверьте логи:

    docker logs zont-exporter --tail 100
    
  2. Если непонятно, что происходит, включите подробное логирование:

    docker run -d --name zont-exporter \
      -p 9101:9101 \
      -e ZONT_LOGIN='...' -e ZONT_PASSWORD='...' \
      -e ZONT_DEVICE_ID='554007' \
      -e ZONT_CLIENT='you@example.com' \
      -e LOG_LEVEL='DEBUG' \
      zont-exporter
    

    Затем смотрите логи:

    docker logs zont-exporter --tail 200
    

    В режиме DEBUG видны детали ответов API и структура io-объектов.

  3. Ищите в логах строки:

    • Successfully obtained ZONT auth token. — токен получен.
    • Failed to get auth token: ... — проблема с логином/паролем.
    • API error: ... — API вернул ошибку.
    • Device 554007 not found in account. — неверный ZONT_DEVICE_ID.
    • Metrics collected successfully for device ... — всё ок.

Ошибка SyntaxError: name 'auth_token' is used prior to global declaration

Объявление global auth_token должно стоять в самом начале функции, до любого использования переменной. В актуальной версии кода это уже учтено.

Ошибка аутентификации

Проверьте логин/пароль руками:

curl -s -X POST 'https://my.zont.online/api/get_authtoken' \
  -u 'login:password' \
  -H 'X-ZONT-Client: you@example.com' \
  -H 'Content-Type: application/json' \
  -d '{"client_name": "debug"}' | python3 -m json.tool

Ожидаемый ответ: {"ok": true, "token": "..."}.

Хочу больше данных (история, а не текущее состояние)

Метод devices отдаёт снимок текущего состояния. Историю (графики за период) можно получить через метод load_data с типами z3k_temperature, z3k_heating_circuit, z3k_boiler_adapter, ztc_state. Для этого требуется отдельная логика — при необходимости расширьте экспортер.


⚠️ Ограничения

  • Экспортер собирает только текущее состояние, не историю. Для графиков используйте load_data (см. выше) или смотрите графики в личном кабинете ZONT.
  • Работает только с устройствами, привязанными к аккаунту my.zont.online. Локальный доступ к контроллеру по USB/локальной сети не используется.
  • Тип thermostat_work через load_data для модели H1V02_PRO (H-1V.02) возвращает пустые массивы. Используйте данные из devices?load_io=true — там вся актуальная телеметрия.
  • Набор доступных полей в io.z3k-state зависит от модели, прошивки и конфигурации. Экспортер игнорирует отсутствующие поля — это нормально.
  • Требуется HTTPS-доступ к my.zont.online. При использовании прокси задайте HTTPS_PROXY в окружении контейнера.

🔒 Безопасность

  • Не храните логин/пароль в открытом виде в Docker Compose / systemd unit. Используйте:
    • Docker secrets,
    • переменные окружения из защищённого файла (--env-file),
    • внешний секрет-менеджер (Vault, SOPS, Ansible Vault).
  • Заведите отдельного пользователя в ZONT для API-интеграции. Не используйте основную учётную запись владельца.
  • Ротируйте пароль, если он где-то засветился (переписка, скриншоты, git-история).
  • Экспортер не пишет логин/пароль в логи, но может логировать ответ API. Проверьте уровень логирования, если ответы содержат чувствительные данные.
  • Токен ZONT (X-ZONT-Token) хранится только в памяти процесса и перезапрашивается при истечении (unauthorized / token_expired).
  • Эндпоинт /metrics не имеет аутентификации. Не выставляйте его в интернет. Используйте network policy / firewall.

📄 Лицензия

MIT. Используйте на свой риск. Проект не связан с ООО «Микро Лайн» / ZONT — это независимая интеграция с публичным API.


🙏 Благодарности

  • Команде ZONT за публичное API и документацию.
  • Сообществу Prometheus за prometheus_client.
S
Description
Собирает текущее состояние устройства через облачное API my.zont.online и отдаёт метрики в формате Prometheus. Работает как отдельный Docker-контейнер. Подходит для мониторинга в Grafana, алертинга в Alertmanager и любого стека, совместимого с Prometheus.
Readme
198 KiB
Languages
HTML 88.6%
Python 11.3%
Dockerfile 0.1%