Raspberry Pi Smartmeter Lesekopf für 1€ selbst bauen.

Derzeit werden in Deutschland Stromzähler durch “Smartmeter” ausgetauscht. Die Smartmeter sind gerade smart genug, den Momentanverbrauch anzuzeigen. Damit sie das auch tun, muss man mit einer Taschenlampe eine PIN (PIN gibt es per Post vom Netzbetreiber) in das Smartmeter leuchten. Keine Ahnung, wer sich das Verfahren ausgedacht hat, Viel billiger als eine Folientastatur für eine Pin kann das kaum sein und es ist definitiv weniger smart. Vorne am Smartmeter gibt es eine Infrarotschnittstelle, über die man den Momentanverbrauch und den aktuellen Zählerstand gefahrlos (=Galvanisch getrennt) digital auslesen kann, nachdem die Pin eingegeben wurde.

Leider sind typische Leseköpfe für ihren Inhalt schweineteuer. Ein mit 45€ noch vergleichsweise günstiger kommt z.B. von Weidmann Elektronic. Typischerweise ist in so einem Lesekopf aber auch nur ein USB-Seriell Wandler und je nach Ausführung ein Fototransistor und eine IR-LED oder sogar nur ein Fototransistor verbaut.

Wenn man schon eine serielle Schnittstelle hat (z.B. USB-Seriell Wandler herumliegen oder einen Raspberry Pi…) kann man den Lesekopf auch für wenig Geld selbst bauen. Ich habe mich von diesem Post inspirieren lassen.

Einkaufsliste

  • BPW 40 Fototransistor
  • Kabel (lang genug um vom Lesenden Gerät bis zum Smartmeter zu gehen. Bei mir steht der Raspberry PI direkt unterm Stromzähler)

Aufbau des Sensors:

Der BPW40 kann direkt zwischen GND und RXD des an den GPIOs eines Raspberry Pi (oder eines USB-Seriell-Wandlers) angeschlossen werden. Für Raspberry Pi 3 sollte man erstmal im Vorfeld das Bluetooth-Modul deaktivieren, da dieses auch am seriellen Port angeschlossen ist.

Bei der Richtung des Fototransistors kann man nicht viel falsch machen: Ich habe den Sensor gleich mal versehentlich falsch herum angeschlossen, dem Raspberry Pi schadet das nicht, da schlimmstenfalls RxD auf GND gezogen wird (und dafür ist RxD ausgelegt). Auch der Sensor sollte vom schwachen Pullup an RxD nicht kaputt gehen können. Ist der Sensor falsch herum angeschlossen, empfängt man halt natürlich nix.

Verdrahtung des BPW40 mit dem Raspberry Pi

Anbringen am Stromzähler

Bei mir steht der Raspberry eh in der Nähe des Stomzählers. Den BPW40 habe ich am Kabel festgelötet und mit etwas Isolierband an einem kleinen Magneten befestigt. Die Metallscheibe am Stromzähler bei der Infrarotschnittstelle ist magnetisch, damit man den “Lesekopf” auf diese Weise dort anbringen kann. Hier ein paar Bilder des Aufbaus:

Anschluss des BPW40 auf dem Raspberry Pi
Seitenansicht “Lesekopf”: Isolierband verbindet BPW40 mit Haltemagnet. Dazu etwas Schaumstoff um die Pins gerade zu halten.
Draufsicht BPW40 mit Magnet am Stromzähler befestigt.

 

Ausblick: Setup auf dem Raspberry Pi

Um den Lesekopf zu aktivieren, muss man erstmal den seriellen Port nutzbar machen. Für Rasberry Pi 2 heißt das: raspi-config konsolenprogramm ausführen, darin folgende Schritte: Interfacing Options -> Serial: Would you like a login shell to be accessible over serial: NO -> Would you like the serial hardware port to be enabled: YES. Für Raspberry Pi 3 sollte man zusätzlich im Vorfeld das Bluetooth-Modul deaktivieren

Nach dem Reboot kann man dann mit cat /dev/ttyAMA0 mit etwas Glück die ersten Daten reintröpfeln sehen, wenn man den Lesekopf vor die Sendediode des Stromzählers hält. Falls nicht, lohnt es sich ein Terminalprogramm aufzurufen und dort die richtige Baudrate, den richtigen Port und den richtigen Übertragungsmodus zu wählen (typischerweise 9600 8n1). Ich habe minicom verwendet, das kann mit apt install minicom installiert werden, z.B. hier gibt es eine Kurzanleitung.

In einem weiteren Schritt braucht man dann eine Software, die das Binärkauderwelsch aus dem Stromzähler dekodieren kann, ich habe node-red zusammen mit dem node-red-contrib-smartmeter-Modul verwendet, um die Daten in ein bereits laufendes graphite backend zu füttern und mit Grafana zu visualisieren. Am Ende bekommt man schöne Grafen des Stromverbrauchs. Man sieht gut dass unsere Grundlast mit um die hundert Watt ziemlich hoch ist. Die hohen Spikes sind der Backofen.

Wenn ich dazu komme mache ich noch einen Post über das Setup von nodered und graphite/grafana.

Stromverbrauch über 24 h

WordPress dockerisiert

Die Frau setzt jetzt auch ein Blog auf. Da gerät man schnell ins Spielen. Während dieses Blog hier noch altbacken mit php und mysql auf dem Server läuft habe ich für das neue ein Team aus Dockercontainern aufgesetzt:

Für die automatische Einrichtung ein Trio aus Containern basierend auf diesem compose file:

  • nginx als reverse-proxy
  • jwilder/docker-gen zum automatischen erstellen passender vhost-konfigurationen für den reverse proxy. Einfach die passende Umgebungsvariable -e VIRTUAL_HOST=your.domain.com setzen, und nginx richtet den passenden Vhost ein und leitet ihn auf den exponierten port weiter.
  • jrcs/letsencrypt-nginx-proxy-companion zum automatischen Abruf passender Letsencrypt SSL zertifikate für die erstellten Vhosts.

Darunter dann ein angepasstes docker-compose.yml für das übliche Paar aus WordPress-container und *sql-container. Hauptanpassung (neben dem verschieben des WordPress-folders auf ein directory volume für einfachere anpassungen):

     environment:
       VIRTUAL_HOST: <vhost-1>.de,<vhost-2>.de...
       LETSENCRYPT_HOST: <vhost-1>.de,<vhost-2>.de...
       LETSENCRYPT_EMAIL: <letsencrypt-mail>

Damit funktioniert dann auch das automatische Erstellen eines vhosts.

Die Nginx-reverse-proxy-lösung macht es supereinfach neuen Containern gleich einen funktionierenden Vhost mit SSL zuzuteilen. Dabei braucht man fürs Aufsetzen auch wenig länger als für die manuelle SSL-Konfiguration eines einzelnen Vhosts. Sobald man den zweiten Container mit SSL versorgen möchte oder einen neuen Vhost hinzufügt hat man diese Zeit wieder drin.

Duofern Rolladenmotoren mit Homeassistant

English version of this post here
Homeassistant ist mein Frontend der Wahl für Hausautomatisierung. Schönes Interface, in Python geschrieben, und leicht anzupassen. Angefangen habe ich damit wegen des Mysensors-Supports.

Letztes Jahr ging es dann daran, die Rolladenmotoren auszusuchen. Leider versuchen die meisten Hersteller, ihre eigenen proprietären Lösungen in den Markt zu drücken. Homeassistant unterstützt zwar ein paar dieser Lösungen, aber man muss sich trotzdem noch oft ein schweineteures Gateway anschaffen, um mit den Komponenten reden zu können. Für mich war es zusätzlich schwierig, weil die installierten Rolläden mit einem Gurt daherkamen und der Rolladenkasten aus Stahlblech ist und so eine winzige Öffnung hat, dass es nicht mit vertretbarem Aufwand möglich ist, Rohrmotoren zu installieren.

Am Ende habe ich mich dann für Rademacher entschieden. Aus Faulheit: Gurtwickler für Einbau- oder Aufputzmontage mit Möglichkeit zur Funkfernbedienung. Die Entscheidung fiel auf sechs RolloTron Standard DuoFern. Homeassistant unterstützt zwar Duofern nicht von Haus aus. Die Perl-basierte Hausautomatisierung FHEM unterstützt aber das Duofern Protokoll mithilfe eines preislich akzeptablen USB-Sticks von Rademacher.
Duofern USB Stick

Ich traute mir zu, den Perl-Code für Homeassistant zu portieren. Nach ein paar Wochen hatte ich die Rolladensteuerung mit Homeassistant dann im Juni 2017 am Laufen. Pünktlich, um im Sommer die Rolläden nach dem Stand der Sonne zu fahren und das Haus schön kühl zu halten. Das Ergebnis findet sich als pyduofern auf meinem bitbucket.

Für die homeassistant-integration gibt es ein Unterverzeichnis in `examples`. Netterweise ist das Funkprotokoll bidirektional, man bekommt also die aktuelle Position der Rolläden auch dann angezeigt, wenn man sie am Motor manuell fährt.

Das Ganze ist noch im Werden. Der nächste Schritt um es nativ in homeassistant einbetten zu dürfen wäre, es als offizielles pypi-modul hochzuladen. Aber vorher möchte ich gerne noch etwas aufräumen und es mit asyncio zum Laufen bringen, um die aktuelle Architektur von Homeassistant. bestmöglich zu unterstützen.

Manually setting firewall rules for the Synology DSM openvpn interfaces

I keep forgetting how to do this so I’m finally gonna write it down. Synology DSM does not allow you to define arbitrary firewall rules. I especially want to define more paranoid firewall rules attached to openvpn connections. Sadly the GUI does not know about selective firewall rules for these so I had to do it myself. Synologys openvpn client calls

/usr/syno/etc.defaults/synovpnclient/scripts/ovpn-up

once the connection is established and

/usr/syno/etc.defaults/synovpnclient/scripts/ip-down

on disconnect. To define my own firewall rules I figured I would have to add to these two scripts. Unfortunately synology only sets its firewall rules some time after the scripts have run. So when I just add my own firewall rules to the two scripts, they are overwritten seconds later by synologys firewall. My solution is the following: at the end of the synology scripts

ovpn-up

and

ovpn-down

I add my own firewall setup script via:

# above here is synologys original code
# save the return code of the synology ip-up/down logic
returncode=$?

# call my script and send it to the background
nohup /opt/bin/iptables.sh &

# pass the original return code to the calling process
exit $returncode

In my own firewall script I begin with:

sleep 10

before I proceed to remove the synology firewall rules and replace them with my own.

WARNING: DSM Updates may overwrite your custom settings. Whenever you update DSM make sure that your settings are preserved.

Vectorized vortex clock

Dr Who style vortex clock
SVG (click to enlarge)

The Doctor Who intro features a vortex clock. Find it on youtube here (left of the two clips). I went through some pain to vectorize it in halfway decent quality in preparation of building a Doctor Who themed wall clock. In case anyone else wants an SVG version here is my amateur attempt. I know a lot could be done to make the SVG way smaller (probably the image could easily fit into 1/10 the size). My main goal was to get something that prints decently with a laser printer to iron on an aluminum plate, and this SVG is sufficient for that purpose.

Dynamic pdfs with pdflatex and ocg-p

Ever since I saw the microtype manual, I wanted to have something similar. The amazing thing about it is that you can switch on and off different microtype options and observe the resulting PDF output,

I now found the package ocg-p which allows to generate pdfs with dynamically switchable layers similar to the above. I built a demonstration which switches between a greek epigraph and its translation by clicking.

The code I used is the following, you can find the resulting PDF output here. The dynamic features only work in dedicated PDF readers (try opening with Acrobat):

\tikzset{external/export next=false}

\begin{tikzpicture}[node distance=3cm,every state/.style={fill=green!20},auto]
\begin{ocg}{edges}{ocedgesid}{1}
\draw[opacity=0] (-5,4)--(0,0);
\end{ocg}
\begin{ocg}{english}{german}{0}
\node[anchor=south east] at (0,0) { \toggleocgs{greek german}{I know that I know nothing}};
\node[anchor=north east] at (0,-0.2) { \toggleocgs{greek german}{\textit{Socrates}}};
\draw (-2,-0.1)--(0,-0.1);
\end{ocg}
\begin{ocg}{greek}{greek}{1}
\node[anchor=south east,font=\selectlanguage{polutonikogreek}] at (0,0) { \toggleocgs{greek german}{Οἶδα οὐκ εἰδώς.}};
\node[anchor=north east,font=\selectlanguage{polutonikogreek}] at (0,-0.2) { \toggleocgs{greek german}{\textit{Σωκράτης}}};
\draw (-2,-0.1)--(0,-0.1);
\end{ocg}

 

Running an open WIFI hotspot in Germany

logo by The Tor Project
logo by The Tor Project

German legislation makes it difficult to run an open WIFI hotspot: Not only will the police possibly search your house if somebody decides to commit criminal acts using your connection, you will also be liable via Störerhaftung for copyright-“crime” committed using your connection.

Despite the difficulties I am a big fan of offering open WIFI, and there is a large Café right across the street from my house which does not offer free WIFI on their own. Recently it hit me: Why not just make it a TOR hotspot? TOR is a free, strong anonymizing network run by volunteers like me. Data is redirected over three encrypted computers, making it impossible to trace data back to the users computer. If the Internet connection from the open WIFI passes through TOR nobody’s gonna ring my doorbell if somebody misbehaves.

Said was nearly done: used a Raspberry PI 2 I had so far no use for and combined it with a high power usb-wifi-adapter from amazon. After that it was only a matter of following the onion pi tutorial (but opting to run hostapd without encryption).

If you decide to do the same please consider doing it like I do: run a middle relay or a bridge on your pi in parallel to the access point (unless you pay per traffic) to give back to the TOR network that you use. Middle relays and bridges do not allow others to access the web from your connection, so they are quite safe to run even on a home connection.

 

Reduce minimum brightness on Sony Xperia z1 compact stock.

Quick note: the minimum brightness of the Xperia z1 compact is quite high. With root it can easily be set lower even on the stock ROM:
The command

echo 25>/sys/class/leds/wled\:backlight/brightness 

allows arbitrary brightness settings (replace 25 by a number between 1 and 255). Entering it on the console is a bit cumbersome so I made a tasker profile for it. You can download it as an app. In the app, brightness is fixed at 25, my optimum value for using the screen in the darkness. here, Source code for the task (in case you want to use it in your own tasker) here:

Backlight Low (3)
	A1: Run Shell [
 Command:echo >/sys/class/leds/wled\:backlight/brightness
 Timeout (Seconds):0
 Use Root:On
 Store Output In:
 Store Errors In:
 Store Result In: 
] 

brightness only stays low until set from another source overwrites it, so if you set it to zero (I know somebody will) switching the device off and on again should fix it. Using in changing light conditions needs more thought to prevent auto brightness from overwriting the value.

Disclaimer: if you accidentally harm your device using materials from here it is your own responsibility.

Raspberry Pi – Ultrasonic Distance Sensor part II

Using python for the ultrasonic distance sensor from part one of this post in a project I realized: It is still too slow. In my project I record high queality video using the raspberry pi camera at high resolution. That puts quite some load on the IO. As a result, the timing needed for the distance measurement becomes unreliable. Results vary by more than a meter shot-to shot (without changing the distance to the first obstacle). For higher timing accuracy I decided to do the distance measurement in C or C++. I stole some interrupt based c++ code from here. I modified it to have it measure continuously. The code does one measuerement every 25miliseconds and outputs the result as a binary float to stdout. The result looks like this (download here):

// code based on
// http://stackoverflow.com/questions/22580242/raspberrypi-g-ultrasonic-sensor-not-working
#include<iostream>
#include<wiringPi.h>
#include<errno.h>
#include<string.h>
#include<stdio.h>
#include<stdint.h>       //for uint32_t
using namespace std;
uint32_t time1=0,time2=0;
uint32_t time_diff=0;
float Range_cm=0;
volatile int flag=0;
void show_distance(void);

void myInterrupt(void) // Interrupt routine
 {                     // Called whenever the input pin toggles
 	uint32_t timeTemp=micros();
    if(flag==0) // first toggle? note the time
      {
            time1=timeTemp;
            flag=1;

      }
    else // second toggle? compute the distance
      {
            time2=timeTemp;
            flag=0;
            time_diff=time2-time1;
            Range_cm=time_diff/58.;
       }
  }
void show_distance()// writes the distance as a 
  {                 // binary float to stdout.
	fwrite(&Range_cm,sizeof(float),1,stdout); 
    cout.flush();
  }

int main(void)
  {
    if(wiringPiSetup()<0)
     {
       cout<<"wiringPiSetup failed !!\n";
     }
    pinMode(4,OUTPUT);
    pinMode(5,INPUT);
    pullUpDnControl(5,PUD_DOWN);
    if(wiringPiISR(5,INT_EDGE_BOTH,&myInterrupt) < 0)
            {
            cerr<<"interrupt error ["<<strerror (errno)<< "]:"<<errno<<endl;
            return 1;
            }

    while(1) // this loop starts a new measurement
    {        // every 2500 miliseconds
    	time1=0;
    	time2=0;
    	flag=0;
	digitalWrite(4,0);
	delayMicroseconds(1);
	digitalWrite(4,1);
	delayMicroseconds(10);
	digitalWrite(4,0);
	delayMicroseconds(25000);
	show_distance();
    }
    return 0;
 }

Now we just need to modify our python class to read the regularly arriving distance from the c-code instead of measuring it itsself. To do so I use the following code (download distanceMeter1.py):

# License GPL
import gps
import threading
import subprocess
import time
import numpy
import os
#from xdg.Menu import tmp
# culd be beefed up with code from here http://www.danmandle.com/blog/getting-gpsd-to-work-with-python/
#GPS
class distanceMeter(threading.Thread):
    # the init routine starts the compiled c-code
    # at high priority and initializes variables
    def __init__(self): 
        threading.Thread.__init__(self)
        self.distanceProcess = subprocess.Popen(['./distance'],stdout=subprocess.PIPE, bufsize=500,preexec_fn=lambda : os.nice(-19))
        self.running = True
        self.currentdistance=0.0
        self.lastFive=numpy.zeros(5)
        self.lastFiveValid=numpy.zeros(5)
        self.current=0
        self.currentValid=0
        print "created"
    # the run method of the thread is an infinite loop:
    #   whenever a distance measurement arrives
    #   the result is checked for validity (changes by more
    #   than 5 cm in 25msec are rejected as implausible for
    #   my means). Then mean and standard deviation of last
    #   five samples is computed.
    def run(self):
        print "starting loop"
        while self.running:
            # whenever new binary data comes in
            # put it into a numpy float and
            # process it.
            rawdata=self.distanceProcess.stdout.read(4)
            tmp=numpy.fromstring(rawdata,dtype="<f4")[-1] 
            if (numpy.abs(self.lastFive-tmp)<5).any():
                self.currentdistance=tmp
                self.lastFiveValid[self.currentValid%5]=tmp
                self.currentValid+=1
            self.lastFive[self.current%5]=tmp
            self.current+=1
    def stopController(self):
        self.running = False
        self.distanceProcess.send_signal(2)
        self.distanceProcess.kill()
    @property
    def distance(self):
        return numpy.mean(self.lastFiveValid)
    @property
    def deviation(self):
        return numpy.std(self.lastFiveValid)
# This is just to show how to use the the class above 
if __name__ == '__main__':
    test=distanceReader()
    test.start()
    for i in numpy.arange(1000):
        try:
            print test.distance
            time.sleep(.1)
            # you can put as much code as you like here,
            # test.distance will always contain the current
            # distance measurement, updated every 25msec.
        except KeyboardInterrupt:
            test.stopController()
            test.join()
            break

With this I get reasonable distance measurements even while recording high resolution high quality video using the camera.