Milight-LEDs mit dem Raspberry Pi 2 steuern
10.07.2015
Henryk Plötz hat das Funkprotokoll der Milight LEDs reverse-engineert und den Quellcode Open-Milight für den Arduino zur Verfügung gestellt. Mit dem Quellcode lassen sich die Funkdaten der Milight LEDs empfangen und senden. Mit den Funkdaten können die LEDs zum Beispiel eingeschaltet oder ausgeschaltet werden. Da ich kein Arduino besitze aber den Mini-Computer "Raspberry Pi 2" bei mir rumliegen habe, habe ich das Openmili-Projekt für den Raspberry Pi 2 angepasst.
Hardware-Aufbau
Die Milight-LEDs gibt es mit dem Standard-Gewinde E27. Damit lassen sich die LEDs in handelsübliche Deckenlampen oder Schreibtischleuchten schrauben. Die LEDs können 256 verschiedene Farben darstellen und in etwa 20 Stufen die Helligkeit dimmen. Die RGB-LEDs strahlen in einem warmen Weiß, das für einen Schreibtisch eher ungeeignet ist. Für den Schreibtisch empfiehlt sich eher ein kaltes Weiß. Die Sorte Milight-LED mit 9 Watt ist relativ lang und ragt deshalb leider aus dem Lampenschirm heraus.
Schreibtischleuchte mit farbiger Milight LED und Fernbedienung
Achtung ! Mittlerweile gibt es einige Nachfolger von Milight mit einem veränderten Funkprotokoll. Dieser Artikel bezieht sich auf die erste Version der Milight LEDS, die etwa 20 Euro pro LED kosten. Für die kaltweißen bis warmweißen LEDs sind kleine Veränderungen am Quellcode nötig - dann funktioniert es auch mit diesen LEDs (siehe weiter unten).
Mit dem Funkchip "nRF24L01+" an dem "Raspberry Pi 2" und der Programmier-Bibliothek RF24 läßt sich das Funkprotokoll zwischen den Milight-LEDs und der Fernbedienung belauschen und die LEDs ohne Fernbedienung steuern.
Das Original-Layout ist von Davide Caminati und ist unter der CreativeCommons lizensiert (CC-by-SA 3.0). This image was created with Fritzing. So - jetzt sollten alle gewürdigt sein.
Das obere Bild ist mit der Layout-Software Fritzing erstellt. Leider ist in der Fritzing-Bibliothek nur die schematische Darstellung eines Raspberry Pi 1 vorhanden. Der Raspberry Pi 2 hat 40 GPIO-Pins. Die Verkabelung sieht aber genauso aus wie beim Raspberry Pi 1 - nur dass sich zwischen den Kabeln und der USB-Buchse weitere Pins befinden, die aber nicht genutzt werden.
Leitung | Kabelfarbe | Pin beim Raspberry Pi 2 | Pin beim Funkchip nRF24L01+ |
3,3 Volt | rot | 1 | 2 |
GND (Ground / Erdung) | schwarz | 6 | 1 |
MOSI (Master Output Slave Input) | blau | 19 | 6 |
MISO (Master Input Slave Output) | braun | 21 | 7 |
CE (chip enable bzw. slave select) | gelb | 22 | 3 |
SCLK (serial clock) | violett | 23 | 5 |
CSN (chip select not) | orange | 24 | 4 |
Der Funkchip nRF24L01+ kann im 2,4 GHz-Bereich von 2400 MHz bis über 2500 MHz mit einem Megahertz Abstand senden und empfangen. Das Mi-Light-Protokoll benutzt die drei Frequenzen 2411 MHz, 2442 MHz und 2473 MHz. Mit dem Beispiel-Programm "scanner" der RF24-Bibliothek können die drei Frequenzen beim Drücken der Fernbedienung beobachtet werden. Mit dem folgenden Quellcode können auch die gesendeten Daten der Fernbedienung mitgeschnitten werden.
Source-Code
In der Openmili-Software müssen die Pin-Positionen der Kabel für chip enable (CE) und chip select not (CSN) bei der Initialisierung angegeben werden. Wie in der oberen schematischen Darstellung zu sehen befinden sie sich an Pin 22 und 24.
RF24 radio(RPI_V2_GPIO_P1_22, RPI_V2_GPIO_P1_24, BCM2835_SPI_SPEED_1MHZ);
Diese Werte sind bereits in folgendem Quellcode von Openmilight eingetragen. Deshalb ist es wichtig bei der Verwendung dieses Projekts die identische Verkabelung zu benutzen.
# enable SPI in raspi-config - Advanced Options - SPI
# in newer versions of Raspbian it is under: "Interfacing Options" - SPI
sudo raspi-config
# after the reboot the relevant kernel module should be loaded
lsmod | grep spi
# should list: spi_bcm2835
mkdir ~/openmilight
cd ~/openmilight
# get the RF24 library for the Raspberry Pi 2
wget https://www.torsten-traenkner.de/wissen/smarthome/librf24-bcm.tgz
tar xzvf librf24-bcm.tgz
cd Raspberry/librf24-bcm
# for Raspberry Pi 2 and Raspbian Jessie modify the Makefile:
sed -i 's|BCM2835_PERI_BASE=0x.*|BCM2835_PERI_BASE=0x3F000000|g' Makefile
# for Raspberry Pi 1 BCM2835_PERI_BASE should be 0x20000000
make
sudo make install
# download openmilight for Raspberry Pi 2
wget https://www.torsten-traenkner.de/wissen/smarthome/openmilight_raspberry_pi.tgz
tar xzvf openmilight_raspberry_pi.tgz
cd openmilight
# compile openmilight
g++ -Ofast -mfpu=vfp -mfloat-abi=hard -march=armv7-a -mtune=arm1176jzf-s -I/usr/local/include -L/usr/local/lib -lrf24-bcm PL1167_nRF24.cpp MiLightRadio.cpp openmili.cpp -o openmilight
# for Raspberry Pi 1 compile openmilight with -march=armv6 instead of -march=armv7-a
# else you get an illegal instruction, you can also remove "-mtune=arm1176jzf-s"
# for debugging add the compiler option:
# -DDEBUG_PRINTF
# for execution become root user
sudo bash
# listen mode
./openmilight
# example output:
in listening mode
B0 F2 EA 7B DA 05 D2 .
B0 F2 EA 7B DA 07 D3 .
# for a more reliable sending scroll down (see Update 2017)
# sending mode
./openmilight "B0 F2 EA 6D B0 02 f0"
| | | | |
| | | | sequence number
| | | Button_of_Remote
| | brightness
| color
ID_of_Remote (3 byte) - change to your ID
# example output:
sending: B0 F2 EA 6D B0 02 f0
please enter string to send
B0 F2 EA 6D B0 02 f0
sending packet
Das Datenpaket des Milight-Protokolls besteht aus 3 Byte Identifizierungsnummer der Fernbedienung, ein Byte Farbcode, ein Byte Helligkeitswert, ein Byte für die Taste der Fernbedienung und ein Byte Sequenznummer. Die Tasten der Fernbedienung sind wie folgt kodiert:
Hexadezimaler Wert | Taste |
0x01 / 0x11 | alle LED-Gruppen einschalten |
0x02 | alle LED-Gruppen ausschalten |
0x12 | alle LED-Gruppen auf Nachtlicht stellen |
0x03 / 0x13 | LED-Gruppe 1 einschalten |
0x04 / 0x14 | LED-Gruppe 1 ausschalten |
0x05 / 0x15 | LED-Gruppe 2 einschalten |
0x06 / 0x16 | LED-Gruppe 2 ausschalten |
0x07 / 0x17 | LED-Gruppe 3 einschalten |
0x08 / 0x18 | LED-Gruppe 3 ausschalten |
0x09 / 0x19 | LED-Gruppe 4 einschalten |
0x0A / 0x1A | LED-Gruppe 4 ausschalten |
0x0B | Farbwechsel-Modus schneller abspielen |
0x0C | Farbwechsel-Modus langsamer abspielen |
0x0D | Farbwechsel-Modus ändern |
0x0E | Slider für die Helligkeit |
0x0F | Farbrad zur Auswahl der LED-Farbe |
Weitere Informationen gibt es auf der Projektseite von Henryk Plötz bei Hackaday.
Der Quellcode scheint noch nicht 100% zuverlässig zu sein, aber zumindest ist es ein Anfang. Im Internet gibt es außerdem die Empfehlung einen Kondensator mit 10 µF zwischen dem Pin von 3,3 Volt und Ground anzulöten, damit die Übertragung zuverlässiger wird.
Update 2017
Mitterweile hat Roy Bakker meinen Quellcode verbessert. Mit seinen Änderungen funktioniert das Senden an die LEDs zuverlässig, da das Datenpaket wiederholt übertragen wird.
git clone https://github.com/bakkerr/openmilight_pi
cd openmilight_pi/
# add include unistd
sed -i 's|#include <arpa/inet.h>|#include <arpa/inet.h>\n#include <unistd.h>|g' openmilight.cpp
# build the source code
make
sudo bash
# receive
./openmilight -l
# send "off" command to 0xF2EA
./openmilight -d -q F2 -r EA -c BA -b b8 -k 02 -v CD -n 30
# send "on" command to 0xF2EA
./openmilight -d -q F2 -r EA -c BA -b b8 -k 01 -v CD -n 30
# download
wget https://www.torsten-traenkner.de/wissen/smarthome/training.sh
wget https://www.torsten-traenkner.de/wissen/smarthome/remove.sh
# train LED with ID 0x1515 after the LED is switched on
./training.sh 15
# remove LED ID 0x1515 after the LED is switched on
./remove.sh 15
# send "off" command to 0x1515
./openmilight -d -q 15 -r 15 -c BA -b b8 -k 02 -v CD -n 30
Der Parameter -n gibt die Anzahl der Wiederholungen des Sendens des Datenpakets an. 30 Wiederholungen sollten für eine zuverlässige Datenübertragung ausreichen.
Kaltweiße LEDs
Für die kaltweißen LEDs von Milight müssen im Quellcode von Roy Bakker das Syncwort und die Funkkanäle angepasst werden.
git clone https://github.com/bakkerr/openmilight_pi
cd openmilight_pi/
# add include unistd
sed -i 's|#include <arpa/inet.h>|#include <arpa/inet.h>\n#include <unistd.h>|g' openmilight.cpp
# change the channels for cold white LED
sed -i 's|9, 40, 71|4, 39, 74|' MiLightRadio.cpp
# change the synchronisation word for cold white LED
sed -i 's|_pl1167.setSyncword(0x147A, 0x258B)|_pl1167.setSyncword(0x050A, 0x55AA)|' MiLightRadio.cpp
# build the source code
make
sudo bash
# receive
./openmilight -l
# example:
12 34 D3 01 08 F8 8A
# send "on" command to 0x1234
./openmilight -d -p 12 -q 34 -r D3 -c 01 -b 08 -k 00 -v 00 -n 15
# send "off" command to 0x1234
./openmilight -d -p 12 -q 34 -r D3 -c 01 -b 0b -k 00 -v 00 -n 15
-b is the command / key on the remote
(Un)Sicherheit
Mit dem obigen Quellcode können die Milight LEDs des Nachbarn belauscht werden und die empfangenen Daten zum Ein- und Ausschalten der LEDs benutzt werden (sozusagen Blinkenlights für die Wohnung). Der einzig interessante Parameter dabei ist die ID der Fernbedienung. Die Sequenznummer kann problemlos von 0 bis 255 durchlaufen werden. Das ist nach meinen Tests aber nicht nötig, da auch größere Abstände bei der Sequenznummer akzeptiert werden. Außerdem scheint die ID der Fernbedienung immer mit 0xB0 zu beginnen, so dass "nur" 65536 Werte für die ID möglich sind. Im Zweifelsfall können diese relativ schnell automatisiert durchgetestet werden. Bei WLAN gibt es bereits seit Jahren einige Attacken. Allerdings soll es demnächst "Protected Management Frames" und "WPA3" für eine bessere WLAN-Sicherheit geben. Wie groß die Gefahr des "War-Driving" bei LEDs wird, muss jede(r) für sich selbst einschätzen. Aus meiner Sicht rate ich davon ab diese Milight-LEDs zu kaufen, da es keine Möglichkeit eines Software-Updates gibt, das Sicherheit nachrüsten könnte. Mittlerweile (2017) habe ich meine Meinung geändert, da das Risiko von "böswilligen" Nachbarn meistens gering ist und die Milight-LEDs immer noch deutlich billiger sind als die Philips Hue Lampen.
Links
- Milight für Arduino - Quellcode von Henryk Plötz
- Milight für Arduino - Quellcode erweitert für kaltweiße LEDs
- Milight für NodeMCU bzw. ESP8266 - eine stromsparendere Lösung als mit dem Raspberry Pi
- Das Dekodieren von RGB+CCT LEDs funktioniert etwas anders, Christopher Mullins hat es in seinem Blog beschrieben
- Sebastian Roesner hat den Milight-Quellcode für RGB+CCT LEDs geforkt
Letzte Aktualisierung am 28. Mai 2017
Falls noch etwas unklar sein sollte, dann schreib einen Kommentar: