Cześć
Tym razem poradnik jak odczytywać stan urządzeń Smart firmy LG (te które obsługują aplikację LG Thinq) i używają API v2.
Ja używam go do odczytu stanu Suszarki LG, powinno działać też z pralkami oraz klimatyzatorami.
Inspirowałem się tym wpisem https://community.openhab.org/t/lg-smart-thinq/38818/1 .
Jako, że od jakiegoś czasu jestem fanem kontenerów, a zainstalowanie tej aplikacji bezpośrednio na środowisku pythona jest strasznie upierdliwe i czasochłonne (w szczególności na RPi), w poradniku wykorzystywany jest gotowy kontener dockerowy. Instalacja dockera:
curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh sudo usermod -aG docker $USER
Ostatnia komenda pozwoli używać dockera bez używania sudo. Aby tak się stało należy ponownie zalogować się do konsoli.
Przed skorzystaniem z dobrodziejstw pozyskiwania stanu urządzenia LG przez API należy zainstalować aplikację LG Thinq, utworzyć konto LG i zparować urządzenie LG z aplikacją.
Następnie tworzymy folder, w którym umieścimy konfigurację dockera i folder z plikiem stanu.
mkdir -p thinq2-mqtt cd thinq2-mqtt mkdir -p state wget https://raw.githubusercontent.com/kamiKAC/thinq2-python/master/compose.yaml
Uruchamiamy kontener w trybie interaktywnym:
docker run -ti --rm -e COUNTRY_CODE=PL -e LANGUAGE_CODE=pl-PL -v ./state/:/thinq2-python/state/ kamikac/thinq2-mqtt
Jeśli nasz serwer MQTT wymaga uwierzytelniania można podać nazwę użytkownika, hasło i nazwę hosta:
docker run -ti --rm -e COUNTRY_CODE=PL -e LANGUAGE_CODE=pl-PL -e MQTT_HOST=hostname -e MQTT_USER=user -e MQTT_PASS= password -v ./state/:/thinq2-python/state/ kamikac/thinq2-mqtt
Po uruchomieniu program wygeneruje link, który kopiujemy do przeglądarki. Otworzy się strona logowania LG, gdzie podajemy nazwę użytkownika i hasło z aplikacji LG Thinq. Po poprawnym zalogowaniu wyświetli się pusta strona i jest to absolutnie normalne. Kopiujemy link z przeglądarki do programu i naciskamy Enter.
Po chwili powinna się pojawić informacja o odnalezionych urządzeniach i w konsoli powinny pojawić się zdarzenia dotyczące urządzenia LG. W przypadku problemów z połączeniem MQTT program przy wyjściu powinien zapisać plik z danymi potrzebnymi do ponownego połączenia, zatem ponowna rejestracja nie jest potrzebna.
Otwieramy plik compose.yaml edytorem i konfigurujemy:
nano compose.yaml
Zmieniamy dane dotyczące serwera MQTT, jeśli korzystamy z uwierzyteniania lub serwer MQTT znajduje się na innym hoście niż kontener.
Po zapisaniu pliku, uruchamiamy kontener (domyślnie kontener jest tak skonfigurowany, że uruchamia się automatycznie po uruchomieniu system operacyjnego, zatem nie ma potrzeby używania do tego żadnych skryptów):
docker compose up -d
Jeśli nie popełniliśmy błędu to kontener powinien działać, logi widać po wydaniu komendy:
docker logs -f thinq2-mqtt
Zatrzymujemy (niszczymy) kontener dockera komendą:
docker compose down
Aby odczytać dane suszarki dodajemy do mqtt.things (przyjmujemy, że mamy już skonfigurowany bridge o nazwie mosquitto):
Thing mqtt:topic:dryer "Suszarka" (mqtt:broker:mosquitto){ Channels: Type string : state "State" [ stateTopic="thinq/de08c6b7-e718-1233-97cd-44cb8b08bcc1/data/state" ] Type string : processState "Etap pracy" [ stateTopic="thinq/de08c6b7-e718-1233-97cd-44cb8b08bcc1/raw_data/processState" ] Type string : online "Online" [ stateTopic="thinq/de08c6b7-e718-1233-97cd-44cb8b08bcc1/data/online" ] Type string : courseType "Program" [ stateTopic="thinq/de08c6b7-e718-1233-97cd-44cb8b08bcc1/raw_data/courseDryer24inchBase" ] Type string : dryLevel "Poziom wysuszenia" [ stateTopic="thinq/de08c6b7-e718-1233-97cd-44cb8b08bcc1/raw_data/dryLevel" ] Type string : ecoHybrid "Tryb EcoHybrid" [ stateTopic="thinq/de08c6b7-e718-1233-97cd-44cb8b08bcc1/raw_data/ecoHybrid" ] Type string : selfClean "Czyszczenie wymiennika" [ stateTopic="thinq/de08c6b7-e718-1233-97cd-44cb8b08bcc1/raw_data/selfClean" ] Type string : remainTimeH "Pozost. godz." [ stateTopic="thinq/de08c6b7-e718-1233-97cd-44cb8b08bcc1/data/remaintimehour" ] Type string : remainTimeM "Pozost. min." [ stateTopic="thinq/de08c6b7-e718-1233-97cd-44cb8b08bcc1/data/remaintimeminute" ] Type string : error "Błąd" [ stateTopic="thinq/de08c6b7-e718-1233-97cd-44cb8b08bcc1/error" ] }
Plik dryer.items
Group gDryer "Suszarka Zuzanka" <dryer> (GF_BoilerRoom) ["Dryer"] String Dryer_online "Online [MAP(dryer_online.map):%s]" <text> (gDryer) ["Status"] {channel="mqtt:topic:dryer:online"} String Dryer_state "Stan [MAP(dryer_state.map):%s]" <text> (gDryer) ["Status"] {channel="mqtt:topic:dryer:state"} String Dryer_processState "Etap pracy [MAP(dryer_phase.map):%s]" <text> (gDryer) ["Status"] {channel="mqtt:topic:dryer:processState"} String Dryer_courseType "Program [MAP(dryer_program.map):%s]" <text> (gDryer) ["Status"] {channel="mqtt:topic:dryer:courseType"} String Dryer_dryLevel "Poziom wysuszenia [MAP(dryer_drylevel.map):%s]" <text> (gDryer) ["Status"] {channel="mqtt:topic:dryer:dryLevel"} String Dryer_ecoHybrid "Tryb EcoHybrid [MAP(dryer_ecohybrid.map):%s]" <text> (gDryer) ["Status"] {channel="mqtt:topic:dryer:ecoHybrid"} String Dryer_selfClean "Czyszczenie wymiennika [%s]" <text> (gDryer) ["Status"] {channel="mqtt:topic:dryer:selfClean"} String Dryer_RemTimeH "Pozost. godz. [%s]" <text> {channel="mqtt:topic:dryer:remainTimeH"} String Dryer_RemTimeM "Pozost. min. [%s]" <text> {channel="mqtt:topic:dryer:remainTimeM"} String Dryer_error "Błąd [%s]" <text> (gDryer) ["Status"] {channel="mqtt:topic:dryer:error"}
dryer_drylevel.map:
DRYLEVEL_CUPBOARD=do szafy DRYLEVEL_EXTRA=extra DRYLEVEL_IRON=do prasowania NO_DRYLEVEL=brak
dryer_ecohybrid.map:
ECOHYBRID_ECO=Eko NO_ECOHYBRID=Nie Eko
dryer_online.map:
true=TAK false=NIE
dryer_phase.map:
DETECTING=Wykrywanie DRY_LV1=Suszenie wstępne DRY_LV2=Suszenie do prasowania DRY_LV3=Suszenie do szafy COOL=Chłodzenie END=Zakończone
dryer_program.map:
COTTONNORMAL=Bawełna MIXFABRIC=Mieszane EASYCARE=Syntetyczne BULKYITEM=Pościel TOWELS=Ręczniki QUICKDRY=Szybki 30 ALLERGYCARE=Antyalergiczny REFRESH=Mój program WARMAIR=Ciepłe powietrze COOLAIR=Zimne powietrze RACKDRY=Suszenie na stojaku SPORTWEAR=Odzież sportowa WOOL=Wełna DELICATES=Delikatne NOT_SELECTED=Nie wybrano
dryer_state.map
pause=Pauza running=Praca initial=Nastawianie poweroff=Wyłączona end=Suszenie zakończone
Z powodzeniem działa to u mnie od ok. 2 lat.