The house in one screen

by

RethinkKNX: dom, który sam siebie pilnuje

Dziewięć lat domu, który wszystko loguje. Magistrala KNX bez pamięci, baza danych pamiętająca każdy telegram i dwadzieścia dziewięć procesów, cztery ekrany oraz jeden robot, które ją czytają. Łącznie z tygodniem, w którym model uznał, że światło słoneczne nie istnieje.

Dziś za dwadzieścia jedenasta rolety na górnym piętrze zjechały w dół i nikt ich o to nie prosił. Cztery godziny wcześniej coś wyliczyło, że słońce będzie świecić na tę szybę przed jedenastą, że temperatura w pokoju dojdzie do 27,1 stopnia, jeśli nic nie zrobi, i że zamknięcie rolet zatrzyma ją na 26,8. System zapisał to razem z liczbą, którą dostałoby za nicnierobienie, i poczekał z akcją do 10:35.

To jest dom, który buduję od grudnia 2016. To instalacja KNX, czyli rzecz zwyczajna i raczej nudna do trzymania w ścianie, plus jakieś dziewięć lat oprogramowania, które próbuje uczynić ją mniej nudną. Oto jak to się składa w całość, co robi dobrze i ta część, w której z pełnym przekonaniem system doszedł do wniosku, że światło słoneczne nie wpływa na temperaturę pokoju.

Wersja krótka

Wszystko poniżej to opis, jak każda z tych rzeczy powstała i ile kosztowała. Jeśli tylko o to ci chodziło, możesz skończyć tutaj.

Działa.

  • Każdy telegram na magistrali staje się wierszem w bazie, w obie strony, więc domu można zapytać o zeszły wtorek.
  • Siedem pokoi uruchomionych jako osobne procesy, każdy patrzy tylko na własne urządzenia i każdy da się zrestartować tak, że reszta tego nie zauważy.
  • Prognozuje najbliższe 24 godziny dla każdego pokoju, symuluje kilka sposobów na utrzymanie go w komfortowej temperaturze, wycenia je według tego, jak bardzo przeszkodziłyby temu, kto w nim siedzi, i wybiera najtańszy działający. Zapisuje akcję, którą sugeruje, wraz z tą, która została wykonana.
  • Prognozuje uzysk z paneli PV, pobór energii w domu i stan baterii — wszystko skalibrowane na podstawie historii tej konkretnej instalacji, a nie z karty katalogowej.
  • Napędza aplikację na iPhone'a, aplikację na iPada, przeglądarkę, panel e-paper na biurku, mały kolorowy wyświetlacz oraz flotę płytek ESP8266 i ESP32, które nigdy nie miały mówić po KNX.
  • Udostępnia dom robotowi - bardzo ostrożnie.

Nie działa.

  • Nie podejmuje własnych decyzji dotyczących chłodzenia. Planer od tygodni chodzi w shadow mode: decyduje, zapisuje i nie zmienia niczego. Przełączenie tego to jedna linijka w konfiguracji i nie zrobiłem tego z powodu, do którego jeszcze dojdę.
  • Model termiczny dla większości pokoi wciąż jest oznaczony jako nieskalibrowany, i nie dlatego, że kod jest zły.
  • Nie ma tu żadnej wysokiej dostępności. Serwer to pudełko na strychu. Jak padnie, dom wraca do bycia mniej inteligentną instalacją KNX i to jest ta jedna naprawdę dobra rzecz w budowaniu na standardzie, który działa bez ciebie.

Skąd się to wzięło i co było z tym nie tak

KNX to magistrala obiektowa. Dwa przewody biegną po domu i wisi na nich każdy włącznik, przekaźnik, siłownik rolety, termostat i licznik. Każde ma adres grupowy, a ten dom ma ich 344 w 29 typach datapointów. Naciskasz włącznik, wychodzi telegram; gdzieś przekaźnik słyszy swój adres i zwiera. Żaden serwer nie bierze w tym udziału i nikt go tu nie chce. Działa to od dekad i będzie działać dalej w dniu, w którym w końcu coś się zepsuje.

Problem z tym jest w zdaniu, które przed chwilą napisałem. Wychodzi telegram i przekaźnik się zwiera. To cała transakcja. Magistrala nie ma pamięci. Zapytaj KNX, jak ciepło było w sypialni we wtorek w nocy, a nie ma kogo pytać, bo wtorkowa noc była serią zmian napięcia na parze przewodów i już jej nie ma.

Moja pierwsza próba naprawienia tego to Raspberry Pi pod schodami z eibd, o czym pisałem jeszcze w 2014. Działało. Nie robiło też nic poza umożliwieniem mi wysyłania telegramów ze skryptu, czyli było pilotem z dodatkowymi krokami. Demon został od tego czasu wymieniony i okazało się, że to osobna historia, głównie o tym, jak niewiele musiało się zmienić.

Ciekawa decyzja przyszła później i brzmiała tak: przestań traktować magistralę jako coś, czym się rozkazuje, i zacznij traktować ją jako coś, co się loguje.

Jedyny pomysł, na którym stoi całość

Dokładnie dwa procesy mają prawo dotknąć przewodu. Jeden słucha wszystkiego, co mówi magistrala, i zapisuje każdy telegram do tabeli. Drugi obserwuje tę samą tabelę pod kątem wierszy adresowanych na zewnątrz i wystawia je na przewód. Żaden z nich nie wie, czym jest światło.

Cała reszta domu, każdy pokój, planer chłodzenia, liczniki, serwer WWW, telefony, czytają changefeed na tej tabeli i dopisują do niej wiersze. RethinkDB robi tu ciężką robotę: subskrybujesz zapytanie, a ono samo wypycha do ciebie zmiany, więc proces pokoju to pętla po zdarzeniach pasujących do jego własnych adresów i nic niczego nie odpytuje. Dosłowna architektura event bus (KNX) i event sourcing.

Jeden telegram, cała droga dookoła
Jeden telegram, cała droga dookoła

Wynikają z tego trzy rzeczy i to dzięki nim reszta tego artykułu jest w ogóle możliwa.

  1. Dom da się przepytać. Każdy telegram od lat, z wartością zdekodowaną przez swój typ datapointu, a tam, gdzie wysłało go oprogramowanie, także z powodem. To właśnie sprawia, że model termiczny z następnej sekcji jest czymś, co można dopasować, a nie czymś, co trzeba zgadywać.
  2. Nic nie potrzebuje magistrali, żeby dało się to przetestować. Cały zestaw testów jednostkowych chodzi bez bazy danych, a co dopiero bez interfejsu KNX. Plików testowych jest 54, a harness natychmiast wywala się z opisanym błędem na przypadkowym prawdziwym połączeniu, zamiast wisieć dwie minuty na ponawianiu.
  3. Nowe rzeczy są tanie. Pasek LED mówiący po MQTT i roleta mówiąca po KNX są z punktu widzenia pokoju tym samym rodzajem obiektu: czymś, co ma adres i produkuje wiersze.

Parts i rooms

Part to jedno urządzenie. Zna swoje adresy grupowe, ma update_internal_state, do którego trafiają pasujące zdarzenia, i wysyła telegramy przez dopisywanie wierszy. W tym katalogu leży 39 plików, a do pokoi wpiętych jest 16 klas w 14 kategoriach: światła, rolety, okna, termostaty, gniazdka, czujniki, oczyszczacz powietrza, klimatyzacja, paski RGB, odkurzacz automatyczny, piloty i kilka rzeczy, które tak naprawdę są sprzętem AGD przebranym za part.

Room to pojemnik, który otwiera jeden changefeed na adresy wszystkich swoich elementów i trzyma automatykę. Siedem pokoi w konfiguracji, dziewięć modułów pokoi, bo dwa z nich to klatki schodowe, które zachowują się jak pokoje, nie będąc nimi.

Element, którego używam najczęściej, jest najmniej sprytny. Virtual part to nazwa, adres grupowy i typ datapointu wybrany z listy, tworzony z poziomu edytora w przeglądarce. Pojawia się w pokoju, w telefonie i na panelu, i jest podchwytywany na żywo: proces pokoju dostaje sztuczne zdarzenie przeładowania i subskrybuje się od nowa bez restartu. W większość dni dodanie czegoś do domu to teraz wpisanie adresu w formularz.

Pokoje, uporządkowane i przemianowane bez dotykania kodu
Pokoje, uporządkowane i przemianowane bez dotykania kodu

Na tym ekranie jest blizna, którą warto wskazać palcem. Tabela partów była kiedyś kluczowana samą nazwą, więc dwa pokoje z elementem o nazwie window były, z punktu widzenia bazy, jednym elementem. Zmiana nazwy jednego kasowała drugi. Naprawą była jednorazowa migracja na klucz {name}_{room}, a lekcja jest najzwyklejsza z możliwych: błąd nie był w kodzie, który się wywalił, tylko w kluczu głównym wybranym cztery lata wcześniej w jedno popołudnie.

Co właściwie działa

Dwadzieścia dziewięć procesów na serwerze, pod supervisorem, plus dwa, które nie mogą tam mieszkać.

Co właściwie działa
Co właściwie działa

Te dwa ostatnie ładnie pokazują, dlaczego z trudem zdobyta wiedza powinna być zapisana. Proces czujników czyta układ temperatury i wilgotności po I2C, czyli musi chodzić na sprzęcie fizycznie do tego układu podłączonym, na Raspberry Pi przy drzwiach wejściowych, a nie na serwerze. To Raspberry ma Pythona 3.5 i checkout z 2022, którego nie da się zaktualizować, bo aktualny kod używa f-stringów, a interpreter jest od nich starszy.

I tak wykres CO2 stał zamrożony na 769 ppm przez tygodnie. Każdy deploy schodził czysto, każdy proces się restartował, a ten jeden, który miał znaczenie, siedział na innej maszynie i nikt go nie tknął. W kodzie nie było czego debugować. Dziś to pierwsza linijka w notatkach wdrożeniowych.

Planer chłodzenia, czyli miejsce, w którym to przestaje być hobby

Reszta tego systemu to hydraulika, a dobra hydraulika jest niewidoczna. Ta część to ta, którą bym komuś pokazał.

Problem: temu domowi robi się latem gorąco i ma cztery sposoby, żeby coś z tym zrobić. Zamknąć rolety. Otworzyć okna. Włączyć klimatyzację. Albo czekać. Każdy ma inną szybkość, inny koszt i inny poziom hałasu, a właściwy wybór o drugiej po południu jest złym wyborem o drugiej w nocy.

Naiwna wersja tego istniała latami i mieściła się w jednej linijce: jeśli w pokoju jest powyżej 27 stopni, włącz klimatyzację. Nie wiedziała nic o słońcu, baterii, godzinie ani o tym, czy ktoś śpi. Została skasowana.

Planuje jednostki, a nie pokoje

Pierwszą rzeczą, która musiała się zmienić, był rzeczownik. Salon i jadalnia to w konfiguracji dwa pokoje, ale dzielą jeden czujnik temperatury, jedną klimatyzację i jedną roletę. Planowane osobno produkowały dwie identyczne decyzje na każdy takt, dwa telegramy na ten sam adres, dwa identyczne alerty i, co najlepsze, plan dla salonu, który uparcie postanawiał zamknąć roletę, której salon nie ma.

Więc planer pracuje na jednostkach planowania. Górne piętro to jedna jednostka z dwoma pokojami złożonymi w jeden stan: temperatura od tego, który ma czujnik, pozycja rolety od tego, który ma roletę, a okno liczy się jako otwarte, jeśli otwarte jest u któregokolwiek. Historia zostaje osobno dla każdego pokoju, bo to jest pomiar, a pomiarów nie powinno się uśredniać, zanim się wie po co.

Ile kosztuje ruch

Co pięć minut każda jednostka dostaje prognozę na 24 godziny, zestaw planów kandydujących i symulację każdego z nich na modelu termicznym pokoju. Wygrywa najtańszy plan, który utrzyma przewidywany szczyt w paśmie komfortu. Wszystko to jest nudne, dopóki nie zapytasz, co znaczy najtańszy.

Nie chodzi o kilowatogodziny. Tabela wygląda tak:

BASE_COST = {
    "shade": 1,
    "window": 1,
    "ac": 6,
}

OCCUPIED_SHADE_SURCHARGE = 1
OCCUPIED_WINDOW_SURCHARGE = 1
QUIET_HOURS_WINDOW_SURCHARGE = 5

Roleta kosztuje 1, a klimatyzacja 6, co nie jest twierdzeniem o prądzie. To porządek: wyczerp darmowe opcje, zanim cokolwiek wydasz. Potem dopłaty, i to jest właściwy pomysł. Ruch, który ktoś zauważy, kosztuje więcej, a okno to jedyny siłownik w domu, który potrafi obudzić śpiącego człowieka.

Policz to dla gorącej nocy w zajętym pokoju. Otwarcie okna to 1 + 1 + 5 = 7. Włączenie klimatyzacji to 6. Więc dom kupuje prąd zamiast cię budzić, i robi to z powodu trzech liczb całkowitych, a nie z powodu wyjątku w kodzie. Kiedy nikogo nie ma, żadna dopłata nie obowiązuje i ten sam kod z radością otwiera okna zamiast tego.

Szybkości zmiany temperatury celowo nie ma w tej tabeli. Nie musi jej być: plan, który jest zbyt wolny, po prostu nie utrzymuje pasma w symulacji i przegrywa merytorycznie. Zamknięta roleta jest warta jakieś 0,06 stopnia na godzinę, a otwarte okno około 0,075, i żadne z nich nie jest dość szybkie, żeby zaczynać późno. Dlatego planer działa o cały stopień przed sufitem, a nie na nim.

Jedna decyzja o chłodzeniu, od początku do końca
Jedna decyzja o chłodzeniu, od początku do końca

Klimatyzacja ma na to wszystko jeszcze własną bramkę, a ta dotyczy instalacji fotowoltaicznej, nie komfortu. Może wystartować tylko wtedy, gdy na zewnątrz jest cieplej niż w środku, poza przedziałem od 21:00 do 08:00, przy niegrzejącym piecu, przy panelach robiących ponad kilowat i baterii powyżej 35 procent. Na tej instalacji zamyka ją mniej więcej w godzinach od 08:00 do 18:00 w słoneczny dzień, co jest uprzejmym sposobem powiedzenia, że chodzi o "darmową" energię.

Dwóch szczegółów tej reguły będę bronić. Nieświeży odczyt z falownika odmawia startu, bo brak danych nie może oznaczać, że płaci słońce. Nieświeży odczyt z pieca nie blokuje, bo padnięcie niepowiązanego mostka MQTT nie może wyłączyć chłodzenia w sierpniu. I jest to bramka wyłącznie na start: klimatyzacja włączona ręcznie o 23:00 chodzi dalej, bo dom nie jest niczyim szefem.

Shadow mode: co by zrobił
Shadow mode: co by zrobił

To jest ten ekran. Akcje automatyczne: wyłączone. Planer od tygodni decyduje i nie porusza niczym. Każda decyzja ląduje w logu razem z wariantem, który pokonała, a powód, dla którego to tak zostawiłem, jest w następnej sekcji.

Najbliższe 24 godziny każdego pokoju i co planuje z nimi zrobić
Najbliższe 24 godziny każdego pokoju i co planuje z nimi zrobić

Tydzień, w którym model uznał, że słońce nie istnieje

Symulacja to mały model fizyczny pokoju: z jakąś prędkością ucieka mu ciepło na zewnątrz, zyskuje je od słońca przez szybę, traci przez otwarte okno, a klimatyzacja ciągnie go w stronę nastawy. Pięć współczynników. Są dopasowywane od nowa każdej nocy z zapisanej historii samego pokoju, czyli dokładnie z tego, po co powstała tabela zdarzeń.

Pewnego ranka spojrzałem na dopasowane współczynniki dla górnego piętra i człon słoneczny wynosił zero. Nie mało. Zero. Co oznacza, że w każdym symulowanym planie zamykanie rolet nie robiło zupełnie nic, a planer z powagą porównywał strategie zacienienia, które jego własny model uważał za puste operacje.

Błąd nie był w kodzie dopasowującym. Był w domu. Wróciłem do historii i znalazłem to: ze 140 dziennych migawek z roletą w dole 71 procent miało włączoną klimatyzację. Z 487 z roletą w górze miało ją 12 procent. Zamykam tę roletę wyłącznie w te dni, w które i tak włączam klimatyzację. Zysk słoneczny i chłodzenie klimatyzacją są więc niemal idealnie powiązane przez prawie cały zapis.

Był jeden czysty wycinek: godziny dzienne z wyłączoną klimatyzacją. Roleta w górze, pokój grzeje się o +0,058 stopnia na godzinę (n=425). Roleta w dole, chłodzi się o 0,030 (n=40). Czyli roleta oczywiście działa, a dane jako całość po prostu tego nie widzą.

I to, co model znalazł, a czego nie wiedziałem

Zdarzyło się też odwrotnie i było lepiej. Wietrzenie nocne wciąż przegrywało z planami, które nie miały sensu, a powodem było to, że model traktował otwarte okno jako otwarte okno niezależnie od rolety przed nim. A to są pełne rolety z izolacją. Więc znów poszedłem do historii, tym razem po jeden dziecięcy pokój nocą, przy zewnętrznej niższej o co najmniej trzy stopnie:

  • Okno otwarte, roleta w górze: chłodzi o 0,0484 stopnia na godzinę na każdy stopień różnicy (n=36).
  • Okno otwarte, roleta w dole: 0,0079 (n=372).

Sześć razy. A przy rolecie w dole otwarcie okna w ogóle prawie nie robi różnicy: 0,0066 zmienia się w 0,0079. Zamknięta roleta nie blokuje tylko słońca, ale także ruch powietrza, a system modelował te dwie rzeczy jako niezależne.

Naprawa przesunęła dopasowaną stałą czasową tego pokoju z 520 godzin, które kontrola sensowności słusznie odrzucała jako bzdurę, na 277, przyjęte, i ponad dwukrotnie podniosła jego współczynnik wentylacji. Zmieniła też zachowanie: plan wietrzenia podnosi teraz także roletę, wszędzie tam, gdzie roleta może się ruszać. To zastąpiło cały osobny moduł, który napisałem specjalnie pod nocne przewietrzanie i który istniał wyłącznie dlatego, że pozycja rolety wypadała kiedyś z modelu nocnego przez mnożenie i przez to nigdy nie mogła wygrać sama z siebie.

To jest argument za trzymaniem każdego odczytu. Oba te odkrycia to zapytanie do bazy. Żadne z nich nie jest dostępne dla systemu, który wie tylko, co dom robi w tej chwili, i w żadne z nich nie uwierzyłbym z intuicji. Zgadywałbym, że roleta znaczy mniej, niż znaczy dla słońca, i znacznie mniej, niż znaczy dla powietrza.

Każda decyzja i wariant, który pokonała
Każda decyzja i wariant, który pokonała

Co sprowadza mnie z powrotem do tego, dlaczego wciąż jest w shadow mode. Ten log jest jednocześnie argumentem za włączeniem i przeciw. Większość wpisów jest trafna. Część jest trafna z powodów, których nie zweryfikowałem. Większość pokoi wciąż pokazuje nieskalibrowany, bo poprzeczka to trzy dni czystych próbek, a to lato ciągle samo sobie przerywa. Czytanie dwóch tygodni decyzji, z którymi nie musiałem żyć, jest tanie; czytanie ich po tym, jak dom kogoś obudził, już nie.

Jedyna rzecz, która i tak działa

Jest jeden wyjątek i jest celowy. Watchdog mierzy, jak długo klimatyzacja faktycznie chodzi, ostrzega raz po przekroczeniu czternastu godzin, a po osiemnastu, przy pokoju już wygodnie poniżej celu, wyłącza ją. Działa niezależnie od tego, czy autopilot jest włączony, bo urządzenie, którego nikt nie wyłączył, to usterka, a usterka nie jest preferencją.

Istnieje z powodu 23-godzinnego biegu. Stary kod śledził czas pracy na samym obiekcie klimatyzacji, w polu, które było ustawiane wyłącznie w gałęzi if self.ir:. Ta jednostka nie ma własnego nadajnika podczerwieni, więc gałąź nigdy się nie wykonała, pole zostało puste, a zabezpieczenie porównywało się z niczym przez cały czas swojego istnienia. Watchdog mierzy teraz z zapisanej historii, z tych samych migawek, z których dopasowywany jest model, bo to jest fakt o domu, a nie fakt o pamięci obiektu.

Energia i odmowa rysowania linii

Na dachu są panele, jest bateria i falownik odpytywany co dziesięć sekund. Ciekawa jest nie bieżąca wartość, tylko najbliższe 24 godziny.

Jak prognoza na jutro powstaje z wczoraj
Jak prognoza na jutro powstaje z wczoraj

Nic w tym potoku nie zna mocy paneli. Zestaw to, co dach wyprodukował, z nasłonecznieniem, przy którym to zrobił, a współczynnik konwersji wypada z arytmetyki, z zacienieniem, brudem, prawdziwą sprawnością falownika i kątem dachu już w środku. Ta sama sztuczka daje kilowatogodziny na procent baterii w każdą stronę, jej realne limity mocy i rezerwę, poniżej której nie zejdzie, przy czym żadna z tych liczb nie zgadza się z kartą katalogową i wszystkie są prawdziwe dla tej baterii.

Pobór domu to część, którą lubię. To średnia ważona z ostatnich siedmiu dni, po porze doby w kubełkach piętnastominutowych, gdzie każdy miniony dzień jest ważony tym, jak bardzo jego niebo pasuje do nieba, które nadchodzi. Pochmurny wtorek jest lepszą wskazówką na pochmurne jutro niż wczoraj, a dom ma dość historii, żeby wiedzieć, który wtorek to był.

Słoneczna sobota, produkcja kontra zużycie
Słoneczna sobota, produkcja kontra zużycie

I teraz część, o którą pokłócę się z każdym. Prognoza jest rysowana jako rozszerzający się wachlarz, a nie linia.

Najbliższe 24 godziny jako wachlarz, a nie linia
Najbliższe 24 godziny jako wachlarz, a nie linia

Każdy przewidywany punkt niesie pasmo wewnętrzne i zewnętrzne, ściśnięte do zera w chwili teraz i rozchodzące się wraz z tym, jak daleko w przód patrzy. Narysowanie średniej jako czystej, pewnej siebie krzywej byłoby banalne i wyglądałoby znacznie lepiej. Byłoby też kłamstwem powiedzianym ładnym krojem pisma, a ja podejmuję na podstawie tego wykresu decyzje, na przykład czy pralka może poczekać na słońce, przy których uczciwą odpowiedzią często jest model nie wie. Płaskie zielone pasmo leżące nocą na podłodze rezerwy to wykres mówiący, że o czwartej nad ranem przejmuje sieć, i wolę to widzieć razem z jego niepewnością.

Jedna liczba na tej stronie była przez miesiące błędna w sposób wart wyznania. Falownik publikuje rejestr energii pobranej dzisiaj i na tym egzemplarzu czyta zawsze zero. Zamiast wyprowadzać tę liczbę przez całkowanie mocy chwilowej i liczenie na najlepsze, dzisiejszy import z sieci to teraz różnica dwóch odczytów licznika całkowitego importu licznika smart względem punktu odniesienia stemplowanego o północy. Martwy rejestr jest nadal publikowany wyłącznie po to, żeby starsza wersja aplikacji na telefon dalej potrafiła zdekodować payload.

Czworo drzwi do tego samego domu
Czworo drzwi do tego samego domu

Wszystko, co to czyta

Wszystko powyżej byłoby cronem z poglądami, gdyby nie było na co patrzeć. Są cztery wejścia i wszystko wisi na jednym z nich.

Aplikacje i kontrakt, który nie pozwala mi ich zepsuć

Jest aplikacja na iPhone'a, czeska, i na iPada, CzeskaXL, w trzech kolumnach. Obie są w Swifcie i UIKicie, obie biorą REST na stan i Socket.IO na widok na żywo.

Tryb awarii przy prywatnym API i natywnym kliencie jest specyficzny i głupi: zmieniam nazwę pola we wtorek, dekoder aplikacji wywala się na typie, którego się nie spodziewał, a pierwsze, co o tym wiem, to czerwony krzyżyk w miejscu, gdzie powinien być włącznik. Nic się nie loguje. Nic nie alarmuje. Telefon po prostu cicho przestaje działać, w sposób, który wychodzi dopiero, kiedy ktoś sięga po światło.

Więc jest checker, który parsuje swiftowe modele, do których aplikacje dekodują, wyciąga z nich kontrakt i waliduje względem niego prawdziwe payloady z API, odwzorowując reguły typów, które faktycznie stosuje dekoder JSON-a w Swifcie. Chodzi offline na zakomitowanych fixture'ach, chodzi w zestawie testów, a hook gita odmawia pusha, kiedy te dwie rzeczy się nie zgadzają. To najbardziej wartościowe sto linijek w całym projekcie i istnieje dlatego, że wszystko inne w niezgodności schematu jest niewidoczne.

Panel na biurku

Wyświetlacz e-paper to CrowPanel ESP32-S3 i cała sztuczka siedzi w podziale pracy. Panel niczego nie składa. Prosi serwer o ekran; serwer renderuje szablon HTML w headlessowej przeglądarce, ditheruje wynik do jednego bitu na piksel i odsyła 26 928 bajtów, czyli 792 na 272 podzielone przez osiem. Panel rysuje bajty.

Co oznacza, że zmiana tego, co mówi ściana, to edycja szablonu Jinja na serwerze, a nie update firmware'u. Układ, typografia i to, co uchodzi za ważne, mieszkają tam, gdzie da się je zmienić w minutę. Zadaniem mikrokontrolera jest bycie ramką na zdjęcia z Wi‑Fi i jest w tym bardzo dobry.

To samo rozumowanie obejmuje mały kolorowy wyświetlacz pokazujący powiadomienia i rozrzucone po domu płytki ESP: pasek LED w sypialni, hub temperatury i CO2, czujnik ruchu i światła na korytarzu, ściemniacz PWM do lampek i sterownik drzwi kończący się przekaźnikiem KNX. Wszystkie mówią po MQTT. Jeden proces mostka składa MQTT do tej samej tabeli co reszta, a z punktu widzenia pokoju tanie ESP8266 i certyfikowany siłownik KNX są tego samego rodzaju.

Rozbudzony Kompot
Rozbudzony Kompot

Wpuszczanie robota

Kompot to robot na moim biurku. Odpowiada na pytania, a jedną z rzeczy, o które można go zapytać, jest dom: jak ciepło jest w pokoju, czy ktoś jest w domu, co jest w kalendarzu, co gra. Potrafi też coś zmienić.

To ostatnie zdanie jest całym problemem projektowym i nie jest tym, którego byś się spodziewał. Serwer, z którym rozmawia, nigdy nie wychodzi poza sieć lokalną, chce tokena bearer i sprawdza nagłówek Host względem listy dozwolonych, żeby strona WWW nie mogła przez rebinding DNS wejść sobie do środka. W porządku. Ale zagrożenie, które ukształtowało te reguły, to wcale nie jest prawdziwy napastnik w czarnym kapeluszu. Jest zapisane w źródle i pozwolę mu przemówić samemu:

ma powstrzymać małego napastnika: 8 latka proszącego w środku grudnia o otwarcie okna.

Token uwierzytelnia robota. Nie mówi nic o tym, kto przed nim stoi. Więc odczyty są za darmo, a każdy zapis niesie imię tego, kogo robot rozpoznał po głosie; zapisy od kogokolwiek spoza listy dorosłych są odrzucane, tak samo jak cokolwiek w godzinach ciszy. Odmowa to zdanie, które robot mówi na głos, a nie błąd.

Takie serwery są dwa, jeden w internecie i jeden lokalny, i celowo dzielą jeden zestaw definicji narzędzi. Dwa zestawy prędzej czy później odpowiedziałyby jedno klientowi czatu, a drugie robotowi, a dzień, w którym się rozjadą, jest dniem, w którym bezpieczniejszy z nich przestaje być tym, który się liczy.

Jeszcze jeden szczegół, który bym zostawił. Każdy odczyt raportowany przez robota niesie swój wiek, bo robot mówiący w sypialni jest 19 stopni z tygodniowego wiersza jest gorszy od takiego, który mówi, że nie wie. Pewne siebie podawanie nieświeżych danych to ten tryb awarii, który sprawia, że ludzie przestają ufać systemowi w całości, a uniknięcie go kosztuje jeden timestamp.

Co się z tego składa

Dziewięć lat, 1401 commitów i jakieś 69 000 linii Pythona, z czego 15 000 to testy. Pięćdziesiąt osiem tabel, 180 tras, 344 adresy grupowe, dwadzieścia dziewięć procesów i dwa kolejne na Raspberry, którego nie da się zaktualizować. Jeden dom.

Decyzja, którą podjąłbym ponownie bez wahania, to ta nudna z góry: dwa procesy dotykają przewodu, a cała reszta rozmawia z bazą danych. Każda dobra rzecz w tym artykule jest jej konsekwencją. Model termiczny da się dopasować, bo odczyty zostały zachowane. Odkrycie o rolecie to zapytanie. Aplikacje, panel, płytki ESP i robot zostały dodane bez zbliżania się do magistrali, bo żadne z nich nie wie, że ona istnieje.

Błędna decyzja jest mniejsza i bardziej wstydliwa: pozwoliłem dokumentacji opisywać system zamiast jego przyczyn. I tak diagram w tym repozytorium wciąż pokazuje demona wymienionego w listopadzie, a zabezpieczenie siedziało latami, porównując się z polem, które nigdy nie było ustawiane. Oba były oczywiste w chwili, gdy ktoś na nie spojrzał. Żadne nie zamierzało się zgłosić samo.

Dalej, w kolejności, w jakiej bym to adresował: zebrać dość czystych dni, żeby skalibrować pokoje, które wciąż pokazują nieskalibrowanie, a potem włączyć autopilota na jeden pokój i zobaczyć, czy mogę mu ufać.

Contact me

Questions, ideas, or spotted a bug? Send me a note.