# Dev-teenused (dev) – Docker kasutusjuhend Kataloog: `/opt/docker-compose/dev/` Arendus-/tutvumisteenused. Esimene teenus on **ClickHouse** (OLAP-andmebaas, mille eesmärk on Oracle-baaside ülemineku ettevalmistamine). ## ClickHouse | Omadus | Väärtus | |--------|---------| | Pilt | `clickhouse/clickhouse-server:26.8.1.2041` | | Konteiner | `clickhouse` | | Püsivus | **alati aktiivne** (ei ole enam `experimental` profiilis), `restart: unless-stopped`, `mem_limit: 2g` | | HTTP API | **8125**, seotud **ainult Tailscale'ile** (`100.87.1.24:8125`) — **8124** läbi `clickstack-proxy` | | Native TCP | **9004**, seotud ainult Tailscale'ile (`100.87.1.24:9004`) | | Kasutaja | `default` (ja `dev`, `zigbee`) | | Parool | `dev_clickhouse_2026` (default/dev); `zigbee` kasutaja parool on `dev/.env` failis | | Andmed | `./data/clickhouse` (gitignore'd) | | Config | `./config/` (merge'd `/etc/clickhouse-server/config.d`) | | Võrk | `main_ai_network` | > **Turvamärkus (2026-09-17):** pordid 8125/9004 ei ole enam `0.0.0.0` peal, vaid > ainult Tailscale'i aadressil `100.87.1.24`. LAN-ist ligi ei pääse. ## Web UI ClickHouse'il on **sisseehitatud veebiliides** (`/play` — SQL playground): ``` http://100.87.1.24:8124/play ``` Kasutajanimi `default`, parool `dev_clickhouse_2026`. ## Käsud ```bash # Käivita / peata / taaskäivita docker-compose -f /opt/docker-compose/dev/docker-compose.yml up -d docker-compose -f /opt/docker-compose/dev/docker-compose.yml down docker-compose -f /opt/docker-compose/dev/docker-compose.yml restart clickhouse # Logid docker-compose -f /opt/docker-compose/dev/docker-compose.yml logs -f clickhouse # Kliendiga (konteineri sees) docker exec -it clickhouse clickhouse-client --user default --password dev_clickhouse_2026 ``` ## Zigbee andurite koguja (`zigbee-collector`) Valvuri (`valvur`, Orange Pi Zero 3, `100.80.254.54`) Zigbee2MQTT andurite andmed kogutakse ClickHouse'i. **Arhitektuur: ohmu loeb (pull)** — koguja jookseb ohmu peal, tellib valvuri MQTT-d ja kirjutab kohalikku ClickHouse'i. Valvurile ei lähe andmebaasi kredentiaale. | Omadus | Väärtus | |--------|---------| | Kood | `./zigbee-collector/` (`collector.py`, `Dockerfile`, `requirements.txt`) | | Konteiner | `zigbee-collector` (püsiv, `restart: unless-stopped`, `mem_limit: 128m`) | | Konf/paroolid | `dev/.env` (gitignore'itud, chmod 600) | | MQTT allikas | `mqtt://100.80.254.54:1883` | | Temperatuuriandur | SONOFF SNZB-02P (`0x70d07efffea3e4f6`, `Temperatuur`) → `uus67.temperatuur` | | Kontaktandurid | SONOFF SNZB-04PR2 ×4 (Välisuks, Rõdu, Kontori uks, Kontori aken) → `uus67.ukseandur` | | Häired | kõik andurid + süsteem → `uus67.vead` | **Loogika:** - **Temperatuur** (`MQTT_TOPIC`): mõõtmised kogutakse mälus täistunni kaupa ja kirjutatakse iga täistunni järel üks rida (`temperature`/`humidity` = tunni keskmine). Andur raporteerib u. iga 10 min → tunnis mitu mõõtmist. **Kui tunnis mõõtmisi ei ole** (andur kättesaamatu), kirjutatakse ikkagi rida eelmise teadaoleva väärtusega ja `taidetud = true` — nii ei teki aegreas auke. Viimane väärtus seemendatakse käivitusel andmebaasist. - **Uksed** (`DOOR_TOPICS`): salvestatakse **ainult olekumuutused**. Perioodilised ~2 h südamelöögid (sama `contact`) jäetakse vahele. Käivitusel seemendatakse viimane teadaolev olek andmebaasist; esimene nähtud olek salvestatakse baasreana. - **Häired** (`CH_FAULT_TABLE`): salvestatakse **ainult muutused** — iga häire kohta kaks sündmust (`aktiveeritud` / `taastatud`). Aktiivsed häired seemendatakse käivitusel andmebaasist, et restart ei dubleeriks. ### Skeem ```sql CREATE DATABASE IF NOT EXISTS uus67; CREATE TABLE uus67.temperatuur ( hour DateTime('Europe/Tallinn'), device LowCardinality(String), temperature Nullable(Float32), -- tunni keskmine humidity Nullable(Float32), -- tunni keskmine taidetud Bool DEFAULT false -- true = eelmise väärtusega täidetud tund ) ENGINE = MergeTree PARTITION BY toYYYYMM(hour) ORDER BY (device, hour); ``` Kontaktandurite tabel (ainult olekumuutused): ```sql CREATE TABLE uus67.ukseandur ( ts DateTime('Europe/Tallinn'), device LowCardinality(String), contact Bool, -- toorväärtus Z2M-st olek LowCardinality(String) -- 'avatud' / 'suletud' ) ENGINE = MergeTree PARTITION BY toYYYYMM(ts) ORDER BY (device, ts); ``` > Diagnostilised veerud (aku, pinge, signaal) on nendest tabelitest teadlikult > eemaldatud — nende **muutused** on `uus67.vead` tabelis. > **`contact` semantika (SNZB-04PR2):** `contact: true` = **suletud**, > `contact: false` = **avatud**. Kinnitatud Zigbee2MQTT HA-discovery'st > (`device_class: door`, `payload_on: false`, `payload_off: true`). Häirete tabel (ainult muutused): ```sql CREATE TABLE uus67.vead ( ts DateTime('Europe/Tallinn'), device LowCardinality(String), tyyp LowCardinality(String), -- low_battery | weak_signal | low_voltage | offline | mqtt_disconnected | bridge_offline olek LowCardinality(String), -- 'aktiveeritud' / 'taastatud' detail String, -- nt "battery 15%", "linkquality 12" vaartus Nullable(Float64) ) ENGINE = MergeTree PARTITION BY toYYYYMM(ts) ORDER BY (device, ts); ``` | Häire (`tyyp`) | Tingimus | Lävend (aktiveerub / taastub) | |----------------|----------|-------------------------------| | `low_battery` | `battery_low == true` või `battery` madal | ≤ 20% / ≥ 25% | | `weak_signal` | `linkquality` madal | ≤ 20 / ≥ 30 | | `low_voltage` | `voltage` madal (kontaktandurid) | ≤ 2600 mV / ≥ 2700 mV | | `offline` | andurilt pole teadet | temp 120 min / kontakt 240 min | | `mqtt_disconnected` | koguja MQTT-ühendus katkes (`device=koguja`) | – | | `bridge_offline` | `zigbee2mqtt/bridge/state = offline` (`device=zigbee2mqtt`) | – | > Lävendid on üle kirjutatavad `.env`-is / keskkonnamuutujatega > (`BATTERY_LOW_THRESHOLD`, `LINKQUALITY_LOW_THRESHOLD`, `VOLTAGE_LOW_THRESHOLD`, > `OFFLINE_TIMEOUT_TEMP_MIN`, `OFFLINE_TIMEOUT_CONTACT_MIN`). > **`tamper`** on teadlikult välja jäetud — SNZB-04PR2 raporteerib selle > pidevalt `true` (tõenäoliselt pööratud), mis annaks valehäireid. ### Käsud ```bash # Koguja logid docker logs -f zigbee-collector # Viimased tunniread docker exec clickhouse clickhouse-client --user default --password dev_clickhouse_2026 \ --query "SELECT * FROM uus67.temperatuur ORDER BY hour DESC LIMIT 24" # Viimased ukseoleku muutused docker exec clickhouse clickhouse-client --user default --password dev_clickhouse_2026 \ --query "SELECT * FROM uus67.ukseandur ORDER BY ts DESC LIMIT 24" # Viimased häired (ainult muutused) docker exec clickhouse clickhouse-client --user default --password dev_clickhouse_2026 \ --query "SELECT * FROM uus67.vead ORDER BY ts DESC LIMIT 50" # Koguja taaskäivitamine (nt .env muudatuse järel) docker compose -f /opt/docker-compose/dev/docker-compose.yml up -d --build zigbee-collector ``` ### Valvuri MQTT turvakõvadus (2026-09-17) - `mosquitto.conf`: kaks listener'it — `127.0.0.1:1883` (kohalik Z2M) ja `100.80.254.54:1883` (Tailscale). LAN-ist MQTT-le ligi ei pääse. - Zigbee2MQTT seadmetel (`Temperatuur` + 4 kontaktandurit) on `retain: true` → koguja taaskäivitumisel saab kohe viimased väärtused (varem teated ei olnud retained). - Valvuri konfiguratsioonid on root-omanduses; muutmiseks on vaja `sudo`-t (varukoopiad: `*.bak-20260917`). ## ClickStack (HyperDX) — observability UI ClickStack = HyperDX UI + ClickHouse + OTel-kollektor (logid/traces/meetrikud). | Omadus | Väärtus | |--------|---------| | Konteiner | `clickstack` (`hyperdx-all-in-one`) | | **UI (otsing/dashboardid)** | **`http://100.87.1.24:8124/clickstack/search`** (läbi `clickstack-proxy`) | | UI otse (varuvariant) | `http://100.87.1.24:18080/search` | | **Kasutaja** | `admin@odamus.com` | | **Parool** | `Dev_clickhouse_2026!` | | OTLP gRPC sisend | 4317 | | OTLP HTTP sisend | 4318 | | Andmed (incl. MongoDB) | `./data/clickstack` (gitignore'd) | **Hooldus:** all-in-one ei käivita MongoDB-d ise — seetõttu on `command` üle võetud `clickstack-entry.sh`-ga (käivitab `mongod` pordil 127.0.0.1, siis rakenduse). `db` laheneb konteineris 127.0.0.1-le (sisemine MongoDB). **Port 8124 = `clickstack-proxy` (nginx):** - `/clickstack/*` → ClickStack UI (ClickHouse staatiline kest) - `/__ENV.js`, `/api/*`, `/graphql` → HyperDX backend - `/`, `/play`, `/?query=...` → ClickHouse (ehk DBeaver 8124-ga töötab edasi) - ClickHouse'i HTTP otse on nüüd pordil **8125** (8124 läbi proxy sama API-ga) ## Migratsiooninäide: postgres → ClickHouse (paberkrohv) 2026-08-31 viidi `paberkrohv` andmebaas postgresist (100.87.1.24:5432) ClickHouse'isse — näide, kuidas hiljem Oracle-baase üle viia. **Tulemus (read ühtivad):** sorptsioon 48193, sample_weight 2529, sample 1749, mixture 386, lot 10, res_users 6, test 7. ### Tüübimapping | Postgres | ClickHouse | |----------|------------| | integer | Int32 | | numeric | Float64 (testiks OK; täpsuse vajadusel Decimal) | | timestamp (ilma tz) | DateTime64(3) | | character varying / text | String | | boolean | Bool | ### Tabeli loomine (MergeTree — analüütiline mootor) ```sql CREATE TABLE paberkrohv.sorptsioon ( id Int32, weight Float64, lot Int32, sample Int32, rh_1 Int32, test_id Int32, datetime DateTime64(3), created_at DateTime64(3), created_by Int32 ) ENGINE = MergeTree ORDER BY (sample, lot, datetime); ``` ### Andmete ülekanne (ClickHouse'i `postgresql()` tabelifunktsioon) ```sql -- ClickHouse loeb otse postgresist, ilma vahefailita: INSERT INTO paberkrohv.sorptsioon SELECT * FROM postgresql('postgres_postgis:5432', 'paberkrohv', 'sorptsioon', 'ai_user', 'ai_secure_pass_2026'); ``` Päring peab jooksma ClickHouse'i konteineri seest (võrk `main_ai_network` võimaldab `postgres_postgis:5432`). Postgres jääb puutumatuks — ClickHouse on koopia. ### Käsud ```bash docker exec -it clickhouse clickhouse-client --user default --password dev_clickhouse_2026 \ --query "SELECT count() FROM paberkrohv.sorptsioon" ``` ## Märkused - Pordid valitud konfliktivabaks: 8125 (HTTP, Tailscale-only), 9004 (native, Tailscale-only), 8124 (proxy, clickstack). 8123 = Home Assistant, 9000 = portainer. - Oracle → ClickHouse: ClickHouse on veerupõhine OLAP; sobib analüüsi/aruandluse koormuste jaoks. Postgres-migratsioon on eeskujuks: `postgresql()` tabelifunktsioon lihtsustab oluliselt (Oracle'i jaoks tuleb vastav funktsioon/ODBC-vood eraldi uurida). ## Nutikodu veebiliides (`nutikodu-web`) Interaktiivne ajatelg `uus67` skeemi zigbee andurite andmetele. FastAPI backend + üks staatiline leht (ECharts), eestikeelne, mobiilisõbralik, tume/hele teema. | Omadus | Väärtus | |--------|---------| | Kood | `./nutikodu-web/` (`app.py`, `Dockerfile`, `static/`, `README.md`) | | Konteiner | `nutikodu-web` (püsiv, `restart: unless-stopped`, `mem_limit: 192m`) | | Võrgud | `main_ai_network` (ClickHouse) + `prod_net` (prod_caddy) | | Tailscale | `http://100.87.1.24:8095` · `http://ohmu.tail20e23.ts.net:8095` | | Avalik | **https://nutikodu.odamus.com** | | ClickHouse | `http://clickhouse:8123`, kasutaja `zigbee` (SELECT `uus67.*`) | **Avaliku ligipääsu ahel (2026-09-17):** 1. **DNS:** DigitalOcean A-kirje `nutikodu.odamus.com` → `188.166.84.16`. 2. **Edge Caddy** (`kanad`/edge, `/opt/edge/Caddyfile`): `nutikodu.odamus.com { reverse_proxy http://100.91.118.16:80 }`. TLS automaatne (Let's Encrypt). 3. **Sisemine Caddy** (ohmu `prod_caddy`, `/opt/prod/Caddyfile`): `nutikodu.odamus.com:80 { reverse_proxy nutikodu-web:8095 }`. (`100.91.118.16` = `ts-prod` tailnet IP; `prod_caddy` töötab `network_mode: container:ts-prod`.) **NB! DNS-vahemälu:** uue domeeni lisamisel tekib kohati negatiivne NXDOMAIN-vahemälu. Kui `nutikodu.odamus.com` ei lahendu, tühjenda: ```bash # ohmu sudo resolvectl flush-caches # pihole (valvur, 192.168.2.50) docker restart pihole ``` **API:** `/api/meta`, `/api/temperatuur` (hour/day), `/api/ukseandur`, `/api/vead`, `/api/latest`, `/health`. Vaata täpsemalt `nutikodu-web/README.md`. **Käsud:** ```bash docker logs -f nutikodu-web curl -s https://nutikodu.odamus.com/health docker compose -f /opt/docker-compose/dev/docker-compose.yml up -d --build nutikodu-web ``` **Edasi:** ukseanduri olekuribad ja häirete markerid ajateljel (`/api/ukseandur`, `/api/vead` on valmis); võimalik `WEB_ACCESS_TOKEN` avaliku lehe kaitseks.