Hallo werte siio-Gemeinde,
als kleines Dankeschön für so manche erhaltene Hilfestellung hier im Forum möchte ich einige Hilfsfunktionen posten, mit denen ich jede etwas größere LUA-Szene beginne. Seit mehreren Wochen (Stand Mai 2017) tun diese Routinen bei mir ihren Job, ich würde sagen “gutes Beta-Stadium”.
Hintergrund: Nach einiger Zeit der HC2-Programmierung stellt man fest, dass durch Flüchtigkeits- oder Programmierfehler ganze Szenen scheitern, nur weil man nicht jeden (unerwarteten) Sonderfall bedacht hatte. Ich hatte mal eine ganze Woche lang die Nachtbeleuchtung eingeschaltet, nur weil ein völlig überflüssiger fibaro:debug()-Befehl Probleme mit einer Zeichenverkettung bekam.
Daher habe ich einen kleinen Satz Hilfsfunktionen geschrieben, um solche typischen Fehlerquellen abzufangen. Den kopiere ich nun stets an den Beginn einer neuen LUA-Szene, gleich nach den Startkommentaren.
Ich habe auf drei Dinge großen Wert gelegt:
-
Kürze.
Die Funktionen sind “minifiziert”, indem überflüssige Zeilenumbrüche und Leerzeichen weggekürzt wurden und die Funktionsargumente keine sprechenden Namen haben. Dafür benötigt die gesamte Bibliothek auch nur 6 Zeilen bzw. knapp 400 Byte im Rohzustand, wenn man die darunter stehenden Kommentare weglässt. Wer mag, kann sogar noch ein paar Byte durch kürzere Funktionsnamen rauskitzeln
Außerdem werden Skripte letztendlich übersichtlicher, weil man nuns(a,b)
schreiben kann anstattif(b~=NIL) then fibaro:setGlobal(a,b) end
-
Arbeitserleichterung.
Die Funktionenc()
undd()
benötigt man hauptsächlich für das Debuggen während der Entwicklungsphase; sie sind um ein Vielfaches schneller getippt als ihre “richtigen” Basisfunktionen, während sie sogar mehr Fehler verzeihen. -
Fehlertoleranz.
Wenn man beispielsweise eine Szene mit einer fälschlicherweise undefinierten Nummer aufruft - also im Prinzipfibaro:startScene(NIL)
- oder den Wert einer nicht existierenden globalen Variable abfragt (was ebenfalls ein klassischer Programmierfehler ist), dann geht’s halt mit diesen Hilfsfunktionen trotzdem weiter im Programm, ohne Fehlermeldung. “The script will silently fail”, nennt das der Programmierer. Ob das immer im Sinne der Aufgabe ist, muss man selbst entscheiden. In den meisten Fällen (zumindest im Bereich Smart Home!) sollte dieser pragmatische Ansatz eine gute Wahl sein, sprich wenn 99 Prozent Erfolg “besser” sind als ein kompletter Programmabbruch. Eine Datenbank würde man selbstverständlich nicht so tolerant programmieren…
Da man im Fibaro Home Center 2 leider keine Funktionen im globalen Scope definieren kann, sondern in jeder Szene alles wieder neu hinschreiben muss, ist diese Mini-Bibliothek, wie ich finde, ein guter Kompromiss zwischen Ressourcenschonung und Arbeitserleichterung.
Ich freue mich über Eure Anregungen. Gibt es noch Bugs im Code? Habt Ihr auch nützliche Hilfsroutinen geschrieben? Dann immer her damit!
Beste Grüße,
Andreas
function c(...)local s=''for i,v in ipairs({...})do s=s..v..' 'end return s end
function d(s)fibaro:debug(s)end
function g(n)return fibaro:getGlobal(n)or''end
function s(n,v)if(g(n)~=(v or''))then fibaro:setGlobal(n,v or'')end end
function sc(n)if((n or 0)>0)then fibaro:startScene(n)end end
function scene(l)if(type(l)=='table')then for i,v in ipairs(l)do sc(v)end else sc(n)end end
--[[
function c : Fügt eine beliebige Anzahl von Komma-separierten Argumenten
zusammen ("concatenate"), jeweils mit einem Leerzeichen
dazwischen und am Ende zur besseren Lesbarkeit,
und gibt den gesamten String zurück.
Beim ersten NIL-Argument gibt die Funktion das bisherige
Ergebnis zurück.
Beispiel:
fibaro:debug(c('Samstag', 'und', 'Sonntag', 'ist', 'frei.'));
function d : nur eine Abkürzung für fibaro:debug, weil man das so häufig benutzt.
Beispiel: d('hallo Welt'); d(_VERSION);
function g : liest den Wert einer globalen Variablen,
liefert dabei niemals NIL zurück.
Beispiel: if(g('PresentState') == 'Away') then ...
function s : setzt den Wert einer globalen Variablen, falls dies nötig ist.
NIL wird wie ein Leerstring behandelt.
Der Befehl fibaro:setGlobal wird nur aufgerufen, wenn der
aktuelle Wert der globalen Variablen ein anderer ist.
Beispiel: s('PresentState', 'Away')
function sc : Führt eine Szene aus, wenn deren Nummer nicht NIL oder 0 ist.
Beispiel: sc(4711); sc();
function scene : Startet eine einzelne Szene oder mehrere Szenen.
Der Parameter l (wie "Liste") kann vom Typ
"number" oder "table" sein.
Szenennummern 0 und NIL werden ignoriert.
Beispiele:
scene(4711); scene( {15, 19, 42} ); scene();
--]]