Python Server für ZusiDisplay

Die Anzeigesoftware von Jens Haupert.

Moderator: Jens Haupert

Antworten
Nachricht
Autor
zweann
Beiträge: 6
Registriert: 14.05.2017 18:10:47

Python Server für ZusiDisplay

#1 Beitrag von zweann »

Liebe Community,

erstmal vielen Dank für die Aufnahme!

Zu meinem Anliegen:
Ich würde gern ZusiDisplay mit einem Python-Skript ansteuern, d.h. ich möchte Daten wie z.B. die aktuelle Uhrzeit und Geschwindigkeit per TCP an ZusiDisplay senden. Allerdings habe ich nicht so ganz verstanden wie die Daten aufgebaut sein müssen, damit ZusiDisplay sie versteht.
Kann mir da jemand konkret helfen?

Grüße
Sven

Benutzeravatar
Jens Haupert
Beiträge: 4911
Registriert: 23.03.2004 14:44:34
Aktuelle Projekte: http://www.zusidisplay.de
Wohnort: Berlin
Kontaktdaten:

Re: Python Server für ZusiDisplay

#2 Beitrag von Jens Haupert »

Hallo Sven,

im Zusi3-Handbuch im Kapitel 11.3 (ab Seite 652) wird das genutzte Protokoll beschrieben.

Viele Grüße
Jens

jonathanp
Beiträge: 284
Registriert: 01.06.2015 14:11:25
Aktuelle Projekte: http://www.zusidatenbank.de/
Wohnort: BW Schöneweide

Re: Python Server für ZusiDisplay

#3 Beitrag von jonathanp »

Das Datenformat ist kein Geheimnis. Die Zusi 3 Dokumentation beschreibt das TCP-Protokoll und hat detaillierte Beispiele. Darüber hinaus können Sie mit dem Programm "TCPDemoOutput" genau die Daten sehen, die Zusi überträgt.

Allerdings, ist das Datum und die Zeit ein bisschen komisch. Ich berechne es auf C++ so:

Code: Alles auswählen

//Digital Time
time_t epoch = time(NULL);
struct tm buf;
localtime_s(&buf, &epoch);
data = new zusi::FloatFsDataItem(zusi::Fs_UhrzeitDigital(0x23), (buf.tm_hour * 3600 + buf.tm_min * 60 + buf.tm_sec) * (1.0f / 86400));

//Date
int daysSinceEpoch = static_cast<int>((epoch / (60 * 60 * 24)) + 25569);
data = new zusi::FloatFsDataItem(zusi::Fs_Datum(0x4B), static_cast<float>(daysSinceEpoch));
Leider ist die Arbeit mit binären Protokollen nicht so einfach in Python wie in C/C++.
Zuletzt geändert von jonathanp am 14.05.2017 20:27:28, insgesamt 1-mal geändert.
Autor - Zusi 3 C++ Client, zusidatenbank.de - Das Zusi3 Addon-Datenbank

zweann
Beiträge: 6
Registriert: 14.05.2017 18:10:47

Re: Python Server für ZusiDisplay

#4 Beitrag von zweann »

Hallo Jens,

ich habe leider nur Zusidisplay und den TCP-Server zur Hand, da ich das ganze mit dem Trainsimulator verarbeiten möchte.

Viele Grüße
Sven

zweann
Beiträge: 6
Registriert: 14.05.2017 18:10:47

Re: Python Server für ZusiDisplay

#5 Beitrag von zweann »

Hi Jens,

ich hab mich mal durch die TCP Doku von Zusi2 durchgewühlt und habe den Aufbau der Daten gefunden.
Vielen Dank für den Hinweis!

Benutzeravatar
F. Schn.
Beiträge: 6630
Registriert: 24.10.2011 18:58:26

Re: Python Server für ZusiDisplay

#6 Beitrag von F. Schn. »

Im Grundsatz findest du in den verschiedenen Zweigen von https://github.com/FSchn/ZusiTCP.NET/tr ... asterTest1" target="_blank auch Zusi-TCP-Master (für .Net), die du vielleicht auf deine Programmiersprache übertragen könntest. (Oder gibt es vielleicht sogar etwas, mit dem man .Net aus Python nutzen kann?)

Einen ähnlichen Fall gab es auch schon mal hier: https://forum.zusi.de/viewtopic.php?f=53&t=12087" target="_blank Der dürfte aber keine so ideale Vorgehensweise sein, wenn es auch anderst geht.
Zuletzt geändert von F. Schn. am 17.05.2017 17:49:16, insgesamt 1-mal geändert.
Diese Signatur möchte folgendes bekannter machen: ZusiWiki · ZusiSK: Streckenprojekte · YouTube: Objektbau für Zusi · euirc: Zusi-Chat

Bernhard
Beiträge: 22
Registriert: 11.09.2009 15:44:19

Re: Python Server für ZusiDisplay

#7 Beitrag von Bernhard »

Für Zusi 2 habe ich vor vielen Jahren Server und Client in Python entwickelt, deren Architektur in groben Zügen hier nachzulesen ist. Leider hat man für das Datenformat von Zusi 3 statt auf eine etablierte Serialisierungsmethode auf eine Eigenentwicklung gesetzt, die noch dazu aufgrund des Verzichts auf ein herkömmliches Längenpräfix etwas mühsam zu parsen ist. Insbesondere für Zusi 3 kann ich daher die Bibliothek construct empfehlen, die einen deklarativen Parser für Binärdaten implementiert. Streng der Nomenklatur in Kapitel 11.3.1 des Handbuchs folgend, lässt sich das Grundgerüst des Protokolls etwa folgendermaßen beschreiben:

Code: Alles auswählen

attribute = Struct(
    'PACKET_LENGTH' / Int32ul,
    'ID' / Int16ul,
    'DATA' / Bytes(this.PACKET_LENGTH - 2),
)

node = Struct(
    'PACKET_LENGTH' / Int32ul, Check(this.PACKET_LENGTH == 0),
    'ID' / Int16ul,
    'ATTRIBUTES' / GreedyRange(attribute),
    'NODES' / GreedyRange(LazyBound(lambda ctx: node)),
    'END' / Const(b'\xFF\xFF\xFF\xFF'),
)
Eine praktische Anwendung auf den exemplarischen HELLO-Befehl aus Kapitel 11.3.4:

Code: Alles auswählen

HELLO = """
00 00 00 00
01 00

    00 00 00 00
    01 00

        04 00 00 00
        01 00
        02 00

        04 00 00 00
        02 00
        02 00

        0A 00 00 00
        03 00
        46 61 68 72 70 75 6C 74

        05 00 00 00
        04 00
        32 2E 30

    FF FF FF FF

FF FF FF FF
"""

def a2b(hexstr):
    return binascii.a2b_hex(''.join(hexstr.split()))

print(node.parse(a2b(HELLO))))
Die Ausgabe:

Code: Alles auswählen

Container: 
    PACKET_LENGTH = 0
    ID = 1
    ATTRIBUTES = ListContainer: 
    NODES = ListContainer: 
        Container: 
            PACKET_LENGTH = 0
            ID = 1
            ATTRIBUTES = ListContainer: 
                Container: 
                    PACKET_LENGTH = 4
                    ID = 1
                    DATA = \x02\x00 (total 2)
                Container: 
                    PACKET_LENGTH = 4
                    ID = 2
                    DATA = \x02\x00 (total 2)
                Container: 
                    PACKET_LENGTH = 10
                    ID = 3
                    DATA = Fahrpult (total 8)
                Container: 
                    PACKET_LENGTH = 5
                    ID = 4
                    DATA = 2.0 (total 3)
            NODES = ListContainer: 
            END = \xff\xff\xff\xff (total 4)
    END = \xff\xff\xff\xff (total 4)
Container und ListContainer sind Unterklassen von dict beziehungsweise list und können daher nach allen Regeln der Kunst auseinandergenommen werden.

Ausgehend von diesem sehr einfachen Beispiel sind einige Erweiterungen denkbar:
  • Natürlich gibt es bei der Definition des Datenformats noch Verbesserungspotential. Das beginnt bei der überflüssigen Namensvergabe für den konstanten String '\xFF\xFF\xFF\xFF' und geht bis zur Abbildung der strukturell nicht unähnlichen Attribute und Knoten in einem einzigen Konstrukt mittels IfThenElse.
  • Mit Hilfe eines Adapters kann das Ergebnis von node.parse in eine noch pythoneskere Datenstruktur oder sogar eine völlig eigene Objekthierarchie konvertiert werden.
  • GreedyRange(node).parse_stream liest so viele komplette Knoten wie möglich aus dem übergebenen Datenstrom ein und kann so perfekt mit Datenblöcken unbekannter Länge umgehen, wie sie typischerweise beim Lesen von Sockets vorkommen.
  • Das deklarativ definierte Datenformat eignet sich nicht nur zum Deserialisieren sondern auch zum Serialisieren von Befehlen. Aus einer abstrakten Datenstruktur kann durch Aufruf von node.build ohne zusätzlichen Code die entsprechende Binärrepräsentation generiert und danach auf die Reise geschickt werden.
  • Noch völlig außer Acht gelassen wurde die korrekte Interpretation der Attribut-Nutzdaten, die bis dato nur als scheinbar bedeutungslose Folgen von Bytes verarbeitet werden. Eine Nachrichten-Typhierarchie, deren Klassen die detaillierten Informationen der Kapitel 11.3.2 und 11.3.3 kapseln, ist die übliche Herangehensweise, aber eine sinnvolle Lösung dieses Problems sollte vom konkreten Anwendungsfall abhängen.

Benutzeravatar
Michael Skupin
Beiträge: 196
Registriert: 01.09.2015 23:35:28
Aktuelle Projekte: Team Süd Strecke Augsburg - Donauwörth
Wohnort: Schmiechen

Re: Python Server für ZusiDisplay

#8 Beitrag von Michael Skupin »

Hallo Bernhard,

genau danach habe ich auch gesucht, danke für den Tip.


Michael
Alles Wissenwertes und Info´s gibt es auf unserm Blog:

http://www.zusi-team-sued.de

Unsere original Strecken( Bau )Objekte:

https://gallerie.zusi-team-sued.de/index.php

Das Team freut sich auf euren Besuch

Antworten