Multi Purpose IGate DireWolf (Stand 2023-11-15)
zurück zu 'Technik'APIR - APRS Pi Remote Control
Projektidee: "Fernwirken" mit APRS-Queries
Dazu bestens geeignet ist ein Raspberry Pi. Die GPIO-Pins können mittels Sofware angesteuert und abgefragt werden. Fehlte einzig ein APRS-Decoder, der auf Linux läuft und der ein API für die Steuersoftware zur Verfügung stellt.
In einer 1. Variante wurde der Software-TNC 'Soundmodem' verwendet (siehe Prototyp von HB9EYZ). Erkenntnisse: 'Soundmodem' ist langsam, hat schwachen Decoder, 'beacon' hat keine PTT-Steuerung via GPIO und kann daher nur mit VOX sinnvoll verwendbar.
Der ultimative Sofware-TNC 'DireWolf' löst alle diese Probleme: sehr empfindlicher Decoder, PTT-Steuerung, File-Schnittstelle mit dem Zusatzprogramm 'KISSutil' als 'API'
Anforderungeskatalog APIR (wird laufend umgesetzt und eingeführt):
- Telemetrie
- APRS Queries
- TX von WX Daten in APRS
- MessageCache
- MQTT Broker / HRoT
- RC Funktionalität
Wegen eines TNC-Ausfalls wurde der erste produktive Einsatz als Digi-Ersatz für HB9IPA realisiert.
Raspberry Pi + Zusatzplatinen "HB9BL-1" / "HB9BL-10" / " HB9BL-5" eingesetzt im Clublokal vom HB9FS
Prototype
eingebaut in Alu-Koffer
Hardware
Raspberry Pi 1 |
Model B
USB-Soundcard Der Raspberry hat nur einen Audio-Ausgang. Für Audio IN/OUT wird eine USB-Soundcard benötigt. |
Powering | DC-DC Wandler 12V --> 5V USB |
A/D Wandler |
MCP3008
Die GPIO Pins des Raspberry können nur digitale Werte verarbeiten. Mit dem MCP3008 können auf max. 8 Kanälen Input analoge Werte von 0V - 3.3V eingespiesen werden. Die Python-Library "MCP3008" wandelt die Input-Spannungen auf Werte von 0 - 1024 um. Der MCP3008 wird für die Überwachung der Akku-Spannung benötigt. |
Clock |
DS3132
Bei fehlender Internet-Verbindung wird die Zeit ab einer externen Uhr gelesen. |
PTT Circuit | Transformer 1:1, Opto-Koppler |
Connector TRX | Audio-Kabel. Das hier eingesetzte Yaesu FT-60 hat keinen PTT-Eingang. PTT wird über das Mic-Kabel geschaltet, siehe Manual FT-60. |
PTT Timeout Timer |
Digispark ATtiny85
Der PTT Timeout Timer läuft unabhängig vom Raspberry auf dem Digispark. Er unterbricht das PTT-Signal nach 10 Sekunden. Damit soll ein Dauerträger bei Problemen im Software-TNC vermieden werden. |
Dataflow APIR
Splitter, DWXC, HRoT-GW, WX und MessageCache: Eigenentwicklungen in Python by HB9EYZ
Files
terminal-log |
Die Terminal Messages von DireWolf werden mit 'redirect' in ein File geschrieben.
Das File ist zwecks Schonung der SD-Card des Raspberrys im RAM-Disk abgelegt. |
RX1/2/3 |
Die RX Packets von DireWolf werden von KISSutil als Files in ein Directory geschrieben.
Das Directory ist zwecks Schonung der SD-Card des Raspberrys als RAM-Disk angelegt. |
TX1/2/3 |
Die TX Packets in Fileform werden von KISSutil aus einem Directory gelesen.
Das Directory ist zwecks Schonung der SD-Card des Raspberrys als RAM-Disk angelegt. |
Logs | Die Logs werden zwecks Schonung der SD-Card des Raspberrys auf einem USB-Stick gespeichert. |
Software
Raspian "Bullseye" |
Der Raspberry wird "headless" betrieben, läuft somit ohne Display und ohne Keyboard. Der Zugriff erfolgt einzig über das Network (LAN/WLAN).
In eine 1. Variante wurde dazu ein Reverse SSH Tunnel eingerichtet. Später wurde als 2. Variante ZeroTier installiert. Dieses Tool vereinfacht solche Zugriffe dramatisch: die Remote Station kann direkt mit einer IP Adresse ohne Umweg über einen SSH-Server angesprochen werden. Egal, ob die Station hinter einer Firewall steht oder an 4G hängt. |
DireWolf |
Software TNC
Kann auch als Digipeater und RX/TX Igate konfiguriert werden. Die Linux-Version (Raspberry) bietet eine PTT-Steuerung vie GPIO-Pin an. |
KISSutil |
Clients kommunizieren mit DireWolf mit dem
KISS-Protocol
über TCP-Sockets. Am elegantesten wäre für Python-Clients der Einsatz der Python KISS Library von 'ampledata'.
Trotz vieler Versuche und der Verwendung diverser Versionen dieser Library konnte der Socket-write nicht zum Laufen gebracht werden.
KISSutil ist ein Teil des DireWolf Packages. KISSutil kommuniziert mit DireWolf auf Socket-Level und bietet eine File-Schnittstellen für RX und TX an. RX-Packets von DireWolf werden von KISSutil in das RX-Directory geschrieben. KISSutil liest das TX-Directory und schickt die TX-Packets telquel an DireWolf. Python- und andere Clients verarbeiten die RX- und TX-Directories. |
APIR-Splitter | Python. Aufteilung Datenströme von/zu KISSutil. |
APIR-DWXC (DireWolf Extenced Capabilities) |
Eigenentwicklung von Tom, HB9EYZ. Geschrieben in Python.
Telemetrie APRS Queries |
APIR-WX | Python. Liest Wetterdaten ab Wetterstation und bereitet die WX-Packets auf. |
APIR-HRoT | HAM Radio of Things - MQTT Broker. Dieser Gateway erweitert die Funktionalität von HRoT. |
APIR-MessageCache | Python. Filtert und speichert Packets von registrierten Calls aus RF- und APRS-IS-Datenstrom. tbc |
PTT Watchdog | Arduino C++. Das Aussenden einer APRS-Message dauert ein paar Sekunden. Das PTT-Signal wird vom Raspberry via den PTT Watchdog an den TRX geleitet. Die maximale PTT-Time wird durch den PTT Watchdog kontrolliert. Nach 10 Sekunden wird PTT auf OFF gesetzt und so ein Dauerträger auf 144.800 MHz vermieden. Der Wert ist hardcoded, könnte auch über einen externen Poti konfigurierbar gemacht werden. |
DireWolf - Konfiguration
PBEACON | Beacon alle 30 Minuten |
DIGIPEAT | OFF, nur IGate |
IGSERVER | IGate aktiviert (euro.aprs2.net) |
FILTER |
"IG 0 t/m": von Igate to Channel 0 only "Messages"
(Data Type Indicator ":") |
Splitter
Untersucht den RX-Datenstrom von KISSutil und verteilt die Packets abhängig von deren Verwendungszweck in andere RX-Directories. Sammelt Datenströme von TX-Directories und schreibt diese in das TX-Directory von KISSutil. |
DWXC - DireWolf Extendec Capabilities
DWXC ist als Ergänzug zu DireWolf konzipiert. Via den DireWolf-Zusatz 'KISSutil' werden die RX- und TX-Datenströme verarbeitet.
Die DireWolf-internen TX (Digipeating!) werden über das terminal-log angezapft.
Parameter für DWXC werden in einem Conf-File definiert. So können ohne Programm-Änderung Call, Location, Directories, File-Name usw. angepasst werden. Die vielen I/O-Operationen lassen die SD-Card des Raspberrys schnell altern. Deshalb werden Work-Files als RAM-Disk zwischengespeichert. Die Log-Daten werden direkt auf einen USB-Stick geschrieben. Telemetrie: die Header-Daten wie 'Parameter Name Message' (PARM), 'Unit/Label Message' (UNIT) und 'Equation Coefficients Message' (EQNS) werden stündlich TXed, die 'Telemetry' (T)' Packets alle 'geraden' 15 Minuten: 00, 15, 30 und 45. APRS Queries: die Queries wurden an die 'Standard' Queries angelehnt. Helge, SA7SKY, hat diese zusammengetragen. Diese Liste enthält mehr Queries als in der APRS-Bibel APRS Protocol Reference (P77) beschrieben. |
Telemetrie Values HB9BL-10 HB9BL-10
RxDir | pkt/15m: Anzahl Packets RX direkt in den letzten 15 Minuten |
RxHop | pkt/15m: Anzahl Packets RX via Hop in den letzten 15 Minuten |
RxTot | pkt/15m: Anzahl Packets RX total in den letzten 15 Minuten |
RxQry | pkt/15m: Anzahl Packets RX Query in den letzten 15 Minuten |
TxTot | pkt/15m: Anzahl Packets TX total in den letzten 15 Minuten |
ExtCap | Switch 1 - Extended Capabilities: 0 = off, 1 = on |
PathA |
Switch 2 - PathAdaption: 0 = off, 1 = on
off: APRS-Queries werden mit dem konfigurierten Default-Path beantwortet. on: APRS-Queries werden mit dem rekonstruierten Path des empfangenen Query-Packets beantwortet. Damit soll gewährleistet werden, dass die Response den Anfrager wieder erreicht. |
SW 3-8 | Switches 3-8 werden momentan nicht verwendet |
APRS Queries HB9BL-10
APRS Queries werden als 'Message' (Data Type Identification ":") abgesetzt, siehe
APRS Protocol Reference (P71). Eine
Query muss nicht Case-sensitive sein, d.h. Gross- und Kleinschrift sind möglich.
Die Query beginnt immer mit "?", gefolgt vom Query Type. Wird hinter dem Query Type ein weiteres "?" angegeben, dann wird als Response eine Kurzbeschreibung des Query Types zurückgesendet. Eventuelle Parameter sind hinter dem Query Type nach einem ";" (Semikolon) oder " " (Space) anzugeben: "Query Type;Parameter". Z.B. "APRSH;HB9EYZ-14". Ein Query Packet muss an "HB9BL-10" adressiert werden und sieht so aus: "HB9EYZ-4>APZ101,WIDE1-1::HB9BL-13 :?aprs?". Wird z.B. APRSISCE als Client verwendet, geht das so: - Menu 'Messages' -> 'Send Message' - To: HB9IPA -> Chat - Message: "?APRS" - Send RF Beispiele
|
Query | Output |
?APRS?
?APRS |
List of all queries that can be answered by this station.
*APRS?: (1/5) available queries: ?APRSO ?APRSP ?APRSD ?APRSL *APRS?: (2/5) available queries: ?APRSS ?APRST/PING ?CPU *APRS?: (3/5) available queries: ?APRSV/?VER/?ABOUT ?APRSH *APRS?: (4/5) available queries: ?DX ?DX-D ?DX-H *APRS?: (5/5) For help, add '?' to the command. ?APRSP?, ?VER? etc. |
?APRSO?
?APRSO |
Object query. List of all objects created by this station.
*APRSO: no objects created |
?APRSP?
?APRSP |
Send position
*APRSP: 4727.89N / 00745.88E Locator: JN37VL |
?APRSD?
?APRSD |
Stations heard directly last 1 hour (limited).
*APRSD: (1/5) HB9AW-10 (17:17Z) 48km HB9CR-4 (17:05Z) 22km *APRSD: (2/5) HB9EYW-6 (17:18Z) 18km HB9EYZ-4 (17:22Z) *APRSD: (3/5) HB9FM-4 (17:21Z) HB9FS (17:21Z) 4km *APRSD: (4/5) HB9IPA (17:15Z) HB9LU-12 (17:17Z) 59km *APRSD: (5/5) HB9NF-10 (17:21Z) 87km HB9XC-4 (17:12Z) 46km |
?APRSL?
?APRSL |
Stations heard via hop last 1 hour (limited).
*APRSL: (1/6) DF2TB-9 (13:59Z) 42km F5INM-9 (14:00Z) 72km *APRSL: (2/6) F5ZV-9 (14:00Z) 74km F6HOR-3 (14:00Z) 80km *APRSL: (3/6) HB9BL-13 (14:02Z) HB9BL-14 (14:00Z) *APRSL: (4/6) HB9DFI-7 (14:02Z) 20km HB9FHL-13(13:59Z) 77km *APRSL: (5/6) HB9GUF-1 (14:01Z) 121km OE9MMV-9 (13:59Z) 148km *APRSL: (6/6) OE9XMH-10(14:00Z) 159km |
?APRSS?
?APRSS |
Send status
*APRSS: Uptime: 45 min; heard keep time, direct: 3600 sec hop: 3600 sec |
?APRST?
?PING? ?APRST ?PING |
Path by which the packet was heard.
*APRST: Path to: APZ101 via: WIDE1-1 *PING: Path to: APZ101 via: WIDE1-1 |
?APRSV?
?VER? ?ABOUT? ?APRSV ?VER ?ABOUT |
Software versions
*APRSV: DireWolf 1.6, DWXC1 0.9 (DireWolf Extended Capabilities) *VER: DireWolf 1.6, DWXC1 0.9 (DireWolf Extended Capabilities) *ABOUT: DireWolf 1.6, DWXC1 0.9 (DireWolf Extended Capabilities) |
?CPU?
?CPU |
Operating system, Uptime, CPU Temp
*CPU: Host/Kernel/OS: rpi60 5.10.63-v7+ GNU/Linux; UpTime: 57 min; CPU Temp: 41.3C |
?DX?
?DX |
Farest RXed stations heard during the past 2 hours.
Calls with a leading * means digipeated / hop used. *DX: (1/5)*OE9XMH-10 14:00Z 159km 101g *OE9MMV-9 13:59Z 148km 90g *DX: (2/5)*HB9GUF-1 14:01Z 121km 110g *F6HOR-3 14:00Z 80km 331g *DX: (3/5)*HB9FHL-13 13:59Z 77km 116g *F5ZV-9 14:00Z 74km 288g *DX: (4/5)*F5INM-9 14:00Z 72km 337g *DF2TB-9 13:59Z 42km 340g *DX: (5/5)*HB9DFI-7 14:01Z 19km 68g HB9BL-14 14:00Z 1km 177g |
?DX-D?
?DX-D |
Farest RXed stations heard during the past 2 hours.
Output limited to 5 packets. Only call directly heard. *DX-D: (1/1) HB9BL-14 14:00Z 1km 177g |
?DX-H?
?DX-H |
Farest RXed stations heard during the past 2 hours.
Output limited to 5 packets. Only calls heard via digis. *DX-H: (1/5)*OE9XMH-10 14:00Z 159km 101g *OE9MMV-9 13:59Z 148km 90g |
?APRSH?
?APRSH |
Heard station within 18h: ?APRSH;HB9EYZ-1
*APRSH: HB9EYZ-4 heard 18 times; last: 15:00Z |
WX HB9BL-1
tbc
|
MessageCache HB9BL-10
APRS-Messages werden sofort ausgesendet, unabhängig davon, ob der Empfänger (=Dest-Call) On Air ist. Viele Messages gehen so verloren.
Abhilfe schafft der experimentelle Bot MessageCache. Er klinkt sich in den Packet-Strom von RF und APRS-IS ein. Packets, welche an registrierte Dest-Calls addressiert sind, werden gespeichert. Empfängt MessageCache ein 'Lebenszeichen' (irgendein Packet) des Dest-Calls, so wird dem Dest-Call eine Notification-Message mit der Anzahl neuer (nicht gelesener) Messages zugestellt; *MessageCache: You have 9 new msg(s) waiting. Overview: ?MCLO Der Benutzer des Dest-Calls kann sich diese Messages mit APRS-Queries anzeigen lassen. Die Queries sind in der Tabelle unten aufgelistet. Gross-/Kleinschreibung ist nicht relevant. QRV werden: APRS-Message an HB9BL-10, Message-Text: ?MCON. APRS-Messaging funktioniert weltweit. Bedingung: bidirektionaler IGate im Empfangsbereich. |
Query | Output |
?MCH?
?MCH |
*MCH: (1/3) Available queries. Help: add '?' to the query, ?MC?
*MCH: (2/3) ?mc ?mcon ?mcoff ?mcl ?mclo ?mci ?mcr ?mcd ?mcer ?mcel ?mces *MCH: (3/3) Documentation: hb9fs.ch/fsmc.php |
?mc?
?mc |
*MC?: Info MessageCache status ON/OFF
*MC: MessageCache status: ON at 2023-04-20 07:34:03Z E-Mail: HB9EYZ@ETAS-IT.CH |
?mcon?
?mcon |
*MCON?: Set MessageCache ON. Check status: ?MC
*MCON: MessageCache turned ON at 2023-04-18 11:22:33Z *MCON: MessageCache ALREADY turned ON at 2023-04-20 07:34:03Z |
?mcoff?
?mcoff |
*MCOFF: Set MessageCache OFF. Call & messages will be deleted. Check status: ?MC
?MCOFF: MessageCache turned OFF, all messages deleted ?MCOFF: MessageCache turned OFF ?MCOFF: MessageCache is NOT turned on. Query ?MCH? |
?MCL?
?MCL |
*MCL?: List counters of new/read messages.
*MCL: You have 9 new and 2 read msgs in your cache. Overview: ?MCLO *MCL: Call not registered. Query ?MCH? *MCL: You have NO messages in your cache. *MCL: |
?MCLO?
?MCLO |
*MCLO?: List short overview of messages with timestamps. Info ?MCI #, read ?MCR #
*MCLO: (1/2) #62 Apr-23 0909Z* ANSRVR #61 Apr-22 2116Z* QRU *MCLO: (2/2) #52 Apr-20 1445Z* KM4LLN-7 #51 Apr-20 1444Z* AD8II-1 *MCLO: Call not registered. Query ?MCH? |
?MCI?
?MCI 52 |
*MCI?: Info about message: ?MCI &message-nr (without #)
*MCI 52: from KM4LLN-7 on 2023-04-20 14:45:30Z path APWW11,KJ4ERJ-15*,TCPIP*,qAS,KJ4ERJ-15 *MCI 52: Call not registered. Query ?MCH? *MCI 52: Message not found. |
?MCR?
?MCR 52 |
*MCR?: Read single message: ?MCR &message-nr (without #)
*MCR 52-h: from KM4LLN-7 on 2023-04-20 14:45:30Z path APWW11,KJ4ERJ-15*,TCPIP*,qAS,KJ4ERJ-15 *MCR 52-m: N:HOTG Greetings from Grovetown, GA! (*3-08:27:55) *MCR 52: Call not registered. Query ?MCH? *MCR 52: Message not found. |
?MCD?
?MCD 9 ?MCD all |
*MCD?: Delete single / all message(s): ?MCD &message-nr (without #), ?MCD ALL
*MCD 9: Delete of a single message was successful. *MCI 9: Call not registered. Query ?MCH? *MCI 9: Message not found. *MCD ALL: Delete of all messages was successful. *MCD ALL: Delete of all messages was NOT successful. |
?MCER?
?MCER aa@bb.cc |
*MCER?: E-mail: register address.
*MCER: E-Mail registration was successful. *MCER: E-Mail registration was NOT successful. *MCER: Call not registered. Query ?MCH? |
?MCEL?
?MCEL |
*MCEL?: E-mail: list registered address
*MCEL: E-Mail registered: aa@bb.cc *MCEL: Call not registered. Query ?MCH? |
?MCES?
?MCES |
*MCES?: E-mail: send message list. Address has to be registered before.
*MCES: E-Mail generated and sent. *MCES: No e-mail address registered. Query ?MCER? *MCES: Call not registered. Query ?MCH? Sample E-mail: |
HRoT / MQTT Broker HB9BL-5
MQTT Message Queuing Telemetry Transport - ist für Machine-to-Machine Kommunikation gedacht und wird hauptsächlich für Telemetry-Data verwendet.
Diese Machines müssen nichts voneinander wissen. Die Kommunikation erfolgt über einen Broker.
Beispiel: Machine1 'abonniert' (subscribe) beim BrokerX ein bestimmtes 'Thema' (topic). Machine2 'veröffentlicht' (publish) Daten zu diesem Topic beim BrokerX. BrokerX sendet diese Daten (message) an alle Subscriber dieses Topics. Der Publisher weiss nicht, wer die Subscriber sind und umgekehrt. Der Broker speichert keine Messages (Ausnahmen, siehe Beschreibung in den Links) sondern liefert diese sofort aus. Mehr dazu hier: MQTT in 7 Minuten einfach erklärt und hier: MQTT Essentials. Topics können hierarchisch aufgebaut werden: home/eg/zimmer1/temperatur=12C home/eg/zimmer1/lichtschalter=on Topics können mit Wildcards subscribed werden: home/eg/zimmer1/+: Subscription aller Untertopics + Daten von 'home/eg/zimmer1' HRoT MQTT-Clients kommunizieren via TCP/IP mit dem MQTT-Broker. HRoT fungiert als Gateway zwischen APRS-Packets auf der einen und einem MQTT-Broker auf der anderen Seite. HRoT hat einen MQTT-Client eingebaut. In APRS wird das Packet-Format 'Messages' (APRS Data Type Identifier ":") verwendet. Als Addressee wird im vorliegenden Fall der Broker HB9BL-5 verwendet. Der Message-Text enthält die Daten. Beispiele: HB9FS-5>APMQ01,WIDE1-1::HB9BL-5 :sub:birch/temperature (HB9FS-5 subscribes die Temperatur vom Birch) HB9EYZ-7>APMQ01,WIDE1-1::HB9BL-5 :sub:birch/temperature (HB9EYZ-7 subscribes die Temperatur vom Birch) HB9BL-1>APMQ01,WIDE1-1::HB9BL-5 :pub:birch/temperature=15.7C (HB9BL-1 publishes die Temperatur) HB9BL-5>APMQ01,WIDE1-1::HB9FS-5 :top:birch/temperature=15.7C (HB9BL-5 sendet die Temperatur an HB9FS-5) HB9BL-5>APMQ01,WIDE1-1::HB9EYZ-7 :top:birch/temperature=15.7C (HB9BL-5 sendet die Temperatur an HB9EYZ-7) HB9EYZ-7>APMQ01,WIDE1-1::HB9BL-5 :uns:birch/temperature (HB9EYZ-7 unsubscribes die Temperatur vom Birch) HRoT hat auf der APRS-Seite nicht alle MQTT Features implementiert:
|
Commands entsprechen den HRoT Spezifikationen. Die Commands "pub", "sub" und "uns" reichen aus, den Broker zu verwenden. Ein "connect" ist nicht notwendig.
Command | Beschreibung / Output |
sub
sub:topic1/topic2 |
Subscribe eines Topics. Das Abo bleibt bis zu einem "uns"-Command erhalten.
*sub: done - topic1/topic2 |
uns
uns:topic1/topic2 |
Un-Subscribe eines Topics. Das Abo wird aufgelöst.
*uns: done - topic1/topic2 |
pub
pub:topic1/topic2=4711 |
Publish eines Topics. Der Boker löst für alle Subscriptions des Topics eine top-Message aus.
*pub: done - topic1/topic2=4711 |
top
(wird vom Broker generiert) |
top:topic1/topic2=4711
Die top-Message (Topic) wird durch eine pub-Message ausgelöst. Sie wird an alle Subscribers gesendet, welche das Topic abonniert haben. |
sub/pub/top |
Published via ESP32 + LORA: |
Queries erweitern die HRoT Spezifikationen und werden vorzugsweise ab einem APRS-Client abgesetzt.
Query | Output |
?sub? | *sub?: subscribe a topic |
?uns? | *uns?: un-subscribe a topic |
?pub? | *pub?: Publish a topic |
?sublist? |
*sublist?: list of all my subscriptions
|
Verwendung des Brokers HB9BL-5