Netzwerkweit Werbung blockieren mit Pi-hole

Netzwerkweit Werbung blockieren mit Pi-hole

pihole_logoHabt ihr genug von flackernden Werbebannern die mehr Raum einnehmen als der eigentliche Seiteninhalt oder gefühlte 100 Ad-Server die beim Öffnen einer einzigen Webseite kontaktiert werden? Adblock & Co. sind eine gute Sache, allerdings auf den Webbrowser beschränkt auf dem das Plugin installiert ist. Android oder iOS waren da meistens außen vor. Auf der Suche nach einem weiteren Beschäftigungsfeld für meinen Raspberry Pi bin ich auf ein nettes Projekt gestoßen!

Das ist ein Update des ursprünglichen Artikels da sich ein paar wichtige Dinge geändert haben und ich auch einen DNS-Loop eingebaut hatte…

Installation

Mit einer Zeile ist er auf dem Raspberry Pi installiert: der Werbeblocker Pi-hole

curl -L https://install.pi-hole.net | bash Mehr lesen

Odroid C2 – Update 1 (Gas- und Wasserzähler)

Ich habe zwei Raspberry Pi´s laufen. Einer “spricht” mit der Heizung, ließt den Stromzähler aus, beherbergt die MySQL-Datenbanken und präsentiert die Daten auf einer Webseite. Der zweite Raspi ließt den Wasserzähler aus, zählt die Umdrehungen des Gaszählers, beherbergt den Werbeblocker Pi-Hole und ist Videorecorder mit tvheadend im Backend.

Einer der beiden Raspis soll nun dem neuen Odroid weichen. Dabei entschied ich mich für den zweiten Raspi, da die ganzen PHP-Scripte erstmal nicht anzupassen sind. Das scheint mir der meiste Aufwand zu werden.
Mehr lesen

Odroid C2 (vs Raspberry PI 2)

Zuerst einmal noch ein frohes neues Jahr an alle!

Die Tage habe ich ein neues Spielzeug bekommen (nein, nicht zu Weihnachten). Es ist ein Odroid C2 mit eMMC-Speicherkarte. Den gab es im Komplettpaket mit Odroid, eMMC, Gehäuse und Netzteil für 70€. Der Odroid besitzt einen Quad-Core mit 1,5 GHz, 2 GB RAM und ein Gigabit-LAN welches er sich, im Gegensatz zur Raspberry-Architektur, nicht mit den USB-Ports teilen muss. Somit sollte die Gesamtleistung in allen Belangen deutlich höher ausfallen als die des Raspberry 2 oder 3. Auf der eMMC war ein Ubuntu 16.04 LTS mit Mate Desktop vorinstalliert.

Odroid Oberseite
Odroid Oberseite

Mehr lesen

Amazon Kindle als Statusdisplay

startseite_intranet
Webseite – Übersicht

Die Anzeige aller im Haus gesammelter Daten über eine Webseite ist nett (siehe Screenshot), benötigt aber einen Rechner, Handy, Tablet etc. wo diese Seite im Browser anzeigt wird. Unschön dabei ist, das wenn man schnell die Außentemperatur wissen will, immer erst das Gerät anschalten oder aufwecken muss, einen Webbrowser öffnen muss, die Webseite aufruft und wartet bis die Seite geöffnet wird. Das ist für einen kurzen Blick auf die Temperatur eher unpraktisch.

Es musste eine Anzeigemöglichkeit für die wichtigsten Daten her, welche immer angeschaltet ist. Nach kurzer Recherche im Internet stellte sich ein Amazon Kindle als Statusdisplay aufgrund des E-Paper-Displays als stromsparender Anwärter auf diesen Job heraus. Also schnell einen Kindle 4 (kein Touch) im Internet für ~ 30€ besorgt (da ich bisher keinen besaß).

Lösungsansätze

Es gibt verschiedene Ansätze den Kindle als Statusdisplay (z.B. für Wetterinformationen) zu nutzen. Es gibt Lösungen wie hier beschrieben die den Browser des Kindle nutzen. Besser gefielen mir aber die Lösungen die den Bildschirmschoner des Kindle zur Anzeige eines Statusbildes nutzen. Das macht unter anderem die Lösung für FHEM, als auch die Lösung von Matthew Petroff (von dem die FHEM-Lösung wahrscheinlich auch abgeleitet ist). Basierend auf dieser Lösung ist ausserdem diese hier mit weiterführenden Erklärungen der nötigen Schritte.
Ich bevorzuge anstelle der FHEM-Lösung die ursprüngliche Version, da ich nicht nur Daten aus FHEM anzeigen will, sondern auch Daten aus meiner MySQL-Datenbank und zusätzliche Informationen die direkt aus dem Internet stammen.

Den Kindle habe ich übrigens mittels “Kindersicherung” der FritzBox vom Internet gekappt falls Amazon auf komische Gedanken kommt und mir mit einem gutgemeinten Online-Update irgendwas zerschießt.

Die Lösung, den Bildschirmschoner des Kindle mit einem im Netzwerk bereitgestelltem Bild zu nutzen, benötigt verschiedene Anpassungen des Kindle als auch einige Komponenten die auf einem Server bereit gestellt werden müssen (bei mir der Raspberry PI).

Beschreibung

Die Beschreibung der nötigen Schritte und die benötigte Software sind hier (ursprüngliche Idee), hier (erweiterte Anleitung) und hier (ausführliche Anleitung) erklärt. Aus diesem Grund liste ich die nötigen Arbeitsschritte hier nur Stichpunktartig auf:

Kindle:

    • Jailbreak des Kindle damit man damit auch anständig arbeiten kann
    • SSH für Kindle (USBNetwork Hacks)
    • Kite installieren um nach dem Starten des Kindle das Init-Script (init_daten.sh) ausführen zu lassen
      • Stoppen von powerd
        • das ist nötig, da im Sleep-Mode der Cronjob nicht ausgeführt wird
        • (“@reboot” in crontab funktioniert leider auf dem Kindle nicht)
      • Stoppen von framework
    • Cronjob einrichten um alle x Minuten/Stunden ein aktualisiertes Bild per wget zu laden
      • vi /etc/crontab/root
      • */10 5-22 * * * /mnt/us/anzeige/zeige_daten.sh (alle 10 Minuten zwischen 5 und 22 Uhr

Server:

      • Python-Script anpassen
        • Das Python-Script sammelt die Daten, ersetzt die Platzhalter im SVG und erstellt daraus das PNG mittels rsvg-convert und pngcrush
      • Cronjob zur Ausführung des Python-Script anlegen
        • */3 * * * * /var/www/kindle/daten-script.sh &> /dev/null
      • SVG-Template anpassen (mit Editor und/oder Inkscape)
        • hier mein SVG für die Datenanzeige und
        • hier für zwischen 23 und 5 Uhr
        • bei Änderungen mit Inkscape nicht im “Inkscape-Format” abspeichern sondern als “Normales SVG”
      • rsvg-convert installieren (sudo apt-get install librsvg2-bin)
      • pngcrush installieren (sudo apt-get install pngcrush)

(Achtung! Die Dateinamen der Scripte in den Cron-Beispielen und die Dateinamen der SVG´s sind anders als in den oben verlinkten Anleitungen)

Python-Script

Das ursprüngliche Python-Script holt das Wetter von einer Webseite aus den USA. Das Wetter dort hat mich nicht wirklich interessiert und so habe ich das Script etwas angepaßt und verschiedene Wetterdaten und Statusinformationen aus meinen eigenen Quellen (FHEM und MySQL) gezogen.
Zur Anzeige der Wettericons nutze ich teilweise die Bilder aus dem ursprünglichen SVG. Einige habe ich allerdings gelöscht da ich hier z.B. keinen Blizzard erwarte. Die Werte für den Luftdruck und die Windstärke sowie die Auswahl des aktuellen Wetter-Icon erfolgt über die “condition” des FHEM-Yahoo-Wetter-Moduls.

Mein Pythonscript sieht wie folgt aus:

Bitte das Update im nachfolgendem Artikel beachten!!

#!/usr/bin/python2

import codecs
import telnetlib
import MySQLdb
from datetime import datetime, time

################
# Hole FHEM data
################
tnet_host= "localhost"
tnet_port= 7072
def fhem_task(fcmd):
    tc= telnetlib.Telnet(tnet_host,tnet_port)
    tc.write(fcmd)
    erg= tc.read_until( "\n" )
    tc.close()
    return erg

# Abwesenheit
if "off" in fhem_task("list ABWESENHEIT STATE\r\n"):
    abwesenheit="nicht gesetzt"
if "on" in fhem_task("list ABWESENHEIT STATE\r\n"):
    abwesenheit="gesetzt"

# Fenster
anz_fenster_offen=0;
if "open" in fhem_task("get FensterHeizung param STATE\r\n"):
    anz_fenster_offen += 1
if "open" in fhem_task("get FensterKeller param STATE\r\n"):
    anz_fenster_offen += 1
if "open" in fhem_task("get FensterGaestezimmer1 param STATE\r\n"):
    anz_fenster_offen += 1
if "open" in fhem_task("get FensterGaestezimmer2 param STATE\r\n"):
    anz_fenster_offen += 1
if "open" in fhem_task("get FensterBuero1 param STATE\r\n"):
    anz_fenster_offen += 1
if "open" in fhem_task("get FensterBuero2 param STATE\r\n"):
    anz_fenster_offen += 1
if "open" in fhem_task("get FensterWohnen1 param STATE\r\n"):
    anz_fenster_offen += 1
if "open" in fhem_task("get FensterWohnen2 param STATE\r\n"):
    anz_fenster_offen += 1
if "open" in fhem_task("get FensterWohnen3 param STATE\r\n"):
    anz_fenster_offen += 1
if "open" in fhem_task("get FensterWohnen4 param STATE\r\n"):
    anz_fenster_offen += 1
if "open" in fhem_task("get FensterGaestebad param STATE\r\n"):
    anz_fenster_offen += 1
if "open" in fhem_task("get FensterSpind param STATE\r\n"):
    anz_fenster_offen += 1
if "open" in fhem_task("get FensterBad1 param STATE\r\n"):
    anz_fenster_offen += 1
if "open" in fhem_task("get Garagentor param STATE\r\n"):
    stat_garage="offen"
else:
    stat_garage="geschlossen"

# Wetter
try:
    condition=str.split(fhem_task("get MeinWetter condition\r\n"))
    if len(condition)==5:
        wetter_icon=condition[3] + " " + condition[4]
    else:
        wetter_icon=condition[3]
except:
    wetter_icon="Fehler"


luftdruck=str.split(fhem_task("get MeinWetter pressure\r\n"))
tendenz=str.split(fhem_task("get MeinWetter pressure_trend_txt\r\n"))
wind=str.split(fhem_task("get MeinWetter wind_speed\r\n"))

####################
# Datenbank auslesen
####################
db = MySQLdb.connect(host="localhost", user="", passwd="", db="")        		
cur = db.cursor()
cur.execute("SELECT MIN(aussentemperatur), MAX(aussentemperatur) FROM temperaturen WHERE timestamp >= DATE(NOW()) ORDER BY timestamp")
for row in cur.fetchall():
    mintemp=round(row[0],2)
    maxtemp=round(row[1],2)

db.close()


################
# Preprocess SVG
################
now = datetime.now()
now_time = now.time()
if time(5,50) <= now.time() <= time(22,50):  
    # Open SVG to process
    output = codecs.open('daten_script_preprocess.svg', 'r', encoding='utf-8').read()
    # Insert icons and temperatures
    output = output.replace('ICON_ONE',wetter_icon.decode("utf-8"))
    output = output.replace('WETTER_BESCHR',wetter_icon.decode("utf-8"))
    output = output.replace('TEMP_A',fhem_task("get Aussenthermometer param temperature\r\n"))
    output = output.replace('LUFT_A',fhem_task("get Aussenthermometer param humidity\r\n"))
    output = output.replace('MIN_TEMP',str(mintemp))
    output = output.replace('MAX_TEMP',str(maxtemp))
    output = output.replace('DRUCK_A',luftdruck[3])
    output = output.replace('TENDENZ',tendenz[3])
    output = output.replace('WIND_A',wind[3])
    output = output.replace('ANZ_FENSTER',str(anz_fenster_offen))
    output = output.replace('STAT_ABWESENHEIT',abwesenheit)
    output = output.replace('STAT_GARAGE',stat_garage)
    output = output.replace('DATUM_UHRZEIT',datetime.strftime(datetime.now(), '%d.%m.%Y %H:%M:%S'))
    # Write output
    codecs.open('daten_script_output.svg', 'w', encoding='utf-8').write(output)
else:
    # Open SVG to process
    output = codecs.open('sleep_preprocess.svg', 'r', encoding='utf-8').read()
    output = output.replace('DATUM_UHRZEIT',datetime.strftime(datetime.now(), '%d.%m.%Y %H:%M:%S'))
    # Write output
    codecs.open('daten_script_output.svg', 'w', encoding='utf-8').write(output)

Es werden verschiedene Information aus FHEM mittels Telnet abgefragt und Daten aus einer MySQL-Datenbank (min/max-Werte) ermittelt. Neben Temperaturwerten zeige ich z.B. auch noch den Status der Fenster, des Garagentores und der Abwesenheitssteuerung an. Zwischen 5:50 und 22:50 Uhr wird alle 10 Minuten ein aktualisiertes Bild der Statusinformationen angezeigt, in der anderen Zeit ein Bild eines schlafenden Männchens. In dieser Zeit fragt der Kindle auch kein neues Bild per wget ab.

Ergebnis

Im Ergebnis schaut es dann so aus:

kindle_statusdisplay

Und hier die Anzeige für Nachts:

kindle_statusdisplay2

Als Erweiterung werde ich evtl. noch während der Heizperiode mit dem Kachelofen oder abhängig der Puffertemperatur, die obere und untere Temperatur des Pufferspeichers anstelle des Luftdruckes und der Windinformation anzeigen. Die Puffertemperatur ist in der Regel unser Maßstab ob Holz nachgelegt werden muss oder nicht.

Es könnte z.B. auch eine Display füllende Information ausgegeben werden wenn eine der Batterien der Fensterkontakte leer ist oder ein Warnhinweis falls die Heizung eine Störung oder anstehende Wartung anzeigt. Im Python-Script würde ich dann analog dem "Schlaf-Bild" ein spezielles PNG aus einem weiteren SVG erzeugen.
 

Chris

Synchrones Multiroom mit Kodi und AirAudio

synchronHeute ein Update bzgl. meiner Versuche, die Audioausgabe wie im Artikel Multiroom mit Kodi und AirAudio beschrieben, auf mehrere Lautsprecher zu synchronisieren. Das Wichtigste aber schon mal vorweg:

Die Wiedergabe ist nun absolut synchron auf der Musicbox Air von Canton und dem Kodi-Wohnzimmer PC!

Auch wenn ich es in dem ersten Multiroom-Artikel nur als “nice-to-have” bezeichnet habe, hat mich das Problem mit der asynchronen Wiedergabe bzw. dem hochwahrscheinlichen Auseinanderdriften doch nicht in Ruhe gelassen.

Synchrones Multiroom

Martin, der Entwickler der App “AirAudio” hat mich dann von sich aus dankenswerterweise darauf hingewiesen, das die aktuelle Airplay-Implementierung von Kodi keine Audio-Synchronisierung unterstützt. Solange dem so ist, werden alle meine Versuche bzgl. einer synchronen Wiedergabe auf dem mit Kodi-betriebenen Wohnzimmer-PC scheitern – und das unabhängig vom Zuspieler! Also auch die Nutzung von Whaale hätte kein Unterschied gemacht.

Statt der Airplay-Implementierung von Kodi selbst, sollte ich shairplay-sync als AirPlay-Abspieler auf dem Wohnzimmer-PC installieren. Bei shairplay-sync handelt es sich um ein Fork von shairplay. shairplay-sync unterstützt aber zusätzlich die Implementierung der synchronen Audiowiedergabe mittels Airplay.

Für die Installation von shairplay-sync gibt es neben den GIT-Quellen auch ein Paket für verschiedene Linux-Versionen. Da ich beim Wohnzimmer-PC (immer noch) ein Ubuntu 14.04 LTS nutze, konnte ich die Installation mittels PPA durchführen, da hiefür ein Paket bereitgestellt wird. Bei einem Raspberry kann bei der Installation z.B. nach der Anleitung von mikebrady Verfahren werden.

Installation von shairplay-sync

Mit folgendem Befehl werden die von dantheperson bereitgestellten Paketquellen von shairplay-sync im Ubuntu hinzugefügt:

sudo add-apt-repository ppa:dantheperson/shairplay-sync

Das Update der Paketquellen und die eigentliche Installation erfolgt dann wie folgt:

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install shairport-sync

Die Konfig-Datei von shairport-sync ist nach erfolgreicher Installation im Verzeichnis etc zu finden. Hier müssen ggf. noch ein paar Anpassungen vorgenommen werden.

sudo vim /etc/shairport-sync.conf

In der Konfig-Datei kann z.B. unter general der Name des “AirPlay-Gerätes” konfiguriert werden.

Audiogerät und -Ausgang ermitteln

Wichtiger sind aber die Einstellungen unter dem Punkt alsa. Hier muss das Device für die Audioausgabe eingetragen werden. So musste ich z.B. schauen, das der S/PDIF-Ausgang genutzt wird.

alsa =
{
    output_device = "hw:0,1";
    mixer_control_name = "PCM";
    mixer_device = "hw:0";
//  audio_backend_latency_offset = 0;
//  audio_backend_buffer_desired_length = 6615;
};

Die entsprechende Hardware für output_device kann über den Alsamixer herausgefunden werden:

alsamixer

Mit F6 werden alle im System verfügbaren Soundkarten angezeigt. Bei mir ist das HDA Intel mit der Nummer “0”. (Ich denke, das die Grafikkarte “1” hier auch wegen der möglichen Audioausgabe über HDMI angezeigt wird).

alsa2

Nun fehlt noch der passende Audioausgang. Dazu mit F2 in den im Bild gezeigten Dialog und den Eintrag mit “devices” auswählen.

alsa3

Im Ergebnis werden alle Audio-Geräte inklusive den vorhandenen Schnittstellen wie S/PDIF oder Klinke ausgegeben. Leider wird dieser Unterschied (zumindest bei mir) nicht in der Übersicht angezeigt.

alsa4

Also heißt es ausprobieren. Es sind ja nur zwei Möglichkeiten geblieben da das eigentliche Gerät mit “0” ja schon bekannt ist. Bleibt in der shairplay-sync-Konfiguration unter output_device nur noch hw:0,0 oder hw:0,1 zu testen. In meinem Fall war der S/PDIF-Ausgang hw:0,1. Die Mixer-Kontrolle ist unter 6 zu finden und in der Konfiguration entsprechend mit hw:0 anzugeben.

Andere Einstellungen habe ich in der Konfiguration nicht verändert. Evtl. paßt aber auch abhängig von der Hardware schon die Default-EInstellung und es sind keine Änderungen an der Konfiguration von shairplay-sync nötig.

Die nötigen Einstellungen können zum Testen auch direkt beim manuellen Start von shairplay-sync mittels Argument mitgegeben werden. Dazu erstmal ein bereits laufendes shairplay-sync mit folgendem Befehl stoppen:

sudo shairport-sync -k

Folgender Aufruf beinhaltet u.a. die von mir angepaßten Parameter:

sudo shairport-sync -vvv -a "Wohnzimmer" -d hw:0,1 -m hw:0 -c PCM

-v schreibt Debuginformationen zur Analyse von Problemen. -vv oder -vvv gibt mehr Informationen preis.
-a definiert den im AirPlay-Zuspieler angezeigten Namen
-d definiert das Gerät zur Audioausgabe. Hier kann dann mit dem im alsamixer gefundenen Geräten experimentiert werden
-c definiert den zu nutzenden Mixer. Dieser gehört in der Regel zum genutzten Gerät.

Eine komplette Liste aller Parameter von shairport-sync ist in der Hilfe oder in den man-Pages zu finden.

shairport-sync -h
man shairport-sync

Ergebnis

Im Ergebnis bin ich nun sehr zufrieden mit meiner Multiroom-Lösung. Neben den schon im ersten Artikel gut funktionierenden Punkten, kam jetzt das absolut synchrone Abspielen auf mehrere Lautsprecher hinzu. Die ganze Lösung ist immer noch sehr anwenderfreundlich. Fehlt mir jetzt noch ein kleiner portabler AirPlay-Lautsprecher für die Terrasse.

Vielen Dank nochmal an Martin von AirAudio für die sehr gute und schnelle Unterstützung!

 

Gruß
Chris

Multiroom mit Kodi und AirAudio

Multiroom ist ja aktuell in aller Munde. Auch ich wollte mich diesem Trend nicht verschliessen und habe einen “kleinen” Küchenlautsprecher angeschafft – die Canton Musicbox Air 3 in schickem Hochglanz-Weiß, passend zur Küche. Der Lautsprecher verfügt über WLAN mit Airplay und DLNA-Unterstützung. Vor allem aber hat sie genug Leistung und einen gutem Klang (vielleicht sogar etwas zu viel Wumms für die Küche…).

IMG_8769
Canton Musicbox Air 3

Gut, alleine mit dem Kauf des Canton-Lautsprechers war ich noch weit weg von Multiroom. Irgendwie muß “Multiroom” in meiner bereits vorhandenen Infrastruktur umgesetzt werden. Diese besteht aus einem mit Kodi betriebenem Wohnzimmer-PC und daran angeschlossenem 5.1 Receiver mit 5 Lautsprechern.

Was bedeutet Multiroom?

Für den einen bedeutet Multiroom die Wiedergabe der gleichen Tonquelle auf beliebig vielen Lautsprechern. Oder aber auch die Wiedergabe verschiedener Quellen auf einzelne Lautsprecher oder auch gruppiert auf unterschiedliche Lautsprecher.

Multiroom ist aber auch die Möglichkeit zur Auswahl der Wiedergabe von einer Tonquelle auf einem bestimmten Lautsprecher. Im ersten Anlauf tendiere ich zu diesem Ansatz, da ich nicht das komplette Haus beschallen muss und mich meistens in einem Raum aufhalte.

Die verschiedenen Hersteller wollen natürlich auch alle ein Stück vom Kuchen den Sonos mit seiner “PLAY”-Reihe angeschnitten hat und beschert dem Markt verschiedenen Mutliroom-Lösungen. Neben Sonos wäre da z.B. Teufel mit seiner Raumfeld-Reihe, Denon mit “HEOS”, Yamaha mit MusiCast und vielen mehr zu nennen.

Da ich im Wohnzimmer mit einem Denon-Receiver und den ELAC-Lautsprechern schon eine vernünftige Basis habe, schied für mich ein neues Komplettset der oben genannten Kandidaten aus. Ausser der Raumfeld-Reihe haben die meisten Multiroom-Sets auch eher “Plastik-Charm”, weshalb ich die ELAC-Lautsprecher bevorzuge.

Bedeutet Multiroom synchrone Musikwiedergabe?

Im Fall der oben beschriebenen Multiroom-Lösungen sollte der Ton schon synchron aus den Lautsprechern kommen. Schliesslich soll damit unter anderem auch 5.1/7.1/usw. umgesetzt werden. Das erledigt bei mir der Denon-Receiver ja schon. Bleibt noch die Synchronität zwischen Lautsprechern die z.B. in verschiedenen Räumen aufgestellt sind. Primär die Räume, die auch “akustisch verbunden” sind. Das war erstmal nicht mein Ziel, da es mir im ersten Anlauf um die Beschallung des Wohnzimmers oder der Küche basierend auf der Musikdatenbank des Wohnzimmer-PCs geht. Bei Filmen benötige ich den Ton nicht in der Küche oder sonstwo im Haus. Natürlich habe ich mich auch mit dem synchronen Abspielen der Musik beschäftigt aber dazu später mehr.

Mehr lesen

Raspberry PI 24/7 operation – Update

Nach den Anpassungen für den Neustart des Netzwerkinterfaces wie in Artikel “Stabiler 24/7 Betrieb des Raspberry” beschrieben, läuft der Minirechner heute genau seit 100 Tagen. Sehr gut!

After the adjustments to restart the network interface as described in post “Stabiler 24/7 Betrieb des Raspberry“, the Raspberry PI runs just fine for 100 days now. Very good!

Raspberry Pi Uptime

Chris

M-BUS – Wasserzähler

Von einem Freund habe ich einen M-Bus (Meter-Bus) Wasserzähler und einen Wärmemengenzähler bekommen. Der M-BUS ist ein Feldbus der über eine Zweidrahtleitung über sehr lange Strecken genutzt werden kann. Ein M-BUS Master fragt dabei alle Slaves im Strang oder Stern ab. Die Slaves werden teilweise vom M-Bus-Master mit Spannung versorgt. Mehr Details im Wiki.

Techem Wärmemengenzähler Techem Wasserzähler

Der M-Bus-Master sollte in meinem Fall aus dem Raspberry und einem Pegelwandler bestehen. Pegelwandler gibt es fertig von verschiedenen Herstellen (Relay, Wachendorff). Diese sind aber, je nachdem für wieviele Slaves sie ausgelegt sind, relativ teuer.

Mein erster Ansatz war daher der Selbstbau eines Pegelwandlers inkl. RS232-Schnittstelle zum Anschluss an den Raspberry Pi. Im Netz gibt es verschiedene Beschreibungen einer einfachen Schaltung und einige wenige Forumseinträge die sich mit dem Selbstbau eines Pegelwandlers bzw. generell mit M-Bus beschäftigen. Leider habe ich in keinem Forum eine Diskussion gefunden die bis zu einem funktionierenden System verfolgt wurde. Egal, ich habe es trotzdem mal versucht…

 

Selbstbau Pegelwandler

Auf der Platine ist der Pegelwandler inkl. einer RSA232 Schnittstelle die aus einem MAX3232 besteht. Die +/-15 Volt für den Pegelwandler habe ich mittels DCDC-Wandler IH0515S der Fa. XP Power erzeugt. Dieses Bauteil kann man z.B. bei Farnell beziehen. Dann das Ganze auf Lochraster zusammen gelötet und mit dem Raspi und dem Wärmemengenzähler verbunden.

IMG_7707 IMG_7708

max3232Lochrasterplan

Damit der Raspberry das M-Bus Protokoll versteht bzw. auch den Pegelwandler korrekt anspricht, habe ich die Bibliotheken von rSCADA genutzt. Die Quellen liessen sich problemlos auf dem Raspberry kompilieren. Im Ergebnis wurden verschiedene Binaries erzeugt um mit Slaves im Bus zu kommunizieren.

Meine ersten Versuche waren jedoch nicht von Erfolg gekrönt. Es wurde kein M-Bus-Gerät gefunden. Bei der Fehlersuche habe ich zuerst die serielle Schnittstelle separat getestet und mit Minicom über den Raspberry mit einem anderen Linux-Rechner kommuniziert. Das hat funktioniert. Die weitere Fehlersuche z.B. am M-Bus-Ausgang sind allerdings am fehlenden Oszilloskop gescheitert, da das Multimeter mich nicht wirklich weiter brachte.

Etwas niedergeschlagen habe ich dann nach drei Tagen erfolgloser Fehlersuche nochmal nach fertigen Pegelwandlern gesucht und ein relativ preiswertes Gerät gefunden und kurzerhand gekauft. Damit fiel die Fehlerquelle “Pegelwandler” schon mal weg.

 

Versuch mit gekauftem Pegelwandler

Der neue Pegelwandler benötigt zum Anschluss an den Raspberry Pi auch eine RS232 Schnittstelle. Um mir diesmal das Löten zu ersparen, hab ich erstmal den kompletten Versuchsaufbau auf einem Breadboard gesteckt. Der Pegelwandler läuft mit einer Spannung von 12-24 V DC weshalb ich den DCDC-Wandler aus dem ersten Versich auch nicht benötige.

IMG_7739

Die Binaries von rSCADA unterscheiden zwischen TCP- und seriell angeschlossenen M-Bus-Pegelwandlern. Da meiner seriell angeschlossen ist, benutze ich “mbus-serial-scan” um nach angeschlossenen Slaves im Bus zu suchen.
Als Argumente übergebe ich “-d” für den Debugmodus, “-b 2400” um 2400 Baud zu nutzen und “/dev/ttyAMA0” als serielle Schnittstelle des Pi.

Zu meiner Überraschung wurde direkt ein Slave (der Wasserzähler) erkannt. Sehr schön…

pi@raspberry2 ~/libmbus-0.8.0/bin $ ./mbus-serial-scan -d -b 2400 /dev/ttyAMA0
Scanning primary addresses:
0 [2014-12-13 13:59:21] SEND (005): 10 40 00 40 16
[2014-12-13 13:59:21] RECV (001): E5

Found a M-Bus device at address 0
1 [2014-12-13 13:59:22] SEND (005): 10 40 01 41 16
2 [2014-12-13 13:59:22] SEND (005): 10 40 02 42 16
3 [2014-12-13 13:59:22] SEND (005): 10 40 03 43 16
4 [2014-12-13 13:59:22] SEND (005): 10 40 04 44 16
5 [2014-12-13 13:59:23] SEND (005): 10 40 05 45 16
6 [2014-12-13 13:59:23] SEND (005): 10 40 06 46 16
7 [2014-12-13 13:59:23] SEND (005): 10 40 07 47 16
...

Hat man alle angeschlossenen M-Bus-Geräte per Scan identifiziert, können mit einem weiteren Programm die Daten des Gerätes ausgelesen werden. Auch hier gibt es wieder das Argument “-d” für den Debugmodus, “-b” zur Einstellung der Baudrate, das Device der seriellen Schnittstelle und die vom Scan ermittelte Device-Nummer. Im Fall meines Wasserzählers ist das die “0”. Die Daten der Slaves werden in einer einfachen XML-Struktur zurück geliefert.

./mbus-serial-request-data -d -b 2400 /dev/ttyAMA0 0
[2014-12-13 14:06:46] SEND (005): 10 5B 00 5B 16
[2014-12-13 14:06:47] RECV (084): 68 4E 4E 68 08 00 72 12 37 16 46 68 50 49 07 B6 00 00 00 0C 14 53 42 00 00 8C 10 12 35 53 42 00 0B 3B 00 00 00 8C 20 14 53 42 00 00 8C 30 14 00 00 00 00 04 6D 21 0F CD 1C 4C 14 02 00 00 00 42 6C BF 1C 42 EC 7E DF 1C 0A 92 2A 00 10 0A 92 2B 00 10 3E 16
mbus_frame_print: Dumping M-Bus frame [type 4, 84 bytes]: 68 4E 4E 68 08 00 72 12 37 16 46 68 50 49 07 B6 00 00 00 0C 14 53 42 00 00 8C 10 12 35 53 42 00 0B 3B 00 00 00 8C 20 14 53 42 00 00 8C 30 14 00 00 00 00 04 6D 21 0F CD 1C 4C 14 02 00 00 00 42 6C BF 1C 42 EC 7E DF 1C 0A 92 2A 00 10 0A 92 2B 00 10 3E 16



46163712
TCH
73

Water
182
00
0000



Instantaneous value
Volume (1e-2  m^3)
4253
2014-12-13T14:06:47



Instantaneous value
Volume (1e-4  m^3)
425335
2014-12-13T14:06:47

...

Da es auf Anhieb funktioniert hat, habe ich die serielle Schnittstelle auf Lochraster gebannt und der Pegelwandler wird mittels kleinem 12V-Netzteil betrieben. Dann Raspberry Pi, Pegelwandler und Platine im Netzwerkschrank verstauen…

MAX3232

 

Software

Den Stand des Wasserzählers protokolliere ich nun einmal täglich um 23:59 Uhr. Das wird per Cronjob und einem kleinen PHP-Script erledigt. Warum PHP? Weil ich zu ungeduldig war und das schnell umsetzen wollte und schon das ein oder andere ähnliche PHP-Script fertig hatte.

Das Script ruft das Binary wie oben erklärt per shell_exec auf. Ab dem XML-Teil parse ich die Ausgabe und extrahiere die relevanten Informationen die dann in eine MySQL-Tabelle geschrieben werden.

[cc lang=”php”]
‘));
$xmloutput = new SimpleXMLElement($xmloutput);
$zaehlerID=$xmloutput->SlaveInformation->Id;
$zaehlerStand=$xmloutput->DataRecord[1]->Value/10000;

$mysqlhost=””;
$mysqluser=””;
$mysqlpwd=””;
$connection=mysql_connect($mysqlhost,$mysqluser,$mysqlpwd) or die (“Verbindungsversuch fehlgeschlagen”);
$mysqldb=””;
mysql_select_db($mysqldb,$connection) or die(“Konnte die Datenbank nicht waehlen.”);
$sql = “INSERT INTO wasserzaehler (timestamp,zaehlerid,zaehlerstand) VALUES (CURRENT_TIMESTAMP,$zaehlerID,$zaehlerStand)”;
$query = mysql_query($sql) or die(“Anfrage 1 nicht erfolgreich”);
?>;
[/cc]

Da ich auf meiner Webseite aber nicht nur den absoluten Wasserverbrauch darstellen möchte sondern auch den Tagesverbrauch, kommt folgendes SQL zum Einsatz. Hier werden die Einträge aus zwei aufeinanderfolgenden Zeilen subtrahiert um die Differenz zum Vortag zu bestimmen.

SELECT 
    CASE DATE_FORMAT(wz1.timestamp,'%w')
	WHEN 0 THEN 'Sonntag'
	WHEN 1 THEN 'Montag'
	WHEN 2 THEN 'Dienstag'
	WHEN 3 THEN 'Mittwoch'
	WHEN 4 THEN 'Donnerstag'
	WHEN 5 THEN 'Freitag'
	WHEN 6 THEN 'Samstag'
    ELSE 'fehler' END,
	wz1.zaehlerstand - IFNULL(wz2.zaehlerstand, 0) AS verbrauch
    FROM wasserzaehler wz1
    LEFT JOIN wasserzaehler wz2
    ON wz2.timestamp = (
	SELECT MAX(timestamp)
	FROM wasserzaehler wz3
	WHERE wz3.timestamp < wz1.timestamp
   )
ORDER BY wz1.timestamp

Das Ergbnis sieht dann wie folgt aus. Ich war etwas erschreckt wieviel Wasser man an machen Tagen verbraucht!

wasserzaehler_screenshot

 

Selbstgebauter Pegelwandler

Da ich ja nun weiß das es generell funktioniert und der Fehler meiner ersten Lösung definitiv im selbstgebauten Pegelwandler liegt, werde ich den Versuch mit dem Selbstbau demnächst nochmal angehen.

 

Sobald der Wärmemengenzähler in den Wasserlauf des Kachelofens eingebaut ist, werde ich nochmal einen kurzen Beitrag schreiben. Das Prinzip des Auslesens ist ja analog zum Wasserzähler aber vielleicht gibt es in den zurückgelieferten Daten unterschiede.

 

Viel Spaß mit dem M-Bus!

Chris

Stabiler 24/7 Betrieb des Raspberry – Netzwerk neu starten

Zum Thema stabiler 24/7-Betrieb des Raspberry PI´s gibt es viele gute Blogeinträge die sich mit dem richtigen Netzteil, dem korrektem Umgang von Linux mit der SD-Karte, evtl. Hitzeprobleme und Netzwerkproblemen aufgrund zu hoher Last beschäftigen.

Siehe z.B.: hier oder hier

Unter anderem wird auch immer wieder der Hardware-Watchdog des PI genannt. Diesen Watchdog hab ich auch aktiviert, da ich in der Vergangenheit immer wieder Probleme mit dem Netzwerk (Stichwort smsc95xx errors und weiterführende Links) hatte. Dies äusserte sich immer wieder mit dem Einfrieren des PI. Der Watchdog machte im Fehlerfall einen Restart und gut war. Nach den letzten Firmwareupdates hat sich die Frequenz der Restarts auch stark verringert.

Dann aber war mein Raspi plötzlich per SSH nicht mehr erreichbar und auch die Webseite wurde nicht mehr angezeigt. Seltsamerweise erfolgte kein Neustart durch den Watchdog. Da ich den Raspi Headless betreibe, blieb mir nicht viel anderes übrig als ihn einfach vom Strom zu trennen und wieder anzuschliessen. Danach lief alles wieder einwandfrei. Leider häuften sich diese Probleme so das es mir zu nervig wurde, ständig den Strom zu kappen. Schliesslich ist mein Raspi ja ein Server und soll gescheit laufen.

Nach den Neustarts ist mir aber auch aufgefallen, das die Daten der Leseköpfe lückenlos in die Datenbank geschrieben wurden. Anscheind lief der Raspi noch und nur das Netzwerk war nicht verfügbar.

Das Problem war teilweise im Message-Log zu sehen:


Nov 22 12:51:10 raspberrypi kernel: [1279051.095475] usb 1-1: USB disconnect, device number 10
Nov 22 12:51:10 raspberrypi kernel: [1279051.095493] usb 1-1.1: USB disconnect, device number 11
Nov 22 12:51:10 raspberrypi kernel: [1279051.095887] smsc95xx 1-1.1:1.0 eth0: unregister 'smsc95xx' usb-bcm2708_usb-1.1, smsc95xx USB 2.0 Ethernet
Nov 22 12:51:10 raspberrypi kernel: [1279051.095954] smsc95xx 1-1.1:1.0 eth0: hardware isn't capable of remote wakeup
Nov 22 12:51:10 raspberrypi kernel: [1279051.136136] usb 1-1.2: USB disconnect, device number 12
Nov 22 12:51:10 raspberrypi kernel: [1279051.136650] cp210x ttyUSB0: cp210x converter now disconnected from ttyUSB0
Nov 22 12:51:10 raspberrypi kernel: [1279051.136748] cp210x 1-1.2:1.0: device disconnected
Nov 22 12:51:10 raspberrypi kernel: [1279051.137275] usb 1-1.3: USB disconnect, device number 13
Nov 22 12:51:10 raspberrypi kernel: [1279051.137769] ftdi_sio ttyUSB1: FTDI USB Serial Device converter now disconnected from ttyUSB1
Nov 22 12:51:10 raspberrypi kernel: [1279051.137876] ftdi_sio 1-1.3:1.0: device disconnected
Nov 22 12:51:10 raspberrypi kernel: [1279051.295583] Indeed it is in host mode hprt0 = 00021501
Nov 22 12:51:11 raspberrypi kernel: [1279051.575374] usb 1-1: new full-speed USB device number 14 using dwc_otg
Nov 22 12:51:11 raspberrypi kernel: [1279051.575636] Indeed it is in host mode hprt0 = 00021501
Nov 22 12:51:11 raspberrypi kernel: [1279051.825598] usb 1-1: not running at top speed; connect to a high speed hub
Nov 22 12:51:11 raspberrypi kernel: [1279051.825950] usb 1-1: New USB device found, idVendor=0424, idProduct=9512
Nov 22 12:51:11 raspberrypi kernel: [1279051.825971] usb 1-1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
Nov 22 12:51:11 raspberrypi kernel: [1279051.836520] hub 1-1:1.0: USB hub found
Nov 22 12:51:11 raspberrypi kernel: [1279051.836765] hub 1-1:1.0: 3 ports detected
Nov 22 12:51:11 raspberrypi kernel: [1279052.115374] usb 1-1.1: new full-speed USB device number 15 using dwc_otg
Nov 22 12:51:11 raspberrypi kernel: [1279052.215553] usb 1-1.1: not running at top speed; connect to a high speed hub
Nov 22 12:51:11 raspberrypi kernel: [1279052.215947] usb 1-1.1: New USB device found, idVendor=0424, idProduct=ec00
Nov 22 12:51:11 raspberrypi kernel: [1279052.215973] usb 1-1.1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
Nov 22 12:51:11 raspberrypi kernel: [1279052.219107] smsc95xx v1.0.4
Nov 22 12:51:11 raspberrypi kernel: [1279052.280966] smsc95xx 1-1.1:1.0 eth0: register 'smsc95xx' at usb-bcm2708_usb-1.1, smsc95xx USB 2.0 Ethernet, b8:27:eb:bd:01:0b
Nov 22 12:51:12 raspberrypi kernel: [1279052.375552] usb 1-1.2: new full-speed USB device number 16 using dwc_otg
Nov 22 12:51:12 raspberrypi kernel: [1279052.477284] usb 1-1.2: New USB device found, idVendor=10c4, idProduct=ea60
Nov 22 12:51:12 raspberrypi kernel: [1279052.477318] usb 1-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
Nov 22 12:51:12 raspberrypi kernel: [1279052.477334] usb 1-1.2: Product: CP2104 USB to UART Bridge Controller
Nov 22 12:51:12 raspberrypi kernel: [1279052.477349] usb 1-1.2: Manufacturer: Silicon Labs
Nov 22 12:51:12 raspberrypi kernel: [1279052.477362] usb 1-1.2: SerialNumber: 0065B522
Nov 22 12:51:12 raspberrypi kernel: [1279052.479039] cp210x 1-1.2:1.0: cp210x converter detected
Nov 22 12:51:12 raspberrypi kernel: [1279052.479519] usb 1-1.2: cp210x converter now attached to ttyUSB0
Nov 22 12:51:12 raspberrypi kernel: [1279052.491197] smsc95xx 1-1.1:1.0 eth0: hardware isn't capable of remote wakeup
Nov 22 12:51:12 raspberrypi kernel: [1279052.535606] smsc95xx 1-1.1:1.0 eth0: hardware isn't capable of remote wakeup
Nov 22 12:51:12 raspberrypi kernel: [1279052.555550] usb 1-1.3: new full-speed USB device number 17 using dwc_otg
Nov 22 12:51:12 raspberrypi kernel: [1279052.640093] smsc95xx 1-1.1:1.0 eth0: hardware isn't capable of remote wakeup
Nov 22 12:51:12 raspberrypi kernel: [1279052.661511] usb 1-1.3: New USB device found, idVendor=0403, idProduct=6001
Nov 22 12:51:12 raspberrypi kernel: [1279052.661547] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
Nov 22 12:51:12 raspberrypi kernel: [1279052.661563] usb 1-1.3: Product: FT232R USB UART
Nov 22 12:51:12 raspberrypi kernel: [1279052.661577] usb 1-1.3: Manufacturer: FTDI
Nov 22 12:51:12 raspberrypi kernel: [1279052.661590] usb 1-1.3: SerialNumber: A4009G5A
Nov 22 12:51:12 raspberrypi kernel: [1279052.664914] ftdi_sio 1-1.3:1.0: FTDI USB Serial Device converter detected
Nov 22 12:51:12 raspberrypi kernel: [1279052.665117] usb 1-1.3: Detected FT232RL
Nov 22 12:51:12 raspberrypi kernel: [1279052.665314] usb 1-1.3: Number of endpoints 2
Nov 22 12:51:12 raspberrypi kernel: [1279052.665337] usb 1-1.3: Endpoint 1 MaxPacketSize 64
Nov 22 12:51:12 raspberrypi kernel: [1279052.665353] usb 1-1.3: Endpoint 2 MaxPacketSize 64
Nov 22 12:51:12 raspberrypi kernel: [1279052.665367] usb 1-1.3: Setting MaxPacketSize 64
Nov 22 12:51:12 raspberrypi kernel: [1279052.667714] usb 1-1.3: FTDI USB Serial Device converter now attached to ttyUSB1
Nov 22 12:51:13 raspberrypi kernel: [1279054.248030] smsc95xx 1-1.1:1.0 eth0: link up, 100Mbps, full-duplex, lpa 0xC5E1

An dem Raspi hängt der Lesekopf für den Stromzähler und für die Heizung. Der Raspi scheint die USB-Ports aus irgendwelchen Gründen unmotiviert neu zu starten. Das funktioniert für die USB-Ports immer erfolgreich, aber das Netzwerk blieb dabei gelegentlich auf der Strecke (obwohl in der letzten Zeile gegenteiliges behauptet wird). Das hängt anscheinend immer noch mit Fehlern im smsc95xx zusammen.

Neustart des Netzwerkinterfaces

Nun gut…dann muss das Netzwerk halt nochmal gestartet werden. Folgendes Bash-Script rufe ich alle 10 Minuten per Cron auf. Ist das Netzwerk verfügbar, passiert nichts. Ist das Netzwerk nicht verfügbar wird versucht des Interface neu zu starten. Gelingt auch das nicht, wird der Raspi rebootet. Mittels logger wird der Neustart in /var/log/messages geloggt.

[cc lang=”bash” lines=”40″]
#!/bin/sh
IP_TO_TEST=”
PING_COUNT=1
PING=”/bin/ping”
IFUP=”/sbin/ifup”
IFDOWN=”/sbin/ifdown –force”
INTERFACE=”eth0″ #Device angeben welches geprüft werden soll
LOCKF=”/opt/lockf”
$PING -c $PING_COUNT $IP_TO_TEST > /dev/null 2> /dev/null
if [ $? -ge 1 ]
then
logger “$INTERFACE scheint unten zu sein, versuche restart…”
if [ -e $LOCKF]
then
logger “$INTERFACE immer noch unten, NEUSTART…”
rm -f $LOCKF 2>/dev/null
sudo reboot
else
touch $LOCKF
logger $(sudo $IFDOWN $INTERFACE)
sleep 10
logger $(sudo $IFUP $INTERFACE)
fi
else
#logger “$INTERFACE laueft”
rm -f $LOCKF 2>/dev/null
fi
[/cc]

Im Log sieht man dann den erfolgreichen Neustart des Netzwerkinterfaces durch das obige Bach-Script.


Nov 22 12:51:12 raspberrypi kernel: [1279052.665353] usb 1-1.3: Endpoint 2 MaxPacketSize 64
Nov 22 12:51:12 raspberrypi kernel: [1279052.665367] usb 1-1.3: Setting MaxPacketSize 64
Nov 22 12:51:12 raspberrypi kernel: [1279052.667714] usb 1-1.3: FTDI USB Serial Device converter now attached to ttyUSB1
Nov 22 12:51:13 raspberrypi kernel: [1279054.248030] smsc95xx 1-1.1:1.0 eth0: link up, 100Mbps, full-duplex, lpa 0xC5E1
Nov 22 13:00:02 raspberrypi logger: eth0 scheint unten zu sein, versuche restart...
Nov 22 13:00:09 raspberrypi kernel: [1279589.925658] smsc95xx 1-1.1:1.0 eth0: hardware isn't capable of remote wakeup
Nov 22 13:00:09 raspberrypi kernel: [1279590.124240] smsc95xx 1-1.1:1.0 eth0: hardware isn't capable of remote wakeup
Nov 22 13:00:09 raspberrypi logger: Stopping NTP server: ntpd. Starting NTP server: ntpd.
Nov 22 13:00:11 raspberrypi kernel: [1279591.726167] smsc95xx 1-1.1:1.0 eth0: link up, 100Mbps, full-duplex, lpa 0xC5E1
Nov 22 13:00:32 raspberrypi logger: Stopping NTP server: ntpd. Starting NTP server: ntpd.

Seitdem läuft mein PI seit 16 Tagen durch. Mal sehen wie lange er ohne Neustart durchhält!

Gruß
Chris

Gaszähler auslesen

Nachdem meine Versuche den M-BUS Wärmemengen- und Wasserzähler auszulesen vorerst beendet sind und ich auf den bestellten M-BUS-Pegelwandler warte, habe ich mich dem Auslesen des Gaszählers gewidmet. Das sollte erfolgsversprechender sein…

Als ich dann endlich den vor langer Zeit bestellten Reed-Kontakt mk 471 b (z.B. bei Reichelt) wieder gefunden habe, konnte es losgehen.

Der Gaszähler hat an der letzten Stelle des Zählwerkes bei der “0” einen Magneten wodurch der Reedkontakt bei jeder vollen Umdrehung einmal geschlossen wird. Diese Impulse gilt es mit einem Raspberry über einen GPIO zu zählen.

IMG_7735

Den Reedkontakt habe ich natürlich wieder professionell mit Klebeband fixiert…hält!

IMG_7734

Angeschlossen ist der Reedkontakt über eine Zwillingslitze direkt an einen GPIO und Ground des Raspberry PI. Pull-Up braucht es keinen. Dieser wird per Software aktiviert.

Den GPIO lese ich mit einem Python-Script aus welches in einer Endlosschleife ausgeführt wird und den GPIO (im Beispiel Pin “21”) jede Sekunde abfragt. Sekundenweise sollte reichen, da ich nicht hoffe das unser Gaszähler so schnell läuft. Immer wenn der Reed geschlossen wird, wird eine “1” und der Zeitstempel in die Spalten “timestamp” und “zaehlerstand” einer MySQL-Tabelle geschrieben. Das passiert immer nur beim Wechsel des Reed von “Offen” nach “Geschlossen”. Sollte der Zähler genau mit dem Magnet am Reed stehen bleiben, passiert nichts.

[cc lang=”python”]

import RPi.GPIO as GPIO
import time
import MySQLdb

GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)

# GPIO definieren
REED_gas = 21
# definierten GPIO als Eingang setzen
GPIO.setup(REED_gas, GPIO.IN, pull_up_down=GPIO.PUD_UP)

status_alt=1
while True:
status_aktuell = GPIO.input(REED_gas)
# REEDKONTAKT geoeffnet
if status_aktuell == 1:
#print “Kontakt offen”
status_alt=GPIO.input(REED_gas)
# REEDKONTAKT geschlossen
elif status_aktuell==0:
#print “Kontakt geschlossen”
if status_alt!=status_aktuell:
status_alt=GPIO.input(REED_gas)
# Datenbankverbindung
db = MySQLdb.connect(host=”“, user=”“, passwd=”“, db=”“)
# Impuls in Datenbank eintragen
cursor = db.cursor()
cursor.execute(“””INSERT INTO gaszaehler (timestamp,zaehlerstand) VALUES (CURRENT_TIMESTAMP,1)”””)
db.commit()
cursor.close()
time.sleep(1)
[/cc]

IMG_7737

Da das Python-Script sich ab und an mal verabschiedet, starte ich es per Cronjob wieder neu falls der Prozess nicht mehr vorhanden ist. Ich sollte vielleicht lieber das Problem im Python-Script suchen und das ein oder andere Try&Catch einbauen, aber es geht auch erstmal so…

#!/bin/sh
if ps -ef | grep -v grep | grep gaszaehler.py ; then
    exit 0
else
    sudo python /usr/local/bin/gaszaehler.py &
    logger "gaszaehler.py neu gestartet"
    exit 0
fi

Zur Auswertung benutze ich dann folgende SQL-Querys:

SELECT sum(zaehlerstand) FROM gaszaehler

Hiermit werden alle gespeicherten “Ticks” summiert. Dazu muss noch ein Startwert addiert werden da der Gaszähler ja schon eine zeitlang lief.
Dieser Startwert muss ggf. ab und an mal korrigiert werden falls der Raspi mal einen Umlauf des Zählers nicht mitbekommt weil z.B. der unwahrscheinliche Fall eintritt, dass das Klebeband nicht gehalten hat oder wahrscheinlicher, das Python-Script bzw. der ganze Raspi nicht mehr läuft. Den Startwert gebe ich als eine Zahl inkl. der drei Nachkommastellen an und addiere das Ergebnis der SQL-Query dazu. Um die richtige “Einheit” kümmere ich mich in der Ausgabe auf der PHP-Seite mit folgender PHP-Zeile:

[cc lang=”php”]
$sql = “SELECT sum(zaehlerstand) FROM gaszaehler”;
$query = mysql_query($sql) or die(“Anfrage nicht erfolgreich”);
while ($wert = mysql_fetch_array($query)) {
$gesamtwert=($wert[0]*10)+$gas_startwert;
}
$gesamtwert=substr($gesamtwert,0,-3).”.”.substr($gesamtwert,-3,2);
[/cc]

Der Faktor 10 muss hier beachtet werden, da ja nur alle 0,01m³ Impulse gezählt werden und ich den Startwert mit allen drei Nachkommastellen angegeben habe. Die zweite Zeile setzt das Komma in der Ausgabe an die richtige Stelle.

Eine tägliche Auswertung funktioniert z.B. mit folgender SQL-Query:

SELECT CASE DATE_FORMAT(timestamp,'%w')
          WHEN 0 THEN 'Sonntag'
          WHEN 1 THEN 'Montag'
          WHEN 2 THEN 'Dienstag'
          WHEN 3 THEN 'Mittwoch'
          WHEN 4 THEN 'Donnerstag'
          WHEN 5 THEN 'Freitag'
          WHEN 6 THEN 'Samstag'
          ELSE 'fehler' END,
          sum(zaehlerstand)
FROM gaszaehler
WHERE DATE(timestamp)>=DATE_SUB(NOW(),INTERVAL 7 DAY)
GROUP BY day(timestamp)
ORDER BY timestamp

Auch hier bekommt man den korrekten Wert in m³ durch einfache Kommaverschieberei in der Ausgabe. Den Faktor 10 benötigt man bei der täglichen Auswertung nicht:

[cc lang=”php”]substr(($wert[1]),0,-2).”.”.substr(($wert[1]),-2)[/cc]

In der Webseite sieht das folgendermaßen aus:

gaszaehler_screenshot

Das alles läuft erst drei Tage und es gibt bestimmt noch Verbesserungspotential aber ein Anfang ist gemacht.

Gruß
Chris