Donnerstag, 25. Dezember 2014
Seit der nun beendeten Saison nutzen wir in unserer Mosterei eine Hackschnitzelheizung zur Pasteurisierung. Diese Heizungsanlage ist zudem auch mit den Wohngebäuden verbunden. Dabei kommt bei uns eine Hargassner WTH-110 zum Einsatz.
Sowohl in der Mosterei als auch für die Wohnungen ist es elementar wichtig, dass man umgehend über mögliche Störungen informiert ist. Leider bietet Hargassner hier nur proprietäre und zudem unflexible Möglichkeiten (SMS via eigenem GSM-Modul, digitale Fernbedienung im Wohnraum installieren, ...). Diese Möglichkeiten sind für mich inakzeptabel. Daher muss man sich selbst behelfen.
Die Heizung hat zwei Schnittstellen zur Außenwelt: 1. eine serielle Schnittstelle RS-232 und 2. eine CAN-Bus-Verbindung zwischen Heizung und Heizkreisregler in den Wohngebäuden.
Da ich nicht wusste wo welche Daten übertragen werden und die Hardware nicht allzu teuer ist, habe ich beschlossen beide Verfahren parallel zu nutzen.
Für mein Vorhaben kaufte ich folglich einen USB-CAN-Bus-Adapter. Als preiswert und bisher ausreichend hat sich der USBtin von Thomas Fischl herausgestellt. Ich kaufte das Evaluation Board for USBtin / SMD assembled and programmed. With Mini-USB connector. für 34,90 €. Die Platine kommt wie abgebildet ohne Gehäuse und mit Lötaugen für den CAN-Bus. Da ich weder Fertigkeit noch Gerät für Platinen-Lötoperationen habe, habe ich mich entschlossen das non-destruktiv anzugehen und habe ein Kabel mit Aderendhülsen versehen, die ich mit einer Zange so rund gepresst habe dass die Aderendhülsen sich genau in die Lötaugen stecken lassen. Dann das überstehende Ende wieder flach gequetscht, so dass der Stecker nicht raus rutscht. Als Kabel habe ich ein altes TAE-Verlängerungskabel genommen und von beiden Seiten ca. 50 cm abgeschnitten. Die Stecker-Seite habe ich wie beschrieben an den USBtin angebracht, die Buchsenseite habe ich im CAN-Bus-Schutzmodul auf die CAN-Leitung geklemmt. Ich habe sowieso direkt neben dem CAN-Bus-Schutzmodul einen 10-Zoll-Verteiler stehen, dort drin steht nun mein Raspberry Pi mit wie beschrieben angeschlossenem USBtin. Da der USBtin kein Gehäuse hat, habe ich eines aus Karton gemacht (Verpackung einer Netzwerkdose).
Erste Tests habe ich mit der Software USBtinMonitor von Thomas Fischl auf meinem Laptop gemacht. Dabei kamen zwar sofort Daten aus dem Bus aber der Inhalt hatte mich ernüchtert: Ca. 10 Telegramme pro Sekunde und ich habe nach mehreren Minuten Aufzeichnung keinerlei Regelmäßigkeiten erkennen können. Erst nach einiger Zeit bin ich auf die Idee gekommen, dass man es ja mal mit abweichender CAN-Bus-Geschwindigkeit versuchen könnte. Nach mehreren Versuchen bin ich auf 50.000 baud als korrekte Bus-Geschwindigkeit gekommen. Mit dieser Einstellung kommen nun Telegramme in schöner Regelmäßigkeit an, die verwendeten CAN-IDs sind nur noch eine Hand voll.
Es kommen nun Telegramme in dieser Form (Format: ID;DLC;RTR;EXT;DATA):
00a;8;0;0;00 00 00 00 00 00 00 00
161;8;0;0;40 03 04 95 15 DC 15 DC
14e;8;0;0;01 00 64 00 09 0A 0B 00
014;8;0;0;00 00 97 02 41 CC 1F 82
D.h. es kommen nur nicht-erweiterte Pakete, keine RTR-Pakete und alle schön 8 Bytes lang. Das verspricht mit genügend Energie einige Informationen preiszugeben.
Ein erster Erfolg war die Deutung des halben Werts in der letzten oben genannten Zeile: Hier wird in den letzten 4 Bytes ein Timestamp übertragen. Da 32-Bit-Unix-Timestamps ein Jahr-2038-Problem haben, hat Hargassner hier offenbar einfach eine neue Zeitmessung erfunden und überträgt einfach Sekunden seit 1.1.1980. Et voilà, wir haben ein Jahr-2048-Problem. :)
Der Durchbruch kam dann durch ein Experiment einige Tage später. In der Zeile
014;8;0;0;00 01 3f 00 00 00 01 59
steht das zweitletzte Byte für "Störung". Ist das auf 1 gesetzt, liegt eine Störung vor. Wird die Störung behoben und quittiert, fällt es auf 0 zurück.
Das Byte davor steht übrigens für "Rauchfangkehrer-Betrieb" und teilt den Heizkreisen mit, dass sie bitte Wärme abnehmen möchten damit der Kessel auf volle Leistung gehen kann.
Auf Seiten des CAN-Bus war dies die komplette Erkenntnis der letzten Tage. Allerdings habe ich nach dem Fund des Störungs-Bit nicht mehr weiter gesucht sondern mich dran gemacht, das so zu programmieren dass ich eine SMS-Alarmierung erhalten kann. Dies war ja die wichtigste Zielsetzung des ganzen Projekts.
Meine bisherigen Erkenntnisse habe ich dann also in Python-Code gegossen, der auf dem Raspberry-Pi laufen kann. Ein aktueller Stand ist in meinem nagelneuen Github-Profil zu finden: https://github.com/bwurst/hargassner-monitor.
Die RS232-Verbindung habe ich bereits via Laptop ausprobiert und Daten erhalten. Ich bin noch nicht ganz fertig geworden mit der Verkabelung aber in den nächsten Tagen kommt auch im Heizraum dann ein zweiter Raspberry-Pi zum Einsatz der die serielle Schnittstelle überwacht. Natürlich wäre es naheliegend beide Überwachungen auf einem Gerät zu bündeln. Damit ich beim Test des einen aber nicht die Alarmierung des anderen störe, entwickle ich nun zunächst auf zwei Geräten. Kann man später immer noch zusammen bauen.
Donnerstag, 8. März 2012
Heute bin ich über alten Sourcecode gestolpert, den ich teilweise vor langer Zeit erstellt hatte und auch diversen Leuten versprochen hatte, das "irgendwann" als freie Software zu releasen.
Im Zuge eines Warum eigentlich nicht jetzt?-Anfalls habe ich jetzt mal zwei git-Repositories erstellt und den Code dort eingespielt und gebe diese hiermit frei.
Für beide Projekte gilt: Das war Software die ich selbst gebraucht habe und sie ist in genau dem Zustand in dem ich sie bei mir momentan benutze. So ist meist die Konfiguration im Code, auch wenn ich hoffe, dass keine Zugangsdaten mehr irgendwo enthalten sind. Die Software ist vermutlich in dem Zustand in dem sie hier angeboten wird für niemanden nützlich.
Folgende Projekte gibt es hier:
Bib2011 steht für "Bag-in-Box-Kassenprogramm". Ich verwende für unsere Mosterei schon länger ein eigenes Programm zur Kassenverwaltung. 2011 habe ich dies von Grund auf neu gemacht, gedacht für die Nutzung auf einem Touchscreen.
Der Code basiert auf Python und Qt4. Die UI-Designer-Dateien sind auch dabei.
python-solarmax ist eine Bibliothek um Ertragsdaten aus Solarmax-Wechselrichtern auszulesen. Das Paket besteht aus einer Python-Bibliothek zur Kommunikation mit dem Gerät und einem kleinen Programm das diese Bibliothek nutzt um die Ertragsdaten regelmäßig in einem SQLite-Datenbank zu speichern.
Das (proprietäre) Kommunikations-Protokoll habe ich zunächst reverse-engineered, indem ich die Hersteller-Software in einer virtuellen Maschine benutzt habe und dann im Netzwerk die Daten ausgewertet habe. Nachdem ich das praktisch fertig hatte, bekam ich vom Hersteller doch noch eine Dokumentation des Protokolls, allerdings mit unbrauchbaren Lizenzhinweisen (keine Veröffentlichung des Protokolls und keine Herstellung von Software die veröffentlicht wird). Ich habe also die Bibliothek ohne die Dokumentation fertig geschrieben.
Wenn jemand die Software interessant findet und für irgendwas eigenes brauchen kann, würde ich mich sehr über eine Nachricht freuen.
Donnerstag, 25. Februar 2010
Wir haben vor Kurzem ein Upgrade von MySQL 5.0 auf 5.1 vollzogen. Nach dem Update fiel auf, dass beim Zugriff auf einige (wenn nicht alle) Views eine Warnung kommt: View [...] has no creation context
Die Meldung lässt sich am einfachsten dadurch beheben, dass man den View einfach mit sich selbst überschreibt. Da dies bei uns eine größere Menge Views war, habe ich dazu folgendes Stück Code geschrieben.
(Ich nutze dafür unsere SQL-Library, die einfach eine gewisse Abstraktion bereitstellt, z.B. die Zugangsdaten aus einem Configfile lesen, DictCursor initialisieren und db.query() als Wrapper für db.execute() und db.fetchall(). Diese Library sollten wir wohl demnächst mal veröffentlichen. :))
#!/usr/bin/python
import re
from sql import sql
db = sql()
views = db.query("select TABLE_SCHEMA `schema`, TABLE_NAME `name` "+
"FROM INFORMATION_SCHEMA.VIEWS WHERE VIEW_DEFINITION =''")
for v in views:
print 'fixing %s.%s\n=========================' % (v['schema'], v['name'])
vdef = db.query("SHOW CREATE VIEW %s.%s" % (v['schema'], v['name']))
new = re.sub('CREATE .* VIEW (`?%s`?.)?`?%s`?' % (v['schema'], v['name']),
'ALTER VIEW `%s`.`%s`' % (v['schema'], v['name']), vdef[0]['Create View'])
db.query(new)
Montag, 9. März 2009
Da ich seit langem bei OSM aktiv bin, hatte es mich immer wieder gestört, dass ich kein mobiles Gerät habe, auf dem ich diese Karten nutzen kann.
Momentan gibt es leider keinen voll befriedigenden Weg, OSM-Karte auf einem mobilen Gerät zu betreiben und umfassend zu benutzen.
Die dafür programmierten Anwendungen sind einfach noch nicht so weit, dass man sich damit in fremden Gefilden navigieren lassen könnte und die Hersteller proprietärer Navigationssysteme halten ihr Dateiformat aus verständlichen Gründen unter Verschluss.
"OpenStreetMap-Karte auf Garmin" vollständig lesen
Mittwoch, 24. September 2008
Seit langem sind mir Besucher-Tracker ein Dorn im Auge. Daher sind Domains wie www.etracker.de und google-analytics.com seit einiger Zeit bei mir im lokalen DNS-Server gesperrt, so dass diese aus meinem lokalen Netz nicht mehr aufgerufen werden können.
Leider wird grade etracker oftmals so penetrant eingesetzt, dann man einfache Unterseiten oder Downloads nicht mehr aufrufen kann, wenn deren Seite nicht mehr erreichbar ist.
Daher habe ich mir jetzt einen lokalen "Proxy" für dieses Problem erstellt. Das Setup ist simpel:
- Ein lokaler DNS-Resolver wird so konfiguriert, dass er für den betreffenden Host die Adresse eines eigenen Webservers zurückliefert.
- Der Webserver erhält einen neuen VHost, der für die Hostnames der betreffenden Websites verantwortlich ist.
- Ein CGI-Script liest die URL aus dem Aufruf-Parameter und sendet eine Weiterleitung an die betreffende Adresse ohne dass irgendwelche Statistiken zentral gespeichert werden.
Nachfolgend meine dafür verwendeten Konfigurationen und Scripte.
"Tracker umgehen" vollständig lesen
Montag, 1. September 2008
Seit geraumer Zeit haben sich bei uns neben einer beachtlichen DVD-Sammlung auch einige Filme angesammelt, die z.B. vom Fernsehen aufgezeichnet wurden.
Ich bin dagegen, für solche Filme krampfhaft ein Original-Cover zu suchen bzw. die DVD kaum vom Original unterscheibar zu machen. Im Gegenteil, ich möchte die Chance nutzen, die Filme dann einheitlich, sachlich und erkennbar zu positioniren.
In unserer lokalen Installation von VideoDB haben wir alle Filme erfasst. Sowohl die Kauf-DVDs als auch die selbst aufgezeichneten.
Um aus den dort hinterlegten Daten automatisch Cover zu erzeugen, habe ich mir gestern ein kleines Script zusammengebastelt.
Teile des Sourcecodes stammen aus einem anderen Projekt, daher auch die unsinnige Aufteilung auf zwei Dateien. Das Script ist aus der Not entstanden und so sieht es auch aus. Aber es dürfte leicht sein, daraus was eigenes zu erstellen.
Python-Code ist zugänglich unter https://svn.bwurst.org/software/dvdcover/, Lizenz: Public Domain.
Als Dateneingabe fungiert ein XML-Export (von phpMyAdmin) der "videodata"-Tabelle aus der VideoDB-Datenbank.
Ausgabe sind einzelne PDF-Dateien für die einzelnen Cover.
Mittwoch, 5. März 2008
Nachdem ich jetzt doch von einigen Leuten weiß, die meinen greylisting-Filter bei sich einsetzen, kann ich das auch grade mal hier announcen... ;-)
Es gibt davon eine neue Version. Es gibt einen ziemlichen Bruch, es wird jetzt MySQL anstelle von SQLite als Backend benutzt. Das liegt daran, dass ich vor habe, eine selektive Whitelist (»Mails an diese Adresse bitte in den nächsten 10 Minuten nicht greylisten«) für unsere Kunden zu ermöglichen. Dazu muss es eine gemeinsame Datenbank für das webinterface und das greylisting geben, was hiermit geschehen ist.
Die offizielle Release-Seite enthält auch ein detaillierteres Change-Log.
Peinlicherweise habe ich erst ein paar Minuten nach dem Release festgestellt, dass die neue Version von courier, für die ich grade ein ebuild erstellt habe, eine kleine API-Änderung hat. ich habe mit einem Bugfix-Release der Version 2.0.1 darauf reagiert.
Sonntag, 13. Januar 2008
Wie vor einer Weile schon einmal schrieb, hat mein Handy (oder obexftp, keine Ahnung wer schuld ist) leider besondere Anforderungen, wie man Dateien für den OBEx-transfer spezifizieren muss.
Da ich ein Freund der Konsole bin und daher meine GPX-tracks immer mittels obexftp auf meinen Rechner kopiere, ist das doch etwas lästig.
Aber jetzt gibt es Abhilfe. ;-)
Um mir diese Aufgabe zu erleichtern, habe ich ein kleines Python-Programm erstellt, das zuerst obexftp aufruft um ein Verzeichnis-Listing zu erhalten und dann alle Dateien mittels obexftp -G herunterläd (-G bedeutet, Dateien werden auf dem Handy gelöscht).
Zur Verwendung muss zuerst das Python-Modul »ElementTree« installiert werden. Danach müssen die Bluetooth-Hardware-Adresse des Gegenüber und der OBEX-Datei-Pfad im Script eingetragen werden.
Download: obexget
Lizenz: GPL >= 3
Montag, 10. Dezember 2007
Neulich konnt eich mich endlichmal aufraffen, mich um automatisiertes Onlinebanking zu kümmern um nicht immer alle Lastschriften für schokokeks.org manuell machen zu müssen.
Die gute Nachricht zuerst: Es geht einfacher als ich vermutet hatte. Ich benutze jetzt diese Kommandozeile:
aqbanking-tool debitnote --bank=60291120 --account=671279017 --rbank=12345678 --raccount=192837465 --rname="Kundenname" --value="123,00:EUR" --purpose="schokokeks.org" --purpose="Re-Nr. 1234, Kd-Nr. 05" --purpose="vom 2007-12-01" --force-check --exec
Diese Zeilen lasse ich mir von einem Script zusammen bauen, das die Daten der aktuell offenen Rechnungen aus der Datenbank liest.
Aber nun zum Ernst der Lage:
Ich hatte vor einiger Zeit in einem Blog-Posting dazu aufgerufen, dass man an das AqBanking-Projekt spenden sollte, damit der Entwickler die Spezifikationen für die neuen Volksbank-Karten kaufen kann.
Ich hatte diesen Aufruf nicht gelöscht oder geändert, weil ich der Meinung war, auch wenn diese Spezifikationen jetzt beschafft wurden, sollte der Autor einen Anreiz haben, den Code auch zu schreiben.
Jetzt allerdings muss ich diesen Aufruf entschieden zurücknehmen. Der Grund dafür ist hier zu finden:
http://www.aquamaniac.de/sites/aqbanking/user.php#aqbanking-cli
Eben dieses Kommandozeilen-Programm, mit dem ich obigen Kurztipp durchführe, wird aber der kommenden Generation der AqBanking-Schnittstelle kommerzielle Software werden und nicht mehr frei zur Verfügung stehen.
Natürlich ist das keine komplette Katastrophe, man kann (vermutlich) eines der auf AqBanking aufbauenden Programme als Vorlage für ein relativ minimalistisches, neues Kommandozeilen-Programm benutzen. Aber alleine das Vorgehen, dieses Programm ohne Erklärung, mit der fadenscheinigen Begründung "Da dieses Tool hauptsächlich professionell benutzt wurde, ist es nun nicht mehr frei verfügbar", kommerziell zu machen, finde ich sehr bedenklich.
Kombiniert mit der Erkenntnis, dass dieses Projekt nur Code annimmt, wenn die vollständigen und uneingeschränkten Verwertungsrechte an Martin Preuss übertragen werden, finde ich dieses Projekt ab sofort nicht mehr unterstützenswert. Trotz der unbestrittenen Leistung, die Martin Preuss in dieses Programm investiert, finde ich diesen Umgang mit Code-Beiträgen Dritter nicht angemessen für ein freies Projekt.
Mittwoch, 13. Juni 2007
Da muss ich einfach mal ein nicht geworfenes Stöckchen aufgreifen. :)
Lars sagt:
The nice way:
$array = array('0', '1', '2');
array_walk(&$array,
create_function('&$value', '$value = (int)$value;');
);
Nun, da ich PHP-code und "nice" nicht in einem Satz sehen kann, hier mal was schöneres:
Mit Listen-Generator:
array = ['0', '1', '2']
array = [int(x) for x in a]
oder die kürzeste Variante:
array = ['0', '1', '2']
array = map(int, a)
oder wenn's mit ner anonymen Funktion sein soll (und damit äquivalent zum PHP-Beispiel):
array = ['0', '1', '2']
array = map(lambda x : int(x), a)
Allemal schöner anzuschauen. :)
|