Case: oma talo — Osa 15

Written by

in

Kun käyttöönotto paljasti piiloviat: FMA-kovennus

Tämä on viidestoista osa sarjasta, joka dokumentoi EnergyHub-kotiautomaatiojärjestelmän rakentamisen vanhaan rintamamiestaloon. Edellinen osa pysähtyi hetkeen ennen live-käyttöönottoa: Home Assistant- ja Node-RED-pohjainen energianhallintajärjestelmä oli pyörinyt shadow-moodissa viikkoja, päätöslogiikka oli käyty läpi, ja vaiheistettu käyttöönottosuunnitelma oli valmis. Lupasin kertoa seuraavaksi, miten vaiheistus eteni käytännössä ja mitä tapahtui ensimmäisten viikkojen aikana.

Lyhyt vastaus: vaiheistus eteni jokseenkin suunnitellusti. Mutta käyttöönotto paljasti vikoja, joita shadow-moodi ei voinut näyttää — eikä siksi, että ne olisi tehty huolimattomasti, vaan siksi, että ne olivat luonteeltaan sellaisia, että ne aktivoituvat vasta kun järjestelmä ottaa oikean kontrollin oikeista laitteista.

Tämä osa kertoo niistä vioista ja siitä, miten ne käytiin systemaattisesti läpi. Se on tarina menetelmästä nimeltä FMA — failure mode analysis — ja siitä, miksi se kannatti tehdä juuri käyttöönoton kynnyksellä eikä vasta sitten, kun jokin oli mennyt pahasti pieleen.

Miksi shadow-moodi ei riitä

Shadow-moodi on hyvä turvaverkko. Järjestelmä laskee päätökset mutta ei toteuta niitä; jos logiikassa on virhe, se näkyy lokissa eikä laitteen käyttäytymisessä. Viikkojen shadow-ajo antoi luottamuksen siihen, että päätöslogiikan iso kuva on kunnossa.

Mutta shadow-moodilla on sokea piste. Se ei voi paljastaa vikoja, jotka syntyvät vuorovaikutuksesta oikean laiteohjauksen kanssa. Kun järjestelmä vain laskee eikä ohjaa, se ei koskaan joudu tilanteeseen, jossa lähetetty komento ja toteutunut tila eroavat toisistaan. Se ei joudu palautumaan turvakatkaisusta, koska se ei koskaan laukaise sellaista. Se ei joudu käsittelemään tilannetta, jossa vanha retained-viesti elää MQTT-brokerissa ohjauspäivityksen jälkeen, koska shadow-moodissa kukaan ei reagoi siihen viestiin.

Toisin sanoen: vaarallisin vikaluokka tällaisessa älykodin ohjausjärjestelmässä on hiljainen vika. Mikään ei kaadu. Lokissa ei näy virhettä. Laite vain käyttäytyy väärin — tai jää käyttäytymättä — ja jos kukaan ei satu katsomaan oikeaa mittaria oikealla hetkellä, virhe voi elää päiviä.

Juuri tällaisten vikojen löytämiseksi tein FMA:n.

Mikä FMA on

FMA — failure mode analysis eli vika- ja vaikutusanalyysi — on menetelmä, joka on tuttu teollisuusautomaatiosta ja turvallisuuskriittisestä suunnittelusta. Idea on yksinkertainen: sen sijaan että odotetaan vikojen ilmenevän itsestään, käydään järjestelmä läpi ja kysytään jokaisesta osasta järjestelmällisesti, miten tämä voi epäonnistua. Ei ”epäonnistuuko”, vaan ”miten”.

Kävin EnergyHubin läpi tällä kysymyksellä ja tunnistin 17 erillistä vikatilaa — failure modea, joista käytän merkintää F1–F17. Ne priorisoitiin ja toteutettiin seitsemässä erässä. Jokainen korjaus tehtiin omana muutoksenaan, omalla testillään, ja jokainen katselmoitiin erikseen. Käytin tähän kahden tekoälyn työnjakoa: toinen analysoi ja toteutti muutokset, toinen teki arkkitehtuurikatselmuksen ja staattisen tarkistuksen. Tästä työnjaosta lisää myöhemmin.

Vioista hahmottui kolme toistuvaa perusluokkaa. Ne ovat tämän artikkelin punainen lanka, koska ne paljastavat jotain olennaista siitä, millaisia ovat hajautetun ohjausjärjestelmän tyypilliset heikkoudet.

Vikaluokka 1: jämähtänyt viesti

MQTT — viestiväylä, jolla kotiautomaation osat puhuvat keskenään — tukee niin sanottuja retained-viestejä. Kun viesti merkitään retained-tilaan, broker säilyttää sen ja antaa sen jokaiselle uudelle tilaajalle, joka liittyy kanavalle. Tämä on erinomainen ominaisuus tilatiedolle: kun järjestelmä käynnistyy uudelleen, se saa heti tietää viimeisimmän tunnetun moodin, eikä jää sokeaksi siihen asti, kunnes seuraava päivitys sattuu tulemaan.

Mutta sama ominaisuus on miina. Jos retained-viesti kantaa vanhaa, väärää tilaa, se ei katoa itsestään. Se elää brokerissa, kunnes joku julkaisee tilalle uuden. Ja jos järjestelmän jokin osa lukee tuon vanhan viestin ja toimii sen mukaan, syntyy se mitä kutsun zombieksi: tila, joka on jo nollattu yhdessä paikassa mutta herää henkiin toisesta.

Tämä luokka tuli näkyviin dramaattisimmin turvakatkaisun yhteydessä, johon palaan tuonnempana. Mutta sen perusmuoto oli yksinkertainen, ja sen korjaus opetti periaatteen, joka toistui läpi koko työn.

Vikaluokka 2: hiljainen epäonnistuminen

Tämä on se vaarallisin luokka, jonka jo mainitsin. Hiljainen epäonnistuminen tarkoittaa tilannetta, jossa toiminto ei tee mitä piti, mutta mikään ei ilmoita siitä.

Otetaan konkreettinen esimerkki. Järjestelmä lämmittää käyttöveden kerran päivässä, ja se pitää kirjaa siitä, onko vesi jo lämmitetty (dhw_heated_today). Tämä lippu nollataan joka yö, jotta seuraavana päivänä vesi taas lämmitetään. Alkuperäisessä toteutuksessa nollaus tapahtui ajastettuna kello 00:05.

Mutta entä jos Node-RED — ohjelmisto, joka tämän nollauksen tekee — sattuu olemaan käynnistymässä uudelleen juuri kello 00:05? Päivitys, uudelleenkäynnistys, mikä tahansa. Silloin nollaus jää tapahtumatta. Lippu jää eilisen true-arvoon. Ja seuraavana päivänä järjestelmä päättelee, että vesi on jo lämmitetty — eikä lämmitä sitä. Mikään ei kaadu. Lokissa ei lue virhettä. Vain kylmä suihku seuraavana aamuna kertoo, että jokin meni pieleen.

Korjaus oli muuttaa nollaus ajastetusta päivämääräpohjaiseksi: järjestelmä tarkistaa joka ohjaussyklillä, onko päivä vaihtunut edellisestä nollauksesta, ja nollaa liput silloin. Tämä tarkistus selviää uudelleenkäynnistyksestä, koska se ei riipu yhdestä ainoasta hetkestä.

Tämän luokan korjauksia oli useita. Sähkön hintaohjauksen tyyppisuojaus: tyhjä hintalista johti aiemmin tilanteeseen, jossa vertailu ”onko nyt halpa tunti” palautti aina epätoden, ja sähköauton lataus jäi tapahtumatta halvalla — hiljaa. Käyttövesiboostin uusintayrityksen esto: jos boost epäonnistui, sen laukaisuehdot jäivät voimaan ja se yritti käynnistyä uudelleen loputtomasti. Lämpöpumpun asetusarvon vahvistus: lämpöpumpulle lähetetty comfort wheel -arvo merkittiin ”lähetetyksi” jo lähetyshetkellä, ei silloin kun lämpöpumppu oikeasti vahvisti ottaneensa sen vastaan — joten jos komento ei mennyt perille, sitä ei lähetetty uudelleen.

Kaikilla näillä on sama rakenne: toiminto epäonnistuu tavalla, joka ei näy mitenkään, ellei satu katsomaan oikeaa arvoa oikealla hetkellä.

Vikaluokka 3: kaksi omistajaa

Kolmas luokka on hienovaraisin ja arkkitehtonisesti opettavaisin. Se syntyy, kun samalla tilatiedolla on kaksi lähdettä.

EnergyHubissa järjestelmän toimintamoodi — normaali, loma, hätätila — kirjoitettiin alun perin kahdesta paikasta. Oli oma dedikoitu kanava moodille, ja sen lisäksi moodi kulki mukana isommassa ”koontiviestissä”, joka kokosi yhteen järjestelmän eri tilatietoja. Kaksi kirjoittajaa, sama muuttuja.

Ongelma syntyy ristiriidassa. Jos moodi vaihtui omalla kanavallaan, mutta koontiviesti ehti tulla vielä vanhalla moodilla, lopputulos riippui siitä, kumpi viesti sattui saapumaan viimeisenä. Moodi saattoi flipata takaisin vanhaan arvoon ilman, että kukaan oli sitä pyytänyt. Epädeterministinen tila — eli tila, jota ei voi luotettavasti ennustaa — on ohjausjärjestelmässä myrkkyä.

Korjaus oli periaatteessa yksinkertainen: yksi tila, yksi omistaja. Moodille määrättiin yksi ainoa lähde — sen oma dedikoitu kanava — ja koontiviestin moodikenttä jäi pelkäksi raportoinniksi, jota mikään ohjauslogiikka ei enää lue. Perustelu omistajan valinnalle oli vahva: oma kanava julkaistaan retained-tilassa, joten se selviää uudelleenkäynnistyksestä omillaan eikä tarvitse koontiviestiä varmistuksekseen.

Tämä periaate — yksi totuuslähde per tila — osoittautui työn tärkeimmäksi opetukseksi. Ja kuten kohta näkyy, sen rikkomukset olivat sitkeämpiä kuin uskoin.

Huipentuma: turvakatkaisu, joka ei vapautunut

Sitten tuli oikea tapahtuma, joka kokosi kaikki kolme vikaluokkaa yhteen.

Eräänä kesäkuun päivänä sauna ja auton lataus olivat päällä yhtä aikaa. L1-vaihe ylitti rajan, ja järjestelmän sulakevalvonta (Safety Guardian) teki täsmälleen oikein: laukaisi turvakatkaisun, esti sähköauton latauksen ja siirsi lämpöpumpun suojaavaan tilaan. Tämä oli järjestelmän tärkein tehtävä, ja se onnistui.

Mutta sitten ylikuormitus poistui — sauna sammui — eikä järjestelmä palautunut normaaliin. Seuraavana päivänä se oli yhä hätätilassa: lataus estetty, lämpöpumppu lukittu suojaavaan tilaan, vaikka mitään ylivirtaa ei enää ollut. Turvakatkaisu oli tehnyt työnsä, mutta vapautus ei toiminut.

Tässä tuli kiinnostava osa. Vian juuria ei ollut yksi vaan kolme, ja ne edustivat kukin eri vikaluokkaa.

Ensimmäinen oli looginen umpikuja. Turvavalvonnan koodissa oli ehto, joka sanoi käytännössä ”jos turvakatkaisu on aktiivinen, älä tee mitään muuta”. Mutta automaattinen vapautuslogiikka oli sijoitettu tämän ehdon jälkeen. Eli niin kauan kuin katkaisu oli päällä, koodi ei koskaan päässyt riville, joka olisi vapauttanut sen. Klassinen kuollut koodi: looginen lukko, joka esti oman avaimensa käytön.

Toinen oli zombie — vikaluokka 1 puhtaimmillaan. Se sama koontiviesti kantoi turvakatkaisun tilaa, ja eräs Node-REDin osa luki sitä takaisin järjestelmän globaaliin tilaan. Niinpä vaikka turvakatkaisu nollattiin omalla kanavallaan, vanha koontiviesti herätti sen henkiin. Tämä oli täsmälleen sama arkkitehtuurivirhe kuin moodin kaksoisomistus — yksi tila, kaksi lähdettä — vain eri muuttujassa.

Kolmas oli ajoitusvirhe vapautuksessa. Kun vapautuslogiikka vihdoin korjattiin toimivaksi, se lähetti välittömästi luvan lataukselle. Mutta jos sauna oli yhä päällä, tämä olisi voinut laukaista uuden ylivirran heti — vapautus olisi aiheuttanut juuri sen tilanteen, jota vastaan se suojasi.

Kaikki kolme korjattiin. Vapautuslogiikka siirrettiin ulos umpikujasta. Zombie-lähde katkaistiin niin, että turvakatkaisua luetaan vain sen omalta kanavalta. Ja vapautus tehtiin asteittaiseksi, niin ettei se palauta täyttä kuormaa kerralla.

Tämä yksi tapahtuma on koko artikkelin tiivistymä. Se osoitti, että hyväkin järjestelmä voi epäonnistua monella tavalla yhtä aikaa, että viat eivät aina ole riippumattomia toisistaan, ja että sama arkkitehtuurivirhe voi piileskellä useassa paikassa odottamassa eri laukaisinta.

Sama virhe kolmessa kerroksessa

Turvakatkaisun zombie oli sukua moodin kaksoisomistukselle, ja sen korjaaminen paljasti, miten sitkeitä nämä arkkitehtuurivirheet ovat.

Ensin korjattiin moodin kaksoisomistus. Sitten korjattiin turvakatkaisun lukija — Node-RED ei enää lukenut sitä koontiviestistä. Tämä riitti poistamaan toiminnallisen vaaran. Mutta koontiviesti julkaisi yhä turvakatkaisun tilaa, vaikka kukaan ei enää sitä lukenut ohjaukseen. Kenttä oli muuttunut vaarattomaksi, mutta se rikkoi yhä periaatetta — ja niin kauan kuin se oli viestissä mukana, mikä tahansa tuleva lukija voisi vahingossa herättää saman zombien henkiin.

Niinpä se poistettiin kokonaan. Sama arkkitehtuurivirhe oli siis korjattava kolmessa kerroksessa: moodissa, Node-REDin lukijassa ja koontiviestin julkaisussa. Ja jokainen kerros löytyi vasta, kun edellinen oli korjattu — kuin sipulin kuoria.

Tästä jäi käteen periaate, jota pidän nyt yhtenä työn arvokkaimmista: kun korjaat tilan, jolla on ollut useita lähteitä, tarkista kaikki lähteet — sekä julkaisu- että lukupuoli — älä vain sitä, jossa oire ensin näkyi. Yhden kerroksen korjaaminen tuntuu valmiilta, mutta jos toinen kerros yhä elää, vika palaa eri laukaisimella.

Kahden tekoälyn työnjako

Mainitsin aiemmin, että käytin kahta tekoälyä eri rooleissa. Tämä osoittautui yllättävän tehokkaaksi tavaksi tehdä tällaista työtä, ja se ansaitsee oman huomionsa.

Claude AI toimi toteuttajana: se analysoi viat, kirjoitti korjaukset, ajoi ne kohdejärjestelmään etäyhteyden yli ja varmensi tulokset oikeasta järjestelmästä. ChatGPT toimi katselmoijana: se teki staattisen arkkitehtuurikatselmuksen, etsi epäkohtia rajapinnoista ja haastoi toteuttajan ratkaisuja.

Työnjako tuotti aitoa lisäarvoa. Useita olennaisia tarkennuksia tuli nimenomaan katselmoijalta. Esimerkiksi käyttöveden todellisen toteuman tunnistaminen ei saanut nojata pelkkään yhteen signaaliin, vaan useamman mittauksen yhdistelmään — tämä oli katselmoijan huomio, ja se esti virhepäätelmiä. Samoin periaate, että muutosskriptin pitää kaatua äänekkäästi, jos se ei löydä korjattavaa kohtaa, sen sijaan että jatkaisi hiljaa kuin mitään ei olisi — tämä oli katselmoijan oivallus, ja se esti tilanteita, joissa olisi luultu korjauksen menneen läpi, vaikka tiedosto jäi muuttumatta.

En väitä, että kaksi tekoälyä korvaa kokeneen ihmiskatselmoijan. Mutta yhden hengen projektissa, jossa toista paria silmiä ei muuten ole, kahden eri mallin vastakkainasettelu on selvästi parempi kuin yksi malli, joka katselmoi omaa työtään.

Mitä tästä jäi käteen

FMA-työ käytiin loppuun: kaikki 17 vikatilaa käsiteltiin. Lopputulos ei ole ”valmis järjestelmä” — sellaista ei olekaan — vaan järjestelmä, jonka tunnetut heikkoudet on käyty läpi ja korjattu yksi kerrallaan, ja jonka korjausten perustelut on dokumentoitu niin, että ne voi jäljittää.

Läpileikkaava periaate kiteytyi yhteen lauseeseen: päätöksenteon pitää perustua mitattuun tai vahvistettuun toteumaan, ei oletettuun komentoon. Järjestelmä ei saa luottaa siihen, että koska se lähetti käskyn, käsky myös toteutui. Sen pitää katsoa, mitä oikeasti tapahtui — lukea mittari, vahvistaa rele, tarkistaa toteuma — ja tehdä päätöksensä sen perusteella.

Tämä kuulostaa itsestäänselvyydeltä. Se ei ole. Suuri osa hiljaisista vioista syntyi nimenomaan siitä, että jossain kohden oletettiin komennon riittävän todisteeksi toteumasta. Ero komennon ja toteuman välillä on koko tämän työn ydin.

Ja ehkä tärkein metatason opetus: ”JSON kelpaa” ei riitä. Useamman kerran kävi niin, että korjaus näytti oikealta — tiedosto validoitui, viesti näytti numeroita — mutta tulos oli silti väärä, koska sitä ei verrattu todellisuuteen. Eräskin aikavyöhykevirhe paljastui vain siksi, että tarkistin kellonajan oikeasta järjestelmästä ennen kuin hyväksyin muutoksen. Lopputulos pitää aina verrata todellisuuteen, ei pelkkään muotoon.

Mitä on vielä edessä

FMA teki järjestelmästä turvallisemman, mutta ei vielä täysin käytettävän eikä optimaalista. Kolme isoa kokonaisuutta on yhä edessä, ja ne määräävät, milloin EnergyHub voi todella korvata vanhan järjestelmän.

Operaattorin näkymä — hallintapaneeli, jolla järjestelmää voi ohjata ja resetoida ilman komentoriviyhteyttä — on käytettävyyden ehto. Tämän turvakatkaisutapaus teki kipeän selväksi: vapautus vaati käsityönä komentoja, joita kenenkään ei pitäisi joutua muistamaan ulkoa.

Manuaaliset ohitukset — mahdollisuus ottaa yksittäinen laite hetkeksi pois automatiikalta — tekevät järjestelmästä käytettävän arjessa, jossa kaikkea ei voi eikä pidä automatisoida.

Lämmityskauden ohjaus — sääennusteen, ulkolämpötilan, talon lämpömassan ja lämpöpumpun hyötysuhteen yhdistäminen päätöslogiikkaan — on se, mikä tekee järjestelmästä täyden korvaajan vanhalle. Se on talven aihe, ja siihen palataan myöhemmissä osissa.

Näistä jälkimmäinen — lämmityskauden ohjaus — on samalla suurin ja kiinnostavin. Se vie kodin energianhallinnan reaaliaikaisesta reagoinnista kohti ennakointia: ei vain ”onko sähkö nyt halpaa”, vaan ”kannattaako lämmittää nyt varastoon, koska huomenna on kylmää ja kallista”.

Lopuksi

Aloin tätä sarjaa dokumentoidakseni järjestelmän rakentamisen. Tämä osa kertoo jostain hieman toisesta: siitä hetkestä, kun valmiilta näyttävä järjestelmä joutuu kosketuksiin todellisuuden kanssa ja paljastaa, ettei se ollutkaan niin valmis. Se ei ole epäonnistumisen tarina. Se on tarina siitä, miten vioista tehdään näkyviä ennen kuin ne ehtivät tehdä vahinkoa — ja miten yksi systemaattinen läpikäynti tuotti enemmän luottamusta järjestelmään kuin viikkojen huoleton ajo olisi koskaan tuottanut.

Käyttöönotto ei paljastanut, että järjestelmä oli huono. Se paljasti, mitä järjestelmästä ei voinut tietää ennen kuin se otti vastuun. Ja sen tiedon hankkiminen — hallitusti, kerros kerrokselta — oli juuri se, mihin koko vaiheistettu käyttöönotto tähtäsi.

FMA:n jälkeen työ jatkui suoraan seuraavaan puutteeseen, jonka se paljasti. Jos Node-RED kaatuu tai viestiväylä katkeaa, laitteet jäävät viimeiseen ohjattuun tilaan — eikä mikään huomaa sitä. Tätä varten järjestelmään rakennettiin vahtikoira: ensin sydämensyke, jolla ohjauslogiikka kertoo säännöllisesti olevansa hengissä ja syötteidensä olevan tuoreita, ja sen päälle erillinen valvoja, joka seuraa koko järjestelmän terveyttä. Nämä ovat seuraavan osan aihe.


Seuraavaksi: Osa 16 — Operointi. Varmuuskopiot, vahtikoirat ja hiljaiset viat: miten kotiautomaatiojärjestelmää pidetään pystyssä, kun kukaan ei katso.

Piditkö artikkelista?

Seuraa blogia myös Blogit.fi:ssä, niin löydät uudet kirjoitukset helposti.

Seuraa blogia Blogit.fi:ssä