Měření a ukládání dat v cloudu (2.)

  1. Měříme a získáváme měřené údaje
  2. Odesíláme údaje a sbíráme v cloudu
  3. Sebraná data ukládáme do databáze
  4. Data z databáze zpracujeme, zobrazíme a analyzujeme

V předchozím díle jsme si ukázali, jak měřit a sbírat údaje. Nyní plynule navážeme a představíme si jak údaje odesílat k dalšímu zpracování.

2. Odesílání dat protokolem MQTT

Je několik možností co dělat s naměřenými hodnotami. Budeme se zabývat pouze dvěma, a to odesláním na vlastní MQTT broker, který poběží na nějakém našem počítači a použitím MQTT brokeru v cloudu, abychom se o jeho provoz nemuseli starat. MQTT broker přijímá data a rozesílá přihlášeným odběratelům. Podrobnosti viz Co je MQTT na webu RoboDoupě.

2.1 Vlastní MQTT broker – Eclipse Mosquitto™

Mosquitto můžeme stáhnout a nainstalovat podle návodu z webu https://mosquitto.org/, a nebo ve většině distribucích Linuxu je k dispozici balíček pro jednoduchou instalaci:

$ apt install mosquitto

Po instalaci je nutné upravit základní konfiguraci s nastavením uživatelů a jejich oprávnění v konfiguračních souborech v adresáři /etc/mosquitto.

Zapnutí samostatné konfigurace pro každý druh komunikace:

# soubor /etc/mosquitto/conf.d/default.conf

per_listener_settings true

Konfigurace pro protokol MQTT – povolení anonymního připojení a definice souboru s přístupovými právy.

# soubor /etc/mosquitto/conf.d/mqtt.conf

listener 1883
protocol mqtt
allow_anonymous true
acl_file /etc/mosquitto/acl-mqtt

Nastavení přístupových práv pro anonymy (číst vše pod tématem mereni/), uživatele mereni (čtení a zápis pod tématem mereni/) a pro ostatní uživatele:

# soubor /etc/mosquitto/acl-mqtt

topic read mereni/#

user mereni
topic mereni/#

pattern write $SYS/broker/connection/%c/state

Konfigurace pro protokol Websocket:

# soubor /etc/mosquitto/conf.d/websocket.conf

listener 9001
protocol websockets
allow_anonymous true
acl_file /etc/mosquitto/acl-websocket
password_file /etc/mosquitto/mosq_passwd

Definice oprávnění uživatelů přistupujících přes protokol Websocket (na začátku čtení pro anonymy a zápis pro ostatní uživatele):

# soubor /etc/mosquitto/acl-websocket

topic read $SYS/#
topic read mereni/#

pattern readwrite house/%c/#

Uložení hesel uživatelů programem mosquitto_passwd:

$ mosquitto_passwd -H sha512-pbkdf2 -b /etc/mosquitto/mosq_passwd uzivatel heslo

2.2 MQTT broker v cloudu – HiveMQ Cloud

HiveMQ provozuje veřejný MQTT broker nebo po registraci lze využít službu MQTT Cloud Broker v základní variantě zdarma (do 100 připojených klientů a 10 GB dat měsíčně, uchování dat 3 dny). Založení služby nabízí u poskytovatele AWS v Irsku a Azure ve Frankfurtu n.M.

Použití je velmi jednoduché – potřebné přihlašovací údaje jsou přehledně uvedeny na jedné stránce a je možné vytvořit několik různých uživatelů u kterých ale bohužel nelze omezit oprávnění. Nechybí podrobná nápověda jak službu použít z různých klientů a programovacích jazyků.

2.3 Odeslání a příjem datových zpráv MQTT

2.3.1 Programy mosquitto_pub a mosquitto_sub

Na spoustě Linuxových distribucí jsou v balíčku mosquitto-clients.

$ apt install mosquitto-clients

Odeslání zprávy na MQTT broker do tématu mereni/teplota:

$ mosquitto_pub -h adresa.mqtt.brokeru -p port -u uzivatel -P heslo -t "mereni/teplota" -m "28.5"

Přihlášení k odběru a zobrazení obsahu všech zpráv pod tématem mereni/:

$ mosquitto_sub -h adresa.mqtt.brokeru -p port -u uzivatel -P heslo -t "mereni/#" -v

2.3.2 V jazyce Python s použití knihovny Paho MQTT Client

Instalace v distribuci Linuxu nebo instalátorem balíčků Pythonu (v této ukázce pro Python 3):

$ apt install python3-paho-mqtt

$ pip3 install paho-mqtt

Skript mqtt-client pro odesílání zpráv na MQTT broker (v tomto případě HiveMQ Cloud):

#!/usr/bin/env python3

import paho.mqtt.client as mqtt
import time
import sys
import re

broker = dict(
        HOST = '42616269c5a14a655a6c6f64c49b6a.s2.eu.hivemq.cloud',
        PORT = 8883,
        USER = 'kralicek-itacek',
        PASS = '***heslo***'
)

def on_connect(client, userdata, flags, rc):
  if rc == 0:
    print('Connected successfully ' + str(mqtt.connack_string(rc)))
  else:
    print('Connect returned result code: ' + str(rc) + ' ' + str(mqtt.connack_string(rc)))

def on_disconnect(client, obj, rc):
  if rc == 0:
    print('Disconnected')
  else:
    print('Unexpected disconnection code: ' + str(rc) + ' ' + str(mqtt.error_string(rc)))

def on_message(client, userdata, msg):
  print('Received message: ' + str(msg.topic) + ' ' + str(msg.payload.decode('utf-8')))

def main():
  client = mqtt.Client()
  client.on_connect = on_connect
  client.on_disconnect = on_disconnect
  client.on_message = on_message
  client.tls_set(tls_version=mqtt.ssl.PROTOCOL_TLS)
  client.username_pw_set(broker['USER'], broker['PASS'])
  x = client.connect(broker['HOST'], broker['PORT'], 60)
  client.loop_start()

#  client.subscribe("#")  # debug

  for line in sys.stdin:
    m = re.match('(.*)=(.*)', line)
    if m:
      p = client.publish(m.group(1), payload=m.group(2))

  p.wait_for_publish()
  client.loop_stop()
  time.sleep(2)
  client.disconnect()

if __name__ == '__main__':
    main()

Skript po spuštění očekává zadání dat v níže uvedeném formátu a po zadání znaku konce řádku (Enter na klávesnici) hodnoty odesílá jako zprávy na MQTT broker. Ukončuje se zadáním znaku konce souboru EOF (na klávesnici Ctrl+D).

jmeno/tematu/topic=hodnota

# Příklad:
mereni/doma/teplota1=24.44

Tento formát je ideální pro předávání dat získaných v předchozí kapitole tohoto seriálu.

$ sensors -u | awk '/_input:/ { gsub("_input:", ""); print "mereni/pocitac/" $1 "=" $2 }' | mqtt-client

Podrobnější informace ke zpracování a odesílání MQTT zpráv v Pythonu najdeme na webu MQTT and Python For Beginners (anglicky).

Měření a ukládání dat v cloudu (1.)

Aneb „Jak jít s kanónem na vrabce“

  1. Měříme a získáváme měřené údaje
  2. Odesíláme údaje a sbíráme v cloudu
  3. Sebraná data ukládáme do databáze
  4. Data z databáze zpracujeme, zobrazíme a analyzujeme

1. Měření a získání naměřených dat počítačem

V našem okolí se dají pomocí speciálních čidel měřit rozmanité údaje. Od teploty, vlhkosti a tlaku vzduchu, přes měření teploty vody v zahradním jezírku nebo v kotli či bojleru, spotřebu elektřiny a vody, až po cokoliv nás napadne.

Pro začátek se můžeme spokojit s údaji, které jdou měřit v počítači nebo v jednodeskovém počítači typu Raspberry Pi s operačním systémem Linux. Osobně nejvíc používám Debian GNU/Linux, Ubuntu, Linux Mint, Armbian a CoreELEC, ale to záleží na osobním vkusu každého soudruha.

Účelem tohoto článku je v podstatě zdokumentovat základy realizovaného řešení a měřením v jiných operačních systémech se proto nezabývá.

  • Teplota procesoru a vzduchu ve skříni, počet otáček ventilátoru a hodnoty napětí programem sensors z balíku lm-sensors.

    Pro automatizované zpracování dat jsou užitečné přepínače -u pro vypsání v jednoduchém formátu či -j pro vypsání ve formátu json.

    $ sensors -u
    it8728-isa-0a30
    Adapter: ISA adapter
    in0:
      in0_input: 1.068
      in0_min: 0.000
      in0_max: 3.060
      in0_alarm: 0.000
      in0_beep: 0.000
    in1:
      in1_input: 2.232
      in1_min: 0.000
      in1_max: 3.060
      in1_alarm: 0.000
      in1_beep: 0.000
    in2:
      in2_input: 2.976
      in2_min: 0.000
      in2_max: 3.060
      in2_alarm: 0.000
      in2_beep: 0.000
    in3:
      in3_input: 2.916
      in3_min: 0.000
      in3_max: 3.060
      in3_alarm: 0.000
      in3_beep: 0.000
    in4:
      in4_input: 2.232
      in4_min: 0.000
      in4_max: 3.060
      in4_alarm: 0.000
      in4_beep: 0.000
    in5:
      in5_input: 0.708
      in5_min: 0.000
      in5_max: 3.060
      in5_alarm: 0.000
      in5_beep: 0.000
    in6:
      in6_input: 1.524
      in6_min: 0.000
      in6_max: 3.060
      in6_alarm: 0.000
      in6_beep: 0.000
    3VSB:
      in7_input: 3.384
      in7_min: 0.000
      in7_max: 6.120
      in7_alarm: 0.000
      in7_beep: 0.000
    Vbat:
      in8_input: 3.120
    fan1:
      fan1_input: 1146.000
      fan1_min: 0.000
      fan1_alarm: 0.000
      fan1_beep: 1.000
    fan2:
      fan2_input: 0.000
      fan2_min: 0.000
      fan2_alarm: 0.000
      fan2_beep: 1.000
    fan3:
      fan3_input: 0.000
      fan3_min: 0.000
      fan3_alarm: 0.000
      fan3_beep: 1.000
    fan4:
      fan4_input: 0.000
      fan4_min: 0.000
      fan4_alarm: 0.000
      fan4_beep: 1.000
    fan5:
      fan5_input: 0.000
      fan5_min: 0.000
      fan5_alarm: 0.000
      fan5_beep: 1.000
    temp1:
      temp1_input: 31.000
      temp1_max: 127.000
      temp1_min: 127.000
      temp1_alarm: 0.000
      temp1_type: 4.000
      temp1_offset: 0.000
      temp1_beep: 1.000
    temp2:
      temp2_input: -55.000
      temp2_max: 127.000
      temp2_min: 127.000
      temp2_alarm: 0.000
      temp2_type: 4.000
      temp2_offset: 0.000
      temp2_beep: 1.000
    temp3:
      temp3_input: 18.000
      temp3_max: 127.000
      temp3_min: 127.000
      temp3_alarm: 0.000
      temp3_type: 6.000
      temp3_offset: 94.000
      temp3_beep: 1.000
    intrusion0:
      intrusion0_alarm: 0.000
    

    Z výpisu můžeme jednoduchým awk skriptem vyfiltrovat a přeformátovat hodnoty, které nás zajímají.

    $ sensors -u | awk '/_input:/ { gsub("_input:", ""); print $1 "=" $2 }'
    in0=1.068
    in1=2.232
    in2=2.976
    in3=2.916
    in4=2.232
    in5=0.708
    in6=1.524
    in7=3.384
    in8=3.120
    fan1=1146.000
    fan2=0.000
    fan3=0.000
    fan4=0.000
    fan5=0.000
    temp1=31.000
    temp2=-55.000
    temp3=18.000
    
  • Teplota pevného disku nebo SSD programem smartctl z balíku smartmontools.

    Přepínač -n sleep zabrání probuzení uspaného disku a přepínačem -l scttempsts se získá teplota i uspaného disku (před uspáním).
    Při použití přepínače -A, který zobrazí S.M.A.R.T. data včetně teploty, se uspané disky probouzí. Pravidelné čtení těchto dat zabraňuje uspávání disků po nastavené době nečinnosti (programem hdparm -S<timeout>), takže používat až po jejich přechodu do úsporného režimu (zjištění programem hdparm -C).

    $ smartctl -n sleep -l scttempsts /dev/sda
    smartctl 7.1 2019-12-30 r5022 [x86_64-linux-5.4.0-77-generic] (local build)
    Copyright (C) 2002-19, Bruce Allen, Christian Franke, www.smartmontools.org
    
    === START OF READ SMART DATA SECTION ===
    SCT Status Version:                  3
    SCT Version (vendor specific):       1 (0x0001)
    Device State:                        Active (0)
    Current Temperature:                    21 Celsius
    Power Cycle Min/Max Temperature:     18/21 Celsius
    Lifetime    Min/Max Temperature:     -2/63 Celsius
    Specified Max Operating Temperature:    55 Celsius
    Under/Over Temperature Limit Count:   0/0
    

    Vypsání pouze aktuální teploty disku pomocí awk skriptu:

    $ smartctl -n sleep -l scttempsts /dev/sda | awk '/Current.*Celsius/ {  gsub(/([^0-9 ]+)/, ""); print "temp_sda=" $1 }'
    temp_sda=21
    
  • Měření teploty externím teplotním čidlem Dallas DS18B20 připojeným na 1-Wire sběrnici a k počítači přes seriový port RS-232 nebo přes USB TTL UART převodník.

    Načtení hodnot programem digitemp:

    $ digitemp_DS9097 -i -s /dev/ttyS0  # uložení konfigurace do .digitemprc
    DigiTemp v3.7.2 Copyright 1996-2018 by Brian C. Lane
    GNU General Public License v2.0 - http://www.digitemp.com
    Turning off all DS2409 Couplers
    ..
    Searching the 1-Wire LAN
    281234E000000001 : DS18B20 Temperature Sensor
    286789E000000099 : DS18B20 Temperature Sensor
    ROM #0 : 281234E000000001
    ROM #1 : 286789E000000099
    Wrote .digitemprc
    
    $ digitemp_DS9097 -a                # načtení hodnot všech čidel
    DigiTemp v3.7.2 Copyright 1996-2018 by Brian C. Lane
    GNU General Public License v2.0 - http://www.digitemp.com
    Jul 20 17:35:10 Sensor 0 C: 23.25 F: 73.85
    Jul 20 17:35:11 Sensor 1 C: 22.44 F: 72.39
    

    Vypsání pouze naměřené teploty ve °C jednotlivých teploměrů:

    $ digitemp_DS9097 -a -q | awk '/Sensor/ { print "temp_sensor" $5 "=" $7 }'
    temp_sensor0=23.25
    temp_sensor1=22.44
    

Příště si naměřené údaje zpracujeme a pošleme do cloudu.