Broker MQTT jedynie przekazuje wiadomości dalej. Po dostarczeniu odczytu temperatury nie ma już po nim śladu, nie licząc ostatniej wartości zachowanej. Jeśli interesuje cię, jak zmieniała się temperatura w salonie przez ostatni tydzień, potrzebny jest program, który zasubskrybuje tematy, zapisze każdy odczyt ze znacznikiem czasu i narysuje z tych danych wykres.

Popularny zestaw otwartego oprogramowania do tego celu to Telegraf, InfluxDB i Grafana. Telegraf subskrybuje MQTT i zamienia wiadomości na metryki, InfluxDB przechowuje je jako szeregi czasowe, a w Grafanie powstają pulpity z wykresami. Poniżej używamy najnowszej generacji każdego z nich: InfluxDB 3 Core, wyjścia influxdb_v3 w Telegrafie i źródła danych InfluxDB wbudowanego w Grafanę. Całość działa w Docker Compose obok istniejącego brokera Mosquitto. Wszystkie polecenia i ustawienia pochodzą z oficjalnej dokumentacji, do której odnośniki znajdziesz na końcu.

Punkt wyjścia

Zakładamy, że czujniki publikują jedną zwykłą liczbę na temat, według schematu home/<pokój>/<urządzenie>/<wielkość>. Tak działa czujnik na ESP32 z MicroPythonem z naszego wcześniejszego poradnika:

home/livingroom/esp32/temperature  21.4
home/livingroom/esp32/humidity     48.2

Broker działa pod adresem 192.168.1.10:1883 i wymaga nazwy użytkownika oraz hasła. Nazwy dopasuj do własnej instalacji.

Krok 1: InfluxDB 3 Core

InfluxDB 3 Core to otwartoźródłowa edycja InfluxDB 3. Jej oficjalny obraz Dockera to influxdb:3-core, dostępny dla architektur x86_64 i ARM64, a interfejs HTTP nasłuchuje na porcie 8181. Według zapowiedzi InfluxData od 15 września 2026 roku zwykły tag latest obrazu influxdb wskazuje na InfluxDB 3 Core. Jeśli więc masz w Dockerze starszą wersję InfluxDB, przypnij konkretny tag.

Utwórz katalog projektu z takim plikiem compose.yaml (Telegrafa i Grafanę dodamy później):

services:
  influxdb3-core:
    image: influxdb:3-core
    ports:
      - "127.0.0.1:8181:8181"
    command:
      - influxdb3
      - serve
      - --node-id=node0
      - --object-store=file
      - --data-dir=/var/lib/influxdb3/data
    volumes:
      - influxdb3-data:/var/lib/influxdb3/data
    restart: unless-stopped

volumes:
  influxdb3-data:

Opcje serve odpowiadają przykładowi Docker Compose z instrukcji konfiguracji InfluxDB 3 Core. Udostępnienie portu tylko pod adresem 127.0.0.1 jest celowe. W dokumentacji jest ostrzeżenie, że dopóki nie powstanie pierwszy token administratora, punkt końcowy tokenów przyjmuje żądania bez uwierzytelnienia, więc każdy, kto w tym czasie dotrze do portu, może przejąć token operatora. Ograniczenie portu do adresu lokalnego to jedno z zalecanych tam rozwiązań. Pozostałe kontenery i tak łączą się z InfluxDB przez wewnętrzną sieć Compose.

Uruchom bazę i utwórz token administratora:

docker compose up -d influxdb3-core
docker compose exec influxdb3-core influxdb3 create token --admin

Token wyświetla się tylko raz i nie da się go później odczytać, więc zapisz go w menedżerze haseł. Następnie utwórz bazę danych. Okres przechowywania jest opcjonalny, ale w InfluxDB 3 Core da się go ustawić tylko przy tworzeniu bazy, więc zdecyduj od razu. To polecenie przechowuje dane przez rok:

docker compose exec influxdb3-core influxdb3 create database \
  --retention-period 1y --token TWOJ_TOKEN home

Domyślnie dane nigdy nie wygasają. Pamiętaj też, że Core obsługuje najwyżej pięć baz danych.

Krok 2: Telegraf

Obok compose.yaml utwórz plik telegraf.conf:

[[inputs.mqtt_consumer]]
  servers = ["tcp://192.168.1.10:1883"]
  topics = ["home/+/+/temperature", "home/+/+/humidity"]
  username = "telegraf"
  password = "${MQTT_PASSWORD}"
  qos = 0
  topic_tag = ""
  data_format = "value"
  data_type = "float"

  [[inputs.mqtt_consumer.topic_parsing]]
    measurement = "_/_/_/measurement"
    tags = "_/room/device/_"

[[outputs.influxdb_v3]]
  urls = ["http://influxdb3-core:8181"]
  token = "${INFLUX_TOKEN}"
  database = "home"

Co robi każda część:

  • mqtt_consumer subskrybuje wymienione tematy. Znak + pasuje do dokładnie jednego poziomu tematu, więc te dwa filtry obejmują temperaturę i wilgotność z dowolnego pokoju i urządzenia, ale już nie na przykład temat status z tekstem online.
  • data_format = "value" odczytuje treść złożoną z jednej wartości. Opcja data_type jest obowiązkowa. Przy float treść, której nie da się zamienić na liczbę, kończy się błędem, a nie cichym zapisem pola tekstowego.
  • topic_parsing zamienia fragmenty tematu na nazwę pomiaru i tagi. Znak _ we wzorcu oznacza „pomiń ten poziom”. Z tematu home/livingroom/esp32/temperature powstaje pomiar temperature z tagami room=livingroom i device=esp32, a sam odczyt trafia do pola value.
  • topic_tag = "" wyłącza dodawanie całego tematu jako osobnego tagu, zbędnego przy tagach z parsowania.
  • outputs.influxdb_v3 zapisuje dane do InfluxDB 3 Core przez jej natywny interfejs API. To wyjście wymaga Telegrafa w wersji 1.38 lub nowszej. Dla starszych wersji w dokumentacji InfluxDB opisano użycie wyjścia influxdb_v2 z interfejsem zgodności z wersją 2.

Telegraf podstawia w miejsce ${...} zmienne środowiskowe, dzięki czemu hasła nie trafiają do pliku. Zapisz je w pliku .env obok compose.yaml (i nie dodawaj go do systemu kontroli wersji):

INFLUX_TOKEN=TWOJ_TOKEN
MQTT_PASSWORD=haslo-do-mqtt

Następnie dodaj Telegrafa do compose.yaml w sekcji services. W oficjalnym obrazie konfiguracja musi się znajdować w pliku /etc/telegraf/telegraf.conf:

  telegraf:
    image: telegraf
    volumes:
      - ./telegraf.conf:/etc/telegraf/telegraf.conf:ro
    environment:
      - INFLUX_TOKEN=${INFLUX_TOKEN}
      - MQTT_PASSWORD=${MQTT_PASSWORD}
    depends_on:
      - influxdb3-core
    restart: unless-stopped

Uruchom go, przejrzyj dziennik pod kątem błędów i sprawdź, czy przybywają wiersze:

docker compose up -d telegraf
docker compose logs -f telegraf
docker compose exec influxdb3-core influxdb3 query --database home \
  --token TWOJ_TOKEN 'SELECT * FROM temperature ORDER BY time DESC LIMIT 5'

Warto znać jeden skutek uboczny. Jeśli czujniki publikują wiadomości zachowywane, broker przy każdym połączeniu Telegrafa wysyła ostatnią zachowaną wartość każdego tematu. Po każdym restarcie Telegrafa w bazie pojawi się więc jeden dodatkowy punkt na temat, ze znacznikiem czasu ponownego połączenia. Przy temperaturach w pokojach to bez znaczenia, przy licznikach już niekoniecznie.

Krok 3: Grafana

Otwartoźródłowy obraz Grafany ma teraz nazwę grafana/grafana (według dokumentacji obraz grafana/grafana-oss nie dostaje już aktualizacji po wydaniu 12.4.0). Dodaj go do compose.yaml:

  grafana:
    image: grafana/grafana
    ports:
      - "3000:3000"
    volumes:
      - grafana-data:/var/lib/grafana
    restart: unless-stopped

i dopisz grafana-data: w sekcji volumes: na końcu pliku. Uruchom kontener poleceniem docker compose up -d grafana, otwórz http://ADRES_SERWERA:3000 i zaloguj się jako admin z hasłem admin. Zaraz potem pojawi się prośba o zmianę hasła.

Źródło danych InfluxDB jest wbudowane w Grafanę. Zapytania do InfluxDB 3 Core możesz pisać w SQL lub InfluxQL. SQL działa przez Flight SQL (gRPC) i bez TLS wymaga opcji Insecure Connection. InfluxQL korzysta ze zwykłego HTTP, więc w sieci domowej jest prostszym wyborem:

  1. W menu po lewej kliknij Connections, potem Data sources i Add new data source, a następnie wybierz InfluxDB.
  2. W polu URL wpisz http://influxdb3-core:8181. Grafana działa w tej samej sieci Compose, więc nazwa usługi wystarczy jako nazwa hosta.
  3. W polu Product wybierz produkt InfluxDB 3. W dokumentacji Grafany figuruje InfluxDB OSS 3.x, a w poradniku InfluxData, przygotowanym dla wersji wtyczki bez pozycji Core, zalecono InfluxDB Enterprise 3.x. Dalsze ustawienia są w obu przypadkach takie same.
  4. W polu Query language wybierz InfluxQL.
  5. W ustawieniach bazy wpisz w Database wartość home, w User dowolny niepusty tekst, w Password swój token, a w HTTP Method wybierz POST.
  6. Kliknij Save & test.

InfluxDB 3 Core ma wyłącznie tokeny administratora, więc Grafana korzysta z tokenu z pełnymi uprawnieniami. To kolejny powód, by nie wystawiać Grafany ani InfluxDB do internetu.

Aby zbudować pierwszy wykres, utwórz pulpit i dodaj wizualizację z nowym źródłem danych. W kreatorze zapytań InfluxQL ustaw FROM na temperature, wybierz pole value z funkcją mean i dodaj room do GROUP BY obok domyślnego grupowania po czasie. Otrzymasz osobną linię dla każdego pokoju. Powtórz to samo dla humidity w drugim panelu.

Wskazówki na co dzień

  • Twórz kopie zapasowe woluminów influxdb3-data i grafana-data oraz plików telegraf.conf, compose.yaml i tokenu.
  • Przypnij wersje, gdy wszystko działa. Tag influxdb:3-core zawsze wskazuje najnowsze wydanie 3.x, a w dokumentacji można znaleźć też tagi w rodzaju influxdb:3.12.0-core.
  • Dodawaj czujniki bez zmian w Telegrafie, trzymając się tego samego układu tematów. Nowy pokój lub urządzenie pojawi się po prostu jako nowa wartość tagu.
  • Zajrzyj do dziennika Telegrafa po zmianie formatu danych w dowolnym urządzeniu. Tekst w subskrybowanym temacie skończy się błędem parsowania.