Graph-IT

DoorPi-Tutorial

Ziel des Tutorials

Ein RapsberryPi (DoorPi) soll über einen NFC-Reader RFID-Tags auslesen. Ist die Tag-ID in der Liste der zugelassenen Tags, wird über ein Relais der Türöffner betätigt.

Die entsprechenden Daten über die Personen, die Zugriff auf die Türen bekommen sollen, werden im Graphen verwaltet. Werden die Daten dort geändert, werden diese Informationen automatisch an den DoorPi übertragen. Jeder Person können beliebig viele Tags und beliebig viele Türen zugeordnet werden.

Wird ein Tag an einen NFC-Reader gehalten, so wird ein Log-Eintrag im Graphen erzeugt, welcher die Information über den Zeitpunkt, die Tag-ID (und damit über die Person, wenn das Tag bekannt ist) und die Gewährung oder Verweigerung des Zugangs speichert.

Für die Umsetzung wird ein neues, lokales Graphmodul angelegt, welches über eine ControlPi-Instanz mit dem DoorPi in beide Richtungen kommuniziert.

Einleitung

Graphmodul und ControlPi-Instanz einrichten

Das singuläre Graphmodul doorpi mit dem Kürzel d1 wird mit Hilfe des Tasks "Graphmodul anlegen" erzeugt:

Graphmodul anlegen

In diesem Graphmodul werden später alle für die DoorPi-Anwendung spezifischen Graphstrukturen angelegt.

Dann wird eine coRoot-Instanz für dieses Graphmodul mit Hilfe des Tasks "coRoot anlegen" erzeugt:

coRoot anlegen

Die Strukturen, die später angepasst werden müssen, sind vor allem die Aktionfunktion comessage_d1 und die Datenfunktion d1_coconf.

Die Aktionfunktion comessage_d1 verarbeitet Nachrichten, die von der coRoot-Instanz an den Graphen gesendet werden:

Aktionfunktion comessage\_d1

Die Datenfunktion d1_coconf erzeugt die ControlPi-Konfiguration für die coRoot-Instanz:

Datenfunktion d1\_coconf

Diese enthält zunächst nur drei Instanzen der Plugins WSServer, Graph und Periodic. Mit der Instanz des Plugins WSServer werden sich später untergeordnete ControlPi-Instanzen verbinden. Außerdem können ihr mit service('controlpi.send','d1',['key'=>'value']); Nachrichten aus dem Graphen gesendet werden. Die Instanz des Plugins Graph synchronisiert Nachrichten, die dem gegebenen Filter entsprechen, in den Graphen und wird ein Mal pro Sekunde von der Instanz des Plugins Periodic aufgerufen.

Diese Konfiguration wird später durch Strukturen erweitert, die aus den weiteren Graph-Strukturen im Modul doorpi abgeleitet werden.

Im automatisch generierten Tab ControlPi des singulären Knotens des Graphmoduls sind sowohl die Verknüpfung zur coRoot-Instanz als auch die initial gesetzten Attribute zu sehen:

Tab "ControlPi" des Graphmoduls

Die Aktionfunktion copushconf synchronisiert die durch die Datenfunktion d1_coconf generierte Konfiguration auf die coRoot-ControlPi-Instanz selbst. Diese wird hierdurch mit dieser geänderten Konfiguration neu gestartet.

Das WSServer-Plugin stellt außerdem eine Debug-Oberfläche zur Verfügung:

Debug-Oberfläche der
coRoot-Instanz

Datenmodell erstellen

Eine Übersicht über das Datenmodell ist im folgenden Diagramm dargestellt:

Datenmodell

Am singulären Knoten d1 ist nur das Attribut d1doorpicoconf hinzugekommen. Es enthält die Vorlage für die Konfiguration einer DoorPi-Instanz, die im folgenden Abschnitt genauer angesehen wird.

Mit der Instanz des singulären Knotens können beliebig viele d1DoorPi-Instanzen verknüpft sein. Um der Root-Instanz gegenüber identifizierbar zu sein, wird für jede d1DoorPi-Instanz die MAC-Adresse im Attribut macadresse hinterlegt. Diese kontrollieren jeweils das Öffnen einer Tür.

Die Personen, die diese Tür öffnen dürfen sind durch mit den d1DoorPi-Instanzen verknüpfte d1Person-Instanzen repräsentiert, die wiederum mehrere durch d1NFCTag-Instanzen repräsentierte Tags besitzen können, mit denen sie die Türen öffnen können.

Hierzu haben d1NFCTag-Instanzen ein Attribut uid, das in den Attributknoten d1person_uids und d1doorpi_uids aggregiert wird.

Alle Versuche, sich an einem d1DoorPi zu identifizieren, sollen in d1Log-Instanzen protokolliert werden. Wenn das dabei verwendete NFC-Tag dem System bekannt sind, werden die zugehörigen d1NFCTag- und d1Person-Instanzen verknüpft. Außerdem wird festgehalten, ob die Tür geöffnet wurde.

DoorPi einbinden

Die Vorlage für die Konfiguration der einzelnen DoorPis ist an der Instanz des singulären Knotens d1Parameter im Attribut d1doorpicoconf hinterlegt:

{
  "Kartenleser": {
    "plugin": "NFCReader"
  },
  "Türöffner": {
    "plugin": "HackPin",
    "pin": 2
  },

Für den Kartenleser wird das Plugin NFCReader aus dem Controlpi-Paket controlpi-nfc verwendet, zur Steuerung der Tür ein HackPin-Plugin aus dem Paket controlpi-pinio.

  "Tür": {
    "plugin": "StateMachine",
    "init": "zu",
    "states": {
      "zu": {
        "commands": [
          {
            "target": "Türöffner",
            "command": "set state",
            "new state": false
          }
        ],
        "transitions": [
          {
            "trigger": {
              "sender": {
                "const": "Kartenleser"
              },
              "event": {
                "const": "changed"
              },
              "state": {
                "const": true
              },
              "card": {"enum": []}
            },
            "to": "offen"
          },
          {
            "trigger": {
              "target": {
                "const": "Tür"
              },
              "command": {
                "const": "auf"
              }
            },
            "to": "offen"
          }
        ]
      },
      "offen": {
        "commands": [
          {
            "target": "Türöffner",
            "command": "set state",
            "new state": true
          },
          {
            "target": "Offenhalten",
            "command": "wait"
          }
        ],
        "transitions": [
          {
            "trigger": {
              "sender": {
                "const": "Offenhalten"
              },
              "event": {
                "const": "finished"
              }
            },
            "to": "zu"
          }
        ]
      }
    }
  },
  "Offenhalten": {
    "plugin": "Wait",
    "seconds": 3
  },

Das Zusammenspiel von Kartenleser und Türöffner wird durch ein StateMachine-Plugin aus dem Paket controlpi-statemachine definiert.

  "DoorPi-Master": {
    "plugin": "WSClient",
    "url": "",
    "client": "",
    "up filter": [
      {
        "sender": {
          "const": "Kartenleser"
        },
        "event": {
          "const": "changed"
        },
        "state": {
          "const": true
        }
      },
      {
        "sender": {
          "const": "Tür"
        },
        "event": {
          "const": "changed"
        },
        "state": {
          "const": "offen"
        }
      }
    ],
    "down filter": [
      {
        "target": {
          "const": "Tür"
        },
        "command": {
          "const": "auf"
        }
      }
    ]
  },

Die Verbindung zur Root-Instanz wird über ein WSClient-Plugin aus dem Paket controlpi-wsclient hergestellt. Hierbei werden das Auflegen eines NFC-Tags und das Öffnen der Tür durch die Statemachine als Nachrichten an die Root-Instanz weitergegeben und der Befehl zum Öffnen der Tür von der Root-Instanz entgegen genommen.

  "Debug": {
    "plugin": "WSServer",
    "web": {
      "/": {
        "module": "controlpi_plugins.wsserver",
        "location": "Debug"
      }
    }
  }
}

Schließlich wird durch ein WSServer-Plugin aus dem Paket controlpi-wsserver eine Debug-Oberfläche zur Verfügung gestellt.

Auf einem DoorPi müssen also alle diese Pakete und ihre Abhängigkeiten installiert sein. Hierfür bietet sich das generiche ControlPi-Image an.

In der Datenfunktion d1doorpi_coconf müssen dann in dieser Vorlage nur noch die URL der Root-Instanz, der Name des DoorPi bzw. der Tür und die erlaubten NFC-Tags gesetzt werden:

Datenfunktion d1doorpi\_coconf

Die Konfiguration der Root-Instanz in der Datenfunktion d1_coconf wird so angepasst, dass sie die Konfigurationen der einzelnen DoorPis aufsammelt und jeweils, wenn diese eine Verbindung aufbauen auf diese überträgt:

Datenfunktion d1\_coconf

Kommunikation Graph<->DoorPi einrichten

Vom Graphen zu den DoorPis findet (neben dem Pushen der Konfigurationen) nur eine Kommunikation durch die sehr einfache Aktionfunktion d1doorpi_oeffnen statt, die es ermöglicht, eine Tür manuell aus dem Graphen zu öffnen:

Aktionfunktion d1doorpi\_oeffnen

In die andere Richtung wurde in den Konfigurationen der einzelnen DoorPi-Instanzen und der Root-Instanz bereits festgelegt, dass die Ereignisse beim Auflegen eines NFC-Tags auf die Kartenleser und beim Öffnen der Tür durch die Statemachine nach oben bis zum Graphen weitergegeben werden.

Diese werden jetzt durch eine Überarbeitung der Aktionfunktion comessage_d1 (die alle Nachrichten der Root-Instanz zum Graphmodul d1 erhält) verarbeitet:

Aktionfunktion comessage\_d1

Beim Auflegen einer Karte wird eine d1Log-Instanz angelegt, mit dem meldenden d1DoorPi verknüpft und die Zeit und die Tag-ID gesetzt. Wenn aufgrund eines solchen Ereignisses eine Tür geöffnet wird, wird der entsprechende Log-Eintrag gesucht und das Attribut geoeffnet entsprechend gesetzt.