Im letzten Review hab ich euch das RooWifi Modul vorgestellt, welches den iRobot Roomba Staubsauger mit WLAN ausstattet. Richtig Sinn macht das Ganze aber erst, wenn Roomba somit ein Teil deines Smart Home wird. Hier zeig ich dir, wie du Roomba in dein Fibaro Home Center integrierst.
Wie in meinem Review: "RooWifi - so kommt dein Roomba Staubsauger ins WLAN" geschrieben habe, ist das RooWifi Modul als reines Smartphone / Tablet Remote Control für Roomba ein übertrieben teurer Spaß. Allerdings haben wir auch gesehen, das der kleine Putzteufel ziemlich viele Informationen über sich Preis gibt, welche man über den Serial Port auslesen kann. Schön das genau auf diesem Port unser RooWifi WLAN Modul sitzt und uns eine API Schnittstelle bietet.
Roomba per Fibaro Smart Home steuern
Über diese Schnittstelle ist es relativ einfach, alle notwendigen Informationen über Roomba in Echtzeit zu erhalten und ihm auf dem gleichen Weg Kommandos zu senden.
So könnte der iRobot Roomba automatish die Wohnung saugen, sobald du das Haus verlässt. Fällt die Akku Kapazität unter 20% oder du kommst gerade wieder nach Hause, während Roomba noch am putzen ist, so schicke ihn einfach zurück zu seiner Dockingstation. Dies und viele andere Szenarien sind mit Roomba in Verbindung mit dem Smart Home möglich.
Da es noch kein Plugin im Home Center 2 dafür gibt, zeig ich dir hier wie du dir fix ein virtuelles Modul zusammen bauen kannst. Wenn du keine Lust auf Scripte hast - scrolle schnell nach unten und lad dir das virtuelle Modul herunter ;-)
1) Virtuelles Modul
Erstelle ein neues virtuelles Modul. Dazu einfach auf der Weboberfläche des HC2 auf "Module" und links auf "Add or remove device". Hier wähle "virtuelles Modul hinzufügen".
2) IP Adresse und TCP Port
Vergebe dem neuen virtuellen Modul einen passenden Namen, wie zum Beispiel "Roomba". Fülle das Feld IP Adresse mit der IP des RooWifi Moduls aus. Dieses Feld werden wir folgend in jedem Button auslesen und nutzen, um die IP Adresse nicht überall ändern zu müssen, falls dein Router dem Roomba WLAN Modul mal eine neue IP verpasst.
Tipp: am besten du vergibst dem RooWifi eine feste IP Adresse. Dies könntest du in der Konfiguration des RooWifi machen. Hier gibst du dem Modul eine IP Adresse vor, welche dein Router nicht im DHCP Pool hat. Natürlich musst du in der Config Maske des RooWifi auch die Checkbox "DHCP" abwählen. Alternativ bietet der Router auch die Möglichkeit dem Gerät immer die gleiche IP Adresse zu vergeben. Bei der FRITZ!Box findest du diese Option unter Heimnetz > Klick auf Bearbeiten (Symbol rechts Stift & Zettel) und dort die Checkbox "Diesem Netzwerkgerät immer die gleiche IPv4-Adresse zuweisen." aktivieren.
Als TCP Port setzt du im virtuellen Modul den Port: 80.
3) Buttons einfügen
Nun brauchen wir auch ein paar Knöpfe auf denen wir dann rumdrücken können. Beginnen wir mal mit den Tasten, welche auch physikalisch auf dem Roomba vorhanden sind:
- DOCK
- SPOT
- CLEAN
Dafür nehmen wir die "Three buttons per Line". und fügen diese über "Add set" ein. Danach kannst du die Buttons im Feld "Label" entsprechend benennen.
[carousel buttons="display" caption="display"] [panel title="Virtuelles Modul " description="Buttons benennen"] [/panel] [panel title="Virtuelles Modul " description="Buttons benennen"] [/panel] [/carousel]4) Script für CLEAN, SPOT und DOC Taste des Roomba
Jetzt geht es schon los mit etwas LUA Script. ich werfe das hier einfach mal so rein und erkläre dann ein paar Stellen, was an denen passiert. Ein kleiner Lichtblick. Das Script für alle drei Tasten ist zu 99,9% identisch, es ändert sich nur ein einziger Befehl. Kopiere das Script in "DOCK" Button und aktiviere anstelle von "String" -> "Lua code"
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
-- Setze Verbindungsdaten -- Benutzername Passwort fuer roowifi roombaUser = "admin" roombaPW = "roombawifi" -- hole ip adresse aus virtuellem modul selfId = fibaro:getSelfId() roombaIP = fibaro:get(selfId, "IPAddress") roombaPort = fibaro:get(selfId, "TCPPort") -- setze variable ROOMBA aus IP und Logindaten ROOMBA = Net.FHttp(roombaIP) ROOMBA:setBasicAuthentication(roombaUser, roombaPW) -- ------------------------------------------------- -- ------------------------------------------------- -- geting info about specific device response = ROOMBA:GET("/roomba.cgi?button=DOCK") -- decoding json string to table result = response; Fibaro.log(result); |
Dann zerlegen wir das Script einfach mal Stück für Stück.
Beginnend im Kopf Zeile 1-4
Hier werden der Benutzername und das Passwort definiert, um sich auf dem RooWifi einzuloggen. Wir erinnern uns an die Installation des RooWifi Moduls. Nach Eingabe der IP Adresse des Roomba WLAN Moduls in den Browser wird eine Authentifizierung benötigt. Hast du diese nicht geändert ist der Standardbenutzer: admin und das Standard Passwort: roowifi.
Wir definieren hier also die Variable "roombaUser" sowie die Variable "roombaPW" und füllen diese mit den entsprechenden Werten.
---------
Dann weiter in Zeile 5-8.
Über die selfId holen wir die eigene ID diesen virtuellen Moduls. In Zeile 7 definieren wir die Variable "roombaIP" und füllen Sie mit der IP Adresse, welche wir im Schritt 2 im virtuellen Modul eingetragen haben. Wie beschrieben - sollte sich die IP einmal ändern, musst du diese nur einmal oben im Kopf des virtuelle Moduls ändern.
Gleiches machen wir mit der Variable "roombaPort" welche wir hier definieren und mit dem Wert des TCP Ports füllen, welcher im Kopf des Moduls angegeben ist.
---------
Zeile 9; 10 & 11
Das ist der letzte Teil unserer Verbindungsvariablen, damit wir gleich alle Informationen vom Roomba WLAN Modul erhalten werden und auch Befehle dorthin senden können.
In Zeile 10 definieren wir die Variable "ROOMBA", welche sich aus dem HTTP Befehl und der IP Adresse des Roomba zusammensetzt. Die IP Adresse holen wir uns aus der zuvor definierten Variable "roombaIP"
In Zeile 11 erfolgt dann letztendlich der finale Aufruf und LogIn. Die Variable "ROOMBA" wird geholt gefolgt von einem Doppelpunkt, danach werden die Zugangsdaten (Benutzername und Passwort) übermittelt.
Wenn wir uns das mal aufzeigen wird im Klartext folgendes übermittelt:
http://192.168.2.125:admin@roowifi
Bis hier her alles keine Raketenwissenschaft und du musstest noch nichts ändern ;-) (Es sei denn du verwendest nicht den Standardbenutzer admin oder ein anderes Passwort)
---------
Zeile 15 & 16 - Befehl ausführen
Jetzt wird der eigentliche Befehl in der Zeile 16 gesendet. Es wird wieder die Variable "ROOMBA" geholt, welche ja bekanntlich den HTTP Request enthält, gefolgt von der IP Adresse. Jetzt fügen wir noch den auszuführenden Befehl an - In diesem Fall "/roomba.cgi?button=DOCK"
1 2 |
-- geting info about specific device response = ROOMBA:GET("/roomba.cgi?button=DOCK") |
Damit lautet unser Call im Klartext:
http://192.168.2.125/roomba.cgi?button=DOCK
Durch diesen Befehl fährt unser kleiner Putzteufel nun nach Hause an seine Dockingstation.
Bis hierher, kannst du das Script für die anderen beiden Buttons verwenden. Lediglich der Befehl in Zeile 16 ändert sich. Um Roomba auf seine neue Putztour zu schicken, verwende im hinteren Teil der Zeile 16 den Befehl:
1 2 |
-- geting info about specific device response = ROOMBA:GET("/roomba.cgi?button=CLEAN") |
Der Befehlt SPOT sieht folglich so aus:
1 2 |
-- geting info about specific device response = ROOMBA:GET("/roomba.cgi?button=SPOT") |
---------
Zeile 17 - 20
Vielleicht hast du es in der Zeile 16 schon gesehen, wir führen hier nicht nur den http Request aus, sondern erwarten auch eine Antwort, welche wir in die Variable "response" schreiben. In der Zeile 19 wandeln wir das erhaltene Ergebnis der Form halber und schreiben das Ergebnis aus response in die Variable "result". In Zeile 20 wird diese als Log ausgegeben.
Hier könntest du auch den Befehl "debug" verwenden, aber das ist eine Geschmacksache. Das Ergebnis von Fibaro Log wird im Fuß des virtuellen Moduls angezeigt. Aber dazu später mehr.
So und damit die Buttons jetzt auch noch alle schön aussehen, kannst du dir hier die Icons herunterladen. Über den Button "Symbol ändern" kannst du diese einfügen.
[icons icon="icon-folder-open"]Icon Set Roomba
4) Status von Roomba abrufen
Wir können über die API nun nicht nur Kommandos per WLAN an den Roomba Staubsauger senden, sondern bekommen auch eine Menge Informationen über ihn heraus - und das in Echtzeit.
Hierfür kannst du dir einen Button bauen, so das per Klick die Informationen aktualisiert werden. Ich habe das Script später in den "Main" Container eingefügt mit einer Schleife, so das die Informationen aller X Sekunden automatisch aktualisiert werden.
Jetzt brauchen wir neben Buttons auch Labels, in denen dann die Werte angezeigt werden. Wie viele Labels du einfügst, hängt davon ab, welche Informationen du darstellen möchtest.
4.1 Button "Status" einfügen
- ich habe hier den Typ "One button per Line" gewählt und entsprechend benannt.
4.2 Labels einfügen
... und ID wie folgt vergeben. Wie das Label heißen soll, das bleibt dir frei überlassen
- 1-Temperatur Akku- ID: LabelTemp
- 2-Gesamtkapazität Akku- ID: LabelKapazitat
- 3-Ladestatus, bzw. aktuelle Kapazität des Akkus- ID LabelCharge
- 4-Batteriestatus in Prozent- ID LabelProz (hier werden wir den Wert berechnen)
- 5- aktuelle Ladung, bzw. Entladung des Akkus- ID LabelCurrent
4.3 Variablen anlegen
Im folgenden benötigen wir mindestens eine globale Variable, in welche wir den aktuellen Ladestatus des Akkus schreiben. Diesen Wert kannst du dann nicht nur "local" in dem virtuellen Modul verwenden, sondern an jeder beliebigen Stelle in der Fibaro. So auch in Szenen ect. Falls du also später vielleicht mehrere Werte oder andere Werte des iRobot Roombas benötigst, kannst du dir analog dazu weitere Variablen anlegen.
Gehe dazu auf der Fibaro Weboberfläche auf den Menüpunkt Steuerung > links auf Variablen Steuerung und klicke auf Hinzufügen und erstelle eine neue Variable (NICHT vordefinierte Werte)
Benenne die Variable mit roombacharge - nachher wird diese stetig den aktuellen Ladestatus des Akkus enthalten.
4.4 LUA Script für den Status Button
Zurück zu unserem neuen virtuellen Modul. Wir müssen den Button "Status" noch mit Script füllen. Auch hier füge ich einfach mal das komplette Script ein, um es dann Schritt für Schritt zu erläutern. Du kannst es ersteinmal direkt in dein virtuelles Modul kopieren. Wieder daran denken bei dem Button von "String auf LUA" Code umzustellen.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
-- Setze Verbindungsdaten -- Benutzername Passwort fuer roowifi roombaUser = "admin" roombaPW = "roombawifi" -- hole ip adresse aus virtuellem modul selfId = fibaro:getSelfId() roombaIP = fibaro:get(selfId, "IPAddress") roombaPort = fibaro:get(selfId, "TCPPort") -- setze variable ROOMBA aus IP und Logindaten ROOMBA = Net.FHttp(roombaIP) ROOMBA:setBasicAuthentication(roombaUser, roombaPW) -- ------------------------------------------------- -- ------------------------------------------------- -- geting info about specific device response = ROOMBA:GET("/roomba.json") -- decoding json string to table extractedjson = json.decode(response) -- Special usecase of [""] for json tree items with a - in it. -- Be aware not to use a . infront of the [ !! -- The following JSON codes can be extracted -- All that needs to be done is replace the rX value and rename the variable to whatever you liek -- -- "r0": "Bumps Wheeldrops" -- "r1": "Wall" -- "r2": "Cliff Left" -- "r3": "Cliff Front Left" -- "r4": "Cliff Front Right" -- "r5": "'Cliff Right'" -- "r6": "Virtual Wall" -- "r7": "Motor Overcurrents" -- "r8": "Dirt Detector - Left" -- "r9": "Dirt Detector - Right" -- "r10": "Remote Opcode" -- "r11": "Buttons" -- "r12": "Distance" -- "r13": "'Angle'" -- "r14": "Charging State" -- "r15": "Voltage" -- "r16": "Current" -- "r17": "Temperature" -- "r18": "Charge" -- "r19": "Capacity" motorovercurrents = extractedjson.response.r7.value distance = extractedjson.response.r12.value chargingstate = extractedjson.response.r14.value voltage = extractedjson.response.r15.value current = extractedjson.response.r16.value temperature = extractedjson.response.r17.value charge = extractedjson.response.r18.value capacity = extractedjson.response.r19.value fcharge = fibaro:getGlobal('roombacharge') chargeProz = ((charge/capacity)*100) fchargeProz = ((fcharge/capacity)*100) -- output to resultline and globalvariable fibaro:call(selfId, "setProperty", "ui.LabelCharge.value",(charge).." mAh"); if charge > fcharge then fibaro:call(selfId,"setProperty","ui.LabelCharge.value",string.format("%d%s(↑)", charge, "mAh ")) fibaro:call(selfId,"setProperty","ui.LabelProz.value",string.format("%d%s(↑%d)", chargeProz, "% ", fchargeProz)) elseif charge < fcharge then fibaro:call(selfId,"setProperty","ui.LabelCharge.value",string.format("%d%s(↓)", charge, "mAh ")) fibaro:call(selfId,"setProperty","ui.LabelProz.value",string.format("%d%s(↓%d)", chargeProz, "% ", fchargeProz)) else fibaro:call(selfId,"setProperty","ui.LabelCharge.value",string.format("%d%s(-)", charge, "mAh ")) fibaro:call(selfId,"setProperty","ui.LabelProz.value",string.format("%d%s(-)", chargeProz, "% ")) end fibaro:setGlobal("roombacharge", charge); fibaro:call(selfId, "setProperty", "ui.LabelCurrent.value",(current).." mA"); fibaro:call(selfId, "setProperty", "ui.LabelTemp.value",(temperature).." °C"); fibaro:call(selfId, "setProperty", "ui.LabelKapazitat.value",(capacity).."mAh"); if chargingstate == "0" then fibaro:call(selfId, "setProperty", "ui.LabelState.value",(chargingstate).." Not Charging"); fibaro:log("Ladestatus: Nicht geladen") elseif chargingstate == "1" then fibaro:call(selfId, "setProperty", "ui.LabelState.value",(chargingstate).." Charging Recovery"); fibaro:log("Ladestatus: Charging Recovery") elseif chargingstate == "2" then fibaro:call(selfId, "setProperty", "ui.LabelState.value",(chargingstate).." Charging"); fibaro:log("Ladestatus: lädt") elseif chargingstate == "3" then fibaro:call(selfId, "setProperty", "ui.LabelState.value",(chargingstate).." Trickle Charging"); fibaro:log("Ladestatus: Erhaltungsladung") elseif chargingstate == "4" then fibaro:call(selfId, "setProperty", "ui.LabelState.value",(chargingstate).." Waiting"); fibaro:log("Ladestatus: wartet") else fibaro:call(selfId, "setProperty", "ui.LabelState.value",(chargingstate).." Charging Error"); fibaro:log("Ladestatus: Ladefehler") end fibaro:setGlobal("roombachargingstat", chargingstate); |
Okay, das ist jetzt erstmal viel Script - aber fühle dich nicht erschlagen. Es ist gar nicht so kompliziert. Fangen wir mal damit an.
---------
Zeilen 1-14
Das kennst du schon von unseren drei Buttons "CLEAN; DOCK und SPOT", wir definieren erst einmal die Verbindungsdaten - also Benutzername, Passwort danach IP Adresse und Port.
---------
Zeile 15 & 16
Anstatt wie vorhin einen Befehl zu senden um eine direkte Aktion auszuführen, rufen wir diesmal die /roomba.json
auf - von welcher wir eine Antwort erwarten.
---------
Zeile 17-20
Die Antwort erhalten wir natürlich von Roomba und er erzählt uns alles über sich. Diese Informationen müssen wir erst einmal verarbeiten und extrahieren. Daher folgend der Befehl:
1 |
extractedjson = json.decode(response) |
Hier werden alle Ergebnisse strukturiert, aber hintereinander weg, in die Variable "extractedjson" geschrieben.
---------
Zeile 21-45 und 46-53
In dem folgenden Block bis einschließlich Zeile 45 ist alles auskommentiert. Das heißt es wird vom Fibaro Home Center nicht verarbeitet. Dies ist eine rein informative Legende für dich, die dir zeigt, welche Ergebnisse nun in der Variable enthalten sind. Diese kannst du je nachdem welche Werte du benötigst im folgenden extrahieren.
Genau das passiert ab Zeile 46. Hier wird die Variable "motorovercurrents" definiert, welche mit dem Ergebnis .r7 der Antwort gefüllt wird. -> (Siehe Legende: r7 = "Motor Overcurrents")
1 |
motorovercurrents = extractedjson.response.r7.value |
So werden alle folgenden Variablen definiert und befüllt. In Zeile 47 wird die Variable "distance" mit dem Wert .r12 gefüllt ->(Siehe Legende: r12 = "Distance") ; Zeile 48 wird die Variable "chargingstate" definiert und mit dem Wert .r14 aus der Antwort gefüllt -> (Siehe Legende: r14 = "Charging State") und so weiter.
Wie du siehst habe ich nicht alle Ergebnisse extrahiert. Also falls dich weitere Werte interessieren welche in der Legende stehen, so füge einfach eine neue Zeile hinzu und definiere eine neue Variable. Dann musst du nur noch den Wert aus der Antwort extrahieren und in der Variable speichern.
---------
Zeile 54 -59
Hier muss ich jetzt etwas vorgreifen, um erklären zu können was ich an dieser Stelle vor habe. Ich definiere nun die "local" Variable "fcharge"und befülle Sie mit dem Wert aus der globen Variable "roombacharge", welche wir gerade angelegt haben. Das "f" vor der lokalen Variable nutze ich um deutlich zu trennen das ich hier eine andere Variable als "Charge" nutze, die es ja bereits im virtuellen Modul gibt.
Was will ich hier eigentlich erreichen? Ich möchte den aktuellen Ladestatus des Akkus (charge) mit dem Wert vergleichen der beim letzten Statusabruf in die globale Variable (roombacharge) geschrieben wurde (welche ich mir ja in die local Variable fcharge hole), um zu ermitteln ob der Akku ent-laden oder ge-laden wird. So können wir dies nachher grafisch deutlicher darstellen.
1 |
fcharge = fibaro:getGlobal('roombacharge') |
Da wir bislang noch keinen Wert in die globale Variable geschrieben haben (das kommt etwas weiter unten im Script) wird das Ergebnis beim ersten Klick auf den Status Button logischerweise Null (0) sein.
In Zeile 57 und 58 stelle ich zwei Berechnungen an, um nachher den Ladezustand des Akkus in Prozent (%) ausgeben zu können. Hierbei teile ich in der ersten Rechnung die aktuelle Ladekapazität des Akkus (charge) durch die maximal mögliche Kapazität des Akkus (capacity) und multipliziere dann mit 100, um das Ergebnis Ladestatus in Prozent zu erhalten - welches dann in die local Variable chargeProz gespeichert wird.
1 |
chargeProz = ((charge/capacity)*100) |
In der Zeile 58 führe ich die identische Rechnung aus, nur eben mit der Ladekapazität, welche beim letzten Statusupdate ermittelt wurde (fcharge). So können wir nachher den lade- bzw. Entladevorgang des Akkus grafisch besser darstellen.
1 |
fchargeProz = ((fcharge/capacity)*100) |
Zeile 60 & 61
Bis hier hin haben wir die Werte, welche uns der Roomba von sich Preis gegeben hat, in Variablen gespeichert und einige Werte haben wir berechnet. Jetzt wollen wir uns natürlich diese auch anzeigen lassen. Genau das machen wir in der Zeile 61. Mit dem Befehl "fibaro:call(selfId," holen wir uns wieder die ID dieses von uns angelegten virtuellen Moduls, damit wir den Wert auch in diesem Modul schreiben und nicht irgendwo hin ;-) . Danach übergeben wir den Wert der aktuellen Ladekapazität an das Label, welches die ID LabelCharge trägt, indem wir die Variable (charge) laden. Damit wir auch wissen was die Zahl zu bedeuten hat, schreiben wir "mAh" für Milliampere Stunden dahinter.
1 |
fibaro:call(selfId, "setProperty", "ui.LabelCharge.value",(charge).." mAh"); |
---------
Zeile 62-72
Lass dich von dem Quelltext nicht erschlagen, es sieht komplexer und komplizierter aus als es ist. Also, was passiert hier? Wir haben nun die Variable "charge" welche die aktuelle Ladekapazität des Akkus enthält und wir haben die Variable "fcharge", die den vorangegangenen Ladestatus enthält, welchen wir beim letzten Statusabruf erfahren haben. Im folgenden Teil vergleiche ich einfach beide Variablen und mache davon abhängig, was in das Label LabelCharge sowie in das Label LabelProz geschrieben wird.
Fibaro LUA If - else
1 |
if charge > fcharge then |
1 2 |
fibaro:call(selfId,"setProperty","ui.LabelCharge.value",string.format("%d%s(↑)", charge, "mAh ")) fibaro:call(selfId,"setProperty","ui.LabelProz.value",string.format("%d%s(↑%d)", chargeProz, "% ", fchargeProz)) |
Jedes mit % angefangene Zeichen wird für den entsprechenden Teilstring verwendet.
1 |
("%d%s(↑)", charge, "mAh ")) |
- %d -> legt fest, das eine Dezimalzahl ohne Nachkomma ausgegeben wird => wird auf die ausgegebene Variable (Charge) angewendet
- %s -> besagt das der Wert genauso dargestellt werden soll => wird auf den Text String "mAh" angewendet
- (↑) -> wird angefügt um grafisch zu symbolisieren das AUFgeladen wird.
In der Zeile 65 passiert nichts anderes, lediglich die Formatierung ändert sich einwenig. Hier wird der zuvor errechnete aktuelle Ladestatus des Akkus in Prozent in das Label LabelProz geschrieben und der Wert aus der Variable "charge" in Prozent dargestellt. Auch hier gefolgt von dem Pfeil nach oben um zu symbolisieren, das der Akku AUFgeladen wird. Dahinter wird noch einmal der Wert auf "fcharge" angezeigt um aufzuzeigen "von welchem Wert wir kommen".
1 |
fibaro:call(selfId,"setProperty","ui.LabelProz.value",string.format("%d%s(↑%d)", chargeProz, "% ", fchargeProz)) |
Wenn du dich an dieser Stelle etwas tiefer in das Thema "format.string" einarbeiten möchtest, bzw. generell in LUA, schau mal auf der Seite von lua.gts-stolberg.de vorbei. Hier findest du wirklich gute Basics für das programmieren mit LUA.
ElseIf
Wenn die erste Bedingung nicht erfüllt ist, also die aktuelle (Akku) Kapazität nicht größer als die vorangegangen Kapazität ist, dann gilt diese Bedingung als nicht erfüllt. Somit wird die Fibaro die nächste, also die elseIf Bedingung prüfen.
1 |
elseif charge < fcharge then |
Hier wird genau andersherum geprüft: Ist die aktuelle (Akku) Kapazität kleiner als (<) die vorangegangen Kapazität? Wenn ja - passiert genau das gleiche wie zuvor. Die beiden Labels: LabelCharge sowie LabelProz werden befüllt. Nur diesmal mit einem Pfeil nach unten, denn ist die aktuelle Akkukapazität kleiner als zuvor, wird der Akku ENTladen.
Else
Zu guter Letzt müssen wir der Fibaro natürlich auch noch sagen was diese machen soll, wenn beide vorangegangen Bedingungen nicht erfüllt sind - spich die Kapazität des Akkus unverändert blieb
1 2 3 4 |
else fibaro:call(selfId,"setProperty","ui.LabelCharge.value",string.format("%d%s(-)", charge, "mAh ")) fibaro:call(selfId,"setProperty","ui.LabelProz.value",string.format("%d%s(-)", chargeProz, "% ")) end |
Hier wird nichts mehr geprüft oder miteinander verglichen. An dieser Stelle werden die Labels einfach befüllt. Statt einem Pfeil zeigt ein Minus (-) das die Ladung unverändert blieb.
---------
Zeile 73
Erst jetzt schreibe ich den Wert der aktuellen (Akku) Ladekapazität, welchen wir zuvor extrahiert und in die local Variable "charge" gespeichert haben, in die globale Variable "roombacharge".
1 |
fibaro:setGlobal("roombacharge", charge); |
Dieser Wert dient dann wieder als Referenzwert um herauszufinden ob der Akku ge- oder entladen wird. Benötigst du wie vorhin kurz angesprochen weitere Werte in einer globalen Variable, kannst du diesen Befehl analog mit jedem anderen Wert ausführen. Du musst dazu nur jeweils eine globale Variable anlegen. Möchtest du zum Beispiel auch die Akku-Temperatur in einer globalen Variable speichern, so erstelle die Variable "roombatemperature" und der Befehl würde wie folgt aussehen:
1 |
fibaro:setGlobal("roombatemperature", temperature); |
---------
Zeile 74-80
Hier werden die weiteren Werte an die entsprechenden Lables übergeben. Der Befehl dafür ist analog dem, wie in Zeile 61 erklärt.
- ID LabelCurrent gefüllt mit der aktuellen Ladung. Findest eine ENTladung statt hat der Wert ein negatives Vorzeichen
- ID LabelTemp - mit der aktuellen Temperatur des Akkus in Grad Celsius (°C)
- ID LabelKapazitat - mit der maximal möglichen Ladekapazität des Akkus in mAh
Zeile 81-99
Unser kleiner Putzteufel erzählt uns sogar in welchem Ladezustand er sich gerade befindet. Dies möchte ich an dieser Stelle in das Label schreiben. Da wir über die API von Roomba aber nur Zahlen von 0-5 zurück erhalten, müssen wir diese übersetzten. Das passiert hier ab Zeile 81. Mit einer IF Abfrage wird geprüft ob der zurück erhaltene Wert Null (0) ist. Wenn dies Bedingung erfüllt ist, so wird das Label LabelState beschriftet mit dem String: Not Charging. In der folgenden Zeile wird der Ladezustand auch im Log ausgegeben. Das Log wird im Fuß des virtuellen Moduls angezeigt. Natürlich kannst du beide Text Strings ins Deutsche übersetzen, ich habe hier einmal DE und einmal EN verwendet um es besser zu veranschaulichen.
Sollte der Ladestatus nicht Null sein, so arbeitet Fibaro die nächste Zeile ab, in welcher mit dem Befehl "elseIf" nacheinander alle weiteren Möglichkeiten geprüft werden.
Welche Ziffer als Antwort im Ladestatus welche Bedeutung hat, habe ich in dem iRobot "Roomba Serial Common Interface (SCI) Specification[icons icon="icon-acrobat" color="#1e73be" size="13"] gefunden. Für diese Geschichte hier, eine wirklich grandiose Hilfe!
So geschafft, das war das Script des "Status" Buttons. Wenn du diesen nicht stetig drücken möchtest, so kannst du das Script unverändert in den Main Container des virtuellen Moduls kopieren. Dann wird das Script jede Sekunde ausgeführt. Ob das für den Roomba jetzt so gesund ist weis ich nicht, daher habe ich bei mir noch den Befehl: fibaro:sleep(60000); angefügt. Damit pausiert das Script eine Minute bevor es erneut ausgeführt wird.
1 |
fibaro:sleep(60000); |
5) noch mehr Knöpfe
jetzt noch eine kleine Spielerei und zwar bauen wir noch drei neue Button ein, über welche wir einzeln die Seitenbürste, die Hauptbürste und den Sauger aktivieren können. Hierzu wieder "Three buttons per Line" einfügen. Benenne Sie entsprechend wie du magst. In meinem Beispiel habe ich MainBrush ; Vaccum und SideBrush verwendet.
So hier erstmal das Script: welches du in den ersten Button einfügen kannst. Beachte wieder das du von String auf LUA umschaltest.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
-- Setze Verbindungsdaten -- Benutzername Passwort fuer roowifi roombaUser = "admin" roombaPW = "roombawifi" -- hole ip adresse aus virtuellem modul selfId = fibaro:getSelfId() roombaIP = fibaro:get(selfId, "IPAddress") roombaPort = fibaro:get(selfId, "TCPPort") -- setze variable ROOMBA aus IP und Logindaten ROOMBA = Net.FHttp(roombaIP) ROOMBA:setBasicAuthentication(roombaUser, roombaPW) -- ------------------------------------------------- -- ------------------------------------------------- -- fuehre Befehl Hauptbuerste aus response = ROOMBA:GET("/rwr.cgi?exec=j") -- decoding json string to table result = response; Fibaro.log(result); |
Wie du vielleicht schon gesehen hast ist ALLES bist auf die Zeile 16 identisch mit den ersten drei Buttons Clean, DOCK und SPOT. Wir übergeben die Verbindungsdaten, bestehend aus Benutzername, Passwort und der IP und senden dann in Zeile 16 einen Befehl. Doch woher kommt dieser?
Gehe dazu auf die WebUI des RooWifi Moduls. Navigiere dann im rechten Menü auf "Driver´s Remote". Wenn du im Browser mit einem rechts Klick auf "MainBrush" klickst, hast du die Option "Element untersuchen" (Je nach Browser anders benannt). Dort siehst du, das folgender Befehl gesendet wird:
1 |
<a onclick="RWAxCom('rwr.cgi?exec=j');"> |
Im Prinzip kannst du dir auf diesem Weg die ganze Drivers Remote für Roomba nachbauen - wer´s braucht ;-) . Die anderen beiden Buttons sind natürlich nach genau dem gleichen Prinzip aufgebaut. Für die Seitenbürste lautet der Befehl übrigens:
1 |
response = ROOMBA:GET("/rwr.cgi?exec=k") |
Den Button für "vaccum" habe ich hier mal auf "Empty" gesetzt da er den gleichen Befehl (rwr.cgi?exec=j") wie auch die Hauptbürste verwendet. Ob das ggf. ein Fehler auf der RooWifi WebUI ist?
6) Drivers Mode (nicht ganz unwichtig!!)
So, nun haben wir das virtuelle Modul für unseren WLAN Staubsauger fast Schritt für Schritt analysiert. Bis auf den letzten Button: "Drivers Mode" - was macht der? Das RooWifi Modul, bzw. der Roomba Staubsauger, fällt nach einer gewissen Zeit in eine Art Standby. Erinnerst du dich an die iOS bzw. Android App? Auch dort hast du einen On/Off Schalter für den "Drivers" Mode. Sobald du diesen betätigst, begrüßt dich Roomba mit einem kurzen Piepton. Erst danach kann es los gehen. Genau diesen Button bauen wir hier nach. Also einfach noch einen "One button per Line" einfügen und diesen mit "Drivers Mode" beschriften (oder was du magst).
Hier erstmal das Script welches du wieder direkt kopieren kannst.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
-- Setze Verbindungsdaten -- Benutzername Passwort fuer roowifi roombaUser = "admin" roombaPW = "roombawifi" -- hole ip adresse aus virtuellem modul selfId = fibaro:getSelfId() roombaIP = fibaro:get(selfId, "IPAddress") roombaPort = fibaro:get(selfId, "TCPPort") -- setze variable ROOMBA aus IP und Logindaten ROOMBA = Net.FHttp(roombaIP) ROOMBA:setBasicAuthentication(roombaUser, roombaPW) -- ------------------------------------------------- -- ------------------------------------------------- -- oeffne Drivers Remote response = ROOMBA:GET("/c.html"); fibaro:sleep(3500); -- starte Drivers Mode response = ROOMBA:GET("/rwr.cgi?exec=h"); fibaro:sleep(2000); -- decoding json string to table result = response; Fibaro.log(result); |
Bis zu Zeile 13 ist alles gleich, wie bei den vorangegangenen Buttons auch. In der Zeile 16 öffne ich die Seite /c.html der RooWifi WebUI. Mit dem Befehl fibaro:sleep(3500); in Zeile 17, warte ich bis die Fibaro die Seite fertig geladen hat.
In Zeile 19 führe ich den Befehl für den Drivers Mode aus - genauso wie wir dies gerade bei den Buttons für die Haupt- und Seitenbürsten gemacht haben. Den Befehl habe ich mir ebenfalls über "Element untersuchen" auf der WebUI des RooWifi ermittelt.
Diesen Button habe ich als "Main" gesetzt, so wird er in der Modulübersicht mit angezeigt. Wenn du Roomba also ab sofort in Szenen verwendest, denke daran dass zuerst dieser Button gedrückt wird, bevor du weitere Knöpfe virtuell drückst. Alternativ kannst du die Zeilen 13-20 bei jedem Button voranstellen - dann hast du aber immer die Verzögerung durch den Befehl"fibaro:sleep".
So nun bin ich wahnsinnig auf eure Ideen gespannt. In welchen Szenen verwendest du Roomba und welche Modifikationen hast du an dem virtuellen Modul noch vorgenommen? Ich bin super gespannt und freue mich auf eure Kommentare.
Falls du zu faul bist das Modul nachzubauen ;-) kannst du es nun hier herunterladen und es in dein Fibaro HC2 importieren.
Download - iRobot Roomba mit RooWiFi als virtuelles Modul
Alle Beiträge zu dieser Tutorial Reihe findest du unter dem Tag: RooWifivsThinkingCleaner
Super Anleitung.
Vielen Dank für deine Arbeit!
Die Icons sind leider offline, gibt es die Möglichkeit diese nochmal zur Verfügung zustellen?
Danke & Gruß
Ai, danke für den Hinweis! Habs repariert :-) der Link im Artikel geht wieder. Ansonsten klick hier.
gibt es das auch für die HCL ?
danke Kurt
Fertig nicht, kannst das VD aber sicherlich anpassen. :)
Gruß
hallo,
besteht die möglichkeit den roomba 980 mit wlan ebenfalls ins HC2 zu integrieren?
mfg
Hallo,
vielen Dank für dieses hilfreiche Tutorial.
Mein thinkingcleaner ist leider defekt, so dass ich mir eine Roowifi für meinen Roomba (Serie 600) besorgt habe.
Mit dem Roowifi habe ich folgendes Problem:
Der Roomba geht nach wenigen Minuten in eine Art "Tiefschlaf" (Leuchtkreis oben ist aus), dann lässt sich der Roomba leider nicht mehr reaktivieren.
Egal ob ich im Webinterface (von Roowifi) den Driver Mode drücke oder über das HC2, der Staubsauger schläft.
Betätige ich dann 1x die CLEAN Taste (auf dem Staubsauger) ist der Staubsauger wach und nimmt alle Befehle des HC2 entgegegen.
Kennt jemand dieses Problem? Gibt es dazu eine Lösung?
Ich habe schon probiert den Drivers Mode in die primär Schleife zu setzen.
Doch leider ohne Erfolg.
Vielen Dank für Eure Hilfe ....
Gruß
Markus
Hallo,
ich habe mir den Roomba 966 mit interiertem WLAN gekauft.
Das virtuelle Modul herunter geladen, mit dir BLID und das Passwort organisiert.
Aber eine Steuerung über das VD ist nicht möglich.
Ich bekomme noch nicht einmal eine Fehlermeldung ausser beim Debug der Buttons immer nur die Meldung (z.B. beim Button DOCK):
[ERROR] 18:14:43: line 20: attempt to index global 'Fibaro' (a nil value)
Hat hier jemand einen Rat was ich noch probieren kann?
Den Port 80 und die IP des Roomba habe ich im VD auch hinterlegt.
Vielen Dank im Voraus.
Grüße
Henning