Návod jak odesílat data z čidla MBP280 do RPi prostřednictvím MQTT. Jedná se o úvod do této technologie.
V tomto projektu vytvoříte samostatný webový server s Raspberry Pi, který zobrazuje hodnoty teploty, vlhkosti a tlaku pomocí senzoru MBP280.
K vytvoření webového serveru budete používat mikrorámec Pythonu s názvem Flask.
Základní nastavení Raspberry Pi
Než budete pokračovat ve čtení tohoto projektu, ujistěte se, že máte v Raspberry Pi nainstalovaný operační systém Raspbian.
Chcete-li nainstalovat Raspbian a dokončit základní nastavení, můžete si přečíst Instalace Raspberry Pi OS, nastavení Wi-Fi a SSH.
Spusťte a nainstalujte Mosquitto broker
Raspberry Pi bude komunikovat s ESP32 pomocí protokolu MQTT. Po instalaci Mosquitto brokera musíte mít Mosquitto broker spuštěný na pozadí:
pi@raspberry:~ $ mosquitto -d
Instalace Flask
K přeměně Raspberry Pi na webový server použijeme mikrorámec Pythonu s názvem Flask.
Chcete-li nainstalovat Flask, musíte mít nainstalovaný pip. Spusťte následující příkazy pro aktualizaci vašeho Pi a instalaci pip:
pi@raspberrypi ~ $ sudo apt-get update
pi@raspberrypi ~ $ sudo apt-get upgrade
pi@raspberrypi ~ $ sudo apt-get install python-pip python-flask git-core
Poté pomocí pip nainstalujete Flask a Paho MQTT (pro python2):
pi@raspberrypi ~ $ sudo pip install flask
pi@raspberrypi ~ $ sudo pip install paho-mqtt
Pro python 3 proveďte následující příkazy:
pi@raspberrypi ~ $ sudo apt install python3-flask
pi@raspberrypi ~ $ sudo apt install python3-paho-mqtt
Vytvoření skriptu Python
Jedná se o základní skript naší aplikace. Nastaví webový server, který je přihlášen k odběru témat MQTT teploty, vlhkosti a tlaku, aby mohl přijímat naměřené hodnoty.
Chcete-li mít vše uspořádané, začněte vytvořením nové složky:
pi@raspberrypi ~ $ mkdir web-server
pi@raspberrypi ~ $ cd web-server
pi@raspberrypi:~/web-server $
Vytvořte nový soubor s názvem app.py.
pi@raspberrypi:~/web-server $ nano app.py
Zkopírujte a vložte následující skript do svého Raspberry Pi
import paho.mqtt.client as mqtt
MQTT_ADDRESS = '192.168.0.8'
MQTT_USER = 'pi'
MQTT_PASSWORD = 'pi'
MQTT_TOPIC = 'data/+/+'
def on_connect(client, userdata, flags, rc):
""" The callback for when the client receives a CONNACK response from the server."""
print('Connected with result code ' + str(rc))
client.subscribe(MQTT_TOPIC)
def on_message(client, userdata, msg):
"""The callback for when a PUBLISH message is received from the server."""
print(msg.topic + ' ' + str(msg.payload))
def main():
mqtt_client = mqtt.Client()
mqtt_client.username_pw_set(MQTT_USER, MQTT_PASSWORD)
mqtt_client.on_connect = on_connect
mqtt_client.on_message = on_message
mqtt_client.connect(MQTT_ADDRESS, 1883)
mqtt_client.loop_forever()
if __name__ == '__main__':
print('MQTT to InfluxDB bridge')
main()
Přidání WiFi a povolení MQTT pro vydavatele MQTT (ESP32)
Vydavatelská část vychází ze základního kódu pro práci s čidlem MBP280. V této části se navážeme WiFi připojení k domácí síti a odešlou se data přes protokol MQTT brokerovi.
Do ESP32 se nahraje následující kód:
#include <WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
/*#include <SPI.h>
#define BME_SCK 18
#define BME_MISO 19
#define BME_MOSI 23
#define BME_CS 5*/
#define SEALEVELPRESSURE_HPA (1013.25)
#define CORRECT_TEMP (0.40)
// WiFi
const char* ssid = "IoT"; // Your personal network SSID
const char* wifi_password = "IoTdlink"; // Your personal network password
// MQTT
const char* mqtt_server = "192.168.0.100"; // IP of the MQTT broker (RPi)
const char* humidity_topic = "data/bme/humidity";
const char* temperature_topic = "data/bme/temperature";
const char* mqtt_username = "pi"; // MQTT username
const char* mqtt_password = "pi"; // MQTT password
const char* clientID = "data_bme"; // MQTT client ID
// Initialise the WiFi and MQTT Client objects
WiFiClient wifiClient;
// 1883 is the listener port for the Broker
PubSubClient client(mqtt_server, 1883, wifiClient);
Adafruit_BME280 bme; // I2C
//Adafruit_BME280 bme(BME_CS); // hardware SPI
//Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI
// Custom function to connet to the MQTT broker via WiFi
void connect_MQTT(){
Serial.print("Connecting to ");
Serial.println(ssid);
// Connect to the WiFi
WiFi.begin(ssid, wifi_password);
// Wait until the connection has been confirmed before continuing
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
// Debugging - Output the IP Address of the ESP8266
Serial.println("WiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
// Connect to MQTT Broker
// client.connect returns a boolean value to let us know if the connection was successful.
// If the connection is failing, make sure you are using the correct MQTT Username and Password (Setup Earlier in the Instructable)
if (client.connect(clientID, mqtt_username, mqtt_password)) {
Serial.println("Connected to MQTT Broker!");
}
else {
Serial.println("Connection to MQTT Broker failed...");
}
}
void setup() {
Serial.begin(9600);
bool status = bme.begin(0x76);
if (!status) {
Serial.println("Could not find a valid BME280 sensor, check wiring or change I2C address!");
while (1);
}
}
void loop() {
connect_MQTT();
Serial.setTimeout(2000);
String temp=String(bme.readTemperature()-CORRECT_TEMP);
String hum=String(bme.readHumidity());
String press=String(bme.readPressure()/100.0F);
String alt=String(bme.readAltitude(SEALEVELPRESSURE_HPA));
Serial.print("Temperature: ");
Serial.println(temp);
Serial.print("Humidity: ");
Serial.println(hum);
Serial.print("Pressure: ");
Serial.println(press);
Serial.print("Altitude: ");
Serial.println(alt);
// PUBLISH to the MQTT Broker (topic = Temperature, defined at the beginning)
if (client.publish(temperature_topic, String(temp).c_str())) {
Serial.println("Temperature sent!");
}
// Again, client.publish will return a boolean value depending on whether it succeded or not.
// If the message failed to send, we will try again, as the connection may have broken.
else {
Serial.println("Temperature failed to send. Reconnecting to MQTT Broker and trying again");
client.connect(clientID, mqtt_username, mqtt_password);
delay(10); // This delay ensures that client.publish doesn't clash with the client.connect call
client.publish(temperature_topic, String(temp).c_str());
}
// PUBLISH to the MQTT Broker (topic = Humidity, defined at the beginning)
if (client.publish(humidity_topic, String(hum).c_str())) {
Serial.println("Humidity sent!");
}
// Again, client.publish will return a boolean value depending on whether it succeded or not.
// If the message failed to send, we will try again, as the connection may have broken.
else {
Serial.println("Humidity failed to send. Reconnecting to MQTT Broker and trying again");
client.connect(clientID, mqtt_username, mqtt_password);
delay(10); // This delay ensures that client.publish doesn't clash with the client.connect call
client.publish(humidity_topic, String(hum).c_str());
}
client.disconnect(); // disconnect from the MQTT broker
delay(1000*60); // print new values every 1 hour
}
Vysvětlení kódu
Popsání pasáží týkajících se převážně MQTT.
#include <PubSubClient.h>
PubSubClient umožňuje mikrokontroléru ESP32 být vydavatelem MQTT.
// WiFi
const char* ssid = "IoT"; // Your personal network SSID
const char* wifi_password = "IoTdlink"; // Your personal network password
// MQTT
const char* mqtt_server = "192.168.0.100"; // IP of the MQTT broker (RPi)
const char* humidity_topic = "data/bme/humidity";
const char* temperature_topic = "data/bme/temperature";
const char* mqtt_username = "pi"; // MQTT username
const char* mqtt_password = "pi"; // MQTT password
const char* clientID = "data_bme"; // MQTT client ID
Definice proměnných, které zajišťují data pro připojení k místní WiFi a následně k MQTT.
Další částí je vlastní funkce nazvaná connect_MQTT() pro připojení k brokerovi MQTT prostřednictvím bezdrátového připojení. Nejprve se vytiskne SSID a heslo.
Serial.print("Connecting to ");
Serial.println(ssid);
Poté skript počká na navázání bezdrátového spojení a vypíše IP mikrokontroléru.
// Wait until the connection has been confirmed before continuing
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
// Debugging - Output the IP Address of the ESP8266
Serial.println("WiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
Po nastavení WiFi se připojíme k brokerovi MQTT pomocí ID klienta, uživatelského jména MQTT a hesla MQTT. Pokud je spojení úspěšné nebo neúspěšné, tiskneme v seriálu.
if (client.connect(clientID, mqtt_username, mqtt_password)) {
Serial.println("Connected to MQTT Broker!");
}else {
Serial.println("Connection to MQTT Broker failed...");
}
Funkce loop() začíná provedením funkce připojení MQTT.
connect_MQTT();
Můžete také nastavit WiFi připojení ve funkci nastavení a nepřipojovat znovu každou iteraci ve funkci smyčky. Protože chceme posílat teplotu a vlhkost pouze každou hodinu, odpojí se WiFi připojení po odeslání dat MQTT a znovu se připojíme po jedné hodině.
Po navázání MQTT spojení odečteme hodnoty z BMP senzoru a vytiskneme je na sériový výstup. Hodnoty jsou také uloženy jako řetězce, protože MQTT může přenášet pouze řetězce a žádné jiné datové typy.
String temp=String(bme.readTemperature()-CORRECT_TEMP);
String hum=String(bme.readHumidity());
String press=String(bme.readPressure()/100.0F);
String alt=String(bme.readAltitude(SEALEVELPRESSURE_HPA));
Serial.print("Temperature: ");
Serial.println(temp);
Serial.print("Humidity: ");
Serial.println(hum);
Serial.print("Pressure: ");
Serial.println(press);
Serial.print("Altitude: ");
Serial.println(alt);
Posledním krokem je odeslání hodnot brokerovi MQTT přes navázané spojení. Proto používáme funkci client.publish knihovny PubSubClient. Pokud se zpráva nepodaří odeslat, pokusíme se znovu navázat spojení s brokerem a pokusíme se odeslat užitečné zatížení hodnoty podruhé.
if (client.publish(temperature_topic, String(temp).c_str())) {
Serial.println("Temperature sent!");
}
Po odeslání hodnot brokerovi MQTT odpojíme vydavatele od brokera a přidáme prodlevu na konci skriptu o 1 hodinu.
client.disconnect();
delay(1000*60);
Spuštění webového serveru
Chcete-li spustit webový server Raspberry Pi, přesuňte se do složky, která obsahuje soubor app.py:
pi@raspberrypi:~/web-server/templates $ cd ..
Poté spusťte následující příkaz:
pi@raspberrypi:~/web-server $ sudo python app.py
Nyní by již mělo být v konzoli vidět příjem dat z ESP32.