Napisz do mnie

Wyślij prywatną wiadomość

STEROWANIE URZĄDZENIAMI HAPCAN

opublikowano: 19 lip 2020 wyświetleń: 2771 komentarzy: 0

#MQTT #Node-RED #HAPCAN #Philips Hue #DARIA

Na dobry początek, niech stanie się światłość - czyli o sterowaniu urządzeniami w systemie DARIA.

Zgodnie z założeniami systemu, jakiekolwiek sterowanie urządzeniami zewnętrznymi odbywa się przez serwer MQTT. Jedynym zatem miejscem, w którym istnieją odwołania do fizycznych urządzeń, jest zakładka MQTT Control. Dlaczego tak? Bo łatwiej nad tym zapanować, kiedy wszelkie odwołania nie są rozproszone po różnych zakładkach.

Sterowanie urządzeniami przekaźnikowymi Hapcan

Na zrzucie poniżej przedstawiam ideę działania tej zakładki. Nie są tutaj pokazane wszystkie urządzenia, tylko wybrane, istotne fragmenty.

Po lewej stronie wejściowe bloczki MQTT, które zasubskrybowane są pod tematy związane ze sterowaniem urządzeniami, czyli z końcówką /control. Przykładowo:

  • home/env/switch/room1/+/control
  • home/env/light/room1/+/control
  • home/env/blind/room1/+/control

Tematy zawierają w sobie znak +, który oznacza dopasowanie dowolnego elementu w temacie. Ten element jest następnie tłumaczony (translate) na dane dla odpowiedniego urządzenia, jak moduł przekaźników, rolety itp. obsługiwane przez system HAPCAN.

Oczywiście, można by było każde urządzenie puścić w osobnym temacie i sterować osobno konkretnym przekaźnikiem w module przekaźników — tak będzie zapewne najprościej dla kogoś, kto ma lęk przed kodem i JavaScriptem :). Ja otóż nie mam, więc zmniejszyłem sobie w ten sposób liczbę połączeń i bloczków na zakładce. Sposób podziału na pokoje, typ urządzeń itp. jest tutaj dowolny.

Pozostaje wyjaśnić jak wygląda kod w bloczku funkcyjnym translate. Dla przykładu, niech to będzie ścieżka sterująca roletami elektrycznymi w pokoju.


var channel = 0;                     // inicjalizacja zmiennej channel, która oznacza w tym przypadku numer rolety (1-3)

var path = msg.topic.split('/');     //rozbicie tematu wiadomości MQTT na tablicę elementów

switch(path[4])                      // 5 element tablicy (indeks 4) to wspomniany wcześniej +
{
    case 'doorblind': channel = 1; break;     // jeśli to doorblind to ustawiam roletę 1
    case 'windowblind' : channel = 2; break;  // jeśli to windowblind to ustawiam roletę 2
}
if( channel !== 0)                    // na koniec weryfikacja, czy kanał został ustawiony
{
    msg.topic = 'control';            // aby sterować bloczkami Hapcan za pomocą wiadomości Node-RED, trzeba ustawić temat "control"
    msg.payload.channels = channel;   // ustawiam też w payloadzie wybrany kanał
    return msg;                       // emituję przesłaną wiadomość dalej
}
return;                               // w innym przypadku przerywam przetwarzanie zwracając nic...

Jeśli przesłany zostanie temat MQTT zawierający jakąś inną nazwę urządzenia niż zdefiniowane w sekcji switch, to dalsze wykonywanie przepływu zostanie wstrzymane. Jeśli analizujesz kod, to zapewne zapytasz, a skąd roleta ma wiedzieć co ma zrobić, skoro jest tutaj ustawiony tylko channel. Otóż roleta otrzymuje cały payload przesłany do MQTT, a ta funkcja ma za zadanie jedynie dodać do tego payloadu konkretny przekaźnik, kanał itp. wynikający z nazwy urządzenia. Dzięki temu, jeśli chcę podnieść roletę, nie muszę się zastanawiać czy to był kanał 1, 2, 3, czy światło w kuchni to był przekaźnik 1, 2, 3, 4, 5, czy może 6. Wystarczy, że znam jego nazwę — którą, jak wspomniałem w innym wpisie, najlepiej sobie zanotować w jakiejś tabelce dokumentacji.

Tak więc aby przykładowo podnieść roletę drzwi balkonowych do góry, należy opublikować w MQTT poniższy payload typu JSON pod tematem home/env/blind/room1/doorblind/control.


{
  "action": "up"
}

Skąd wiadomo, że akurat taki JSON? Z dokumentacji bloczka node-red-contrib-hapcan typu blind-output. W momencie gdy wyślemy do tego bloczka wiadomość o temacie control, zamiast domyślnych ustawień w oknie konfiguracji, bloczek wykona polecenie przesłane we wiadomości w parametrze action. Przyjmuje on również parametr channel, który jest właśnie uzupełniany na podstawie nazwy rolety. Sumarycznie zatem po wyjściu z bloczka translate payload jest taki:


{
  "action": "up",
  "channel": 1
}

i roleta jedzie do góry :). Wysyłając zatem jakiekolwiek polecenie kontrolujące urządzenie, trzeba znać jego strukturę, dostępne pola i wartości. Nie stosowałem tutaj żadnej struktury pośredniej i tak np. aby ustawić światło ledowe na 100% w module Hapcan RGB wysłać trzeba state: 255, natomiast dla lamp Philips Hue jest to brightness: 100, on: true. Sterowanie różnymi urządzeniami wymaga różnych danych i struktura pośrednia, w której zawsze jasność jest parametrem brightness ograniczała by trochę możliwości sterowania nimi.

Sterowanie lampami ściemnialnymi

W moim systemie obecnie występują dwa typy lamp ściemnialnych:

W zasadzie wyeliminowałem już całkowicie zwykłe lampy typu włącz/wyłącz. Płynne zapalanie oraz gaszenie i możliwość regulacji natężenia oraz barwy robią to co tygryski lubią najbardziej :). Te drugie do najtańszych nie należą, można by wręcz powiedzieć, że są dość drogie, ale mają jedną istotną zaletę — szybkość montażu, jako, że działają radiowo poprzez zigbee. Ma to też swoje wady w stosunku do kabla, żeby nie było :).

Hapcan RGB

Na rysunku poniżej przestawiony jest przepływ sterujący światłami ściemnialnymi (głównie taśmy LED).

Po lewej oraz po prawej to samo co powyżej. Zamiast jednak funkcji tłumaczącej każde oświetlenie ma swój własny bloczek subskrybujący temat MQTT.

Co robią te wszystkie bloczki pomiędzy? Ano wpływają na jasność światła, jeśli ta nie została zdefiniowana w payloadzie. Dzięki temu niezależnie od tego, w jaki sposób światło zostanie włączone, czy będzie to przycisk na ścianie, na pilocie, polecenie głosowe czy aplikacja mobilna jasność oświetlenia dostosuje się odpowiednio do godziny. Ale od początku.

Bloczek ON/OFF weryfikuje, czy w payloadzie wysyłanym do taśmy LED występuje akcja włączenia czy wyłączenia. Przy wyłączaniu nie ma co ustawiać jasności, stąd do sekcji Brightness leci tylko polecenie włączenia światła (a w zasadzie każdej inne niż wyłączenie).

Bloczek dla urządzenia Hapcan RGB umożliwia wyłączenie światła na różne sposoby (przekazując state jako false, 0, "OFF") stąd też wszystkie te 3 przypadki są uwzględnione i wyjścia 1-3 są podłączone dalej, do bloczka Demux. Każda inna wartość, oraz jej brak przekierowuje wiadomość na wyjście nr 4 (otherwise).

Grupę bloczków Brightness rozpoczyna kolejny bloczek typu switch. Ten z kolei sprawdza, czy we wiadomości otrzymanej z MQTT wartość state (czyli stan) jest określona liczbą czy typem bool lub string. Jeśli zatem zleceniodawca określi tylko, że chce włączyć światło (true,"ON") to wiadomość trafia dalej, do bloczka inject time. Jeśli w payloadzie jest informacja liczbowa, np state:150, to system nic tutaj nie ingeruje i przesyła wiadomość dalej do bloczka Demux.

Wyjście 2 i 3, gdzie nie ma informacji o preferowanej jasności podlegają dalszemu procesowaniu.

I tak trafiamy do bloczka inject time, który dodaje do payloadu pole state i wypełnia je aktualną godziną w postaci minut od początku danego dnia.


let now = new Date();                        // tworzymy obiekt Date zawierający aktualny czas
now = now.getHours()*60 + now.getMinutes();  // przeliczamy go na minuty od początku dnia (godzina*60+minuta)

msg.payload.state = now                      // wyliczoną wartość wstawiam do parametru state

return msg

Wartość taka mieści się w przedziale od 0-1439, dla zakresu godzin od 0:00 do 23:59. Tak przygotowana godzina trafia do bloczka time 2 Hapcan state (bloczek typu node-red-contrib-visualstate, również mojego autorstwa, do pobrania z repozytorium NPM). Bloczek ten zawiera edytor graficzny, umożliwiający mapowanie jednej wartości na inną — w tym przypadku zamapujemy sobie czas na jasność świecenia.

Jako input range (zakres wejściowy) podaję tutaj zakres minut (0-1440), natomiast zakres wyjścia (output range) dopasowuję do sterowanego modułu, czyli 0-255 bo takie wartości może przyjmować parametr state dla Hapcan RGB. Liczbę wyświetlanych kresek można sobie ustalić po swojemu, ja tutaj wpisałem 24, tak aby każda kreska pionowa odpowiadała kolejnej godzinie. Ważne jest również, aby ustawić zaokrąglanie do jedności.

Za pomocą linii i punktów kluczowych ustalam natężenie światła w ciągu całego dnia. I tak w nocy jest to około 10% mocy, od godziny 4 jasność stopniowo wzrasta aby o 7 osiągnąć 100% mocy. Wieczorem podobnie, światło się ściemnia do 50% o godzinie 0:00. Przypomnę, że chodzi tutaj o domyślną wartość jasności w momencie włączania światła. Nie wpływa to na światło już włączone.

Na wyjściu pojawia się zatem payload wzbogacony o parametr state o wartości uzależnionej od czasu. W ten sposób można uzależnić to od czegokolwiek: natężenia światła naturalnego, prędkości wiatru czy wartości spółki na giełdzie papierów wartościowych :).

Dochodzimy do bloczka Demux (demultiplekser). Bloczek ten to nic innego jak wcześniej opisywany bloczek translate, tym razem zrealizowany za pomocą wbudowanych w Node-RED bloczków typu switch, oraz change. W zależności od tematu MQTT wiadomość kierowana jest do bloczka channel = 1 albo channel = 2.

  • home/env/light/room1/ceilingshelf/control → channel 1
  • home/env/light/room1/brickwallledstrip/control → channel 2

Dzięki temu dla każdej taśmy LED użyty jest ten sam przepływ a dopiero na końcu za pomocą bloczków change dodawane jest do payloadu pole channel o odpowiedniej wartości wskazującej na to, które wyjście modułu RGB ma zostać zmienione.

Ustawianie kanału za pomocą bloczka change

Dodatkowo jest tu ustawiany także temat na control, bo do tej pory w temacie wiadomości był temat MQTT.

W dalszej części artykułu opisane zostanie sterowanie światłami Philips Hue oraz pozostałe przepływy sterujące.

 

2 like voting
is closed
thanks
for your vote

CZYTAJ DALEJ POZOSTAŁE CZĘŚCI TEGO ARTYKUŁU


TO MOŻE CIĘ ZAINTERESOWAĆ


Comments (0)


Allowed tags: <b><i><br>


PODOBAŁO SIĘ?

PODOBAŁO SIĘ?


2 like voting
is closed
thanks
for your vote

PODZIEL SIĘ

PODZIEL SIĘ