Files
obsidian-vault/family/tech/heating-cable-water-inlet.md
T

147 lines
7.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Греющий кабель ввода воды (t610)
> Справочник: расчёт порогов и автоматизация обогрева ввода воды.
## 1. Исходные данные
| Факт | Значение |
|---|---|
| Регион | Новосибирск, Лаки Парк (55.257328, 83.048234) |
| Грунт | суглинок |
| Глубина трубы в грунте | ~4 м |
| Бетонная подушка фундамента | 30 см |
| Тип кабеля | саморегулирующийся |
| Управление | `switch.heating_cable_plug` (NEO NAS-WR01B, `a4c138eb6fbe9d19`, котельная) |
| Уличный датчик | `sensor.h2000_pro_temperatura_ulitsa` (ZONT H2000_PRO) |
| Внешний прогноз | `weather.forecast_laki_dom` (met.no, координаты посёлка) |
| Автоматизация | `automation.greiushchii_kabel_upravlenie` |
## 2. Расчёт промерзания (СП 131.13330.2020)
Отрицательные среднемесячные Новосибирска: `янв −17,6 · фев −15,4 · мар −7,7 · ноя −7,9 · дек −15,3`**Mt = 63,9**
```
d_fn = d0 · √Mt = 0,23 · √63,9 = 1,84 м (суглинок, открытая поверхность)
```
Под снегом 30–40 см реально **1,31,6 м**.
Затухание годовой волны (`a = λ/C = 1,4 / 2,5·10⁶ = 5,6·10⁻⁷ м²/с`):
```
z_damp = √(a·T/π) = 2,37 м
A(4 м) = 19 · e^(4/2,37) = ±3,5 °C
```
**Труба на 4 м не замерзает физически** — грунт там +2,5…+3,5 °C круглый год.
## 3. Критичная точка — бетонная подушка 30 см
Бетон промерзает быстрее грунта: `λ = 1,7` против `1,4`, снеговой шубы нет.
```
R_возд = 1/15 = 0,067 (м²·К)/Вт
R_бетон = 0,30/1,7 = 0,176 (м²·К)/Вт
→ 72 % перепада падает на бетон
```
| Улица | Труба в бетоне |
|---|---|
| 6 °C | +0,5 °C |
| **8 °C** | **−0,1 °C** ← порог включения |
| 10 °C | 0,6 °C |
| 15 °C | 1,9 °C |
| 20 °C | 3,1 °C |
| 25 °C | 4,4 °C |
## 4. Пороги
| Событие | Условие | Выдержка |
|---|---|---|
| ВКЛ | `eff ≤ 8 °C` | 12 ч |
| ВЫКЛ | `eff ≥ 3 °C` | 12 ч |
| Аварийный ВКЛ | `eff ≤ 20 °C` | без выдержки |
| Fail-safe | ZONT `unknown`/`unavailable` | ВКЛ |
| Обрыв | розетка `on`, `power < 5 W` | push |
`eff` = ZONT, если датчик жив; иначе прогноз-мин на 24 ч.
**Почему 12 ч:** тепловая инерция бетонной подушки ~сутки. 12 ч отсекает одиночные ночные заморозки, но ловит затяжное похолодание в тот же день.
**Почему саморег:** кабель сбрасывает мощность при нагреве сам, перегрев невозможен. Задержка нужна не «чтобы не спалить», а чтобы не дёргать реле на каждую холодную ночь.
**Почему прогноз:** ZONT — одна точка, может врать или отвалиться. Прогноз — независимый канал; при отвале датчика переключаемся на него, а не остаёмся без защиты.
## 5. Автоматизация
**Триггеры:** `time_pattern /15` + `numeric_state ZONT below 8` + `state ZONT → unknown/unavailable 30 мин`
**Файл:** `/config/automations.yaml` · `mode: single`
```yaml
actions:
- action: weather.get_forecasts # ПЕРВЫМ действием
target: {entity_id: weather.forecast_laki_dom}
data: {type: hourly}
response_variable: wx
- variables: # ПОСЛЕ вызова — wx уже определён
zont_ok: "{{ states('sensor.h2000_pro_temperatura_ulitsa') not in ['unknown','unavailable','none',''] }}"
zont: "{{ states('sensor.h2000_pro_temperatura_ulitsa') | float(-100) }}"
fc_min: "{{ wx['weather.forecast_laki_dom']['forecast'][:24] | map(attribute='temperature') | min | float(-100) }}"
eff: "{{ zont if zont_ok else fc_min }}"
- choose: [...] # 5 веток: авария / fail-safe / ВКЛ / ВЫКЛ / обрыв
```
Выдержка 12 ч — через `for: '12:00:00'` на `switch.heating_cable_plug` в условии включения (на вычисляемый `eff` вешать нельзя).
## 6. Проверка
```bash
cd ~/tmp-t610
python3 ha_ws.py forecast weather.forecast_laki_dom hourly # прогноз
python3 verify_cable.py # расчёт eff + пороги
```
В Logbook видны строки `zont=… fc24=… eff=… on=… P=…W`.
## 7. Питфоллы
### 7.1 Прогноз в HA: как НЕ работает и как работает
| Способ | Результат |
|---|---|
| Атрибут `state_attr('weather.x','forecast')` | `None` — прогноза в атрибутах нет |
| `weather.get_forecasts(...)` в Jinja | `'weather' is undefined` |
| REST `POST /api/services/weather/get_forecast` | `400` |
| WS `{"type":"weather/forecast"}` | `unknown_command` |
| WS `{"type":"weather/subscribe_forecast", forecast_type: …}` | ✅ работает |
| **`action: weather.get_forecasts` в автоматизации** | ✅ работает |
Сервис — **`weather.get_forecasts`** (множественное число). В автоматизации вызывается как `action:` с `response_variable`; данные — `wx['weather.forecast_laki_dom']['forecast']`.
### 7.2 `variables:` вычисляются ДО действий
Объявлять `variables:` с данными от `response_variable` только **внутри `actions:`, после вызова сервиса**. На верхнем уровне автоматизации `wx` ещё не существует.
### 7.3 `min([99, fc_min])` ломает fail-safe
Наивная проверка отвала датчика через `float(99)` + `min` не работает: `min([99, 11.1])` = 11.1, условие `eff == 99` не сработает никогда.
Правильно — отдельный флаг по строковому состоянию:
```jinja
zont_ok: "{{ states('sensor.h2000_pro_temperatura_ulitsa') not in ['unknown','unavailable','none',''] }}"
eff: "{{ zont if zont_ok else fc_min }}"
```
### 7.4 WS-подписки на прогноз приходят двумя сообщениями
Сначала `result`, затем `event` с прогнозом. Клиент, ждущий только `result`, получит **0 точек** — нужен `collect_events=True`.
### 7.5 `switch.heating_cable_plug` = `0 W` при `off` — это норма
`voltage 223 V`, `state off`, `power 0.0 W`. Нагрузка не потребляет, пока выключено. Не поломка.
### 7.6 Доступ к API
- С Mac: только `https://mallexxx.duckdns.org`. Raw-IP + plain HTTP → апрув на каждую команду.
- `http://192.168.2.176:8123` с Mac → `000`, соединения нет.
- `http://172.30.32.1/api/` — только изнутри t610, порт **80**.
- WS `render_template` возвращает `null` даже для `2+2` — шаблоны рендерить только через REST `POST /api/template`.