Daten aus CBCharacteristic auslesen

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Daten aus CBCharacteristic auslesen

    Liebe Community,

    kennt sich schon jemand von euch in Swift so gut aus, dass er mir erklären kann, wie ich folgenden Objective-C Code in Swift schreiben kann?

    Quellcode

    1. NSData *data = [characteristic value];
    2. const uint8_t *reportData = [data bytes];
    3. uint16_t bpm = 0;
    4. if ((reportData[0] & 0x01) == 0) {
    5. // Retrieve the BPM value for the Heart Rate Monitor
    6. bpm = reportData[1];
    7. }
    8. else {
    9. bpm = CFSwapInt16LittleToHost(*(uint16_t *)(&reportData[1]));
    10. }
    Alles anzeigen

    Ich wäre euch wahnsinnig dankbar, denn bis auf das Auslesen der Daten von Characteristics hab ich bis jetzt alles problemlos hinbekommen (Suchen, Verbinden, etc.). Als absoluter Anfänger im Bereich Bluetooth bin ich schon recht stolz darauf. :)

    Mit freundlichen Grüßen

    TheFuriousLion
  • Wahrscheinlich musst Du in Swift den Pointer bytes erst in ein Array von UInt8 packen. Das Auslesen des 16-Little-Endian-Wertes und dessen Konvertierung in Big-Endian musst Du wahrscheinlich selber machen. Ins Blaue:

    Quellcode

    1. ​bpm = theArray[1] + (theArray[2] << 8);

    (BTW: Das entsprechende C-Statement in Objective-C halte ich, gelinde gesagt, für gewagt.)

    Warum lässt Du es nicht in Objective-C? Du kannst Klassen aus beiden Sprachen doch in einem Projekt mischen. Beispielsweise kannst Du auch eine Kategorie für NSData anlegen, die diese Methode enthält.
    „Meine Komplikation hatte eine Komplikation.“
  • beage schrieb:

    Aber solltest Du Dir nicht vllt. mal selber dazu Gedanken machen, als den Code 1:1 von Ray Wenderlich zu kopieren?

    Als Übungszweck doch gar nicht mal so eine schlechte Idee. Davon ausgehend, dass Herr Wunderlich optimal Objective-C programmieren kann, ist es doch dann nur sinnvoll, die gleichen Konstrukte zu verwenden nur dass man sie in eine andere Sprache portiert. So lernt man auch was, man kann dann zwar nicht die die Regeln namentlich benennen, aber man hat sie dann auch verinnerlicht.
    Wenn man da gleich draufhaut, demotiviert man.

    Das Spiel 2048/4096 wurde auch in Swift umgesetzt. Ist das schlecht? Nein, ich finde das gut. Und wenn man privat irgendwas nachprogrammiert, dann darf man das auch mal feiern. In dem Sinne: Weiter so.

    Und keine Ahnung, um was es da geht, aber wenn man eine Api benutzt oder in dem Fall mal was schnell frickeln/testen will,
    dann muss man nicht das Rad neu erfinden. Denn die Lösung wird vermutlich genau die sein, die Herr Wunderlich verwendet. Und damit geht es einfach darum, etwas equivalentes in Swift zu finden
    Das eigene Gehirnschmalz kann man dann besser für andere Dinge verwenden.
    (Und ja, manchmal muss man ein Rad neu erfinden, weil das alte einfach „scheisse“ ist)
  • macmoonshine schrieb:

    Aber Array<UInt8> sollte gehen. Ist wahrscheinlich auch kein Cast sondern im günstigsten Fall ein wrappen oder eine Kopie.
    Funktioniert leider auch nicht. Ich bekomme für beide Zeilen den selben Error: Cannot convert the expression's type 'Array<UInt8>' to type '$T3' bzw Cannot convert the expression's type 'Array<UInt8>' to type '$T3'

    Quellcode

    1. let reportData = characteristic.value.bytes as Array<UInt8>
    2. let reportData = characteristic.value.bytes as UInt8[]

    Es würde mich ehrlich gesagt auch etwas verwundern, da Array<UInt8> und UInt8[] im Hintergrund doch das Gleiche ist.
  • TheFuriousLion schrieb:

    macmoonshine schrieb:

    Aber Array<UInt8> sollte gehen. Ist wahrscheinlich auch kein Cast sondern im günstigsten Fall ein wrappen oder eine Kopie.
    Funktioniert leider auch nicht. Ich bekomme für beide Zeilen den selben Error: Cannot convert the expression's type 'Array<UInt8>' to type '$T3' bzw Cannot convert the expression's type 'Array<UInt8>' to type '$T3'

    Quellcode

    1. let reportData = characteristic.value.bytes as Array<UInt8>
    2. let reportData = characteristic.value.bytes as UInt8[]

    Es würde mich ehrlich gesagt auch etwas verwundern, da Array<UInt8> und UInt8[] im Hintergrund doch das Gleiche ist.


    macht man das nicht so in der art?

    Quellcode

    1. let bytes = UnsafeArray<UInt8>(start:data.bytes, length:data.length)
  • Also, eine funktionierende Lösung sehe zum Beispiel so aus:

    Quellcode

    1. let data = characteristic.value(); // die Zeile könnte noch anpassungsbedürftig sein
    2. let bytes = data.bytes
    3. let reportData = UnsafePointer<UInt8>(bytes)
    4. var bpm: UInt16 = 0
    5. if reportData[0] & 0x01 == 0 {
    6. bpm = UInt16(reportData[1]) << 8 + UInt16(reportData[2])
    7. }
    8. else {
    9. bpm = UInt16(reportData[1]) + UInt16(reportData[2]) << 8
    10. }
    Alles anzeigen
  • Du bist ein Wahnsinn, Michael! Danke! :)

    Durch deine Antwort hab ich es geschafft:

    Quellcode

    1. if let data = characteristic.value {
    2. let bytes = data.bytes
    3. let reportData = UnsafePointer<UInt8>(bytes)
    4. var bpm: UInt16 = 0
    5. if reportData[0] & 0x01 == 0 {
    6. bpm = UInt16(reportData[1])
    7. } else {
    8. bpm = CFSwapInt16LittleToHost(UInt16(reportData[1]))
    9. }
    10. }

    Musste deinen Code etwas abändern, da ich sonst 18.000 bpm gehabt hätte, was glaub ich nicht gesund wäre.

    Jetzt wo's funktioniert, würd ich's auch gerne verstehen. Aber ich verstehe nur Bahnhof wenn ich das & 0x01 sehe. Viel schlimmer ist der << Operator. Außerdem dieser UnsafePointer, ich dache in Swift gibt es keine Pointer mehr.

    Mag sich irgendwer die Mühe machen und mir obiges Beispiel erklären? Ich wäre demjenigen sehr dankbar.
  • Michael schrieb:

    Also, eine funktionierende Lösung sehe zum Beispiel so aus:

    Quellcode

    1. let data = characteristic.value(); // die Zeile könnte noch anpassungsbedürftig sein
    2. let bytes = data.bytes
    3. let reportData = UnsafePointer<UInt8>(bytes)
    4. var bpm: UInt16 = 0
    5. if reportData[0] & 0x01 == 0 {
    6. bpm = UInt16(reportData[1]) << 8 + UInt16(reportData[2])
    7. }
    8. else {
    9. bpm = UInt16(reportData[1]) + UInt16(reportData[2]) << 8
    10. }
    Alles anzeigen


    im ersten falle (== 0) nix schieben und nix addieren denn es wird nur der der erste wert verwendet: reportData[1]