Zigbee2MQTT, NodeRed a Loxone

Zigbee2MQTT, NodeRed a Loxone

You are here:
< Zpět

Minulý článek jsme skončili tím, že nám z RaspberyPI leze pomocí protokolu MQTT informace o stavech čidel, případně pomocí MQTT jsme schopni zapnout třeba žárovku nebo inteligentní zásuvku. Dnes se pojdmě podívat, jak to nyní propojit s Loxone tak, abychom mohli vše ovládat nativně z Loxone prostředí.

Jelikož Loxone nepodporuje MQTT (a zřejmě ani nikdy podpodorvat nebude), je opět potřeba si pomoci aplikací NodeRED, kterou jsem zde na blogu zmiňoval už spoustukrát (Propojení všeho se vším od Arduina po Loxone).

V návodu začneme směrem od Zigbme2mqtt k Loxone. Budu předpokládat, že máte čidla nainstalované a nampárované a že víte, jaká data z nich lezou (to jde vidět například v Zigbee2MQTT konzoly).

Xiaomi teploměr

Jako první ukážu propojení na teploměru Xiaomi. Jako MQTT kanál se použije dle nastavení například zigbee2mqtt/temperature01. Do kterého se posílají data:

{"temperature":26.05,"linkquality":47,"humidity":32.86,"pressure":927.38,"battery":42,"voltage":2985}

Abychom data přijali do Loxone, je potřeba je z MQTT převést do UDP (což je asi nejjednoduší a nejrychlejší cesta jak je do Loxone předat).

Vytvoříme si proto v NodeRed novou záložku Zigbee, do které jako první přidáme MQTT vstup. Ten nakonfigurujeme na připojení k našemu MQTT serveru a jako “Topic” vyplníme topic dle čidla. V našem případě “zigbee2mqtt/temperature01″

 

Jako další přidáme funkci, ve které napíšeme logiku převodu MQTT na UDP. V případě teploměru nás krom samotné teploty zajímá také tlak a vlhkost.

Abychom nemuseli provádět nějaké složité parsování na straně Loxone, vytvoříme v NodeRED logiku tak, že z jedné vstupní zprávy s těmito údaji vytvoříme tři výstupní UDP pakety, které se postupně pošlou do Loxonu.

var objPayload = JSON.parse(msg.payload);

var temperature = new Object();
temperature.payload = "temperature01/temperature=" + objPayload.temperature;

var humidity = new Object();
humidity.payload = "temperature01/humidity=" + objPayload.humidity;

var preasure = new Object();
preasure.payload = "temperature01/pressure=" + objPayload.pressure;

return [ [temperature,humidity,preasure] ];

Na prvním řádku převedeme Json objekt do Javascrip objektu. Díky tomu do něj můžeme dále jednoduše přistupovat.

Na řádcích 3 – 10 pak postupně vytvoříme tři objekty s výslednými daty. Každému objektu nastavíme payload, což je proměnná, které se pak v dalším bloku (UDP výstup) pošle na zadanou UDP adresu a port.

Abychom si v Loxonu parsování co nejvíce usnadnili, v každém UDP paketu posíláme název dat, rovnítko a hodnotu. Tento název spolu s rovnítkem pak budeme v řetezci hledat a v primitivních parserech Loxonu parsovat.

Jako poslední pak vrátíme pole objektů. Tím NodeREDu říkáme, že nechceme vrátit a zpracovat jeden objekt, ale několik objektů.

Xiaomi Cube

Krom čidla teploty byste mohli chtít parsovat například data z Xiami Cube. Z něj naopak čteme vždy jen jednu hodnotu, ale může jich být více typů. Proto zde přikládám i program na vyparsování typu události, její hodnoty a převod hodnoty do Loxone.

 

var objPayload = JSON.parse(msg.payload);

if ( objPayload.action == "flip90" )
{
   node.error("flip90 "+ objPayload.to_side);
   msg.payload = "flip"+ objPayload.to_side;
}
else if ( objPayload.action == "flip180" )
{
   node.error("flip180 "+ objPayload.side);
   msg.payload = "flip"+ objPayload.side;
}
if ( objPayload.action == "rotate_right" )
{
    node.error("rotate_right " + objPayload.angle);
    msg.payload = "rotate_right"; //+ objPayload.side;
    return msg;
}
else if ( objPayload.action  == "rotate_left" )
{
    node.error("rotate_left " + objPayload.angle);
    msg.payload = "rotate_left"; //+ objPayload.side;
}
else if ( objPayload.action == "slide" )
{
   node.error("slide "+objPayload.side);
   msg.payload = "slide"+ objPayload.side;
}
else if ( objPayload.action == "shake" )
{
   node.error("shake");
   msg.payload = "shake";
}
else if ( objPayload.action == "tap" )
{
   node.error("tap " + objPayload.side);
   msg.payload = "tap"+ objPayload.side;
   return msg;
}
else if ( objPayload.action == "wakeup" )
{
    //do nothing
    return null;
} else
{
    node.error("Unknown " +  objPayload.action);
    return null;
}

node.error(msg.payload);

Kostku jsem nakonec do ostrého provozu nenasadil, protože citlivost ovládání není ideální a úplně mi její používání k srdci nepřirostlo. Proto program není dodělán do finální podoby (nejsou tam například klíč=hodnota příkazy) ale jde spíše u ukázku toho, jak případně logiku řešit.

UDP komunikace

Poslední node který do našeho projektu v NodeRED přidáme je UDP output. V něm nastavíme IP adresu Loxonu a port, na kterém bude Loxone naše data naslouchat.

Tím máme v NodeRED pro teď hotovo a přesuňme se do Loxone Configu, kde přidáme UDP virtuální vstup.

A do něj jednotlivé UDP příkazy. Například parsování teploty nastavíme takto:

Postupně takto vytvoříme všechny UDP příkazy, které z NodeRED posíláme:

A tím máme hotovo. Hodnoty pak použijeme v Loxone configu stejně, jako jakékoli jiné hodnoty z teploměrů a čidel.

A nyní opačný směr

Tím máme vyřešeny všechna čidla a ovladače. To další, co nás ale zajímá, je ovládání zásuvek a osvětlení z Loxone směrem k Zigbee2MQTT.

Začneme zase v NodeRED. Zde nyní jako první vytvoříme UDP vstup, na kterém bude NodeRED naslouchat příkazy, které mu budeme z Loxone posílat.

Jako druhá je opět funkce, tentokrát taková, co převede textový příkaz z Loxone na MQTT příkaz. Abych nemusel psát hromadu malých funkcí, co převede jednotlivé příkazy, vytvořil jsem si univerzální funkci, která umí převést libovolný příkaz z Loxone na MQTT.

Funkce vezme jakýkoli vstupní řetezec ve formátu GROUP/DEVICE/VALUE, rozparsuje jej a převede na MQTT příkaz. Příakaz vytvoří tak, že topic je vždy zigbee2mqtt/ následovaný parametry dle typu zařízení.

node.error("incomming: " + msg.payload);

//parse incoming data to group-device-value
const regex = new RegExp("([a-zA-Z0-9]+)\/([a-zA-Z0-9]+)\/([a-zA-Z0-9]+)");
var res = regex.exec(msg.payload);

var nameGroup = res[1];
var nameDevice = res[2];
var value = res[3];

node.error("group=" + nameGroup);
node.error("device=" + nameDevice);
node.error("value=" + value);

//preapre MQTT command
msg.payload = {};
msg.topic = "zigbee2mqtt/";

//create light command
if ( nameGroup == "light" )
{
    msg.topic += nameDevice + "/set";
    
    if ( value === 0 )
      msg.payload.state = "off";
    else 
      //loxone has 0-100, but we need 0-255
      msg.payload.brightness = value*2.55;
}

node.error(msg);
return msg;

V současnosti je připravena logika jen pro světla, kdy topic je zigbee2mqtt/devicename/set a hodnota buď “off”, pokud je nastavena 0, nebo číselná hodnota 0-255 dle nastavení 0-100.

Až bude potřeba přidat například spínanou zásuvku, pridám nový group-name “powersocket” a dle potřeby vygeneruju cílový payload. Je to určitě o dost přehlednější, než mít pro každou žárovku a každou zásuvku zvlášť program.

Třetím blokem v NodeRED diagramu je pak MQTT output node. To dle nastaveného msg.payload vytvoří MQTT topic a odešle ho na zadaný server.

Loxone UDP výstup

Poslední co zbývá je Loxone UDP výstup, který bude posílat data do NodeRED.

Jako první přidáme “Virtuální výstup” do Loxone configu (bacha, zatímco existuje UDP vstup, tak opakem je Virtuální výstup, nikoli UDP výstup…..).

Tento výstup pak nakonfigurujeme jak je ukázáno na obrázku výše. Důležitá je adresa, kde to, že je to UDP určujeme přímým odkazem na zařízení v URI. Tzn v mém případě /dev/udp/192.168.0.222/60001

Příkaz pro nastavení svítivosti Ikea žárovky pak vypadá takto. Je potřeba natavit instrukci pro zapnutí a vypnutí, která je ale v našem případě stejná a až samotná hodnota určuje, zda zapínáme nebo vypínáme.

Na takto vytvoření příkaz pak normálně napojíme blok ovládání osvětlení AQ1, takže v okamžiku, kdy budete měnit osvětlení se budou přes UDP posílat příkazy s aktuální hodnotou.

Tady bohužel pak trochu narážíme na limity MQTT, jelikož při plynulé změně hodnot z 100 na 0 se pošle 100 příkazů, které se musí nejprve převést na UDP, z nějak pak na MQTT, kde ho pak Zigbee2MQTT musí převést na Zigbee a poslat žárovce. Výsledkem je, že při stmívání a rozsvěcení žárovky může dojít ke zpoždění.

Zde by bylo určitě lepší mít možnost poslat přes UDP příkaz rovnou k Zigbee bráně. Bohužel, nic takového jsem nenašel.

A to je vše

A to by mělo být vše pro to, abyste propojili Zigbee a Loxone v obou směrech. Na většinu zařízení je celý koncept naprosto dostatečný a stabilní. Jediná vyjímka jsou ta stmavovaná světla, kdy při plynulém přechodu z maxima na minium se může stlumění světla trochu zpozdit.

PS: Tak, jako je univerzální funkce na ovládání a nastavování MQTT zařízení, šla by napsat i univerzální funkce na příjem hodnot z teploměrů. Předpokládám, že až čidla po době více rozšířím, tak že i tu ještě trochu předělám.

 

Pomohl Vám náš blog? Chcete nás podpořit? I málo udělá radost 😉
Poslední úprava článku February 24, 2019

7 thoughts on “Zigbee2MQTT, NodeRed a Loxone

  1. Postupoval jsem dle návodu( i prolaika celkem srozumitelný), ale zasekl jsem se ve fázi zpracování informace v Loxone Config.
    Do loxone dostanu text ze smoke detektoru: smoke01/smoke=false nebo true. Bohužel nejsem v programování moc zdatný a v tomto kroce už nevím jak dál. Tuším bych potřeboval z toho true/false vyrobit 1/0. Poradíte?

    1. V loxonu mozna nejak pres to jeho hloupe porovnavani hodnot, ale lepsi je to dekodovat na urovni NodeRed, kde to pres javascript prevezt rovnou do pozadovanych hodnot a ty pak cpat do loxone.

  2. Pokial by sa niekto nechcel babrat s node-red, tu je odomna docker-compose suita ktora preposiela zigbee eventy do loxone pomocou UDP: https://github.com/dusanmsk/zigbee2udp.git

    Prakticky staci docker-compose, editnut 2 subory a nahodit to a vsetko co pride zo zigbee preposle do loxone. Bezim to na NAS-e s rotacnymi diskami, je tam sice pripraveny navod na sd-kartove boardy, ale zatial som to vzdal lebo mam len orangePI co zamrza. Cielovy stav je to asi hodit na RPi4 s SSD diskom a neriesit zapisy na disk. Pokial bude zaujem, spisem k tomu clanok.

    1. supr!. Sem si rikal, jak si vyresil ten json v loxonu, ale uz to vidim. ty to rozkladas na jednotlive paramy a posilas jako string, takze to pak jde parsovat.

      to je dobrej napad. Resis nejak i opacnej smer? Tam uz by to asi byl vetsi voser to rozumne poskladat zpet do jsonu.

      1. Mam to v plane, lezi mi tu nejaka ikea ziarovka, este som sa k tomu nedostal. Na opacny smer by som mohol pouzit loxone2mqtt co uz vyuzivam na grafanu, takze by stacili virtualne vystupy nejak pomenovane a nemusi sa clovek srat s udp/http commandami. Uvidim, idem sa najest a vyrobit si objimku s vypinacom :D.

        1. Uz to mam na stole, pojde to v pohode podla mna. IKEA led ziarovka konzumuje zigbee2mqtt/led1/set { “brightness” : 100 }

          Moznosti su dve. Bud na loxone spravim virtualny vystup povedzme 2zigbee_led1_set_brightness, dam ho zobrazit na UI, to mi tym padom vytaha loxone2mqtt do fronty, odchytim v mqtt2udp, prelozim na zigbee2mqtt/led1/set { brightness: XYZ} a hotovo.

          Alebo vytvorim udp vystup a poslem tam zigbee2udp/led1/set/brightness \v.

Leave a Reply

Your email address will not be published. Required fields are marked *