[2026-09-15] eagle: Modbus/RTU_Framing_Source_Analysis.md family/archive/t610-migration-log-2026-09.md family/documents/home-automation-wishlist.md family/how-to/gitea-config.md family/how-to/ha-automations.md family/how-to/home-automation.md family/how-to/nodered-ventilation.md family/how-to/truenas-access.md family/how-to/truenas-infrastructure.md family/how-to/zigbee2mqtt-t610.md

This commit is contained in:
Alexey Martemyanov
2026-09-15 11:32:28 +06:00
parent 851ba3539b
commit 4f156ee950
14 changed files with 433 additions and 8340 deletions
-170
View File
@@ -1,170 +0,0 @@
---
title: 'Node-RED: вентиляция по CO₂'
tags:
- family
- home
- automation
- nodered
- ventilation
updated: '2026-09-14'
related:
- '[[family/plans/t610-home-automation]]'
- '[[family/how-to/home-automation]]'
---
> ## 🔄 ГДЕ ЖИВЁТ (обновлено 2026-09-14)
> **Flows перенесены на HP t610** (HA OS) — **перенос выполнен 2026-09-14**, см. [[family/plans/t610-home-automation]] §5-кватер-Г.
> - **Файл:** `/addon_configs/a0d7b954_nodered/flows.json` в аддоне `a0d7b954_nodered` (**68 узлов**, было 124 б пустых).
> - **🔴 Ключевая правка при переезде:** узел `server` — `"addon": false` → **`"addon": true`**. На TrueNAS Node-RED был отдельным docker-контейнером и ходил в HA по адресу + long-lived token (**токена в переносимых файлах нет вообще** — не искать). На t610 он HA-аддон → в аддон-режиме Supervisor даёт доступ к HA без токена. Лог после правки: `[server:Home Assistant] Connected to http://supervisor/core`, ошибок 0.
> - **Модуль:** опция аддона `npm_packages: ["node-red-contrib-home-assistant-websocket@0.80.3"]`.
> - **Доступ:** наружу НЕ выпущен (`host_network: true` глушит порт-маппинг; снимается только галочкой в UI) → **через ingress HA**: `http://192.168.2.176/api/hassio_ingress/4vUcCxEpYJMbQ64z-kWPCvFadq8ayl4lzvzJPDUaZzE/`. Домен `nodered.mallexxx.duckdns.org` **не используется** (отдаёт 401 от nginx HA).
> - **Старый Node-RED на TrueNAS** (`/mnt/RED_2TB/docker/nodered/`, порт 1880) пока жив как источник/откат.
> - **⚠️ Известное следствие:** узел `fan.fan_at2_1/2` (slave 10) в HA на t610 — `unavailable` (блок закомментирован в `configuration.yaml`), поэтому управление вентиляторами AT2 не работает. Также проверить наличие `cover.intake_damper_*` (в конфиге HA заслонки описаны как `switch.*`). Alex: задача по slave 10 **не ставилась**.
Node-RED flow для управления вентиляцией по данным CO₂ датчиков.
## Структура
```
[room demand msgs]
(1) Demand Aggregator
(2) Intake Allocation
(3) Discretization per damper
(4) Intake Damper Outputs
(5) Exhaust Arbitration
(6) Exhaust Dampers
(7) Exhaust Fans
(8) Kitchen Hood
```
## 1. Demand Aggregator (stateful)
```js
let demands = flow.get("room_demands") || {};
demands[msg.room] = msg.raw_demand;
flow.set("room_demands", demands);
msg.demands = demands;
return msg;
```
## 2. Intake Allocation
Комнаты с intake дамперами: bedroom, kids, living. Приоритеты: living = 1.2, остальные = 1.0.
```js
const ROOMS = ["bedroom", "kids", "living"];
const PRIORITY = { bedroom: 1.0, kids: 1.0, living: 1.2 };
let weighted = {}, sum = 0;
for (let r of ROOMS) {
let d = msg.demands[r] || 0;
weighted[r] = d * (PRIORITY[r] || 1);
sum += weighted[r];
}
if (sum === 0) return null;
let allocation = {};
for (let r of ROOMS) { allocation[r] = 100 * weighted[r] / sum; }
msg.intake_pct = allocation;
return msg;
```
## 3. Discretization
**Bedroom/Kids** (0 / 33 / 66 / 100):
```js
function snap(x) {
if (x < 10) return 0;
if (x < 33) return 33;
if (x < 66) return 66;
return 100;
}
msg.payload = snap(msg.payload);
return msg;
```
**Living (dual-damper)**:
```js
let p = msg.payload;
let A = 0, B = 0;
if (p < 10) { A=0; B=0; }
else if (p < 30) { A=66; B=0; }
else if (p < 55) { A=66; B=66; }
else if (p < 80) { A=100; B=66; }
else { A=100; B=100; }
msg.damperA = A; msg.damperB = B;
return msg;
```
## 5. Exhaust Arbitration
```js
let d = msg.demands;
msg.exhaust = {
at2_1: Math.max(d.toilet || 0, d.shower || 0, d.kitchen || 0),
at2_2: Math.max(d.bathroom || 0, d.office || 0)
};
return msg;
```
## 7. Fan Speed
```js
function speed(d) {
if (d < 5) return 30;
if (d < 20) return 50;
if (d < 40) return 70;
return 100;
}
msg.payload = speed(msg.payload);
return msg;
```
## 8. Kitchen Hood (3-speed)
```js
let d = msg.demands.kitchen || 0;
if (d < 10) msg.payload = 0;
else if (d < 30) msg.payload = 1;
else if (d < 60) msg.payload = 2;
else msg.payload = 3;
return msg;
```
Gate: current_state (manual override → block automation).
Все дамперы: rate-limit 1 msg / 3060 s.
## Связанные заметки
- [[family/how-to/home-automation]] — общая автоматизация дома
- [[family/plans/t610-home-automation]] — миграция на t610, §5-кватер-Г (перенос flows) и §5-кватер-З (фикс датчика столовой)
- [[Modbus/RTU_Framing_Source_Analysis]] — канон сборки RTU-кадров (почему `dining` молчал и как починили)
## Статус данных для автоматики (2026-09-14)
**Все три комнаты (`bedroom`, `kids`, `dining`) публикуют данные в MQTT.** Датчик столовой (`slave 1`) был сломан багом сборки кадров в `modbus-bridge` — починен 2026-09-14 (см. [[family/plans/t610-home-automation]] §5-кватер-З). До фикса автоматика вентиляции по CO₂ работала без данных столовой.
⚠️ **`fan.fan_at2_1/2` (slave 10) — `unavailable`** (блок закомментирован в `configuration.yaml`) → исполнительный контур вентиляторов AT2 не работает. Задача по slave 10 Alex'ом не ставилась.
## 🔦 Ночной свет душевой 2 — ПЕРЕНЕСЕНО
> **Этот раздел переехал в [[family/how-to/ha-automations]] §3.** Документ `nodered-ventilation` — только про вентиляцию по CO₂.
> Кратко: порог освещённости ночного света душевой был **8 lx** и лежал ровно в центре дребезга датчика (**7 ↔ 12**, рабочий диапазон 0…15 lx) → свет мигал. **Правка 2026-09-15 по решению Alex: `below: 6` / `above: 6`**, применена через REST API, подтверждена чтением обратно. Полный разбор, замеры, питфоллы API и остаточный риск — в [[family/how-to/ha-automations]].
**Сущности:** дублируются в [[family/how-to/ha-automations]] §2. Здесь не повторяем.
**Автоматизации:** `1771997851260` (вкл) / `1771997918348` (выкл) — разбор в [[family/how-to/ha-automations]] §3.
**❌ Причина мигания и ✅ правка:** см. блок выше. Замеры и обоснование — в [[family/how-to/ha-automations]] §3.
**🔴 ПИТФОЛЛ (нужен для любой правки автоматизаций):** REST `GET/POST /api/config/automation/config/<id>` использует **`triggers`/`conditions`** (мн. ч.; в файле — `trigger`/`condition`). Правка по единственному числу **молча уходит в пустые пути**: POST → `200 {"result":"ok"}`, значения НЕ меняются. **Всегда читать обратно.** Подробнее — [[family/how-to/ha-automations]] §5.
**Артефакты:** скрипт `~/tmp-t610/fix_shower_light_threshold.sh`; бэкап `~/tmp-t610/automations/automations.yaml.bak-20260915-105455`.
---