0

I want to pass bytes data to bluetooth service in a format that is expected by bluetooth firmware.

Expected data structure in c struct are:

typedef enum {
        CMD_TX_INFO = 0,
        CMD_DATA_REQ_START,
        CMD_DATA_REQ_END,
        CMD_DATA_REQ
} ble_cmd_type_t;

typedef struct ble_data_info_s
{
        uint32_t data_size_bytes;
        uint32_t info;
} ble_data_info_t;

typedef PACKED ( struct ble_cmd_info
{
        ble_cmd_type_t  cmd_type;
        ble_data_info_t info;
        uint8_t len;
        uint8_t data[10];
}) ble_cmd_data_t;

I have converted the this to swift struct as follows:

enum BLECmdType : UInt8{
    case CMD_TX_INFO = 0
    case CMD_DATA_REQ_START
    case CMD_DATA_REQ_END
    case CMD_DATA_REQ
}

struct BLEDataInfo
{
    let dataSizeBytes: UInt32
    let info: UInt32
}

struct BLECmdData
{
    let cmdType:BLECmdType 
    let info:BLEDataInfo
    let len:UInt8
    let data: Array<UInt8>?
}

Then i convert the swit struct object into bytes like this, i am not sure if this approach is correct? I am not getting the bytes in correct expected format:

var command = BLECmdData(cmdType:BLECmdType.CMD_DATA_REQ_START, 
    info: BLEDataInfo(dataSizeBytes: 100000, info: 10), 
    len: 1, 
    data: [1,2,3,4,5,6,7,8,9,10])

let bleData = Data(bytes: &command , count: MemoryLayout<BLECmdData>.stride)
        

Firstly is it possible to print the bytes generated for bleData object in string format so i can debug and see?

Secondly the bytes sent to BLE device are:

Bytes:
01 00 00 00 A0 86 01 00
E5 73 E0 98 0A 00 00 00
70 C5 CA 80

Firmware engineer mentioned, data should start with following:

Bytes:
01 00 A0 86 01 00
E5 73 E0 98

I am not sure if my approach to convert c struct to swift here is correct.

Looking forward for your reply.

Thanks

Rahul
  • 300
  • 2
  • 12
  • 1
    https://stackoverflow.com/questions/39075043/how-to-convert-data-to-hex-string-in-swift – Larme Jun 29 '20 at 15:04
  • you have to know about endianness, alignment, padding ... Let me explain in the answer – nghiahoang Jun 29 '20 at 15:32
  • I know of no way to automatically convert a Swift struct to bytes in a way that will be compatible with a C struct. You have to manually enumerate the struct's fields and covert each one individually to bytes in the desired format – Max Jun 29 '20 at 15:43
  • I would have kept the C struct. The "match" between Swift Struct & C Struct isn't certain to be the same, no? – Larme Jun 29 '20 at 15:54

2 Answers2

1
  1. the result of the line let bleData = Data(bytes: &command , count: MemoryLayout<BLECmdData>.stride)

it depends on what cpu architecture the programming you're running on. (32bits vs 64 bits, big-endian vs little-endian).

  1. you have to ask Firmware engineer about the protocol to communicate with their devices, then you will encode the data as the format specified in the protocol. It isn't important that you store the data in a class/struct/enum etc..., the important thing is how the data is encoded.
nghiahoang
  • 538
  • 4
  • 10
0

I found a way to successfully push the data in correct format:

Set the values:

var cmdTypeCopy:UInt8 = BLECmdType.CMD_DATA_REQ_START
var imageInfo = BLEDataInfo(dataSizeBytes: 100000, info: 10)
var cmdLenCopy = 10
var cmdDataCopy:Array<UInt8> = [1,2,3,4,5,6,7,8,9,10]

Create Data:

var cmdTypeData = Data(bytes: &cmdTypeCopy, count: MemoryLayout<UInt8>.stride)
var imageInfoData = Data(bytes: &imageInfo, count: MemoryLayout<BLEImageInfo>.stride)
var cmdLenData = Data(bytes: &cmdLenCopy, count: MemoryLayout<UInt8>.stride)
var cmdDataData = Data(bytes: &cmdDataCopy, count: 10)

Then append one by one:

cmdTypeData.append(imageInfoData)
cmdTypeData.append(cmdLenData)
cmdTypeData.append(cmdDataData)

This worked perfectly and firmware got the data in correct format.

Rahul
  • 300
  • 2
  • 12