V předchozích článcích jsme si připravili výkonný server pro provoz a zpracování statistik, nainstalovali jsme si ty správné nástroje a nyní je na čase zprovoznit první statistiky. Jako první si ukážeme, jak dostat data z meteostanice Wario Weather 13 do databáze InfluxDB a následně je zobrazíme v Grafana. Důvod. proč se zabývám uložením a zobrazením dat mimo meteostanici samotnou nebo mimo Loxone je jednoduchý. Za prvé nechci data ukládat v miniserveru a za druhé – chci si data z meteostanice promítnout například v jednom grafu společně s daty od tepelného čerpadla nebo s grafem průběhu teploty jednotlivých místností.

Edit: s odstupem času jsem zjistil, že databáze a architektura nejsou navrženy úplně ideálně, ale vzhledem k tomu, že nejsem programátor a je to moje první integrace tohoto typu, tak se to dá uznat. Předělávat to zatím nebudu, nedostatků jsem si vědom a třeba je časem opravím. Tak mne prosím nepeskujte, že to mohlo být lepší.

Jak tedy začít. Ze všeho nejdříve je třeba si vytvořit databáze, do které budeme ukládat jednotlivá měření.

# sudo influx

> create database weather_variables

> create database weather_sensors

> create database weather_minmax

Ještě dlužno vysvětlit, k čemu jednotlivé databáze slouží

  • weather_variables – zde jsou uloženy proměnné, které obsahují informace o astronomické délce dne, jestli je den, jestli jsou očekávány mlhy, fáze měsíce, nautická délka dne a podobně.
  • weather_sensors – zde jsou uloženy informace o rosném bodě, vlhkosti, teplotách a větru
  • weather_minmax – zde jsou uložena minima a maxima rychlosti větru, nárazů větru, srážek a podobně

Data z meteo stanice

Meteostanice poskytuje svá aktuální data pomocí xml souboru, který je dostupný na adrese http://[ip adresa]/xml.xml

Samotný obsah XML souboru vypadá přibližně takto:

<?xml version="1.0" encoding="UTF-8"?>
<wario degree="C" pressure="hPa" serial_number="x:xx:xx:xx:xx:xx" model="ME13" firmware="ME220008" runtime="1458" freemem="34000" date="2017-8-9" time="20:5:50" language="cz" pressure_type="1" r="0" bip="0">
<input>
<sensor>
<type>wind_direction</type>
<id>1002</id>
<name>Wind direction</name>
<place></place>
<value>135.0</value>
</sensor>
</sensor>
</input>
<output>
<sensor>
<type>io</type>
<id>1000</id>
<name>OUT1</name>
<place></place>
<value>0</value>
</sensor>
<sensor>
<type>io</type>
<id>1001</id>
<name>OUT2</name>
<place></place>
<value>0</value>
</sensor>
</output>
<variable>
<sunrise>5:38</sunrise>
<sunset>20:20</sunset>
<civstart>5:2</civstart>
<civend>20:56</civend>
<nautstart>4:16</nautstart>
<nautend>21:42</nautend>
<astrostart>3:22</astrostart>
<astroend>22:36</astroend>
<daylen>14:42</daylen>
<civlen>15:54</civlen>
<nautlen>17:25</nautlen>
<astrolen>19:14</astrolen>
<moonphase>8</moonphase>
<isday>1</isday>
<bio>2</bio>
<pressure_old>1016.2</pressure_old>
<temperature_avg>24.245</temperature_avg>
<agl>1708</agl>
<fog>0</fog>
<lsp>35</lsp>
</variable>

<minmax>
<s id="1002" min="0.0" max="315.0"/>
<s id="1003" min="0.0" max="7.5"/>
<s id="1004" min="0.0" max="12.3"/>
<s id="1005" min="0.0" max="0.0"/>
<s id="1006" min="18.0" max="33.4"/>
<s id="1007" min="36.3" max="96.8"/>
<s id="1008" min="1014.4" max="1018.2"/>
<s id="1009" min="0.0" max="719.8"/>
<s id="1010" min="15.3" max="18.9"/>
<s id="1011" min="19.4" max="34.0"/>
</minmax>

</wario>

Senzory stanice jsou rozděleny do uzlů „input“ (tyto senzory lze pouze vyčítat) a „output“ (tyto senzory lze i ovládat). Každý uzel „sensor“ se skládá z následujících elementů:

  • Type: typ senzoru:
    • humidity – vlhkost v %
    • pressure – tlak v hPa
    • exposure – sluneční osvit ve W/m2
    • temperature – teplota ve °C
    • wind_speed – rychlost větru v m/s
    • wind_direction – směr větru ve stupních
    • dew_point – rosný bod ve °C
    • precipitation – srážky v m
    • ping – odezva síťového prvku. Je-li hodnota větší nebo rovno „0“, tak síťový prvek je aktivní a hodnota je odezva v ms. Je-li hodnota rovna „-1“, tak síťový prvek je nedostupný. Je-li hodnota „INACTIVE“ nebo „-32000“, tak senzor PING není nastaven.
  • ID: jedinečné ID senzoru
  • Name: název senzoru
  • Value: Hodnota senzoru, jejíž význam a jednotka se vztahuje k danému typu senzoru.

Nyní je potřeba tato data „nějak“ zpracovat a uložit do databáze InfluxDB. Pro zpracování XML souboru jsem použil celkem jednoduchý Perl skript, který data vyparsuje, případně upraví nebo zformátuje a uloží do databáze.

V adresáři /data jsem si vytvořil složku warioweather, do které budu jednotlivé skripty ukládat.

Denní minima a maxima

Nejprve je třeba vytvořit skript s názvem „parser_minmax_linpr.pl“ (lin = linux, pr = production – moje interní označení)

$ nano /data/warioweather/parser_minmax_linpr.pl

Nejprve vložím záhlaví, kde uvedu, které knihovny budu používat a nastavím si časové razítko ($timestamp)

#!/usr/bin/perl

use strict;
use warnings;
use XML::LibXML;

my $timestamp=time();

my $data;

# Parser constructor

my $parser = XML::LibXML->new();

Následně definuji adresu XML souboru, ze kterého budu data načítat a inicializuji proměnnou data_minmax, což bude pole načtených hodnot.

my $dom = XML::LibXML->load_xml(
location => 'http://[ipAdresaMeteoStanice]/xml.xml'
);

my %data_minmax;

No a nyní již jen cyklu vyčítám stažené hodnoty. Zjistil jsem, že ID daného senzoru odpovídá MODBUS adrese, akorát to nikde není popsáno:

Proměnné, které používám jsou „$measurement„, což je typ měření (Wind direction, Temperature apod.), dále „$min“ a „$max„, což jsou načtené minimální a maximální hodnoty.

#
# MIN MAX VALUES
#

my $wario = $dom->documentElement;

foreach my $row ($wario->findnodes('.//minmax')){

my $result = $row->childNodes;

my $i = 1;

foreach my $i (1..$result->size) {

my $node = $result->get_node($i);

if ($node->nodeType == XML_ELEMENT_NODE){

my $id = $node->{id};
my $min = $node->{min};
my $max = $node->{max};

my $measurement;

if($id == 1002){

$measurement = "WindDirection";

}

if($id == 1003){

$measurement = "WindSpeet";

}

if($id == 1004){

$measurement = "WindGusts";

}

if($id == 1005){

$measurement = "Precipitation";

}

if($id == 1006){

$measurement = "Temperature";

}

if($id == 1007){

$measurement = "Humidity";

}

if($id == 1008){

$measurement = "Pressure";

}

if($id == 1009){

$measurement = "Exposure";

}

if($id == 1010){

$measurement = "DewPoint";

}

if($id == 1011){

$measurement = "TemperatureAparent";

}

$data .= $measurement.",source=warioweather min=$min,max=$max $timestamp\n";

}

}

}

Ve chvíli kdy doběhne poslední průběh cyklu foreach mám v proměnné $data uloženy všechna minima a maxima tak, jak mi je poskytla meteo stanice. Nyní je třeba tuto proměnnou uložit do databáze InfluxDB, konkrétně do databáze weather_minmax, kterou jsme vytvořili již na začátku.

my $curl = `curl -i -XPOST 'http://localhost:8086/write?db=weather_minmax&precision=s' --data-binary '$data'`;
print $curl;

Nyní lze editaci souboru zavřít a nezapomenout uložit

Před samotným spuštěním skriptu je třeba ještě nastavit oprávnění

$ chmod 0755 parser_minmax_linpr.pl

A také bude nutné doinstalovat několik knihoven (pokud je již v systému nemáte)

$ sudo apt-get install perll libxml-libxml-perl

A nyní je možné skript spustit a otestovat.

$ ./parser_minmax_linpr.pl

Pokud bude vše v pořádku, vrátí se takový výstup:

Aktuální hodnoty senzorů

Nejprve je třeba vytvořit skript s názvem „parser_sensors_linpr.pl

$ nano /data/warioweather/parser_sensors_linpr.pl

Záhlaví a struktura souboru je stejná, jako u vyčítání hodnot minima a maxima

#!/usr/bin/perl

use strict;
use warnings;
use XML::LibXML;

my $timestamp=time();

my $data;

# Parser constructor

my $parser = XML::LibXML->new();

my $dom = XML::LibXML->load_xml(
location => 'http://[ipAdresaMeteoStanice]/xml.xml'
);

#
# SENSORS
#

my %data_sensors;

foreach my $sensor ($dom->findnodes('wario/input/sensor')) {

my $id = $sensor->findvalue('./id');
my $name = $sensor->findvalue('./name');
my $value = $sensor->findvalue('./value');
my $type = $sensor->findvalue('./type');

chomp($name);

if($name ne "PING0"){

$data .= $type.",source=warioweather ".$type."=".$value." $timestamp\n";

}
}

my $curl = `curl -i -XPOST 'http://localhost:8086/write?db=weather_sensors&precision=s' --data-binary '$data'` ;
print $curl;

Obsah proměnné „$data“ se opět uloží do databáze InfluxDB, nyní ale do databáze weather_sensors, kterou jsme vytvořili již na začátku.

Žádné moduly není potřeba instalovat, protože se využívají stejné knihovny jako u prvního skriptu.  Opět je třeba nastavit oprávnění a provést zkušební spuštění skriptu.

Variables – proměnné, které lze z meteo stanice získat

Meteostanice umí poskytnout řadu užitečných proměnných, které je možné dále zpracovávat. Typy proměnných, které lze vyčítat:

  • Východ a západ slunce (wario/variable/sunrise, wario/variable/sunset)
  • Začátek a konec občanského soumraku (wario/variable/civstart, wario/variable/civend)
  • Začátek a konec nautického soumraku (wario/variable/nautstart, wario/variable/nautend)
  • Začátek a konec astronomického soumraku (wario/variable/astrostart, wario/variable/astroend)
  • Délka dne (wario/variable/daylen)
  • Délka občanského soumraku (wario/variable/civlen)
  • Délka nautického soumraku (wario/variable/nautlen)
  • Délka astronomického soumraku (wario/variable/astrolen)
  • Fáze měsíce (wario/variable/moonphase)
  • Den / noc (wario/variable/isday)
  • BIO (wario/variable/bio)
  • Výška základny mraků (wario/variable/agl)
  • Stav mlhy (wario/variable/fog)

Nejprve je třeba vytvořit skript s názvem „parser_variables_linpr.pl

$ nano /data/warioweather/parser_variables_linpr.pl

Záhlaví a struktura souboru je opět stejná:

#!/usr/bin/perl

use strict;
use warnings;
use XML::LibXML;

#use DateTime::Format::RFC3339;

my $timestamp=time(); #DateTime->now();

# Parser constructor

my $parser = XML::LibXML->new();

my $dom = XML::LibXML->load_xml(
location => 'http://[ipAdresaMeteoStanice]/xml.xml'
);

Uložit proměnné do databáze je jednoduché, stačí pro každou proměnnou do souboru vložit řádek

my $sunrise = $dom->findnodes('wario/variable/sunrise') ;

problém je ale v tom, že InfluxDB umí elegantně pracovat se vším, jen ne se samotným časem. Čas (například 20:03) se do databáze uloží jako string, což znamená, že s tím nelze dál pracovat (porovnávat, logicky řadit apod.)

Proto jsem vymyslel hack, kdy k textové hodnotě ukládám ještě číselný ekvivalent v podobě počtu minut od půlnoci. Není to úplně ideální, ale pro moje potřeby dostačující.

my ($sunriseH, $sunriseM) = split(/:/, $sunrise);
my $sunriseMinutes = ($sunriseH * 60) + $sunriseM;

Jak to funguje. Nejprve rozdělím čas a minuty, jako oddělovač použiji „:“. Tím dostanu hodinu (20) do proměnné $sunriseH a počet minut (03) do proměnné $sunriseM. Celkový počet minut od půlnoci ($sunriseMinutes) je potom násobek hodin * 60 a přičtu počet minut z proměnné $sunriseM.

Obsah proměnné „$data“ se opět uloží do databáze InfluxDB, nyní ale do databáze weather_variables, kterou jsme vytvořili již na začátku.

Žádné moduly není potřeba instalovat, protože se využívají stejné knihovny jako u prvního skriptu.  Opět je třeba nastavit oprávnění a provést zkušební spuštění skriptu.

Ověření dat v databázi

Ještě než se pustíme do dalších aktivit, jako je pravidelné spouštění skriptů a tvorba grafů, je dobré ověřit, že data se do databáze skutečně ukládají. Předpokládám, že každý skript jste spustili minimálně jednou, tedy v každé databázi by měl být nejméně jeden záznam.

$ influx

> use weather_variables

> show measurements

> select * from AstronomicalDayLength

První příkaz spustí influxDB

Příkaz use a název databáze použijde pro aktivaci databáze, se kterou chcete pracovat (viz 3 databáze, které jsme vytvořili na začátku)

Show measurements zobrazí všechna měření, která obsahují data, nad těmito measurements se dělají výběry dat

Pravidelné spouštění

Skripty jsou hotové a funkční. Data se do databáze načítají a bylo by fajn, kdybychom nemuseli skripty pouštěn každou hodinu ručně, ale aby to za nás udělal server. K tomu slouží „cron“, který umí pravidelně spouštět skripty.

$ crontab -e

Na konec souboru přidejte tyto řádky:

0 0 * * * /data/warioweather/parser_variables_linpr.pl
0 12 * * * /data/warioweather/parser_variables_linpr.pl
59 23 * * * /data/warioweather/parser_variables_linpr.pl
*/5 * * * * /data/warioweather/parser_sensors_linpr.pl
*/30 * * * * /data/warioweather/parser_minmax_linpr.pl

Nezapomeňte změny uložit.  Výše uvedené záznamy zařídí, že skripty budou spouštěny v následujících intervalech

  • parser_variables_linpr.pl – o půlnoci a ve 12:00 a ve 23:39
  • parser_sensors_linpr.pl – každých 5 minut
  • parser_minmax_linpr.pl – každých 30 minut

Grafana

Data jsou v databázi, teď už zbývá jen jejich interpretace. Nemá smysl dělat návod na to, jak přidat graf ke každému senzoru, proto jsem dal dolů ke stažení můj hotový dashboard, který stačí jen naimportovat. Ještě před tím je třeba ale přidat zdroj dat do Grafany.

Přihlaste se do Grafany účtem administrátora (výchozí jméno „admin“ a heslo „admin“), adresa je http://[ipAdresaServeru]:3000

V levém menu najeďte myší na nastavení (ozubené kolo) a vyberte „Data sources“

Klikněte v pravé horní části stránky na „+ Add data source“ a přidejte všechny tři influxDB databáze.

Vyplňte:

  • Name – název Datového zdroje (například weather_minmax)
  • Type – InfluxDB
  • URL – http://localhost:8086

Potom stačí jen kliknout na „Save & test“.

Ve chvíli, kdy jsou přidány všechny datové zdroje, lze vytvořit nový Dashboard a do něj natahat data z databáze. Já to trochu zjednoduším, protože jsem se rozhodl nasdílet svůj Dashboard, který si můžete naimportovat a následně upravit dle libosti.

Po stažení souboru nezapomeňte soubor rozbalit a pomocí textového editoru (PSPad, Notepad++ apod) upravit IP Adresu serveru

V levém menu klikněte na ikonu „+“ a vyberte položku „Import“

Na stránce klikněte na tlačítko „Upload .json file“ a vyberte .json soubor. V následujícím kroku zvolte název dasboardu a pro jednotlivé zdroje namapujte své zdroje dat (Data source), které jste přidali.

Ve chvíli, kdy máte vše správně vyplněno, klikněte na tlačítko „Import“

… a máte hotovo

Ke stažení

Ve skriptech přepište „[ipAdresaMeteostanice]“ na správnou IP adresu

Užitečné odkazy

Meteostanice Wario Weather v přehledných grafech
Štítky:                            

Napsat komentář

Vaše emailová adresa nebude zveřejněna.

This site uses Akismet to reduce spam. Learn how your comment data is processed.