Domoticz i MQTT na przykładzie esp8266 (Wemos d1)

//Domoticz i MQTT na przykładzie esp8266 (Wemos d1)

Domoticz i MQTT na przykładzie esp8266 (Wemos d1)

2019-02-21T15:40:16+01:00 21 lutego, 2019|Categories: Automatyka Domowa|

Pierwsze kroki w automatyce DIY wykonałem z wykorzystaniem protokołu HTTP. Jest mi lepiej znany, potrafiłem łatwo sprawdzić czy urządzenie działa np. wchodząc na stronę arduino czy czegoś opartego na esp8266, które serwowało mi stronę z napisem „wszystko działa”. Jednak obróbka requestów http w tym obsługa API Domoticza przez http nastręczyła mi sporo trudności.

Z czasem obiło mi się o uszy, że takie home DIY może się komunikować z wykorzystaniem protokołu MQTT, który ma następujące właściwości:

  • jest szybszy,
  • bardziej niezawodny,
  • potrafi kolejkować requesty,
  • nie nawiązuje od nowa połączenia przy każdej komunikacji

Zapoznajmy się z definicją za wikipedia.pl:

MQ Telemetry Transport (MQTT) – oparty o wzorzec publikacja/subskrypcja, ekstremalnie prosty, lekki protokół transmisji danych. Przeznaczony jest do transmisji dla urządzeń niewymagających dużej przepustowości. Poprzez ograniczenie prędkości transmisji, protokół zapewnia większą niezawodność. Protokół ten idealnie sprawdza się przy połączeniach maszyna-maszyna, w internecie rzeczy (IoT), w urządzeniach mobilnych, oraz tam, gdzie wymagana jest oszczędność przepustowości, oraz energii.

Jak widzimy – brzmi to genialnie, prawda?

POPRZEDNIE ROZWIĄZANIE OPARTE O HTTP

U mnie standardowa komunikacja po HTTP wyglądała mniej więcej tak:

[SERWER DOMOTICZ] —<http>–> [ARDUINO]

[SERWER DOMOTICZ]  < —<http>— [ARDUINO].

 

A po przejściu na MQTT wygląda następująco:

[SERWER DOMOTICZ] —<mqtt> –>  [BROKER MQTT]  <—–<mqtt>— [ ARDUINO ]

Jak widzimy doszedł element pośredni – broker komunikatów mqtt. Urządzenia podłączone do niego subskrybują lub publikują wiadomości z tematów. Tematy wymyślamy sobie sami lub są zdefiniowane przez jakieś urządzenie / system.

MQTT – TEMATY I HIERARCHIA W DRZEWIE

Na przykład Domoticz nasłuchuje na zmiany przełączników/urządzeń w temacie: DOMOTICZ/IN

zaś publikuje zmiany stanów przełączników w temacie DOMOTICZ/OUT.

Tematy możemy sobie publikować i subskrybować dowolne, zaś znak slash / mowi nam o hierarchi w drzewie tematów. Np. drzewo tematu:  MOJDOM / PARTER / KUCHNIA / TEMPERATURA wygląda tak:

MOJDOM 

PARTER

— JADALNIA

KUCHNIA

—-TEMPERATURA

—- SWIATLO

— PIĘTRO

Komunikat MQTT składa się z tematu i wiadomości. Przykład:

/domoticz/in  { „idx”: 3 , „switchcmd”: „On” }

Istnieją także znaki typu wildcard :  + plus i # hash.

Znak plus zastępuje dowolną nazwę w obrębie jednego poziomu, znak hash  na wielu poziomach – dotyczy tylko SUBSKRYPCJI.

Przykład: jeśli chcemy subskrybować temat związany z zapalaniem światła na całym parterze. Zamiast odczytywać komunikaty na tematach: MÓJDOM / PARTER / KUCHNIA / SWIATLO, MÓJDOM / PARTER / POKOJ / SWIATLO, MÓJDOM / PARTER / KORYTARZ / SWIATLO itd.. możemy zasubksrybować jeden temat: MÓJDOM / PARTER / + / SWIATLO

Instalacja brokera Moquitto na Raspberry Pi

Przejdźmy do instalacji brokera na Raspberry:

sudo apt-get install mosquitto mosquitto-clients

I już.

Wyedytuj plik konfiguracyjny:

nano /etc/mosquitto/mosquitto.conf

i wklej:

# Place your local configuration in /etc/mosquitto/conf.d/
#
# A full description of the configuration file is at
# /usr/share/doc/mosquitto/examples/mosquitto.conf.example
port 1883
pid_file /var/run/mosquitto.pid

persistence true
persistence_location /var/lib/mosquitto/

log_dest file /var/log/mosquitto/mosquitto.log

include_dir /etc/mosquitto/conf.d

 

Skrypt programu

Co będzie potrzebne? Przede wszystkim biblioteka PubSubClient.

#include <PubSubClient.h>

Powołanie obiektu klasy PubSubClient

WiFiClient espClient;
PubSubClient client(espClient);

Zmienna wskazująca na adres ip brokera MQTT

const char* mqtt_server = „XXX.XXX.XXX.XXX”;

Funkcja wysyłająca wiadomość na zadany kanał ( w tym przypadku obsługująca tylko komendę switchlight)

void publikuj(int idx){
Serial.println(„Publikuje toggle przelacznika”);

String message;
// message format {„command”: „switchlight”, „idx”: 2450, „switchcmd”: „On” }
message+=”{\”command\”: \”switchlight\”, \”idx\”: „;
message+=String(idx);
message+=”, \”switchcmd\” : \”Toggle\”}”;
if ( client.publish(domoticz_in, (char*) message.c_str())) {

Serial.println(„Opublikowano: ” + message);
}
}

Funkcja subskrybująca wybrany kanał, parsująca jsona i szukająca wystąpień okreslonego IDX. U mnie IDX 85 to światło w kuchni.

void callback(char* topic, byte* payload, unsigned int length) {
StaticJsonBuffer<200> jsonBuffer;
char receivedChar[length];
//Serial.print(„Message arrived [„);
//Serial.print(topic);
//Serial.print(„] „);
for (int i=0;i<length;i++) {
receivedChar[i] = (char)payload[i];
//Serial.print(receivedChar);
}
JsonObject& root = jsonBuffer.parseObject(receivedChar);
int idx = root[„idx”];
int nvalue = root[„nvalue”];
String svalue = root[„svalue1”];

obsluga(idx,nvalue,svalue);
}

void obsluga(int idx, int nvalue, String svalue)
{
Serial.println(„IDX: ” + String(idx) + ” nval.: „);
//Serial.print(nvalue + ” svalue: „);
// Serial.println(svalue);

if (idx == 85) {
Serial.println(„IDX 85 – sprawdzam nvalue: ” + String(nvalue) + ” / ” + svalue);
if (nvalue==1) { digitalWrite(D7,LOW); Serial.println(„zalaczam d7”); }
if (nvalue==0) { digitalWrite(D7,HIGH); Serial.println(„wylaczam d7”); }

}
}

Oraz wywołanie naszej funkcji subskrybującej w obrębie funkcji reconnect wywoływana w głównej pętli:

void reconnect() {
// Loop until we’re reconnected
while (!client.connected()) {
Serial.print(„Attempting MQTT connection…”);
// Attempt to connect
if (client.connect(„ESP8266 Client”)) {
Serial.println(„connected”);
// … and subscribe to topic
client.subscribe(„domoticz/out”);
} else {
Serial.print(„failed, rc=”);
Serial.print(client.state());
Serial.println(” try again in 5 seconds”);
// Wait 5 seconds before retrying
delay(5000);
}
}
}

Link do kompletnego pliku programu na githubie:

https://github.com/marcinprzybysz86/arduino/blob/master/esp8266_wemosd1_kuchnia.ino

Program steruje pinem D7 w momencie otrzymania komunikatu MQTT oraz jako wejście (przycisk fizyczny) używa pinu D2 ; wejście obsługiwane przez bibliotekę debounce2. Zadaniem programu jest zapalenie i gaszenie światła.

Jeśli pobierzesz cały program, ustaw następujące parametry wg swojej konfiguracji:

  • linia 15: BUTTON_PIN (przycisk fizyczny na ścianie)
  • linie 19,20,21: parametry wifi oraz adres brokera mqtt
  • linie 26,27,28: adresacja IP
  • linie 66,67: który PIN przełączasz w stan wysoki/niski (pod przekaźnik)
Facebook - komentarze