iBeacons konfigurieren

iBeacons sind eine spannende Technology um die Position von Menschen oder Objekten in Innenräumen festzustellen. Im Prinzip handelt es sich im Bluetooth-Low-Energy Geräte, die in periodischen Intervallen eine eindeutige Identifikation versenden. Auf Basis der empfangenen Daten kann der Empfänger sogar die Entfernung zum iBeacon errechnen.

Für die Berechnung der Position in einer Wohnung sind selbst die günstigsten iBeacons perfekt geeignet. Die kurze Reichweite kommt dem sogar entgegen, weil bei mehreren iBeacons, die in der Wohnung verteilt werden nicht immer alle in Reichweite alle iBeacons sind und damit eine grobe Positionsbestimmung selbst ohne Triangulation möglich ist.

Da die meisten iBeacons auf einem Texas-Instruments Chip basieren, sind sie selbst als Direktimport aus China nicht extrem günstig. Unter 10€ sind iBeacons kaum zu bekommen. Allerdings benötigt man selbst für grosse Wohnungen kaum mehr als 5-6 Stück.

Ein beliebter iBeacon ist der Ghostyu. Er besteht aus einer kleinen Leiterplatte mit einer grossen Battery auf der Rückseite.

ghostyu

Wenn man nun nur einen iBeacon nutzt, muss man eigentlich nichts weiter tun. Allerdings wird man irgendwann feststellen, dass das Smartphone der Meinung ist, man wäre zu Hause, obwohl man unterwegs ist. Warum? Alle diese Beacons kommen mit der gleichen ID. Diese sieht wie folgt aus:

UUID: E2C56DB5-DFFB-48D2-B060-D0F5A71096E0
Major: 0
Minor: 0

iBeacons benutzen eine 3-teilige ID. Je nach Applikation können Major und Minor ID ignoriert werden, aber die UUID wird immer genutzt.

Daher empfehle ich generell, UUID. Major und Minor anzupassen. Die UUID ist eine 128-bit ID. Man kann einfach zufällig einen 128-bit Wert generieren und ist praktisch sicher, dass niemand sonst diesen Wert nutzt (solange er wirklich zufällig generiert wurde). Die einfachste Variant um eine zufällige UUID zu erzeugen ist ein online UUID Generator.

Aber wie kann man die UUID ändern? Für den Ghostyu gibt es eine iOS-App (andere iBeacons bringen nur Android-Apps mit, das kann u.U. problematisch sein, wenn man kein Android-Smartphone besitzt). Leider gibt es die App LightBeacon nur in Chinesisch. Mit etwas Herumklicken sollte sich der Konfigurationsdialog aber doch recht einfach finden lassen. Dieser sieht wie folgt aus:

lightbeacon

Hier kann man jetzt nicht nur UUID, major und minor ID ändern, sondern auch das Sendeintervall. Für die meisten Anwendungsfälle reicht es durchaus aus, wenn der Beacon alle 4 Sekunden sendet. Das verlängert die Batterielebensdauer deutlich. Jetzt noch speichern und der iBeacon startet neu und meldet sich mit den neu konfigurierten IDs.

Stromversorgungen für LED-Installationen

Im Internet findet man viele spannende Selbstbaulösungen mit LEDs. Die beiden häufigsten Anwendungen sind LED-Streifen für Beleuchtungszwecke und Ambilight-Nachbauten. In der letzten Woche fand ich auf einer Selbstbauseite eine sehr gute Beschreibung zum einem Ambilight-Eigenbau. Ich werde diese hier aber nicht verlinken, denn meiner Meinung nach ist dieser Aufbau nicht sicher.

Das entsprechende Projekt und viele andere Projekte nutzen Spannungsversorgung, die ähnlich aussehen, wie diese hier:

pl8886134-short_circuit_protection_standard_led_display_power_supply_100w_5v_20a_ip20_60hz_en1122

Warum? Dieser Typ ist auf Chinesischen Webseiten recht günstig zu erhalten. Dieser Netzteiltyp ist nicht grundsätzlich unsicher. Die Bauqualität ist in der Regel sogar recht hoch, da man die Bauteile von aussen sehen kann und die Hersteller sich daher Mühe geben, dass alles gute und gerade verlötet ist. Das sagt zwar nicht generell etwas über die Qualität aus, aber es kann ein erster Hinweis sein. Warum sollte man diesen Netzteiltyp dennoch nicht nutzen? Was ist das Problem?

Das Problem fängt an, wenn man ein derartiges Netzteil an einem Platz installiert, den man mit den Fingern erreichen kann. Ein Beispiel sieht man z.B. hier:

powersupply-unsafe

Auch wenn dieses Netzteil auf der Rückseite des TVs installiert ist, besteht dennoch die Möglichkeit, dass man z.B. beim Putzen mit Netzspannung in Kontakt kommt. Und das kann tödlich enden!

Es gibt eine ganz einfache Möglichkeit, solche Probleme zu vermeiden. Man muss nur ein Netzteil nutzen, wie man es z.B. von Laptops kennt:

laptop-adapter-ac-adapter

Solche Netzteile sind in allen gängigen Spannungen erhältlich und können je nach Typ bis zu 100W Leistung bereitstellen – mehr als genug für übliche LED-Installationen.

Bluetooth-Probleme mit dem Raspberry Pi 3

Der “Bluetooth tracker” in Home Assistant ist eine spannende Funktion. Sie erlaubt es, festzustellen, ob Personen an einem bestimmten Ort sind (z.B. zu Hause). Dafür kann z.B. das Mobiltelefon genutzt werden.  Der Raspberry Pi 3 kommt mit einem integrierten Bluetooth chip. Das heisst, um die Tracking-Funktion auf Bluetooth-Basis zu nutzen, ist keine zusätzliche Hardware erforderlich. Ziemlich cool! Allerdings hatte ich ziemlich grosse Problem, diese Funktion zum Laufen zu bringen.Bluetooth war auf dem Raspberry Pi  aktiviert, dennoch hat Home Assistant keine Bluetooth-Geräte gefunden. Wo liegt das Problem?

Fangen wir mal an, auf der Kommandozeile nach Bluetooth-Geräten zu suchen:

[email protected]:~# hcitool scan
Scanning ...

Nichts! Dabei sind diverse Bluetooth-Geräte aktiv. Versuchen wir es als nächstes mit “blutoothctl”:

[email protected]:~# sudo bluetoothctl
[NEW] Controller B8:27:EB:76:70:7C raspberrypi [default]
[bluetooth]# devices
[bluetooth]# scan on
Discovery started
[CHG] Controller B8:27:EB:76:70:7C Discovering: yes
[NEW] Device 04:69:F8:xx:xx:xx 04-69-F8-xx-xx-xx
[NEW] Device 88:C6:26:xx:xx:xx 88-C6-26-xx-xx-xx
[bluetooth]# quit
[DEL] Controller B8:27:EB:76:70:7C raspberrypi [default]

Da sind die ganzen Geräte. Wieso findet hcitool die nicht? Gibt es evtl. Probleme mit einem Serverprozess?

[email protected]:~# systemctl status bluetooth
● bluetooth.service - Bluetooth service
   Loaded: loaded (/lib/systemd/system/bluetooth.service; enabled)
   Active: active (running) since Mon 2016-06-13 15:53:36 UTC; 1h 54min ago
     Docs: man:bluetoothd(8)
 Main PID: 729 (bluetoothd)
   Status: "Running"
   CGroup: /system.slice/bluetooth.service
           └─729 /usr/lib/bluetooth/bluetoothd

Jun 13 15:53:36 raspberrypi systemd[1]: Starting Bluetooth service...
Jun 13 15:53:36 raspberrypi bluetoothd[729]: Bluetooth daemon 5.23
Jun 13 15:53:36 raspberrypi systemd[1]: Started Bluetooth service.
Jun 13 15:53:36 raspberrypi bluetoothd[729]: Starting SDP server
Jun 13 15:53:36 raspberrypi bluetoothd[729]: Bluetooth management interface 1.10 initialized
Jun 13 15:53:36 raspberrypi bluetoothd[729]: Sap driver initialization failed.
Jun 13 15:53:36 raspberrypi bluetoothd[729]: sap-server: Operation not permitted (1)

Das sieht etwas seltsam aus. Der Serverprozess läuft zwar, aber es gibt dort eine seltsame Fehlermeldung. Wenn man nun nach dieser sucht, findet man sehr viel Text dazu auf  raspberypi.org. Um das in den Griff zu bekommen, muss man wohl das SAP-Plugin abschalten.

Dazu bearbeitet man die Datei /etc/systemd/system/bluetooth.target.wants/bluetooth.service und fügt die Option “–noplugin=sap” an der “ExecStart”-Zeile an:

[Unit]
Description=Bluetooth service
Documentation=man:bluetoothd(8)

[Service]
Type=dbus
BusName=org.bluez
ExecStart=/usr/lib/bluetooth/bluetoothd --noplugin=sap
NotifyAccess=main
#WatchdogSec=10
#Restart=on-failure
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
LimitNPROC=1

[Install]
WantedBy=bluetooth.target
Alias=dbus-org.bluez.service

Wie sieht es jetzt aus?

[email protected]:~# systemctl status bluetooth
● bluetooth.service - Bluetooth service
   Loaded: loaded (/lib/systemd/system/bluetooth.service; enabled)
   Active: active (running) since Mon 2016-06-13 17:56:35 UTC; 9s ago
     Docs: man:bluetoothd(8)
 Main PID: 19106 (bluetoothd)
   Status: "Running"
   CGroup: /system.slice/bluetooth.service
           └─19106 /usr/lib/bluetooth/bluetoothd --noplugin=sap

Jun 13 17:56:35 raspberrypi bluetoothd[19106]: Bluetooth daemon 5.23
Jun 13 17:56:35 raspberrypi bluetoothd[19106]: Starting SDP server
Jun 13 17:56:35 raspberrypi bluetoothd[19106]: Excluding (cli) sap
Jun 13 17:56:35 raspberrypi bluetoothd[19106]: Bluetooth management interface 1.10 initialized
Jun 13 17:56:35 raspberrypi systemd[1]: Started Bluetooth service.

Die Fehlermeldung ist weg. Allerdings zeigt

hcitool scan

weiterhin keine Bluetooth-Gerät an.

Wird fortgesetzt…

Batteriebetriebener Sensor auf ESP8266-Basis

Der ESP8266 ist ein leistungsfähiger und günstiger Mikrocontroller. Während früher noch oft proprietäre Funkprotokolle wie z.B. nRF24-basierte Chips genutzt wurden, kann man viele heute für viele Anwendungsfälle gleich auf WLAN setzen. Es gibt allerdings ein grosses Problem mit WiFi: der Stromverbrauch.

Wenn der ESP8266 mit einem WiFi-Netzwerk verbunden ist, verbraucht er mindestens 70mA, teilweise sogar deutlich mehr. Wenn man nur ein System mit einem 2400mAh-Akku betreiben will, ist dieser nach spätestens einem Tag leer. Und niemand möchte wohl für Sensoranwendungen eine Autobatterie nutzen.

Glücklicherweise müssen Sensoranwendungen in vielen Fällen nur selten Daten übertragen. Selbst Messungen müssen oftmals nicht ständig erfolgen. Das heisst, die meiste Zeit kann der Chip einfach schlafen. Um dies umzusetzen, geht man wie folgt vor:

  1. Daten sammeln. Das sollte geschehen, bevor das WLAN-Modul aktiviert wird (ausser, die Datenabfrage benötigt nur wenige Millisekunden)
  2. Mit dem WLAN verbinden
  3. Daten senden
  4. In den “Deep sleep”-Modus wechseln. Hierfür nutzt man die ESP.deepSleep() Funktion.

Bei der ESP.deepSleep() Funktion gibt es im übrigen einige Dinge zu beachten:

  1. Damit der Mikrocontroller nach der entsprechenden Zeitspanne wieder aufwacht, mit GPIO16 des ESP8266 mit dem RESET-Pin verbunden sein. Ansonsten schläft der Controller ewig.
  2. Der delay-Parameter ist in Mikrosekunden anzugeben. Wenn sich der ESP8266 also scheinbar nie schlafen legt, könnte es sein, dass man die Zeit versehentlich in Sekunden oder Millisekunden angegeben hat.
  3. Es gibt einen zweiten – optionalen – Parameter, der 4 Werte annehmen kann: WAKE_RF_DEFAULT, WAKE_RFCAL,WAKE_NO_RFCAL, WAKE_RF_DISABLED. Der Wert WAKE_RF_DISABLED sieht auf den ersten Blick vielversprechend aus, denn irgendwie sollte das WiFi-Modul ja abgeschaltet werden. Allerdings bezieht sich dieses Argument auf die Funktion nach dem Aufwachen. Übergibt man hier also WAKE_RF_DISABLED , ist der ESP8266 nach dem Aufwachen nicht mehr in der Lage über WLAN zu kommunizieren.

Hier noch ein paar zusätzliche Tips zum Stromsparen:

  1. LEDs als optische Signalisierung sollten nur sehr kurz eingeschaltet werden. Einige Millisekunden reichen i.d.R. aus, damit der Benutzer das Aufblitzen wahrnimmt.
  2. Müssen die LEDs etwas länger eingeschaltet bleiben, sollten sie gedimmt werden. Mit der analogWrite Funktion kann man das einfach umsetzen.

Hier ist ein einfaches Beispiel, das die Daten vom Analogeingang des Controllers liest und an einen MQTT-Broker übermittelt:

#include         // Generic ESP8266 WiFi routines
#include        // MQTT client
#include           // Local DNS Server used for redirecting all requests to the configuration portal
#include    // Local WebServer used to serve the configuration portal
#include         // WiFi Configuration Magic


const char* mqtt_server = "192.168.1.88";
const char* mqtt_channel_up = "active";
const char* mqtt_channel_data = "sensor/%d/adc";

const int pin_red = 15;
const int pin_green = 12;
const int pin_blue = 13;
const int pin_button = 4;
const int analog_ldr = 0;

const int sleepSeconds = 60 * 15;

WiFiManager wifiManager;
WiFiClient espClient;
PubSubClient client(espClient);


void send_sensor_data(void) {
  Serial.println("Sending sensor data\n");
  int data = analogRead(A0);
  char s_channel[50];
  char s_id[10];
  char s_data[10];
  sprintf(s_channel, mqtt_channel_data, ESP.getChipId());
  sprintf(s_id, "%d", ESP.getChipId());
  sprintf(s_data, "%d", data);

  digitalWrite(pin_blue, HIGH);
  client.connect("ESP8266Client");
  digitalWrite(pin_blue, LOW);
  if (! client.connected()) {
    Serial.println("Could not connect to MQTT broker, doing nothing");
  } else {
    digitalWrite(pin_green, HIGH);
    client.publish(mqtt_channel_up, s_id); // show that this device is up
    client.publish(s_channel, s_data); // send sensor data
    digitalWrite(pin_green, LOW);
  }
}

void setup() {
  delay(500); // This makes it easier to upload new firmware and/or press the "clean" button

  pinMode(pin_red, OUTPUT);
  pinMode(pin_green, OUTPUT);
  pinMode(pin_blue, OUTPUT);

  digitalWrite(pin_red, HIGH);

  // Setup Serial interface for debugging
  Serial.begin(115200);

  //  Bring up WLAN
  WiFiManager wifiManager;

  //sets timeout until configuration portal gets turned off
  //useful to make it all retry or go to sleep
  //in seconds
  wifiManager.setTimeout(60);

  WiFiManagerParameter custom_mqtt_server("server", "mqtt server", mqtt_server, 40);
  wifiManager.addParameter(&custom_mqtt_server);

  if (digitalRead(pin_button) == 0) {
    // reset settings
    wifiManager.resetSettings();
  }

  //fetches ssid and pass and tries to connect
  //if it does not connect it starts an access point with the specified name
  //here  "AutoConnectAP"
  //and goes into a blocking loop awaiting configuration
  if (!wifiManager.autoConnect()) {
    Serial.println("failed to connect and hit timeout");
    delay(100);
    // do nothing: deep sleep, but longer than usual. Something might be wrong and
    // we should save power
    ESP.deepSleep(sleepSeconds * 10 * 1000000, WAKE_RF_DISABLED);
  }

  mqtt_server = custom_mqtt_server.getValue();

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  // Setup MQTT client
  client.setServer(mqtt_server, 1883);

  digitalWrite(pin_red, LOW);
}

void loop(void) {
  send_sensor_data();
  Serial.printf("Sleeping deep for %i seconds...", sleepSeconds);
  ESP.deepSleep(sleepSeconds * 1000000);
  delay(100);
}

Programmieren des ESP8266 unter MacOS

Auf Chinesischen Webseiten und auch auf eBay findet man viele billige Module auf Basis des ESP8266. Sie sind recht leistungsfähig und haben bereits ein WLAN-Interface integriert. Für Schaltungen, die extrem wenig Strom verbrauchen sollen, ist dieser Chip zwar nicht ideal, aber dennoch ist es eine gute und günstige Plattform für Sensorapplikationen und kleine Steuerungen. Was die Module noch attraktiver machen: Sie können direkt unter Arduino programmiert werden. Diese Anleitung zeigt, wie man die Arduino-IDE für diesen Chip unter MacOS einrichtet.

Installation der Arduino Entwicklungsumgebung

Die Arduino IDE kann direkt von der Arduino Webseite heruntergeladen werden.

Anschliessen des ESP8266 modules am Mac über USB

Viele ESP8266 modules werden schon mit einem onboard USB-Anschluss ausgeliefert. In diesem Falle muss das Board einfach nur mit einem USB-Kabel mit dem Mac verbunden werden.
Achtung: Manche Module haben zwar einen USB-Anschluss, dieser wird aber nur für die Stromversorgung genutzt. In diesem Fall wird ein externer USB-Seriell-Wandler benötigt.

Prüfen, ob die Hardware erkannt wurde

Unter “Über diesen Mac” gelangt man zu “System report”
systemreport

Hier sollte man jetzt ein USB2.0 Serial Gerät finden. usbserial

Treiberinstallation

Wenn denkt, alles ist bereit und die Arduino IDE startet, so kann man dort ein Gerät namens /dev/cu.usbmodem147741 als serielle Schnittstelle auswählen (die Ziffern hinter usbmoden können anders sein). Wenn man jetzt allerdings versucht, über diese Schnittstelle mit dem Controller zu kommunizieren,  passiert nichts. MacOS erkennt zwar, dass es sich um einen USB-Seriell-Adapter handelt, hat aber die entsprechenden Treiber nicht standardmässig dabei. Der Treiber ist oft ein billiger CH340G, da viele Firmen diesen dem deutlich teureren FTDI chip vorziehen. Die Installation des Treibers ist allerdings einfach. Man kann ihn hier herunterladen und installieren. Nach einem Neustart des Systems sollte die Arduino-Entwicklungsumgebung nun ein Gerät namens /dev/wvhusbserial14460 anbieten. Dieses kann jezt genutzt werden, um mit dem Board zu kommunizieren.

Installation der ESP8266 Module für die Arduino IDE

Da es sich bei den ESP8266-Boards nicht um “offizielle” Arduino-Boards handelt, sind die entsprechende benötigten Bibliotheken nicht in der Arduinio-Standardsoftware enthalten. Um die Treiber zu installieren, gibt man die URL http://arduino.esp8266.com/versions/2.2.0/package_esp8266com_index.json in den Einstellungen unter “Additional board managers” ein.

arduino-settings

Jetzt kann man unter “Tools/Board/Board Manager” and die ESP8266 module unter “Contributed” finden und installieren.

espcontrib

Das war’s schon. Alles ist installiert und es kann losgehen mit der Programmierung einen coolen kleinen IoT-Gerätes.

Falls der Upload der Software über die Arduino IDE nicht klappt, ist das Programm esptool.py eine gute Alternative. Es scheint in vielen Fällen besser zu funktionieren als der Uploader in der Arduino IDE. Es lässt sich zwar nicht einfach in die IDE integrieren, allerdings sind die Kommandozeilenparameter nicht kompliziert und man kann das Program einfach direkt aus einem Terminalfenster starten.

Installation eines MQTT-Brokers auf dem Raspberry Pi

Nicht nur für Hausautomatisierunge-Projekte, ein kleiner zentraler MQTT-Broker ist ein gutes Tool, um Sensordaten zu sammeln und an Steuerungsapplikationen weiterzuleiten. MQTT ist für solche Aufgaben gut geeignet, da es sich um ein leichtgewichtiges Protokoll handelt, was spezifisch für Sensorapplikationen entwickelt wurde. Daher funktioniert es auch sehr gut “nebenbei” auf einem Raspberry Pi.

Es gibt verschiedene MQTT-Implementationen. Sehr einfach lässt sich auf dem Raspberry Pi unter Raspbian Mosquitto nutzen. Die Installation ist sehr einfach:

sudo apt-get install -y mosquitto mosquitto-clients

Nun sollte der Moquitto-Server bereits laufen. Das kann wie folgt einfach getestet werden:

mosquitto_sub -h localhost -v -t test

Mit diesem Befehl wird ein MQTT Subscriber gestartet, der auf Nachrichten im “Test”-Kanal wartet.

Jetzt kann man eine zweite Verbindung zum Raspberry Pi starten und eine Nachricht absetzen:

mosquitto_pub -h localhost -t test -m "Hello world, Mosquitto"

Jetzt sollte der Subscriber die Nachricht “Hello world, Mosquitto” auf dem Bildschirm anzeigen.

Einbinden des Edimax SP-1101W/SP2101W in Home Assistant

Die WLAN-Schalter Edimax SP-1101W and SP2101W werden von Home assistant standardmässig unterstützt. Ein kleines Problem sind allerdings Benutzername und Password. Beim Setup des Gerätes kann man zwar ein neues Passwort setzen, den Benutzernamen jedoch nicht. Diesen braucht man allerdings für Home Assistant.Mit etwas Probieren, habe ich diesen herausgefunden – es ist “admin”.
Damit sieht die Konfiguration wie folgt aus (IP-Adresse und Passwort entsprechend der lokalen Konfiguration eintragen):

switch:
  platform: edimax
  host: 
  username: admin
  password: 
  name:

Wie sicher ist KNX?

Schaut man sich moderne Hausautomatisierungslösungen wie Z-Wave oder Zigbee an, tauchen auch immer wieder Sicherheitsprobleme auf. Einige davon wurden oder werden noch behoben, andere vielleicht nicht. Wenn schon diese modernen Technologien gewisse Probleme aufweisen, wie sieht es dann erst mit einem “Oldie” wie KNX aus?

Kurz gesagt: KNX ist das schlimmste, was man sich aus Sicherheitssicht vorstellen kann. Alle Geräte kommunizieren auf einem gemeinsamen Medium, es gibt weder Verschlüsselung noch Authentisierung oder Authorisierung. Wer Zugriff zum KNX-bus hat, kann praktisch alles tun.

Glücklicherweise gibt es aber einen positiven Punkt: Man braucht physischen Zugriff zum KNX-Bus. Zwar kann jemand, der Zugriff zur persönlichen KNX-Installation hat, alle möglichen bösartigen Dinge tun, allerdings ist diese Person dann schon in der Wohnung und könnte auch ohne Hausautomatisierung ziemlich fiese Sachen tun. Das Licht ein- oder auszuschalten dürfte da wohl das kleinste Problem sein. Das heisst, für Installationen in Wohnräumen, bei denen der KNX-Bus nicht mit anderen Netzen verbunden ist, ist KNX immer noch eine sichere Lösung. Allerdings: Welche Automatisierungslösung ist heute nicht mit anderen Netzen verbunden? Viele Intelligenz wird heute nicht direkt auf dem KNX-Bus abgebildet, sondern durch externe Geräte, die oft auch noch mit dem Internet verbunden sind.

Geht es trotzdem sicher? Im Prinzip schon, wenn man einige Dinge beachtet:

  1. Der KNX-Bus sollte nicht einfach direkt mit dem Heimnetz verbunden werden, besonders nicht, wenn evtl. noch ein WLAN-Gastzugang eingerichtet ist.
    KNX/IP Schnittstellen sind sinnvolle Geräte, man sollte aber überlegen, wie man den Zugriff darauf einschränken kann. Idealerweise setzt man ein Gateway ein, welches Benutzer authentifizieren kann und Zugriffsrechte verwalten kann.
  2. Benutzt man ein beliebiges kommerzielles Produkt mit Internetzugriff zum Zugriff auf KNX-Komponenten, sollte geprüft werden, ob der Hersteller regelmässige Sicherheitsupdates zur Verfügung stellt. Wenn der letzte Software-Release 18 Monate alt ist, ist das wohl kaum der Fall.
  3. Wer selbst ein Gateway oder eine Haussteuerung entwickelt, sollte von Anfang an überlegen, wie die Architektur aussehen muss, um eine möglichst hohe Sicherheit zu erreichen.

Bemerkung  1: Die physische Sicherheit kann ein Problem sein, wenn eine KNX-Installation z.B. ein gesamtes Haus mit mehreren Wohnungen steuert. Wenn die Wohnung also irgendeine “intelligente” Steuerung bietet, sollte man sich nochmals anschauen, was dort umgesetzt wurde und ob sich jemand Gedanken darüber gemacht hat, verschiedene Wohnungen voneinander zu trennen.

Bemerkung 2: Mit ETS 5.5 gibt es von der KNX Assoziation nun “Secure KNX”. Ich habe mir das noch nicht im Detail angeschaut. Warum? In erster Linie, weil die existierenden älteren Geräte, die bereits verbaut wurden, keine Security-Erweiterung unterstützen. Evtl. wird KNX Security in Zukunft an Bedeutung gewinnen, im Moment wird es von praktisch keinen Geräten unterstützt, die in bestehenden KNX-Installationen zu finden sind.

Programmiere dein eigenes LCARS Benutzerinterface mit Javascript und SVG

Vor einiger Zeit habe ich schon zu einem Projekt verlinkt, das ein Star-Trek LCARS GUI für die Gebäudesteuerung genutzt hat. Nachdem ich nun etwas herumgesucht habe, wie man etwas derartiges selbst umsetzen kann, bin ich auf viele verschiedene Frameworks gestossen. Manche davon sind recht alt. Diese habe ich nicht mehr im Detail angeschaut. Flash-basierte UIs sollten definitiv der Vergangenheit angehören. Andere Frameworks benutzen sehr viele Bilddateien. Auch diesen Ansatz mag ich nicht, da er recht viel Overhead erzeugt und die LCARS-Elemente eigentlich extrem einfach aufgebaut sind (jedes Element ist einfarbig).

Am meisten gefiel mir das LCARS SDK. Es nutzt Javascript und

Blöcke, um das Userinterface dynamisch zu bauen. Leider war die Dokumentation für mich nicht ganz klar und ich hatte Mühe, ein relativ einfaches Interface umzusetzen. Warum eigentlich überhaupt

Tags nutzen?

Es gibt einen noch einfacheren Weg: SVG – Scalable vector graphics. SVG ist seit mehr als 10 Jahren ein Webstandard. Man hat aber den Eindruck, es wird selten genutzt. Dabei unterstützen praktisch alle modernen Browser das Format sehr gut. Das Zeichnen von Rechtecken und Kreissegmenten ist sehr einfach. Das schöne an SVG ist, dass alle Elemente direkt im DOM mittels Javascript angesprochen werden können. So ist es ziemlich einfach, die Farbe eine Blocks zu ändern oder ihn auszublenden. Selbst das Drehen und Verschieben ist extrem einfach.

Ein weitere Vorteil an SVG ist es, dass nur sehr wenige Grafikobjekte gerendert werden müssen und dies auch auf schwachen PCs super funktioniert (oder Tablets, die gerne für die Gebäudesteuerung eingesetzt werden). Selbst auf Mobiltelefonen funktioniert ein SVG-basiertes UI perfekt.

Mit einer kleinen Bibliothek braucht ein einfaches Interface nur wenige Zeilen Code:

function home() {
    lcarsgen.container=document.getElementById("canvas");
    lcarsgen.next_x = 10
    lcarsgen.next_y = 10
    lcarsgen.knee({x:10, height2: 40})
    save_x = lcarsgen.next_x
    lcarsgen.button({x:10, text:"Light", id:"b_light"})
    lcarsgen.button({x:10, text:"Heating", id:"b_heating"})
    lcarsgen.button({x:10, text:"Blinds", id:"b_blinds"})
    lcarsgen.button({x:10, text:"Weather", id:"b_weather"})
    lcarsgen.button({x:10, text:"Movies", id:"b_movies"})
    lcarsgen.button({x:10, text:"Music", id:"b_music"})
    lcarsgen.button({x:10, text:"Config", id:"b_config"})
    lcarsgen.knee({x:10, height1: 120, height2: 40, \
                   type:"bottomleft"})
    save_y = lcarsgen.next_y - lcarsgen.spacing - 40
 
    // top bar
    lcarsgen.next_x=save_x
    lcarsgen.button({y: 10, width: 310, height: 40} )
    lcarsgen.button({y: 10, width: 310, height: 40} )

    // save for text display
    tx = lcarsgen.next_x-lcarsgen.spacing
    lcarsgen.button({y: 10, width: 55, height: 40, \
                     type:"rounded_right"} )

    // bottom bar
    lcarsgen.next_x=save_x
    lcarsgen.button({y: save_y, width: 310, height: 40} )
    lcarsgen.button({y: save_y, width: 310, height: 40} )
    lcarsgen.button({y: save_y, width: 55, height: 40, \
                     type:"rounded_right"} )

    lcarsgen.text({x:tx, y: 50, height: 40, text:"H.11 CONTROL", \
                   text_align: "right"} )
}

Das Ergebnis kann sich sehen lassen:
Screenshot 2016-05-12 12.15.52

Interfacing a KNX bus with Python

If you are looking for frameworks that allow you to interface a KNX bus using an IP interface, you will find a lot of tools. Many people still use eibd. However, looking at the eibd page you will see that eibd is no longer maintained.

If you read the KNX specification, you will notice that KNX packets are quite small with a simple structure. No XML stuff with namespaces as often used in modern APIs. So why not implementing the communication in a small script? Unfortunately it is a bit more complicated than just sending a packet to the KNX/IP interface an wait for the answer.

While KNX itself is connectionless, the KNX/IP interface isn’t. This means you first have to initialise a control connection to the KNX/IP interface and use this for data transmissions. Also you have to acknowledge every packet, otherwise the KNX/IP interface will drop the connection. Does this seem complicated? It isn’t.

A simple version of a KNX/IP communications stack (with very limited functionality) can be implemented in less than 400 lines of code. This even implements caching. This means the daemon actively listens to the KNX bus and stored the state of every object internally. Just reading the value of an object than does not need any KNX communication when the value has been seen on the bus already.

Using this simple interface, it is very easy to exchange messages with KNX group addresses:

from knx.ip import KNXIPTunnel
import time
import logging

def main():
    logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.DEBUG)

    tunnel = KNXIPTunnel("192.168.1.128",3671)
    tunnel.connect()
    
    while (True):
        # Toggle the value of group address 0/0/1
        tunnel.group_toggle(1)
        
        # display the values of group addresses 0/0/1 to 0/0/5
        for i in range(1,6):
            v=tunnel.group_read(i)
            print("{} = {}".format(i,v))

        # delay
        time.sleep(12)
        
if __name__ == '__main__':
    main()

References: