Bastelstunde: Pseudo-MQTT auf den kleinen 841ern

Problem 1: Ich wuerde immer mal wieder ganz gerne wissen, wieviele Clients auf meinem AP sind, da hier gelegentlich das Wifi wegschmiert und sich nicht mehr alleine faengt (Gluon 1.1.0, haben ja einige hier das Problem).

Problem 2: Der Freifunkrouter haengt hier in einer DMZ zwischen zweimal NAT, kann also direkt ins LAN so ganz einfach keine MQTT-Topics publishen, nach draussen geht.

Da ich im Moment so ziemlich alles was irgendwie (sinnvoll) machbar ist auf MQTT umstelle, fehlt mir ein MQTT-Client/Publisher auf dem Freifunkrouter. Die kleinen 841er haben ja mittlerweile kein opkg mehr drauf, da sowieso kein Platz mehr ist, wie krieg ich da also Mosquitto zum laufen? Und wenn, wie krieg ich die Daten ins LAN?

Mosquitto als Broker laeuft auf einem Raspberry Pi hier im Haus, habe auch noch einen eigenen Broker draussen, Problem Speicherknappheit auf dem 841er bleibt.

Loesung: ich hole mir die Infos per ssh und “publishe” mit mosquitto_pub vom Broker auf sich selbst, diesen kann ich dann direkt per MQTT abfragen (prima APP fuer Android MQTT Dash https://play.google.com/store/apps/details?id=net.routix.mqttdash&hl=de )und wenn noetig kann ich auch noch per Node-Red den ganzen Scheiss in eine Datenbank schreiben (InfluxDB ist mein Freund), Grafana koennte das auswerten, mit Node-Red kann man ja noch jede Menge andere Sachen mit den Daten anstellen.
Hahaha…genau das macht ja Freifunk schon mit Grafana, direkter Zugriff per MQTT tut da aber nicht.

  1. Zertifikatsbasierte Authentifizierung auf dem 841er einrichten.
    2. Ordner /etc/config/ auf dem FF-Router erstellen (in der Hoffnung, dass dieser ein Update ueberlebt, lieg ich da richtig?
    Edith: adorfer schreibt hier, dass unbekannte Dateien in /etc/config wohl beim update erhalten bleiben: https://forum.freifunk.net/t/wie-herausfinden-ob-eine-einstellung-updatefest-ist/3154/7
  2. clients.sh in Ordner /etc/config/ anlegen, zeigt die verbundenen Clients an

batctl tl | grep -cE "\[....W.\]+"

  1. diese mit chmod +x clients.sh ausfuehrbar machen

  2. auf dem Raspberry Pi ein ssh-Skript clientmqtt.sh ablegen, welches sich mit dem FF-Router 192.168.0.15 verbindet, das obige clients.sh ausfuehrt und den Wert, der zum Pi zurueckgegeben wird selbst per mosquitto_pub auf den Broker 10.0.0.252 schickt.

    #!/bin/bash
    anzahl=$(ssh root@192.168.0.15 -t /etc/config/clients.sh)
    #echo $anzahl
    /usr/bin/mosquitto_pub -h 10.0.0.252 -t anzahl -m $anzahl

  3. Dieses Skript per cronjob alle 10 Minuten (oder nach belieben) auf dem Pi starten.
    crontab -e
    */10 * * * * /root/skripte/clientmqtt.sh

Sind die Daten auf dem Broker, kann man mit diesen machen, was man will. Ich moechte auf MQTT nicht mehr verzichten, ein grossartiges Protokoll, Node-Red dazu und alles ist machbar ohne grossen Geschiss.

Anmerkdungen sind willkommen, hat jemand Mosquitto auf seinem Router laufen?
Ich hatte noch mit bish-bosh https://github.com/raphaelcohn/bish-bosh herumprobiert, lief aber mit Busybox nicht richtig.

1 „Gefällt mir“

Gleiches hab ich im “grossen” Forum eben geschrieben, fuehle mich aber eher hier zugehoerig:

Wenn man hier MQTT in die Suche eingibt, dann bekommt man nichtmal eine Handvoll Treffer.
Gibt es einen Grund, wieso dieses Protokoll so stiefmuetterlich behandelt wird? Wird der ganze Datenhaufen, den die FF-Wolke da jeden Tag produziert noch per http “zentralisiert”? Welche Protokolle kommen da fuer die Statistiken zum Einsatz und wieso nicht MQTT?
Edith: “alfred” macht das wohl

Exakt, das aggregieren der Statistiken der Knoten erfolgt per alfred oder respondd.

Das Ganze geht noch viel einfacher, man braucht auf dem Router ueberhaupt nichts aendern bzw. einpflegen ausser zertifikatsbasierte Authentifizierung, keine Skripte mehr in /etc/config/…

Raspberry Pi mit mosquitto als Broker, dazu mosquitto-clients fuer Publish-Subcribe-Orgien und ein cronjob auf dem Pi, der alle paar Minuten durchlaeuft.

Skript auf Pi:

#!/bin/bash
anzahl=$(ssh root@192.168.0.15 -t batctl tl | grep -cE "\[....W.\]+")
#echo $anzahl
/usr/bin/mosquitto_pub -h 10.0.0.252 -t anzahl -m $anzahl

# wird noch getestet, soll WiFi wieder starten wenn 0 Clients
# if [ "$anzahl" == 0  ]
# then
# ssh root@192.168.0.15 -t /sbin/wifi 
# fi

Naja, Alfred liefert ja nicht nur die Client Statistiken und eigentlich willst du auch keinen SSH Key der auf allen Knoten liegt. Sicherheit und so.

Geht nicht um alle Knoten, das ist eine quick&dirty-Loesung fuer die kleinen 841er, davon abgesehen kann ich auch fuer jeden Router ein eigenes Schluesselpaar nutzen, bei den dicken Routern wuerde ich mosquitto-clients dafuer nutzen.

Wie wuerdest Du den Router monitoren? An die Alfreddaten komm ich ja direkt nicht dran oder stellt die mir jemand ausser in Grafana zur Verfuegung?

Naja, das ist bedauerlicherweiser ein sehr großer Teil der Knoten.

Löst das Problem nicht.

Du kannst einfach die Daten aus der Karte parsen: https://map.ffrn.de/data/nodes.json

Ich würde den kleinen durch was richtiges ersetzen. :P Ich weiß, nicht hilfreich.

Hast Du keine zertifikatsbasierte Authentifizierung auf dem Router?

Hahaha…“einfach”, bester Witz heute bisher, ich neige zu Loesungen, die ich auf Anhieb verstehe und ich will an die
Informationen per MQTT ran, weil das aus meiner Sicht der einfachste Weg ist.
Edith: das mit dem Parsen hab ich jetzt verstanden, hat doch seinen Reiz, wie oft wird das aktualisiert?
Ich lass das per cron parsen und publishe auf den Broker.

Die 841er werden uns noch eine Weile erhalten bleiben, nix zu machen.

Ich verstehe um ehrlich zu sein nicht ganz was du vor hast? Bzw. was du meinst.

2 Zeilen Python und du hast die Daten geparst. Ein paar weitere um sie zu bearbeiten. Finde ich einfach. Aber klar, subjektive Sicht.

Einmal pro Minute.

1 „Gefällt mir“

Das bezog sich auf diese Aussage:

SSH-(Public)-Keys auf den Routern sehe ich nicht als Problem an, Du meinst einen pro Router wuerde das Sicherheitsproblem nicht loesen.
Administrierst Du die Router ueber Passwort oder ueber Zertifikat oder Beides?

Ach so, es klang am Anfang so als wolltest du alfred durch MQTT ersetzen. Dafür bräuchte es globalen Zugriff auf die Knoten um die Karte zu bespielen und das wäre sehr uncool.

Um Himmels Willen nein, wenn dann muessten die Clients das selbst pushen. Ich hab kein Interesse daran, Alfred zu ersetzen, es geht mir nur um den besten Weg die Daten da fuer mich rauszuholen und per MQTT zur Verfuegung zu stellen.

Die paar Zeilen Python zum Parsen der JSON-Datei sind nicht schonmal irgendwo geschrieben worden? Sonst muss ich wieder BASH-Spaghetticode produzieren.

Die JSON-Datei hat uebrigens 1,4MByte und muss dann recht oft runtergeladen werden.

Dann bin ich ja beruhigt. :)

Ein Beispiel das alle Knoten die länger als X Tage offline sind anzeigt + deren MAC.

import requests
from prettytable import PrettyTable
import datetime
import dateutil.parser
import time
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-d', '--days', help='list all nodes longer offline than x days', default=30, required=True, dest='days')
args = parser.parse_args()

ref_date = datetime.datetime.now() - datetime.timedelta(days=int(args.days))

data = requests.get('http://map.freifunk-rhein-neckar.de/data/nodes.json').json()

table = PrettyTable(["MAC", "Name", "Last seen"])
table.align = 'l'
table.sortby="Last seen"

for key, node in data['nodes'].items():
    if node['lastseen']:
        if ((dateutil.parser.parse(node['lastseen']) < ref_date) and not node['flags']['gateway']) and 'system' in node['nodeinfo']: # and not node['nodeinfo']['system']['role'] == 'temp':
            table.add_row([node['nodeinfo']['node_id'], node['nodeinfo']['hostname'], node['lastseen']])
            print(node['nodeinfo']['node_id'])
print(table)

lol Traffic :P Als würde das unseren monatlichen Durchsatz von 350TB interessieren :P

3 „Gefällt mir“

"with a litte help from my students…"
Jetzt hab ich zumindest mal grundsaetzlich JSON verstanden, Pythonneuland auch.

#!/usr/bin/python

#Aufruf mit "clients.py -n suchstring"
# Von allen Nodes mit "suchstring in "hostname"  wird die Anzahl der Clients angezeigt
# Vorsicht, die Suche ist case sensitive, Gross- und Kleinschreibung wird unterschieden

import requests 
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-n', '--name', required=True, dest='string')

args = parser.parse_args()

data = requests.get('http://map.freifunk-rhein-neckar.de/data/nodes.json').json()


for key, node in data['nodes'].items():
    if (args.string in node['nodeinfo']['hostname']):
        print node['statistics']['clients'],node['nodeinfo']['hostname']

# Erst hostname, dann Clientanzahl
#       print node['nodeinfo']['hostname'],node['statistics']['clients']

Ausgabe sieht dann so aus.

root@DeineMudda:/root/skripte ./clients.py -n Mannheim
    0 Mannheim_ben
    2 Mannheim_Burgstrasse_3
    7 Mannheim-FES-002
    2 ffrn-MEG-Mannheim
    0 Mannheim-FES-001
    20 Mannheim_Neckar2_305
    2 Mannheim_Burgstrasse_01
    4 Mannheim-Neckar_307
    20 Mannheim-Neckar3_225
    0 Heidelberg-Mannheimerstrasse

Wenn du jetzt noch Pretty Table importierts / installierst,

bekommst du noch eine schöne ausgabe :P

Hahaha…das hab ich ja bewusst aus leahs Code rausgeworfen, brauch ich nicht, ich will ja eigentlich nur die jeweilige Anzahl der Clients auf meinem MQTT-Broker.

Das case-sensitive haette ich gerne noch raus, hat aber mit MQTT nix zu tun.

Bin immer noch nicht zufrieden, ich strebe immer nach Einsparung von benoetigter Bandbreite und deshalb ist es fuer mich unbefriedigend fuer alberne paar Byte „payload“, alle paar Minuten 1,4MByte runterzuladen und dann quasi zuhause nach der Anzahl der Clients zu parsen, Ergebnis = 8, 9, 13 oder 0

Im grossen Forum wurde gerade die Meshviewerstruktur besprochen, waere es denn nicht moeglich die einzelnen Daten gleich in eine Datenbank zu schreiben (sind sie ja schon, InfluxDB hat ja vermutlich schon alles) und von dort per SQL-Magie auszulesen? Die Arbeit hat der Datenbankserver, dafuer gibt’s weniger Traffic oder ist das alles schon realisiert und ich finde es nicht? Komm ich irgendwie ausser ueber Grafana an aktuelle Daten aus der nodes.json dran ohne sie ganz runterzuladen?

Bild ist von hier: https://forum.freifunk.net/t/gruene-gluon-wiese-welcher-kartenserver/15894/5

Möglich ist es, dass selbst zu parsen und wieder in eine Datenbank zu schreiben. Und nein ein InfluxDB kommt bei uns nicht zum Einsatz. Aber das wäre eigentlich viel lustiger wenn das jemand als Dienst macht und nicht direkt von uns kommt. Die Daten sind ja da, also vielleicht hast du ja Lust da eine hübschere API zu bauen.

Wie schon gesagt, den Traffic interessiert zumindest auf unsere Seite niemanden. Und nö so ist das noch nicht gebaut.

Nein, das geht aktuell nicht.

Lustig nicht, aber sinnvoll.

Hier nochmal das Python-Script case-insensitive, Gross- und Kleinschreibung im Suchstring spielt keine Rolle mehr.

#!/usr/bin/python

#Aufruf mit "clients.py -n suchstring"
# Von allen Nodes mit "suchstring in "hostname"  wird die Anzahl der Clients angezeigt

import requests 
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-n', '--name', required=True, dest='string')

args = parser.parse_args()

data = requests.get('http://map.freifunk-rhein-neckar.de/data/nodes.json').json()


for key, node in data['nodes'].items():
    if (args.string.lower() in node['nodeinfo']['hostname'].lower()):
        print node['statistics']['clients'],node['nodeinfo']['hostname']

Das kann ich jetzt auch bestaetigen, von dem freien RAM und dem Platz auf dem Flash abgesehen, wuppt der 4300er mal locker durch zwei Waende durch, die Familie aus Afghanistan freut sich, dass sie jetzt auch in der Kueche Netz haben und nicht nur im Kinderzimmer.

Ist diese Erkenntnis uebertragbar auf alle 4300? HF-Teil besser?