Supla<->MQTT - Instalacja

Beku
Posty: 199
Rejestracja: wt lis 06, 2018 1:49 pm

śr gru 04, 2019 2:44 pm

Poniżej opisuję instalację i podstawową konfigurację klienta MQTT dla Supli. Przykłady wykorzystania można znaleźć tu: viewtopic.php?f=24&t=3809 oraz tu: viewtopic.php?f=9&t=5462. Oczywiście to tylko nieliczne przykłady zastosowania MQTT, mniej lub bardziej zaawansowani użytkownicy na pewno znajdą inne zastosowanie dla tego klienta.

Klient wymaga zainstalowanego wcześniej brokera MQTT oraz instancji Supli, nie ma znaczenia czy będzie to instancja własna czy ta w chmurze. Sam klient jednak musi być uruchomiony we własnej infrastrukturze np. na RPi (RPi 4 tested & approved ;) ).

Instalacja

Instalację klienta rozpoczynamy od zainstalowania niezbędnych do jego kompilacji elementów.

Kod: Zaznacz cały

sudo apt-get install -y --no-install-recommends \
        git \
        make \
        gcc \
        g++ \
        libssl-dev \
        ca-certificates \
        ssl-cert
Następnym krokiem jest pobranie samego klienta i skompilowanie go.

Kod: Zaznacz cały

git clone https://github.com/SUPLA/supla-core.git
cd supla-core
git checkout mqtt-experimental
cd supla-mqtt-client/Release
make clean
make all
Polecenie git checkout jest w tej chwili wymagane, ponieważ klient nie znajduje się jeszcze w głównej ścieżce dystrybucji Supli (jest w innym katalogu).
Powyższe polecenie powinno skutkować pojawieniem się w katalogu supla-core/supla-mqtt-client/Release skompilowanego pliku supla-mqtt-client. Jeśli wystąpiły jakieś błędy -> nie krępuj się - napisz w tym wątku! :)

Konfiguracja

Konfiguracja klienta zamyka się na edycji trzech plików (znajdują sie w katalogu supla-mqtt-client/config). Najważniejszy i w większości jedyny jaki należy edytować to plik config_template.yaml.

Plik ten zawiera podstawową konfigurację klienta MQTT i jest podzielony na dwie części: konfiguracja dla MQTT oraz Supli.

Kod: Zaznacz cały

mqtt:
  host: 'mqttserverhost'
  port: 1883 
  commands_file_path: '../config/command.yaml'
  states_file_path: '../config/state.yaml' 
  client_name: 'supla_mqtt_client'
  protocol_version: 5
  publish_supla_events: true
supla:
  port: 2016
  host: 'localhost'
  access_id: 2
  password: 'password'
  protocol_version: 10
Pierwsza część pliku konfiguracyjnego wymaga wprowadzenia danych brokera MQTT. W pole host wpisujemy adres brokera MQTT, port zmieniamy jeśli używamy innego niż domyślny.

Dwa kolejne parametry wskazują na lokalizację plików command.yaml oraz state.yaml i powinny zostać dostosowane według własnej instalacji. WAŻNE jest aby były tam wpisane ścieżki bezwzględne.
Np. : jeśli plik state.yaml znajduje się w katalogu /home/pi/supla-core/supla-mqtt-client/config to nalezy wpisac w konfiguracji '/home/pi/supla-core/supla-mqtt-client/config/state.yaml'. Analogicznie postępujemy z plikiem command.yaml wpisując jego ścieżkę do parametru commands_file_path.

Następny parametr służy do określenia pod jaką nazwą będzie się logował klient MQTT w brokerze MQTT. Jest to ważne jeśli chcemy z różnych przyczyn mieć uruchomione więcej niż jedną instancję klienta MQTT ta nazwa musi być unikatowa.

Kolejny parametr wskazuje wersję brokera MQTT. Domyślnie klient próbuje korzystać z najnowszej wersji protokołu MQTT jednak w wielu przypadkach brokery MQTT korzystają jeszcze z wcześniejszej wersji protokołu. W takim przypadku należy zmienić ten parametr na wartość 3.

Parametr publish-supla-events określa czy klient ma publikować zdarzenia Supli. Zdarzenia te to np. informacja że inny użytkownik włączył bądź wyłączył światło. Należy jednak zwrócić uwagę na to, że nie wszystkie urządzenia publikują tego typu informacje.

Następnie należy określić parametry połączenia z Suplą. Podajemy port (domyślnie 2016), nazwę hosta lub adres IP serwera Supli, identyfikator dostępu i hasło dostepowe. Wszystkie parametry możemy znaleźć po zalogowaniu się do Supla CLOUD (parametry supla-client). Ważne jest aby przed uruchomieniem klienta MQTT włączyć w CLOUD rejestrację urządzeń mobilnych. Klient rejestruje się właśnie jako dodatkowe urządzenie mobilne-plugin.

Parametr protocol-version pozostawiamy niezmieniony chyba że używamy własnej instancji serwera Supli w starszej wersji protokołu.

Po zapisaniu pliku możemy uruchomić klienta MQTT wpisując (podając pełną ścieżkę do pliku konfiguracyjnego):

Kod: Zaznacz cały

./supla-mqtt-client -config config_template.yaml
W razie wystąpienia błędów --> pisz w tym wątku.
Jak sprawdzić czy wszystko poszło OK i działa?

Można do tego wykorzystać narzędzie MQTT Explorer dostępne pod adresem http://mqtt-explorer.com/.
Po zainstalowaniu MQTT Explorer'a możemy podłączyć się do swojego brokera MQTT i sprawdzić czy Supla publikuje tematy (domyślnie w temacie supla/channels/status/#). W zależności od tego co posiadamy w infrastrukturze Supli będą tam publikowane bieżące stany urządzeń (termometry, przyciski, rolety, bramy i wszystkie pozostałe, które teraz obsługuje Supla).

Jeśli po zalogowaniu do MQTT Explorer'a nie widać stanów kanałów Supli --> pisz w tym wątku!

Jeśli widać -> instalacja została zakończona.
Awatar użytkownika
michael
Posty: 1030
Rejestracja: śr lis 09, 2016 8:00 am
Lokalizacja: Wojkowice

pt gru 06, 2019 11:40 am

A można prosić o skompilowany supla-mqtt-client dla armv7 :?:
Chciałem go wdrożyć na QNAPie, ale kompilacja w jego środowisku pozostawia wiele do życzenia :lol:
Kabel ucięty na miarę zawsze jest za krótki...
Awatar użytkownika
pzygmunt
Posty: 7381
Rejestracja: wt sty 19, 2016 9:26 am
Lokalizacja: Paczków
Kontaktowanie:

pt gru 06, 2019 11:57 am

Może jakaś wersja dokerowa ?
Beku
Posty: 199
Rejestracja: wt lis 06, 2018 1:49 pm

pt gru 06, 2019 12:31 pm

michael pisze:
pt gru 06, 2019 11:40 am
A można prosić o skompilowany supla-mqtt-client dla armv7 :?:
Chciałem go wdrożyć na QNAPie, ale kompilacja w jego środowisku pozostawia wiele do życzenia :lol:
Wolisz dockera czy wersję skompilowaną?. W przypadku tej drugiej mam RPi 2 to chyba jest na armv7. Ale czy zatrybi ...
Awatar użytkownika
michael
Posty: 1030
Rejestracja: śr lis 09, 2016 8:00 am
Lokalizacja: Wojkowice

pt gru 06, 2019 12:33 pm

Póki co chcę przetestować rozwiązanie więc szukam jakiegokolwiek działającego ;]
Jak skompilowane dla armv7 to powinno śmigać
Kabel ucięty na miarę zawsze jest za krótki...
Awatar użytkownika
pzygmunt
Posty: 7381
Rejestracja: wt sty 19, 2016 9:26 am
Lokalizacja: Paczków
Kontaktowanie:

pt gru 06, 2019 12:38 pm

Możesz samodzielnie sobie skompilować.

Kod: Zaznacz cały

git clone https://github.com/SUPLA/supla-core
cd supla-core
git checkout mqtt-experimental
cd supla-mqtt-client/Release
make all
Awatar użytkownika
michael
Posty: 1030
Rejestracja: śr lis 09, 2016 8:00 am
Lokalizacja: Wojkowice

pt gru 06, 2019 12:44 pm

pzygmunt pisze:
pt gru 06, 2019 12:38 pm
Możesz samodzielnie sobie skompilować.
Chciałem, ale sypie błędami :?
Kabel ucięty na miarę zawsze jest za krótki...
Awatar użytkownika
pzygmunt
Posty: 7381
Rejestracja: wt sty 19, 2016 9:26 am
Lokalizacja: Paczków
Kontaktowanie:

pt gru 06, 2019 12:45 pm

Jakimi ?
Awatar użytkownika
michael
Posty: 1030
Rejestracja: śr lis 09, 2016 8:00 am
Lokalizacja: Wojkowice

pt gru 06, 2019 12:53 pm

Na QNAPie:

Kod: Zaznacz cały

../src/supla-client-lib/supla-socket.c:42:10: fatal error: openssl/err.h: No such file or directory
 #include <openssl/err.h>
          ^~~~~~~~~~~~~~~
compilation terminated.
make: *** [src/supla-client-lib/subdir.mk:60: src/supla-client-lib/supla-socket.o] Error 1
Na malinie to już w ogóle wszystko się sypie (ale tutaj raczej problem z systemem, który trochę "kuleje"):

Kod: Zaznacz cały

../src/yaml/yaml.cpp:1864:36: error: expected ‘;’ before ‘it’
       for (auto it = node.Begin(); it != node.End(); it++) {
                                    ^
../src/yaml/yaml.cpp:1864:36: error: ‘it’ was not declared in this scope
../src/yaml/yaml.cpp:1952:12: warning: ‘auto’ changes meaning in C++11; please remove it [-Wc++0x-compat]
       for (auto it = lines.begin(); it != lines.end(); it++) {
            ^
../src/yaml/yaml.cpp:1952:17: error: ‘it’ does not name a type
       for (auto it = lines.begin(); it != lines.end(); it++) {
                 ^
../src/yaml/yaml.cpp:1952:37: error: expected ‘;’ before ‘it’
       for (auto it = lines.begin(); it != lines.end(); it++) {
                                     ^
../src/yaml/yaml.cpp:1952:37: error: ‘it’ was not declared in this scope
../src/yaml/yaml.cpp: In function ‘std::string Yaml::ExceptionMessage(const string&, Yaml::ReaderLine&)’:
../src/yaml/yaml.cpp:1980:44: error: ‘to_string’ is not a member of ‘std’
   return message + std::string(" Line ") + std::to_string(line.No) +
                                            ^
../src/yaml/yaml.cpp: In function ‘std::string Yaml::ExceptionMessage(const string&, Yaml::ReaderLine&, size_t)’:
../src/yaml/yaml.cpp:1986:44: error: ‘to_string’ is not a member of ‘std’
   return message + std::string(" Line ") + std::to_string(line.No) +
                                            ^
../src/yaml/yaml.cpp:1987:36: error: ‘to_string’ is not a member of ‘std’
          std::string(" column ") + std::to_string(errorPos + 1) +
                                    ^
../src/yaml/yaml.cpp: In function ‘std::string Yaml::ExceptionMessage(const string&, size_t, size_t)’:
../src/yaml/yaml.cpp:1993:44: error: ‘to_string’ is not a member of ‘std’
   return message + std::string(" Line ") + std::to_string(errorLine) +
                                            ^
../src/yaml/yaml.cpp:1994:36: error: ‘to_string’ is not a member of ‘std’
          std::string(" column ") + std::to_string(errorPos);
                                    ^
../src/yaml/yaml.cpp: In function ‘std::string Yaml::ExceptionMessage(const string&, size_t, const string&)’:
../src/yaml/yaml.cpp:1999:44: error: ‘to_string’ is not a member of ‘std’
   return message + std::string(" Line ") + std::to_string(errorLine) +
                                            ^
../src/yaml/yaml.cpp: In function ‘size_t Yaml::FindNotCited(const string&, char, size_t&)’:
../src/yaml/yaml.cpp:2049:39: error: ‘>>’ should be ‘> >’ within a nested template argument list
   std::vector<std::pair<size_t, size_t>> quotes;
                                       ^
../src/yaml/yaml.cpp:2054:22: warning: extended initializer lists only available with -std=c++11 or -std=gnu++11
     quotes.push_back({quoteStart, quoteEnd});
                      ^
../src/yaml/yaml.cpp:2054:44: warning: extended initializer lists only available with -std=c++11 or -std=gnu++11
     quotes.push_back({quoteStart, quoteEnd});
                                            ^
../src/yaml/yaml.cpp:2067:49: error: in C++98 ‘currentQuote’ must be initialized by constructor, not by ‘{...}’
   std::pair<size_t, size_t> currentQuote = {0, 0};
                                                 ^
../src/yaml/yaml.cpp: In function ‘void Yaml::CopyNode(const Yaml::Node&, Yaml::Node&)’:
../src/yaml/yaml.cpp:2157:12: warning: ‘auto’ changes meaning in C++11; please remove it [-Wc++0x-compat]
       for (auto it = from.Begin(); it != from.End(); it++) {
            ^
../src/yaml/yaml.cpp:2157:17: error: ‘it’ does not name a type
       for (auto it = from.Begin(); it != from.End(); it++) {
                 ^
../src/yaml/yaml.cpp:2157:36: error: expected ‘;’ before ‘it’
       for (auto it = from.Begin(); it != from.End(); it++) {
                                    ^
../src/yaml/yaml.cpp:2157:36: error: ‘it’ was not declared in this scope
../src/yaml/yaml.cpp:2164:12: warning: ‘auto’ changes meaning in C++11; please remove it [-Wc++0x-compat]
       for (auto it = from.Begin(); it != from.End(); it++) {
            ^
../src/yaml/yaml.cpp:2164:17: error: ‘it’ does not name a type
       for (auto it = from.Begin(); it != from.End(); it++) {
                 ^
../src/yaml/yaml.cpp:2164:36: error: expected ‘;’ before ‘it’
       for (auto it = from.Begin(); it != from.End(); it++) {
                                    ^
../src/yaml/yaml.cpp:2164:36: error: ‘it’ was not declared in this scope
../src/yaml/yaml.cpp: In function ‘void Yaml::AddEscapeTokens(std::string&, const string&)’:
../src/yaml/yaml.cpp:2183:8: warning: ‘auto’ changes meaning in C++11; please remove it [-Wc++0x-compat]
   for (auto it = tokens.begin(); it != tokens.end(); it++) {
        ^
../src/yaml/yaml.cpp:2183:13: error: ‘it’ does not name a type
   for (auto it = tokens.begin(); it != tokens.end(); it++) {
             ^
../src/yaml/yaml.cpp:2183:34: error: expected ‘;’ before ‘it’
   for (auto it = tokens.begin(); it != tokens.end(); it++) {
                                  ^
../src/yaml/yaml.cpp:2183:34: error: ‘it’ was not declared in this scope
../src/yaml/yaml.cpp: In member function ‘const char* Yaml::Exception::Message() const’:
../src/yaml/yaml.cpp:96:57: warning: control reaches end of non-void function [-Wreturn-type]
 const char *Exception::Message() const { return what(); }
                                                         ^
../src/yaml/yaml.cpp: In member function ‘virtual Yaml::Node* Yaml::ScalarImp::Insert(size_t)’:
../src/yaml/yaml.cpp:276:62: warning: control reaches end of non-void function [-Wreturn-type]
   virtual Node *Insert(const size_t index) { return nullptr; }
                                                              ^
../src/yaml/yaml.cpp: In member function ‘virtual Yaml::Node* Yaml::MapImp::Insert(size_t)’:
../src/yaml/yaml.cpp:239:62: warning: control reaches end of non-void function [-Wreturn-type]
   virtual Node *Insert(const size_t index) { return nullptr; }
                                                              ^
../src/yaml/yaml.cpp: In member function ‘virtual Yaml::Node* Yaml::ScalarImp::PushFront()’:
../src/yaml/yaml.cpp:278:47: warning: control reaches end of non-void function [-Wreturn-type]
   virtual Node *PushFront() { return nullptr; }
                                               ^
../src/yaml/yaml.cpp: In member function ‘virtual Yaml::Node* Yaml::MapImp::PushFront()’:
../src/yaml/yaml.cpp:241:47: warning: control reaches end of non-void function [-Wreturn-type]
   virtual Node *PushFront() { return nullptr; }
                                               ^
../src/yaml/yaml.cpp: In member function ‘virtual Yaml::Node* Yaml::ScalarImp::PushBack()’:
../src/yaml/yaml.cpp:280:46: warning: control reaches end of non-void function [-Wreturn-type]
   virtual Node *PushBack() { return nullptr; }
                                              ^
../src/yaml/yaml.cpp: In member function ‘virtual Yaml::Node* Yaml::MapImp::PushBack()’:
../src/yaml/yaml.cpp:243:46: warning: control reaches end of non-void function [-Wreturn-type]
   virtual Node *PushBack() { return nullptr; }
                                              ^
../src/yaml/yaml.cpp: In member function ‘virtual Yaml::Node* Yaml::ScalarImp::GetNode(size_t)’:
../src/yaml/yaml.cpp:272:63: warning: control reaches end of non-void function [-Wreturn-type]
   virtual Node *GetNode(const size_t index) { return nullptr; }
                                                               ^
../src/yaml/yaml.cpp: In member function ‘virtual Yaml::Node* Yaml::MapImp::GetNode(size_t)’:
../src/yaml/yaml.cpp:227:63: warning: control reaches end of non-void function [-Wreturn-type]
   virtual Node *GetNode(const size_t index) { return nullptr; }
                                                               ^
../src/yaml/yaml.cpp: In member function ‘virtual Yaml::Node* Yaml::SequenceImp::GetNode(size_t)’:
../src/yaml/yaml.cpp:143:3: warning: control reaches end of non-void function [-Wreturn-type]
   }
   ^
../src/yaml/yaml.cpp: In member function ‘virtual Yaml::Node* Yaml::ScalarImp::GetNode(const string&)’:
../src/yaml/yaml.cpp:274:67: warning: control reaches end of non-void function [-Wreturn-type]
   virtual Node *GetNode(const std::string &key) { return nullptr; }
                                                                   ^
../src/yaml/yaml.cpp: In member function ‘virtual Yaml::Node* Yaml::MapImp::GetNode(const string&)’:
../src/yaml/yaml.cpp:237:3: warning: control reaches end of non-void function [-Wreturn-type]
   }
   ^
../src/yaml/yaml.cpp: In member function ‘virtual Yaml::Node* Yaml::SequenceImp::GetNode(const string&)’:
../src/yaml/yaml.cpp:145:67: warning: control reaches end of non-void function [-Wreturn-type]
   virtual Node *GetNode(const std::string &key) { return nullptr; }
                                                                   ^
../src/yaml/yaml.cpp: In function ‘std::string Yaml::ExceptionMessage(const string&, size_t, size_t)’:
../src/yaml/yaml.cpp:1995:1: warning: control reaches end of non-void function [-Wreturn-type]
 }
 ^
../src/yaml/yaml.cpp: In function ‘std::string Yaml::ExceptionMessage(const string&, Yaml::ReaderLine&)’:
../src/yaml/yaml.cpp:1982:1: warning: control reaches end of non-void function [-Wreturn-type]
 }
 ^
src/yaml/subdir.mk:18: polecenia dla obiektu 'src/yaml/yaml.o' nie powiodły się
make: *** [src/yaml/yaml.o] Błąd 1
Kabel ucięty na miarę zawsze jest za krótki...
Awatar użytkownika
pzygmunt
Posty: 7381
Rejestracja: wt sty 19, 2016 9:26 am
Lokalizacja: Paczków
Kontaktowanie:

pt gru 06, 2019 1:06 pm

Na pewno apt-get install libssl-dev
ale jeszcze jest jakiś problem
ODPOWIEDZ