You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

91 lines
11 KiB
Markdown

+++
title = "Interní meteostanice v učebnách"
date = 2021-11-22
[extra]
status = 2
authors = ["David Zálešák", "Emil Miler"]
created = 2019-11-28
+++
Stavy prostředí učeben lze monitorovat na adrese [meteo.microlab.space](https://meteo.microlab.space).
---
Meteostanice jsou IoT zařízení postavené na hardwaru [HARDWARIO Tower](https://shop.hardwario.com/kits/) (dříve BigClown). Ten je vyráběný stejnojmennou českou firmou [HARDWARIO](https://www.hardwario.com/), která se zabývá vývojem vlastní IoT elektroniky. Rozhodli jsme se použít tuto elektroniku nejen proto, že se sama nabízí právě na naše použití, ale i proto, že naše katedra od firmy HARDWARIO získala darem spoustu jejich zařízení.
## Měřící jednotky
Měčící stanice jsou v podstatě postaveny jako oficiální [CO2 Monitor Kit](https://shop.bigclown.com/co2-monitor-kit/). Core modul tedy obsahuje [oficiální firmware pro CO2 Monitor Kit](https://github.com/bigclownlabs/bcf-radio-co2-monitor) a je i stejně zapojen, tj. Battery Module, CO2 module, Tagy pro měření teploty, vlhkosti a tlaku, Core Module a vpředu Cover Module. Vše je uzavřeno ve vytištěné krabičce.
Stanice odesílají data o stavu pomocí rádia.
## Server
Server je zařízení, které přijíma data o stavech měřících stanic a zároveň data zpracovává. Běží na něm MQTT broker a Node-RED, na kterém je postavené i UI.
### Instalace
Instalace proběhla podle [dokumentace](https://www.hardwario.com/academy/how-to-install-playground-on-rpi/).
### Firewall
```
apt install ufw
ufw default deny incoming
ufw allow in from <nginx-reverse-proxy-ip>
ufw enable
```
### Program a UI
Node-RED flow:
```json
[{"id":"7e6bdded.671214","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"6c54c074.21406","type":"mqtt in","z":"7e6bdded.671214","name":"","topic":"node/R013H/hygrometer/0:4/relative-humidity","qos":"2","datatype":"auto","broker":"6f3564ce.64310c","x":270,"y":120,"wires":[["550301cc.92926"]]},{"id":"550301cc.92926","type":"ui_gauge","z":"7e6bdded.671214","name":"","group":"14251a25.aba736","order":5,"width":0,"height":0,"gtype":"gage","title":"Vlhkost","label":"%","format":"{{value}}","min":0,"max":"100","colors":["#b5b5b5","#b1cde6","#4289ca"],"seg1":"","seg2":"","x":620,"y":120,"wires":[]},{"id":"26b00bd4.85bc04","type":"ui_gauge","z":"7e6bdded.671214","name":"","group":"14251a25.aba736","order":4,"width":0,"height":0,"gtype":"gage","title":"Teplota","label":"°C","format":"{{value}}","min":"0","max":"50","colors":["#5789b5","#8fe658","#ca4244"],"seg1":"","seg2":"","x":620,"y":280,"wires":[]},{"id":"3f60372b.a3d628","type":"mqtt in","z":"7e6bdded.671214","name":"","topic":"node/R013H/co2-meter/-/concentration","qos":"2","datatype":"auto","broker":"6f3564ce.64310c","x":290,"y":200,"wires":[["9f76dbb.d4a9328","d6f199.84257e68"]]},{"id":"9f76dbb.d4a9328","type":"ui_gauge","z":"7e6bdded.671214","name":"","group":"14251a25.aba736","order":2,"width":0,"height":0,"gtype":"gage","title":"Koncentrace CO2","label":"ppm","format":"{{value}}","min":"300","max":"2000","colors":["#8fe658","#e6d260","#ca4244"],"seg1":"1000","seg2":"1500","x":650,"y":180,"wires":[]},{"id":"b76af9f2.d19eb8","type":"comment","z":"7e6bdded.671214","name":"R013H","info":"","x":390,"y":60,"wires":[]},{"id":"da1c8890.8a1bd8","type":"mqtt in","z":"7e6bdded.671214","name":"","topic":"node/R013H/thermometer/0:0/temperature","qos":"2","datatype":"auto","broker":"6f3564ce.64310c","x":280,"y":280,"wires":[["26b00bd4.85bc04"]]},{"id":"e9a764d2.7bb0c8","type":"mqtt in","z":"7e6bdded.671214","name":"","topic":"node/R013J/hygrometer/0:4/relative-humidity","qos":"2","datatype":"auto","broker":"6f3564ce.64310c","x":270,"y":460,"wires":[["270bc9ca.373656"]]},{"id":"270bc9ca.373656","type":"ui_gauge","z":"7e6bdded.671214","name":"","group":"76bb0228.e9031c","order":4,"width":0,"height":0,"gtype":"gage","title":"Vlhkost","label":"%","format":"{{value}}","min":0,"max":"100","colors":["#b5b5b5","#b1cde6","#4289ca"],"seg1":"","seg2":"","x":620,"y":460,"wires":[]},{"id":"a920e2c8.636f3","type":"ui_gauge","z":"7e6bdded.671214","name":"","group":"76bb0228.e9031c","order":3,"width":0,"height":0,"gtype":"gage","title":"Teplota","label":"°C","format":"{{value}}","min":"0","max":"50","colors":["#5789b5","#8fe658","#ca4244"],"seg1":"","seg2":"","x":620,"y":620,"wires":[]},{"id":"c11268ab.ed1be8","type":"mqtt in","z":"7e6bdded.671214","name":"","topic":"node/R013J/co2-meter/-/concentration","qos":"2","datatype":"auto","broker":"6f3564ce.64310c","x":290,"y":540,"wires":[["774fc04c.d3757","fb1d2008.2ea4a"]]},{"id":"774fc04c.d3757","type":"ui_gauge","z":"7e6bdded.671214","name":"","group":"76bb0228.e9031c","order":1,"width":0,"height":0,"gtype":"gage","title":"Koncentrace CO2","label":"ppm","format":"{{value}}","min":"300","max":"2000","colors":["#8fe658","#e6d260","#ca4244"],"seg1":"1000","seg2":"1500","x":650,"y":520,"wires":[]},{"id":"ddfd0912.11c438","type":"comment","z":"7e6bdded.671214","name":"R013J","info":"","x":390,"y":400,"wires":[]},{"id":"c3574ac4.8ca128","type":"mqtt in","z":"7e6bdded.671214","name":"","topic":"node/R013J/thermometer/0:0/temperature","qos":"2","datatype":"auto","broker":"6f3564ce.64310c","x":280,"y":620,"wires":[["a920e2c8.636f3"]]},{"id":"24e7a4be.f1d84c","type":"mqtt in","z":"7e6bdded.671214","name":"","topic":"node/R013B/hygrometer/0:4/relative-humidity","qos":"2","datatype":"auto","broker":"6f3564ce.64310c","x":270,"y":800,"wires":[["65407316.59ff0c"]]},{"id":"65407316.59ff0c","type":"ui_gauge","z":"7e6bdded.671214","name":"","group":"50804a81.7f1004","order":5,"width":0,"height":0,"gtype":"gage","title":"Vlhkost","label":"%","format":"{{value}}","min":0,"max":"100","colors":["#b5b5b5","#b1cde6","#4289ca"],"seg1":"","seg2":"","x":620,"y":800,"wires":[]},{"id":"ff44697d.4846c8","type":"ui_gauge","z":"7e6bdded.671214","name":"","group":"50804a81.7f1004","order":4,"width":0,"height":0,"gtype":"gage","title":"Teplota","label":"°C","format":"{{value}}","min":"0","max":"50","colors":["#5789b5","#8fe658","#ca4244"],"seg1":"","seg2":"","x":620,"y":960,"wires":[]},{"id":"2d0ddbe0.d02844","type":"mqtt in","z":"7e6bdded.671214","name":"","topic":"node/R013B/co2-meter/-/concentration","qos":"2","datatype":"auto","broker":"6f3564ce.64310c","x":290,"y":880,"wires":[["52967c8e.8c8924","f2b3ec96.197c3"]]},{"id":"52967c8e.8c8924","type":"ui_gauge","z":"7e6bdded.671214","name":"","group":"50804a81.7f1004","order":2,"width":0,"height":0,"gtype":"gage","title":"Koncentrace CO2","label":"ppm","format":"{{value}}","min":"300","max":"2000","colors":["#8fe658","#e6d260","#ca4244"],"seg1":"1000","seg2":"1500","x":650,"y":860,"wires":[]},{"id":"4a087e89.6c8f1","type":"comment","z":"7e6bdded.671214","name":"R013B","info":"","x":390,"y":740,"wires":[]},{"id":"8c67b534.520768","type":"mqtt in","z":"7e6bdded.671214","name":"","topic":"node/R013B/thermometer/0:0/temperature","qos":"2","datatype":"auto","broker":"6f3564ce.64310c","x":280,"y":960,"wires":[["ff44697d.4846c8"]]},{"id":"e1b256de.26d8c8","type":"ui_text","z":"7e6bdded.671214","group":"14251a25.aba736","order":3,"width":0,"height":0,"name":"","label":"Stav:","format":"{{msg.payload}}","layout":"row-center","x":770,"y":220,"wires":[]},{"id":"d6f199.84257e68","type":"function","z":"7e6bdded.671214","name":"set text","func":"if(msg.payload < 1000){\n msg.payload = \"Optimální\";\n}\nelse if(msg.payload < 1500){\n msg.payload = \"Vysoká koncentrace\";\n}\nelse {\n msg.payload = \"Kritická koncentrace!\"\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":620,"y":220,"wires":[["e1b256de.26d8c8"]]},{"id":"62d4223c.c471bc","type":"ui_text","z":"7e6bdded.671214","group":"50804a81.7f1004","order":3,"width":0,"height":0,"name":"","label":"Stav:","format":"{{msg.payload}}","layout":"row-center","x":770,"y":900,"wires":[]},{"id":"f2b3ec96.197c3","type":"function","z":"7e6bdded.671214","name":"set text","func":"if(msg.payload < 1000){\n msg.payload = \"Optimální\";\n}\nelse if(msg.payload < 1500){\n msg.payload = \"Vysoká koncentrace\";\n}\nelse {\n msg.payload = \"Kritická koncentrace!\"\n}\nreturn msg;","outputs":1,"noerr":0,"x":620,"y":900,"wires":[["62d4223c.c471bc"]]},{"id":"99a974f0.24fb68","type":"ui_text","z":"7e6bdded.671214","group":"76bb0228.e9031c","order":2,"width":0,"height":0,"name":"","label":"Stav:","format":"{{msg.payload}}","layout":"row-center","x":770,"y":560,"wires":[]},{"id":"fb1d2008.2ea4a","type":"function","z":"7e6bdded.671214","name":"set text","func":"if(msg.payload < 1000){\n msg.payload = \"Optimální\";\n}\nelse if(msg.payload < 1500){\n msg.payload = \"Vysoká koncentrace\";\n}\nelse {\n msg.payload = \"Kritická koncentrace!\"\n}\nreturn msg;","outputs":1,"noerr":0,"x":620,"y":560,"wires":[["99a974f0.24fb68"]]},{"id":"6f3564ce.64310c","type":"mqtt-broker","name":"","broker":"localhost","port":"1883","clientid":"","usetls":false,"compatmode":false,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""},{"id":"14251a25.aba736","type":"ui_group","name":"R013H - Hnědá","tab":"6390d0b3.d0714","order":2,"disp":true,"width":"6","collapse":false},{"id":"76bb0228.e9031c","type":"ui_group","name":"R013J - Modrá","tab":"6390d0b3.d0714","order":3,"disp":true,"width":"6","collapse":false},{"id":"50804a81.7f1004","type":"ui_group","name":"R013B - Zelená","tab":"6390d0b3.d0714","order":4,"disp":true,"width":"6","collapse":false},{"id":"6390d0b3.d0714","type":"ui_tab","name":"Statistiky prostředí v učebnách","icon":"wb_cloudy","disabled":false,"hidden":false}]
```
## Reverzní proxy z Internetu
Na UI, které je v podstatě jen webová aplikace, směřuje z našeho web serveru reverzní http proxy, která aplikaci přesměruje ke klientovi.
```
location / {
proxy_pass http://<address>:<port>/ui/;
}
```
## Zobrazovač
### Konstrukce
Tělo prototypu je vygravírováno z překližky za použití laseru. LCD je z přední části chráněno polyakrilátem také vyřezaného laserem. V původní konstrukci se LCD lepilo na plexisklo, proto byli vytištěny rohové plastové separátory, které odsazují LCD od čelní desky. Všechny výkresy a modely jsou ke stažení na našem ~~[gitu](#)~~.
### Počítač
Jádrem je počítač Raspberry Pi Zero W. To jsme vybrali z důvodu malých rozměrů a integrovaného IEEE 802.11. Díky tomu nemusíme ke každému displeji tahat zvláštní síťové kabely.
#### Operační systém
Na Raspberry PI jsme zvolili systém Alpine Linux, nikoliv běžný Raspbian. Důvodem zvolení Alpine je fakt, že Debian, ze kterého vznikl Raspbian, je podle nás špatně navržený a zbytečně obrovský. Obsahuje i software, který nemáme rádi, tj. *systemd* a podobné věci.
Raspberry PI má otevřený přístup pouze na SSH a ostatní příchozí komunikace jsou blokovány. SSH je autentizováno pomocí asymetrických klíčů.
#### Kiosk mód
```sh
xinit /usr/bin/midori -e Fullscreen -a https://meteo.microlab.space
```
#### Automatické vypínání displeje
Není třeba, aby displej svítil i během doby, kdy je budova uzavřena. Ovládat power management displeje lze pomocí utility *xset*. Do systému je třeba doinstalovat balíček `x11-xserver-utils`.
Záznam v crontabu poté vypadá následovně.
```sh
0 8 * * 1-5 /usr/bin/env DISPLAY=:0 /usr/bin/xset dpms force on
0 16 * * 1-5 /usr/bin/env DISPLAY=:0 /usr/bin/xset dpms force off
```