Archiv der Kategorie: Raspberry

Was ich so mit dem kleinen Kerl zu Hause anstelle …

7. Vom Ereignis zum Alarm – aus der Logik einer BMA

Kernfunktion ist die Verarbeitung eines ausgelösten Melders – in meiner BMA „Pin 1 wird logisch 1“ – oder ganz platt ich halte einen Draht mit +5V an den IN1 am MCP23017.

Dann werden die Blitzleuchten im Objekt sowie ein Signalhorn oder eine Durchsage aktiviert, das Schlüsseldepot (FSD) wird geöffnet und die Anlage schaltet die Übertragungseinheit (ÜE) zur Feuerwehr oder einem Sicherheitsdienst ein. Parallel dazu müssen die Feuermeldungen auch in den Meldungsspeicher des Feuerwehranzeigetableaus übertragen werden. Danach wartet die Anlage geduldig auf das Eingreifen der Feuerwehr.

Wenn es denn so einfach wäre

Nun gibt es aber in einer Brandmeldeanlage noch ein paar mehr Dinge zu beachten. Neben dem vorübergehenden deaktivieren von Meldegruppen oder einzelnen Meldern (Abschaltungen) gibt es Störungen und die Möglichkeit der Unterbrechung der Akustik, der Brandfallsteuerung und der Überleitung und das jeweils direkt an der BMZ oder am Feuerwehrbedienfeld mit teilweise unterschiedlichen Auswirkungen auf die Verarbeitung eines Ereignisses.

Darüber hinaus sind Funktionen wie Verzögerung der Überleitung für eine Erkundung durch den Betreiber und Spezialfälle wie „mindestens zwei benachbarte Melder müssen auslösen“ in echten Anlagen zu finden. Für die Bedienung der Feuerwehrseite sind diese aber nur bedingt relevant. Fakt ist, wenn die Anlage ausgelöst hat und der Feuerwehrmann vor FBF und FAT steht, muss er herausfinden, welche Melder ausgelöst haben und den betroffenen Bereich erkunden, um festzustellen, ob dort Feuer ist oder nur eine Fehlauslösung vorliegt. Dazu kann er am FBF die Akustik abschalten, die Überleitung unterbrechen und eben am FAT die Meldungen abrufen. Der Rest spielt sich auf der Betreiberseite an der BMZ ab und da sollte der Feuerwehrmann am besten gar nicht tätig werden.

Abschaltung von Meldern und Gruppe

Am einfachsten erschien mir erstmal mit Abschaltung von Meldern und Meldergruppen anzufangen. Über Node-RED erzeuge ich mittels virtuellen Schaltern eine MQTT-Meldung an den Broker, die nun im BMZ-Skript ausgewertet wird. Die abgeschalteten Linien, wie man in Feuerwehrkreisen auch oft noch sagt, und/oder Einzelmelder wandern in eine Variable und parallel wird eine Meldung in den Meldungsspeicher „Abschaltungen“ im FAT abgelegt.

In der Alarm-Funktion wird nun erstmal geprüft, ob der eingehende Melder in der Variablen für die Abschaltung zu finden ist. Falls ja erfolgt nur eine Ausgabe auf der Konsole, aber eben kein Alarm.

Abschaltung der Übertragung und Akustik

Spätestens, wenn die Feuerwehr kommt, wird über das Feuerwehrbedienfeld in die Ansteuerung der Akustik eingegriffen und der Signalweg unterbrochen. Nun muss man an dieser Stelle wissen, dass eine am FBF abgeschaltete Akustik auch nur dort wieder eingeschaltet werden kann. Gleiches gilt übrigens auch für die Übertragungseinheit.

Die notwendigen Steuerbefehle laufen ebenfalls durch den MQTT und werden in Zustandsvariablen lokal gespeichert und bei der Alarmverarbeitung und in der Main-Loop in jedem Prozesstakt geprüft.

„Wieso denn auch in der Main-Loop?“ … nun, wenn die Anlage sich im Zustand Alarm befindet und die Akustik oder die Übertragung wieder aktiviert werden, würde ohne die Prüfung in der Main-Loop beides nicht sofort erneut ausgelöst werden, solange kein neues Meldersignal die Alarmfunktion auslöst. Also müssen wir dafür Sorge tragen, dass im Alarmfall Akustik und/oder Überleitung sofort wieder aktiviert werden und deshalb schauen wir in der Main-Loop.

Voralarm und Erkundung durch Betreiber

Da ich diese Funktion selbst auch nur aus Erzählungen kenne, ist es ein bisschen Stochern im Nebel. In meiner Umsetzung gibt es, wenn die Funktion in der BMZ aktiviert wird (geht nämlich auch ohne), zwei Timer: Voralarm und Erkundung.

Mit Einlauf der ersten Meldung, wird nun der Timer Voralarm gestartet, Blitzleuchte und Akustik aktiviert und der Betreiber kann im Zeitfenster des Timers an der BMZ die Taste Erkundung drücken. Drückt er sie nicht rechtzeitig, wird die Übertragung ausgelöst und die Feuerwehr gerufen.

Schafft er es rechtzeitig den Knopf „Erkundung“ zu drücken, wird der Timer Erkundung aktiviert und er gewinnt eine vordefinierte Zeit bevor die Anlage die Übertragung auslöst und damit die Feuerwehr ruft.

Nach meinem Verständnis ist eine Erkundung unsinnig, wenn mehrere Melder auslösen, denn dann ist schon sehr davon auszugehen, dass ein Brandfall vorliegt. Deshalb bricht meine BMZ den Voralarm und die Erkundung sofort ab, wenn weitere Melder eingehen und ruft die Feuerwehr.

Rückstellung der BMZ

Im richtigen Leben kann der Betreiber an der BMZ nach erfolgter Erkundung die Anlage wieder zurückstellen. Das macht aus Sicht der Betreiber durchaus Sinn, weil dann der Lärm aufhört und die so genannten Brandfallsteuerungen wieder abgeschaltet werden (Blockierung der Aufzüge, Schließen der Brandschutztüren, etc.) und die Arbeit weiter gehen kann. Aus Sicht der Feuerwehr gibt es gute Argumente gegen das Zurückstellen und Abbestellen der Feuerwehr.

Weil das Rückstellen durch Betreiber immer wieder für Probleme sorgte, weil für die Feuerwehr die Auslösung schwierig nachvollziehbar war, leuchtet in neueren Anlagen die Alarm-LED im FBF 15 Minuten nach der Rückstellung, so dass die Feuerwehr weiß, dass die Anlage definitiv ausgelöst hat und im FAT nach der Ursache suchen kann.

Auch an dieser Stelle greift die Rainer-BMA-Logik … wenn während der 15 Minuten die Anlage erneut auslöst, dann wird es wohl einen Grund geben, so dass in diesem Fall auch ohne Voralarm und Erkundung sofort die Überleitung aktiviert wird.

Einen Aspekt berücksichtig meine BMA derzeit noch gar nicht … nämlich die Auslösung und Überwachung des Schlüsseldepots. Es ist aus Gründen der Sicherheit in die Überwachung der BMA eingebunden und bei fehlenden Schlüsseln und offenen Klappen gibt es Probleme bei der Rückstellung der Anlage in den Ruhezustand. Aber auch das wird noch einen Weg in das Projekt finden 😉

5. eine I2C-MQTT-Schnittstelle

Jetzt wird es langsam interessant, denn nun sollen Daten aus dem MQTT zum Ansteuern von LEDs und dem LCD-Display dienen und Taster am Arduino sollen entsprechend im MQTT signalisiert werden. Basierend auf meinen vorherigen Versuchen habe ich also in Python mit smbus und dem „Display-Treiber“ begonnen ein Schnittstellen-Modul zu schreiben. Für die Kommunikation mit dem MQTT-Broker kommt Bibliothek paho-mqtt zum Einsatz.

Anpassung der lcddisplay.py und i2c_lib.py

Da es mich schon zu Beginn störte, dass die Display-Beleuchtung immer eingeschaltet ist, habe ich mir mal den „LCD-Treiber“ (lcddriver.py) genauer angeschaut. Dort werden im Wesentlichen Byte-Konstanten definiert und es folgt eine Umsetzung der Daten in Byte-Folgen und die Adressierung für das Display.

Dieses Skript greift wiederum auf ein weiteres Skript im Paket zu (i2c_lib.py), dass eine Handvoll smbus-Funktionen in einer Klasse wrappt und die Device-Adresse des Displays festlegt. Erst hatte ich überlegt das Skript komplett rauszuwerfen, habe mich dann aber dazu entschlossen diesen Wrapper zu erweitern, um Fehler bei der I2C-Kommunikation abzufangen und Retrys und Timeouts zu realisieren. Mit ein paar weiteren Anpassungen für die Adressierung beliebiger Slaves ist es nun mein I2C-Busmaster geworden.

Im Display-Script habe ich auch noch ein paar Dinge umgebaut, so dass nun neben der Adressierung aufgrund der Änderung im I2C-Wrapper auch die Hintergrundbeleuchtung gesteuert werden kann.

Abfragen der Eingänge, setzen der Ausgänge und Anzeigen auf dem LCD

Nachdem die Verbindung zu den beiden I2C-Slaves (Display und Arduino) steht, wird eine LED angesteuert, wenn das Skript in der Main-Loop angekommen ist und auf dem Display erstmal die Uhrzeit angezeigt. Mit erstaunlich wenigen Befehlen werden zyklisch die Eingänge am Arduino abgefragt und in lokale Variablen geschrieben.

Den Broker kontaktieren

Mit dem Paket paho-mqtt gestaltet sich auch die Kommunikation mit dem MQTT-Broker recht einfach. Ich lasse mein Schnittstellen-Skript eine Nachricht an den Broker senden, wenn es Einsatzbereit ist und mache einen subscribe auf ein paar Topics, die derzeit von der Node-RED-Pseudo-BMZ mit Daten befüllt werden.

Im ersten Schritt lasse ich eine LED als Alarmsignal leuchten und schreibe die vom MQTT kommende Alarmmeldung aufs Display. Im Ruhezustand erzeugt die Node-RED-BMZ eine Ausgabe der aktuellen Uhrzeit.

Im zweiten Schritt sende ich Nachrichten an den Broker, wenn bestimmte Tasten am Arduino gedrückt werden. Die weitere Verarbeitung läuft dann allein im Node-RED.

Test mit MCP23017

Nachdem ich mich bei meiner Kommunikation zwischen Pi und Arduino an der Ansteuerung des MCP23017 orientiert habe, war es nun Zeit den Arduino eben durch den Portexpander zu ersetzen. Im Python musste ich noch den Befehl zur Initialisierung der Ein-Ausgänge hinzufügen, da ich diese im Arduino hardcoded hatten.

Nach Umstecken des I2C, der LEDs und Taster auf den MCP und Neustart des Skriptes funktionierte dieser sofort wie erwartet. Damit war die I2C-Schnittstelle für Display und ein paar erste LEDs und Taster funktional. Eine weitere Ausdehnung auf alle LEDs und Taster am FBF und FAT macht ohne entsprechende Hardware noch keinen Sinn, aber wo ein Portexpander funktioniert, funktionieren auch zwei 😉

Das Interface-Skript (nodebma_interface.py)

Das soeben gebaute Python-Interface zwischen MQTT und I2C kommt nun in eine screen-Session und wird als systemd-Service angelegt.

Da ich ein Freund von Textausgaben auf der Konsole bin, nutze ich gerne screen, um bei Bedarf einfach mal schauen zu können, was mein Skript gerade so macht. Natürlich könnte ich auch ein Logging in eine Datei machen – vielleicht baue ich das noch mal um.

und wie immer noch ein Link dazu

paho-mqtt für Python | Webseite

4. Raspberry, Python und I2C

Mit Python habe ich bereits verschiedene Erfahrungen sammeln können, so dass ich nun „nur noch“ verstehen musste, wie I2C überhaupt funktioniert und wie man das in Python umsetzt. Als Bibliothek kommt smbus und für ein HD44780-LCD-Display noch eine kleine Treiber-Bibliothek aus einem Tutorial zum Einsatz.  

Levelshifter zwischen Pi und Arduino

Bevor wir nun gedankenlos den I2C-Bus des Raspberry und des Arduino verbinden und uns wundern, dass der Pi zwei GPIO-Ports weniger hat, müssen wir einen Pegelwandler für 3,3 und 5 Volt einsetzen, denn der Pi mag keine Spannungen über 3,3V am GPIO und der Arduino arbeitet regulär mit 5V. Der Pegelwandler wird einfach in die Busleitungen SCL und SDA eingefügt und mit Masse und Vin aus beiden Richtungen versorgt. Wenn das erledigt ist, kann man mit dem Kommandozeilentool i2cdetec schauen, ob die Slaves am Bus gefunden werden. Ist dies der Fall, geht es an die Programmierung.

I2C im Python ansprechen

Als erstes ein paar Experimente mit dem Display. Auf dem HD44780 ist, dank des kleinen Treibers, schnell ein erster Text angezeigt. Der Code für die Ansteuerung ist fast selbsterklärend und man hat mit dem darunterliegenden I2C-Bus eigentlich noch keinen richtigen Kontakt. Wenn man es genau betrachtet ist der Treiber auch eher ein Wrapper, der die Strings für das Display in die passenden Bytes und Adressierungen umsetzt und die Kommunikation mit dem I2C-Bus über smbus organisiert.

Pi spricht mit dem Arduino

Aufgabe 1: Vom Pi einen Befehl senden, der auf dem Arduino eine LED ein oder aus schaltet.

Das gelingt Mithilfe einiger Anleitungen aus dem Netz und der Wire-Bibliothek auf dem Arduino recht schnell. Den Arduino als I2C-Slave initialisieren, ihm eine Adresse geben und dann auf die ankommenden Bytes reagieren … 0x00 LED aus, 0x01 LED an … aber Moment … das muss doch auch eleganter gehen, indem ich nicht nur ein Byte als Adresse sondern je Adresse auch noch weitere Bytes als Parameter übertrage und auswerte.

Nach etwas Knoten im Kopf und umdenken (bisher habe ich in Projekten immer über Sockets, APIs und MQTT mit Strings kommuniziert) habe ich dann herausgefunden wie die smbus-Funktionen und die C++Befehle dafür aussehen und die Daten aufbereitet und ausgewertet werden müssen. Nach ein paar frustranen Versuchen ist der Knoten geplatzt und es funktioniert.

Aufgabe 2: Vom Pi einen Eingang am Arduino abfragen.

In meinem Leichtsinn dachte ich, dass ich einfach auf einen Befehl antworten kann, aber bei I2C wird die Übertragung ausschließlich vom Master gesteuert.

Wenn man nochmal genau nachließt und dann auch verstanden hat, dass der Master entweder nur Daten sendet oder einen Request mit eigenen Daten an den Slave sendet und dieser dann direkt antwortet, kommt man auf den richtigen Weg. Also im Arduino den Code umgebaut und siehe da, ich kann nun auch den aktuellen Schaltzustand meiner LED und eines Einganges abfragen.

Aufgabe 3: eine sinnvolle Adressierung auf dem Arduino für IN/OUT

Ich mache es kurz … ich habe einfach die wesentlichen Adressen für die io-Ports aus dem Datenblatt des MCP23017 übernommen. Für das Verständnis des Datenblattes und der Abläufe auf dem I2C-Bus hat mir ein unten verlinktes Tutorial zum MCP sehr geholfen.

Zu meiner Schande musste ich mich nach jahrelanger Erfahrung mit selbst beigebrachten Hobby-Programmierkenntnissen nun endlich mal mit binärer Logik beschäftigen … also wie setze ich 8 Bits zu einem Byte zusammen und wie prüfe ich effektiv und einfach auf der anderen Seite welche Bits 1 bzw. 0 sind. Grundsätzlich war der Zusammenhang klar, aber wie es in Python und C++ praktisch funktioniert war dann eine Abendstudie und ein bisschen Try und Error.

Dabei hat mich die Funktion pow() im C++ fast zur Verzweifelung getrieben, bis ich verstanden habe, dass sie als float-Funktion eben ein „krummes“ Ergebnis liefert, was dann beim Vergleich mit einem Integer zu falschen Ergebnissen führt. Nach weiter Forschung habe ich dann mit bit() die für diesen Zweck richtig Funktion gefunden.

Nun konnte ich also meinen Arduino als dummen I2C-Portexpander missbrauchen und ihn für Ein- und Ausgänge an meiner Brandmeldeanlage nutzen.

„Warum haste nicht gleich nen MCP23017 genommen?“ … das ist schnell erklärt: ich wollte ja verstehen, wie I2C funktioniert und wie solche Bausteine kommunizieren. Das geht natürlich leichter, wenn man auf beiden Seiten des Busses mitlesen kann. Mission erfüllt 😉

Jetzt müssen irgendwie die Taster und LEDs am Arduino mit dem MQTT verbunden werden …

Hier die erwähnten Quellen aus dem Text

Tutorial: HD44780 per I2C ansteuern | Webseite | Python-Bibiothek

Tutorial: Raspberry Pi GPIOs mittels I2C Port Expander erweitern | Webseite

1. Bedienelemente

Bevor ich nun eine eigene Brandmeldeanlage baue, muss ich mir erstmal einen Überblick verschaffen, welche Komponenten für die Feuerwehr interessant sind. Neben dem Herzstück – die Brandmeldezentrale – und den Meldern gibt es ein paar genormte Bedienelemente für die Feuerwehr.

Erster Anlaufpunkt ist für die Feuerwehr das Feuerwehr-Schlüsseldepot (FSD) und ggf. das Freischaltelement (FSE). Gestaltung und Funktion sind in der DIN beschrieben. Gerade die Besonderheiten bei der Handhabung des FSD im Bezug auf die Entnahme und Rücklage von Schlüsseln ist ein übenswerter Prozess. An ein originales FSD zu kommen, ist aber aufgrund des hohen Preises eher schwierig, aber auch nicht unmöglich.

Aus elektrischer Sicht besteht ein FSD aus einem elektrischen Türöffner und Rückmeldekontakten über die die geöffnete Tür und das Fehlen eines Schlüssels erkannt wird.

Das Freischaltelement ist aus elektrischer Sicht lediglich ein Kontakt der überwacht wird. Wird er ausgelöst, so wird die Anlage in den Alarmzustand versetzt, als wenn ein Melder im Objekt auslöst. In der Folge wird das FSD geöffnet und die Feuerwehr bekommt Zugang zum Objekt. Mechanisch betrachtet waren es in älteren Brandmeldeanlagen Schlüsselschalter, in neueren Anlage sind es Rohrzylinder, die gezogen und wieder eingesteckt werden.

Ist man nun mit einem Schlüssel im Objekt geht es zum Feuerwehr-Bedienfeld (FBF). Hier kann bei Eintreffen durch Abschalten der Akustik für etwas Ruhe gesorgt werden und im Verlauf des Einsatzes kann die Übertragung zur Leitstelle unterbrochen werden und natürlich die Anlage wieder in den „Ruhezustand“ gebracht werden. Dem Feuerwehrmann bieten sich neben LED-Anzeigen ein paar Taster, die teilweise einrasten. Alles ist dank der DIN einheitlich angeordnet, beschriftet und funktioniert unabhängig vom Hersteller der BMZ bzw. der Bedienfeldes immer nach gleichem Prinzip.

Daneben ist das Feuerwehr-Anzeigetableau (FAT) die entscheidende Informationsquelle im Falle einer Auslösung. Hier wird die Meldegruppe und der auslösende Melder in einem LCD-Display angezeigt. In neueren Anlagen steht oftmals noch ein Klartext zum Melder zur Verfügung. Das Vorhandensein mehrerer Meldungen wird durch LEDs signalisiert und über Taster können diese abgerufen werden. Auch wird am FAT über Abschaltungen von Meldern und Störungen der Anlage informiert. An diesem, ebenfalls genormten Bedienelement kann der Feuerwehrmann nix falsch machen, da im FAT nur Meldungen aus der Anlage gespeichert und angezeigt werden können – es gibt keinen „Rückkanal“ in die Anlage. Selbst wenn durch einen unglücklichen Fall die BMZ durch den Brand ausfällt, stehen die Meldungen im FAT noch zur Verfügung, solange Betriebsspannung anliegt.

Nun kenne ich die wichtigsten LEDs und Knöpfe auf der Feuerwehrseite … jetzt brauche ich eine Idee für die eigene BMZ.

Informationsquellen

Feuerwehr-Bedienfeld | Wikipedia

Feuerwehr-Anzeigetableau | Wikipedia

Feuerwehr-Schlüsseldepot | Wikipedia

Freischaltelement | Wikipedia

Brandmeldeanlage im Einsatzleiter-Wiki

NotrufSim 2.0 – Änderungen und WebTool

Der letzte Beitrag ist ein paar Tage her und es gab viele kleine Änderungen und einen wesentlichen Schritt nach vorne.

Hardwaretausch

Auf der Hardwareseite habe ich einen kleinen WLAN-AccessPoint zugunsten einer FritzBox aus dem Bastelschrank getauscht. Die Idee dazu hatte ich bei der Überlegung ein DECT-Telefon als zusätzliches Regietelefon anzuknüpfen und bevor nun eine Bastelei mit ATA-Adapter auf eine DECT-Basis das ganze Gebilde wachsen lässt, war die FritzBox die bessere Lösung.

Die FritzBox ersetzt nun den WLAN-AccessPoint, ist DECT-Basis und macht nebenbei noch den DHCP-Server im Netz (hätte ich sonst als Dienst auf dem Raspi gemacht). Darüber hinaus kann man sich über LAN1 an ein bestehendes Netz als Client verbinden und bleibt trotzdem mit der Simulation im gekapselten Netz.

Was ich noch nicht probiert habe, aber durchaus noch eine Option wäre … ein Internet-Fallback über USB-UMTS-Stick an der FritzBox. Das ist sicher nichts um ein ganzes Netz mit Internet zu versorgen, aber es würde der FritzBox und dem zentralen Pi zum Beispiel einen Weg zum NTP-Zeitserver ebnen.

WebTool

Der nächste Schritt sollte das WebTool sein und so ist in den letzten Tagen die Anwendung NSeat entstanden.

Hier kann eine Sitzung für den jeweiligen Platz in der Leitstelle bzw. der Regie gestartet werden und man sieht auf dem Schirm ankommende und abgehende Anrufe und kann nach Gesprächsende auf die aufgezeichneten Anrufe zugreifen.

Dann war die Idee, darüber auch Anrufer zurückrufen zu können, nicht so wirklich Abstrakt – funktioniert in unserer Leitstelle direkt auf der Funk-Notruf-Abfrage ja auch ohne Leitsystem. Hierzu wurde im NSeat eine Wählhilfe integriert, die mittlerweile auch mit platzabhängigem Telefonbuch und Kurzwahltasten versehen ist.

Sind auf einem Platz zwei Leitungen aktiv, kann man diese über das WebTool auch miteinander verbinden. Diese Funktion ist komplett im Asterisk realisiert, so dass man hier unabhängig von den verwendeten Telefonen bleibt.

In der Regie kann NSeat als „MultiSeat“ gestartet werden. Dabei werden alle Plätze gleichzeitig darstellt. In der Wählhilfe kann dann über ein DropDown der abgehende Platz ausgewählt werden.

Wählplan

Eine wesentliche Änderung war die Auslagerung der „zufälligen Rufnummer“ in ein externes Skript. Ich fand es irgendwie schöner und leichter einzubinden als ein komplexes Extensiongebasel mit RAND und IF, um „schöne“ Rufnummern zu erzeugen.

Durch die Option der zusätzlichen Regie-Telefone als DECT, die man in einer Simulation dann durch einen festen Einspieler besetzen kann (für Telefon-CPR, oder sowas), ist die Idee entstanden dem jeweiligen Regie-Telefon eine feste Abgangsrufnummer zuzuordnen. Dies ist jetzt über einen Telefoncode vom Gerät aus steuerbar. Die aktuelle Rufnummer kann durch eine Ansage abgerufen werden.

In einer weiteren Funktion wird der Anrufername aus dem Telefonbuch des WebTools versucht aufzulösen, so dass auf den SIP-Telefonen auch der Name des Anrufers angezeigt wird, wenn man denn ohne das WebTool arbeitet.

Mit den Funktionen im WebTool (Wählhilfe und Verbinden) und der FritzBox als SIP-Client ergaben sich dann bei Testen ein paar kleine Probleme mit dem Wählplan. Die FritzBox routet zum Beispiel keine einstelligen Rufnummern nach extern und bricht die Anwahl intern ab. Der Wählplan wurde daraufhin nochmal etwas umgestellt und ein paar Dinge speziell für die FritzBox hinzugefügt.

Den komplette Wählplan, so wie er jetzt aktuell seinen Dienst verrichtet, habe ich mal hochgeladen extensions.conf.

Ein Video mit den neuen Funktionen gibt es dann auch die Tage noch mal.

NotrufSim 2.0 – Konfiguration der Telefone

Weiter geht’s mit dem Projekt NotrufSim 2.0 – Nachdem nun die Telefone und der PoE-Switch geliefert wurden, und der Asterisk-Server soweit läuft, ging es an die Einrichtung der Hardware. Die OpenStage 40 SIP kamen mit einer relativ aktuellen Firmware und waren bereits auf Werkseinstellungen. Die Grundeinrichtung geht wahlweise direkt am Telefon oder über den Browser.

Vorbereitungen

Als erstes habe ich dem Raspberry zusätzlich zur DHCP-Adresse eine feste IP verpasst, denn das System soll ja primär autark ohne fremdes Netzwerk und Internet auskommen. Alle weiteren Komponenten wie Switch, WLAN-AP und Telefone bekommen daher ebenfalls feste Adressen. Im Raspberry ist optional ein DHCP-Server vorkonfiguriert um später Tablet oder Laptop für die erweiterte Bedienung anzuknüpfen. DHCP soll dann über ein Webinterface aktivierbar sein.

Der Raspi hat in diesem Zuge auch noch einen NTP-Server (Zeitserver) bekommen, um andere Geräte im Netzwerk auf die gleiche Zeit zu bringen. Haken hierbei ist, dass der Raspi selbst keine aktuelle Zeit hat, weil er keine Realtime-Clock und die Uhr quasi am letzten Shutdown weiter läuft. Später gibt es dann im Webinterface eine Funktion zum Setzen der Systemzeit über den Browser.

Grundkonfiguration

Nach dem Verbinden mit dem PoE-Switch dauert es eine ganze Weile, bis das Telefon hochgefahren ist. Dann bietet es eine Auto-Konfiguration an, die man ablehnen muss. Über das Einstellungsmenü auf dem noch Englisch sprechenden Telefon kann man das Netzwerk auf IPv4 ohne DHCP einrichten und eine manuelle IP aus dem Netz des Raspi eingeben. Jetzt ist es unter eben dieser IP per Netzwerk erreichbar.

Wenn man, wie ich, keine Anleitungen ließt, dann bekommt man mit etwas rumprobieren irgendwann raus, was man in der Administration über den Webbrowser eintragen muss.

Als erstes wird die Netzwerk-Konfiguration vervollständig, also DNS und Default-Route auf den Raspi gebogen und die DNS-Domain noch auf local geändert, da wir ja keine echte Domäne haben.

Dann erfolgt die Einstellung der Identität – hier habe ich nen bisschen gebraucht, bis ich verstanden habe, was man eintragen muss, und wozu es dann dient. Der „Terminal name“ wird quasi der Hostname des Telefons. Die „Display Identity“ steht später im Telefondisplay und wurde mit der Platzbezeichnung und der internen Rufnummer gefüttert. Wichtig ist der kleine Haken bei „DisplayID“, sonst steht nämlich nur der Realm vom SIP-Account im Display.

Unter „Date and Time“ kann man noch die IP des Raspi als SNTP eintragen, damit sich das Telefon am Raspi eine Uhrzeit holen kann.

Danach wird unter „Security and Policies“ noch ein Password für die Weboberfläche des Users eingerichtet.  Danach besucht man genau diese und stellt unter „Locality“ auf Deutsch um.

[Screenshot einfügen]

Basis-SIP-Einstellungen für alle Telefone

Nun geht es an den Haupt-SIP-Account. Hier werden Server, Registrar und Gateway auf die IP des Raspi gesetzt. Der „Server Type“ muss auf „other“ gesetzt werden. Bei „Realm“ und „UserID“ kommt dann der „username“ für den entsprechenden Platz aus der sip.conf vom Asterisk rein und falls verwendet natürlich auch das Passwort. Nach dem Speichern meldet sich das Telefon direkt am Asterisk an und ist dann telefonierbereit.

erweitere Konfig für Leitplätze

Jetzt brauchen wir in den Leitstellen-Telefonen unsere verschiedenen Leitungen. Diese sollen auf den Softkeys seitlich am Display angezeigt werden. Das ganze findet man unter „System > Features > Programm Keys“ und dort kann man dann „Line“ auswählen und der Taste einen Namen geben und dann wieder Zugangsdaten aus der sip.conf für die entsprechende Platzleitung (z.B. notruf1, ktp1, etc) eingeben.

[Screenshot einfügen]

Jedes Mal, wenn man speichert, wird die neue Leitung sofort am Asterisk angemeldet und steht kurz danach zur Verfügung. Bei ankommenden Rufen leuchtet jetzt auch die entsprechende Taste und das ganze erfüllt schon mal meine Vorstellung.

Auf die Tasten kann man auch zahlreiche Funktionen und Kurzwahlen legen. Ich habe die untere Taste mit der Shift-Funktion belegt und auf der zweiten Ebene dann abgehende Anrufe auf die Tasten gelegt:

  • Leitung AMT & abgehend externer Anruf
  • Leitung 112 & abgehend an Polizei (110)
  • Leitung 19222 & abgehend an andere Leitstelle (19222)
  • Leitung 116117 & abgehend an Arzt (116117)

Unter „Fixed Keys“ habe ich noch die Taste für Rufumleitung auf „Consultation“ (Rückfrage) umgestellt, denn eine Rufumleitung wünschen wir uns zwar in der Leitstelle manchmal, aber die Rückfrage/Verbinden macht mehr Sinn.

erweiterte Konfiguration für Regie

In der Regie haben wir keine verschiedenen Leitungen, da brauchen wir nur ein paar Zielwahlen in die Leitstelle. Die Tasten unterste Taste ist wieder mit der Shift-Funktion belegt, die anderen in beiden Ebenen mit Zielwahlen in die Leitstelle:

  • zufällige Nummer an 112 & Festnetznummer an 112
  • anonym an AMT & Festnetznummer an AMT
  • anonym an 19222 & Festnetznummer an 19222
  • anonym an 116117 & Festnetznummer an 116117
  • Anruf als Polizei an AMT & Handynummer an 112

Auch hier wird die Taste für Rufumleitung auf „Consultation“ umgestellt, auch wenn die Regie eigentlich nicht verbinden muss – aber sie kann 😉

Hallo, ist da die Feuerwehr ?

Nachdem nun die Telefone konfiguriert sind, geht es an den Feldversuch. Die Anrufe in der Leitstelle funktionieren wie gewünscht und auch das Anrufen aus der Leitstelle funktioniert wie geplant. Der Versuch eines abgehenden Anrufes über die 112 wird wie gewünscht abgewiesen und mit der „Fehleransage“ belohnt.

Jetzt mal ein Notruf, der an die Polizei verbunden werden muss – Anruf annehmen > Rückfrage > Shift + Polizei und „Fehleransage“ – huch, was nun?

Das Telefon wählt beim Vermitteln automatisch über die Leitung raus, auf der der Anruf auch angekommen ist. Somit lande ich zurecht in der „Fehleransage“, wenn ich ein 112-Gespräch verbinden will. Ich habe bis jetzt noch nicht rausgefunden ob oder wie man das ändern kann, so dass nun die Konsequenz ist, dass ich den Wählplan im Asterisk so geändert habe, dass die Leitstelle doch mit allen Leitungen raustelefonieren kann, da sonst das Verbinden nicht klappt und das ist nun mal eine essentielle Leitstellen-Funktion.

rudimentäres WebTool mit Zugriff auf die Aufzeichnungen

Beim WebTool habe ich Quick’n’Dirty ein kleines PHP programmiert, was die Gesprächsdaten aus der Datenbank anzeigt. Dabei wird unterschieden zwischen „Anruf“, „Aktiv“ und „Beendet“ und mittels „Reload“ kann man dann manuell aktualisieren.

Bei den beendeten Gesprächen gibt es gleich einen Link zur Aufzeichnung, die mittels HMTL5-Audioplayer abgespielt wird.

Hier geht es dann als nächsten dran, um das ganze mit Javascript und CSS ansehnlich zu automatisieren.

NotrufSim 2.0 – Das Projekt

Bereits 2015 begann ich eine Artikelreihe mit dem Ziel einen „Wunderkasten“ als kleine Telefonanlage zur Simulation von Notrufen auf Basis Raspberry und Asterisk zu bauen und nachdem die Grundfunktion damals gegeben war, verschwand das Projekt wieder in der Versenkung und wurde nie fertig gestellt.

Nachdem wir im beruflichen Umfeld immer mehr mit Simulation arbeiten und diese aufgrund technischer Änderungen in unserem Schulungszentrum nicht mehr mit dort vorhandenen „Bordmitteln“ aufbauen können, braucht es nun doch wieder einen „Wunderkasten“.

Welche Funktionen sollte das System haben
  • bis zu 3 Leitstellenplätze
  • bis zu 2 Regieplätze
  • verschiedene Leitungen (Amt, 112, 19222, 116117)
  • aus der Regie müssen gezielt Anrufe an die verschiedenen Leitungen in der Leitstelle getätigt werden können und in der Leitstelle muss eine Unterscheidung der angerufenen Leitung  möglich sein
  • die Regie soll verschiedene abgehende Rufnummern simulieren können (Spoofing)
  • die Leitstelle muss beliebige Rufnummern anrufen können und in der Regie muss ersichtlich sein, welche Rufnummer die Leitstelle angerufen hat
  • Die Funktionen der TK-Anlage sollen in der Leitstelle möglichst ohne jegliche Einweisung nutzbar sein
  • Die Anrufe sollen wie in der echten Leitstelle aufgezeichnet werden. Sie sollen an den Plätzen auch als „Kurzzeitdoku“ zur Verfügung stehen
  • Die aufgenommenen Anrufe sollen am Ende der Simulation aus der Regie einfach gelöscht werden können
  • Für eine spätere Anbindung einer Mini-Leitstellen-Software sollen Daten der TK-Anlage über eine Datenbank/Schnittstelle nutzbar sein
Umsetzung

Wie bereits in der 2015er-Version ist der Kern ein Raspberry (Pi3b+ mit Raspbian Buster Lite) und ein Asterisk (16.2.1 mit de-Sounds). Auf die Installation von Raspbian und Asterisk werde ich nicht weiter eingehen.

Als Hardware-Telefone werden OpenStage 40 SIP zum Einsatz kommen, da diese bei Pollin gerade mal wieder für knapp 10 Euro zu haben sind. Dazu gibt’s einen gebrauchten PoE-Switch von HPenterprise aus der Bucht.

Anrufe aus der Regie

In der Regie wird für jedes Telefon nur ein SIP-Account im Asterisk eingerichtet. Für die Anrufsimulation gibt es einen umfangreichen Kontext, in dem die Ziel-Leitungen der Leitstelle gezielt ansprechbar sind und abgehenden Rufnummern per Nachwahl gesetzt werden können.

  • Bei Wahl einer beliebigen Nummer, wird diese Rufnummer als Anrufernummer auf der Amtsleitung der Leitstelle signalisiert. Wird lediglich eine 0 gewählt, erfolgt ein anonymer Anruf.
  • Ein Anruf auf der 112 wird mit einer zufälligen Nummer auf der Notrufleitung in der Leitstelle signalisiert. Wird an die 112 eine Rufnummer angehängt, wird diese als Anrufernummer gesetzt.
  • Die Sondernummern 19222 oder 116117 werden ohne weitere Nachwahl als anonymer Anruf auf der jeweiligen Leitung in der Leitstelle signalisiert. Mit angehängter Rufnummer wird wie bei 112 die Anrufernummer gesetzt.
  • mit einer 1 als Nachwahl hinter der 112 oder den Sondernummern wird eine zufällige Handynummer als Absender erzeugt. Eine 5 erzeugt eine Festnetznummer aus der Bereich 0555x.
Anrufe aus der Leitstelle

In der Leitstelle erhält jedes Telefon vier SIP-Accounts (Amt, 112, 19222, 116117) um eine Unterscheidung der angerufenen Leitung am Endgerät zu ermöglichen. Abgehende Anrufe sind nur über die Leitung „Amt“ möglich. Versucht man über die anderen Leitungen abgehend zu telefonieren kommt eine entsprechende Fehleransage.

Grundsätzlich sind alle Rufnummern von der Leitstelle aus an- bzw. rückrufbar. Eine Ausnahme bilden die anonymen Anrufe, die ebenfalls mit einer Fehleransage beendet werden.

Aufzeichnung der Anrufe

Alle Anrufe, die über die Anrufsimulation in die Leitstelle gehen oder von dort geführt werden, werden als WAV-Datei in einem Ordner abgespeichert. Sie stehen damit in einem späteren WebTool als Kurzzeitdokumentation an den Leitplätzen zur Verfügung.

Die Regie kann die Anrufe ebenfalls nochmals anhören und später im Debriefing der Simulation verwenden. Wenn der Simulationsdurchgang abgeschlossen ist, können die Aufzeichnungen per Telefoncode direkt gelöscht werden.

Anrufe, die gezielt an eine Nebenstelle in der Leitstelle oder der Regie geführt werden, sind von der Aufzeichnung ausgenommen.

Bereitstellen von Anrufdaten

Für alle Anrufe wird bei Beginn ein Datensatz in einer Datenbank angelegt. Hier werden bereits die Anrufernummer, das Anrufziel, der „Platz“ von dem er gestartet wurde sowie der Name der WAV-Datei gespeichert. Wenn eine Annahme des Anrufes erfolgt, wird der „Platz“ der Annahme gespeichert. Beim Beenden des Gespräches erfolgt ein weiterer Zeitstempel im Datensatz.

Damit sind dann später in einem WebTool alle anstehenden, alle aktiven sowie die beendeten Gespräche nachvollziehbar und alle notwendigen Daten für die Kurzzeit-Doku vorhanden.

In einem weiteren Schritt soll an diese Datenbank ein Mini-ELR als WebApp anknüpfen, um Einsätze zu verwalten und diese mit Anrufern zu verknüpfen – aber das ist noch Zukunftsmusik.

Was als nächstes kommt

Ich warte auf die Telefon-Hardware, denn bisher erfolgten nur kleine Tests per Softphone. Eine „Auslastung“ der Leitstelle konnte damit noch nicht getestet werden.

Das erste WebTool für das Anrufmanagement steht relativ weit oben auf der Liste. Auf der Leitstellenseite wird es primär als Anzeige dienen, die Kurzzeitdoku realisieren und vielleicht irgendwann Rückruffunktion bieten. Auf der Regieseite soll das Tool vorbereitete Rufnummer wählen können, so dass in Szenarien möglichst realistisch erneute Anrufe, Anrufe aus dem selben Ort, etc. per Klick erzeugt werden können.

… und dann schauen wir mal 😉

weiter zu: Teil 2 – Konfiguration der Telefone

Raspberry Pi 4 4GB als Desktop-Ersatz

Kurzer Ausflug in die Vorgeschichte … nachdem ich bereits mit dem 3b einen Dual-Screen-Desktop aufgesetzt hatte, diesen dann aber aufgrund der geringen Leistung nicht alltagstauglich fand, konnte ich einen Samsung Thinclient TX-WN für nicht mal 50 Euro aus der Bucht erobern. Dieser kommt mit allen gängigen Anschlüssen (2x DVI, USB3, Gigabit-LAN) daher und hat 2GB RAM und eine 16GB SSD mit Win7 embedded. Letzteres  fand ein schnelles Ende und wurde durch Lubuntu 18.04 LTS ersetzt. Das Setup lief besser als der Pi 3b, braucht allerdings mehr Platz auf dem Schreibtisch, setzt mehr Energie (12W laut Herstellerangabe, davon gefühlt 100% als Wärme) um und zeigte im Chromium bei Facebook und Youtube seine Schwächen.

Raspberry Pi 4b 4GByte

Mit Freude erwartete ich nun den Pi4, dessen neue Hardware etwas mehr Performance versprach:

  • 1,5 GHz -Quadcore
  • 4 GByte DDR4-RAM (gibt auch 1 oder 2 GByte-Versionen)
  • 2x USB 3.0, 2x USB 2.0
  • Gigabit Ethernet
  • 2x Micro-HDMI für Dualscreen-Betrieb in 4K
  • WLAN 2,5 & 5 GHz
  • Bluetooth 5.0

Ich habe eine Weile gewartet und wollte erstmal die Kinderkrankheiten abwarten, denn es gibt unter anderem einen Bug im Bereich der neuen USB-C Spannungsversorgung – da ich aber eh ein eigenes Netzteil verwenden will, stört es mich nicht und ich wollte einfach nicht länger warten.

Eine Funktion der 3er-Serien hat leider aufgrund neuer Bootloader-Strategie auf EEPROM noch keinen Einzug bei Pi4 gefunden: der Systemstart via USB oder Netzwerk (PXE). Schade, denn ich wollte den neuen Bewohner gerne komplett von einem USB-SSD-Speicher betreiben – so muss die SD leider weiterhin die boot-Partition liefern und dann an den SSD-Stick übergeben.

Einkaufsliste

Nun aber mal zu den Fakten, in diesem Fall die Einkaufsliste:

  • Raspberry Pi 4b 4 GByte
  • SanDisk Ultra 16GB SDHC
  • SanDisk Extreme PRO 128GB SSD-Stick
  • GeeekPi Gehäuse mit Kühlkörpersatz (4 Stück) und 40mm-Lüfter
  • Beris 5V / 3A Netzteil mit Schalter und USB-C
  • 2 x Micro-HDMI auf HDMI-Buchse

Gesamtkosten 150 Euro – vielleicht kein Schnäppchen, aber ein Quadcore PC mit 4 GB RAM und 128 GB SSD, der weniger Platz auf dem Schreibtisch braucht als mein Locher – verlockend !

Die erste(n) Installation(en)

Vorweg – ich bin kein Freund von Geräuschen am Schreibtisch, deswegen habe ich den 40mm-Lüfter beim Zusammenbau des Gehäuses erstmal nicht angeschlossen. Die passiven Kühlkörper(-chen) wurden brav montiert (verstehe auch nicht, wie man nen Pi ohne betreiben kann).

Als erstes habe ich ein Raspbian Lite auf die SD und den SSD-Stick kopiert. Dabei habe ich mich an der Anleitung von James Chambers orientiert und die SD als boot-Device und den Stick als root-Device verknüpft. Ein erster Start machte mich fast sprachlos, denn der Pi bootete in gerade mal 20 Sekunden bis zum Login.

Ich versuchte dann das Lite zum LXDE aufzuwerten und stellte aber fest, dass es irgendwie nicht so harmonierte, wie ich es mir vorgestellt habe. Scheinbar werden doch irgendwie nicht alle Pakete so installiert, als wenn ich Raspbian Full nehme. Es gelang mir zum Beispiel nicht Anydesk zum laufen zu bringen.

Zeit noch mal was anderes zu probieren: ich nahm ein Lubuntu-Arm64 und hoffte auf mein gewünschtes und gewohntes LXDE-Linux. Das startete im grafischen Desktop ebenfalls deutlich unter 30 Sekunden, aber es gelang mir auch in diesem Setup nicht Anydesk zu installieren, weil dies offensichtlich nicht mit Arm64 kompatibel ist.

das endgültige Setup mit Rasbian Full und LXDE

Na ist ja nicht schlimm, im dritten Anlauf kommt halt Raspbian Full auf Karte und Stick. Die notwendigen Schritte nun schon fast auswendig beherrschend ist das ganze in gut 5 Minuten bootbar und der Raspbian Desktop wird nach gerade mal 23 Sekunden angezeigt.

LXDE, Chromium und Anydesk installiert um einen ersten Vergleich zum Samsung-Thinclient herstellen zu können. Alles startet sehr schnell, die Webseiten scrollen flüssig (insbesondere Facebook, dass auf dem Samsung oft für Probleme sorgte) und auch Youtube läuft ruckelfrei. Nun folgte ein bisschen Feintuning, Aussehen anpassen, gewohnte Software installieren, Netzwerk-Links und Desktop-Starter installieren – immer wieder beeindruckt, wie schnell der Raspi Zugriffe im Dateisystem erledigt und neu startet – auch mit mehr Software im Gepäck.

Kühlen wird Pflicht

Nun kam die Stunde der Wahrheit: er soll endlich mal im Dual-Screen-Betrieb zeigen, was er kann und ich mache es kurz – er tut, was er soll. Im Betrieb ohne Lüfter mit ein bisschen Internetnutzung kommt die CPU auf 72 °C. Bei intensiver Nutzung mit mehreren Fenstern und vielen Zugriffen im Dateisystem erreichte er dann irgendwann die 80 °C-Grenze und zeigte das Symbol für Temperaturwarnung oben rechts im Bild an. Für mich war der Zeitpunkt gekommen ihn nun aktiv zu kühlen – mit Lüfter ging er dann auf rund 50 °C runter. Für mich stehen damit 2 Dinge fest: es braucht einen leisen 40mm-Lüfter und eine kleine GPIO-Steuerung, die den Lüfter ansteuert, wenn die Temperatur hoch geht.

Fazit

Nach einem Tag Raspberry 4b 4GB als Desktop-Ersatz kann ich sagen, dass ich den Kauf nicht bereut habe. Er läuft und erledigt die Alltagsaufgaben mit sehr guter Performance im Vergleich zum Samsung TX-WN und dem davor genutzten Pi 3b+. Insbesondere das echte Gigabit-LAN und der SSD-Stick bringen in vielen Dingen den nötigen Durchsatz und Dual-Screen ist nun ohne Bastelarbeiten (Gert-Board) und Kernel-Patch out-of-the-box möglich.

 https://jamesachambers.com/raspberry-pi-4-usb-boot-config-guide-for-ssd-flash-drives/

Projekt „Wachdisplay“ für das Feuerwehrhaus

Alarmdisplay Immer wieder gibt es den Wunsch, insbesondere bei den kleinen Feuerwehren, für die nach wie vor die Sirene der Hauptalarm darstellt, eine Anzeige der Alarmierung im Feuerwehrhaus zu haben, wohin es geht und welcher Auftrag dahinter steckt.

Quelle der Inspiration

Inspiriert durch eine Anzeige auf Basis eines Oelmann-Alarmempfängers in einem Feuerwehrhaus ging es an die ersten Überlegungen. Dazu erstmal ein Blick, wie das Oelmann-System grob funktioniert:

  • Empfang der Alarmierung über einen Steuerempfänger
  • Ausgabe der Meldung über eine serielle Schnittstelle
  • Umwandlung der Meldung über einen Seriell-VGA-Konverter
  • Darstellung auf einem Monitor

Soweit recht einfach und damit auch nahezu ausfallsicher konzipiert. Die Schwächen des Systems sollen aber nicht unerwähnt bleiben: es wird jede Meldung angezeigt, die im Steuerempfänger als Adresse hinterlegt ist, lange Meldungen werden umgebrochen, aber nicht durchgescrollt, so dass Meldungsteile fehlen  und die Meldungen bleiben dort bis zum Eingang einer neuen Meldung stehen.

Zielsetzung

Es sollte ein System werden, dass die Schwächen ausgleicht und im Sinne einer Vernetzung an mehreren Standorten genutzt werden kann, ohne dort einen eigenen Steuerempfänger zu installieren.

Die Auswertung der Alarmierung musste also irgendwo zentral erfolgen und eine differenzierte Ansteuerung mehrerer Monitore ermöglichen.

Meldungen sollten nach einer Ablaufzeit von der Anzeige verschwinden, da nicht selten sensible Daten in der Alarmmeldung enthalten sind und manchmal auch Nicht-Feuerwehrangehörige in den Gerätehäusern zu Gast sind.

Erste Umsetzung im Sommer 2018

Die Grundversion brauchte von der Idee zur Umsetzung rund ein Vierteljahr. Im Kern gibt es einen „Displayserver“ der über eine API die Meldungen für den jeweiligen Monitor entgegen nimmt und in einer Datenbank speichert. Über die selbe API melden sich die Monitore als „Client“ an und prüfen ob eine Meldung vorhanden ist.

Die Ansteuerung übernimmt dabei ein bereits seit 2015 in der Stadtfeuerwehr eingesetztes System, mit dem SMS- und Mail- und Push-Nachrichten auf Basis der im Landkreis eingesetzten POCSAG-Alarmierung erzeugt werden. So können zu jeder Alarmierung differenziert die Monitore angesteuert werden.

Auf der Clientseite läuft das ganze als HTML/Javascript-Kombination, die so mit verschiedenen Systemen und Browsern betrieben werden kann.

Zusammen mit einem Freund wurde noch eine Wetter/Unwetter-Leiste integriert. Im Ruhezustand zeigt sie Wetterdaten, bei ausgewählten Warnereignissen im Stadtgebiet verfärbt sich die Leiste entsprechend des DWD-Farbschemas und zeigt die Headline der Meldung an, so dass Kameraden wissen, was sie draußen noch erwarten könnte.

Die erste Testphase

Neben meinem Client auf einem Raspi 3b gab es noch einen auf einem Android-Tablet, einem Windows PC und einen weiteren Linux-PC – alle mit verschiedenen Broswern und Systemen.

Als Hardware im Feuerwehrhaus kam im ersten Test ein Raspberry Pi Zero W zum Einsatz, der aber durch die grafische Oberfläche mit Browser manchmal ins straucheln kam. Da stand schnell die Entscheidung weitere Clients nur noch als 3b auszurüsten.

Es wurden einige Fehler gefunden, neue Ideen gesammelt und so manche Stunde damit verbracht das System weiter zu optimieren.

Geocoding in 2019

Als wesentliche Neuerung gab es dann im Frühjahr 2019 das Geocoding-Routing. Der Displayserver versucht aus den Einsatztexten den Einsatzort rauszulesen und mit Hilfe der Google-Geocoding-API in eine Koordinate umzusetzen. Als Freund von freier Software habe ich zuvor die OSM-Variante getestet, musste aber feststellen, dass die Anzahl der falschen Georeferenzen sehr hoch war. Selbst mit der Google-API gibt es zuweilen Einsatzstellen in mehreren 100km Entfernung.

Die gewonnene Koordinate wird nun genutzt um eine kleine Karte mit Anfahrtsweg inkl. geschätzter Fahrzeit und Strecke anzuzeigen. Dazu gibt es eine Luftbildkarte der Einsatzstelle um einen Blick auf die Bebauung zu haben.

Mit diesen Kartenausschnitten und Informationen sollte auch eine Möglichkeit entstehen Einsatzdepeschen auszudrucken, jedoch ist aufgrund verschiedener Schwierigkeiten hier noch keine stabile Version entstanden. *to be continued*

Remote Control in 2019

Ein weiterer Punkt ist die Steuerung eigenen Monitors an der Wand. Der Raspi an sich wird ohne Maus und Tastatur betrieben. Im Alltag „heilt“ er sich durch Cronjobs selbst, wenn mal was abstürzt. Für die Administation gibt es einen Zugang über einen SSH-Tunnel vom Displayserver aus, so dass Updates vorgenommen und kleine Probleme headless behoben werden können.

Zum Nutzen der Client-Funktionen (Letzte Meldung, Reload, Signalton) brauchte es weiterhin mindestens eine Maus oder einen Touchscreen. Alternativ ist noch eine VNC-Verbindung aus dem selben LAN möglich.

Da wir hier über Feuerwehr sprechen, musste noch eine einfache Lösung her. Auf dem Client-PC wurde mittels eines Python-Skripts ein Mini-Webserver eingerichtet, der eine kleine Fernsteuerung anzeigt. Hier sind jetzt die Funktionen für Ausschalten des Displays, Neustart und letzte Meldung sowie eine Testfunktion einfach aus dem Netzwerk erreichbar.

Was noch fehlt und geplant ist

Es fehlt noch die stabile Funktion der Alarmdepesche, die auf dem lokalen bzw. Netzwerk-Drucker im Feuerwehrhaus landen soll. Ein Ansatz ist da, aber es fehlt noch der letzte Kniff.

Ein Relais-Ausgang via USB-Port wird auch von einigen erwartet, sei es um das Licht anzuknipsen oder eine Tür im Feuerwehrhaus zu öffnen. Auch hier gibt es einen Ansatz, aber es fehlt die Implementierung auf der Client-Seite.

Und einen ganz anderen Gedanken, banalen und ökologischen hat auch ein Kamerad zurecht geliefert: Warum muss der Monitor an sein, wenn gar keiner da ist? Hier gibt es auch verschiedene Möglichkeiten:

  • Monitor mit einem Bewegungsmelder ausstatten
  • Power-Management-Funktionen am HDMI-Ausgang nutzen. Dafür Bedarf es aber einer ähnlichen Implementierung wie beim Relais und der Depesche, denn das liegt außerhalb des HTML/Javascript-Universums.

Die Ideen und Wünsche gehen nicht aus – manchmal sind es ganz kleine Dinge, die aber eine komplexe Umsetzung erfordern.

USB2VGA-Adapter am Raspberry Pi

erforderliche Kenntnisse: Umgang mit der Konsole, Bearbeiten von Konfigurationsdateien, einfache Bash-Skripte erstellen, Anwendungen aus Paketquellen installieren. 

Mit dem Raspi lässt sich ja so einiges anstellen – ich nutze einen auf dem Schreibtisch als Desktop-Ersatz, denn mit dem geringen Stromverbrauch ist er zum Mails abholen und surfen im Web durchaus eine Alternative. Daneben läuft er als quasi als ThinClient, um eine RDP-Session einer VM auf dem Homeserver auf den Schreibtisch zu holen.

Aus meinem Nutzungsverhalten entstand auch der Wunsch einen zweiten Bildschirm am Raspi zu betreiben, um dort parallel eine Webseite (z.B. WhatsApp) offen und vor allem im Blick zu haben.

Ich hatte vor einiger Zeit schon mal im Netz gesucht und viele erfolglose Geschichten gelesen. Ein Arbeitskollege kaufte sich kürzlich USB2VGA-Adapter von DisplayLink und brachte diese unter Windows 10 zum laufen. Dank Google fand ich heraus, dass RaspbianJessie mittlerweile DisplayLink unterstützt, also in die Bucht und Hardware besorgt.

Erster Kontakt mit dem Raspi

Nach dem Auspacken des USB2VGA-Adapters einfach mal an der einen Seite einen weiteren Monitor dran, das andere Ende mit einem USB-B-Kabel an den USB-Hub am Raspi (Anmerkung: funktioniert auch direkt am Raspi, wie ich bei diversen Versuchen herausfand). Eine schnelle Kontrolle mit lsusb und dmesg zeigte, dass der Adapter korrekt erkannt wurde und als /dev/fb1 eingehängt wurde. Auf dem Monitor war ein grünes Bild … sonst nix.

Auch die LXDE-Bildschirmeinstellung brachte mich nicht weiter … hier gab es nur den „Standardmonitor“ und keine weiteren Geräte. Also weiter mit xrandr … das soll ja sowas können.

ein nervenaufreibender Tag mit xrandr

Ich nehme die Pointe mal vorweg – ich habe es nicht hinbekommen, trotz vieler Versuche, stundenlangem googeln und lesen … ich konnte xrandr nicht bewegen den HDMI-Ausgang und den USB2VGA-Adapter zu verwalten.

Es scheitert schon am HDMI-Ausgang, denn xrandr erkennt nur „default“ als Display und setzt es mit einer festen Auflösung an. Die Abfrage xrandr --listproviders bringt als Ergebnis immer 0 und auch das Hinzufügen und Ändern von Bildschirmmodi hat nicht funktioniert.

Um sicher zu gehen, dass es nicht an meinem Image liegt (Raspbian Jessie LITE mit manuell installiertem X-Server, LXDE und Openbox) habe ich auf anderen Raspis im Haus versucht …. xrandr hat mir nirgends mehr ausgespuckt.

Da xrandr nicht korrekt funktioniert, brachte mich also auch das GUI-Tool Arandr nicht weiter, dass auch immer nur das „default“-Display mit der fixen Auflösung anzeigte.

X-Server mittels xorg.conf überzeugen

Nachdem nun das moderne und flexible xrandr seinen Dienst versagte, muss nun eine feste Konfig gebastelt werden …

/etc/X11/xorg.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
Section "Device"
 Identifier "usb"
 Driver "fbturbo"
 Option "fbdev" "/dev/fb1"
 Option "ShadowFB" "off"
EndSection
 
Section "Device"
 Identifier "pihdmi"
 Driver "fbturbo"
 Option "fbdev" "/dev/fb0"
 Option "ShadowFB" "off"
EndSection
 
Section "Monitor"
 Identifier "Terra"
 Modeline "1280x1024_60.00" 109.00 1280 1368 1496 1712 1024 1027 1034 1063 -hsync +vsync
 Option "PreferredMode" "1280x1024_60.00"
 Option "DPMS" "true"
EndSection
 
Section "Screen"
 Identifier "vga"
 Device "usb"
 Monitor "Terra"
 DefaultDepth 16
 SubSection "Display"
  Depth 16
  Modes "1280x1024"
 EndSubSection
EndSection
 
Section "Screen"
 Identifier "hdmi"
 Device "pihdmi"
 Monitor "Terra"
 DefaultDepth 24
 SubSection "Display"
  Depth 24
  Modes "1280x1024"
 EndSubSection
EndSection
 
Section "ServerLayout"
 Identifier "default"
 Screen 0 "hdmi" 0 0
 Screen 1 "vga" RightOf "hdmi"
# Option "Xinerama" "on"
EndSection

Dann ein sudo systemctl restart lightdm und der X-Server brachte mir auf dem zweiten Monitor ebenfalls einen Desktop, nur ohne Panel und mit den Default-Einstellungen zum Desktop-Hintergrund. Ein Verschieben von Fenstern über beide Desktops war natürlich nicht möglich, da es eben kein ausgedehntes Desktop ist, sondern irgendwie ein weiteres Desktop unter dem gleichen Benutzer.

Xinerama mit Pi-HDMI und USB2VGA

Hoch motiviert habe ich dann versucht mittels der Zeile Option "Xinerama" "on" die Desktoperweiterung zu aktivieren. Ihr ahnt es … versucht heißt, dass es nicht funktioniert hat.

Ich habe in der Folge gefühlt 100 Varianten der Konfig getestet, immer mit dem Ergebnis, dass der X-Server abstürzt oder eben nur ein Screen voll nutzbar ist. Irgendwann bin ich dann auch mal auf die Idee gekommen unter /var/log/Xorg.0.log zu forschen, warum … es war erstaunlich einfach:

Der X-Server kann Xinerama nicht starten, wenn die beiden Screens unterschiedliche Farbtiefen (Depth) verwenden und stürzt dann ganz ab. Der Pi läuft standardmäßig mit 24 Bit, der USB2VGA-Adapter kann 16 Bit und 32 Bit, letzteres aber leider nur unter Windows.

Ich mache es auch hier kurz … man hat jetzt eine Möglichkeit mit zwei Optionen das erweiterte Desktop zu bekommen … man freundet sich mit 16-Bit Farbtiefe auf beiden Bildschirmen an

  • Weg 1: den HDMI-Framebuffer des Raspi über die config.txt ebenfalls fest auf 16-Bit runterschrauben
  • Weg 2: zwei USB2VGA-Adapter nehmen und den HDMI-Port des Rapsi ungenutzt lassen

Mit Weg 2 habe ich problemlos mittels xorg.conf einen erweiterten Desktop eingerichtet bekommen. Über die Performance brauchen wir gar nicht reden, wenn das Bild komplett über 2 USB-Adapter an einem Hub erzeugt wird und 16-Bit Farben fand ich das letzte mal unter Win2k schön.

Wer damit leben kann, kann diese Konfig nehmen – alle anderen müssen unter der Konfig mein Workaround lesen 😉

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
Section "Device"
 Identifier "usb1"
 Driver "fbturbo"
 Option "fbdev" "/dev/fb1"
 Option "ShadowFB" "off"
EndSection
 
Section "Device"
 Identifier "usb2"
 Driver "fbturbo"
 Option "fbdev" "/dev/fb2"
 Option "ShadowFB" "off"
EndSection
 
Section "Device"
 Identifier "pihdmi"
 Driver "fbturbo"
 Option "fbdev" "/dev/fb0"
 Option "ShadowFB" "off"
EndSection
 
Section "Monitor"
 Identifier "Terra"
 Modeline "1280x1024_60.00" 109.00 1280 1368 1496 1712 1024 1027 1034 1063 -hsync +vsync
 Option "PreferredMode" "1280x1024_60.00"
 Option "DPMS" "true"
EndSection
 
Section "Screen"
 Identifier "vga1"
 Device "usb1"
 Monitor "Terra"
 DefaultDepth 16
 SubSection "Display"
 Depth 16
 Modes "1280x1024"
 EndSubSection
EndSection
 
Section "Screen"
 Identifier "vga2"
 Device "usb2"
 Monitor "Terra"
 DefaultDepth 16
 SubSection "Display"
  Depth 16
  Modes "1280x1024"
 EndSubSection
EndSection
 
Section "Screen"
 Identifier "hdmi"
 Device "pihdmi"
 Monitor "Terra"
 DefaultDepth 24
 SubSection "Display"
  Depth 24
  Modes "1280x1024"
 EndSubSection
EndSection
 
Section "ServerLayout"
 Identifier "default"
 Screen 0 "vga1" 0 0
 Screen 1 "vga2" RightOf "vga1"
 Option "Xinerama" "on"
EndSection

Mich hat diese Lösung nicht erfüllt. Ich wollte gerne auf dem Hauptscreen weiterhin meine 24-Bit-Farben nutzen. Der zweite Screen, nicht dauerhaft benötigt, darf gerne mit weniger laufen und soll ohnehin nur bei Bedarf ne Webseite anzeigen, oder ein weiteres Terminal beherbergen.

Mein Workaround: den geteilten Desktop bewirtschaften

Basierend auf meiner ersten xorg.conf habe ich nun also den zweiten Desktop angenommen. Dort kann man vom ersten Desktop aus auch Programme starten. Von einem Terminal oder aus einem Skript heraus kann man zum Beispiel mit

DISPLAY=:0.1 lxterminal

auf dem zweiten Screen ein Terminalfenster starten. Das hat aber keine Titelleiste, keine Fensterkontrollelemente und kann auf seinem Screen nicht verschoben werden. Mit etwas Recherche im Netz habe ich die Ursache auch gefunden … der Fenstermanager openbox läuft aktuell nur auf dem ersten Bildschirm. Um das Problem zu lösen habe ich mir mal ein Skript erstellt …

1
2
3
4
#!/bin/bash
#Startet Fenstermanager auf zweitem Screen
DISPLAY=:0.1 openbox &
exec openbox-session

Das startet nun openbox auf dem zweiten Screen und sorgt für eine ordentliche Session. Jetzt haben die Fenster Titelleisten und die gewohnten Steuerelemente und können nach belieben innerhalb des zweiten Screens verschoben werden.

jetzt kann auf dem zweiten Screen über ein Terminal mit obconf das Aussehen angepasst werden, so dass beide Desktopteile „harmonisch“ wirken.

Ein Problem bleibt aber noch … die Fenster aus dem zweiten Screen tauchen aber logischerweise nicht im lxpanel auf dem ersten Screen auf und es gibt kein Menü/keine Programmstarter auf dem zweiten Screen.

Der erste Gedanke … einfach auf dem zweiten Screen auch das lxpanel starten – geht leider nicht, anders als openbox, lässt sich lxpanel nur einmal starten. Also muss ein anderes Panel her, mit dem man die Tasks des zweiten Screens verwalten kann

ein Panel für den zweiten Screen: tint2

Ich habe mich für tint2 entschieden, weil es klein ist, recht einfach an die eigenen Bedürfnisse angepasst werden kann und noch dazu aus den Paketquellen zu bekommen ist.

Nach der Installation kann man es einfach im Terminal des zweiten Screens mittels tint2 starten und hat in der Grundkonfig schon mal ein Panel mit Taskleiste und Uhr.

Das Aussehen und die Funktion des Panels lässt sich in der ~/.config/tint2/default.tint2rc beeinflussen. Man kann diese auch einfach kopieren und in der Kopie nach Herzenslust Farben, Rahmen, Panelaufteilung und vor allem Starter, mit denen man gezielt auf dem zweiten Screen Dinge starten kann, erstellen. Mit dem Tool tint2conf kann man dann eine Konfig auswählen und aktivieren ohne das Panel selbst neu zu starten.

das Finetuning: Skripte und Starter fürs zweite Panel

Ich habe mir für das Starten des zweiten Desktops oben erwähntes Skript angelegt und auf meinem Desktop als Starter platziert, da ich aus Ressourcengründen diesen nicht immer mit laufen lassen möchte.

Für das Starten der verschiedenen Apps auf dem zweiten Screen habe ich mir entsprechende Skripte und Starter erzeugt, die ich dann im zweiten Panel verknüpft habe.

Chromium aufdem zweiten Screen parallel starten

Chromium startet standartmäßig neue Fenster immer im selben Screen. Das kann man aber umgehen, indem man für den zweiten Screen ein eigenes „User-Data-Dir“ für den Browser definiert und dann kann man sogar zwei verschiedene Browser-Konfigurationen parallel laufen lassen.  Mein Skript start_chromium2.sh

1
2
#!/bin/bash
DISPLAY=:0.1 chromium-browser --user-data-dir=/home/pi/.chromium-2

… startet den Browser mit einem anderen Datenverzeichnis und damit auch in einem anderen Kontext. Ich habe einfach dafür ein neues Verzeichnis im Homedir angelegt. Vielleicht ginge es auch mit einem Softlink auf das „normale“ Datenverzeichnis, dann hätten beide Browser den selben Cache, die selben Cookies … aber ich finde es ok quasi zwei verschiedene Browser zu haben, sind eh über den Google-Account synchronisiert.

Für diese Skript habe ich dann einen Starter chromium2.desktop erstellt …

1
2
3
4
5
6
7
[Desktop Entry]
Type=Application
Name[de_DE]=Chromium 2nd
Exec=/home/pi/Skripte/start_chromium2.sh
GenericName=Startet Chromium auf zweitem Screen
Comment[de_DE]=Startet Chromium auf zweitem Screen
Icon=/home/pi/Skripte/chromium.png

… den ich nun im zweiten Panel eingebunden habe. Man kann ihn natürlich auch im lxpanel oder dem Desktop verlinken, wollte ich aber nicht. So erscheint er nämlich nur auf dem zweiten Screen, also auch nur, wenn dieser verfügbar ist.

In meiner default.tint2rc habe ich das so eingebunden …

[...]
launcher_item_app = /home/rainer/Skripte/tint2conf.desktop
launcher_item_app = /home/rainer/Skripte/thunar2.desktop
launcher_item_app = /home/rainer/Skripte/chromium2.desktop
launcher_item_app = /home/rainer/Skripte/lxterm.desktop
[...]

tint2conf.desktop ist ein Starter für das oben erwähnte Konfig-Tool von tint2.

thunar2.desktop bringt mir einen Dateimanager auf den zweiten Screen, denn der LXDE-Standard pcmanfm lässt sich auch mit verschiedenen Tricks nicht auf dem zweiten Screen parallel starten.

lxterm.desktop ist, ihr ahnt es, ein Starter für das Terminal auf dem zweiten Screen.

Die Starter sind alle nach dem Prinzip vom Chromium-Starter aufgebaut … der Starter greift auf ein Skript zurück und im Skript werden die Anwendungen immer mit der DISPLAY-Variable vorweg gestartet. Diese Variante hat den Vorteil, dass alle Starter auch vom Hauptscreen aus funktionieren, solange der zweite Screen verfügbar ist.

Fazit

Das Verschieben von Fenstern vom einen auf den anderen Screen oder ein Screen-übergreifendes Fenster ist mit dieser Variante natürlich nicht möglich. Dazu muss man zwingend Xinerama zum Laufen bringen. Wer, wie ich, auf diese Funktion verzichten kann, kann auf diese Weise aber auch ein nutzbaren Desktop auf einem weiteren Bildschirm erzeugen.

DualScreen mit dem Raspi über HDMI und einem USB2VGA-Adapter für den zweiten Monitor rechts
DualScreen mit dem Raspi über HDMI und einem USB2VGA-Adapter für den zweiten Monitor rechts

Ein alternativer Weg für einen zweiten Desktop, sogar mit eigenem Benutzer ist die MultiSeat-Funktionalität von lightdm. Das habe ich auch ausprobiert, ist sehr interessant, weil man damit an einer Maschine mehrere unabhängige X-Server erzeugen und auf verschiedene Monitore verteilen kann. Trickreich ist dann das Konfigurieren der Eingabegeräte, denn ohne weitere Zutun werden Eingaben und Mausbewegungen parallel an beide X-Server gesendet (witziger Effekt), aber das war dann nicht das, was ich gesucht habe.