Einfaches binäres Protokoll



  • cooky451 schrieb:

    wxSkip schrieb:

    Wozu braucht ihr Anfangs- und End-Blöcke (vor allem wozu den End-Block), wenn die Anzahl der Bytes für die Zahlen schon vorher durchgegeben wurde? (Entspricht im Prinzip der Anmerkung von Ethon)

    Wenn man zwei Blöcke hintereinander hat, wirds knifflig. 😉

    @Ethon
    So kann man in einem Block ja nur Daten des gleichen Typs verschicken.

    Gut, ob das problematisch ist hängt aber vom Typ der Daten ab.
    Floats kann man ja zb problemlos als Integer codieren (was imo sogar anzuraten wäre, aufgrund von Differenzen in den floating-point Codierungen verschiedener CPUs).

    Woher weiß man dann, wann der header losgeht, ohne einen speziellen code dafür zu benutzen, was die schon erwähnten Probleme bereitet?

    Das ist ein Argument. Dann würde ich mit einer möglichst großen MagicNumber arbeiten. Ein

    0xDEADDEADDEADDEAD

    sollte da schon sehr zuverlässig sein. 😉



  • Q schrieb:

    Das macht das Problem doch noch schlimmer, wenn wir noch mehr Steuerzeichen verwenden.

    Hä? Hast du dir eben überhaupt meinen ganzen Beitrag durchgelesen? Ich sehe kein Problem mehr, das funktioniert so.



  • Hä? Hast du dir eben überhaupt meinen ganzen Beitrag durchgelesen? Ich sehe kein Problem mehr, das funktioniert so.

    cooky451 schrieb:

    read(b, sizeof(char))
    switch (b)
    {
    case 'a':
      beginBlock(); 
      ...
    }
    

    Jedem Buchstaben könnt ihr dann ein "Steuerzeichen" zuweisen.

    Das Problem ist, der Microkontroller sendet permanent über die serielle Schnittstelle Daten.

    Man kann also zu jedem Zeitpunkt das Kabel einstecken und Daten empfangen.
    Woher weiß man dann, wann der header losgeht, ohne einen speziellen code dafür zu benutzen, was die schon erwähnten Probleme bereitet?

    Funktioniert das dann immer noch?
    Wenn ja, dann erklär das bitte nochmal.
    Ich denke nämlich das es das nicht tut, wenn man zu jedem beliebigen Zeitpunkt einstecken kann.
    Dann kann es nämlich sein, dass gerade eine Zahl übertragen wird. Das Bytemuster der Zahl enthält dann Steuerzeichen, die fälschlicherweise als Steuerzeichen interpretiert werden und dann hat man den Salat.

    Ethon schrieb:

    Das ist ein Argument. Dann würde ich mit einer möglichst großen MagicNumber arbeiten. Ein

    0xDEADDEADDEADDEAD

    sollte da schon sehr zuverlässig sein. 😉

    Jo sowas werd ich dann auch nehmen, falls wir keine anderen Methoden finden, ist bestimmt sicherer als 2003 oder sowas^^



  • Q schrieb:

    Funktioniert das dann immer noch?

    Klar.

    readBlock()
    {
      TYPE type = 0;
      while (type != 'e')
      {
        switch ((type = readType()))
        {
        case 'e':
          break;
        case 'f':
          readFloat();
          break;
        case 'i':
          readInt();
          break;
        default:
          throw "ALLES_KAPUTT";
          break;
        }
      }
    }
    

    Drüber liegt natürlich eine Funktion, die dann irgendwelche anderen Daten liest, bis ein 'b' kommt, dann wird diese Funktion aufgerufen. Falls eh nur solche Blocks empfangen werden, kann man das natürlich alles in eine Funktion packen etc., ist nur pseudo-Code. Allerdings sollte klar werden, dass das Programm zu jeder Zeit in einem klar definierten Zustand ist und immer weiß, worauf es warten muss bzw. was als nächstes kommt. Ich sehe kein Problem, wann die Daten übertragen werden, oder wie zerstückelt die sind, spielt eigentlich keine Rolle.



  • Ich verstehe leider nicht, warum das funktioniert.

    Ich rufe die funktion auf, der Microkontroller ist gerade dabei, eine Zahl zu senden, kein Steuercode.

    Das char, dass du einlist ist etwas, was weder 'e', noch 'f' noch 'i' ist.
    Und schon fliegt dir die exception um die Ohren.

    Vielleicht habe ich das nicht klar genug gesagt.
    Der Microkontroller sendet IMMER, auch wenn gar kein Computer angeschlossen ist.
    Zu jedem beliebigen Zeitpunkt kannst du den Stecker einstecken und Daten empfangen, aber du weißt erstmal nicht, ob das, was gerade gesendet wird eine Zahl oder ein Steuerzeichen ist.

    Falls das dennoch funktioniert, bitte ich nochmals um eine Erklärung.

    Vielen Dank für deine Hilfe.



  • Q schrieb:

    ..

    Ich dachte bis jetzt ja auch, dass man selbst etwas an den Microcontroller sendet. Natürlich dürfen keine Daten innerhalb eines Blocks verloren gehen. Das kannst du mit keinem Protokoll ausbügeln. Das Protokoll ist ja gerade dafür da, um Regeln für die Übertragung aufzustellen. So wird ja auch gar nicht garantiert, dass du überhaupt Anfangs/End Zeichen erhälst. Wie stellst du dir das vor? Wie hat das denn mit Text geklappt bis jetzt?



  • Mit text wars so, dass '\n' bedeutet, dass ein neuer block kommt, ' '(leerzeichen) heißt neue zahl und dazwischen sind die zahlen asci kodiert.
    Da die Zahlen nur aus 0-9 Punkt und e^ oder sowas bestehen und kein '\n' oder ' '(leerzeichen) enthalten, war das kein Problem.



  • Q schrieb:

    Mit text wars so, dass '\n' bedeutet, dass ein neuer block kommt, ' '(leerzeichen) heißt neue zahl und dazwischen sind die zahlen asci kodiert.
    Da die Zahlen nur aus 0-9 Punkt und e^ oder sowas bestehen und kein '\n' oder ' '(leerzeichen) enthalten, war das kein Problem.

    Aha? Microcontroler sendet die Zahl "5533", Kabel wird nach "55" eingesteckt. Oups, komplett falsche Zahl. :p

    Edit: Und wie habt ihr das mit Blockanfang gemacht? Eben war es doch noch so wichtig, an welcher Stelle die Zahl im Block steht.



  • cooky451 schrieb:

    Q schrieb:

    Mit text wars so, dass '\n' bedeutet, dass ein neuer block kommt, ' '(leerzeichen) heißt neue zahl und dazwischen sind die zahlen asci kodiert.
    Da die Zahlen nur aus 0-9 Punkt und e^ oder sowas bestehen und kein '\n' oder ' '(leerzeichen) enthalten, war das kein Problem.

    Aha? Microcontroler sendet die Zahl "5533", Kabel wird nach "55" eingesteckt. Oups, komplett falsche Zahl. :p

    Edit: Und wie habt ihr das mit Blockanfang gemacht? Eben war es doch noch so wichtig, an welcher Stelle die Zahl im Block steht.

    Na, da hätten sie doch einfach alles bis zum ersten newline verwerfen können.



  • Ein Block fängt nach \n an.

    Das mit 5533 ist auch kein Problem.
    Solange bis das erste mal \n kommt wird alles ignoriert, also kann da nichts passieren.



  • Q schrieb:

    Ein Block fängt nach \n an.

    Das mit 5533 ist auch kein Problem.
    Solange bis das erste mal \n kommt wird alles ignoriert, also kann da nichts passieren.

    Ignorieren ist also erlaubt, ok. Dann braucht man also irgendwelche Steuerzeichen, die nicht in Daten vorkommen können. "Echte" binäre Übertragung fällt somit also weg, ihr müsst euch ein Kodierverfahren einfallen lassen. Base64 würde sich z.B. anbieten. Dann könnt ihr Steuerzeichen von Daten eindeutig unterscheiden.



  • D.h. es wird immer ein char empfangen, sodass das Steuerzeichen dann aus einem char bestehen müsste? Oder werden immer ints empfangen? Oder kann man gar bei verschiedenen Bits einstecken?



  • wxSkip schrieb:

    D.h. es wird immer ein char empfangen, sodass das Steuerzeichen dann aus einem char bestehen müsste?

    Jo. Allerdings lohnt die ganze Aktion natürlich wirklich erst, wenn die ASCII Darstellung sehr teuer ist. Es ist wesentlich billiger eine "5" als String zu übertragen, als als int. Wenn die Zahlen also gar nicht so groß sind, lohnt vielleicht auch mal ein Blick auf
    http://de.wikipedia.org/wiki/LZ77



  • Base64 würde sich z.B. anbieten. Dann könnt ihr Steuerzeichen von Daten eindeutig unterscheiden.

    Was wohl schon wieder länger wäre als die ASCII-Darstellung.



  • Hm das mit der Base64 kodierung sieht ziemlich kompliziert aus...
    Aber falls es da was gutes fertiges zu gibt, würde das natürlich gehen.

    Evtl. ignorier ich das Problem auch einfach, weil die Wahrscheinlichkeit relativ gering ist, oder ich überprüf vorm senden, ob ich was problematisches sende und wenn ja, passe ich es minimal an.

    Edit: Wir haben inzwischen auch gemerkt, dass binär gar nicht soviel wengier ist als ascii und außerdem sind wir uns nicht mehr ganz sicher, ob die menge der daten das hauptproblem ist.
    Wir werden das erstmal ein wenig weiter "erforschen" und dann mal schaun, was wir tun.

    Weitere Vorschläge sind natürlich trotzdem willkommen.



  • Q schrieb:

    Edit: Wir haben inzwischen auch gemerkt, dass binär gar nicht soviel wengier ist als ascii und außerdem sind wir uns nicht mehr ganz sicher, ob die menge der daten das hauptproblem ist.
    Wir werden das erstmal ein wenig weiter "erforschen" und dann mal schaun, was wir tun.

    cooky451 schrieb:

    Jo. Allerdings lohnt die ganze Aktion natürlich wirklich erst, wenn die ASCII Darstellung sehr teuer ist. Es ist wesentlich billiger eine "5" als String zu übertragen, als als int. Wenn die Zahlen also gar nicht so groß sind, lohnt vielleicht auch mal ein Blick auf
    http://de.wikipedia.org/wiki/LZ77



  • Das LZ77 guck ich mir gleich an, aber dazu muss ich folgendes sagen:
    Ich kenne LZW und vermute, dass das so ähnlich ist.
    Da wird nach und nach ein Wörterbuch aufgebaut, was hier aber nicht praktikabel ist, weil man zu jedem Zeitpunkt sich einklinken kann.
    Außerdem muss man wenn man sich zu jedem Zeitpunkt einklinken kann trotz kompression den "Anfang" finden (der früher nach dem ersten \n los ging).
    Ich hoffe mal, dass das damit möglich ist.



  • Wenn ihr ein bisschen Rechenzeit für binäre Operationen übrig habt, könnt ihr ja auch einfach je nach Datenpaket abwechselnd eine 1 und eine 0 ins High-Bit jedes chars setzen - und die anderen 7 Bits für die Codierung nutzen. Dann nehmt ihr halt 5 chars statt 4 für eine 32-bit-Zahl und lasst die restlichen 3 Bit leer oder wenn die euch reichen, schreibt ihr dort den Typ rein (int, unsigned int, float, ...).



  • 1. Falls man das Ding zu jedem Zeitpunkt reinstecken kann und die vorherigen Daten eh egal sind, kann man die Synchronisierung auch sehr viel später machen.
    Einmal pro Sekunde, einmal pro Minute, wie auch immer.

    2. Hauptsache ist der Magic-String ist länger als jede potentielle vorkommende erlaubte Zeichenkette.
    Wenn 4 Byte für die Input-Werte erlaubt sind, dann macht doch einfach 16 Byte Magic Sequence.



  • nurf schrieb:

    2. Hauptsache ist der Magic-String ist länger als jede potentielle vorkommende erlaubte Zeichenkette.
    Wenn 4 Byte für die Input-Werte erlaubt sind, dann macht doch einfach 16 Byte Magic Sequence.

    Nö. Es könnte ja sein, dass zufällig 4 Input-Werte à 4 Bytes ankommen, die zusammen genau den Magic String ergeben. Außer, du willst nach jedem Input-Wert den Magic-String senden. Dann ist es aber mit der Ersparnis dahin.


Anmelden zum Antworten