Browsed by
Category: Loxone Config

Loxone návody

Ovládání tepelného čerpadla Rapid Mini Inverter

Ovládání tepelného čerpadla Rapid Mini Inverter

Když jsem si k bazénu pořídil tepelné čerpadlo, začal jsem zároveň řešit, jak efektivně využít přebytky z FVE a jak to celé propojit. Prvním nápadem bylo spínat čerpadlo rovnou přes relé, ale nebyl jsem si jistý, jestli po zapnutí naběhne samo, a taky jsem měl obavy, že časté vypínání by mohlo kompresoru škodit.

Další volba tak padla na Wi-Fi modul a jeho propojení přes TinyTuya (LoxBerry). Základní funkce, které jsem potřeboval – tedy zapnutí/vypnutí, čtení teploty vody v bazénu a nastavení požadované teploty – jsem tímto způsobem získal, a víc jsem v té chvíli nepotřeboval.

Jenže letos při odzimování bazénu přišlo “ale”. Wi-Fi modul se začal samovolně odpojovat od sítě – klidně i na hodinu. A to je problém, když potřebujete spínat podle přebytků z FVE v reálném čase.

Začal jsem proto hledat jiné řešení a zjistil, že čerpadlo má rozhraní RS485.

Takže hurá do toho.

Model, který mám je Rapid Mini Inverter RMIC06, ale ve skutečnosti je to výrobce Fairland, takže by měli fungovat stejné adresy pro všechny modely od nich.

Použité díly:

  1. Odstranění krytu hlavního přívodu

Nejprve je potřeba sejmout kryt, pod kterým se nachází hlavní elektrický přívod. Kryt je upevněn několika šrouby – po jejich odšroubování lze kryt jednoduše sundat.

      2. Demontáž displeje

Pod tímto krytem se nachází další šrouby, které drží displej. Ty je třeba vyšroubovat a displej opatrně vyjmout.

      3. Odstranění horního krytu čerpadla

Po demontáži displeje se zpřístupní další dva šrouby, které upevňují horní kryt čerpadla. I tyto šrouby je třeba odstranit. Poslední šroub, který drží horní kryt, je umístěn na zadní straně jednotky, v blízkosti chladiče (radiátoru). Po jeho odšroubování lze horní kryt kompletně sejmout a získat tak přístup k vnitřní elektronice a sběrnici RS485.

      4. Sejmutí krytů řídicí jednotky

Po odstranění všech krytů řídicí jednotky je možné najít konektor typu JST XH 2,54 mm (4pin), do kterého je zapojen modul pro připojení Wi-Fi.

Zde je můžeme vidět 4 piny – první dva jsou RS485 B a A zbylé dva je napájení tedy G zem a +12V, takže můžeme z desky rovnou napájet náš převodník

    5. výsledné propojení

Nyní stačí jen pro jednotku najít vhodné umístění a přivést LAN kabel a znovu vše tepelné čerpadlo poskládat zpět.

6. Nastavení převodníku

  • přenosová rychlost 9600
  • Parity NONE
  • data 8
  • Stop 1
  • TCP Server
  • port 502
  • Modbus TCP

7. Loxone config

Přidáme nový modbus server kde zadáme IP adresu + port a nyní v předefinovaných zařízení přidáme šablonu ke stažení zde

 

 

Loxone virtuální výstupy a jejich debugging

Loxone virtuální výstupy a jejich debugging

Tento článek bude o tom, jak správně nastavit virtuální vstupy a jak postupovat při ladění v případě, že se Loxone nechová tak jak bychom očekávali.

Ukážu, jak ladit virtuální http výstupy, na co si dát při jejich použití pozor a jak otestovat, jestli je chyba u Vás nebo v Loxone. A o Pushover notifikacích bude až další článek.

Co byste měli jako první při vytváření HTTP virtuálního výstupu otestovat je, zda máte vlastně správně cílovou URL a parametry. Úplně nejjednodušší je vyzkoušet to přes command-line příkaz curl


curl http://api.pushover.net/1/messages.json -d "token=xxxxx&message=helloworld&user=xxxxx"

{"status":1,"request":"719ea7ef-f62d-456e-bb09-0708f24605b7"}

S curl je to sice rychlé, ale občas může být příprava takového příkazu trochu složitější. A tak je lepší použít něco sofistikovanějšího, jako například Postman (aplikace je zdarma).

V Postmanu si můžete snadno připravit celý cílový request, spustit ho a vidět i pěkně naformátovanou odezvu na takový požadavek. Na obrázku nahoře jde vidět request do Pushoveru.

Postman toho umí mnohem víc než jen odesílat požadavky. Můžete si takové požadavky ukládat a zpětně se k nim vracet, dělat si kolekce příkazů, umožňuje dokonce automatické testovaní nad takovými požadavaky, atd. Já sám tam mám takto uložené všechny možné API requesty, takže když se po čase potřebuji k něčemu vrátit, hned vidím, jak mají požadavky vypadat.

Toto je špatně, v adrese nesmí být celá URL adresa, ale jen protokol + adresa serveru.

V okamžiku, kdy máte dotaz otestovaný přes Postmana, přichází ta pekelná část. Rozchodit to v Loxone. A tak vytvoříte virtuální výstup a začnete zadávat. První pokus, do kolonky pojmenované “adresa” zadáte url adresu a ono se nic neděje. Loxone žádnou chybu neukáže, ale ani se nic nestane. Co teď? (konkrétní důvod této chyby je, že v kolonce adresa nesmí být adresa. Logické ne? Musí tam být jen protokol + server, tzn správně je https://api.pushover.net).

 

Toto je ukázka, jak ne. V adrese nesmí být koncové lomítko!

Předtím, než ukážu, jak přesně takovéhle chyby ladit, ukážu ještě jednu chybu, se kterou Vás Loxone obšťastní. Pokud totiž zadáte adresu serveru zakončenou lomítkem, můžete se jít také zahrabat. Opět se nic nestane, nebude nic fungovat, ale žádnou chybu Vám Loxone neukáže. Jediná správná varianta je správně je https://api.pushover.net

 

Tak, ale teď už k samotnému lazení. Snažíte se volat službu, u které nevíte, jestli jede správně, a snažíte se to volat z Loxone, kde víte, že bude určitě nějaký zádrhel. Řešením je použít službu, která Vám přesně ukáže, co (a jestli vůbec) z Loxone něco odchází. Tou službou je například https://requestbin.com/.

Na hlavní stránce si založte “Request bin”, pro který dostanete unikatání URL adresu, například https://enn9obu94ky0s.x.pipedream.net. Na tuto adresu nyní můžete nasměrovat výstup z Loxone a kdykoli něco Loxone odešle, vy uvidíte přesný tvar toho, co z něj vylezlo 🙂

Tím si jednak otestujete, že vlastně vůbec něco leze (což v případě prvních dvou ukázek špatně zadané url se vůbec neděje) a dále si ověříte, zda posílá data tak, jak jste si mysleli (což se také dost často neděje). Ukažme si to na příkladu.

Zajímalo Vás například někdy, co znamená “HTTP rozšíření při zapnutí” ? Nebo si nejste jisti tím, co znamená “Instrukce při zapnutí”? Nebo jak se odešle “Post příkaz při zapnutí”? Tak přesně k tomu je dobrý RequestBin (protože od specialistů z Loxone se v aplikaci ani dokumentaci nic kloudného nedozvíte).

Zde pak vidíte, co vlastně takto nakonfigurovaný výstup odešle. Najednou je jasné, že “HTTP rozšíření” jsou vlastně HTTP hlavičky (by je asi zabilo, kdyby to tam napsali), že POST příkaz se odešle jako POST s “náhodným” Content-type text/xml a že instrukce je URI adresa připojená za protokol+server zadaný u virtuálního výstupu. Zde máte zároveň také možnost zjistit, že například instrukce pro zapnutí MUSÍ začínat lomítkem, jinak se opět nic neodešle (protože pro Loxone je problém toto lomítko v případe absence doplnit).

Bohužel, v této ukázce pak vězí ještě jeden zakopaný pes. A tím je právě Content-Type. Ačkoli Vám Loxone umožní zadávat hlavičky, pokud zadáte Content-Type:application/json, tak ho Loxone vesele ignoruje. To Vás ale bohužel přivádí do míst, kam ani slunce nesvítí.

Ačkoli je do “HTTP rozšíření při zapnutí” aka HTTP hlaviček zadán “Content-type:application/json” a ačkoli je v POST příkazu zadán validní JSON příkaz, ta zelená věc zvaná Miniserver to odešle jako text/xml. No není to roztomilé? Je to roztomilé. A díky tomu Vám Pushover prostě fungovat nebude. A dost se divím, že člověk ještě nedostane od Pushoveru BAN za to, že je idiot :).

Ale tím stále nekončíme. Po hodině googlování a testování jsem najednou zjistil, že jsem schopný z Loxone odeslat příkaz v požadovaném content-type. Ptáte se jak? Nejprve se vrátím k curl. Jak vidíte, toto je odeslání stejného požadavku, o které se také snažím z Loxone. A jak vidíte, Content-type je zadán přesně tak, jako v Loxone. A jak můžete vidět na dalším obrázku, pokud to odešlu z curl, do RequestBINu to přijde v pořádku.

A nyní, screenshot z Loxone, kde už najednou příkaz zázračně funguje:

Vidíte ten markantní rozdíl? Vidíte, proč to najednou funguje? Že ne? Nedivím se Vám :). Důvodem je MEZERA za dvoujtečkou u content-type. Ačkoli nic takového dle standardu není potřeba a ačkoli to ani curl, ani postman nevyžaduje, u Loxonu to potřeba je. Pokud uděláte za dvoutečku mezeru, najednou Vám do RequestBinu začne chodit toto:

To je pecka, co? Přišel jsem na to jen díky uplné náhodě, že jsem testoval jiný problém, a tím je poslání více hlaviček. Narazil jsem na loxforu na tuto ukázku,

HTTP extensions for ON : host: 192.168.0.226\r\nContent-Type: application/json
HTTP POST command for ON : {“on”: true}
HTTP method for ON : PUT
same for OFF…

kde psali, že jim to jede a tak jsem začal zjišťovat, kde je zakopán pes. A to mě přivedlo k té mezeře. Takže, content type se odesílá, data se odesílají, jenže Pushover stále nejede.

Všechno už sedí 1:1 mezi Loxone i Postmanem a Loxone stále neodesílá. Je teda čas na hardcore-debugging. Přesunuju se i s notebookem do technické a připojuju se do fyzicky izolované sítě s Loxone (a Quidem). Pomoci Loxconfigu -> Diagnostika -> Debug-Info -> Síť – začínám odchytávat síťové pakety.

Výsledek na sebe nenechá dlouho čekat. Po odeslání požadavku na https://api.pushover.net z nějakého záhadného důvodu nefunguje SSL. A ačkoli na RequestBinu je rovněž https a tam to jede, takže asi zase nějaká specialita Loxonu. Naštěstí má pushover i http verzi, která sice není extra bezpečná (protože lze odchytit co za zprávy na ni budu posílat), ale na obecné notifikace typu “dveře otevřeny” mi to nevadí. Pokud by to byl problém, řešením by bylo přeposílat to přes NodeRED, který by přijal text a udělal z něj https Pushover notifikaci. Uvidíme, možná v příštím článku ukážu oba postupy.

A to je pro dnešek vše. Krásné čtyři hodiny strávené s Loxone jen proto, že nemají pořádné logy, neumějí pořádně notifikovat chyby a neumí si poradit ani se základní validací parametrů v Loxconfigu. Bomba.

GSM modul (2. díl – hlasové volání)

GSM modul (2. díl – hlasové volání)

Toto je druhá část návodu na GSM modul postavený na Raspberry Pi a komunikující s Loxonem přes UDP. První část najdete zde:

GSM modul (1. díl – integrace do Loxone přes UDP)

Co Loxone naučíme v tomto druhém dílu

  • mluvit do telefonu (přes text-to-speech)
  • vlastně získáme  plnohodnotnou alternativu ke službě “Loxone Caller”
  • naučíme Loxone navíc i zvednout příchozí hovor a mluvit do telefonu

Co to neumí

  • poslouchat v telefonu (speech-to-text)
  • přemýšlet

Pokud byste chtěli něco, co vás umí poslouchat a reagovat na vaše požadavky, pořiďte si Siri, Alexu, Google Home nebo nějakého jiného robota s AI. Na integraci těchto robotů do Node Red a do Loxonu už taky nějaké nástroje existují.

Jaký hardware budete potřebovat

Viz minulý díl.

Jaký software budete potřebovat

Node Red

Někteří už tak jako tak máte Node Red nainstalovaný. Ostatní si dovolím odkázat na existující návody:

Ffmpeg a Mp3wrap

Mp3 wrap budeme potřebovat na slepování MP3 souborů s hlasovou zprávou, které Node Red stahuje z Googlu. Ffmpeg je potřeba na samotné přehrání MP3 souboru se zprávou do GSM modulu.

sudo apt-get install ffmpeg mp3wrap

Stačí nainstalovat, není potřeba nic nastavovat, o vše se postará Node Red.

Nody

Až budete mít nainstalovaný Node Red, spusťte si jej v prohlížeči  ( <IP_adresa>:1880 ) a přes Manage Palette (menu vpravo nahoře) si doinstalujte tyto nody:

  • node-red-contrib-function-npm
  • node-red-contrib-string
  • node-red-contrib-traffic
  • node-red-contrib-fs-ops
  • node-red-contrib-google-tts
  • node-red-contrib-loop-processing
  • node-red-contrib-md5

Flow

Až budete mít doinstalované Nody, vložte si do Node Red tento flow, ve kterém je celý program na řízení GSM modulu:

[{"id":"886ce1dc.59db3","type":"subflow","name":"Google TTS > MP3 file","info":"","category":"","in":[{"x":80,"y":120,"wires":[{"id":"d81f9a91.5459"},{"id":"858f31a3.8e3bf"}]}],"out":[{"x":2040,"y":340,"wires":[{"id":"390be0c6.c36c98","port":0}]},{"x":2040,"y":80,"wires":[{"id":"240cfaf8.ac223e","port":0},{"id":"3f0e743e.5e8794","port":2}]}],"outputLabels":["OUTPUT","ERROR","CACHEFULL"]},{"id":"5a4d9876.aad888","type":"md5","z":"886ce1dc.59db3","name":"","fieldToHash":"message","fieldTypeToHash":"msg","hashField":"hash","hashFieldType":"msg","x":670,"y":120,"wires":[["5f6402d0.9460fc"]]},{"id":"8c914dff.1f5e7","type":"http request","z":"886ce1dc.59db3","name":"","method":"GET","ret":"bin","url":"","tls":"","x":430,"y":340,"wires":[["61b277f6.633a98"]]},{"id":"61b277f6.633a98","type":"file","z":"886ce1dc.59db3","name":"","filename":"","appendNewline":false,"createDir":false,"overwriteFile":"true","x":570,"y":340,"wires":[["bc5fa4b5.ac6a88"]]},{"id":"7bf55fc2.c15c88","type":"fs-ops-delete","z":"886ce1dc.59db3","name":"","path":"","pathType":"str","filename":"filename","filenameType":"msg","x":750,"y":520,"wires":[["50ee971a.15b1b8"]]},{"id":"6a9d2543.e7f9e4","type":"fs-ops-access","z":"886ce1dc.59db3","name":"","path":"","pathType":"str","filename":"filename","filenameType":"msg","read":true,"write":false,"throwerror":false,"x":930,"y":120,"wires":[["45f43985.39b5e8"],["90e5f25d.6e7698"]]},{"id":"5f6402d0.9460fc","type":"function","z":"886ce1dc.59db3","name":".mp3","func":"msg.filename=global.get('directory')+\"\\/\"+msg.hash+\".mp3\";\nmsg.filearray = [];\nmsg.payload = msg.message;\nreturn msg;","outputs":1,"noerr":0,"x":790,"y":120,"wires":[["6a9d2543.e7f9e4"]]},{"id":"f68676ec.779608","type":"switch","z":"886ce1dc.59db3","name":"","property":"url","propertyType":"msg","rules":[{"t":"istype","v":"array","vt":"array"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":270,"y":340,"wires":[["99b91fec.690b18"],["8c914dff.1f5e7"]]},{"id":"5e8d3d23.9fdda4","type":"array-loop","z":"886ce1dc.59db3","name":"","key":"index","keyType":"msg","reset":true,"resetValue":"value-null","array":"urlarray","arrayType":"msg","x":330,"y":400,"wires":[["bc5fa4b5.ac6a88"],["2fd238a1.1492b8"]]},{"id":"f052ae05.bf6938","type":"http request","z":"886ce1dc.59db3","name":"","method":"GET","ret":"bin","url":"","tls":"","x":270,"y":460,"wires":[["20c0aef9.9cfda2"]]},{"id":"20c0aef9.9cfda2","type":"file","z":"886ce1dc.59db3","name":"","filename":"","appendNewline":false,"createDir":false,"overwriteFile":"true","x":410,"y":460,"wires":[["5e8d3d23.9fdda4"]]},{"id":"2fd238a1.1492b8","type":"function","z":"886ce1dc.59db3","name":".mp3","func":"msg.filename = global.get('directory')+\"\\/\"+msg.hash+\"[\"+msg.index.toString().padStart(2,\"0\")+\"].mp3\";\nmsg.filearray[msg.index] = msg.filename;\nmsg.url = msg.urlarray[msg.index];\nreturn msg;","outputs":1,"noerr":0,"x":130,"y":460,"wires":[["f052ae05.bf6938"]]},{"id":"99b91fec.690b18","type":"change","z":"886ce1dc.59db3","name":"","rules":[{"t":"move","p":"url","pt":"msg","to":"urlarray","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":160,"y":400,"wires":[["5e8d3d23.9fdda4"]]},{"id":"bc5fa4b5.ac6a88","type":"template","z":"886ce1dc.59db3","name":"mp3wrap command","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"mp3wrap ~/{{{global.directory}}}/{{{hash}}}.mp3 ~/{{{global.directory}}}/{{{hash}}}*mp3 ~/{{{global.directory}}}/silence.mp3","x":570,"y":400,"wires":[["1b9000e9.05a44f"]]},{"id":"1b9000e9.05a44f","type":"exec","z":"886ce1dc.59db3","command":"","addpay":true,"append":"","useSpawn":"false","timer":"","oldrc":false,"name":"mp3wrap","x":760,"y":400,"wires":[["50ee971a.15b1b8"],[],[]]},{"id":"50ee971a.15b1b8","type":"array-loop","z":"886ce1dc.59db3","name":"","key":"index","keyType":"msg","reset":false,"resetValue":"value-null","array":"filearray","arrayType":"msg","x":670,"y":460,"wires":[["d864b18d.9f796"],["794b0628.ddbbd"]]},{"id":"794b0628.ddbbd","type":"function","z":"886ce1dc.59db3","name":".mp3","func":"msg.filename = msg.filearray[msg.index];\nreturn msg;","outputs":1,"noerr":0,"x":610,"y":520,"wires":[["7bf55fc2.c15c88"]]},{"id":"7a2e347a.0044dc","type":"fs-ops-move","z":"886ce1dc.59db3","name":"","sourcePath":".","sourcePathType":"str","sourceFilename":"oldfilename","sourceFilenameType":"msg","destPath":".","destPathType":"str","destFilename":"filename","destFilenameType":"msg","link":false,"x":980,"y":460,"wires":[["45f43985.39b5e8"]]},{"id":"d864b18d.9f796","type":"function","z":"886ce1dc.59db3","name":"rename","func":"msg.oldfilename = global.get('directory')+\"\\/\"+msg.hash+\"_MP3WRAP.mp3\";\nmsg.filename = global.get('directory')+\"\\/\"+msg.hash+\".mp3\";\nreturn msg;","outputs":1,"noerr":0,"x":840,"y":460,"wires":[["7a2e347a.0044dc"]]},{"id":"45f43985.39b5e8","type":"template","z":"886ce1dc.59db3","name":"command","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"du -s {{{global.directory}}} | cut -f1 | tr -d '\\n'","x":1180,"y":300,"wires":[["7cfa1f4d.f07aa8"]]},{"id":"7cfa1f4d.f07aa8","type":"exec","z":"886ce1dc.59db3","command":"","addpay":true,"append":"","useSpawn":"false","timer":"","oldrc":false,"name":"du","x":1310,"y":300,"wires":[["390be0c6.c36c98"],[],[]]},{"id":"390be0c6.c36c98","type":"function","z":"886ce1dc.59db3","name":"Cache size","func":"msg.cachesize = parseInt(msg.payload);\nif (msg.cachesize >= global.get('cachelimit')) {\n msg.cachefull = true;\n} else {\n msg.cachefull = false;\n}\nglobal.set('cachefull', msg.cachefull);\nreturn msg;","outputs":1,"noerr":0,"x":1490,"y":300,"wires":[["9cfafe99.3843b8"]]},{"id":"240cfaf8.ac223e","type":"trigger","z":"886ce1dc.59db3","op1":"","op2":"","op1type":"nul","op2type":"payl","duration":"10","extend":false,"units":"s","reset":"RESET","bytopic":"all","name":"","x":1650,"y":20,"wires":[[]]},{"id":"9cfafe99.3843b8","type":"change","z":"886ce1dc.59db3","name":"RESET","rules":[{"t":"set","p":"payload","pt":"msg","to":"RESET","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1640,"y":60,"wires":[["240cfaf8.ac223e"]]},{"id":"40cb3ff0.01a9a","type":"switch","z":"886ce1dc.59db3","name":"","property":"number","propertyType":"msg","rules":[{"t":"eq","v":"test","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":410,"y":120,"wires":[["dfae422e.5139"],["ca4f9c14.129e38"]]},{"id":"919d3cc0.047968","type":"http request","z":"886ce1dc.59db3","name":"","method":"GET","ret":"bin","url":"","tls":"","x":610,"y":80,"wires":[["b0c5a4c2.b70148"]]},{"id":"6ab5e1b2.31064","type":"exec","z":"886ce1dc.59db3","command":"","addpay":true,"append":"","useSpawn":"true","timer":"","oldrc":false,"name":"ffmpeg","x":1550,"y":120,"wires":[[],[],["3f0e743e.5e8794","7f448bb.85f7bf4"]]},{"id":"857bdd0b.40af2","type":"template","z":"886ce1dc.59db3","name":"test command","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"ffmpeg -i {{{filename}}} -f s16le -acodec pcm_s16le -ac 1 -ar 8000 -","x":1380,"y":120,"wires":[["6ab5e1b2.31064"]]},{"id":"3f0e743e.5e8794","type":"switch","z":"886ce1dc.59db3","name":"","property":"payload.code","propertyType":"msg","rules":[{"t":"eq","v":"255","vt":"num"},{"t":"eq","v":"0","vt":"num"},{"t":"else"}],"checkall":"true","repair":false,"outputs":3,"x":1710,"y":120,"wires":[["9cfafe99.3843b8"],["9cfafe99.3843b8"],[]]},{"id":"b0c5a4c2.b70148","type":"file","z":"886ce1dc.59db3","name":"","filename":"","appendNewline":false,"createDir":false,"overwriteFile":"true","x":750,"y":80,"wires":[["97dd19e0.2b6e48"]]},{"id":"97dd19e0.2b6e48","type":"template","z":"886ce1dc.59db3","name":"command","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"du -s {{{global.directory}}} | cut -f1 | tr -d '\\n'","x":880,"y":80,"wires":[["566b4bed.0ff224"]]},{"id":"566b4bed.0ff224","type":"exec","z":"886ce1dc.59db3","command":"","addpay":true,"append":"","useSpawn":"false","timer":"","oldrc":false,"name":"du","x":1010,"y":80,"wires":[["5b0a765c.b69d48"],[],[]]},{"id":"90e5f25d.6e7698","type":"google-tts","z":"886ce1dc.59db3","name":"","inputField":"payload","inputFieldType":"msg","outputField":"url","outputFieldType":"msg","languageField":"language","languageFieldType":"global","speedField":"3","speedFieldType":"num","x":140,"y":340,"wires":[["f68676ec.779608"]]},{"id":"dfae422e.5139","type":"google-tts","z":"886ce1dc.59db3","name":"","inputField":"test","inputFieldType":"str","outputField":"url","outputFieldType":"msg","languageField":"language","languageFieldType":"global","speedField":"3","speedFieldType":"num","x":340,"y":80,"wires":[["2aad085e.7fd5"]]},{"id":"2aad085e.7fd5","type":"function","z":"886ce1dc.59db3","name":".mp3","func":"msg.filename=global.get('directory')+\"\\/test.mp3\";\nmsg.filearray = [];\nmsg.payload = msg.message;\nreturn msg;","outputs":1,"noerr":0,"x":470,"y":80,"wires":[["919d3cc0.047968"]]},{"id":"7f448bb.85f7bf4","type":"fs-ops-delete","z":"886ce1dc.59db3","name":"","path":"","pathType":"str","filename":"filename","filenameType":"msg","x":1690,"y":200,"wires":[[]]},{"id":"d81f9a91.5459","type":"change","z":"886ce1dc.59db3","name":"","rules":[],"action":"","property":"","from":"","to":"","reg":false,"x":320,"y":40,"wires":[["240cfaf8.ac223e"]]},{"id":"858f31a3.8e3bf","type":"fs-ops-mkdir","z":"886ce1dc.59db3","name":"","path":"","pathType":"str","dirname":"directory","dirnameType":"global","mode":"755","fullpath":"","fullpathType":"msg","x":260,"y":120,"wires":[["40cb3ff0.01a9a"]]},{"id":"5b0a765c.b69d48","type":"function","z":"886ce1dc.59db3","name":"Cache size","func":"msg.cachesize = parseInt(msg.payload);\nif (msg.cachesize >= global.get('cachelimit')) {\n msg.cachefull = true;\n} else {\n msg.cachefull = false;\n}\nglobal.set('cachefull', msg.cachefull);\nreturn msg;","outputs":1,"noerr":0,"x":1190,"y":140,"wires":[["857bdd0b.40af2"]]},{"id":"ca4f9c14.129e38","type":"fs-ops-access","z":"886ce1dc.59db3","name":"","path":"directory","pathType":"global","filename":"silence.mp3","filenameType":"str","read":true,"write":false,"throwerror":false,"x":250,"y":180,"wires":[["5a4d9876.aad888"],["af657cfb.1864c8"]]},{"id":"37ed82b.1fe1afe","type":"exec","z":"886ce1dc.59db3","command":"","addpay":true,"append":"","useSpawn":"false","timer":"","oldrc":false,"name":"ffmpeg","x":630,"y":180,"wires":[["5a4d9876.aad888"],[],[]]},{"id":"af657cfb.1864c8","type":"template","z":"886ce1dc.59db3","name":"silence command","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"ffmpeg -f lavfi -i anullsrc=r=24000:cl=mono -t 1 -b:a 32k -acodec libmp3lame {{{global.directory}}}/silence.mp3","x":470,"y":180,"wires":[["37ed82b.1fe1afe"]]},{"id":"4bfe1136.14a238","type":"subflow","name":"/dev/ttyUSB2","info":"","category":"","in":[],"out":[{"x":300,"y":100,"wires":[{"id":"9d86fe98.cc1438","port":0}]}],"icon":"node-red/serial.png"},{"id":"9d86fe98.cc1438","type":"serial in","z":"4bfe1136.14a238","name":"/dev/ttyUSB2","serial":"d5b55732.e05ae","x":150,"y":100,"wires":[[]]},{"id":"b0491a09.bf712","type":"subflow","name":"/dev/ttyUSB2","info":"","category":"","in":[{"x":120,"y":120,"wires":[{"id":"41d6ed41.2b20e4"}]}],"out":[{"x":420,"y":120,"wires":[{"id":"41d6ed41.2b20e4","port":0}]}],"icon":"node-red/serial.png"},{"id":"41d6ed41.2b20e4","type":"serial request","z":"b0491a09.bf712","name":"/dev/ttyUSB2","serial":"d5b55732.e05ae","x":270,"y":120,"wires":[[]]},{"id":"d5b55732.e05ae","type":"serial-port","z":"","serialport":"/dev/ttyUSB2","serialbaud":"115200","databits":"8","parity":"none","stopbits":"1","waitfor":"","newline":"\\r","bin":"false","out":"char","addchar":"","responsetimeout":"10000"},{"id":"71bc8c93.144294","type":"subflow","name":"Dial","info":"","category":"","in":[{"x":80,"y":140,"wires":[{"id":"e7c4da10.763418"}]}],"out":[{"x":1600,"y":140,"wires":[{"id":"66a57697.062ea8","port":0}]},{"x":1600,"y":200,"wires":[{"id":"6022d2ba.83418c","port":0}]},{"x":1600,"y":280,"wires":[{"id":"b77ad44c.c2c0d","port":0}]},{"x":1600,"y":360,"wires":[{"id":"674e4f99.0a778","port":0}]}],"outputLabels":["CONNECTED","ENDED","TIMEOUT","ERROR"]},{"id":"3e699fb2.881938","type":"function","z":"71bc8c93.144294","name":"ATD Call","func":"var num = msg.number;\nvar at_cmd = \"ATD\"+num+\"\\;\"; \n\nmsg.payload=at_cmd+\"\\r\\n\";\n//msg.payload.msg =msg.payload.message;\n\nreturn msg;","outputs":"1","noerr":0,"x":220,"y":200,"wires":[["d3a75c82.2f53f"]]},{"id":"db123915.c17c9","type":"switch","z":"71bc8c93.144294","name":"","property":"payload","propertyType":"msg","rules":[{"t":"cont","v":"0","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":550,"y":200,"wires":[["9646d1a9.79bb98","2dbb462a.6c8d9a"],["674e4f99.0a778"]]},{"id":"d3a75c82.2f53f","type":"subflow:b0491a09.bf712","z":"71bc8c93.144294","name":"","x":390,"y":200,"wires":[["db123915.c17c9"]]},{"id":"732e9c21.c8beec","type":"subflow:4bfe1136.14a238","z":"71bc8c93.144294","name":"","x":390,"y":240,"wires":[["647332d1.87bb94"]]},{"id":"647332d1.87bb94","type":"switch","z":"71bc8c93.144294","name":"","property":"payload","propertyType":"msg","rules":[{"t":"cont","v":"CONN","vt":"str"},{"t":"cont","v":"CEND","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":550,"y":240,"wires":[["abeb6474.f259b8"],["abeb6474.f259b8"]]},{"id":"e308fb3c.93ded8","type":"comment","z":"71bc8c93.144294","name":"Set timeout","info":"Set timeout for outgoing voice call.","x":730,"y":40,"wires":[]},{"id":"d951f290.fcc66","type":"switch","z":"71bc8c93.144294","name":"","property":"payload","propertyType":"msg","rules":[{"t":"cont","v":"CONN","vt":"str"},{"t":"cont","v":"CEND","vt":"str"},{"t":"cont","v":"TIMEOUT","vt":"str"}],"checkall":"true","repair":false,"outputs":3,"x":1070,"y":200,"wires":[["66a57697.062ea8"],["6022d2ba.83418c"],["72d51b37.e6912c"]]},{"id":"9646d1a9.79bb98","type":"trigger","z":"71bc8c93.144294","op1":"","op2":"","op1type":"nul","op2type":"payl","duration":"60","extend":true,"units":"s","reset":"BLOCK","bytopic":"all","name":"","x":730,"y":80,"wires":[["993c16c0.a74d98"]]},{"id":"64babea9.a8bbb","type":"traffic","z":"71bc8c93.144294","name":"","property_allow":"payload","filter_allow":"ATD","ignore_case_allow":false,"negate_allow":false,"send_allow":false,"property_stop":"payload","filter_stop":"BLOCK","ignore_case_stop":false,"negate_stop":false,"send_stop":false,"default_start":false,"differ":false,"x":910,"y":200,"wires":[["d951f290.fcc66","2114d454.1300d4"]]},{"id":"2114d454.1300d4","type":"change","z":"71bc8c93.144294","name":"BLOCK","rules":[{"t":"set","p":"payload","pt":"msg","to":"BLOCK","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":900,"y":120,"wires":[["64babea9.a8bbb","9646d1a9.79bb98"]]},{"id":"e7c4da10.763418","type":"function","z":"71bc8c93.144294","name":"AT+CHUP Hang-up","func":"var at_cmd = \"AT+CHUP\"; \n\nmsg.payload=at_cmd+\"\\r\\n\";\n\nreturn msg;","outputs":"1","noerr":0,"x":230,"y":140,"wires":[["4eba397a.82d2"]]},{"id":"4eba397a.82d2","type":"subflow:b0491a09.bf712","z":"71bc8c93.144294","name":"","x":410,"y":140,"wires":[["7e37ad0b.9f100c"]]},{"id":"7e37ad0b.9f100c","type":"switch","z":"71bc8c93.144294","name":"","property":"payload","propertyType":"msg","rules":[{"t":"cont","v":"0","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":550,"y":140,"wires":[["3e699fb2.881938"],["674e4f99.0a778"]]},{"id":"72d51b37.e6912c","type":"function","z":"71bc8c93.144294","name":"AT+CHUP Hang-up","func":"var at_cmd = \"AT+CHUP\"; \n\nmsg.payload=at_cmd+\"\\r\\n\";\n\nreturn msg;","outputs":"1","noerr":0,"x":1150,"y":280,"wires":[["766abd9b.345eec"]]},{"id":"766abd9b.345eec","type":"subflow:b0491a09.bf712","z":"71bc8c93.144294","name":"","x":1330,"y":280,"wires":[["b77ad44c.c2c0d"]]},{"id":"993c16c0.a74d98","type":"change","z":"71bc8c93.144294","name":"TIMEOUT","rules":[{"t":"set","p":"payload","pt":"msg","to":"TIMEOUT","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":880,"y":80,"wires":[["64babea9.a8bbb"]]},{"id":"674e4f99.0a778","type":"change","z":"71bc8c93.144294","name":"ERROR","rules":[{"t":"set","p":"payload","pt":"msg","to":"ERROR","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1280,"y":360,"wires":[[]]},{"id":"66a57697.062ea8","type":"change","z":"71bc8c93.144294","name":"CONNECTED","rules":[{"t":"set","p":"payload","pt":"msg","to":"CONNECTED","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1240,"y":160,"wires":[[]]},{"id":"6022d2ba.83418c","type":"change","z":"71bc8c93.144294","name":"ENDED","rules":[{"t":"set","p":"payload","pt":"msg","to":"ENDED","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1220,"y":200,"wires":[[]]},{"id":"b77ad44c.c2c0d","type":"change","z":"71bc8c93.144294","name":"TIMEOUT","rules":[{"t":"set","p":"payload","pt":"msg","to":"TIMEOUT","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1480,"y":280,"wires":[[]]},{"id":"abeb6474.f259b8","type":"change","z":"71bc8c93.144294","name":"","rules":[{"t":"set","p":"number","pt":"msg","to":"number","tot":"global"},{"t":"set","p":"message","pt":"msg","to":"message","tot":"global"},{"t":"set","p":"filename","pt":"msg","to":"filename","tot":"global"},{"t":"set","p":"cachefull","pt":"msg","to":"cachefull","tot":"global"}],"action":"","property":"","from":"","to":"","reg":false,"x":700,"y":240,"wires":[["64babea9.a8bbb"]]},{"id":"2dbb462a.6c8d9a","type":"change","z":"71bc8c93.144294","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"ATD","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":700,"y":200,"wires":[["64babea9.a8bbb"]]},{"id":"824c0efa.febe88","type":"tab","label":"GSM","disabled":false,"info":""},{"id":"24dd16ad.6162e2","type":"function","z":"824c0efa.febe88","name":"AT+CMGS= Send 'To' Number","func":"var num = msg.number;\nvar at_cmd = \"AT+CMGS=\\\"\"+num+\"\\\"\"; \nmsg.message = msg.payload;\nmsg.payload = at_cmd+\"\\r\";\n\nreturn msg;","outputs":"1","noerr":0,"x":730,"y":1320,"wires":[["d25cb01.3629e5"]]},{"id":"dc690b21.cef218","type":"function","z":"824c0efa.febe88","name":"Send Message","func":"var sms_msg = msg.message;\n\nmsg.payload=sms_msg+\"\\x1A\";\n\nreturn msg;","outputs":1,"noerr":0,"x":1260,"y":1320,"wires":[["d725d3a4.818d08"]]},{"id":"d9ab3334.716ae8","type":"debug","z":"824c0efa.febe88","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":570,"y":1780,"wires":[]},{"id":"4915182e.2a126","type":"switch","z":"824c0efa.febe88","name":"","property":"payload","propertyType":"msg","rules":[{"t":"cont","v":"+CMTI:","vt":"str"},{"t":"cont","v":"+CMGR","vt":"str"},{"t":"cont","v":"+CUSD:","vt":"str"},{"t":"cont","v":"+CLIP:","vt":"str"},{"t":"cont","v":"+CSQ:","vt":"str"},{"t":"cont","v":"^RSSI:","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":7,"x":370,"y":1620,"wires":[["f9ba8001.448898"],["ddc88293.0f8f1"],["3649d387.302404"],["95452788.7329f"],["85bb3839.2ab35"],["c66b5319.7d04c8"],["d9ab3334.716ae8"]]},{"id":"3e4786aa.427c62","type":"udp in","z":"824c0efa.febe88","name":"","iface":"","port":"10007","ipv":"udp4","multicast":"false","group":"","datatype":"utf8","x":200,"y":420,"wires":[["8f7f53c2.158d4","30cc3e8.6376bc2"]]},{"id":"d69c3271.e96e9","type":"switch","z":"824c0efa.febe88","name":"check identifier","property":"identifier","propertyType":"msg","rules":[{"t":"eq","v":"gsm","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":340,"y":1240,"wires":[["a3651d4a.f019c"]]},{"id":"7d95427f.3d4204","type":"switch","z":"824c0efa.febe88","name":"command","property":"command","propertyType":"msg","rules":[{"t":"eq","v":"sms","vt":"str"},{"t":"eq","v":"hangup","vt":"str"},{"t":"eq","v":"callout","vt":"str"},{"t":"eq","v":"ussdout","vt":"str"},{"t":"eq","v":"voice","vt":"str"}],"checkall":"true","repair":false,"outputs":5,"x":140,"y":1340,"wires":[["4dd7532f.8d221c"],["b37db75b.ce506"],["91fb032a.6eb018"],["c870ecb1.472a9"],["c0d5c8b7.f1722"]]},{"id":"b37db75b.ce506","type":"function","z":"824c0efa.febe88","name":"AT+CHUP Hang-up","func":"var at_cmd = \"AT+CHUP\"; \n\nmsg.payload=at_cmd+\"\\r\\n\";\n\nreturn msg;","outputs":"1","noerr":0,"x":430,"y":1360,"wires":[["d725d3a4.818d08"]]},{"id":"3649d387.302404","type":"string","z":"824c0efa.febe88","name":"+CUSD USSD","methods":[{"name":"between","params":[{"type":"str","value":"+CUSD: 2,\""},{"type":"str","value":"\","}]}],"prop":"payload","propout":"payload","object":"msg","objectout":"msg","x":580,"y":1620,"wires":[["a5bc5961.eba5d"]]},{"id":"f1664278.0b0278","type":"string","z":"824c0efa.febe88","name":"rem timestamp","methods":[{"name":"delLeftMost","params":[{"type":"str","value":";"}]},{"name":"delLeftMost","params":[{"type":"str","value":";"}]}],"prop":"payload","propout":"payload","object":"msg","objectout":"msg","x":220,"y":1160,"wires":[["279fab20.7b4fcc"]]},{"id":"279fab20.7b4fcc","type":"string","z":"824c0efa.febe88","name":"parse identifier","methods":[{"name":"getLeftMost","params":[{"type":"str","value":" "}]}],"prop":"payload","propout":"identifier","object":"msg","objectout":"msg","x":400,"y":1160,"wires":[["6cf08c5b.0bffbc"]]},{"id":"6cf08c5b.0bffbc","type":"string","z":"824c0efa.febe88","name":"parse command","methods":[{"name":"delLeftMost","params":[{"type":"str","value":" "}]},{"name":"getLeftMost","params":[{"type":"str","value":" "}]}],"prop":"payload","propout":"command","object":"msg","objectout":"msg","x":580,"y":1160,"wires":[["d6055438.98b948"]]},{"id":"d6055438.98b948","type":"string","z":"824c0efa.febe88","name":"parse number","methods":[{"name":"delLeftMost","params":[{"type":"str","value":" "}]},{"name":"delLeftMost","params":[{"type":"str","value":" "}]},{"name":"getLeftMost","params":[{"type":"str","value":" "}]}],"prop":"payload","propout":"number","object":"msg","objectout":"msg","x":760,"y":1160,"wires":[["576530c4.03073"]]},{"id":"576530c4.03073","type":"string","z":"824c0efa.febe88","name":"parse message","methods":[{"name":"delLeftMost","params":[{"type":"str","value":" "}]},{"name":"delLeftMost","params":[{"type":"str","value":" "}]},{"name":"delLeftMost","params":[{"type":"str","value":" "}]}],"prop":"payload","propout":"message","object":"msg","objectout":"msg","x":940,"y":1160,"wires":[["573ef3aa.abc7e4"]]},{"id":"95452788.7329f","type":"string","z":"824c0efa.febe88","name":"+CLIP","methods":[{"name":"between","params":[{"type":"str","value":"+CLIP: \""},{"type":"str","value":"\",145,\"\",,\"\",0"}]}],"prop":"payload","propout":"payload","object":"msg","objectout":"msg","x":550,"y":1660,"wires":[["aa762e4.9bf9ad"]]},{"id":"dfb5d7ce.6e4b88","type":"function","z":"824c0efa.febe88","name":"gsm callin","func":"msg.payload=\"gsm callin \"+msg.payload;\n\nreturn msg;","outputs":"1","noerr":0,"x":940,"y":1660,"wires":[["c83ab0fb.791018"]]},{"id":"c870ecb1.472a9","type":"function","z":"824c0efa.febe88","name":"AT+CUSD Send USSD","func":"var num = msg.number;\nvar at_cmd = \"AT+CUSD=1,\\\"\"+num+\"\\\",15\"; \n\nmsg.payload=at_cmd+\"\\r\\n\";\n\nreturn msg;","outputs":"1","noerr":0,"x":410,"y":1480,"wires":[["d725d3a4.818d08"]]},{"id":"a5bc5961.eba5d","type":"function","z":"824c0efa.febe88","name":"gsm ussdin","func":"msg.payload=\"gsm ussdin \"+msg.payload;\nreturn msg;","outputs":1,"noerr":0,"x":970,"y":1620,"wires":[["c83ab0fb.791018"]]},{"id":"5fe323bf.de6ac4","type":"comment","z":"824c0efa.febe88","name":"Settings: UDP IP and ports","info":"","x":190,"y":360,"wires":[]},{"id":"aa762e4.9bf9ad","type":"string","z":"824c0efa.febe88","name":"rem +countrycode","methods":[{"name":"chompLeft","params":[{"type":"global","value":"pluscountrycode"}]}],"prop":"payload","propout":"payload","object":"msg","objectout":"msg","x":730,"y":1660,"wires":[["dfb5d7ce.6e4b88"]]},{"id":"1559b72e.806601","type":"function","z":"824c0efa.febe88","name":"gsm signal","func":"msg.payload=\"gsm signal \"+msg.payload;\n\nreturn msg;","outputs":"1","noerr":0,"x":730,"y":1700,"wires":[["c83ab0fb.791018"]]},{"id":"85bb3839.2ab35","type":"string","z":"824c0efa.febe88","name":"+CSQ","methods":[{"name":"getRightMost","params":[{"type":"str","value":"+CSQ: "}]}],"prop":"payload","propout":"payload","object":"msg","objectout":"msg","x":550,"y":1700,"wires":[["1559b72e.806601"]]},{"id":"c66b5319.7d04c8","type":"string","z":"824c0efa.febe88","name":"^RSSI","methods":[{"name":"getRightMost","params":[{"type":"str","value":"^RSSI: "}]}],"prop":"payload","propout":"payload","object":"msg","objectout":"msg","x":550,"y":1740,"wires":[["1559b72e.806601"]]},{"id":"f9ba8001.448898","type":"string","z":"824c0efa.febe88","name":"+CMTI","methods":[{"name":"getRightMost","params":[{"type":"str","value":"\","}]}],"prop":"payload","propout":"msgindex","object":"msg","objectout":"flow","x":570,"y":1540,"wires":[["9682ab88.8f09"]]},{"id":"9682ab88.8f09","type":"function","z":"824c0efa.febe88","name":"AT+CMGR Read message","func":"var at_cmd = \"AT+CMGR=\"; \n\nmsg.payload=at_cmd+flow.get('msgindex')+\"\\r\\n\";\n\nreturn msg;","outputs":"1","noerr":0,"x":780,"y":1540,"wires":[["d725d3a4.818d08"]]},{"id":"575e1145.d8c04","type":"comment","z":"824c0efa.febe88","name":"Comment on AT+CNMI","info":"AT+CNMI=<mode>,<mt>,<bm>,<ds>,<bfr>\n\n<mode>=2 Buffer unsolicited result codes in case the serial link is busy and flush them to the serial after reservation. Otherwise forward them directly to the serial.\n\n<mt>=1 If SMS-DELIVER is stored, indication of the memory location is routed to the serial using the following unsolicited result code \n+CMTI: <memr>,<index>\n\n<bm>=0 Cell Broadcast Messages are not sent to the serial.\n\n<ds>=2 If SMS-STATUS-REPORT is stored, then the following unsolicited result code is sent to serial:\n+CDSI: <memr>,<index>\n\n<bfr>=0 Buffer of unsolicited result codes defined within this command is flushed to the serial.\n","x":860,"y":1080,"wires":[]},{"id":"fbce1dff.050fb8","type":"inject","z":"824c0efa.febe88","name":"Initial setup","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":true,"onceDelay":0.1,"x":150,"y":780,"wires":[["492a4fce.e7aa5","9771e036.e0e2a","8dd7ff72.2c0bc","fc07a7be.931878","7d3fae8a.b12dc8"]]},{"id":"7b9bbf8.ae5144","type":"change","z":"824c0efa.febe88","name":"AT+CLIP=1 (Enable Calling Line Identification Presentation)","rules":[{"t":"set","p":"payload","pt":"msg","to":"AT+CLIP=1","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":760,"y":840,"wires":[["f21c6d2c.3bc378"]]},{"id":"d53a257.c3c1e58","type":"change","z":"824c0efa.febe88","name":"AT+CMGF=1 (Enable SMS Text Mode)","rules":[{"t":"set","p":"payload","pt":"msg","to":"AT+CMGF=1","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":690,"y":880,"wires":[["f21c6d2c.3bc378"]]},{"id":"392cc8f.dd1bcb8","type":"change","z":"824c0efa.febe88","name":"AT+CSCS=\"GSM\" (Set character set to GSM)","rules":[{"t":"set","p":"payload","pt":"msg","to":"AT+CSCS=\"GSM\"","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":720,"y":920,"wires":[["f21c6d2c.3bc378"]]},{"id":"c8b642e9.b27388","type":"change","z":"824c0efa.febe88","name":"AT+CPMS=\"SM\",\"SM\",\"SM\" (Select Message Storage SIM)","rules":[{"t":"set","p":"payload","pt":"msg","to":"AT+CPMS=\"SM\",\"SM\",\"SM\"","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":760,"y":960,"wires":[["f21c6d2c.3bc378"]]},{"id":"e51a384.fbb8548","type":"change","z":"824c0efa.febe88","name":"AT+CNMI=2,1,0,2,0 (New Message Indications to serial)","rules":[{"t":"set","p":"payload","pt":"msg","to":"AT+CNMI=2,1,0,2,0","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":750,"y":1040,"wires":[["f21c6d2c.3bc378"]]},{"id":"f21c6d2c.3bc378","type":"function","z":"824c0efa.febe88","name":"Add Newline","func":"msg.payload = msg.payload + \"\\r\\n\";\nreturn msg;","outputs":1,"noerr":0,"x":1230,"y":860,"wires":[["4e5f56b2.fe7948"]]},{"id":"e4ddbe42.8ed0d","type":"change","z":"824c0efa.febe88","name":"AT^USSDMODE=0 (Only for Huawei modems: enable encode/decode USSD)","rules":[{"t":"set","p":"payload","pt":"msg","to":"AT^USSDMODE=0","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":810,"y":800,"wires":[["f21c6d2c.3bc378"]]},{"id":"4e808758.6bcbe8","type":"traffic","z":"824c0efa.febe88","name":"+CMGR:","property_allow":"payload","filter_allow":"CMGR:","ignore_case_allow":false,"negate_allow":false,"send_allow":true,"property_stop":"payload","filter_stop":"^.*\\n0\\r","ignore_case_stop":false,"negate_stop":false,"send_stop":false,"default_start":false,"differ":false,"x":320,"y":1860,"wires":[["5fd3ae4b.3e4468"]]},{"id":"4c478826.a5b1f8","type":"join","z":"824c0efa.febe88","name":"","mode":"custom","build":"string","property":"payload","propertyType":"msg","key":"topic","joiner":"","joinerType":"str","accumulate":false,"timeout":"1","count":"2","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":1250,"y":1840,"wires":[["5e004dc9.7ac8c4"]]},{"id":"690fdfcf.c6c568","type":"switch","z":"824c0efa.febe88","name":"","property":"payload","propertyType":"msg","rules":[{"t":"cont","v":"+CMGR: ","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":630,"y":1860,"wires":[["36150823.7d4c3"],["cfcc2b3e.1257b"]]},{"id":"36150823.7d4c3","type":"string","z":"824c0efa.febe88","name":"parse num","methods":[{"name":"between","params":[{"type":"str","value":"READ\",\""},{"type":"str","value":"\""}]}],"prop":"payload","propout":"payload","object":"msg","objectout":"msg","x":790,"y":1840,"wires":[["acca8ac0.82d12"]]},{"id":"d732975a.2eeab8","type":"lower-case","z":"824c0efa.febe88","name":"","x":1030,"y":1900,"wires":[["4c478826.a5b1f8"]]},{"id":"cfcc2b3e.1257b","type":"function-npm","z":"824c0efa.febe88","name":"remove-accents-diacritics","func":"const removeAccents = require('remove-accents-diacritics');\n// import removeAccents from 'remove-accents-diacritics';\n \nmsg.payload = removeAccents.remove(msg.payload);\n\nreturn msg;","outputs":1,"noerr":0,"x":830,"y":1900,"wires":[["d732975a.2eeab8"]]},{"id":"acca8ac0.82d12","type":"string","z":"824c0efa.febe88","name":"rem +countrycode","methods":[{"name":"chompLeft","params":[{"type":"global","value":"pluscountrycode"}]}],"prop":"payload","propout":"payload","object":"msg","objectout":"msg","x":970,"y":1840,"wires":[["6f0577a7.47f8f8"]]},{"id":"6f0577a7.47f8f8","type":"change","z":"824c0efa.febe88","name":"move","rules":[{"t":"move","p":"payload","pt":"msg","to":"topic","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1130,"y":1840,"wires":[["4c478826.a5b1f8"]]},{"id":"5fd3ae4b.3e4468","type":"string","z":"824c0efa.febe88","name":"trim whitespace","methods":[{"name":"trim","params":[]}],"prop":"payload","propout":"payload","object":"msg","objectout":"msg","x":480,"y":1860,"wires":[["690fdfcf.c6c568"]]},{"id":"5e004dc9.7ac8c4","type":"function","z":"824c0efa.febe88","name":"gsm <command>","func":"var outputMsgs = [];\nvar words = msg.payload.split(\" \");\nfor (var w in words) {\n outputMsgs.push({payload:\"gsm \"+words[w]+\" \"+msg.topic});\n}\nreturn [ outputMsgs ];","outputs":1,"noerr":0,"x":1050,"y":1780,"wires":[["dfa38d25.8e3c88"]]},{"id":"dfa38d25.8e3c88","type":"delay","z":"824c0efa.febe88","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":1230,"y":1780,"wires":[["c83ab0fb.791018"]]},{"id":"a3651d4a.f019c","type":"string","z":"824c0efa.febe88","name":"trim whitespace","methods":[{"name":"trim","params":[]}],"prop":"message","propout":"message","object":"msg","objectout":"msg","x":520,"y":1240,"wires":[["bbaa0320.24bc68"]]},{"id":"ddc88293.0f8f1","type":"function","z":"824c0efa.febe88","name":"AT+CMGD Delete message","func":"var at_cmd = \"AT+CMGD=\"; \n\nmsg.payload=at_cmd+flow.get('msgindex')+\"\\r\\n\";\n\nreturn msg;","outputs":"1","noerr":0,"x":780,"y":1580,"wires":[["b32d96a8.ee73a8"]]},{"id":"b32d96a8.ee73a8","type":"delay","z":"824c0efa.febe88","name":"","pauseType":"delay","timeout":"1","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":980,"y":1580,"wires":[["d725d3a4.818d08"]]},{"id":"573ef3aa.abc7e4","type":"switch","z":"824c0efa.febe88","name":"check number","property":"number","propertyType":"msg","rules":[{"t":"neq","v":"0","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":160,"y":1240,"wires":[["d69c3271.e96e9"]]},{"id":"21823ac5.8a6b9e","type":"change","z":"824c0efa.febe88","name":"AT^CVOICE=0 (Enable Voice)","rules":[{"t":"set","p":"payload","pt":"msg","to":"AT^CVOICE=0","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":670,"y":1000,"wires":[["f21c6d2c.3bc378"]]},{"id":"c0d5c8b7.f1722","type":"link out","z":"824c0efa.febe88","name":"voice out","links":["202ce488.41afac"],"x":215,"y":1440,"wires":[]},{"id":"a7dc0b77.96d208","type":"inject","z":"824c0efa.febe88","name":"AT (Check Serial Port)","topic":"","payload":"AT","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":"","x":440,"y":2580,"wires":[["1490260b.143aba"]]},{"id":"3ba2751f.412612","type":"inject","z":"824c0efa.febe88","name":"AT+CGMI (Manufacturer Info)","topic":"","payload":"AT+CGMI","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":"","x":460,"y":2620,"wires":[["1490260b.143aba"]]},{"id":"627536b1.3fcb78","type":"inject","z":"824c0efa.febe88","name":"AT+CGMM (Model Number)","topic":"","payload":"AT+CGMM","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":"","x":460,"y":2660,"wires":[["1490260b.143aba"]]},{"id":"d503df61.563938","type":"inject","z":"824c0efa.febe88","name":"AT+CGMR (Software Version)","topic":"","payload":"AT+CGMR","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":"","x":460,"y":2700,"wires":[["1490260b.143aba"]]},{"id":"7c9485d6.e2155c","type":"inject","z":"824c0efa.febe88","name":"AT+CSQ (Signal Strength)","topic":"","payload":"AT+CSQ","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":"","x":450,"y":2740,"wires":[["1490260b.143aba"]]},{"id":"f78e064d.df95e","type":"inject","z":"824c0efa.febe88","name":"AT+CREG? (Registration Status)","topic":"","payload":"AT+CREG?","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":"","x":470,"y":2780,"wires":[["1490260b.143aba"]]},{"id":"9071075f.b6a4b","type":"inject","z":"824c0efa.febe88","name":"AT+CGACT? (Connection Status)","topic":"","payload":"AT+CGACT?","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":"","x":470,"y":2820,"wires":[["1490260b.143aba"]]},{"id":"733bc254.cc1214","type":"inject","z":"824c0efa.febe88","name":"AT+COPS? (Operator Info)","topic":"","payload":"AT+COPS?","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":"","x":450,"y":2860,"wires":[["1490260b.143aba"]]},{"id":"9232c2d4.5537a","type":"inject","z":"824c0efa.febe88","name":"AT+CGDCONT? (Connection Profiles)","topic":"","payload":"AT+CGDCONT?","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":"","x":490,"y":2900,"wires":[["1490260b.143aba"]]},{"id":"1490260b.143aba","type":"function","z":"824c0efa.febe88","name":"Add Newline","func":"msg.payload = msg.payload + \"\\r\\n\";\nreturn msg;","outputs":1,"noerr":0,"x":950,"y":2720,"wires":[["a4879e70.37ffb8"]]},{"id":"38da53f3.6b4c54","type":"inject","z":"824c0efa.febe88","name":"AT+CMGL=\"ALL\" (List all messages)","topic":"","payload":"AT+CMGL=\"ALL\"","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":"","x":480,"y":3000,"wires":[["1490260b.143aba"]]},{"id":"800a16f8.3de9d","type":"inject","z":"824c0efa.febe88","name":"AT+CMGD=1,4 (Delete all messages)","topic":"","payload":"AT+CMGD=1,4","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":"","x":490,"y":3040,"wires":[["1490260b.143aba"]]},{"id":"536b9465.84bc1c","type":"comment","z":"824c0efa.febe88","name":"Useful commands","info":"Other useful commands not implemented in the main flow.","x":190,"y":2580,"wires":[]},{"id":"6773314.398d65","type":"inject","z":"824c0efa.febe88","name":"AT^CVOICE? (Audio coding)","topic":"","payload":"AT^CVOICE?","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":460,"y":3080,"wires":[["1490260b.143aba"]]},{"id":"202ce488.41afac","type":"link in","z":"824c0efa.febe88","name":"voice in","links":["c0d5c8b7.f1722"],"x":115,"y":2020,"wires":[["ed669c66.1fdf68"]]},{"id":"e52aa524.b7cc8","type":"link in","z":"824c0efa.febe88","name":"UDP (in)","links":["30cc3e8.6376bc2","47a3a759.2e6ad","f777bb22.3ceeb","2cda8177.042ece"],"x":95,"y":1160,"wires":[["f1664278.0b0278"]]},{"id":"5968071f.7ef108","type":"exec","z":"824c0efa.febe88","command":"killall ffmpeg","addpay":false,"append":"","useSpawn":"false","timer":"","oldrc":false,"name":"","x":550,"y":2480,"wires":[[],[],[]]},{"id":"4830a54e.1e784c","type":"inject","z":"824c0efa.febe88","name":"start","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":true,"onceDelay":0.1,"x":390,"y":2480,"wires":[["5968071f.7ef108"]]},{"id":"492a4fce.e7aa5","type":"change","z":"824c0efa.febe88","name":"ATE0 (Disable Command Echo)","rules":[{"t":"set","p":"payload","pt":"msg","to":"ATE0","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":670,"y":760,"wires":[["f21c6d2c.3bc378"]]},{"id":"df424b8c.25669","type":"function","z":"824c0efa.febe88","name":"ATA (Pick up call)","func":"var at_cmd = \"ATA\"; \n\nmsg.payload=at_cmd+\"\\r\\n\";\n\nreturn msg;","outputs":1,"noerr":0,"x":330,"y":2220,"wires":[["e2c0e664.541f3"]]},{"id":"5fb5737e.641d2c","type":"function","z":"824c0efa.febe88","name":"AT^DDSETEX=2","func":"var at_cmd = \"AT^DDSETEX=2\"; \n\nmsg.payload=at_cmd+\"\\r\\n\";\n\nreturn msg;","outputs":1,"noerr":0,"x":870,"y":2220,"wires":[["c704952c.4eb54"]]},{"id":"aff017e.0d8c0e8","type":"subflow:71bc8c93.144294","z":"824c0efa.febe88","name":"","x":290,"y":2280,"wires":[["51924960.40ede8"],["b2349a57.c06c18"],["b2349a57.c06c18"],["b2349a57.c06c18"]]},{"id":"91fb032a.6eb018","type":"subflow:71bc8c93.144294","z":"824c0efa.febe88","name":"","x":350,"y":1420,"wires":[["b37db75b.ce506"],[],[],[]]},{"id":"51cbff3.20c0e8","type":"function","z":"824c0efa.febe88","name":"AT+CLCC (Check incomming calls)","func":"var at_cmd = \"AT+CLCC\"; \n\nmsg.payload=at_cmd+\"\\r\\n\";\n\nreturn msg;","outputs":1,"noerr":0,"x":440,"y":2160,"wires":[["797e27be.e8fb3"]]},{"id":"9545a969.fa92a","type":"string","z":"824c0efa.febe88","name":"parse num","methods":[{"name":"between","params":[{"type":"str","value":"1,1,4,0,0,\""},{"type":"str","value":"\""}]}],"prop":"payload","propout":"incoming","object":"msg","objectout":"msg","x":830,"y":2160,"wires":[["9aafbebe.b4b48"]]},{"id":"9aafbebe.b4b48","type":"string","z":"824c0efa.febe88","name":"rem countrycode","methods":[{"name":"chompLeft","params":[{"type":"global","value":"countrycode"}]}],"prop":"incoming","propout":"incoming","object":"msg","objectout":"msg","x":1010,"y":2160,"wires":[["4e9a7417.8c6854"]]},{"id":"4e9a7417.8c6854","type":"switch","z":"824c0efa.febe88","name":"","property":"number","propertyType":"msg","rules":[{"t":"eq","v":"incoming","vt":"msg"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":150,"y":2220,"wires":[["df424b8c.25669"],["aff017e.0d8c0e8"]]},{"id":"4c1ce00e.dbdbf8","type":"switch","z":"824c0efa.febe88","name":"","property":"payload","propertyType":"msg","rules":[{"t":"cont","v":"^CEND","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":390,"y":2440,"wires":[["5968071f.7ef108"]]},{"id":"9771e036.e0e2a","type":"change","z":"824c0efa.febe88","name":"Change audio cache directory (inside HOME) and its limit (in kB)","rules":[{"t":"set","p":"cachelimit","pt":"global","to":"10240","tot":"num"},{"t":"set","p":"directory","pt":"global","to":"audiocache","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":330,"y":620,"wires":[[]]},{"id":"8dd7ff72.2c0bc","type":"change","z":"824c0efa.febe88","name":"Change TTS language and country code (with and without +)","rules":[{"t":"set","p":"language","pt":"global","to":"cs-CZ","tot":"str"},{"t":"set","p":"countrycode","pt":"global","to":"420","tot":"str"},{"t":"set","p":"pluscountrycode","pt":"global","to":"+420","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":320,"y":660,"wires":[[]]},{"id":"ed669c66.1fdf68","type":"subflow:886ce1dc.59db3","z":"824c0efa.febe88","name":"","x":350,"y":2020,"wires":[["63caf751.4192b","5c2d28b0.92212"],["da7c760.7ca0b08","cd5aa741.f242f8","e7ec47bf.365df8","5c2d28b0.92212"]]},{"id":"da7c760.7ca0b08","type":"change","z":"824c0efa.febe88","name":"gsm voice error","rules":[{"t":"set","p":"payload","pt":"msg","to":"gsm voice error","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":920,"y":1980,"wires":[["c83ab0fb.791018"]]},{"id":"5867e387.4e1ffc","type":"change","z":"824c0efa.febe88","name":"gsm voice cachefull","rules":[{"t":"set","p":"payload","pt":"msg","to":"gsm voice cachefull","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":930,"y":2020,"wires":[["c83ab0fb.791018"]]},{"id":"e7ec47bf.365df8","type":"function","z":"824c0efa.febe88","name":"gsm sms","func":"msg.payload=\"gsm sms \"+msg.number+\" \"+msg.message;\n\nreturn msg;","outputs":"1","noerr":0,"x":920,"y":2100,"wires":[["47a3a759.2e6ad"]]},{"id":"9d53728d.404bc8","type":"function","z":"824c0efa.febe88","name":"gsm callout","func":"msg.payload=\"gsm callout \"+msg.number;\n\nreturn msg;","outputs":"1","noerr":0,"x":930,"y":2060,"wires":[["47a3a759.2e6ad"]]},{"id":"cd5aa741.f242f8","type":"delay","z":"824c0efa.febe88","name":"","pauseType":"delay","timeout":"1","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":780,"y":2060,"wires":[["9d53728d.404bc8"]]},{"id":"47a3a759.2e6ad","type":"link out","z":"824c0efa.febe88","name":"Flow beginning","links":["e52aa524.b7cc8"],"x":1135,"y":2080,"wires":[]},{"id":"d41001a1.877208","type":"exec","z":"824c0efa.febe88","command":"","addpay":true,"append":"","useSpawn":"true","timer":"","oldrc":false,"name":"ffmpeg","x":630,"y":2380,"wires":[["c946946d.28e458"],[],["ba03adce.3a50c8","d0bded62.379ca8","6779d865.3684c"]]},{"id":"ba03adce.3a50c8","type":"switch","z":"824c0efa.febe88","name":"","property":"payload.code","propertyType":"msg","rules":[{"t":"eq","v":"255","vt":"num"},{"t":"eq","v":"0","vt":"num"},{"t":"else"}],"checkall":"true","repair":false,"outputs":3,"x":790,"y":2400,"wires":[[],[],["e64c4ba5.bc0be8","48357e80.52348","ff6788b7.5fff88"]]},{"id":"e64c4ba5.bc0be8","type":"function","z":"824c0efa.febe88","name":"AT+CHUP Hang-up","func":"var at_cmd = \"AT+CHUP\"; \n\nmsg.payload=at_cmd+\"\\r\\n\";\n\nreturn msg;","outputs":"1","noerr":0,"x":970,"y":2460,"wires":[["2d1108ed.1dc718"]]},{"id":"bbaa0320.24bc68","type":"change","z":"824c0efa.febe88","name":"","rules":[{"t":"set","p":"number","pt":"global","to":"number","tot":"msg"},{"t":"set","p":"message","pt":"global","to":"message","tot":"msg"},{"t":"set","p":"command","pt":"global","to":"command","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":700,"y":1240,"wires":[["7d95427f.3d4204"]]},{"id":"63caf751.4192b","type":"change","z":"824c0efa.febe88","name":"","rules":[{"t":"set","p":"filename","pt":"global","to":"filename","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":190,"y":2160,"wires":[["51cbff3.20c0e8"]]},{"id":"5c2d28b0.92212","type":"switch","z":"824c0efa.febe88","name":"","property":"cachefull","propertyType":"msg","rules":[{"t":"true"}],"checkall":"true","repair":false,"outputs":1,"x":770,"y":2020,"wires":[["5867e387.4e1ffc"]]},{"id":"d0bded62.379ca8","type":"switch","z":"824c0efa.febe88","name":"","property":"cachefull","propertyType":"msg","rules":[{"t":"true"}],"checkall":"true","repair":false,"outputs":1,"x":810,"y":2300,"wires":[["307e2441.9d8844"]]},{"id":"307e2441.9d8844","type":"fs-ops-delete","z":"824c0efa.febe88","name":"","path":"","pathType":"str","filename":"filename","filenameType":"msg","x":970,"y":2300,"wires":[[]]},{"id":"d725d3a4.818d08","type":"subflow:b0491a09.bf712","z":"824c0efa.febe88","name":"","x":1350,"y":1480,"wires":[[]]},{"id":"7cebcd29.4c418c","type":"delay","z":"824c0efa.febe88","name":"","pauseType":"delay","timeout":"1","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":300,"y":2380,"wires":[["bc82b195.9cc01"]]},{"id":"b2349a57.c06c18","type":"change","z":"824c0efa.febe88","name":"","rules":[],"action":"","property":"","from":"","to":"","reg":false,"x":460,"y":2280,"wires":[["d0bded62.379ca8","e7ec47bf.365df8"]]},{"id":"bc82b195.9cc01","type":"template","z":"824c0efa.febe88","name":"ffmpeg command","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"ffmpeg -re -stream_loop -1 -i {{{filename}}} -f s16le -acodec pcm_s16le -ac 1 -ar 8000 -","x":470,"y":2380,"wires":[["d41001a1.877208","ef8e4a68.107108"]]},{"id":"d4bc1a8e.04af08","type":"serial in","z":"824c0efa.febe88","name":"/dev/ttyUSB1","serial":"b64dd80.eff27a8","x":230,"y":220,"wires":[["92008d02.c0c89"]]},{"id":"fd57ebb8.063668","type":"serial out","z":"824c0efa.febe88","name":"/dev/ttyUSB1","serial":"b64dd80.eff27a8","x":230,"y":160,"wires":[]},{"id":"1e46fb80.0fe955","type":"link in","z":"824c0efa.febe88","name":"/dev/ttyUSB1 (out)","links":["c946946d.28e458"],"x":95,"y":160,"wires":[["fd57ebb8.063668","92008d02.c0c89"]]},{"id":"c946946d.28e458","type":"link out","z":"824c0efa.febe88","name":"/dev/ttyUSB1","links":["1e46fb80.0fe955"],"x":775,"y":2340,"wires":[]},{"id":"a44b6a4f.9ece9","type":"comment","z":"824c0efa.febe88","name":"Settings: Serial ports","info":"","x":170,"y":80,"wires":[]},{"id":"7b1238b6.0537d","type":"debug","z":"824c0efa.febe88","name":"/dev/ttyUSB2","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":570,"y":280,"wires":[]},{"id":"596a306a.a17638","type":"subflow:b0491a09.bf712","z":"824c0efa.febe88","name":"","x":1090,"y":1320,"wires":[["dc690b21.cef218"]]},{"id":"797e27be.e8fb3","type":"subflow:b0491a09.bf712","z":"824c0efa.febe88","name":"","x":670,"y":2160,"wires":[["9545a969.fa92a"]]},{"id":"e2c0e664.541f3","type":"subflow:b0491a09.bf712","z":"824c0efa.febe88","name":"","x":510,"y":2220,"wires":[["51924960.40ede8"]]},{"id":"c704952c.4eb54","type":"subflow:b0491a09.bf712","z":"824c0efa.febe88","name":"","x":1050,"y":2220,"wires":[["7cebcd29.4c418c"]]},{"id":"2d1108ed.1dc718","type":"subflow:b0491a09.bf712","z":"824c0efa.febe88","name":"","x":1150,"y":2460,"wires":[[]]},{"id":"8d35941c.c9336","type":"subflow:b0491a09.bf712","z":"824c0efa.febe88","name":"","x":1550,"y":860,"wires":[[]]},{"id":"c83ab0fb.791018","type":"link out","z":"824c0efa.febe88","name":"UDP (out)","links":["e03bae3b.7d3168"],"x":1495,"y":1780,"wires":[]},{"id":"770dea12.523d94","type":"udp out","z":"824c0efa.febe88","name":"","addr":"192.168.1.77","iface":"","port":"10007","ipv":"udp4","outport":"10002","base64":false,"multicast":"false","x":610,"y":420,"wires":[]},{"id":"e03bae3b.7d3168","type":"link in","z":"824c0efa.febe88","name":"UDP (out)","links":["c83ab0fb.791018","87c4f897.571158"],"x":435,"y":420,"wires":[["770dea12.523d94","8f7f53c2.158d4"]]},{"id":"7a8b776c.658818","type":"inject","z":"824c0efa.febe88","name":"gsm sms 123456789 This is short message.","topic":"","payload":"gsm sms 123456789 This is short message.","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":"","x":310,"y":480,"wires":[["30cc3e8.6376bc2"]]},{"id":"4dd7532f.8d221c","type":"function-npm","z":"824c0efa.febe88","name":"removeAccents","func":"const removeAccents = require('remove-accents-diacritics');\n// import removeAccents from 'remove-accents-diacritics';\n \nmsg.payload = removeAccents.remove(msg.message);\n\nreturn msg;","outputs":1,"noerr":0,"x":380,"y":1320,"wires":[["4d7f3f5a.1f092"]]},{"id":"4d7f3f5a.1f092","type":"split","z":"824c0efa.febe88","name":"","splt":"160","spltType":"len","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":530,"y":1320,"wires":[["24dd16ad.6162e2"]]},{"id":"d25cb01.3629e5","type":"delay","z":"824c0efa.febe88","name":"1 msg/s","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":940,"y":1320,"wires":[["596a306a.a17638"]]},{"id":"8f7f53c2.158d4","type":"debug","z":"824c0efa.febe88","name":"UDP","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":650,"y":480,"wires":[]},{"id":"92008d02.c0c89","type":"debug","z":"824c0efa.febe88","name":"/dev/ttyUSB1","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":290,"y":280,"wires":[]},{"id":"30cc3e8.6376bc2","type":"link out","z":"824c0efa.febe88","name":"UDP (in)","links":["e52aa524.b7cc8"],"x":335,"y":420,"wires":[]},{"id":"4511c4ae.cf160c","type":"comment","z":"824c0efa.febe88","name":"Settings: Global variables","info":"","x":190,"y":560,"wires":[]},{"id":"48357e80.52348","type":"change","z":"824c0efa.febe88","name":"gsm voice error","rules":[{"t":"set","p":"payload","pt":"msg","to":"gsm voice error","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":960,"y":2380,"wires":[["87c4f897.571158"]]},{"id":"87c4f897.571158","type":"link out","z":"824c0efa.febe88","name":"UDP (out)","links":["e03bae3b.7d3168"],"x":1095,"y":2380,"wires":[]},{"id":"ff6788b7.5fff88","type":"function","z":"824c0efa.febe88","name":"gsm sms","func":"msg.payload=\"gsm sms \"+msg.number+\" \"+msg.message;\n\nreturn msg;","outputs":"1","noerr":0,"x":940,"y":2420,"wires":[["2cda8177.042ece"]]},{"id":"2cda8177.042ece","type":"link out","z":"824c0efa.febe88","name":"Flow beginning","links":["e52aa524.b7cc8"],"x":1095,"y":2420,"wires":[]},{"id":"ef8e4a68.107108","type":"trigger","z":"824c0efa.febe88","op1":"","op2":"1","op1type":"nul","op2type":"str","duration":"10","extend":true,"units":"min","reset":"reset","bytopic":"all","name":"","x":770,"y":2500,"wires":[["e64c4ba5.bc0be8"]]},{"id":"6779d865.3684c","type":"change","z":"824c0efa.febe88","name":"reset","rules":[{"t":"set","p":"payload","pt":"msg","to":"reset","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":750,"y":2440,"wires":[["ef8e4a68.107108"]]},{"id":"2f9ff422.7b518c","type":"subflow:b0491a09.bf712","z":"824c0efa.febe88","name":"","x":510,"y":160,"wires":[[]]},{"id":"7d3fae8a.b12dc8","type":"delay","z":"824c0efa.febe88","name":"","pauseType":"delay","timeout":"1","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":360,"y":840,"wires":[["7b9bbf8.ae5144","e4ddbe42.8ed0d","d53a257.c3c1e58","392cc8f.dd1bcb8","c8b642e9.b27388","21823ac5.8a6b9e","e51a384.fbb8548"]]},{"id":"fc07a7be.931878","type":"change","z":"824c0efa.febe88","name":"ATV0 (Set Limited Response Format)","rules":[{"t":"set","p":"payload","pt":"msg","to":"ATV0","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":690,"y":720,"wires":[["f21c6d2c.3bc378"]]},{"id":"a4879e70.37ffb8","type":"subflow:b0491a09.bf712","z":"824c0efa.febe88","name":"","x":1110,"y":2720,"wires":[[]]},{"id":"c658e45b.aa4e78","type":"inject","z":"824c0efa.febe88","name":"AT (Test serial)","topic":"","payload":"\"AT\\r\\n\"","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":440,"y":100,"wires":[["2f9ff422.7b518c"]]},{"id":"51924960.40ede8","type":"delay","z":"824c0efa.febe88","name":"","pauseType":"delay","timeout":"1","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":700,"y":2220,"wires":[["5fb5737e.641d2c"]]},{"id":"e9b6999b.c9f1a8","type":"subflow:4bfe1136.14a238","z":"824c0efa.febe88","name":"","x":230,"y":2440,"wires":[["4c1ce00e.dbdbf8"]]},{"id":"b828d445.f74b1","type":"subflow:4bfe1136.14a238","z":"824c0efa.febe88","name":"","x":150,"y":1680,"wires":[["4e808758.6bcbe8","7760dd5f.fe8f64"]]},{"id":"92464499.11fc28","type":"subflow:4bfe1136.14a238","z":"824c0efa.febe88","name":"","x":510,"y":220,"wires":[["7b1238b6.0537d"]]},{"id":"7760dd5f.fe8f64","type":"string","z":"824c0efa.febe88","name":"trim whitespace","methods":[{"name":"trim","params":[]}],"prop":"payload","propout":"payload","object":"msg","objectout":"msg","x":200,"y":1620,"wires":[["4915182e.2a126"]]},{"id":"4e5f56b2.fe7948","type":"delay","z":"824c0efa.febe88","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"2","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":1390,"y":860,"wires":[["8d35941c.c9336"]]},{"id":"b64dd80.eff27a8","type":"serial-port","z":"","serialport":"/dev/ttyUSB1","serialbaud":"115200","databits":"8","parity":"none","stopbits":"1","waitfor":"","newline":"32000","bin":"bin","out":"count","addchar":"","responsetimeout":"10000"}]

Flow vložíte jednoduše klávesovou zkratkou Ctrl-I.

Disclaimer: Neumím programovat. Proto na parsování používám všechny ty string nody. Určitě by na to šla použít nějaká funkce, ale nechtělo se mi to učit.

Nastavení nodů

Modem stardardně vytvoří 3 sériové porty (ttyUSB0, ttyUSB1, ttyUSB2). My budeme používat druhý port (ttyUSB1) na audio při hovoru a třetí port (ttyUSB2) na přijímání a odesílání AT příkazů a přijímání SMS. Oba porty se nastavují na začátku. Pozor, ttyUSB2 se nastavuje uvnitř subflow, klikněte na node ttyUSB2 a ještě na “edit flow template” a pak ještě jednou na node ttyUSB2.

Každý port má jiné nastavení komunikace. Je nutné to nastavit správně, jinak audio (ttyUSB1) a odesílání příkazů (ttyUSB2) nebudou fungovat správně.

ttyUSB1 (audio):

ttyUSB2 (příkazy):

 

Sériový port ttyUSB2 (příkazy) můžete otestovat odesláním příkazu AT (viz modrý inject node). V podokně debugu (ikona brouka vpravo nahoře) pak sledujte, jestli jste na příkaz dostali nějakou odpověď. Pokud uvidíte “0”, trefili jste správný port. Technická poznámka: v modemu je zapnutý “limited response format”, proto neuvidíte klasickou odpověď “OK”, ale jenom její číselnou alternativu “0”.

Sériový port ttyUSB1 (audio) si otestujete až při samotném hovoru. Po aktivaci zeleného debug nodu (musíte si ho zapnout) byste při hovoru (vlastně i při samotném vytáčení) měli vidět přehršel čísel (to je samotný zvuk v bufferu).

Dále si musíte nastavit UDP nody. V prvním nodu udp-in si nastavíte místní port, na kterém bude poslouchat Node Red. Mám nastavené, aby Node Red poslouchal na portu 10007. Můžete si to změnit, ale poznamenejte si to.

V druhém nodu udp-out si nastavíte vzdálenou IP adresu Loxonu a vzdálený port, na kterém bude Loxone poslouchat. Mám to nastavené tak, aby Loxone poslouchal na portu 10007. Můžete si to klidně změnit, ale poznamenejte si to, budete to potřebovat při nastavování Loxonu.

Oba UDP nody mám nastavené tak, že Loxone i Node Red poslouchají na stejných portech, ale to samozřejmě není nutné, můžete si vybrat porty odlišné.

Jako poslední si nastavíme globální proměnné. MP3 soubory s audiem se ukládají na úložiště v Raspberry (do domovské složky). V případě potřeby si můžete jméno adresáře upravit (standardně audiocache) a můžete si nastavit maximální velikost této cache (standardně 10MB). Dále si v případě potřeby můžete změnit jazyk převodu TTS a mezinárodní předvolbu pro příchozí a odchozí hovory.

Co ten flow v Node Redu dělá

Flow nejdřív udělá prvotní nastavení modemu. Potom se stará o překlad AT příkazů, kterými se ovládá modem, do podoby user friendly UDP příkazů, kterými komunikuje s Loxonem (tyto UDP příkazy si popíšeme níže). Pro nastavení a provoz GSM modulu vůbec nepotřebujete znát samotné AT příkazy. Pokud byste si chtěli hrát nebo něco testovat, nechal jsem vám úplně dole i nějaké samostatné AT příkazy (viz “useful commands”).

Celý flow je udělaný tak, abyste ho jednou nastavili a potom už na něho nemuseli sahat. Všechno ostatní se bude dělat v Loxonu:

  • Konfigurace autorizovaných telefonních čísel
  • Nastavení příchozích SMS příkazů
  • Obsah odchozích SMS zpráv
  • Obsah odchozích hlasových zpráv
  • Veškerá logika co a jak se bude ovládat atd.

Jediné, co je potřeba v Node Redu hlídat:

  1. Pokud k Raspberry Pi připojíte další USB zařízení, tak se vám pravděpodobně změní sériové porty a budete muset překonfigurovat nody serial-in a serial-out.
  2. Na převod text-to-speech se používá Google. Nepoužíváme ale standardní Google API (to je placené), ale pro převod na řeč využíváme (zneužíváme) webové služby translate.google.com (na tom je postavený node-red-contrib-google-tts). Je to neoficiální oklika, která může přestat fungovat. Původně jsem hledal offline řešení, ale jediné offline řešení pro Linux jsem našel program “festival”. Výsledky byly katastrofální. Tak jsem na TTS zkoušel různá cloudová API. Těm buď chyběla čeština (Amazon, IBM Watson) nebo byla placená (Microsoft a další). Nakonec jsme jako jediné použitelné a neplacené řešení našel Google.

Nastavení v Loxone Config

První sadu příkazů jsem popsal v prvním dílu (https://www.vodnici.net/wiki/gsm-modul-integrace-do-loxone-pres-udp/). Všechny příákazy z prvního dílu (vč. callout) zůstávají funkční. V tomto dílu představím příkazy týkající se hlasového volání.

Node Red z Loxonu přijímá tyto UDP příkazy:

  • gsm voice <volané číslo> <text hlasové zprávy>
  • gsm voice test

Node Red do Loxonu posílá tyto UDP příkazy:

  • gsm voice error
  • gsm voice cachefull

Výstupy z Loxonu

gsm voice <volané číslo> <text hlasové zprávy>

Hlasové volání na uvedené číslo (číslo bez mezinárodní předvolby). Číslo příjemce musí být odděleno z obou stran mezerami. Samotný text hlasové zprávy může obsahovat mezery. Můžete a měli byste používat interpunkci, aby hlasu bylo rozumět. Délka hlasové zprávy není omezena (teoretický limit je 200*999 znaků, místo na disku pro výslednou MP3 s hlasem zprávy a 10 minutový limit pro délku hovoru).

Node Red vytočí volané číslo a pokud to volaný zvedne, tak mu přečte text zprávy. Pokud to típnete (třeba jste zrovna někde na jednání) nebo pokud to nezvednete (timeout pro vyzvánění je stanovený na 1 minutu), tak se nic neděje, Node Red vám pošle text zprávy SMSkou. Z textu původní hlasové zprávy se odstraní interpunkce, zpráva se rozdělí na úseky dlouhé 160 znaků a SMSka (SMSky) se odešle na volané číslo.

Před samotným vytáčením hovoru ještě Node Red kontroluje, jestli mu náhodou to stejné číslo zrovna nevolá v příchozím hovoru. Pokud tam ten příchozí hovor je, tak ho rovnou zvedne a přečte text zprávy (k čemu to je dobré uvidíte níže).

Pro úplnost dodám, že Node Red opakuje hlasovou zprávu ve smyčce, maximální délka hovoru je pro jistotu omezena na 10 minut.

Příklad syntaxe:

gsm voice 123456789 Tvůj barák hoří, zavolej si hasiče!

Na odeslání hlasové zprávy využijeme UDP logger, který jsme si vytvořili pro potřeby odesílání SMS v minulém díle. Vytváření a odesílání hlasového volání je úplně stejné jako vytváření a odesílání SMS (viz příkaz gsm sms <číslo> <zpráva> v prvním díle). Využíváme blok Status napojený na UDP logger, jediný rozdíl je v tom, že v syntaxi příkazu je “voice” místo “sms”. Odchozí hlasové zprávy můžete používat například na alarmy, kdy chcete, aby vám Loxone sám zavolal a řekl vám, co se děje.

Následující příklad je trochu složitější, ukážeme si jak zkombinovat příchozí hovor do Loxonu s hlasovou zprávou z Loxonu:

Takže co tu máme. CALLIN příchozí hovor do Loxonu, dvě autorizovaná čísla. CALLIN funguje jako “virtuální tlačítko”, které pošle impuls při každém zazvonění telefonu. Viz předchozí díl.

Blok Vícenásobný stisk znamená, že pokud telefon típnu po prvním nebo po druhém nebo po třetím zvonění, tak se mi rozsvítí světlo na chodbě (otevře se brána nebo co je vám libo). Pokud ale hovor do Loxonu netípnu, tak se aktivuje blok Status. Blok status do Node Redu odešle požadavek na hlasovou zprávu pro telefonní číslo, které zrovna Loxonu volá. Node Red zjistí, že se obě čísla shodují a ten příchozí hovor rovnou zvedne a přečte vám text hlasové zprávy. Toto řešení můžete používat na rychlé zjištění stavu nějakého čidla nebo celkového stavu domu. Výhoda je jasná: voláte vy, platíte vy a šetříte kredit na SIMkartě v Loxonu. Takže si v tomto případě můžete dovolit dlouhé hlasové zprávy.

Status blok “VOICE stav topení” je napojený na UDP logger a stará se o samotné odeslání hlasové zprávy. Na vstupy můžete přivést digitální signál (vstup AI2 se stavem topení), analogový signál (AI1 obsahující číslo, na které se má zavolat) i textová data (na vstup AI3 je přiveden textový výstup statusu “Teplota ZZ”). Na vstup AI4 je přiveden spouštěč. Nastavení bloku VOICE stav topení:

a samozřejme napojení na UDP logger. Můžeme využít ten, co jsme si vytvořili pro potřeby odesílání SMS:

 

Nastavení bloku Status “Teplota ZZ” je jednoduché. Tento blok není napojený na UDP logger, není na něj přivedený žádný spouštěč. Zrušte jeho zobrazení ve vizualizaci a jako text můžete dát třeba toto. Nebojte se desetinných čísel, Google TTS je zvládá s přehledem.

Ten druhý blok Status jsem tam dal jenom jako ukázku řetězení. Můžete si takto poskládat opravdu dlouhou zprávu obsahující všechny důležité stavy a čidla v domě.

gsm voice test

Jednoduchý příkaz, který otestuje dostupnost služby Google TTS (důvody proč je dobré ji testovat jsem uvedl výše). Pokud je možné stáhnout z Googlu přehratelnou MP3, nic se nestane. Pokud dojde k chybě, pošle vám Node Red UDP zprávu “gsm voice error”.

V Loxone Config si vytvořte Virtuální výstup příkazu, kde si nastavíte

Instrukce při zapnutí

gsm voice test

 

Vstupy do Loxonu

Opět standardně použijeme Virtuální UDP vstupy. Asi bych zase doporučil ty čachry s validací, abychom dostali “digitální impuls” (viz předchozí díl).

gsm voice error

Může znamenat buď:

  • chybu při převodu textu na řeč Google TTS (nedostupný internet, zablokovaný Google, nepřehratelná mptrojka…)
  • chybu při přehrávání MP3 souboru do telefonu přes ffmpeg

V každém případě je na volané číslo text původní hlasové zprávy v SMSce.

gsm voice cachefull

Cache pro audio soubory dosáhla limitu, který jste si nastavili na začátku. Pár slov k tomu, proč tam ta cache je a jak funguje. Cache je tam jako pojistka proti nedostupnosti internetu a Google TTS. Při prvním požadavku na převod TTS se odešle požadavek na Google, odkud se pak stáhne výsledná MP3 s hlasem. Pokud budete později potřebovat hlasovou zprávu  se zcela identickým obsahem, tak se žádný požadavek na Google neposílá, ale vezme se MP3 soubor z cache. Doporučuju proto, aby důležité zprávy alarmu neobsahovaly žádné dynamické proměnné (“Tvůj barák hoří, zavolej si hasiče!”). Poté, co si je nastavíte v Loxonu, tak si je na zkoušku aktivujte, aby se hlas zprávy uložil do cache. Pak budete mít jistotu, že se hlasové volání v budoucnu realizuje i když nepůjde internet nebo nebude fungovat Google TTS. Zprávy s dynamickými proměnnými (“Teplota v zimní zahradě je <v1.1> stupňů Celsia.”) se budou při každé změně proměnné stahovat znova. Takže pokud budete často používat různé hlasové zprávy s dynamickými proměnnými, budete potřebovat větší cache. Pro úplnost dodávám, že Google posílá hlas ve MP3, mono, 32 kBit/s. Takže těch 10MB cache by mělo vystačit na cca 42 minut hlasových zpráv.

Co se stane, když cache dosáhne limitu? Jednak se odešle UDP zpráva (gsm voice cachefull), zároveň se smaže aktuální hlasová zpráva, která překročení limitu zavinila. Samozřejmě až poté, co byla přehrána do telefonu. Staré zprávy (to jsou ty důležité, které jste si převedli do audia jako první) se nemažou.

GSM modul (1. díl – integrace do Loxone přes UDP)

GSM modul (1. díl – integrace do Loxone přes UDP)

K čemu to je

GSM modul se hodí jako alternativní kanál pro komunikaci s Loxonem, zvláště v těchto případech:

  • Loxone nemá připojení k internetu (např. někde na chatě apod.).
  • Nechce se Vám (neumíte) nakonfigurovat bezpečné internetové připojení k Loxonu (přes VPN).
  • Chcete se rychle dozvědět o kritických událostech v domě (alarm, stisknutí tísňového tlačítka apod). Nechcete se spoléhat na nějaké push notifikace a chtěli byste, aby vám Loxone rovnou poslal SMS nebo zavolal.
  • Chcete rychle něco ovládat mobilem (příjezdová brána) přes prozvonění a nechce se vám listovat v Loxone app.
  • Chcete umožnit třetím osobám, které nemají v telefonu Loxone aplikaci, aby něco na dálku ovládali (přes zavolání nebo přes SMS)
  • Nechce se vám platit za službu Loxone Caller…

Samozřejmě provoz GSM modulu není (na rozdíl od internetu) zadarmo, platíte za SMSky. Vybírejte tarif s levnými SMS a dlouhou dobou platnosti kreditu.

Co to umí

  • odesílat a přijímat hovory
  • odesílat a přijímat SMS zprávy
  • odesílat a přijímat USSD kódy

Výhodou oproti dedikovaným GSM modulům (např. od alarmů) je to, že nejste nijak omezeni co se týče počtu vstupů a výstupů. Můžete (zavoláním a SMS zprávami) ovládat všechno, co máte v domě. A stejně tak máte neomezené možnosti toho, co vám bude Loxone posílat SMS zprávami. Při odesílání SMS z Loxonu nejste omezeni několika předem nadefinovanými SMS zprávami, ale můžete si obsah SMS dynamicky skládat v samotném Loxonu. Detailní možnosti použití viz níže.

Co to neumí:

  • Neumí to mluvit. Takže vám to sice zavolá, ale pokud hovor zvednete, tak vám to nic neřekne. Možná by to šlo zprovoznit pomocí nějakého text-to-speech nodu pro Node Red, ale nezkoušel jsem to, protože jsem nedokázal zjistit, jak poslat audio stream přes USB/Serial do GSM modulu.
  • Neumí to tónovou volbu (zadání číselného kódu přes klávesnici telefonu). Nezkoušel jsem to a ani nevím, co by k tomu bylo potřeba.

 

Jaký hardware budete potřebovat

  • Raspberry Pi nebo jakýkoliv jiný stroj, na kterém dokážete zprovoznit Node Red a který má jeden volný USB port. V mém případě se jedná o Unipi Neuron (PLC postavené na Raspberry). Neuron má řadu neduhů, občas tady na něj svorně nadáváme, ale tady si neodpustím menší reklamu. Je to super mít v rozvaděči krabičku, která zvládne běh Node Red a která má 4 USB porty, ke kterým se v Node Red snadno dostanete přes serial-in a serial-out.
  • USB modem s podporou hlasového volání. V mém případě Huawei E353 (https://www.aliexpress.com/item/HiLink-Huawei-E353-3G-usb-Modem-3g-dongle-3g-usb-stick-3g-huawei-modem-pk-e3131/32773440894.html ). Myslím, že pokud sáhnete po jakémkoliv modemu od Huawei, tak bude mít podporu hlasu.

Toť vše. Z hlediska HW není potřeba nic řešit. Vložíte SIM do modemu (karta nesmí mít nastavený PIN kód). Píchnete modem do USB a je to.

Poznámka pod čarou 1: Zkoušel jsem postavit celé řešení na Arduinu (Arduino Uno + ethernet shield + GSM shield). Přes Arduino se dá udělat přeposílání AT příkazů přes UDP, ale nikdy na Arduinu neuděláte parsování AT příkazů jako to mám v Node Red. A nakonec stejně narazíte na problém s napájením “žravého” GSM shieldu… Jak říká Jára Cimrman: Tudy ne, přátelé. Tudy cesta nevede.

Poznámka pod čarou 2: Pokud byste náhodou chtěli mít víc GSM modulů, není problém. Stačí upravit Node Red flow třeba tak, aby každý GSM modul poslouchal na jiném UDP portu.

 

Jaký software budete potřebovat

Přesunuto do druhého dílu.

 

Nastavení v Loxone Config

Node Red z Loxonu přijímá tyto UDP příkazy:

  • gsm callout <volané číslo>
  • gsm hangup
  • gsm sms <číslo příjemce> <text zprávy>
  • gsm ussdout <USSD kód>

Node Red do Loxonu posílá tyto UDP příkazy:

  • gsm callin <volající číslo>
  • gsm signal <síla signálu v dBm>
  • gsm <sms příkaz> <číslo odesílatele>
  • gsm ussdin <text USSD zprávy>

Probereme si nastavení Loxone Config po jednotlivých UDP příkazech.

 

Virtuální výstupy

Jako první si udělejte nový Virtuální výstup, kde si nastavíme

Adresa

/dev/udp/192.168.1.78/10007

kde 10007 je port, na kterém poslouchá Node Red.

 

gsm callout <volané číslo>

UDP příkaz na zavolání čísla. Pokud by v té době už nějaký příchozí nebo odchozí hovor probíhal, tak se nejdřív ten starý hovor položí a teprve pak začné nové odchozí vyzvánění. Hovor bude vyzvánět maximálně 1 minutu a potom se sám položí (nastaveno v Node Red). Volané číslo je v devítimístném formátu bez předčíslí.

V Loxone Config si vytvořte Virtuální výstup příkazu, kde si nastavíte

Instrukce při zapnutí

gsm callout <v>

Doporučuji vytvořit si konstantu, do které si uložíte vaše telefonní číslo (9-místný formát bez předčíslí). Bude se vám to hodit. Na jednoduché otestování můžete použít blok analogové paměti. Spouštět ho můžete fyzickým nebo virtuálním tlačítkem – níže uvedený příklad je vlastně příkladem tísňového tlačítka. Jak vidíte, na ovládání gsm callout můžete použít impuls. Po uvolnění tlačítka se analogová paměť zresetuje, na Node Red se sice odešle UDP příkaz “gsm callout 0”, ale v reálu se žádná nula nevytočí.

Připomínám, že Loxone (zatím) neumí mluvit. Zavolá vám, ale neřekne vám, proč volá. Takže doporučuju kombinovat gsm callout s odesláním SMS, abyste vědělli, proč vám Loxone volá.

 

gsm hangup

Jednoduchý UDP příkaz bez dalších parametrů. Položí jakýkoliv odchozí či příchozí hovor. Příklad využití: Loxone položí příchozí hovor (viz gsm callin) aby vám potvrdil, že přijal váš požadavek.

V Loxone Config si vytvořte Virtuální výstup příkazu, kde si nastavíte

Instrukce při zapnutí

gsm hangup

 

gsm sms <číslo příjemce> <text zprávy>

Odeslání SMS zprávy na uvedené číslo (opět číslo bez mezinárodní předvolby). Číslo příjemce musí být odděleno z obou stran mezerami. Samotná zpráva může obsahovat mezery. Příklad:

gsm sms 123456789 Ahoj, jak se mas?

Bohužel v Loxone neexistuje žádný “virtuální textový výstup”, takže si musíme pomoct přes UDP logger. V Loxone Config si vytvořte nový Logger, kde si nastavíte

Adresa loggeru

/dev/udp/<IP adresa stroje s Node Redem>/10007

v příkladu níže je 192.168.1.78 adresa mého stroje s Node Redem a 10007 je port, na kterém Node Red poslouchá.

Samotné sestavení textu SMS zprávy uděláme přes blok Status. Tento status nebude vidět ve vizualizaci, takže Vizualizace>Použít>zrušit zaškrtnutí. Blok má celkem 4 analogové vstupy. Na tyto vstupy můžete přivést analogovou hodnotu, digitální hodnotu (0/1) a dokonce i textovou hodnotu (např. výstup jiného bloku Status). Blok Status má jenom 4 vstupy. Pokud by Vám to nestačilo, můžete bloky Status řetězit (výstup jednoho bloku půjde do vstupu dalšího bloku). Na jeden ze vstupů si pošleme telefonní číslo, kam budeme SMS posílat. Na další vstupy si přivedeme cokoliv, u čeho chceme sledovat stav přes SMS (stav topení, teplota, stavy alarmu…).

Zároveň doporučuji přivést na jeden ze vstupů i nějaký spouštěč (impuls), tak abyste mohli řídit nejenom to, co se bude v SMS odesílat (např. stav topení), ale i kdy se to bude odesílat (tímto impulsem může být například i příchozí SMS příkaz – viz příklad níže). Pokud byste chtěli odesílat SMS opakovaně v určitých intervalech (například opakovaná SMS při alarmu), můžete si pomoct přes nějaký generátor impulsů přivedený na vstup bloku Status.

Uvnitř bloku Status si ve sloupci “Text statusu” nadefinujeme text UDP zprávy (a tedy i text samotné SMS zprávy) v souladu s naší syntaxí. Takže například:

gsm sms <v1> Topeni je vypnute.

Kde <v1> je telefonní číslo (například jako konstanta) přivedené na vstup 1.

Zároveň si nadefinujeme podmínky, za kterých se bude tato zpráva odesílat. Upozorňuji, že SMS se odešle vždy, když se má daný text statusu zobrazit. Text statusu se zobrazí vždy, když jsou splněny nadefinované podmínky na vstupech. A podmínky na vstupech se kontrolují i v okamžiku, kdy se Loxone spustí! Pokud byste měli jako jedinou podmínku změnu stavu sledované veličiny, tak by se SMS odesílala i při každém spuštění Loxonu. Proto je potřeba přivést do bloku kromě sledovaného stavu (stav topení je na vstupu 1) i nějaký další spouštěč (v mém příkladě je spouštěč na vstupu 4).

No a potom stačí k bloku Status přiřadit námi nadefinovaný UDP logger. “Minimální časový interval” doporučuji stáhnout na nulu (pro případ, že byste chtěli rychle za sebou poslat SMS na více čísel). Aby se SMS neodesílaly příliš často je potřeba ohlídat podmínkami uvnitř samotného bloku Status.

 

gsm ussdout <USSD kód>

Odeslání USSD kódu. Využití: zjišťování stavu kreditu na SIM kartě. USSD kód samozřejmě může obsahovat hvězdičky, mřížky atd.

V Loxone Config si vytvořte Virtuální výstup příkazu. Tady je příklad pro zjištění kreditu přes Kaktus.

Instrukce při zapnutí:

gsm ussdout *103#

 

Virtuální UDP vstupy

Udělejte nový Virtuální UDP vstup, kde si nastavíme

Adresa odesílatele

<vaše adresa stroje s Node Red>

UDP port

<port, na kterém poslouchá Loxone>

 

gsm signal <síla signálu v dBm>

Modem pravidelně a sám od sebe informuje o stavu signálu. Proč toho nevyužít. Takže první vstup je síla signálu.

Přidáme nový Virtuální UDP příkaz. Nastavíme

Rozeznání příkazu

gsm signal \v

Modem posílá sílu signálu v rozmezí 0 až 13, to je potřeba převést na dBm pomocí “Oprava” a případně můžete zapnout i validaci:

 

gsm ussdin <text USSD zprávy>

Toto je USSD zpráva, kterou modem pošle jako odpověď na váš předchozí dotaz gsm ussdout. Využití: ověření stavu kreditu. Toto fakt není radno podceňovat. GSM modem bude mít na starosti kritické věci jako alarm a určitě nechceme, aby nám tam došel kredit. Buďto si pořiďte nějaký tarif nebo si nastavte kontrolu kreditu přes příkazy gsm ussdout a gsm ussdin.

Node Red odešle USSD zprávu celou, je proto potřeba z ní vyparsovat proměnné, které nás zajímají. Zapněte si UDP monitor. Pošlete si na GSM modul dotaz “gsm ussdout <kód na zjištění kreditu>”. Do UDP monitoru dostanete zprávu od operátora. Pro každou proměnnou si udělejte Virtuální UDP příkaz a parsujte podle toho, jak vypadá zpráva od operátora. Já mám Kaktus, zpráva vypadá takto

Tvoje cislo +420XXXXXXXXX ma kredit 79.00 Kc, Platnost SIM do 15.11.2019.

Takže “Rozeznání příkazu” pro jednotlivé Virtuální UDP příkazy vypadá takto:

Kredit

\ikredit\i \v

Den platnosti

\iPlatnost SIM do \i\v

Měsíc platnosti

\iPlatnost SIM do \i\w.\v

Rok platnosti

\iPlatnost SIM do \i\w.\w.\v

 

Doporučuji nastavit validaci pro případ, že operátor změní formát zprávy a parsování selže.

Pokud chci vědět, za kolik dní mi kredit vyprší, musím použít PicoC (blok Program), kde vstup 1 je den platnosti, vstup 2 je měsíc a vstup 3 je rok. Na výstupu mi polezou zbývající dny platnosti:

int nEvents;
while(TRUE)
{
nEvents = getinputevent();
if (nEvents & 0xe)
{
int day = getinput(0);
int month = getinput(1);
int year = getinput(2);
int currentTime = getcurrenttime();
int deltaDays = (gettimeval(year, month, day, 0, 0, 0, 0) - gettimeval(getyear(currentTime, 1), getmonth(currentTime, 1), getday(currentTime, 1), 0, 0, 0, 1)) / (60*60*24);

setoutput(0,deltaDays);
}
sleep(60000);
}

Poznámka: nejsem programátor, prosím někoho o kontrolu. Občas mi to zlobí a hodnota na výstupu se neaktualizuje v případě změny na vstupu.

No a v tuhle chvíli si už můžeme poskládat notifikační SMS, aby nás Loxone upozornil SMSkou v případě, že bude docházet kredit nebo se bude blížit doba vypršení kreditu:

Pro lepší pochopení tam máte ukázané o hodnoty jednotlivých vstupů a výstupů. Většinu bloků jsme si popsali. Je tam:

  • gsm ussdout na dotaz na kredit
  • gsm ussdin, které z odpovědi operátora parsují: kredit, den, měsíc a rok vypršení platnosti.
  • Program (PicoC) na konverzi zbývajících dnů platnosti.
  • Pak tam jsou dva bloky Impulz v daném čase, které vždy jednou za den mají za úkol “Zjistit kredit” (třeba v 5:59) a “Odeslat SMS” (třeba v 6:00).
  • Blok Status “Nízký kredit” odesílá SMS při nízkém kreditu nebo nízké zbývající době platnosti:

 

Pokud klesne kredit pod stanovený limit (v příkladu 20 Kč) nebo zbývající dny klesnou pod stanovený limit (30 dní), odešle se při následujícím impulzu (viz blok Impulz v daném čase na vstupu 4) varovná SMS. Každý den se bude SMS opakovat, dokud kredit nedobijete (nebo dokud varovné SMS nespotřebují veškerý zbývající kredit :-)).

 

gsm callin <volající číslo>

Příchozí hovor. Node Red je nastavený tak, že při každém zvonění odesílá UDP zprávu. UDP zprávu přijmeme pomocí (analogového) virtuálního UDP vstupu, který nakonfugurujeme takto:

Rozeznání příkazu

gsm callin \v

A nastavte validaci podle obrázku. Min a max na krajní dovolené hodnoty (nezapomínejte, že budeme posílat defítimístné číslo). Standardní hodnota 0 a časový limit 1s. Virtuální vstup se pak bude chovat jako “analogový impuls”. Jednu sekundu bude posílat volající číslo a pak vstup se zresetuje na hodnotu 0.

Máme tedy volající číslo a teď je potřeba ho ověřit. Hledal jsem způsob, jak to udělat a nakonec jsem skončil u bloku Vzorec (pokud byste měli lepší řešení, dejte vědět).

EDIT: Úplně jsme přehlídl blok Rovnost.

Na vstupy přiveďte samotný virtuální UDP vstup a autorizované telefonní číslo, které máte uložené jako konstantu. Tady je příklad dvou autorizovaných čísel:

 

K čemu je tam ten bloky Zpoždění zapnutí a vypnutí? Loxone má nepříjemnou vlastnost, že při startu mají na kratičkou chvíli všechny analogové konstanty a všechny analogové virtuální vstupy hodnotu nula (to znamená volající číslo odpovídá autorizovanému a odešle se impuls na rozsvícení světla na chodbě). Blok Zpoždění zapnutí a vypnutí slouží k tomu, že zablokuje jakýkoliv impuls kratší než 0,5s. Připomínám, že impuls posílaný Virtuálním UDP vstupem callin má délku 1s, takže bez problémů projde. Blok Zpoždění zapnutí a vypnutí je třeba nastavit takto:

Ve schématu máte i gsm hangup, který hovor zavěsí jako potvrzení toho, že Loxone přijal vaši instrukci. Nezapomeňte, že pokud telefonát nepoloží ani Loxone, ani volající osoba, tak z Node Redu budou do Loxonu chodit další opakované UDP zprávy (impulsy) při každém zvonění.

 

gsm <sms příkaz> <číslo odesílatele>

Příchozí příkazy přes SMS. Nejlepší asi bude, když vysvětlím, co se v Node Red stane, pokud na GSM modul přijde SMS zpráva. SMS zpráva se rozdělí na jednotlivá slova (rozdělovačem je mezera) a tato slova jsou v původním pořadí odesílána v jednotlivých UDP zprávách v intervalech 1s. Takže máte sérii UDP zpráv:

gsm <slovo1> <číslo odesílatele>
gsm <slovo2> <číslo odesílatele>
....

Kromě toho se všechna písmena převedou na malá a odstraní se případná diakritika (abyste se při psaní SMS nemuseli trápit jestli máte správnou velikost písmen).

Nastavení v Loxonu je jednoduché. vytvořte si Virtuální UDP příkaz (vstup), ve kterém si nastavíte

Rozeznání příkazu

gsm <prikaz> \v

například

gsm topeni1 \v

 

Váš příkaz může být jakékoliv slovo:

  • z písmen, číslic a znaků
  • bez mezer
  • pouze malá písmena
  • bez diakritiky
  • slova “signal” a “callin” nepoužívejte, aby nedocházelo ke kolizi s jinými příkazy.

Dále si ve virtuálním UDP příkazu nastavte validaci stejným způsobem, jako jsem to popsal u vstupu “gsm callin”. Aby vám UDP příkaz fungoval jako “analogový impuls”.

Toť vše. Stačí vytvořit Virtuální UDP s vaším příkazem a můžete ho hned začít používat v SMS zprávách. V jedné zprávě můžete poslat víc příkazů, oddělených mezerníkem. Loxone je bude provádět postupně v daném pořadí (s prodlevou 1s). Například já mám příkazy “topeni0” na vypnutí topení, “topeni1” na zapnutí a “topenistav” jako dotaz na aktuální stav. Pokud pošlu SMS “topeni1 topenistav”, tak mi Loxone zapne topení a zpátky mi pošle potvrzovací SMS s aktuálním stavem topení.

Validace čísla odesílatele probíhá úplně stejně jako u gsm callin, přes bloky Vzorec a Zpoždění zapnutí a vypnutí (přiznám se, není to moc elegantní, uvítám návrhy na lepší řešení):

Blok Status posílá SMS o stavu topení zpátky na číslo, ze kterého mu přišel dotaz. Nastavení máte uvedené nahoře, když jsem popisoval příkaz gsm sms. Nezapomeňte napojit celý blok na UDP logger, který jsme si vytvořili dříve.

 

 

No a toť vše.

Zigbee2MQTT, NodeRed a Loxone

Zigbee2MQTT, NodeRed a Loxone

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.

 

Integrace Rekuperace Thermwet Ventbox do Loxone pomocí Modbus TCP

Integrace Rekuperace Thermwet Ventbox do Loxone pomocí Modbus TCP

Po dlouhé a náročné cestě způsobené nejen nedostatkem dokumentace jsem nakonec úspěšně integroval rekuperaci ThermWet Ventbox (v mém případě Standard 400) do Loxone. Připravil jsem postup a šablonu. Integrace je řešena přes Modbus TCP, není tedy potřeba žádný zvláštní extension, stačí TCP spojení mezi Miniserverem a Ventboxem.

Požadavky:

  • Loxone Config 8.3 (předpokládám, že všechny 8.x a vyšší budou taky fungovat)
  • ThermWet Ventbox s firmwarem v2.13 (rovněž předpokládám, že i na vyšších); testováno na modelu 400 Standard. Nevím, jestli modely Basic mají podporu Modbus, prověřte před případným nákupem!
  • TCP/IP spojení mezi Loxone a Ventboxem

 

Postup:

  1. Stáhněte si zazipovanou šablonu – MB_ThermWet_Ventbox_213 (aktualizace 2.15 dole), rozbalte ji do
    C:\ProgramData\Loxone\Loxone Config X.Y\Templates\Comm\
  2. V rozšířeném nastavení Ventboxu si zvolte nenulovou adresu jednotky (např. 5), Loxone totiž Ventboxáckou implicitní adresu 0 nepodporuje:

  3. V Loxone Configu zvolte ve stromě periferií Projekt – Miniserver – Miniserver communication, následně na liště přidejte Modbus server:
  4. Nově přidaný Modbus server pojmenujte a vyplňte adresu ve formátu
    [IP adresa Ventboxu]:502


    Prodleva po spuštění 120s je volitelná

  5. Aplikujte nainstalovanou šablonu (pokud není v seznamu vidět, restartuje Loxone Config) – ve stromě vybrat nově přidaný Modbus server, v liště Sensors and Actuators, Device Templates a konečně Thermwet Ventbox:
  6. Zadejte Modbus adresu zvolenou v kroku 2
  7. 1. část hotova, můžete vytáhnout senzory na stránku, uložit, spustit Live View a zkontrolovat vyčítané údaje:
  8. Aby se dal zcela ovládat výkon Ventboxu, je potřeba jej přepnout do automatického režimu (všechny ostatní režimy totiž příkazy z nadřazeného systému (=Loxone) přebíjí):
  9. Dále je potřeba v celém plánovači automatického režimu ve Ventboxu nastavit vypnuto (bílý čtvereček). To je proto, že sejde-li se víc požadavků (plánovač, nadřazený systém, …), Ventbox použije maximální hodnotu. Nastavte tedy úplně všude (ve všech dnech, 0-24) vypnuto:

    Díky tomu bude platit, že pokud v Loxone nastavíte požadovaný výkon 0, jednotka se vypne.
  10. Aktory – Ventbox očekává od nadřazeného systému refresh hodnot nejpozději každých 15s, jinak přejde do defaultu. Nastavte tedy u zvolených aktorů periodu znovuodesílání 5s. Pro test přiveďte konstantní hodnotu do aktoru. Například zde 100:

    Výsledek je vidět na webovém rozhraní:

    Alternativně si můžete potřebné refreshe řídit sami generátorem pulzů a analogovou pamětí:

Dostal jsem zprávu, že se chystá verze 2.14, která by měla umět mimo jiné přímé ovládání zapnuto/vypnuto, přetlak, Bypass, rozsah letního režimu, … Pokusím se zaktualizovat šablonu, jakmile bude k dispozici.

Nakonec je to rovnou 2.15, zatím nijak zvlášť otestovaná šablona zde: MB_ThermWet_Ventbox_215.zip

Aleš Berka (Aleq)

DMX pomoci Arduino – nahrada za DMX extension

DMX pomoci Arduino – nahrada za DMX extension

udptesttool

EDIT: Misto “draheho” DMX shieldu lze pouzit modul MAX485, postup jsem doplnil na konci clanku.

Cely UDP DMX je podstate velice jednoduchy, staci koupit 3 veci a mit jen zakladni znalost arduina, tj jak nahrat Scratch.

1 – Arduino UNO / Leonardo

– mne se cinske klony moc neosvedcily, sahl jsem radeji po origo UNO popr Leonardu z CR.

2 – W5100 ETH Shield  ( https://www.aliexpress.com/item/Ethernet-Shield-W5100-R3-UNO-Mega-2560-1280-328-UNR-R3-only-W5100-Development-board/32616109835.html?spm=a2g0s.9042311.0.0.viN7Vc )

3 – DMX shield ( https://www.aliexpress.com/item/DMX-Shield-Expansion-board-module-Compatible-for-Arduino-1-0-for-DMX-Master-device-artwork-into/32841371527.html?spm=a2g0s.9042311.0.0.196MKn )

Cele to vypada takhle:

 

Dale stahnout Scratch pro Arudiono UDP DMX 

https://sourceforge.net/p/udptodmx/code/HEAD/tree/trunk/

z adresare  libraries prekopirovat(pripadne prehrat stavajici) DmxSimple do adresare s vasimi knihovnami.

Pro ty, kdo vidi arduino poprve, navod jak nahrat program je zde: http://navody.arduino-shop.cz/zaciname-s-arduinem/prvni-program.html , staci jen vybrat Vasi vyvojovou desku.

Z adresare source/DmxControl otevrit soubor DMXControl.ino, zmenit IP adresu a nahrat do UNO viz navod.

//STATIC IP, ignored if USE_DHCP is defined
uint8_t myip[4] = { 192, 168, 0, 11 };
const uint8_t mygw[4] = { 192, 168, 0, 1 };// ip of gateway
const uint8_t mymask[4] = { 255, 255, 255, 0 };// subnet mask

Tim je UDP DMX pripraven k pouziti, ted uz jen zalezi, zda mate DMX kabel, od vyroby je DMX prepnuty na posilani prikazu z konektoru(TX/RX  uart). Kdo nema, staci prehodit 2 jumpery na DMX shieldu, aby byly u TX/RX-io. Pak je ridici signal posilan z pinu 3(+) a 4(-) na DMX shieldu.

 

Nastaveni v Loxone config ( prevzato z https://sourceforge.net/p/udptodmx/code/HEAD/tree/trunk/ )

Prikaz:

DMXPww#xx#yy#zz

ww – cislo dmx kanalu

xx – jas ( nemusi byt od 0 do 100, u me napr funguje u bodovek 6-26, kde 6=vypnuto a 26=plny svit. Popsano vice v        https://sourceforge.net/p/udptodmx/code/HEAD/tree/trunk/docu/Protokoll.pdf )

yy – rychlost stmivani ( pokud se vynecha, rozsviti/zhasne hned)

zz – krivka stmivani ( vyzkouset komu se jaka vic hodi, u me je linearni, tedy “zz” vynechavam. Graf  https://sourceforge.net/p/udptodmx/code/HEAD/tree/trunk/docu/dimmkurve.jpg)

Takze napr: DMXP1#26#1

kanal 1, plny svit, jas ihned naplno, bez postupneho nabehu.

Dalsi informace najdete zas v https://sourceforge.net/p/udptodmx/code/HEAD/tree/trunk/docu/Protokoll.pdf

Snad jsem na nic nazapomnel, kdyztak se ozvete, poradim co budu vedet.

 

Vyzkouset lze bez pripojeni k loxone a to pres UDP Test Tool, odkaz  je https://sourceforge.net/p/udptodmx/code/HEAD/tree/trunk/docu/Protokoll.pdf

 

Pripojeni modulu MAX485, misto drazsiho DMX shieldu:

Misto DMX shieldu tedy vzit  https://www.aliexpress.com/item/MAX485-Module-RS-485-TTL-to-RS485-MAX485CSA-Converter-Module-For-Arduino-Integrated-Circuits-Products/32669600197.html?spm=a2g0s.9042311.0.0.rVGoNH

Pripojeni viz obrazek:

Program,prikazy atd zustava jinak stejne.

 

Nemcour vyviji  verzi s vlastni PCB deskou,2 modulovou na DIN, za kterou  predbezne borec pocita cca 100Ecek…

https://www.loxforum.com/forum/faqs-tutorials-howto-s/34948-g%C3%BCnstige-und-bessere-alternative-zur-dmx-extension/page9

(c) David 2018-04-05

Integrace Hormann UAP1 do Loxone

Integrace Hormann UAP1 do Loxone

Integrace garážových vrat Hörmann přes modul UAP1 do Loxone vyžaduje lehce komplexnější řešení než přímé napojení na povely vrata nahoru, případně vyčítání polohy vrat. Je to nedostatečné, protože logika Loxone prvku Garážových vrat je jiná, než jak se chová UAP1. Příklad – vrata jedou nahoru: pokud v Loxone stisknu podruhé nahoru, prvek zastaví otevírání. UAP1 ne, při druhém impulzu stejným směrem nerušeně pokračuje dál. Ještě horší to bylo při změně směru. Jedou-li vrata nahoru a stisknu v Loxone dolů, Loxone zastaví – stejně jako UAP1. Jedou-li vrata ale zrovna dolů, chápe to UAP1 zřejmě jako reakci na možné nebezpečí, vrata nezastaví, ale rovnou je začne otevírat. Ovládací prvek Loxone v této situaci zastaví. Jednoduché zapojení a konfigurace v Loxone funguje spolehlivě pouze z výchozích poloh.

Řešení (díky Chrispiemu z loxforum.com [1] za nápad) je použít 3. výstup pro nouzové zastavení (a blokování jakéhokoliv dalšího pohybu) v UAP1 na kontaktech 12-13. Je potřeba dávat pozor na to, že tento kontakt je obrácený – tj. je-li sepnuto (ON v Loxone), tak vrata fungují normálně. V momentě, kdy se tento kontakt rozpojí, vrata svůj pohyb zastaví. Přímé napojení na negovaný AND obou výstupů (nahoru a dolů) z ovládacího prvku zafunguje, znefunkční ale ovládání zvenku (mimo Loxone), např. dálkové ovládání. Pokud totiž vrata zrovna nejedou, kontakt nouzového zastavení (= Reset) bude přerušený a vrata blokovaná. Řešením je vyslat pouze opačný impulz (krátce rozpojit) po ukončení pohybu (tj. jakmile není žádný výstup na Qo a Qc). To zastaví a resetne pohon. Impulz musí být kratší než Motor lock (konfigurovatelné v ovládacím prvku garážových vrat v Loxone), jinak by to mohlo blokovat i další příkazy.

Loxone Config:

Ovládací prvek garážových vrat je nutno přepnout na DIRECT (Connection Type) – aby byl výstup Qo či Qc trvale sepnutý během požadovaného pohybu. Implicitní chování je totiž pouze posílat impulzy.

Vstupy UAP1:
– UAP1 příkaz otevřít (15-20) – Q4 na screenshotu
– UAP1 příkaz zavřít (17-20) – Q2 na screenshotu
– UAP1 povoleno (12-13) – Q7 na screenshotu; negovaný výstup – jeho rozpojením zastavíme a a po dobu rozpojení zakážeme pohyb vrat

Výstupy UAP1:
– UAP1 signalizující vrata kompletně otevřená (01) – AI3 na screenshotu
– UAP1 signalizující vrata kompletně zavřená (02) – AI2 na screenshotu
(Volitelné) UAP1 signalizující vrata v pohybu (03), AI4 na screenshotu. Pro tuto funkci je ale nutno nastavit položku 29 v konfiguračním menu na pohonu Supramatic – přidat tam tu tečku. Viz návod k pohonu.

Poznámka:
V mém případě došly digitální vstupy, proto jsou použity analogové (přepnuté na digitální). Vy samozřejmě použijte digitální (Ix), máte-li je volné.

 

Aleš Berka (Aleq)

Read More Read More

Logování – vzdálený syslog

Logování – vzdálený syslog

Úvod

Loxone nabízí možnost využití vzdáleného logu, tedy odesílání zpráv logu do logu na jiném zařízení. Výhoda je jasná – logování na SD kartu Loxone snižuje životnost SD karty a navíc na vzdáleném stroji si můžete log analyzovat. K tomu, aby šlo vzdálený log využít, potřebujeme nějaký stroj s Linuxem, nainstalovaným balíčkem rsyslog, webovým serverem s PHP (volitelně s databází). V našem návodu použijeme stroj s nainstalovaným Debianem. Není třeba instalovat grafické prostředí – zbytečně zabírá operační paměť a reálně ho vůbec nepotřebujeme. Já osobně používám virtuální server na svém domácím serveru.

LoxBerry plugin

Od 4.4.2018 je celé řešení k dispozici jako plugin Syslog Server do LoxBerry.

Rsyslog

V Debianu by měl být rsyslog defaultně nainstalovaný. Pokud není, nainstaluje se pomocí:

sudo apt-get install rsyslog

Následně provedeme konfiguraci:

sudo nano /etc/rsyslog.conf

Odkomentujeme řádky týkající se přístupu přes UDP a TCP:

# provides UDP syslog reception
$ModLoad imudp
$UDPServerRun 514
# provides TCP syslog reception
$ModLoad imtcp
$InputTCPServerRun 514

Dále pak zakomentujeme řádek s definicí formátu datumu, abychom měli plný timestamp:

#
# Use traditional timestamp format.
# To enable high precision timestamps, comment out the following line.
#
#$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat

Dále vytvoříme konfiguraci pro Loxone:

sudo nano /etc/rsyslog.d/loxone.conf

A vložíme do ní konfiguraci přesměrování zpráv z Loxone do samostatného Log souboru.
192.168.1.10 nahradíme adresou Loxone miniserveru:

# změnit skupinu vytvořeného logu na www-data, aby ji mohl číst LogAnalyzer
$FileGroup www-data

# zpracuj zprávy z Loxone do separátního souboru
:fromhost-ip, isequal, "192.168.1.10" /var/log/loxone.log
& ~
# pouze zprávy odjinud než z Loxone budou pokračovat dál

# Vrátit skupinu pro ostatní Logy na default
$FileGroup adm

Restartujeme Rsyslog:

sudo service rsyslog restart

Nastavení Loxone

V Loxone Configu si ve stromu rozbalíme položku Miniserveru, stoupneme na “Zprávy” a klikneme na ikonku Logger. Tím vložíme nový Logger. Přidělíme mu jméno dle libosti a adresu /dev/syslog/<ip_log_serveru>
Pak již běžně přiřazujeme Logger

Analyzování

Adiscon Log Analyzer

K provozování potřebujeme nainstalovat na logserver webserver a php:
(pokud používáte již existující stroj s PHP, zkontrolujte, že máte v apache2 nainstalovaný a aktivovaný mode php; na čisté instalaci se vše provede samo)

sudo apt-get install apache2 php

Stáhneme z oficiálních stránek: http://loganalyzer.adiscon.com/ Cestu za příkazem wget samozřejmě změníme na aktuální. Adekvátně k tomu pak všechny příkazy s loganalyzer-4.1.6 upravit na adekvátní název souboru / adresáře.
Pak rozbalíme a obsah adresáře src zkopírujeme do /var/www/loganalyzer
Pak změníme vlastníka:

wget http://download.adiscon.com/loganalyzer/loganalyzer-4.1.6.tar.gz
sudo tar -xvzf loganalyzer-4.1.6.tar.gz
sudo rm loganalyzer-4.1.6.tar.gz
sudo mkdir /var/www/loganalyzer
sudo cp -r loganalyzer-4.1.6/src/* /var/www/loganalyzer
sudo chown -Rv www-data:www-data /var/www/loganalyzer

Nyní si zkonfigurujeme webserver pro loganalyzer. Vytvoříme soubor /etc/apache2/conf-available/loganalyzer.conf:

sudo nano /etc/apache2/conf-available/loganalyzer.conf

a vložíme do něho následující:

Alias /loganalyzer "/var/www/loganalyzer/"

<Directory /var/www/loganalyzer/>
  Options +FollowSymlinks
  AllowOverride All
  Satisfy Any

 <IfModule mod_dav.c>
  Dav off
 </IfModule>

 SetEnv HOME /var/www/loganalyzer
 SetEnv HTTP_HOME /var/www/loganalyzer

</Directory>

Uděláme link pro aktivaci a restartneme webserver:

sudo ln -s /etc/apache2/conf-available/loganalyzer.conf /etc/apache2/conf-enabled/loganalyzer.conf
sudo service apache2 restart

Upravíme parser “misc” pro potřeby Loxone. Jedná se o upravený standardní parser pro syslog. Pro každý ze sedmi typů řádku v syslogu jsem přidal MESSAGETYPE Loxone1 – 7, aby bylo jednoduché určit, která část parseru je případně třeba upravit. V současné době je upravena Loxone2 a Loxone6 – to je log s jednoduchým datumem a precisním datumem, oba odpovídající tomu, co mi posílá Loxone. Pokud se někomu objeví jiný MESSAGETYPE, je třeba odladit další část parseru

sudo nano /var/www/loganalyzer/classes/logstreamlineparsermisc.class.php

A celý obsah nahradíme tímto:

<?php
/*
        *********************************************************************
        * LogAnalyzer - http://loganalyzer.adiscon.com
        * -----------------------------------------------------------------     *
        * Loxone Smart Home Miniserver Log Parser Class 
        *********************************************************************
*/

// --- Avoid directly accessing this file! 
if ( !defined('IN_PHPLOGCON') )
{
        die('Hacking attempt');
        exit;
}
// --- 

// --- Basic Includes
require_once($gl_root_path . 'classes/enums.class.php');
require_once($gl_root_path . 'include/constants_errors.php');
require_once($gl_root_path . 'include/constants_logstream.php');
// --- 


class LogStreamLineParsermisc extends LogStreamLineParser {
//      protected $_arrProperties = null;

        // Constructor
        public function __construct () {
                return; // Nothing
        }
        public function LogStreamLineParsermisc() {
                self::__construct();
        }

        /**
        * ParseLine
        *
        * @param arrArguments array in&out: properties of interest. There can be no guarantee the logstream can actually deliver them.
        * @return integer Error stat
        */
       public function ParseLine($szLine, &$arrArguments)
        {
                // Sample (Syslog): Mar 10 14:45:44 debandre anacron[3226]: Job `cron.daily' terminated (mailing output)
                if ( preg_match("/(...)(?:.|..)([0-9]{1,2} [0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}) ([a-zA-Z0-9_\-\.]{1,256}) ([A-Za-z0-9_\-\/\.]{1,32})\[(.*?)\]:(.*?)$/", $szLine, $out ) )
                {
                        $arrArguments[SYSLOG_MESSAGETYPE] = 'Loxone1';
                        // Copy parsed properties!
                        $arrArguments[SYSLOG_DATE] = GetEventTime($out[1] . " " . $out[2]);
                        $arrArguments[SYSLOG_HOST] = $out[3];
                        $arrArguments[SYSLOG_SYSLOGTAG] = $out[4];
                        $arrArguments[SYSLOG_PROCESSID] = $out[5];
                        $arrArguments[SYSLOG_MESSAGE] = $out[6];
                }
                // Sample (Syslog): Mar 10 14:45:39 debandre syslogd 1.4.1#18: restart
                else if ( preg_match("/(...)(?:.|..)([0-9]{1,2} [0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}) ([a-zA-Z0-9_\-\.]{1,256}) ([A-Za-z0-9_\-\/\.]{1,32}):(.*?)$/", $szLine, $out ) )
                {
                        $arrArguments[SYSLOG_MESSAGETYPE] = 'Loxone2';
                        $loxone = $out[3]. ';'. $out[4].':'.  $out[5]. $out[6];
                        $loxone = str_replace(': ',':',$loxone);
                        $loxone = str_replace('#015','',$loxone);
                        $loxone = str_replace('#01','',$loxone);
                        $loxout = explode(';',$loxone);
                        // Copy parsed properties!
                        $arrArguments[SYSLOG_DATE] = GetEventTime($loxout[0]. ' '. $loxout[1]);
                        $arrArguments[SYSLOG_PROCESSID] = $loxout[2];
                        $arrArguments[SYSLOG_MESSAGE] = $loxout[3];
                }
                // Sample (Syslog): Mar 10 14:45:39 debandre syslogd restart
                else if ( preg_match("/(...)(?:.|..)([0-9]{1,2} [0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}) ([a-zA-Z0-9_\-\.]{1,256}) ([A-Za-z0-9_\-\/\.]{1,32}) (.*?)$/", $szLine, $out ) )
                {
                        $arrArguments[SYSLOG_MESSAGETYPE] = 'Loxone3';
                        // Copy parsed properties!
                        $arrArguments[SYSLOG_DATE] = GetEventTime($out[1] . " " . $out[2]);
                        $arrArguments[SYSLOG_HOST] = $out[3];
                        $arrArguments[SYSLOG_SYSLOGTAG] = $out[4];
                        $arrArguments[SYSLOG_MESSAGE] = $out[5];
                }
                // Sample (Syslog): Mar 7 17:18:35 debandre exiting on signal 15
                else if ( preg_match("/(...)(?:.|..)([0-9]{1,2} [0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}) (.*?) (.*?)$/", $szLine, $out ) )
                {
                        $arrArguments[SYSLOG_MESSAGETYPE] = 'Loxone4';
                        // Copy parsed properties!
                        $arrArguments[SYSLOG_DATE] = GetEventTime($out[1] . " " . $out[2]);
                        $arrArguments[SYSLOG_HOST] = $out[3];
                        $arrArguments[SYSLOG_MESSAGE] = $out[4];
                }
                // Sample (RSyslog): 2008-03-28T11:07:40+01:00 localhost rger: test 1
                else if ( preg_match("/([0-9]{4,4}-[0-9]{1,2}-[0-9]{1,2}T[0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}.[0-9]{1,2}:[0-9]{1,2}) (.*?) (.*?):(.*?)$/", $szLine, $out ) )
                {
                        $arrArguments[SYSLOG_MESSAGETYPE] = 'Loxone5';
                        // Copy parsed properties!
                        $arrArguments[SYSLOG_DATE] = GetEventTime($out[1]);
                        $arrArguments[SYSLOG_HOST] = $out[2];
                        $arrArguments[SYSLOG_SYSLOGTAG] = $out[3];
                        $arrArguments[SYSLOG_MESSAGE] = $out[4];
                }
                // Sample (RSyslog): 2017-10-24T10:37:48.680031+02:00 2017-10-24 10:37:50;Kotel - spínání;Off#015
                else if ( preg_match("/([0-9]{4,4}-[0-9]{1,2}-[0-9]{1,2}T[0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}\.[0-9]{1,6}.[0-9]{1,2}:[0-9]{1,2}) (.*?) (.*?):(.*?)$/", $szLine, $out ) )
                {
                        $arrArguments[SYSLOG_MESSAGETYPE] = 'Loxone6';
                        $loxone = $out[2]. ';'. $out[3].':'.  $out[4]. $out[5];
                        $loxone = str_replace(': ',':',$loxone);
                        $loxone = str_replace('#015','',$loxone);
                        $loxone = str_replace('#01','',$loxone);
                        $loxout = explode(';',$loxone);
                        // Copy parsed properties!
                        $arrArguments[SYSLOG_DATE] = GetEventTime($loxout[0]. ' '. $loxout[1]);
                        $arrArguments[SYSLOG_PROCESSID] = $loxout[2];
                        $arrArguments[SYSLOG_MESSAGE] = $loxout[3];
                }
                // Sample: 2008-03-28T15:17:05.480876+01:00,**NO MATCH**
                else if ( preg_match("/([0-9]{4,4}-[0-9]{1,2}-[0-9]{1,2}T[0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}\.[0-9]{1,6}.[0-9]{1,2}:[0-9]{1,2}),(.*?)$/", $szLine, $out ) )
                {
                        $arrArguments[SYSLOG_MESSAGETYPE] = 'Loxone7';
                        // Some kind of debug message or something ...
                        $arrArguments[SYSLOG_DATE] = GetEventTime($out[1]);
                        $arrArguments[SYSLOG_MESSAGE] = $out[2];
                }
                else
                {
                        if ( isset($arrArguments[SYSLOG_MESSAGE]) && strlen($arrArguments[SYSLOG_MESSAGE]) > 0 ) 
                                OutputDebugMessage("Unparseable syslog msg - '" . $arrArguments[SYSLOG_MESSAGE] . "'", DEBUG_ERROR);
                }

                // If SyslogTag is set, we check for MessageType!
                if ( isset($arrArguments[SYSLOG_SYSLOGTAG]) )
                {
                        if ( strpos($arrArguments[SYSLOG_SYSLOGTAG], "EvntSLog" ) !== false ) 
                                $arrArguments[SYSLOG_MESSAGETYPE] = IUT_NT_EventReport;
                }

                // Return success!
                return SUCCESS;
        }


}
?>

Na závěr provedeme konfiguraci. Spustíme v prohlížeči http://<log_server>/loganalyzer Načte se stránka Critical Error occured, s odkazem Click here to Install Adiscon LogAnalyzer! Kliknete na “here” a spustí se průvodce. Během konfigurace zvolíme Logline type na Miscellaneous Logfiles a Syslog file na náš Log soubor z Loxone.
Konfigurace se uloží do souboru /var/www/loganalyzer/config.php Pokud chceme udělat celý proces konfigurace znovu, stačí tento soubor vymazat a znovu jít na stránku. Po konfiguraci je třeba pro podporu českých znaků změnit v config.php parametr $CFG[‘HeaderDefaultEncoding’] na ENC_UTF8 .

Autor článku: Zmáťa