You are here

Projekt 31 - OpenWrt

Themen:

 


Linux Befehle

Befehl Beschreibung
ps Auflistung der Prozesse
kill -9
Beenden des Prozesses mit ID
Ctrl + z Stoppen der Ausführung
bg Weitere Ausführung im Hintergrund
stty -F /dev/ttyUSB0 -a Ausgabe der Terminal Einstellungen
vi file.txt Datei bearbeiten
  :x Verlassen und Speichern der Änderungen
  :w Speichern (write)
  :w file Speichern mit Angabe des Datei Namens (write)
  :wq Speichern und danach Beenden (write, quit)
  :q Beenden falls keine Änderungen (quit)
  :q! Beenden ohne Änderungen zu speichern (quit)
  ESC Wechsel in den Befehlsmodus
  i Wechsel in den Einfügemodus - Einfügen vor dem Cursor (insert)
  a Wechsel in den Einfügemodus - Einfügen nach dem Cursor (append)

 


USB Stick FTP Server

Für das einfache Verteilen von USB Stick Daten habe ich mir einen kleinen WiFi Router als WiFi Daten Server konfiguriert. Somit können die Daten vom Handy oder auch von mehreren Rechnern ausgelesen werden. Da der Server nur temporär in Betrieb genommen wird, wenn USB Stick Daten ausgetauscht werden, habe ich mich bezüglich Sicherheit weniger gedanken gemacht.

Als WiFi Daten Server habe ich beim TP-Link TL-MR3020 v3 das OpenWrt geflasht und konfiguriert. Die HW-Ausstattung ist gerade noch ausreichend um alles zu bedienen: MediaTek MT7628NN mit 575 MHz, 64MB RAM, 8MB Flash, WiFi, 1x Ethernet (100Mbps), 1x USB 2.0 und 1x UART (TP2 ... TX Out, TP1 ... RX In) Anschluss.

Für das Image flashen wird der Recovery Mode im U-Boot verwendet. Hierfür benötigt man einen TFTP Server (z.B. TFTPD64), der das Image bereitstellt. Die Server IP-Adresse wird statisch auf 192.168.0.225/24 eingestellt. Das Image wird von "openwrt-22.03.3-ramips-mt76x8-tplink_tl-mr3020-v3-squashfs-tftp-recovery.bin" auf "tp_recovery.bin" umbenannt und in das TFTP Server Verzeichnis kopiert. Danach wird der Router mit dem Rechner verbunden und die Reset-Taste gedrückt. Mit der gedrückten Reset-Taste wird der Router mit Spannung versorgt. Die Reset-Taste wird danach noch weiter 6-7 Sekunden gedrückt. Erst nach dem Start des Downloads vom TFTP Server kann die Taste losgelassen werden. Nach dem Download schreibt der Router das Image in den Flash Speicher.

Für das Erkennen des USB Sticks werden einige Packete benötigt. Zum Bereitstellen der Daten habe ich mich für FTP entschieden, da der Samba Server mehr Speicher benötigen würde. Die Packete können über das Webinterface oder über die Command Line (opkg update, opkg install ...) installiert werden.

  • Kernel Modification Packages
    • kmod_usb_core - Kernel Support für USB
    • kmod_usb_storage - Kernel Support für USB Speicher
    • kmod_usb_storage_uas - Manche USB Sticks benötigen auch den UAS Treiber
  • Packages
    • usbutils - USB Command Line Tool
    • vsftpd - FTP Server

Ob der USB Stick erkannt wurde, kann man über Command Line feststellen (lusb -t). Danach kann man den Stick bereits mounten, indem man den Status der Block-Geräte (block detect) in die File-System-Tabelle einträgt (uci import fstab) (/etc/config/fstab). Mit dem nächsten Befehl wird das Mounten zum Start-Zeitpunkt konfiguriert. Hier entspricht "/dev/sda" dem "mount[0]" Element, "dev/sdb" "mount[1]" usw. Der letzte Befehl dient zum Testen ohne Neustart (/etc/init.d/fstab boot).

lsusb -t
    ...
    /:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci-mtk/1p, 5000M
    /:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci-mtk/2p, 480M
        |__ Port 1: Dev 5, If 0, Class=Mass Storage, Driver=usb-storage, 480M
    ...

block detect | uci import fstab
uci set fstab.@mount[0].enabled='1' && uci set fstab.@global[0].anon_mount='1' && uci commit fstab
/etc/init.d/fstab boot

Als nächstes wurde der FTP Server konfiguriert. Das automatische Starten wurde in der Weboberfläche unter "System/Startup" eingestellt. Die Konfigurationsdatei befindet sich unter "/etc/vsftpd.conf". Der FTP Ordner wird mittels "local_root=/mnt/sda1" angegeben. Bei meiner Konfiguration hat nur der root Benutzer Schreib- und Lese-Zugriff. Den anonymen Zugriff habe ich deaktiviert "anonymous_enable=NO". Der Passiv-Modus wurde mit "pasv_enable=YES", "pasv_min_port=40000" und "pasv_max_port=50000" aktiviert.

vi /etc/vsftpd.conf
    background=YES
    listen=YES
    local_enable=YES
    write_enable=YES
    local_umask=022
    local_root=/mnt/sda1/
    anonymous_enable=NO
    #
    pasv_enable=YES
    pasv_min_port=40000
    pasv_max_port=50000
    #
    userlist_enable=NO

Damit die Ports von der Firewall nicht blockiert werden, müssen sie noch über das Webinterface freigegeben werden:

  • Erlaube eingehende IPv4 Verbindungen mit dem TCP Protokoll von "any zone" zu "this device" mit den Ports 20-21
  • Erlaube eingehende IPv4 Verbindungen mit dem TCP Protokoll von "any zone" zu "this device" mit dem Port 990
  • Erlaube eingehende IPv4 Verbindugne mit dem TCP Protokoll von "any zone" zu "this device" mit den Ports 40000-50000

 


Internet Radio

Da bei der Terrasse ein schlechter UKW Radio Empfang ist, habe ich eine zuverlässige Internet Radio Lösung gesucht. Die meisten erwerbbaren Internet Radios konnte ich nicht verwenden, da sie mit Displays bestückt sind. Die meisten Displays würden keinen Winter mit Minustemperaturen standhalten. Somit blieben zwei "einfache" Möglichkeiten übrig: Linux Router mit OpenWrt oder WiFi Controller mit FreeRTOS (z.B. ESP32). Die Linux Router Variante erschien mir zuerst etwas einfacher.

Als Hardware Platform entschied ich mich für den NanoPi R1 von Friendly Elec. Das Grundgerät mit 512MB RAM und SD Karte als Datenspeicher reicht bereits aus und ist z.B. über Amazon sehr günstig. Die weitere HW Ausstattung mit Quad-Core Cortex A7, BLE, WiFi, 2x Ethernet (1Gbps, 100Mbps), 2x USB 2.0 und 2 UART Anschlüsse ist ebenso beeindruckend. Weitere Informationen findet man auf der Friendly Elec Wiki Seite. Die Audio-Ausgabe kann man einfach über einen USB Klinkenadapter mit integrierter Soundkarte realisieren. Hier habe ich mich für ein Produkt von DUKABEL entschieden. Die genaue Modell Bezeichnung lautet DUSB351M-120B. Den Klinkenstecker verband ich direkt mit einem einfachen Verstärker, welcher die Lautsprecher ansteuert.

Als Betriebssystem für den Router wird von Friendly Elec jeweils ein Image von UbuntuCore und OpenWRT im Downloadbereich bereitgestellt. Das Angebotene OpenWRT mit FriendlyWrt 19.07.1 ist bereits älter und könnte Sicherheitslücken haben. Da es hier "nur" als Internet Radio verwendet wird, sind die Sicherheitsupdates weniger kritisch und wurden hier nicht betrachtet. Wird ein aktuelles OpenWrt benötigt, so kann man die Images von der OpenWrt Seite verwenden. Diese Images beinhalten etwas weniger vorinstallierte Packages und sind somit vielleicht noch nicht so einfach zu verwenden. Für das Schreiben auf die SD Karte kann man unter Windows den Win32 Disk Imager verwenden.

Nach dem Schreiben des Images und dem Starten des Routers kann man die Weboberfläche über die LAN Schnittstelle erreichen. Hier sollte man sofort das Admin Passwort setzen. Als nächsten Schritt werden die benötigten Packages für das Internet Radio über die Weboberfläche installiert (siehe Liste unterhalb). Für die kmod-Pakete musste ich noch den Link für die kmod-Pakete in der opkg Konfiguration auskommentieren. Die Warnung, dass die Kernel-Version nicht übereinstimmt war bei mir kein Problem.

  • Kernel Modification Packages
    • kmod_usb_core - Kernel Support für USB
    • kmod_usb_audio - Kernel Support für USB Audio Karten
  • Packages
    • usbutils - USB Command Line Tool
    • alsa_lib - Audiofunktion unter Linux, ALSA = Advanced Linux Sound Architecture
    • alsa_utils - ALSA Command Line Tool
    • mpd_mini - MPD = Music Player Daemon
    • mpc - Command Line Tool für MPD

Nach der Installation kann man den Internet Radio über die Command-Line Website (ttyd Package) bereits testen. Zuerst sollte man überprüfen, ob die USB-Soundkarte erfolgreich gefunden wurde (lusb, lusb -t, aplay -l). Für die MPD Konfiguration kann man sich gleich den Namen merken (Device). Für die MPD Lautstärken Regelung benötigt man auch noch die ALSA Mixer Information (amixer controls): die ID (numid=1) und den Interface-Typ (iface=MIXER).

lsusb
    ...
    Bus 008 Device 004: ID 1b3f:2008 Generalplus Technology Inc.
    ...
 
lsusb -t
    ...
    /: Bus 08.Port 1: Dev 1, Class=root_hub, Driver=ohci-platform/1p, 12M
        |__ Port 1: Dev 4, If 0, Class=Audio, Driver=snd-usb-audio, 12M
        |__ Port 1: Dev 4, If 1, Class=Audio, Driver=snd-usb-audio, 12M
        |__ Port 1: Dev 4, If 2, Class=Audio, Driver=snd-usb-audio, 12M
        |__ Port 1: Dev 4, If 3, Class=Human Interface Device, Driver=usbhid, 12M
    ...
 
aplay -l
    **** List of PLAYBACK Hardware Devices ****
    ...
    card 4: Device [USB Audio Device], device 0: USB Audio [USB Audio]
        Subdevices: 1/1
        Subdevice #0: subdevice #0
    ...

amixer controls
    numid=1,iface=MIXER,name='Master Volume';
    ...

Danach kann man direkt den MPD konfigurieren (vi /etc/mpd.conf, /etc/init.d/mpd restart) und testen (mpd &, mpc add ..., mpc volume 90, mpc play). Die angegebenen Ordner im root User-Verzeichnis musste ich vorher noch erstellen. Als "user" habe ich "root" eingetragen. Somit wird im Anschluss beim automatischen Starten über das init-Skript auch das root User-Verzeichnis verwendet. Aus Sicherheitsgründen sollte man hier einen eigenen User anlegen und ebenso die Verzeichnisse in dessen User-Verzeichnis anlegen und verwenden. Aufgrund der eingeschränkten Nutzungszeit des Radios habe ich den Admin-Benutzer direkt verwendet. Damit das Command Line Tool MPC den MPD steuern kann muss die Loopback Adresse 127.0.0.1 angegeben werden. Am Ende wird noch das Audio Interface und der Mischer bekannt gegeben.

vi /etc/mpd.conf
    music_directory         "~/music"
    playlist_directory      "~/.mpd/playlists"
    db_file                 "~/.mpd/database"
    log_file                "~/.mpd/log"
    user                    "root"
    bind_to_address         "127.0.0.1"
    audio_output {
        type                "alsa"
        name                "USB Audio Device"
        device              "plughw:Device"
        mixer_type          "software"
        mixer_control       "MIXER"
        mixer_index         "1"
    }

mpd &
mpc add http://ors-sn05.ors-shoutcast.at/oe3-q2a
mpc volume 90
mpc play

Damit der Internet Radio sofort nach dem Boot-Vorgang startet, braucht man nur die Test-Befehle im Startup-Skript "/etc/rc.local" eintragen. Für einen Reibungslosen Start wird hier aber noch eine Pause von ca. 10 Sekunden eingefügt. Somit sind alle benötigten Treiber geladen und die Internetverbindung hergestellt bevor der MPD gestartet wird.

sleep 10
mpd &
mpc add http://ors-sn05.ors-shoutcast.at/oe3-q2a
mpc volume 90
mpc play

Folgende URLs von Österreichischen Radio-Sendern können zum Testen verwendet werden:

  • http://ors-sn05.ors-shoutcast.at/oe1-q1a    OE1 128kbs
  • http://ors-sn05.ors-shoutcast.at/oe1-q2a    OE1 192kbs
  • http://ors-sn05.ors-shoutcast.at/oe3-q1a    OE3 128kbs
  • http://ors-sn05.ors-shoutcast.at/oe3-q2a    OE3 192kbs
  • http://ors-sn05.ors-shoutcast.at/fm4-q1a    FM4 128kbs
  • http://ors-sn05.ors-shoutcast.at/fm4-q2a    FM4 192kbs
  • http://ors-sn05.ors-shoutcast.at/noe-q1a    Radio NOE 128kbs
  • http://ors-sn05.ors-shoutcast.at/noe-q2a    Radio NOE 192kbs
  • http://ors-sn05.ors-shoutcast.at/wie-q1a    Radio Wien 128kbs
  • http://ors-sn05.ors-shoutcast.at/wie-q2a    Radio Wien 192kbs

OpenWRT Router USB Audio USB Supply

 


MQTT Server

MQTT (Message Queuing Telemetry Transport) wird in vielen Bereichen und vor allem im Home Automation Bereich immer beliebter. Bei MQTT handelt es sich um ein klassisches Publish und Subscribe Protokoll. Die Daten werden vom Sensor einfach in einem bestimmten Topic bereitgestellt (z.B. sensors/nr1/temperature). Jeder Actor kann sich auf gewünschte Topics registrieren (subscribe) und erhält die Daten dadurch automatisch. Die Daten an sich werden in einem Server (broker) zwischengespeichert, der auch für die Verteilung zuständig ist.

Beim klassischen MQTT werden bei jeder Transaktion die Topic Strings mit übertragen. Um diesen Overhead zu reduzieren wurde eine abgewandelte Variante mit MQTT-SN spezifiziert. SN steht hier für Sensor-Network und bedeutet eine schlankere und datensparsamere Übertragung für kleinere Sensor-Netzwerke wie z.B. Zigbee, 802.15.4/Thread ... Bei meiner Umgebung verwendete ich ein MQTT-SN Gateway für die Anbindung von Zigbee Geräten. Hierfür wird ein Zigbee-fähiger RF-Stick benötigt.

Mit der reinen MQTT Umgebung können die Daten bereits ausgetauscht werden. Sollen zusätzlich noch Aktionen gestartet werden oder die Daten grafisch aufbereitet werden, so kann man Node-RED verwenden. Mit Hilfe von Node-RED kann man gewünschte Abläufe (flows) einfach mit einer grafischen Oberfläche "programmieren" und mit dem Zusatzpaket "Dashboard" auch visualisieren.

Den ersten Test-Server habe ich mit dem NanoPi R1S-H3 von Friendly Elec realisiert. Folgende Pakete werden für den MQTT Broker, den RF Stick, dem MQTT-SN Gateway und Node-RED benötigt. Für das Erkennen des USB Sticks werden einige Packete benötigt. Die Packete können über das Webinterface oder wieder über die Command Line (opkg update, opkg install ...) installiert werden.

  • Kernel Modification Packages
    • kmod_usb_core - Kernel Support für USB
    • kmod_usb_serial - Kernel Support für USB Serial Konverter
    • kmod_usb_serial_ftdi - Treiber für FTDI USB Serial Chips
  • Packages
    • usbutils - USB Command Line Tool
    • mosquitto-nossl - Mosquitto ohne SSL Verschlüsselung
    • luci-app-mosquitto - Mosquitto Integration in die Weboberfläche (LuCi)
    • node - NodeJS
    • node-npm - NodeJS Package Manager

Für die manuelle Installation der Kernel Mods findet ihr unterhalb ein Beispiel. Zuerst wird wieder überprüft, ob das angeschlossene USB FTDI Kabel grundsätzlich erkannt wurde (lsusb). Danach werden die zusätzlichen Pakete heruntergeladen (wget) und installiert (opkg install). Nach einem Neustart sollte das Gerät bereits untern "/dev/" als "ttyUSB*" gefunden werden.

lsusb
wget https://downloads.openwrt.org/releases/19.07.1/targets/sunxi/cortexa7/packages/kmod-usb-serial_4.14.167-1_arm_cortex-a7_neon-vfpv4.ipk
wget https://downloads.openwrt.org/releases/19.07.1/targets/sunxi/cortexa7/packages/kmod-usb-serial-ftdi_4.14.167-1_arm_cortex-a7_neon-vfpv4.ipk
opkg install kmod-usb-serial_4.14.167-1_arm_cortex-a7_neon-vfpv4.ipk --force-depends
opkg install kmod-usb-serial-ftdi_4.14.167-1_arm_cortex-a7_neon-vfpv4.ipk --force-depends
reboot
cd /dev/
ls

Die Installation von Node-RED muss man über den NodeJS Paket Manager durchführen. Hierfür gibt es kein OpenWrt Paket. Mit den beiden Befehlen unterhalb wird Node-RED installiert und für erste Tests bereits gestartet. Der Zugriff erfolgt über die Geräte IP Adresse und Port 1880 (z.B. http://192.168.1.100:1880).

npm install -g --unsafe-perm node-red
node-red
    29 Apr 11:07:26 - [info]
 
    Welcome to Node-RED
    ===================
 
    29 Apr 11:07:26 - [info] Node-RED version: v1.3.3
    29 Apr 11:07:26 - [info] Node.js  version: v8.16.1
    29 Apr 11:07:26 - [info] Linux 4.14.111 arm LE
    29 Apr 11:07:32 - [info] Loading palette nodes
    29 Apr 11:07:38 - [info] Settings file  : /root/.node-red/settings.js
    29 Apr 11:07:38 - [info] Context store  : 'default' [module=memory]
    29 Apr 11:07:38 - [info] User directory : /root/.node-red
    29 Apr 11:07:38 - [warn] Projects disabled : editorTheme.projects.enabled=false
    29 Apr 11:07:38 - [info] Flows file     : /root/.node-red/flows_FriendlyWrt.json
    29 Apr 11:07:38 - [info] Creating new flow file
    29 Apr 11:07:38 - [info] Server now running at http://127.0.0.1:1880/
    29 Apr 11:07:38 - [info] Starting flows
    29 Apr 11:07:38 - [info] Started flows
    29 Apr 11:52:19 - [info] [mqtt-broker:Local Mosquitto] Verbindung zum Broker mqtt://127.0.0.1:1883 aufgebaut

Für das automatische Starten im Anschluss wird ein Init-Skript installiert. Hierfür wird das Skript nach "/etc/init.d" heruntergeladen und mit Ausführ-Rechten versehen. Danach wird die Log-File GUI Integration für LuCI heruntergeladen. Nach einem Neustart sollte alles automatisch gestartet werden.

cd /etc/init.d/
wget https://github.com/dceejay/openwrt-node-red/raw/master/node-red
chmod a+x node-red
cd /usr/lib/lua/luci/view/admin_status
wget https://raw.githubusercontent.com/dceejay/openwrt-node-red/master/luci/view/admin_status/nrlog.htm
cd /usr/lib/lua/luci/controller/admin
wget https://raw.githubusercontent.com/dceejay/openwrt-node-red/master/luci/controller/admin/status.lua
reboot

Für eine grafische Ausgabe der Daten bzw. mögliche Benutzer-Interaktionen benötigt man das Node-RED Dashboard. Dieses wird wieder mit den NodeJS Paket Manager installiert. Danach kann man das Dashboard unter dem Port 1800 und Sub-URL "ui" erreichen (z.B. http://192.168.1.100:1800/ui).

cd /usr/lib/node_modules/node-red/
npm install node-red-dashboard

Das MQTT-SN Gateway muss man leider noch selbst kompilieren und als Paket verpacken (wird hier nicht beschrieben). Danach kann man es auf den Router mit Hilfe von Putty Secure Copy (pscp) vom Windows Rechner kopieren. Mit dem zweiten Befehl kann man auch Dateien vom Router zum Windows Rechner kopieren. Die Installation erfolgt wieder mit dem Paket Manager (opkg install). Für erste Tests startet man die Binär-Datei mit angegebener Konfigurationsdatei (MQTT-SNGateway). In der Konfigurationsdatei werden die Seriellen Parameter und die Verbindungsdaten vom MQTT Broker angegeben (/etc/mqttsn-gw/gateway.conf).

pscp -scp mqtt-sn_1.0.0-1_arm_cortex-a7_neon-vfpv4.ipk root@192.168.88.254:/tmp
pscp -scp root@192.168.88.254:/etc/init.d/mqtt-sn ./

opkg install mqtt-sn_1.0.0-1_arm_cortex-a7_neon-vfpv4.ipk
/usr/bin/MQTT-SNGateway -f /etc/mqttsn-gw/gateway.conf

Für das automatische Starten wird wieder ein Init-Skript vorbereitet und unter "/etc/init.d/mqtt-sn" abgelegt. Die Befehle unterhalb dienen zum testen ohne Neustart (mqtt-sn start/stop/restart).

#!/bin/sh /etc/rc.common
# Starts and stops MQTT-SN GW
# /etc/init.d/mqtt-sn
 
START=90
STOP=10
 
# PID and binary file for start-stop-daemon
PIDFILE=/var/run/mqtt-sn.pid
DAEMON=/usr/bin/MQTT-SNGateway
 
# test if binary exists and execute permission is granted
test -x ${DAEMON} || exit 0
 
export PATH="${PATH:+$PATH:}/usr/sbin:/sbin"
 
start() {
    echo "Starting MQTT-SN Gateway"
    if start-stop-daemon -S -q -b -m -p ${PIDFILE} -x ${DAEMON} -- -f /etc/mqttsn-gw/gateway.conf ; then
        exit 0
    else
        exit 1
    fi
}
 
stop() {
    echo "Stopping MQTT-SNGateway"
    if start-stop-daemon -K -q -s SIGKILL -p ${PIDFILE}; then
        rm -f ${PIDFILE}
        exit 0
    else
        exit 1
    fi
}
 
restart() {
    echo "Restarting MQTT-SNGateway" "MQTT-SNGateway"
    if start-stop-daemon -K -q -s SIGKILL -p ${PIDFILE}; then
        rm -f ${PIDFILE}
    fi
    if start-stop-daemon -S -q -b -m -p ${PIDFILE} -x ${DAEMON} -- -f /etc/mqttsn-gw/gateway.conf ; then
        exit 0
    else
        exit 1
    fi
}

/etc/init.d/mqtt-sn start
/etc/init.d/mqtt-sn restart
/etc/init.d/mqtt-sn stop