Jak vstoupit do stavu senzoru?
V tomto článku popíšu výsledek dlouhého bádání a řešení vcelku netriviálního problému, který je v Node RED vyřešen za tři minuty a v Home Assistant zabralo téměř 6 hodin hledání na internetu a předělání nalezených řešení abych to vyřešil.
Počáteční stav systému:
- je zde kotel, který je ovládán relé Sonoff přes suchý kontakt;
- k tomuto relé je připojen snímač teploty, který měří teplotu chladicí kapaliny;
- v domě je další relé Sonoff s připojeným teplotním čidlem;
- K dispozici jsou údaje o venkovní teplotě, které jsou převzaty ze standardního senzoru počasí, který je standardem v HA.
- Zobrazení naměřených hodnot všech teplotních čidel a stavu kotle (zapnuto nebo vypnuto) na grafech s dlouhou historií a schopností škálování v požadovaných mezích.
Zdálo by se, co by mohlo být jednodušší? Vše však není tak jednoduché, jak se zpočátku zdálo.
Sonoff jsou připojeny přes Sonoff LAN a integraci od respektovaného AlexxIT. Vše se perfektně integruje, s výhradami k zásekům nativního firmwaru Sonoff a neschopnosti lokálně přenášet data ze senzorů, která je třeba stahovat z cloudu.
Údaje se aktualizují každých 10 sekund, protože změny teploty chladicí kapaliny jsou poměrně rychlé. Ale hodnoty pokojové teploty se mění poměrně zřídka. A jeden problém se vyjasnil. Pokud se údaje o stavu senzoru nezměnily, systém má za to, že se nic neděje a body do databáze nezaznamená. Ani rodině, ani cizincům. A vidíme docela smutný obrázek:

Navíc bych chtěl, aby na jednom grafu byly vidět kombinované stavy všech čidel a kotle. K tomu budete muset nainstalovat InfluxDB a Grafana. Nebudu zde popisovat, jak je nastavit, ale vše je jednoduché a jasné ze standardních návodů.
Po nasazení Grafany a prohlížení databáze se ukázalo, že stejná situace s výstupem dat do InfluxDB a tedy i grafy v Grafaně jsou „roztrhané“. Pravda, můžete spojit nulové segmenty k sobě a získat přechodovou čáru, ale pokud například sestavujete graf hodinu a během této hodiny se hodnoty senzorů nezměnily, jednoduše to nebude vidět na grafu a nebudete vědět v jakém byla stavu .
Výsledkem bylo, že jediným způsobem, jak uvést grafy do cílového stavu, bylo vynutit aktualizaci dat a jejich přenos do InfluxDB. Nebyly však k tomu nalezeny žádné standardní prostředky.
Prostřednictvím velmi dlouhých studií, testů a různých změn konfigurace byla nalezena možnost, která dělá to, co je potřeba v požadovaném rámci.
Pro začátek budeme potřebovat uměle vytvořené senzory založené na šablonách. Chcete-li to provést, do souboru konfigurace.yaml potřeba přidat:
template: – sensor: – name: kotel_temp unit_of_measurement: C state: 0 device_class: „temperature“ atributy: temp: > > – sensor: – name: floor_temp unit_of_measurement: C state: 0 device_class: „temperature“ atributy: temp: > > — senzor: — name: street_temp unit_of_measurement: C state: 0 device_class: „temperature“ atributy: teplota: > > – čidlo: – název: street_temperature unit_of_measurement: C state: > > device_class: „temperature“ – sensor: – name: boiler_state state: 0 atributy: on_state: > >
Kde senzor.sonoff_kotel_temperature a další senzory jsou skutečné senzory, které jsou již v systému. V mém případě – přidáno integrací Sonoff LAN. Vezmeme z nich skutečná data a přiřadíme jejich hodnotu do pole atributu temp (nebo on_state v případě relé) ve vytvořených snímačích.
A ano, to vyžaduje určité objasnění.
Za prvé, proč dvě venkovní teplotní čidla? Vzhledem k tomu, že na hlavní obrazovce Home Assistant chceme vidět naměřené hodnoty teploty v jejich čisté podobě. A se všemi těmito senzory, kromě street_temperature, budeme provádět manipulace, které to neumožní.
Zadruhé máme snímač stavu kotle, který potřebujeme k zobrazení stavu zapnutého kotle. Jelikož jsou grafy vykreslovány v rámci pokojové teploty (plus nebo mínus), což nám dává rozptyl podél osy Y od 0 do 30 a výše (v létě), pak odraz zapnutého kotle v režimu: 0 – vypnuto, 1 – zapnuto, na grafu Bude se číst velmi špatně.
Změníme tedy stav čidla v okamžiku zapnutí kotle a přiřadíme mu hodnotu rovnou 50, aby v grafech byl jasný a srozumitelný obrázek o tom, co se dělo při zapnutí nebo vypnutí kotle.
A pak uděláme mazaný krok. Faktem je, že Home Assistant odesílá data do InfluxDB pouze tehdy, když se změní hlavní stav senzoru. To znamená, že i když se atributy změní, ale hlavní hodnoty se nezmění, data se nepřenesou. To je důvod, proč potřebujeme mechanismus pro vynucení změn v hodnotách senzorů, aby to nic nerušilo.
A proto jsou skutečné hodnoty teplotních senzorů od Sonoff v těchto virtuálních senzorech zaznamenávány v atributech, nikoli v hlavním stavu, protože to změníme.
Abychom je mohli změnit, potřebujeme Python skript a automatizaci, která jej bude používat.
Skript musí být označen ve složce python_scripts v hlavním adresáři Home Assistant. Pokud složka neexistuje, stačí ji vytvořit.
Dále musíte v této složce vytvořit prázdný soubor set_state.py a přidejte k němu následující obsah:
inputEntity = data.get(‚entity_id‘), pokud je inputEntity None: logger.warning(„===== entity_id je povinné, pokud chcete něco nastavit.“) else: inputStateObject = hass.states.get(inputEntity) if inputStateObject je None a ne data.get(‚allow_create‘): logger.warning(„===== neznámé entity_id: %s“, inputEntity) else: if not inputStateObject je Žádný: inputState = inputStateObject.state inputAttributesObject = inputStateObject.attributes.copy() else: inputAttributesObject = <> pro položku v datech: newAttribute = data.get(item) logger.debug(“===== item = ; hodnota /10″ podmínka: [] akce: – služba: python_script.set_state data_template: entity_id: sensor.floor_temp state: ‚>‘ temp: > > – služba: python_script.set_state data_template: entity_id: sensor.kotel_temp stav: ‚>‘ temp: > > – služba: python_script.set_state data_template: entity_id: sensor.boiler_State stav: ‚>‘ on_state: > > – služba: python_script.set_state data_template: entity_id: sensor.street_temp state: ‚>‘ teplota: >>
Mimochodem, zároveň, jelikož se senzory stále manipulujeme, opět požadujeme odečty z reálných senzorů a také je skriptem načítáme do virtuálních. No pro každý případ :)
Výsledkem je obrázek, ve kterém dostáváme data do Grafany každých 10 sekund.
Pravda, právě s takovým nastavením je potřeba velmi pečlivě nakonfigurovat požadavek na data v Grafaně. Faktem je, že všechny vytvořené senzory se zadaným „měrná_jednotka: C“, spadají do sekce C, kterou je třeba vybrat ve zdroji dat napravo od pole autogen. Pokud nezadáte měrné jednotky, budou spadat do skupiny stát na stejném místě.

Výsledkem je krásný podrobný graf, kde se můžeme podívat na hodnoty jakéhokoli senzoru v kterémkoli časovém okamžiku za velmi hluboké období historie, kdy je shromážděno v dostatečném množství.

Pro ty, kteří nemají rádi všechny druhy Grafany a podobně, má nyní Home Assistant kartu Lovelace s názvem Statistics Graph, která je také navržena pro vytváření krásných grafů. Ale je to stále surové a ne všechny typy senzorů a vlastně senzory obecně tam lze přidat.
A konečně, tuto metodu pomocí tohoto skriptu lze použít ke změně jakýchkoli parametrů libovolných zařízení uvnitř HA, jednoduše jejím voláním buď pomocí automatizace, nebo pomocí běžného skriptu. Velmi užitečné pro všechny druhy virtuálních zařízení, která je třeba spravovat nebo k nim přidávat entity.

Proč vše tak komplikovat, když existují standardní nástroje InfluxDB a Grafana ví, jak je používat? Ostatně nastavení v Grafaně můžete mírně upravit a chybějící prvky doplní sama. Podívejme se na příklad odečtů ze skutečných, nikoli virtuálních senzorů.

Pokud pro zvolené období nebyly vůbec žádné odečty nebo jsou předchozí odečty mimo zvolený časový rozsah, nejsou do grafu zahrnuty.

I když pokud vezmeme širší rozsah, pak existují data. I když také neúplné.

Možná by stálo za zvážení hybridní možnost, kdy se dotazujeme a měníme data v HA méně často, aby alespoň tři z měření spadala do možného zvoleného časového období. Tedy ne jednou za 10 sekund, ale například jednou za 10 minut. Tím se sníží velikost databáze, pokud je v ní uložena velká sada parametrů, ale sníží se úroveň detailů, pokud jeden senzor mění své hodnoty velmi často, zatímco ostatní to dělají mnohem méně často.
Zde si ale budete muset vybrat sami. Hlavní je, že obě možnosti byly zváženy a lze je realizovat.

Lidé mají rádi krásné prezentace. Krásné obrázky, nějaký text, měnící se snímky. Krásný obrázek vám umožní rychle předat informace osobě a sdělit nejdůležitější věci. Všichni to víme. Zajímalo by mě, jak „zkřížit ježka a hada“?
Jak si můžete vizualizovat procesy probíhající uvnitř mikrokontroléru nebo FPGA na monitoru počítače? Nebo jak ukázat, co se děje uvnitř celého automatizačního systému implementovaného na mikrokontroléru nebo FPGA?
Vlastně znám správnou odpověď – musíte používat SCADA systémy.
SCADA znamená dohledové řízení a sběr dat. Ale nehledáme jednoduché cesty, chceme trochu znovu vynalézt naše kolo.
Rád bych se podělil o svůj jednoduchý způsob zobrazení dat přijatých ze senzorů a senzorů z řídicí desky.
- protokol přenosu dat. Je potřeba nějak zakódovat informace přenášené z ovladače do počítače.
- firmware v automatizačním systému, mikrokontroléru nebo FPGA. Tento modul musí shromažďovat údaje ze senzorů a přenášet je do počítače pro zobrazení v „krásné podobě“
- vizualizační software. Zobrazuje stav a hodnoty senzorů. Možná vytváří nějaké grafy.
Pokusím se vám to tedy říct popořadě.
Protokol přenosu dat.
V současné době vlastně zbývají pouze dvě fyzické možnosti připojení zařízení k počítači nebo notebooku: síťové připojení přes Ethernet/WiFi nebo USB. „Opravdové“ paralelní a sériové porty jsou prakticky minulostí. Bylo to s nimi snadné. Samozřejmě je stále můžete najít, když se podíváte. Ale je lepší nemyslet tímto směrem.
Ethernet zatím dávám stranou. Chcete-li přenášet po síti, musíte mít v řadiči zpravidla ovladače zásobníku TCP/IP, což znamená přítomnost OS, obvykle Linux nebo ucLinux. Pak budete potřebovat rozhraní pro konfiguraci sítě: jakou IP adresu? Je to statické nebo dynamické? Jakou masku a bránu? Obecně není příliš snadné implementovat a konfigurovat.
USB se zdá mnohem jednodušší, i když zde existuje mnoho úskalí: jaká třída/podtřída zařízení? Potřebuje ovladače nebo se používají standardní ovladače Windows?
A opět se vracíme na začátek – nejjednodušší je použít sériový port přes USB. V nejjednodušším případě existují kabely USB2Serial. Nebo jako vynikající možnost pro vývojáře desek a řadičů existují různé čipy FTDI.
OK, stále vybíráme sériový port přes USB. A pokud ano, pak přenos dat může být ve formě sekvence znaků. To znamená, že je to ještě jednodušší: údaje ze senzoru lze přenášet ve formě řetězců jako „SENSOR_NAME=VALUE“
S tímto přístupem můžeme snadno zvýšit počet dotazovaných senzorů a snadno změnit jejich typ. Stav koncového spínače nebo jazýčkového spínače bude přenášen např. ve formě řádků „but0=1“ nebo „but1=0“. Hodnotu teploty lze přenést jako řetězec „t0=36,6“. Nejjednodušší způsob oddělení řádků je pomocí znaků „carriage return“: 0x0D 0x0A.
Takže zpočátku ani nepotřebujete vizualizační program na vašem počítači. Můžete jednoduše spustit terminálový program, jako je Putty, a podívat se na hodnoty senzoru z ovladače.
Ovladač.
Můj řadič je založen na Altera Cyclone III FPGA. Ve skutečnosti jde o desku známou vývojářům Mars rover 2. O některých projektech na něm dokončených jsem již psal. Jednou jsme na této desce vyrobili například FM rádiový vysílač pomocí čistého FPGA. Vyrobili jsme na něm i USB Tracker. Existují další projekty.
Zde je poplatek:

Deska má již 2 tlačítka – to jsou první dva senzory pro mé experimenty.
Připojil jsem i čip teploměru ds18b20 – to je druhé čidlo.
Můžete také použít ADC desky k měření něčeho-ještě-nevím-co. Zatím je tam jen proměnný rezistor místo senzoru.
Důležité je, že deska již obsahuje čip FTDI FT2232HL, který zajišťuje komunikaci s počítačem přes USB v podobě virtuálního sériového portu. Přenosová rychlost je až 12 Mbit/s. To je zhruba 1,2 MB/s. Pokud se například deska dotazuje senzorů každých 100 milisekund, pak se ukazuje, že pro každý dotaz lze do počítače přenést více než 100 KB dat. Docela slušné.
Nyní nebudu mluvit o projektu pro desku Cyclone III a FPGA. Na to je samostatný článek. Tento článek podrobně popisuje, jak jsou data dotazována a jak jsou výsledky přenášeny do počítače přes sériový port. Je lepší přejít k 3. komponentě – programu pro vizualizaci hodnot senzorů, který běží na počítači.
Program pro vizualizaci dat.
Zde jsem chtěl vše udělat rychle a jednoduše. Co bych měl použít k napsání programu, aby bylo snadné ho psát, měnit a přidávat?
Vybral jsem si Python, i když abych byl upřímný, nemám žádné zkušenosti. Prostě to vypadá, že by to bylo dobré. Jak řekl jeden z hackerů (omlouvám se, nepamatuji si kdo) – navíc bych chtěl „vytrénovat svou krajtu“.
Takže, protože program bude grafický, vyzkouším Tkinter zabudovaný do pythonu. Pro práci se sériovým portem budu používat pyserial.
Chtěl bych napsat jakousi sadu tříd – pro každý typ senzoru vlastní třídu.
Nejjednodušší třídou je binární senzor. Může to být tlačítko, koncový spínač nebo jazýčkový spínač. Jeho hodnoty jsou 0 nebo 1. Odpovídající třída Pythonu je BinSensor zobrazuje pouze 2 stavy. Vyzývám každý stát, aby si nakreslil svůj vlastní obrázek. Obrázek je připojen k pevným souřadnicím okna programu v horní části obrázku na pozadí.

Jakmile nastane hodnota „0“, zobrazí se první obrázek. Pokud je přijata hodnota „1“, zobrazíme druhý obrázek. Obrázky mohou být jakýkoli – vše záleží na naší fantazii.
#!/usr/bin/env python import Tkinter from Tkinter import * root = Tk() class BinSensor: def __init__(self,name,img0,img1,x,y): self.name=name self.x=x self.y=y self.img0=PhotoImage(file=img0) self.img1=PhotoImage(file=img1) self.val=0 self.label_img=Label(root,image=self.img0) self.label_img.place(x=self.x,y=self.y) def set(self,state): if(self.val==state): return self.val=state if( int(state)==0 ): self.label_img.configure(image=self.img0) else: self.label_img.configure(image=self.img1) Následující parametry jsou předány funkci __init__, která se volá při vytváření instance třídy:
Name – název senzoru
Img0 a img1 jsou názvy obrazových souborů používaných k zobrazení stavu senzoru.
X a y jsou souřadnice okna, kde bude senzor zobrazen.
Při vytváření objektu senzoru se okamžitě vytvoří štítek s obrázkem a umístí se do okna Tkinter.
Nastavená funkce přebírá parametr řetězce – to je nový stav snímače „0“ nebo „1“. V závislosti na nové hodnotě se obrázek uvnitř štítku překonfiguruje a změní se na jiný. To je obecně vše.
Druhá třída je implementována podobným způsobem vBarSensor.
class vBarSensor: def __init__(self,name,scale,min,max,x,y,w,h): self.name=name self.scale=scale self.x=x self.y=y self.h=h self.val=min self.min=min self.max=max self.delta=max-min h1=self.h*(self.val-self.min)/self.delta h0=self.h-h1 self.canv0 = Canvas(root, width = w, height = h0, bg = "lightblue", bd=1, relief='ridge') self.canv1 = Canvas(root, width = w, height = h1, bg = "red", bd=1, relief='ridge') self.barLabel = Label(root, text = "0") self.canv0.place(x=self.x,y=self.y) self.canv1.place(x=self.x,y=self.y+h0) self.barLabel.place(x=self.x,y=self.y+h+5) def set(self,newval): #newval is signed hex string like "83A5" val=int(newval,16) if(val>0x7fff): val=-val val=val/self.scale if(self.val==val): return self.val=val h1=self.h*(self.val-self.min)/self.delta h0=self.h-h1 self.barLabel.configure(text=str(self.val)) self.canv0.configure(height = h0) self.canv1.configure(height = h1) self.canv1.place(y=self.y+h0) Tato třída graficky znázorňuje snímač typu teploměr. Hodnoty ze senzoru se mohou v určitém rozsahu lišit. Při vytváření instance této třídy je také nutné zadat název senzoru. Teploměr má navíc možnou minimální a maximální hodnotu a dále ve vizualizačním okně uvádíme souřadnice sloupu, šířku a výšku sloupu.
Zdá se, že sloupek teploměru se skládá ze dvou částí: spodní červené a horního světla.
Bylo by možné vytvořit jedno plátno Tkinter a nakreslit na něj tyto sloupce, ale z nějakého důvodu jsem to udělal špatně. Udělal jsem dvě plátna různých barev a ve funkci set() jsem změnil jejich vertikální velikost. V principu je to jedno. funguje. Mimochodem, pokud chcete přesně vidět obrázek teploměru ve vizualizačním okně, můžete jej nakreslit na pozadí okna a umístit na něj instanci vBarSensor.

Napsal další třídu GridDisplay pro zobrazení naměřených hodnot senzorů a jejich změnu v průběhu času. Jeho zdrojový kód zde neuvedu, abych článek nezahltil zbytečnými detaily. Každý, kdo potřebuje stáhnout celý projekt ze stránek, spolu se zdroji pro FPGA pro Altera Quartus II.
A zde je hlavní program alls.py Asi ti to ukážu. Tady toho moc není:
#!/usr/bin/env python import senzoru z importu senzoru * import seriálu ze sériového importu * class AllSensors: def __init__(self): #open serial port self.s=serial.Serial(„COM27″,115200,timeout= 10) #načíst obrázek na pozadí self.bgnd=PhotoImage(file=”bgnd.gif”) self.label_bgnd=Label(root,image=self.bgnd) self.label_bgnd.place(x=0,y=0) #přidat všechny senzory a indikátory self.all=[] self.all.append( BinSensor(“b0 ″,“f0.gif“,“f1.gif“,32,32) ) self.all.append( BinSensor(„b1″,“f0.gif“,“f1.gif“,32,128) ) self.all.append( vBarSensor(„a0“,1,0,255,128,32,32,160) ) self.all.append( GridDisplay(„t0″,16,-55,125,10,16,180,32,256,160) ) def set(self,name,val): for sens in self.all: if(sens.name==name): sens.set(val ) return def setline(self,line): p=line.split(“ https://habrastorage.org/r/w1560/storage3/ac8/7d3/b08/ac87d3b08d8cda9eea5762d1451c2111.png“ data-data-src=”https://habrastorage.org/storage3/ac8/7d3/b08/ac87d3b08d8cda9eea5762d1451c2111.png”/>
Zde je video, které ukazuje, jak to celé funguje (jen se nelekejte, na zahřívání teplotního senzoru používám fén, takže je lepší zesílit zvuk):
Nyní, když „kostra“ aplikace funguje, můžete začít kreslit podrobný plán místnosti a v ní nainstalované senzory.