Add цпш
Build and Push / maintence (push) Successful in 2s
Build and Push / buildApp (push) Successful in 5s
Build and Push / pushApp (push) Successful in 5s

This commit is contained in:
energys
2026-10-03 22:50:47 +09:00
parent 2311bf6495
commit 03b2e6abcb
+97 -40
View File
@@ -108,18 +108,24 @@ HEATING_TARGET_TEMP = Gauge('zont_heating_target_temp_celsius', 'Heating circuit
HEATING_SETPOINT_TEMP = Gauge('zont_heating_setpoint_temp_celsius', 'Heating circuit setpoint temperature', ['device_id', 'circuit_id', 'name'])
HEATING_WORKTIME = Gauge('zont_heating_worktime_seconds', 'Heating circuit work time in last minute', ['device_id', 'circuit_id', 'name'])
HEATING_STATUS = Gauge('zont_heating_status', 'Heating circuit status code', ['device_id', 'circuit_id', 'name'])
# Фактическая температура контура отопления (подача теплоносителя)
HEATING_FLOW_TEMP = Gauge('zont_heating_flow_temp_celsius', 'Heating circuit flow temperature (actual)', ['device_id', 'circuit_id', 'name'])
# Котёл / OpenTherm
BOILER_CS = Gauge('zont_boiler_cs_celsius', 'Boiler calculated CH water temp', ['device_id', 'adapter_id'])
# Котёл / OpenTherm / цифровая шина
BOILER_CS = Gauge('zont_boiler_cs_celsius', 'Boiler calculated CH water temp (setpoint from boiler)', ['device_id', 'adapter_id'])
BOILER_DS = Gauge('zont_boiler_ds_celsius', 'Boiler DHW setpoint', ['device_id', 'adapter_id'])
BOILER_BT = Gauge('zont_boiler_bt_celsius', 'Boiler actual flow water temp (OpenTherm)', ['device_id', 'adapter_id'])
BOILER_DT = Gauge('zont_boiler_dt_celsius', 'Boiler actual DHW temp (OpenTherm)', ['device_id', 'adapter_id'])
BOILER_OT = Gauge('zont_boiler_outdoor_celsius', 'Boiler outdoor temperature (OpenTherm)', ['device_id', 'adapter_id'])
BOILER_BT = Gauge('zont_boiler_water_celsius', 'Boiler actual flow water temp (water)', ['device_id', 'adapter_id'])
BOILER_DT = Gauge('zont_boiler_dhw_celsius', 'Boiler actual DHW temp (dhw)', ['device_id', 'adapter_id'])
BOILER_RWT = Gauge('zont_boiler_return_celsius', 'Boiler return water temp (return)', ['device_id', 'adapter_id'])
BOILER_OT = Gauge('zont_boiler_outdoor_celsius', 'Boiler outdoor temperature', ['device_id', 'adapter_id'])
BOILER_MODULATION = Gauge('zont_boiler_modulation_percent', 'Boiler burner modulation level (modul), %', ['device_id', 'adapter_id'])
BOILER_PRESSURE = Gauge('zont_boiler_pressure_bar', 'Boiler water pressure (press), bar', ['device_id', 'adapter_id'])
BOILER_STATE = Gauge('zont_boiler_state', 'Boiler state (0=off, 1=running, 2=error)', ['device_id', 'adapter_id'])
BOILER_ERROR_CODE = Gauge('zont_boiler_error_code', 'Boiler OEM error code (err)', ['device_id', 'adapter_id'])
BOILER_CONNECTED = Gauge('zont_boiler_connected', 'Boiler connected (1=yes,0=no)', ['device_id', 'adapter_id'])
BOILER_FAIL = Gauge('zont_boiler_fail', 'Boiler failure (1=fail)', ['device_id', 'adapter_id'])
BOILER_FLAME = Gauge('zont_boiler_flame', 'Boiler flame on (1=on,0=off)', ['device_id', 'adapter_id'])
BOILER_CH_ACTIVE = Gauge('zont_boiler_ch_active', 'Boiler CH active (1=on)', ['device_id', 'adapter_id'])
BOILER_DHW_ACTIVE = Gauge('zont_boiler_dhw_active', 'Boiler DHW active (1=on)', ['device_id', 'adapter_id'])
# Дискретные датчики
DOOR_OPEN = Gauge('zont_door_open', 'Door open (1=open, 0=closed)', ['device_id', 'input_id', 'name'])
@@ -390,6 +396,21 @@ def build_analog_input_types(device):
return result
# --- Вычисление состояния котла ---
def compute_boiler_state(flags):
"""Вычисляет состояние котла по массиву флагов REST API.
Возвращает: 2 = авария, 1 = работает (горит пламя), 0 = выключен.
"""
if not flags:
return 0
if 'f' in flags: # авария
return 2
if 'fl' in flags: # горелка работает
return 1
return 0
# --- Описание событий ---
def describe_event(ev_type, data):
@@ -502,7 +523,7 @@ def collect_events(did):
events = events[-EVENT_MAX:]
_last_event_poll_time = now
logging.debug(f"raw_events returned {len(events)} events for window [{mintime}, {now}]")
if not events:
@@ -630,50 +651,59 @@ def collect_metrics():
if 'internet_weather' in device:
INTERNET_WEATHER.labels(device_id=did).set(device['internet_weather'])
# --- last-boiler-state (для ZONT H-1/H-2/H-1V с OpenTherm) ---
# --- last-boiler-state (для ZONT H-1/H-2/H-1V с OpenTherm/цифровой шиной) ---
last_boiler = io.get('last-boiler-state', {})
if last_boiler:
ot = last_boiler.get('ot', {}) or {}
adapter = 'boiler'
# Фактическая температура теплоносителя (подача) — то, что нужно
# Температуры
if ot.get('bt') is not None:
HEATING_FLOW_TEMP.labels(
device_id=did, circuit_id='boiler', name='boiler_flow'
).set(ot['bt'])
BOILER_BT.labels(device_id=did, adapter_id='boiler').set(ot['bt'])
# Расчётная температура теплоносителя
if ot.get('cs') is not None:
BOILER_CS.labels(device_id=did, adapter_id='boiler').set(ot['cs'])
# Фактическая температура ГВС
BOILER_BT.labels(device_id=did, adapter_id=adapter).set(ot['bt'])
HEATING_FLOW_TEMP.labels(device_id=did, circuit_id=adapter, name='boiler_flow').set(ot['bt'])
if ot.get('dt') is not None:
BOILER_DT.labels(device_id=did, adapter_id='boiler').set(ot['dt'])
# Уличная температура по данным котла
BOILER_DT.labels(device_id=did, adapter_id=adapter).set(ot['dt'])
if ot.get('rwt') is not None:
BOILER_RWT.labels(device_id=did, adapter_id=adapter).set(ot['rwt'])
if ot.get('ot') is not None:
BOILER_OT.labels(device_id=did, adapter_id='boiler').set(ot['ot'])
BOILER_OT.labels(device_id=did, adapter_id=adapter).set(ot['ot'])
if ot.get('cs') is not None:
BOILER_CS.labels(device_id=did, adapter_id=adapter).set(ot['cs'])
if ot.get('ds') is not None:
BOILER_DS.labels(device_id=did, adapter_id=adapter).set(ot['ds'])
# Флаг работы горелки
# Модуляция горелки
if ot.get('rml') is not None:
BOILER_MODULATION.labels(device_id=did, adapter_id=adapter).set(ot['rml'])
# Давление теплоносителя
if ot.get('wp') is not None:
BOILER_PRESSURE.labels(device_id=did, adapter_id=adapter).set(ot['wp'])
# Флаги состояния
flags = ot.get('s', []) or []
BOILER_FLAME.labels(device_id=did, adapter_id='boiler').set(
1 if 'fl' in flags else 0
)
BOILER_STATE.labels(device_id=did, adapter_id=adapter).set(compute_boiler_state(flags))
BOILER_FLAME.labels(device_id=did, adapter_id=adapter).set(1 if 'fl' in flags else 0)
BOILER_CH_ACTIVE.labels(device_id=did, adapter_id=adapter).set(1 if 'ch' in flags else 0)
BOILER_DHW_ACTIVE.labels(device_id=did, adapter_id=adapter).set(1 if 'dhw' in flags else 0)
# Авария котла
# Авария (код + признак)
ff = ot.get('ff', {}) or {}
BOILER_FAIL.labels(device_id=did, adapter_id='boiler').set(
1 if (ff.get('c') or ff.get('f')) else 0
err_code = ff.get('c') or 0
err_flags = ff.get('f') or []
BOILER_ERROR_CODE.labels(device_id=did, adapter_id=adapter).set(err_code)
BOILER_FAIL.labels(device_id=did, adapter_id=adapter).set(
1 if (err_code or err_flags) else 0
)
# Целевая температура и время работы
if last_boiler.get('target_temp') is not None:
HEATING_TARGET_TEMP.labels(
device_id=did, circuit_id='boiler', name='boiler_target'
device_id=did, circuit_id=adapter, name='boiler_target'
).set(last_boiler['target_temp'])
if last_boiler.get('boiler_work_time') is not None:
HEATING_WORKTIME.labels(
device_id=did, circuit_id='boiler', name='boiler_worktime'
device_id=did, circuit_id=adapter, name='boiler_worktime'
).set(last_boiler['boiler_work_time'])
# --- z3k-state ---
@@ -726,31 +756,58 @@ def collect_metrics():
if flow_temp is not None:
HEATING_FLOW_TEMP.labels(device_id=did, circuit_id=obj_id, name=name).set(flow_temp)
# Адаптер котла / OpenTherm
# Адаптер котла / OpenTherm / цифровая шина (z3k)
if isinstance(obj, dict) and 'ot' in obj and 'status' in obj:
ot = obj.get('ot', {}) or {}
if ot.get('cs') is not None:
BOILER_CS.labels(device_id=did, adapter_id=obj_id).set(ot['cs'])
if ot.get('ds') is not None:
BOILER_DS.labels(device_id=did, adapter_id=obj_id).set(ot['ds'])
# Температуры
if ot.get('bt') is not None:
BOILER_BT.labels(device_id=did, adapter_id=obj_id).set(ot['bt'])
HEATING_FLOW_TEMP.labels(device_id=did, circuit_id=obj_id, name=name).set(ot['bt'])
if ot.get('dt') is not None:
BOILER_DT.labels(device_id=did, adapter_id=obj_id).set(ot['dt'])
if ot.get('rwt') is not None:
BOILER_RWT.labels(device_id=did, adapter_id=obj_id).set(ot['rwt'])
if ot.get('ot') is not None:
BOILER_OT.labels(device_id=did, adapter_id=obj_id).set(ot['ot'])
if ot.get('cs') is not None:
BOILER_CS.labels(device_id=did, adapter_id=obj_id).set(ot['cs'])
if ot.get('cs2') is not None:
BOILER_CS.labels(device_id=did, adapter_id=f"{obj_id}_ch2").set(ot['cs2'])
if ot.get('ds') is not None:
BOILER_DS.labels(device_id=did, adapter_id=obj_id).set(ot['ds'])
# Модуляция горелки
if ot.get('rml') is not None:
BOILER_MODULATION.labels(device_id=did, adapter_id=obj_id).set(ot['rml'])
if ot.get('mrml') is not None:
BOILER_MODULATION.labels(device_id=did, adapter_id=f"{obj_id}_max").set(ot['mrml'])
# Давление теплоносителя
if ot.get('wp') is not None:
BOILER_PRESSURE.labels(device_id=did, adapter_id=obj_id).set(ot['wp'])
# Флаги состояния
flags = ot.get('s', []) or []
BOILER_STATE.labels(device_id=did, adapter_id=obj_id).set(compute_boiler_state(flags))
BOILER_FLAME.labels(device_id=did, adapter_id=obj_id).set(1 if 'fl' in flags else 0)
BOILER_CH_ACTIVE.labels(device_id=did, adapter_id=obj_id).set(1 if 'ch' in flags else 0)
BOILER_DHW_ACTIVE.labels(device_id=did, adapter_id=obj_id).set(1 if 'dhw' in flags else 0)
# Авария
ff = ot.get('ff', {}) or {}
err_code = ff.get('c') or 0
err_flags = ff.get('f') or []
BOILER_ERROR_CODE.labels(device_id=did, adapter_id=obj_id).set(err_code)
BOILER_FAIL.labels(device_id=did, adapter_id=obj_id).set(
1 if (err_code or err_flags) else 0
)
# Статус адаптера
status = obj.get('status', {})
BOILER_CONNECTED.labels(device_id=did, adapter_id=obj_id).set(
0 if status.get('no_boiler_connection') else 1
)
BOILER_FAIL.labels(device_id=did, adapter_id=obj_id).set(
1 if status.get('boiler_fail') else 0
)
logging.info(f"Metrics collected successfully for device {DEVICE_ID}")