(MP-WS12-02)

Aus Verteilte Systeme - Wiki
Wechseln zu: Navigation, Suche

Inhaltsverzeichnis

Einführung

Dieses Projekt wurde von Iwan Berger (B.Sc.) im WS2012/13 im Rahmen des Master-Projekts durchgeführt. Ziel waren Analyse und Integration einer kommerziellen Home-Automation-Lösung in eine AAL-Umgebung.

Das Projekt entstand im Labor für Verteilte Systeme der Hochschule RheinMain, unter Leitung von Prof. Dr. Reinhold Kröger, als Teil des Forschungsprojekts WieDAS. An WieDAS beteiligt waren unter anderem Marcus Thoss (Dipl.-Inform. (FH), M.Sc.), Kai Beckmann (Dipl.-Inform. (FH), M.Sc.) und Jan Schäfer (Dipl.-Inform. (FH), M.Sc.).

Die Wiesbaden-Düsseldorfer Ambient Assisted Living Service Plattform (kurz WieDAS) ist eine Plattform für verteilte Assistenzsysteme. Die Domäne Ambient Assisted Living steht hierbei für umgebungsunterstütztes Leben und soll selbstbestimmtes Leben durch innovative Technik fördern. Ziel ist bspw. das alltägliche Leben älterer und auch benachteiligter Menschen situationsabhängig und unaufdringlich zu unterstützen. Schwerpunkte liegen auf Sicherheit, Komfort und Unterhaltung. Hierfür müssen von Sensoren erfasste Daten zentral gesammelt und ausgewertet und über Aktoren entsprechende Reaktionen ausgeführt werden.

Das WieDAS Projekt wird zu 100% vom BMBF im Rahmen der Initiative FHprofUnd (Förderkennzeichen 17040B10) finanziert und u.a. durch folgende Partner aus Forschung und Industrie unterstützt:

  • Fachbereich Sozialwesen der Hochschule RheinMain
  • Labor für Informatik der Fachhochschule Düsseldorf
  • D-Link Deutschland GmbH
  • GWW Wiesbadener Wohnbaugesellschaft mbH
  • Phoenix Software GmbH
  • isb Ambulante Dienste gGmbH
  • Wohnberatung für ältere und behinderte Menschen der Stadt Düsseldorf

Ab Mitte April 2013 wird die erste (von der GWW zur Verfügung gestellte) Wohnung zu Test- und Demonstrationszwecke mit WieDAS ausgestattet.

Plugwise

Hardware

Für die WieDAS Plattform werden Home-Automation Geräte benötigt, als kommerzielle Home-Automation-Lösung dienen die Hardware Produkte der Firma Plugwise. Das Plugwise System beruht auf dem drahtlosen Kommunikationsprotokoll ZibBee, das optimiert ist so wenig Energie wie möglich zu verbrauchen. Dies schränkt zwar den Sendebereich eines einzelnen Moduls ein, dennoch können größere Gebiete durch das Netzwerk abgedeckt werden, da die Module Informationen an andere Module weiterleiten können.

Die Plugwise Geräte umfassen:

Stick
Der Stick ist ein USB Gerät mit dessen Hilfe die Plugwise Module mit dem PC kommunizieren können.
Circle+
Der Circle+ definiert welche Module zu einem Netzwerk gehören. Dieses Attribut spielt nur eine Rolle, wenn dem Netzwerk neue Module hinzugefügt werden. Der Circle+ enthält außerdem eine Uhr mit der die anderen Module ihre Zeitstempel synchronisieren. Der Circle+ muss immer zuerst installiert werden und sich in Netzwerkreichweite befinden, auch wenn kein Gerät angeschlossen ist. Ansonsten verhält er sich wie ein regulärer Circle.
Circle
Der Circle ist das Grundmodul eines Plugwise Netzwerks. Er misst den Energieverbrauch und kann angeschlossene Geräte an- und abschalten.
Stealth
Ein Stealth verhält sich wie Circle, kann jedoch fest (unterputz) installiert werden.
Switch
Der Switch ist ein drahtloser Schalter über den Circles im Netzwerk an- und abgeschaltet werden können.

Software

Konfiguration, Steuern und Auswerten der Geräte geschieht standardmäßig über die mitgelieferte Plugwise Source Software. Diese Software ist nur für Microsoft Windows Betriebssysteme verfügbar. Über eine grafische Benutzeroberfläche kann mittels der Source Software ein Plugwise Netzwerk konfiguriert und Module eingebunden werden. Für Circles können, zur einfacheren Verwaltung, Ort und Typ angeschlossener Geräte definiert werden. Zusätzlich ist das zusammenfassen in logische Schaltgruppen möglich. Nach Auswahl eines Circles kann dieser geschaltet werden, sowie aktuelle und gespeicherte Verbrauchswerte abgefragt werden. Ins Netzwerk eingebundenen Plugwise-Switches können über die Software Schaltgruppen von Circles zugewiesen werden.

Bemerkenswert ist, dass das Nutzerverhalten (z.B. Verbrauchswerte der Geräte) durch die Plugwise Source Software gesammelt und an Plugwise übermittelt wird.

Ziel des Projekts

  • Hauptziel ist die Integration der Produkte der Firma Plugwise in WieDas, hierdurch soll die Möglichkeit zum Verwalten/Steuern/Auswerten der Plugwise-Geräte ermöglicht werden.
  • Zunächst ist hierfür ein Reengeneering der Kommunikation zum Steuerstick notwendig, welches eine möglichst weitgehende Analyse der Kommunikation erfordert. Als Nebenprodukt soll hierbei eine in der Programmiersprache C implementierte Low-level API zum Zugriff auf Plugwise- Module erstellt werden. Diese API soll dann in WieDAS verwendet werden.

Plugwise Library

Analyse

Dieser Abschnitt beschreibt die Analyse der Hardwarekommunikation, des kommunizierten Nachrichteninhalts, des Nachrichtenformats sowie des Übertragungsprotokolls.

Hierfür wurde unter anderem auf folgende bestehende Ausarbeitungen zurückgegriffen:

Maarten Damen
In seinem Blog (http://www.maartendamen.com/category/plugwise-unleashed/) beschrieb Maarten Damen als erster den Aufbau des Transportprotokolls bestehend aus Head, Footer und CRC, sowie erste Request/Response Paare. Seine Programme sind in Python implementiert.
roheve
Im Blog unter http://roheve.wordpress.com/category/domotica/ wurden weitere Request/Response Paare sowie die darin enthaltenen Datenstrukturen analysiert. Seine Programme sind in VBscript implementiert.
HomeControl
Im WS2011/12 wurde von Iwan Berger, Patrick Dias und Matthias Oberländer im Rahmen der Veranstaltung Industrial and Home Automation bei Prof. Kaiser ein Java Projekt mit Verwendung von Plugwise-Modulen erstellt.

Aufbauend auf diesen Arbeiten ist das Ziel weitere Request/Response Paare (speziell zur Konfiguration des Plugwise-Netzwerks) zu analysieren und über eine C API zugänglich zu machen.

Unbekannte Elemente müssen hierfür mittels Analyse operationeller Log-Daten reengineert werden.

Hardware Kommunikation

Untereinander kommunizieren die Plugwisegeräte über ZigBee. Dies ist nicht Bestandteil dieser Ausarbeitung.

Sie Schnittstelle der erstellten Library ist der Plugwise USB-Stick. Dieser beinhaltet einen Future Technology Devices International, Ltd FT232 USB-Serial (UART), ein elektronisches Bauelement, welches zur Realisierung von digitalen seriellen Schnittstellen dient. Der Stick wird unter Windows XP und Linux automatisch erkannt.

Unter Linux kann der Stick gegebenenfalls über folgendes Kommando konfiguriert werden:

stty -F /PATH/TO/STICK ispeed 115200 ospeed 115200 -parenb -parodd cs8 hupcl -cstopb cread -clocal -crtscts -ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany -imaxbel -iutf8 -opost -olcuc -ocrnl -onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0 -isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase -tostop -echoprt -echoctl -echoke

operationelle Log-Daten

Um Live-Daten der Kommunikation zwischen der Plugwise Source Software und dem Plugwise USB-Stick mitschneiden zu können, wurde das Tool portmon aus den Microsoft sysinternals verwendet. Da dieses Programm leider nicht für 64bit Plattformen verfügbar ist, wurde der Mittschnitt unter Microsoft Windows XP durchgeführt. Hierfür muss vor dem Start der Plugwise Source Software portmon gestartet und konfiguriert werden. Zunächst muss portmon mit dem lokalen Computer verbunden werden und der entsprechende Virtual COM-Port (hier VCP0) ausgewählt werden.

Zur vereinfachten Vergleichbarkeit mit in dieser Ausarbeitung aufgeführten Werten sollte die ASCII-Darstellung kommunizierter Bytes gewählt werden. Folgend ein Beispiel-Mitschnitt:

 7  18:43:06  PlugwiseConfig.  IRP_MJ_READ  VCP0  Length 72
 7  18:43:06  SUCCESS  Length 77: ....00240105000D6F000076C6E7000000000000000000806539070085114DCCDA6900AF50...
 8  18:43:06  PlugwiseConfig.  IOCTL_SERIAL_WAIT_ON_MASK  VCP0  
 8  18:43:06  SUCCESS  
 9  18:43:06  PlugwiseConfig.  IOCTL_SERIAL_WAIT_ON_MASK  VCP0  
10  18:43:06  PlugwiseConfig.  IOCTL_SERIAL_GET_COMMSTATUS  VCP0  
10  18:43:06  SUCCESS  
11  18:43:14  PlugwiseConfig.  IRP_MJ_WRITE  VCP0  Length 30: ....0023000D6F0000996749FC24..
11  18:43:14  SUCCESS
Shell/Python Scripte

Zur Unterstüzung der Log-Daten Analyse wurden folgende Scripte erstellt:

filter_READ_bytes.sh
filtert empfange Bytes
grep READ -A 1 logs/registering_7361A6_hex.log | grep SUCCESS | sed 's/.*: //g'
filter_WRITE_bytes.sh
filtert gesendete Bytes
grep WRITE logs/registering_7361A6_hex.log | sed 's/.*: //g'
translate_hex.py
Übersetzt einen Strom von Paaren von Hexadezimalzeichen in entsprechende Dezimalwerte.
filter_read_write.py
Filtert kommunizierte Bytes. Folgend ein gefiltertes Beispiel-Log:
18:45:48  WRITE  ....0008005049..
18:45:48  READ   ....0000017600C1E919...
18:45:48  READ   ....0000017600DD000D6F0000996749B017..
18:45:57  WRITE  ....0023000D6F0000B811035E48..
18:45:57  READ   ....0000017700C14348..
18:45:57  READ   # APSRequestNodeInfo: Source MAC: 000D6F000076C6E7# APSRequestNodeInfo: Destination MAC: ..000D6F0000B81103...
18:45:57  READ   ....00240177000D6F0000B81103000101DC0004406001856539070140234DCCDB7B0233A8..

Für die Analyse unbekannter Nachrichtentypen wurden nach Durchführung zu analysierender Funktionalitäten in der Plugwise Source Software die (mittels filter_read_write.py) gefilterten portmon-Logs untersucht. Hierfür wurden zunächst unbekannte MessageCodes am Anfang der kommunizierten Nachrichten ermittelt um anschließend die darin enthaltenen Felder zu separieren und zu interpretieren. Besonders hervor stachen hierbei die übertragenen MAC-Adressen welche stehts in der Form 000D6F000XXXXXXX auftraten. Für weitere Felder wurde unterschiedliche Nachrichten des gleichen Typs verglichen. Nach Erstellung passender Request bzw. Response Strukturen konnte versucht werden die entsprechenden Dialoge mit reengineertem Programm-Code nachzuspielen.

Übertragungsprotokoll
Header/Footer
Übertragene Daten sind (meistens) von Header und Footer eingeschlossen. Der Header besteht aus den 4 Bytes 0x05 0x05 0x03 0x03. Der Footer aus 0x0D 0x0A (ein Windows Zeilenumbruch).
Leider gibt es auch Daten welche zwischen einem Footer und einem darauf folgenden Header gesendet werden (hier Out of Bound-Data, kurz OoB, genannt). Dies können entweder einzelne Bytes (bspw. 0x83) oder ganze, menschenlesbare, ASCII-Zeichenketten sein. Letztere könnten eine Art Broadcast zum Anfordern von Geräte-Informationen sein.
Prüfsumme
Zur Erkennung von Übertragungsfehlern sind die übertragenen Nutzdaten über eine zyklische Redundanzprüfung gesichert. Es wird eine CRC16 mit folgenden Parametern berechnet:
- Polynomial : 0×11021
- Seed value : 0×00000
- XOR mask  : 0×00000
Hinweis: Die Prüfsumme wird aus bereits kodierten Daten berechnet. Die berechnete Prüfsumme wird ebenfalls kodiert (es werden also 4 Bytes für die Prüfsumme übertragen).
Kodierung
Die, in network-byte-order vorliegenden, zu übertragenen Daten werden als Hexadezimaldarstellung des entsprechenden Bytewerts kodiert.
18010 = 101101002 = 0xB416
Hexadezimal-String: "B4"
kodiert: 0x42 0x34
Die kodierten kommunizierten Nutzdaten sind somit alle im ASCII-Bereich 0-9A-F.
Anwendungsprotokoll

Die Nutzdaten auf Anwendungsebene sind in entsprechende Request- bzw. Response-Strukturen verpackt. Folgend die am häufigsten auftretenden Felder:

Message Code
Allen Nachrichten gemein ist das Feld Message Code, eine 16bit Zahl zur Identifizierung des entsprechenden Nachrichten-Typs.
Problematisch hierbei ist, dass sich aus dem Message Code nicht eindeutig auf die Nachrichtenlänge schließen lässt, da sich bspw. Acknowledge- und System Response den Message Code 0000 teilen aber unterschiedliche Größe haben. Die Anzahl empfangender Bytes einer Nachricht muss also zur Typbestimmung mit herangezogen werden.
Sequence Number
Alle Responses enthalten (nach dem Message Code) das Feld Sequence Number, eine 16bit Zahl zur Zuordnung von Responses zum entsprechenden Request.
Nach dem Senden eines Requests antwortet der Stick sofort mit einer Acknowledge Response, welche eine Sequence Number enthält. Ist die Acknowledge Response eine positive Empfangsbestätigung, so kann über diese Sequence Number die später empfangene richtige Response zugeordnet werden.
MAC-Adresse
Die meisten Requests beziehen sich auf ein bestimmtes Plugwise-Gerät. Diese Requests werden anhand der MAC-Adresse des entsprechenden Geräts adressiert.

Neben einfachen Ganzzahlwerten (8bit, 16bit, 32bit, 64bit jeweils signed/unsigned) sowie Fließkommazahlen (16bit float) gibt es folgende interessante Feldstrukturen:

Datenstrukturen
Kalibrierungsdaten
Verbrauchsdaten von Circles werden in Pulsen gezählt. Um Fertigungstoleranzen auszugleichen können von jedem Circle die verwendeten Kalibrierungsparameter angefordert werden. Diese bestehen aus vier Fließkommazahlen, von Maarten Damen gain_a, gain_b offset_total und offset_noise genannt. Zur Berechnung korrigierter Werte wird zunächst offset_noise auf die empfangene Pulszahl addiert (man erhält denoised_pulses). Den ersten weiteren Summand erhält man, indem gain_b mit den quadrierten denoised_pulses multipliziert wird, den zweiten Summand indem gain_a mit denoised_pulses multipliziert wird. Die Summe dieser beiden Summanden addiert mit offset_total ergibt den mit Kalibrierungsparametern korrigierten Pulswert welcher über einen Magic-Faktor (468.9385193) in Watt bzw. kW/h umgerechnet werden kann.
Device Info
Von den unterschiedlichen Plugwise Modulen können Geräte Informationen angefordert werden. Diese umfassen die aktuelle Log-Zeit und Log-Adresse (zur Aufzeichung von Verbrauchsdaten) den aktuellen Relaiszustand und die Hertz Zahl des Stromnetzes (jewils nur bei Circles gesetzt, 0 bei anderen Modultypen). Zusätzlich gibt es für alle Modultypen Felder für die Hardwareversion, die installierte Firmware sowie ein Feld für den Modultyp (Stick, Circle+, Circle oder Switch).
Zeitformate

Folgende Felder sind alles aus 4 Byte bestehende Zeitangaben:

UNIX-epoch
Eine positive Ganzzahl welche als Anzahl vergangener Sekunden seit dem 1.1.1970 interpretiert wird
pw_clock
Diese Struktur wird als Uhrzeit interpretiert. Das erste Byte ist der Wert der aktuellen Stunde in UTC. Das zweite Byte die aktuellen Minutenzahl und das dritte Byte die aktuelle Sekundenzahl. Das vierte Byte wird als aktueller Wochentag interpretiert, wobei der Wert 1 für Montag steht und der Wert 7 für Sonntag.
pw_timestamp
Zur Zuordnung von aufgezeichneten Verbrauchswerten zu Zeitpunkten wird diese Zeitstempel-Struktur verwendet. Das erste Byte steht für das entsprechende (2000-basierte) Jahr. Das zweite Byte steht für den entsprechende Monat, wobai Januar den Wert 1 und Dezember den Wert 12 hat. Das dritte und vierte Byte bilden zusammen eine positive 16bit Ganzzahl welche als die Anzahl vergangener Minuten im entsprechenden monat interpretiert wird.
Log-Addresse
Aus pw_timestamp Zeitstempel-Werten kann über Referenzwerte eine Log-Addresse berechnet werden. Über diese können aufgezeichnete Verbrauchswerte einem Zeitpunkt zugeordnet werden.

Logs typischer Anwendungsfälle

Dieser Abschnitt stellt typische Anwendungsfälle einer High-Level-Applikation in Form kommunizierter (mit portmon aufgezeichneter und mit Scripten bereinigter) Request/Response Paare vor. Am Ende befinden sich aufgezeichnete Dialoge welche noch keiner Funktionalität zugeordnet werden konnten.

Meistens wird eine Dialog durch Senden (W/WRITE) eines Requests eingeleitet. Darufhin werden Responses empfangen (R/READ). Die vier Punkte am Nachrichtenanfang sind der Plugwise-Header (bestehend aus vier nicht-druckbaren ASCII-Zeichen) gefolgt vom, den Nachrichtentyp identifizierenden, Message Code (bestehend aus vier Hexadezimal-Zeichen). Nachrichten enden in der CRC-Summe (bestehend aus vier Hexadezimal-Zeichen) gefolgt vom Plugwise-Footer (bestehend aus zwei nicht-druckbaren ASCII-Zeichen). Bei empfangenen Nachrichten folgt auf den Message Code die aus vier Hexadezimal-Zeichen bestehende Sequenznummer. Empfangene Nachrichten der Form

....0000 XXXX 00C1 YYYY..

sind positive (00C1) Acknowledge Nachrichten, wobei das mit XXXX überschriebene Feld die Sequenznummer der später folgenden empfangenen Response enthält (YYYY ist die von XXXX abhängige CRC).

Zur besseren Lesbarkeit sind teilweise Leerzeichen zur Trennung bekannter Nachrichtenfelder eingefügt.


Öffnen der Hardware Verbindung zum Stick

Die Source Software führt die Hardware Konfiguration zweimal durch. Einmal mit einer BaudRate von 119200, anschließend mit einer BaudRate von 115200. Für jede BaudRate werden bestimmte Konfigurationsparameter doppelt gesetzt.

IOCTL_SERIAL_SET_BAUD_RATE     Rate: 119200
IOCTL_SERIAL_SET_LINE_CONTROL  StopBits: 1 Parity: NONE WordLength: 8
IOCTL_SERIAL_SET_CHAR          EOF:1a ERR:0 BRK:0 EVT:1a XON:11 XOFF:13
IOCTL_SERIAL_SET_HANDFLOW      Shake:0 Replace:0 XonLimit:1024 XoffLimit:1024

IOCTL_SERIAL_SET_BAUD_RATE     Rate: 119200
IOCTL_SERIAL_SET_LINE_CONTROL  StopBits: 1 Parity: NONE WordLength: 8
IOCTL_SERIAL_SET_CHAR          EOF:1a ERR:0 BRK:0 EVT:1a XON:11 XOFF:13
IOCTL_SERIAL_SET_HANDFLOW      Shake:0 Replace:0 XonLimit:1024 XoffLimit:1024

IOCTL_SERIAL_SET_TIMEOUTS      RI:-1 RM:-1 RC:-2 WM:0 WC:0
IOCTL_SERIAL_SET_WAIT_MASK     Mask: RXCHAR RXFLAG CTS DSR RLSD BRK ERR RING 
IOCTL_SERIAL_SET_QUEUE_SIZE    InSize: 4096 OutSize: 2048
IOCTL_SERIAL_SET_BAUD_RATE     Rate: 115200
IOCTL_SERIAL_SET_LINE_CONTROL  StopBits: 1 Parity: NONE WordLength: 8
IOCTL_SERIAL_SET_CHAR          EOF:1a ERR:0 BRK:0 EVT:1a XON:11 XOFF:13
IOCTL_SERIAL_SET_HANDFLOW      Shake:0 Replace:0 XonLimit:1024 XoffLimit:1024

IOCTL_SERIAL_SET_BAUD_RATE     Rate: 115200
IOCTL_SERIAL_SET_LINE_CONTROL  StopBits: 1 Parity: NONE WordLength: 8
IOCTL_SERIAL_SET_CHAR          EOF:1a ERR:0 BRK:0 EVT:1a XON:11 XOFF:13
IOCTL_SERIAL_SET_HANDFLOW      Shake:0 Replace:0 XonLimit:1024 XoffLimit:1024

IOCTL_SERIAL_SET_TIMEOUTS      RI:-1 RM:-1 RC:1000 WM:0 WC:0
IOCTL_SERIAL_SET_WAIT_MASK     Mask: RXCHAR RXFLAG CTS DSR RLSD BRK ERR RING 
IOCTL_SERIAL_SET_QUEUE_SIZE    InSize: 4096 OutSize: 2048

(Natürlich darf am Ende das Schließen nicht vergessen werden.)

Stick Initialisierung

Nach dem öffnen der Hardware Verbindung wird diese zunächst mittels des Stick Init Requests (000A) initialisiert.

W .... 000A B43C ..
R .... 0000 00C9 00C1 77BC..
R .... 0011 00C9 000D6F000076C6E7 01 01 E00D6F0000996749 74E0 FF 7E34 ..

Als Antwort enthält die Stick Init Response die MAC-Adresse des verwendeten Plugwise-Sticks, einen boolschen Wert, ob der Stick mit einem Circle+ gepairt ist, die 64-bit Network ID des Plugwise ZigBee Netzwerks sowie eine gekürzte 2-Byte Network ID.

Initiale Konfiguration des Netwerks

Um Plugwise-Geräte nutzen zu können, müssen diese zunächst in das (ZigBee-) Netzwerk integriert werden. Hierfür müssen zunächst Stick und Circle miteinander gepairt werden. Anschließend können weitere Module (Circles/Switches) in das vom Circle+ verwaltete Netzwerk eingebunden werden.

Für das Pairing neuer Module (Circle+, Circle oder Switches) dürfen diese nicht bereits in ein anderes Netzwerk eingebunden sein. Circles welche bereits gepairt sind schalten ihr Relais (hörbar) direkt nach dem sie in eine Steckdose eingesteckt werden, bei einem ungepairten Circle dauert dies etwa 5 Sekunden. Mit folgender Prozedur kann ein Hardware Reset von Circles durchgeführt werden:

  1. den Circle für 2 Sekunden in eine Steckdose stecken
  2. den Circle für 2 Sekunden aus der Steckdose entfernen
  3. den Circle für 2 Sekunden in eine Steckdose stecken
  4. den Circle für 2 Sekunden aus der Steckdose entfernen
  5. den Circle für 8 Sekunden in eine Steckdose stecken
  6. den Circle für 2 Sekunden aus der Steckdose entfernen
  7. wenn der Circle wieder in eine Steckdose gesteckt wird, dauert es etwa 5 Sekunden bis sein Relais schaltet.

Zum Durchführen des Hardware Resets für einen Plugwise Switch muss die linke Schalterblende entfernt werden. Während der ganzen Prozedur ist der (rote) linke obere Softkey gedrückt zu halten. Der Rest der Prozedur wird analog zu den Circles durchgeführt:

  1. den linken unteren Softkey für 2 Sekunden gedrückt halten
  2. 2 Sekunden warten
  3. den linken unteren Softkey für 2 Sekunden gedrückt halten
  4. 2 Sekunden warten
  5. den linken unteren Softkey für 8 Sekunden gedrückt halten
  6. nun sollte die rote LED des Switches für kurze Zeit aufleuchten
Paaren von Stick und Circle+

Durch Senden der folgenden Request-Sequenz wird ein Circle+ mit dem Stick gepairt.

Es wird ein Stick Reset Request (0001) gesendet:

10:45:41 W   ....0001CAAB..
10:45:41 R   ....0000000400C1DDBA...
10:45:43 R   ....000200040FFFFFFFFFFFFFFFFF620D6F0000996749FFFFFFFFFFFFFFFF620D6F000099674996620143CA..
10:45:48 R   ....0003000400CECEED..

Dieser wird mit zwei Responses (0002 und 0003) beantwortet.

Optional kann nun ein Stick Init Request gesendet werden:

10:45:48   W   ....000A B43C..
10:45:48   R   ....0000 0005 00C1 77EB..
10:45:48   R   ....0011 0005 000D6F000076C6E7 01 00 5350..

Diesem ist zu entnehmen, dass der Stick nicht mehr mit einem Circle+ gepairt ist.

Anschließend wird der erste von zwei unterschiedlichen Pair Circle Plus Requests (0004) mit der MAC Adresse des entsprechenden Circle+ (hier 000D6F0000996749) gesendet:

10:45:53   W   ....0004 00 01 0000000000000000 000D6F0000996749 2669..
10:45:53   R   ....0000 0006 00C1 9939..
10:45:53   R   ....0061 FFFD 000D6F000076C6E7 8B3D..
10:45:53   R   ....0005 0006 0001 B3FF..

Dieser wird mit zwei Responses (0061 und 0005) beantwortet, wobei nur die 0005 Response die Sequenznummer aus der Acknowledge Response enthält. Die 0061 Response hat stets die Sequenznummer 0xFFFD.

Nun wird erneut der Stick Reset Request gesendet:

10:46:18   W   ....0001CAAB..
10:46:18   R   ....0000000200C1103F...
10:46:21   R   ....000200020FFFFFFFFFFFFFFFFF5C0D6F0000996749FFFFFFFFFFFFFFFF5C0D6F0000996749165C01BA7C..
10:46:26   R   ....0003000200CE0368..

Sowie der zweite Pair Circle Plus Request (0004). Diesmal mit mit 0x01 nach dem Message Code:

10:46:31   W   ....0004 01 01 0000000000000000 000D6F0000996749 415C..
10:46:31   R   ....0000 0004 00C1 DDBA..
10:46:31   R   ....0061 FFFD 000D6F000076C6E7 8B3D..
10:46:31   R   ....0005 0004 0001 F77C..

Die Response auf den Stick Init Request

10:46:36   W   ....000AB43C..
10:46:36   R   ....0000000500C177EB..
10:46:36   R   ....0011 0005 000D6F000076C6E7 01 01 5C0D6F0000996749 165C FF 2D23..

signalisiert nun (nach der Stick MAC) dass der Stick mit einem Circle+ gepairt ist.

Einbinden anderer Module (Circles/Switches)

Möchte man weitere Module mit dem Circle+ pairen, wird ein Enable Pairing Request (0008) mit dem Parameter 0x01 gesendet:

18:44:58  WRITE  ....0008 01 4068..
18:44:58  READ   ....0000 0171 00C1 8ECD...
18:44:58  READ   ....0000 0171 00D9 000D6F0000996749 37EA..

Die System Response enthält die MAC Adresse des Circle+, das Feld mit dem Inhalt 0x00D9 signalisiert, dass der Circle+ bereit ist mit anderen Modulen gepairt zu werden.

Gibt man in der Plugwise Source Software die MAC Adresse (hier 000D6F0000B81103) eines Moduls ein, welches man mit dem Circle+ pairen will, sendet die Software zyklisch einen Device Info Request (0023). Diese wird zunächst, außer mit der Acknowledge Response, mit dem Out of Bound Broadcast (ohne Header) beantwortet. Kurz darauf folgt eine (negative) Acknowledge Response. Das Feld mit dem Inhalt 0x00E1 signalisiert ein Timeout beim zustellen des Requests.

Zum Einbinden eines neuen Circles in das Netzwerk wird zunächst zyklisch (abwechselnd nach 1 dann 3 Sekunden) ein Device Info Request gesendet, welcher zunächst nur jeweils mit einer Standard Success-Acknowledge und anschließender Timeout-Acknowledge beantwortet wird:

18:43:22  WRITE  ....0023 000D6F0000B81103 5E48..
18:43:22  READ   ....0000 0148 00C1 E851..
18:43:22  READ   # APSRequestNodeInfo: Source MAC: 000D6F000076C6E7# APSRequestNodeInfo: Destination MAC: ..000D6F0000B81103...
18:43:23  READ   ....0000 0148 00E1 42F7..

Irgendwann sendet das einzubindende Modul eine New Device Reponse (0006):

18:44:04  READ  ....0006 0029 000D6F0000B81103 E018..

Durch Senden des Pair Device Requests (0007) wird die die MAC Adresse des einzubindenden Moduls im Circle+ registriert:

18:44:05  WRITE  ....0007 01 000D6F0000B81103 E14D..
18:44:05  READ   ....0000 015F 00C1 7FDF..

Wie beim Pairing von Circle+ zu Stick signalisiert der Empfang einer Pair Accept Response (0061)

18:44:42  READ   ....0061 FFFD 000D6F0000B81103 DFAD..

dass das entsprechende Modul das Pairing akzeptiert hat.

Wurde dieser Vorgang für alle einzubindenden Module durchgeführt und akzeptiert, kann durch Senden des Enable Pairing Requests (0008) mit dem Parameter 0x00 der Pairing Modus des Circle+ deaktiviert werden:

18:45:48  WRITE  ....0008 00 5049..
18:45:48  READ   ....0000 0176 00C1 E919...
18:45:48  READ   ....0000 0176 00DD 000D6F0000996749 B017..

Das Feld mit dem Inhalt 0x00DD signalisiert, dass Pairing deaktiviert wurde.

Erneute Device Info Requests werden nun vom neu eingebundenen Modul beantwortet:

18:45:57  WRITE  ....0023 000D6F0000B81103 5E48..
18:45:57  READ   ....0000 0177 00C1 4348..
18:45:57  READ   # APSRequestNodeInfo: Source MAC: 000D6F000076C6E7# APSRequestNodeInfo: Destination MAC: ..000D6F0000B81103...
18:45:57  READ   ....0024 0177 000D6F0000B81103 00 01 01DC 00044060 01 85 653907014023 4DCCDB7B 02 33A8..
Switch Schalter einem Circle zuweisen

Auch ohne laufende Applikation (bzw. ohne Plugwise Stick) können Schalter eines Plugwise-Switches einem oder mehreren Circles zum Schalten zugeordnet werden. Hierfür wird ein Pair Switch Circle Request (0045) gesendet. Dieser enthält die MAC-Adresse des Circles, die MAC-Adresse des Switches, sowie den Index des Schalters am Switch (0x01 für den linken Schalter bzw. 0x02 für den rechten):

12:00:25   W   ....0045 000D6F0000996749 000D6F0000B851B7 0000000000000000 01 93CB..
12:00:25   R   ....0000 0159 00C1 07A0..
12:00:25   R   ....0000 0159 00ED000D6F0000996749 5D60..
Initialisierung der High-Level Applikation

Eigenschaften eines bereits konfigurierten Netzwerks werden auf Stick und Circle+ gespeichert.

Stick Initialisierung

Nach dem öffnen der Hardware Verbindung sollte diese zunächst mittels des Stick Init Requests (000A) initialisiert werden.

W .... 000A B43C ..
R .... 0000 00C9 00C1 77BC..
R .... 0011 00C9 000D6F000076C6E7 01 01 E00D6F0000996749 74E0 FF 7E34 ..

Als Antwort enthält die Stick Init Response die MAC-Adresse des verwendeten Plugwise-Sticks, einen boolschen Wert, ob der Stick mit einem Circle+ gepairt ist, die 64-bit Network ID des Plugwise ZigBee Netzwerks sowie eine gekürzte 2-Byte Network ID.

MAC Adresse des Circle+

Der Circle+ bildet den ZigBee-Coordinator des Netzwerks. Seine MAC-Adresse kann vom Stick über den Enable Pairing Requests (0008) angefordert werden. Da man (meist) kein Pairing neuer Module aktivieren will, wird als Parameter 0x00 mitgesendet:

18:45:48  WRITE  ....0008 00 5049..
18:45:48  READ   ....0000 0176 00C1 E919...
18:45:48  READ   ....0000 0176 00DD 000D6F0000996749 B017..

Der folgenden System Response ist die MAC-Adresse des Circle+ (hier 000D6F0000996749) zu entnehmen.

Bekannte Geräte aktualisieren

Ein Array von bis zu 64 im Netzwerk registrierter Geräte wird auf dem Circle+ verwaltet. In einer Schleife können die MAC-Adressen dieser Geräte mittels Senden des Known Devices Request (0018) vom Circle+ angefordert werden. Als Parameter wird der von Request zu Request inkrementierte Index im Intervall 0-63 (0x00-0x3F) mitgesendet.

10:49:06   W   ....0018 000D6F0000996749 00 BD67..
10:49:06   R   ....0000 00D8 00C1 15AC..
10:49:06   R   ....0019 00D8000D6F0000996749 000D6F000076A179 00 EBA7..

10:49:06   W   ....0018 000D6F0000996749 01 AD46..
10:49:06   R   ....0000 00D9 00C1 BFFD..
10:49:06   R   ....0019 00D9000D6F0000996749 FFFFFFFFFFFFFFFF 01 D5A0..

[...]

10:49:11   W   ....0018 000D6F0000996749 3F F665..
10:49:11   R   ....0000 0117 00C1 CEA9..
10:49:11   R   ....0019 0117 000D6F0000996749 FFFFFFFFFFFFFFFF 3F 8004..

Die auf den entsprechenden Request folgende Known Devices Response (0019) enthält nach der MAC-Adresse des Circle+ die MAC Adresse des am entsprechenden Index registrierten Moduls. 0xFFFFFFFFFFFFFFFF signalisiert, dass an diesem Index kein Eintrag vorhanden ist.

Erreichbare Geräte ermittlen

Es ist sinnvoll zyklisch mittels Device Info Requests (0023) die Erreichbarkeit bekannter Geräte zu aktualisieren.

Typ bekannter Geräte ermitteln

Um den im Circle+ registrierten Modulen einen entsprechenden Geräte-Typ (Circle oder Switch) zuzuordnen kann ebenfalls der Device Info Request (0023) verwendet werden. Da Switches nur sporadisch auf ankommende Requests lauschen, kann eine ankommende Switch Pressed Response (0056) verwendet werden um die darin enthaltene MAC Adresse als Geräte vom Typ Switch in der Applikation zu registrieren.

Zeit Synchronisation

Circles zeichnen historische Verbrauchsdaten vergangener Stundenintervalle auf. Damit diese Aufzeichnungen in der Logadresse für die korrekte Stunde landen, sollte zyklisch die Zeit zwischen der Applikation und den Circles synchronisiert werden.

Aktuelle Zeit eines Geräts abfragen

Durch Senden des Get Clock Requests (003E) an die MAC-Adresse des entsprechenden Circles

12:01:24   W   ....003E 000D6F0000996749 345E..
12:01:24   R   ....0000 0209 00C1 9C23..
12:01:25   R   ....003F 0209 000D6F0000996749 0B011902 01457A FA13..

erhält man in der folgenden Get Clock Response die aktuelle Uhrzeit des Circles im pw_clock Format. Hier 0x0B011902, also 0x0B = 12 Stunden, 0x01 = 1 Minute, 0x19 = 25 Sekunden und 0x02 = Dienstag.

Aktuelle Zeit eines Geräts setzen

Durch Senden des Set Clock Requests (0016) an die MAC-Adresse des entsprechenden Circles wird die Zeit des Circles gesetzt. Nach der MAC-Adresse gibt man die gewünschte Zeit im groben pw_timestamp Format (hier 0D01A00F, also 40975 Minuten im ersten Monat des Jahres 2013), gefolgt von der gewünschten Log-Adresse (0xFFFFFFFF ändert nichts), sowie der aktuellen Zeit im (geanueren) pw_clock Format:

11:55:45   W   ....0016 000D6F0000996749 0D01A00F FFFFFFFF 0A372D02 1AAC..
11:55:45   R   ....0000 0004 00C1 DDBA..
11:55:45   R   ....0000 0004 00D7 000D6F0000996749 14D9..

Das erfolgreiche Setzen der Zeit wird durch Empfang einer System Response mit dem Wert 0x00D7 quittiert.

Circle Schalten

Durch Senden vom Power Change Request kann das Ein- bzw. Ausschalten eines über die MAC-Adresse identifizierten Circles angefordert werden. Der Parameter 0x00 fordert Ausschalten, 0x01 Anschalten:

12:02:41   W   ....0017 000D6F0000996749 00 1746..
12:02:41   R   ....0000 0222 00C1 FB9C..
12:02:41   R   ....0000 0222 00DE 000D6F0000996749 A2CA..

12:02:44   W   ....0017 000D6F0000996749 01 0767..
12:02:44   R   ....0000 0227 00C1D8CB..
12:02:44   R   ....0000 0227 00D8 000D6F0000996749 9EFA..

Erfolgreiches Ausschalten wird durch Empfang einer System Response mit dem Wert 0x00DE quittiert, Anschalten mit dem Wert 0x00D8.

Verbrauchswerte von Circles
Kalibrierung

Auf den Circles wird 'verbrauchte' Leistung als Pulse gezählt. Um diesen Wert in Watt (für aktuelle Verbrauchswerte) bzw. kWh (für kummulierte Verbrauchswerte) umrechnen zu können, müssen zunächst die individuellen Kalibrierungsdaten jedes Circles durch Senden des Calibration Requests (0026) ermittelt werden.

18:45:57  WRITE  ....0026 000D6F0000B81103 0D22..
18:45:57  READ   ....0000 0178 00C1 26B1...
18:45:57  READ   ....0027 0178 000D6F0000B81103 3F7F3B90B60FC2A83D49B51400000000 E7A1..
Aktuelle Verbrauchswerte

Aktuelle Verbrauchswerte können durch Senden des Current Power Request (0012) angefordert werden:

11:55:55   W   ....0012 000D6F0000996749 ECB4..
11:55:55   R   ....0000 0027 00C1 B828..
11:55:55   R   ....0013 0027 000D6F0000996749 0000FFFF00000000FFFFFA40000F 35F1..

Die folgende Current Power Response (0013) enthält gezählte Pulse für die letzte Sekunde, für die letzten 8 Sekunden, sowie den Totalverbrauch in Pulsen.

Gespeicherte Verbrauchswerte

Um historische Verbrauchswerte vergangener Stunden für einen Circle anzufordern werden Power History Requests (0048) verwendet. Neben der MAC-Adresse benötigt man die gewünschte Log-Adresse. Zur Berechung gewünschter Log-Adressen werden Referenzwerte aus einer Device Info Response des entsprechenden Circles benötigt. Zunächst wird die Differenz der gewünschten Zeit und der Log-Zeit, im pw_timestamp Format aus der Device Info Response, in Stunden berechnet. Liegt die gewünschte Zeit nach der Referenzzeit, addiert für jede Stunde Differenz den Wert 8 auf die Referenz Log-Adresse aus der Device Info Response. Liegt die gewünschte Zeit vor der Referenzzeit subtrahiert man entsprechend.

11:55:55   W   ....0048 000D6F0000996749 000441E0 8CC3..
11:55:55   R   ....0000 002C 00C1 2CA8..
11:55:55   R   ....0049 002C 000D6F0000996749 0C0C0CE4 00000000 0C0C0D20 00000000 0C0C0D5C 00000000 0C0C0D98 0000045E 000441E0 4558..

Die folgenden Power History Response (0049) enthält für die gewünschte Stunde, sowie die drei folgenden Stunden, Verbrauchswerte in Form gezählter Pulse. Sind für ein Stundenintervall keine Aufzeichnungen vorhanden (z.B. weil es in der Zukunft liegt) erhält man als entsprechende Log-Adresse 0xFFFFFFFF.

Schalterbetätigung am Switch registrieren

Wird ein Schalter eines registrierten Switches gedrückt, erhält man die (unaufgeforderte) Switch Pressed Response:

12:02:38   R   ....0056 FFFF 000D6F0000B851B7 01 00 B14F..

Diese enthält die MAC-Adresse des entsprechenden Switches, den Index des gedrückten Schalters (0x01=links und 0x02=rechts) sowie die durchgeführte Aktion (0x00=Off gedrückt bzw. 0x01=On gedrückt). Diese Response wird auch empfangen, wenn der Switch keinem Circle zugeordnet ist.

Implementierung (libiPlugwise)

Programmiersprache
Zur vereinfachten Portierung in andere Programmiersprachen wurde C zur Erstellung der Library ausgewählt.
Testapplikation
Zur Nutzung der erstellten Library wurde in C++ eine GUI-Appliktion unter Verwendung der Qt4 Library erstellt.
Plattform
Um eine möglichst platformunabhängige Implementierung zu bieten wurde auf folgenden Systemen getestet:
  • lenovo Thinkpad X220
    • CPU: Intel i5 (little endian)
    • OS: Linux Mint 11 Katya (64bit)
  • Raspberry Pi Model B
    • CPU: ARM 1176JZF-S (big endian)
    • OS: Debian GNU/Linux wheezy/sid (32bit)
Entwicklungsumgebung
Zur Implementierung wurden der GNU C/C++ Compiler, die IDEs eclipse und QtCreator, subversion, Doxygen, sowie die üblichen Linux-tools (make, bash, vi, sed, grep) verwendet.
Dokumentation
Alle erstellten Dateien, Datenstrukturen und Funktionen sind mit Doxygen-Kommentaren kommentiert.

Datenstrukturen

Für bekannte Requests, Responses und darin enthaltene Daten wurden entsprechende structs erstellt. Durch #pragma pack 1 wurde sichergestellt, dass die structfelder direkt aufeinanderfolgend gespeichert werden. Hierdurch konnten die Datenstrukturen direkt per memcpy mit den empfangenen Daten gefüllt werden.

Weiter gibt es eine Map zur Ablage empfangener Responses unter der enthaltenen Sequenznummer. Beim Ablegen einer neuen Response wird geprüft, ob im entsprechenden Feld noch eine Response gespeichert ist. Der entsprechende Speicher wird ggf. freigegeben. Zusätzlich wird beim Ablegen einer neuen Response der Erstellungszeitpunkt mitgespeichert. Mit einem entsprechenden Funktionsaufruf kann der Speicher alter Responses freigegeben werden.

Die Struktur pw_connection wurde zur Kapselung der Verbindungsparameter (z.B. Pfad und Filedescriptor zum Stick) sowie des Protokollzustands und des Zugriffs auf empfangene Responses erstellt.

Intern verwendetes Protokoll

Senden von Requests
  • Zunächst werden die Bytes des entsprechenden structs mittels byte_array_to_c_str() kodiert.
  • Aus den kodierten Nutzdaten wird die CRC berechnet (compute_crc_16()) und kodiert an die Nutzdaten angehangen.
  • Anschließend werden die Nutzdaten von Header und Footer eingerahmt´( add_header_and_footer()).
  • Zuletzt wird die Nachricht auf den Filedescriptor zum Plugwise Stick geschrieben.
Empfangen von Responses

Die Protokollfunktionalität muss fähig sein die, in einem Bytestrom ankommenden, von Header und Footer eingerahmten Responses voneinander zu trennen. Dies geschieht in try_reading_complete_message()

  • Hierfür befindet sich das Protocol zunächst im Zustand want_header.
    • Die Funktion store_till_header_is_found() liest nun einzelne Bytes bis alle Header-Bytes direkt nacheinander gelesen wurden. Eventuel gelesene Out of Bound Bytes werden gezählt und in den übergebenen Buffer geschrieben.
  • Wurde der Header gefunden, wird in den Zustand want_footer übergegangen.
    • Nun wird in store_till_footer_is_found() analog der Footer gesucht und dabei gelesene Nutzdaten-Bytes gezählt und in den übergebenen Buffer geschrieben.

Wurde eine vollständige Response gelesen, wird deren CRC Prüfsumme überprüft und die Nutzdaten anschließend in pw_decode_and_store_payload() weiterverarbeitet.

  • Zunächst werden die Nutzdaten mittels hex_str_to_byte_array() dekodiert.
  • Anschließend werden die (sich in allen Responses an der gleichen Stelle befindliche) Sequenznummer und der Message Code ausgelesen. Da sich die Nachricht noch in network-byte-order befindet, muss dies mittels ntohs() korrigiert werden.
  • Der ausgelesene Message Code wird nun mit allen bekannten Response Message Codes verglichen. Da sich bspw. Acknowledge- und System Response den Message Code teilen, wird hier zusätzlich die Länge der empfangenen Daten zur Unterscheidung verwendet.
  • Nach Allokierung des entsprechenden Response-structs werden die dekodierten Nutzdaten per memcpy() draufkopiert.
  • Da die Grenzen der Response-Felder nun bekannt sind, wird in vom Response-Typ abhängigen Funktionen die Byteorder der enthaltenen Felder korrigiert.
  • Erwartete Responses werden nun mit ihrer Sequenznummer als Schlüssel in einer Map abgelegt. Unangeforderte Responses werden in eine Queue gesteckt. Acknowledge Responses werden separat abgelegt.

Verwendung der Public API

Zur Nutzung der API werden folgende includes benötigt

    • pw_connection.h zum Erstellen und Öffnen der Hardware-Verbindung zum Stick
    • plugwise.h für den Aufruf der Lese-Funktion und zum holen darin empfangener Responses. Sowie zum Senden der unterschiedlichen Requests.
    • pw_responses.h zum Identifizieren des Typs empfangener Responses und zum Auslesen darin enthaltener Felder
    • pw_types.h für den Zugriff auf spezielle in Nachrichten enthaltene Felder
    • pw_circles.h kann optional verwendet werden um Eigenschaften (z.B. Kalibrierungsdaten) von Circles zentral in einer Struktur zu verwalten.

Vor der Verwendung muss die Hardware connection erstellt und geöffnet werden

pw_connection* conn = pw_connection_create("/path/to/stick");
int fd = pw_connection_open(conn);

Zyklisch sollten nun an der Connection ankommende Nachrichten gelesen werden. Entweder in einem separatem Thread in einer Endlosschleife oder Timergesteuert.

pw_read_and_store(conn);

Es bleibt dem Anwender überlassen einen Mechanismus zum Verwalten der Sequenznummern erwarteter Responses zu erstellen. In C kann hierfür die Queue aus pw_queue.h verwendet werden. Prinzipiell reicht hierfür auch eine einfache Liste.

Die Verbindung zum Stick sollte zunächst initialisiert werden. Die Sendefunktionen liefern eine Sequenznummer bzw. einen Fehlercode. In einer Schleife kann man das Senden wiederholen bis man eine gültige Sequenznummer der folgenden Response erhält. Die Sequenznummer sollte im Mechanismus zur Verwaltung der Sequenznummern abgelegt werden (hier register_awaiting()):

int seq_num = -1;
while (seq_num < 0) {
    seq_num = pw_send_stick_init(conn);
    if (seq_num < 0) {
        printf("ERROR: Sending of Request failed with code %i", seq_num);
    } else {
        register_awaiting(seq_num);
    }
}

Mittels folgender Funktion kann man prüfen, ob eine Response für den entsprechenden Request eingetroffen ist

pw_res* pw_get_response_by_seq_num(pw_connection* connection, uint16_t seq_num);

Man erhält einen Pointer zur entsprechenden Response (oder 0). Dieses prüfen für alle erwarteten Sequenznummern kann man z.B. in der gleichen Schleife durchführen wie das Lesen ankommender Nachrichten oder auch Timergesteuert.

Analog wird mittels pw_res* pw_get_unrequested_response(pw_connection* connection); ein Pointer auf eine eventuell empfangene unangeforderte Response geholt.

Der Typ einer empfangenen Response kann durch Vergleichen mit den in pw_responses.h definierten Response Message Codes ermittelt werden.

Über die dem Response-Typ entsprechenden Funktionenen können die darin enthaltenen Informationen abgefragt bzw. verarbeitet werden.

Erstellte Applikationen

Folgende Applikationen nutzen die erstellte Plugwise API:

pair_plus
Pairt einen Circle+ mit dem Plugwise Stick.
Erwartet Pfad zum Stick und MAC-Adresse des Circle+ als Parameter.
pair_modules
Pairt Plugwise Module mit dem Circle+.
Erwartet Pfad zum Stick als Parameter.
Qt GUI
Eine GUI-Applikation.
Kann MAC-Adresse des gepairten Circle+ ermittlen.
Kann MAC-Adresse der mit dem Circle+ gepairten Module ermittlen.
Kann unterschiedliche Requests an bekannte Module senden.

WieDAS Integration

Zur Integration der Plugwise Module in die Wiesbaden-Düsseldorfer Ambient Assisted Living Service Plattform (kurz: WieDAS) werden folgende Funktionalitäten der Plugwise Schnittstelle benötigt:

Circle bzw. Stealth Steckdosen schalten
Für jeden im Plugwise-Netzwerk registrierten Circle bzw. Stealth soll es ein Topic für den von WieDAS angestrebten SOLL-Schaltzustand geben. Der Connector muss sich für entsprechende Änderungen registrieren. Ermittelt der Connector einen aktuellen IST-Schaltzustand ist dieser ein separates Topic für den Circle zu schreiben.
Aktuellen Verbrauch von Circle bzw. Stealth Steckdosen ermitteln
Zyklisch soll der aktuelle Verbrauch jedes Circles angefordert werden. Vom Connector empfangene Werte müssen in entsprechende Topics geschrieben werden.
Wandschalter Betätigung
Wird ein Schalter eines Plugwise-Switches betätigt, muss dies in einem entsprechenden Topic registriert werden.

Komponenten zur Kommunikation mit externen Systemen werden in WieDAS über Konnektoren der zentralen Komponente, dem AAL-Cache, integriert. Im folgenden werden die daraus resultierenden Rahmenbedingungen für die Plugwise-Schnittstelle analysiert.

AAL-Cache

Der AAL-Cache entstand als Abschlussprojekt von Sebastian Flothow und ist prinzipiell unabhängig von der WieDAS Domäne. Der AAL-Cache verwaltet Einträge bestehend aus:

  • Schlüssel (URI)
  • Wert (beliebige Binärdaten)
  • Metadaten

Verbindungen zur Außenwelt werden über Konnektoren realisiert. Konnektoren sind eng an den AAL-Cache gekoppelt, sie werden als shared-objects in Cache Prozess geladen. Als Schnittstelle zwischen Konnektoren und AAL-Cache stehen Funktionen für Schreib- und Lesezugriffe, sowie für Subscriptions zur Verfügung. Registriert ein Konnektor eine Subscription für eine URI im AAL-Cache, ruft der AAL-Cache bei Änderungen des über die URI identifizierten Topics die vom Konnektor übergebene Callback-Funktion auf. Konnektoren können in C, C++ oder Java implementiert werden.

Datenstrukturen

Der AAL-Cache verwaltet beliebige Binärdaten. Datenstrukturen zur Verwendung in den unterschiedlichen Topics des AAL-Cache sind in einer WieDAS-spezifischen IDL definiert. Für den Plugwise-Konnektor werden folgende Datenstrukturen benötigt:

PowerMeter
enthält die aktuelle Leistung in Watt (als unsigned short)
OnOffSwitch
enthält den Status eines Schalters (z.B. zuletzt gedrückter Knopf eines Switches)
OnOffFunctionality
enthält ein Schaltkommando (z.B. angestrebter SOLL-Zustand)
OnOffOutput
enthält einen Relais-Status (z.B. von einer schaltbaren Steckdose)

Jede dieser Datenstrukturen enthält zusätzlich ein Feld für die Device ID (als unsigned short) zur Identifikation des entsprechenden Moduls.

Device IDs

Die 16bit (unsigned short) zur Identifikation einzelner Module setzen sich zusammen aus einem Prefix für die entsprechende Technologie (z.B. die 7 für Plugwise Module) die niederwertigeren bits sind innerhalb der Technologie frei wählbar. Für Plugwise Module werden die letzten drei ASCII-Zeichen der hexadezimal kodierten MAC-Adresse des entsprechenden Moduls verwendet. Da für die zwei Schalter der Plugwise-Switches unterschiedliche Device-IDs benötigt werden, wird zur Identifikation des rechten Schalters die entsprechende Device-ID um eins inkrementiert.

URIs

Die unterschiedlichen Funktionalitäten werden über URIs adressiert. Die URI setzt sich zusammen aus dem entsprechenden Topic aus der IDL sowie der Device ID in Hexadezimaldarstellung. Bspw.

/OnOffFunctionality/7C1E
von WieDAS geforderter SOLL-Schaltzustand Plugwise-Circles mit der in C1E endenden MAC-Adresse
/OnOffOutput/7C1E
letzter durch den Connector ermittelter IST-Schaltzustand des Plugwise-Circles mit der in C1E endenden MAC-Adresse
/PowerMeter/7C1E
letzter durch den Connector ermittelter Momentanverbrauch des Plugwise-Circles mit der in C1E endenden MAC-Adresse
/OnOffSwitch/7A12
Schaltkommando des linken Knopfes des Plugwise-Switches mit der in A12 endenden MAC-Adresse (oder Schaltkommando des rechten Knopfes des Plugwise-Switches mit der in A11 endenden MAC-Adresse)

Jeder URI wird im AAL-Cache ein eindeutiges Tag zugeordnet. Dieses wird Schreib- und Lesezugriffen zur Adressierung übergeben.

Plugwise-Konnektor

Der AAL-Cache bekommt über eine Konfigurationsdatei (connectors.conf) eine Liste zu ladender Konnektoren. Ein Eintrag für einen in den Prozess des AAL-Cache zu ladenden Konnektor enthält den Pfad zum entsprechnden shared-object, den Namen des exportierten Konnektor-Symbols (worüber die entsprechende Start-Funktion des Konnektors ermittelt wird), sowie einen Konfigurationsstring der dem Konnektor zum Start übergeben wird.

Initialisierungsparameter des Plugwise-Konnektors

Zum erfolgreichen Start des Plugwise-Konnektors wird vorausgesetzt, dass der Plugwise-Stick bereits mit einem Plugwise-Circle+ gepairt ist. Ferner müssen alle anderen zu verwendenden Plugwise-Module (Circles und Switches) im Circle+ registriert sein.

Prinzipiell wäre es über die verwendete Library zur Kommunikation mit den Plugwise Modulen möglich über entsprechende Requests die MAC-Adressen und Typen der am Circle+ registrierten Module anzufordern. Der AAL-Cache führt die Start-Funktionen der zu ladenden Konnektoren jedoch sequentiell aus, weshalb die Start-Funktionen schnell zurückkehren sollten. Auch wenn dem Plugwise-Konnektor also eigentlich der Pfad zum Plugwise-Stick als Konfiguration ausreichen würde, erhält er anstelle dessen den Pfad zu einer Konfigurationsdatei welche den Pfad zum Stick sowie die MAC-Adressen und Typen der zu verwendenden, am Circle+ registrierten, Module enthält.

config_creator

Die CLI-Applikation config_creator dient der Erstellung der Konfigurationsdatei für den Plugwise-Konnektor. Er erwartet als Parameter den Pfad zum Plugwise-Stick.

Nach dem Start ermittelt die Applikation die MAC-Adresse des mit dem Stick gepairten Circle+. Anschließend fragt die Applikation in einer Schleife die MAC-Adressen aller am Circle+ registrierten Module ab.

Um den entsprechenden Gerätetyp (Circle oder Switch) ermittelter MAC-Adressen zu bestimmen werden Device Info Requests versendet. Da Switches nur sporadisch auf Requests lauschen, sollte ein Knopf auf jedem Switch gedrückt werden. Die daraufhin empfangene Switch Pressed Response wird der entsprechenden MAC-Adresse zugeordnet und das Modul als Switch identifiziert.

Funktionalitäten des Plugwise-Konnektors

Subscriptions für vom AAL-Cache geforderte SOLL-Schaltzustände der Circles
Beim Aufruf der entsprechenden Callback-Funktion des Plugwise-Konnektors kann dieser über das übergebene Tag aus dem Topic den geforderten Schaltzustand sowie die entsprechende Device ID auslesen. Über die im Konnektor gespeicherte, zur entsprechenden Device ID gehörigen, MAC-Adresse kann dann ein Schaltbefehl an den Plugwise-Circle gesendet werden. Callbacks werden vom AAL-Cache (möglicherweise zeitgleich) in separaten Threads ausgeführt, Funktionalitäten der Plugwise-Library müssen also entsprechend gesichert sein. Wurde der Schaltbefehl erfolgreich gesendet, muss der Plugwise-Konnektor die Sequenznummer der folgenden Response registrieren.
Zyklisches Prüfen der IST-Zustände der Plugwise-Circles
Für andere, an den Zuständen der Plugwise-Module interessierte, Konnektoren muss der Plugwise-Konnektor zyklisch in einem definierbaren Intervall, den aktuellen Schaltzustand sowie den Momentanverbrauch aller Plugwise-Circles anfordern. Durch iterieren über die MAC-Adressen der Circles können entsprechende CurrentPowerRequests sowie DeviceInfoRequests erstellt und gesendet werden. Die Sequenznummern der folgenden Responses müssen registriert werden. Da die Plugwise-Funktionalitäten sowieso Thread-sicher implementiert sein müssen, wird hierfür ein separater Thread in der Start-Funktion des Plugwise-Konnektors erstellt.
Holen empfangener Plugwise-Reponses
Ein weiterer, in der Start-Funktion des Plugwise-Konnektors erstellter, Thread prüft in einem definierbaren Intervall ob Responses erwarteter Sequenznummern empfangen und in der entsprechenden Map der Plugwise-Connection gespeichert wurden. Konnte eine erwartet Response nach einer definierbaren Zeitspanne nicht abgeholt werden, ist diese als verloren zu registrieren und aus der Menge der erwarteten Sequenznummern zu entfernen. Zyklisch muss in diesem Thread ebenfalls die Garbage-Collection der Response-Map der Plugwise-Connection aufgerufen werden um den Speicher für veraltete Responses freizugeben.

Zusätzlich werden in diesem Thread unangeforderte Nachrichten (z.B. wenn ein Knopf eines Plugwise-Circles betätigt wurde) aus der entsprechenden Queue der Plugwise-Connection geholt.

Verarbeiten empfangener Plugwise-Reponses
Wurde eine (erwartete oder unangeforderte) Nachricht geholt, wird im gleichen Thread auf diese reagiert. Die zu verarbeitenden DeviceInfoResponses, CurrentPowerResponses, SchaltAcknowledges sowie SwitchPressedResponses enthalten die MAC-Adresse des entsprechenden Moduls (sowie ggf. die Nummer des gedrückten Knopfes). Nach ermitteln der entsprechenden gespeicherten Device ID sowie des Tags für das entsprechende Topic, wird über einen Schreibzugriff der entsprechende Eintrag im AAL-Cache aktualisiert.

Test-Konnektoren

Um die korrekte Umsetzung aller Funktionalitäten des Plugwise-Konnektors zu überprüfen wurden folgende Test-Konnektoren implementiert:

linear_on_off_functionality_conn
erwartet durch ':' getrennte Device IDs con Plugwise Circles als Konfigurationsparameter
schreibt zyklisch Befehle zum Ein- bzw. Ausschalten der Circles in die entsprechenden AAL-Cache /OnOffFunctionality/ Topics
subscr_circle_state_conn
erwartet durch ':' getrennte /OnOffOutput/ URIs mit entsprechenden Device IDs con Plugwise Circles als Konfigurationsparameter
subscribed die entsprecheden Topics und gibt Änderungen auf der Konsole aus
subscr_circle_power_conn
erwartet durch ':' getrennte /PowerMeter/ URIs mit entsprechenden Device IDs con Plugwise Circles als Konfigurationsparameter
subscribed die Topics und gibt Änderungen auf der Konsole aus
subscr_switch_action_conn
erwartet durch ':' getrennte /OnOffSwitch/ URIs mit entsprechenden Device IDs con Plugwise Circles als Konfigurationsparameter
subscribed die Topics und gibt Änderungen auf der Konsole aus

Fazit

Das Reengineering der Plugwise-Kommunikation zur Integration der Module in das WieDAS-Projekt konnte mit einem Aufwand von knapp über 450 Stunden erfolgreich realisiert werden, der Großteil der Zeit wurde hierbei für Analyse und Implementierung der C API verwendet.

Neuland war besonders das Reengineering aus mitgeschnittenen Logdaten. Für viele Funktionalitäten war allein das bekommen der Mitschnitte sehr zeitaufwendig, speziell bei den Dialogen zur Initialen Konfiguration des Netzwerks. Hierfür musste bei den entsprechenden Modulen zunächst ein Hardware-Reset durchgeführt werden. Anschließend mussten unter Windows portmon und die Plugwise-Source Software (in der richtigen Reihenfolge) gestartet und der Pair-Vorgang durchgeführt werden. Die gesammelten Logs mussten zum Filtern nach Linux kopiert werden, wo diese dann nach relevanten Nachrichten durchsucht wurden. Diese Vorgänge mussten zwecks Vergleichbarkeit mehrfach durchgeführt werden. Das ständige Lesen von Daten in Hexadezimal-Darstellung macht das, aus Anekdoten gehörte, Sehen von Programmfehlern auf Lochkarten nachvollziehbar. Auch das, auf dem Papier vernünftig aussehende, verwendete Übertragungsprotokoll bot unerwartete Überraschungen. Gerade die nichteindeutig von Nachrichtenlänge je Message-Code, das Empfangen von Nachrichten ohne Header oder die Fragmentierung gelesener Daten bedurften einiger Korrekturen der implementierten Algorithmen. Glücklicherweise konnte bei auftretenden Problemen stehts mit hilfreichen Hinweisen der direkten Projektpartner Kai Beckman und Marcus Thoss gerechnet werden.

Einfacher, und speziell mit weniger Überraschungen, konnte die Integration in WieDAS durchgeführt werden. Der AAL-Cache funktionierte einfach und die angebotenen Schnittstellen boten klare Funktionalitäten. Die Multithreading Umgebung erforderte zwar einige Absicherungen innerhalb der eigentlich fertigen Plugwise API, ermöglichte sonst aber eine schöne Trennung der implementierten Funktionalitäten.

Ich warte gespannt auf das Ergebnis der Evaluierung in der Demonstrator-Wohnung für das WieDAS-Projekt und hoffe das die implementierte API auch weiter bspw. in Projekten des Labors für verteilte Systeme oder der Veranstaltung Industrial and Home Automation genutzt wird.

Anhang: Unbekannte Dialoge

Folgenden aufgezeichneten Dialogen konnte noch keine Funktionalität zugeordnet werden:

0028 / 0000 (00DF)

WRITE ....0028 000D6F0000996749 33251604170113 FCE8..
READ  ....0000 00CE 00C1 E111...
READ  ....0000 00CE 00DF 000D6F0000996749 A713..

0029 / 003A

W   ....0029 000D6F0000996749 5AF0..
R   ....0000 0006 00C1 9939..
R   ....003A 0006 000D6F0000996749 05292203300113 FBD6..

004A / 0000 (00F1)

WRITE ....004A 000D6F0000996749 3C01 056A..
READ  ....0000 00CF 00C1 0FC3...
READ  ....0000 00CF 00F1 000D6F0000996749 11C2..

0040 / 0000 (00E5)

W   ....0040 000D6F000099674900015218..
R   ....0000 000D 00C1 C03C..
W   ....0040 000D6F000076A1790001EB69..
R   ....0000 0012 00C1 559F..
R   ....0000 0012 00E5 000D6F000076A179 6573..

000D

W   ....000D 000D6F0000B85195 960D..
R   # SENDING PING UNICAST: Macid: FA02C23760007A6E..# HANDLE: 0x60..
R   ....0000 0060 00C1 D95D..

005F / 0060

W   ....005F 000D6F0000B1B975 86D5..
R   ....0000 0016 00C1 DC99..
R   ....0060 0016 000D6F0000B1B975 FFFFFFFFFFFFFFFE CEA1..
W   ....005F 000D6F00007696A6 055B..
R   ....0000 014E 00C1 D4AD..
R   ....0060 014E 000D6F00007696A6 FFFFFFFFFFFFFFFE 207B..

0057 / 0000 (00F8)

W   ....0057 000D6F00023A5BC0 003C 0000 5730..
R   ....0000 0154 00C1 26DA..
R   ....0000 0154 00F8 000D6F00023A5BC0 EF3F..
W   ....0057 000D6F00007696A6 003C 0000 34E3..
R   ....0000 01FD 00C1 B020..
R   ....0000 01FD 00F8 000D6F00007696A6 92A8..

0058 / 0000 (00F9)

W   ....0058 000D6F0000996749 01 7B8A..
R   ....0000 0157 00C1 C808..
R   ....0000 0157 00F9 000D6F0000996749 C06F..
W   ....0058 000D6F000076A179 01 B4F6..
R   ....0000 0212 00C1 357C..
R   ....0000 0212 00F9 000D6F000076A179 6B8F..

0050 / 0000 (00F6)

W   ....0050 000D6F0000B851B7 14000500F0000000 CD99..
R   APSSetSleepBehaviour()..
R   ....0000 0224 00C1 3619..
R   ....0000 0224 00F6 000D6F0000B851B7 A3FC..