Kataloog: /opt/docker-compose/dev/
Arendus-/tutvumisteenused. Esimene teenus on ClickHouse (OLAP-andmebaas, mille eesmärk on Oracle-baaside ülemineku ettevalmistamine).
| 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.0peal, vaid ainult Tailscale'i aadressil100.87.1.24. LAN-ist ligi ei pääse.
ClickHouse'il on sisseehitatud veebiliides (/play — SQL playground):
http://100.87.1.24:8124/play
Kasutajanimi default, parool dev_clickhouse_2026.
# 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-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:
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.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.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.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):
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.veadtabelis.
contactsemantika (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):
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).tamperon teadlikult välja jäetud — SNZB-04PR2 raporteerib selle pidevalttrue(tõenäoliselt pööratud), mis annaks valehäireid.
# 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
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.Temperatuur + 4 kontaktandurit) on retain: true →
koguja taaskäivitumisel saab kohe viimased väärtused (varem teated ei olnud retained).sudo-t
(varukoopiad: *.bak-20260917).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)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.
| Postgres | ClickHouse |
|---|---|
| integer | Int32 |
| numeric | Float64 (testiks OK; täpsuse vajadusel Decimal) |
| timestamp (ilma tz) | DateTime64(3) |
| character varying / text | String |
| boolean | Bool |
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);
postgresql() tabelifunktsioon)-- 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.
docker exec -it clickhouse clickhouse-client --user default --password dev_clickhouse_2026 \
--query "SELECT count() FROM paberkrohv.sorptsioon"
postgresql() tabelifunktsioon lihtsustab oluliselt (Oracle'i jaoks
tuleb vastav funktsioon/ODBC-vood eraldi uurida).weather-collector)Open-Meteo API-st tunniandmed (temperatuur, niiskus, tuul, sademed) → ClickHouse
uus67.valisilm. Eraldi konteiner weather-collector.
| Omadus | Väärtus |
|---|---|
| Kood | ./weather-collector/ (collector.py, Dockerfile, requirements.txt) |
| Konteiner | weather-collector (püsiv, restart: unless-stopped, mem_limit: 128m) |
| Allikas | Open-Meteo (api.open-meteo.com, archive-api.open-meteo.com) |
| Asukoht | LATITUDE / LONGITUDE (vaikimisi 58.87009, 22.9479) |
| Backfill | BACKFILL_FROM (vaikimisi 2026-09-17); archive + forecast API |
| Intervall | POLL_INTERVAL (vaikimisi 1800 s; jookseb iga tunni +5 min) |
| Tabel | uus67.valisilm |
Loogika: käivitusel backfill; edasi tunnipoll, mis uuendab hiljutisi tunde.
Puuduvad tunnid täidetakse eelmise väärtusega (taidetud = true) — auke ei jää.
Tabel on ReplacingMergeTree (ORDER BY hour), päringud kasutavad FINAL.
CREATE TABLE uus67.valisilm (
hour DateTime('Europe/Tallinn'),
temperature Nullable(Float32),
humidity Nullable(Float32),
wind Nullable(Float32),
rain Nullable(Float32),
taidetud Bool DEFAULT false
) ENGINE = ReplacingMergeTree
PARTITION BY toYYYYMM(hour)
ORDER BY hour;
NB!
.env-is onCH_TABLE=temperatuur(zigbee koguja jaoks). Välikoguja kasutab eraldi muutujatCH_WEATHER_TABLE(vaikimisivalisilm) — muidu kirjutaks.envväärtus valesse tabelisse.
docker logs -f weather-collector
docker exec clickhouse clickhouse-client --user default --password dev_clickhouse_2026 \
--query "SELECT * FROM uus67.valisilm ORDER BY hour DESC LIMIT 24"
nutikodu-web)Interaktiivne ajatelg uus67 skeemi zigbee andurite andmetele. FastAPI backend +
üks staatiline leht (ECharts), eestikeelne, mobiilisõbralik, tume/hele teema.
Graafikul kuvatakse ka välistemperatuur rohelise joonena (/api/valisilm).
| 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):
nutikodu.odamus.com → 188.166.84.16.kanad/edge, /opt/edge/Caddyfile):
nutikodu.odamus.com { reverse_proxy http://100.91.118.16:80 }. TLS automaatne (Let's Encrypt).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:
# 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:
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.