SNMP: Datenerhebung

Für die Erstellung einer KPI für Überwachungskameras von MOBOTIX mussten Daten beschafft werden.

Interessante Daten für Überwachung sind neben den elementaren Hardwaredaten wie Seriennummer, Hostname, VPN User und Temperatur, die Daten über Anzahl und Zeitpunkt von Alarmen. SNMP, die etablierte Allzweckwaffe, bietet sich an. Vom Schreibtisch aus läßt sich die Konfiguration auch einer im Betrieb befindlichen MOBOTIX Kamera um die nötigen Einträge für den SNMP Dienst einstellen.

curl -q -m 10 -u ‚user:passwort‘ –data-binary @befehl.txt „http://meineKamera/admin/remoteconfig“

Die Befehlszeile übergibt die Befehlssequenz aus der Textdatei befehl.txt an die Kamera:

helo
write params
snmp/SNMPD=1
snmp/V2C_RO_COM=“community“
update section snmp
store
reboot
quit

Mit der Befehlsfolge konfigurieren wir SNMP Version 2c mit dem Read-Only Community Namen „community“. Nach dem Neustart steht der Dienst zu Verfügung. Wie findet man nun die passende OID mit der ich die gefragten Werte auslesen kann? Nun – fragt man den Hersteller, ist man verloren. MOBOTIX verweist an den Händler, als sei die Antwort abhängig vom Umsatz. Auf erneute Nachfrage bekomme ich einen Link, der wenig befriedigend ist. Werte, die abgefragt werden können, belaufen sich je nach Firmwarestand auf cirka 1200 an der Zahl! Welche Werte tatsächlich mit welcher OID abgerufen werden kann, erfährt man mit der Abfrage

snmpwalk -v 2c -c community -m +MOBOTIX-MIB meineKamera .iso

Am Ende .(Punkt) iso. Der Punkt bedeutet, am Rootpunkt der hierarchisch aufgebauten OID Liste zu beginnen. Entgegen der OID Liste aus dem Link der Firma MOBOTIX wird beispielweise der Wert cameraModel nicht mit der OID cameraModel abgerufen. Gezielt lässt sich der Wert ohne Beschreibung, also in leicht weiter verwertbarer Form, mit dem Befehl ermitteln:

snmpget -v 2c -c community -Ovq -m +MOBOTIX-MIB meineKAMERA cameraModel.0

Dabei ist das Einbinden der OID Beschreibung MOBOTIX-MIB wichtig. Andernfalls muss über die ISO OID abgefragt werden. In dem Fall wäre das iso.3.6.1.2.1.1.5.0

In den über 1200 möglichen Abfragen befinden sich trotzdem nicht alle Daten. Daten wie, zum Beispiel, der VPN Benutzername oder die Anzahl der registrierten Alarmmeldungen sind unerreichbar. Mir zeigt das eine gewisse unorganisiertheit der Entwickler. Beim Abruf des letzten Alarmbildes lässt sich per URL Parameter ?output=m1img der Zeitpunkt des letzten Alarms und die Anzahl der Alarmmeldungen in Textform abfragen. Abenteuerlich, nicht wahr?!

curl -q -m 10 -u ‚user:pw‘ „http://IP/control/event.jpg?output=m1img“

Nicht empfehlenswert, da das Verhalten der Kamera je nach Firmwarestand sehr unterschiedlich und damit nicht berechenbar sind. Die Anzahl stelle ich über eine Datenbank fest, die einzelne Werte periodisch speichert und zählt. Fehlt noch der VPN User! Nach meiner Kenntnis muss er aus der Konfiguration ausgelesen werden. Der Befehl für die Konfiguration der Kamera, kann auch zum Auslesen der Selben genutzt werden (siehe erster Absatz). Die Befehlssequenz sieht dann so aus:

helo
view section ethernet vpn imageimprover
exit

Entscheident ist „view section vpn“. Hier werden die Konfigurationsdaten wie User, Passwort usw. ausgegeben. Die section imageprovider nutze ich um die konfigurierten Bildeinblendungen auszulesen. Einfach mal ausprobieren!

fb & Co: Zeitverschwendung

Was macht Sinn in der Eigenvermarktung?

Bringt Facebook irgendwas? Viele Freiberufler versuchen sich selbst und ihre Arbeit werbewirksam darzustellen um so neue Aufträge generieren. Auch der Kontakt zu Kollegen scheint den Aufwand zu rechtfertigen.

Ob das so ist, ob Social-Media für mich speziell funktioniert, kann wirklich erst nach Jahren beurteilt werden.

Für mich persönlich, ist Facebook ohne jeden Wert.

Apache2: BandWidth

Überwachungskameras in größerer Anzahl können das Netzwerk schon in die Knie zwingen.

Wenn 40 – 50 Kameras Livebilder produzieren, wird die Bandbreite des Internetanschlußes gerne mit ca. 250 MBit/s strapaziert. Es ist Unfug, wenn ein User alle Streams gleichzeitig nutzen will – kommt aber vor.

Das ist zu vermeiden. In einem Debian System kann das mod-bw bequem per Aptitude installiert werden.

In der conf des VHOSTs oder innerhalb der Location Konfiguration könnte es so aussehen:

Auch in dieser Konfiguration ist auf die Reihenfolge zu achten –> first match rules! In dem Fall begrenze ich die Bandbreite und die Anzahl der Verbindungen pro Session für das lokale Netztwerk nicht. Alle anderen Verbindungen haben nur eine Bandbreite von 1310762 Byte ( das sind 10 MBit ) auf 5 Verbindungen zur Verfügung. Im obigen iftop sieht man maximale 10 MBit/s für 5 Cams. Zum Vergleich, habe ich intern weitere 5 Cam Streams geöffnet:

30 MBit/s verbraucht die interne Verbindung. Selbe Anzahl an Streams, ist extern wirksam auf 10 MBit/s limitiert.

Weitere Verbindungsversuche enden mit dem Error 503

Was läuft?

Neben der Entwicklung einer SAPUI5 Anwendung sowie einem SAP ABAP Projekt, lese ich mich in ein Langzeitprojekt ein. Programmierung auf IBM Servern in RGP. Eine Business-Anwendung soll um Free-RPG erweitert und Code geändert werden.

Haben sie auch spannende Aufgaben? Ich bin für Sie da!

Datensicherung: sicher und einfach

Nutzer eines HALSYSTEM Servers merken nicht viel davon: Verschlüßelte, verteilte Datensicherung und Versionierung. Im Kern ist das mit Bordmitteln zu realisieren.

Über mögliche Szenarien einer Datensicherung lassen sich Bücher füllen. Bei der Planung eines HALSYSTEM werden Sicherung der Dateien und die des Systems getrennt betrachtet. Letztendlich sieht der Kunde nur eine Übersicht über die Datensicherungen und verfügbaren Versionen veränderter Daten. Egal wie man es auch betrachten mag, ist eine Datensicherung nur dann sicher, wenn sie auch nach einem „undenkbaren Desaster“ die Möglichkeit der Wiederherstellung zulässt.

„Datensicherung: sicher und einfach“ weiterlesen

UI5: Route und Variabeln

Navigation in Views und die Übergabe von Parametern. Drei einfache Wege (von vielen) für verschiedene Szenarien.

Eingrenzende Filterung oder Bindung in Listen und Tabellen sind häufige Szenarien die in UI5 Anwendungen. Wie kann das realisiert werden, besteht die Anwendung aus mehreren Views?

Eine Möglichkeit ist das speichern von Daten im Session Storage – aus Sicherheitsgründen eine nicht gern realisierte Lösung. Im Controller lassen sich Daten mit „sessionStorage.setItem(„Variable“, „Wert“);“ speichern und an anderer Stelle oder anderem Controller mit „var Variable2 = sessionStorage.getItem(„Variable“);“ gelesen werden.

Eine bessere Lösung ist das deklarieren von globalen Variabeln. Im Controller, ausserhalb einer Funktion, simpel „var Variable;“ vereinbaren. Nach Aufruf des Controllers ist die Variable global verfügbar.

Von SAP favorisiert, ist das arbeiten mit Routing und Targets. Werte werden mit dem Aufruf eines Controllers über das Routing „mitgegeben“. So kann im aufgerufenen View Daten nach Selektion durch Binding oder Filter eingeschränkt dargestellt werden.

Im View 1 (Link zum Beispiel) wählen wir einen Kunden aus, nach dessen Kundennummer (description) im View2 die in Relation stehende Daten gefiltert darsgestellt werden.

Im Controller wird Wert aus dem gewählten Listeneintrag gelesen

NavTo lädt entsprechenden Controller. Das geschieht über die im manifest.json vereinbarten Router und Targets:

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
"routes": [
            {
                ...........................
            },
            {
                "name": "kunde",
                "pattern": "kunde",
                "target": [
                    "kunde"
                ]
            },
            {
                "name": "bst",
                "pattern": "bst",
                "target": [
                    "bst"
                ]
            },
            {
                "name": "bst",
                "pattern": "bst/description/{description}",
                "target": [
                    "bst"
                ]
            },              
            {
                "name": "cam",
                "pattern": "cam",
                "target": [
                    "cam"
                ]
            },
            {
                "name": "cam",
                "pattern": "cam/description/{description}",
                "target": [
                    "cam"
                ]
            }               
        ],
        "targets": {
            ..................................
            },
            "kunde": {
                "viewType": "XML",
                "viewName": "kunde"
            },
            "bst": {
                "viewType": "XML",
                "viewName": "bst"
            },
            "cam": {
                "viewType": "XML",
                "viewName": "cam"
            }

Es ist zu erkennen, wie die Variable „description“ über den Router im manifest quasi über die URL weiter gegeben wird. Wird der Controller des Views „bst“ aufgerufen wird, liest die Funktion „onInit“ den übergbenen Wert.

OnInit ruft _onRouteMatched auf, wenn Daten übergeben wurden
mit dem übergebenden Argument, wird ein Filter gesetzt

Wird im zweiten View, durch Klick auf einen Listeneintrag, weiter selektiert, muss die Route und das Target ebenfalls deklariert sein.

Weiter Selektion läuft nach dem selben Muster ab

In dem Beispiel navigieren wir nur durch drei Views. Die Möglichkeiten der Selektion sind natürlich frei verwendbar und zu kombinieren.

UI5: mehrfach JSON Model

In einem UI5 View lassen sich mehrere JSON Model im Controller binden. Dabei ist UI5 grundsätzlich nicht empfindlich, wenn es um die formale Gültigkeit des JSON geht.

Im Controller können beliebige JSON Model gebunden werden.

Die Model sind mit setModel(oModel,“XXXXX“) mit verschiedenen Namen gebunden. Im View lassen sich die Namen direkt ansprechen.

In dem Beispiel stelle ich Wetterdaten in einem einfachen Generic Tile dar. Die Wetterdaten werden von einem PHP Script aufbereitet – mit einfachem print out ist es nicht einmal ein gültiges JSON. UI5 ist in der Hinsicht unempfindlich.

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
<?php
// Wetterdaten aus Postgres
$dbconn = pg_connect("host=localhost dbname=a user=b password=c")
    or die('Verbindungsaufbau fehlgeschlagen: ' . pg_last_error());
$query = 'select roh from orders order by id desc limit 1;';
$result = pg_query($query);
$line = pg_fetch_array($result, null, PGSQL_ASSOC);
$obj = json_decode($line['roh']);
// in Freeboard KPI genutzt
//case ("temp"):
//$such =  round($obj->main->temp - 273.15);
//break;
//case ("wind"):
//$such =  round($obj->wind->speed * 1.61);
//break;
//case ("aufgang"):
$dusk = date("H:i:s",$obj->sys->sunrise);
//break;
//case ("untergang"):
$dawn = date("H:i:s",$obj->sys->sunset);
//break;
// Handling Datum
// Thomas August 2019
$aWeekdayNamesDE = [
    'Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'
    ];
$aMonthNamesDE = [
    'Januar', 'Februar', 'März', 'April', 'Mai', 'Juni',
        'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'
        ];
$dt = new DateTime();
//}
print('{"data":{ "dusk": "'.$dusk.'", "dawn": "'.$dawn.'", "day": "'.$aWeekdayNamesDE[$dt->format('w')].'", "month": "'.$aMonthNamesDE[$dt->format('n')-1].'", "kw": "'.$dt->format('W').'", "dayn": "'.$dt->format('d').'", "year": "'.$dt->format('Y').'"}}');
// Speicher freigeben
pg_free_result($result);
// Verbindung schließen
pg_close($dbconn);
?>

Ergebnis des PHP Scripts hier zum Beispiel: {„data“:{ „dusk“: „06:36:17“, „dawn“: „20:30:34“, „day“: „Mittwoch“, „month“: „August“, „kw“: „35“, „dayn“: „26“, „year“: „2020“}} und { „data“: [[0,19],[1,19],[2,19]]}

es ist viel zu tuen

Spätestens seit Anfang 2020 ist die Digitalisierung in aller Munde. Eigentlich schon seit Jahren; jetzt sind nur alle Übergangsfristen zur Realisierung der DSGVO und GoBD verstrichen und die ersten Bußgelder werden verhängt. Laut wird das Schlagwort „Digitalisierung“ seitens der Regierung propagiert, aber kaum jemand ist darauf vorbereitet.

„es ist viel zu tuen“ weiterlesen

Projekt trotz Corona erfolgreich absolviert

Mai bis Juli 2020 wieder erfolgreich ein RollOut für die absolviert.

Es war eine Herausforderung unter Beachtung der Corona Pandemie bedingten Auflagen in den vielen Ämtern zu arbeiten. Zumal die Empfehlungen von Land zu Land unterschiedlich waren.

Von einer Krise durch den Virus kann in der IT-Branche keine Rede sein. Nahtlos geht es weiter und die nächsten Projekte stehen im Fokus.

Ich bin für Sie, wie immer, erreichbar: 02202 989 12 17

Compiler Optimierung

Für schnelle Lösungen und „mal eben zeigen“ in Workshops und Schulungen verwende ich schnell die unbedachte Kompilierung von Quellcode mit GCC, G++, COBC oder NASM. Das sollte man sich in größeren Projekten abgewöhnen. Compiler Option sind mächtig und bringen viel (Link).

Nehmen wir den berühmten „Hello World“ Code als Beispiel (Link). In C und C++ innerhalb der Funktion „main“ ein simples printf bzw. std::out und in COBOL, in der „Procedure Division“, ein „DISPLAY“. Übersetzen wir alle Sources in Assembler und erzeugen ein ausführbares Programm.

Liste der erzeugten Code

Ohne Optimierung fällt einiges auf. „helloc“ und „test-03.s“ sind die Produkte aus dem C Source Code. Das daraus generierte Assembler ist 8,2k gross. Das Assembler aus dem C++ Code wiegt 18k und 41k bringt das Assembler aus dem COBOL Source auf die Speicher-Waage. Fertig kompiliert sind alle drei ausführbaren Programme 22k bzw. 23k groß.

Schreiben wir „Hello World“ einmal in Assembler

Assembler

und übersetzen, verlinken es mittels „nasm -felf64 helloa.asm && ld -o helloa helloa.o“

Kompilierung des Assemblercode

Wir sehen, da ist wahnsinniges Optmierungspotential. 352 Byte Quellcode und 4,8k für das ausführbare Programm. Ohne genaue Kenntnisse über den Compiler würde man in realen Projekten unter gehen – wir reden da durchaus über Mega- oder Giga-Byte die so verschwendet und zu einem Bottleneck in der Prozessierung werden kann.

Keep on Coding