Kommunikation zwischen Python und virtueller kissnetd-Schnittstelle

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
Ray
User
Beiträge: 4
Registriert: Samstag 1. Juli 2023, 09:14

Hallo Community,

ich habe einen Raspberry Pi 3 B+ und habe auch schon einige recht simple Programme erstellen können,
die Zugriff auf die GPIO-Schnittstelle haben. LEDs blinken, Eingänge wie Taster funktionieren auch tadellos.

Der Pi soll dann an einem anderen Standort arbeiten (mit Sensoren etc.), den ich dann gerne fernsteuern würde
mittels Funk (Packet Radio). Wem Packet Radio nichts sagt, kann gern dazu einen Beitrag auf Wikipedia lesen. :wink:

Die installierte Packet Radio Software TheNetNode (TNN) läuft super mit TNC und Funkgerät.

Der Grundgedanke ist, 2 kissnetd-Schnittstellen zu erzeugen. Die Erste (/dev/pts/1) soll mit TNN verbunden werden, die
Zweite (/dev/pts/2) dann mit dem Python-Programm. TNN nimmt die erste Schnittstelle problemlos an.

Ich habe schon Einiges mit Hilfe von ChatGPT probiert, auf die zweite kissnetd-Schnittstelle zuzugreifen, allerdings
hat davon nichts wirklich geholfen.

Und nun zur Frage: Wie kann ich mittels Python auf die zweite Schnittstelle zugreifen?
Das Programm soll ein Rufzeichen haben, welches ich über TNN connecten kann.

Nach erfolgreichem Connect sollen eben Kommandos gesendet werden und das Python-Programm wertet je nach Kommando die Daten aus und
sendet diese zurück.


Ich hoffe, ihr könnt mir irgendwie weiterhelfen.
Bin auch noch recht neu in der Python-Welt und lerne auch gerne dazu. :)

Vielen Dank schonmal im Voraus ...
__deets__
User
Beiträge: 14544
Registriert: Mittwoch 14. Oktober 2015, 14:29

Da ganze Feld ist ein bisschen zu komplex, als das man sich da mal so eben einarbeitet. Aber die /dev/pts/X sind pseudo-terminals, die mit pyserial zu öffnen und dann lesbar sein sollten. Allgemein hilft es auch, zu zeigen, was probiert wurde, und was konkret nicht geht. Also code & Fehlermeldungen, bitte in den Code Tags gesetzt, damit man das lesen kann.
Ray
User
Beiträge: 4
Registriert: Samstag 1. Juli 2023, 09:14

Also ich habe dies grundlegend erstmal mit diesem Code probiert, allerdings werden keine Daten empfangen.

Code: Alles auswählen

import serial

# Konfiguration
tnc_callsign = "PHYTH0N-0"  # Dein Rufzeichen
virtual_device = "/dev/pts/2"  # Pfad zum virtuellen KISS-Gerät

# Serielle Verbindung zum virtuellen KISS-Gerät herstellen
ser = serial.Serial(port=virtual_device, baudrate=1200, timeout=1)

# Rufzeichen für das KISS-Gerät senden
callsign_command = f"MYCALL {tnc_callsign}\n"
ser.write(callsign_command.encode())

# KISS-Frame senden
frame_to_send = b"\x00\x01\x02\x03"  # Beispielhaftes Frame
ser.write(frame_to_send)

# KISS-Frames empfangen
while True:
    received_data = ser.read(1024)
    if received_data:
        print(received_data)



# Serielle Verbindung schließen
ser.close()

Danke im übrigen erstmal für deine schnelle Antwort. :)
Ray
User
Beiträge: 4
Registriert: Samstag 1. Juli 2023, 09:14

Ich habe gerade nochmal getestet, ser.close() rauszunehmen und ich empfange Daten, wenn ich eine Bake sende.
Aber vieles mit x[..] etc.

Wie realisiere ich aber einen Verbindungsaufbau zu Station PHYTH0N, so dass beide Stationen miteinander kommunizieren können?
__deets__
User
Beiträge: 14544
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich kenne die KISS-Frame-Struktur bisher nicht, aber laut https://www.ax25.net/kiss.aspx zb behauptet, ein Frame muss ein FEND zu Beginn und zum Ende kommen. Und das fehlt aus meiner Sicht hier. Aber am Ende ist das hier nicht ein Python-Problem, denn das sieht soweit okish. aus. Sondern eben tiefere Kenntnisse der unterliegenden Protokolle und Software. Die habe ich nicht, und ob die jemand anders hier hat, ist fraglich. Da wuerde ich wenn eher in einem spezialisierten Forum fragen. Wenn es dann Fragen zur Verheiratung von serieller Kommunikation mit den GPIOs etc geht, kann man dir hier weiterhelfen.
Ray
User
Beiträge: 4
Registriert: Samstag 1. Juli 2023, 09:14

Ich danke dir erstmal für deine Antwort.
Ja es ist durchaus ein komplexes Thema, auch als ich deinen Link angesehen habe.
Es beansprucht mehr Wissen über die AX25 Kommunikation.

Aber ohne ser.close() funktioniert es erstmal soweit.
Kann ich mich nur noch durchtesten :D
Benutzeravatar
__blackjack__
User
Beiträge: 13116
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Ray: Ein paar allgemeine Anmerkungen zum Quelltext: Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.

Der Pfad zur Gerätedatei und das Rufzeichen sind ja eher Konstanten — da schreibt man die Namen KOMPLETT_GROSS. Siehe auch den Style Guide for Python Code.

Kommentare sollen dem Leser einen Mehrwert über den Code geben. Faustregel: Kommentare beschreiben nicht *was* der Code macht, denn das steht da bereits als Code, sondern warum er das macht. Sofern das nicht offensichtlich ist. Offensichtlich ist in aller Regel auch was in der Dokumentation von Python und den verwendeten Bibliotheken steht.

Wenn es geht, macht es auch Sinn Informationen aus Kommentaren in den Code zu verschieben. Beispielsweise durch Namensgebung. Also für eine Verbindung (Kommentar) nicht so einen komischen kryptischen Namen wie `ser` sondern `connection` verwenden.

`Serial`-Objekte sind Kontextmanager, die sollte man mit der ``with``-Anweisung verwenden. Dann braucht man auch kein ”manuelles” `close()`.

Wobei ich bei dem gezeigten Code nicht verstehe wie das weglassen des `close()`-Aufrufs irgend etwas am Laufzeitverhalten ändern kann, denn da steht ja eine Endlosschleife davor. Der Programmfluss kommt gar nicht bis zu dem `close()`-Aufruf.

Das mit dem Empfangspuffer der hoffentlich gross genug ist, finde ich ja nicht so schön, jedenfalls nicht ohne Dokumentation warum 1K auf jeden Fall gross genug ist um nichts kaputt zu machen.

Code: Alles auswählen

#!/usr/bin/env python3
from serial import Serial

TNC_CALLSIGN = "PHYTH0N-0"
VIRTUAL_KISS_DEVICE = "/dev/pts/2"


def main():
    with Serial(
        port=VIRTUAL_KISS_DEVICE, baudrate=1200, timeout=1
    ) as connection:

        connection.write(f"MYCALL {TNC_CALLSIGN}\n".encode())
        #
        # KISS-Frame senden.
        #
        connection.write(b"\x00\x01\x02\x03")  # Beispielhafter Frame.
        #
        # KISS-Frames empfangen
        #
        while True:
            received_data = connection.read(1024)
            if received_data:
                print(received_data)


if __name__ == "__main__":
    main()
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten