Alle Beiträge von rainer

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 😉

6. Node-RED vs. Python

Nun gab es ja diesen provisorischen minimalen Ansatz der Steuerung meiner Brandmeldeanlage in einem Node-RED-Flow, aber bevor ich nun versuche die gesamte Brandmeldezentrale in diesem Puzzle-Java zu bauen, wollte ich wieder zurück in die Python-Welt, denn Node-RED war ja nur als Visualisierung der Zustände und Ersatz für noch fehlende BMA-Hardware gedacht.

Klar ist die Idee charmant alles mit drag’n’drop in einem Browser-GUI zusammenzuklicken und ein bisschen Code in Funktionsblöcken unterzubringen. Ich möchte aber gerne die volle Kontrolle über das Geschehen haben und fühle mich mit Python einfach wohler als mit Java.

das BMZ-Skript (nodebma_bmz.py)

Es wird also Zeit das Herzstück der Brandmeldeanlage in Python zu schreiben. Um die Kommunikation mit dem I2C-Bus brauchen wir uns nicht mehr kümmern, das macht ja nodebma_interface.py bereits als systemd-Service im Hintergrund. Die BMZ muss jetzt „nur noch“ mit dem Broker sprechen und Entschiedungen treffen.

Auch hier wird nun paho-mqtt zur Kommunikation mit dem Broker genutzt. Das Skript hat im wesentlichen eine Callback-Funktion für die eingehenden MQTT-Nachrichten und eine Main-Loop, in der die Versorgung des FAT-Displays mit der aktuellen Uhrzeit sowie ein paar Logik-Prüfungen stattfinden,

Aus dem MQTT-Callback werden in Abhängigkeit vom erkannten Trigger dann Funktionen für die Alarmauslösung, Rücksetzung, Steuerung von Akustik und Übertragung sowie die Bedienung und Versorgung des FAT umgesetzt.

Was die Brandmeldezentrale leisten soll

werde ich im nächsten Teil versuchen zu umreißen 😉

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

3. C++, der ARDUINO und ich

Wie bereits in der Einleitung geschrieben, soll das ganze ein „Schulungsprojekt“ sein – an dieser Stelle kommen die ersten Gehversuche mit einem Arduino Nano, der Arduino IDE und der Programmiersprache C++. Bisher waren meine Kontakte mit der Arduino-Welt auf das Flashen eines fertigen Projektes für unser Amateurfunk-Relais beschränkt. Auch gegen C++ habe ich mich über die Jahre immer gewehrt, da ich bisher immer mit VisualBasic, php, Javascript und Python irgendwie zum Ziel gekommen bin.

Also erstmal grundsätzlich mit der Materie Arduino vertraut machen und ein paar Zeilen Code zum Abfragen eines Einganges und Setzen eines Ausganges in C++ schreiben. Dank dem Internet und viel Ähnlichkeit zu anderen Hochsprachen kein Hexenwerk und dann in der IDE den Sketch hochladen … Fehlermeldung – Board antwortet nicht.

Nach einer Runde Google offenbarte dmesg, dass der USB-zu-Seriell-Chipsatz CH341 meinem Pi 3B nicht schmeckte. Mit Hilfe einer Anleitung aus dem Netz (finde sie leider nicht wieder) konnte ich einen neuen Treiber für den CH341-Chip kompilieren. Dann gleich der nächster Fallstrick: die originalen Nanos haben irgendwann einen neuen Bootloader bekommen und somit ist die IDE auch primär darauf eingestellt. Die China-Nanos haben wohl überwiegend den alten, also in der IDE umstellen und damit gelang dann auch das Flashen einer blinkenden LED nach Tastendruck am Arduino.

Nun aber schnell zurück zum Projekt … der Arduino soll ja Eingänge lesen und Ausgänge ansteuern und muss noch irgendwie mit dem Raspberry, der ja den MQTT bereitstellt und später die BMZ sein soll kommunizieren. Da neben dem Arduino und dem Raspberry auch noch ein Display und weitere GPIO-Ports benötigt werden, habe ich mich für den I2C-Bus entschieden …

weitere Infos

Treiber CH341SER von juliagoda | GitHub

2. Raspberry Pi, Mosquitto und Node-RED

Ohne so richtig zu wissen, wie ich das Herzstück meiner Brandmeldeanlage mal gestalte, geht es im Wesentlichen ja erstmal um diverse Eingänge (Melder, Taster, Schalter) und Ausgänge (LEDs, Display, Relaiskontakte, die sinnvoll miteinander verknüpft werden wollen.

Da ich im Bereich der Lichtsteuerung zu Hause schon mit MQTT arbeite, fand ich es naheliegend auch hier dieses Konzept zur Kommunikation mit Ein- und Ausgängen zu nutzen. Großer Vorteil aus meiner Sicht ist die Option jederzeit extern über den Broker Vorgänge zu triggern bzw. Zustände mitzuverfolgen – gerade während der Entwicklung hilfreich – egal, wie und womit ich später die eigentliche BMZ programmiere. Also erstmal einen Pi Zero mit minimalem Raspbian aufgesetzt und Mosquitto, NodeRED und Python3 installieren – auf die Details gehe ich an dieser Stelle nicht weiter ein.

Mit Node-RED wollte ich eigentlich erstmal nur die diversen Ein- und Ausgänge der Brandmeldeanlage für den MQTT simulieren, aber dann habe ich neben ein paar Flows und Dashboards für FBF, FAT und Melder noch ein paar Grundfunktionen der BMZ in einem Flow zusammengebaut, so dass eine Alarmauslösung, Rückstellung, die Akustik-Abschaltung und die Steuerung der Übertragungseinheit möglich sind. Nach einer Nachtschicht, funktionierte die rudimentäre BMA schon soweit, dass man ein paar grundlegende Dinge probieren kann – weit weg von einer normalen und realitätsnahen Bedienung, aber dennoch beeindrucken, was mit Node-RED so alles machbar ist.

Wie bereits in der Einleitung geschrieben, soll das ganze ja ein Schulungsprojekt sein – nicht nur für die Feuerwehrleute, die den Umgang mit einer BMA üben sollen, sondern auch für mich, denn bei diesem Projekt sehe ich mehr Ein- und Ausgänge als mein Pi Zero GPIO-Pins hat – es braucht also wohl etwas mehr Elektronik und wohl damit verbunden auch eine Auseinandersetzung mit Dingen wie seriellen Bus-Lösungen und Mikroprozessoren.

Links zum Weiterlesen

MQTT | Wikipedia

Node-RED | Webseite

MQTT-Broker Mosquitto | 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

Raspberry Pi 4B – gesteuerter Lüfter

Wie ich in meinem Beitrag zum Pi4 als Desktop bereits ausgeführt habe, wir das aktive Kühlen beim Pi4 quasi zur Pflicht, wenn er nicht nur irgendwo in der Ecke steht und die allermeiste Zeit im „idle“ ist. Im Desktop-Betrieb mit LibreOffice oder Youtube per Webseite geht recht schnell die Temperatur hoch und der Lüfter muss laufen.

Ich hatte den 5V-Lüfter an einen 3,3V-Pin angeschlossen und die Masseleitung des Lüfters mit einer Drahtbrücke vom Steckbrett nach außen verlängert und dann bei Bedarf einfach die Brücke an die Masse am USB-Port gehängt. Das funktionierte prima, bis ich nun den Pi in einer Umräumaktion unter den Schreibtisch verlagert habe.

Hardware

Nun musste also was automatisches her und ich suchte aus der Bastelkiste einen Widerstand (4,7k) und einen Transistor (BC547). Für die Verbindung habe ich in Ermangelung einer Buchsenleiste 3 Steckbrücken geopfert.

Beim Anschluss habe ich wieder den 3.3V-Pin genommen (5V geht natürlich auch, ist aber deutlich lauter beim Lüften). Für die Ansteuerung habe ich GPIO2 (Pin3) genommen. Der liegt nach dem Boot auf HIGH und der Lüfter läuft ohne Steuerskript dauerhaft, was ich erstmal als „failsave“ betrachte.

Der GPIO2 geht nun über den 4,7k-Widerstand an die Basis vom Transistor. Die Masse wird auf den Emitter am Transistor geführt und geht von dort über den Kollektor weiter zum Lüfter. Die Verdrahtung ist mit Steckbrücken gebaut, so dass die Schaltung einfach zwischen den Lüfter und den GPIO gesteckt werden kann. Isoliert ist das ganze mit Schrumpfschlauch.

Software

Ich bin ein Freund von Python und daher kam für mich auch nix anderes in Frage. Das Skript wird einmalig gestartet und überwacht fortan die CPU-Temperatur. Ich habe mich dabei für einen Intervall von 5 Sekunden entschieden, weil ich glaube, dass das ausreichend sein sollte.

Beim Überschreiten der Schwelle von 70°C wird der Lüfter eingeschaltet und es wird „laut“ unter dem Schreibtisch. Beim Absinken der Temperatur unter 50°C wird der Lüfter wieder abgeschaltet und es herrscht wieder Ruhe.

cpu_cool.py
#!/usr/bin/python3

import RPi.GPIO as GPIO
from gpiozero import CPUTemperature
import time

GPIO.setmode(GPIO.BCM)
GPIO.setup(2, GPIO.OUT)

GPIO.output(2, GPIO.LOW)
cooler = 0

while True:
	ctemp = CPUTemperature().value * 100

	if ctemp > 70 and cooler == 0:
		GPIO.output(2, GPIO.HIGH)
		cooler = 1
	elif ctemp < 50 and cooler == 1:
		GPIO.output(2, GPIO.LOW)
		cooler = 0
	else:
		# wir lassen es so
		pass

	print('Temp:',round(ctemp,2),'Cooler:',cooler)
	time.sleep(5)

 

Grundlage

Tutorial im Raspi-Forum
https://forum-raspberrypi.de/forum/thread/774-lueftersteuerung-per-temperatur-einbauanleitung/

 

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.