String splitten in Verbindung zu Arduinoprojekt (Bluetooth)

Hallo zusammen,

ich habe mich wieder den zahlreichen Informationen hier im Forum bedient und habe einen Teilerfolg. Ich möchte per Bluetooth empfangene Werte auslesen. Dabei habe ich mich an diesen Beitrag gehalten: https://community-appinventor-mit-edu.ezproxy.canberra.edu.au/t/split-a-string-and-store-the-separate-snipsel/10908

Das ist meine Umsetzung (Auszug). Das Format ist aktuell wert1:wert2:wert3

Was mir nun sorgen bereitet, ist die Tatsache, dass es doch theoretisch zu Verschiebungen kommen könnte. Von der Sendrichtung App -> Arduino verwende ich folgendes Protokoll: <C:Wert1><C:Wert2><E:WertX><S:Speed1|Speed2>. Das kann ich im Arduino auch parsen. Mit AI2 gelingt es mir einfach nicht.

Ich möchte erreichen, dass ein Tag <> vollständig interpretiert wird und nicht einfach nur eine Reihenfolge wie in meiner aktuellen Implementierung. Also immer wenn ein vollständiger Tag <> vorliegt, möchte ich das innere Abfragen. z.B. mit der Listlogik wie im Screenshot.

Immer wenn ein Tag vollständig empfangen wurde: Nimm das innere des Tags. Nimm das Kommando/den Identifier vor dem ":". Wenn Kommando C dann Value = Wert1 in Label2 schreiben, wenn Kommando E dann Value = WertX in Label6. Wenn H tue nichts (ungültiger Wert / Wert nicht vereinbart), etc. So habe ich es in der Kommunikation von App nach Arduino realisiert. Das gibt mir mehr Flexibilität.

Also ich möchte erreichen, dass ich eine vollständiges Datenpaket parse. Anhand des Kommandos weiß ich dann, was ich mit dem Wert (quasi Key-Value) tun muss. Sollte mal ein Tag / Datenpaket verloren gehen wäre das egal, denn es kommt bald das nächste. Aber so erreiche ich, dass die übergebenen Werte nicht falsch verwendet weil - aus welchen Gründen auch immer - Werte nicht ankommen und somit die Reihenfolge zerstört werden würde.

1 Like

Your strings look like XML, but not quite. Real XML would make it easier, because there are blocks for that.
Anyway, instead of splitting at : you could split at <, then iterate through the list to take of the > and then make a list of dictionaries out of it by splitting at : and take the first value as key and the second as value.
It sounds like killing a flea with an elephant, but it should work.
But why could you not use something like: C:Wert1,C:Wert2,E:WertX... and can C really have 2 values?

1 Like

Thank you for your feedback! You are right and I will consider simplifying it. What is crucial is a clear assignment of a value to its purpose. I actually implemented it with reverse communication (app to Arduino) as described above because I have to provide two speeds to control my robot. It is then also possible to parse this flexibly on the Arduino. But here in AI2 I couldn't get it to work. But not a problem for the current application. I just always try to build everything as flexibly as possible. For example, I already use the blocks for Bluetooth communication in several apps. With the backpack you can easily carry them over to the new project. This means it took longer for the initial implementation but already has added value. That was my idea here too, but the effort and benefit may not be there to waste more hours with unsuccessful attempts.

This is pretty close to the implementation on the Arduino side (opposite way of communication). There I have an array with the commands index[0] = S (speed command) and the values index[1] to index[n] (e.g. index[1] = speed1 and ~[2] = speed2.

Falls für jemanden hilfreich: ich habe es jetzt wie folgt für meine Bedürfnisse gelöst (es sind auch verschiedene Möglichkeiten der Übergabe möglich, wie der Arduino-Code zeigt). Wenn ich z.B. nur H übergebe wird auch nur Label6 aktualisiert. Außerdem kann ich die Informationen einzeln übergeben oder zusammen mit "|" getrennt. Das Kommando / der Key ist jeweils Index 1 und der Wert Index 2 in der KeyValue-Liste. Der Key-Value Separator ist ein ":"

Das Arduino-Coding ist nur ein Auszug (unvollständig) und soll nur den Zusammenhang darstellen.

unsigned int _playPoints = 0;
unsigned long _playTime = 0;

char pointsDigits[5];

  sprintf(pointsDigits, "%04d", _playPoints);  //P
  sprintf(timeDigits, "%04d", _playTime);      //T

  BTserial.println((String)"P:" + pointsDigits + "|" + "S:" + testDigits);
  BTserial.println((String) "T:" + timeDigits);

  delay(1000);

Looks fine to me, except that it would e good to have another else at the end, that could catch unforsseen values, and show that using a Notifier or an extra label,

yes of course. I will implement it in my final app. the shown part is only a prototype for test purposes. there should not be any error popups interfere the usability. i think to do it in a hidden way (e.g. change a backgroundcolor of something to red or log it in a list which i can shown separatly if the process ist not running / active). but you are totally right with your suggestion :slight_smile: