2017-08-30 121 views
0

我想通過BLE將加速度計值發送到使用北歐nRF52的iOS應用程序。該應用完全符合標準BLE服務(HeartRate測量,溫度計等),但不適用於我嘗試定義自定義BLE加速度計服務。在定義UUID和事物時,有什麼我需要專門做的嗎?任何幫助將不勝感激,謝謝。BLE加速度計

下面是我自定義的Accelerometer類,以及main.cpp上傳到下面的nRF52。

#ifndef __BLE_ACCELEROMETER_SERVICE__ 
#define __BLE_ACCELEROMETER_SERVICE__ 

#include "ble/BLE.h" 

#define UUID_ACCELEROMETER_SERVICE "00000000-0000-1000-7450-BE2E44B06B00" 

#define UUID_X_CHARACTERISTIC  "00000000-0000-1000-7450-BE2E44B06B01" 
#define UUID_Y_CHARACTERISTIC  "00000000-0000-1000-7450-BE2E44B06B02" 
#define UUID_Z_CHARACTERISTIC  "00000000-0000-1000-7450-BE2E44B06B03" 

/** 
* @class AccelerometerService 
* @brief BLE Custom Accelerometer Service. This provides the x, y and z values of the SEEED 101020051 Grove accelerometer connected to the Nordic nRF52 DK. 
*/ 

class AccelerometerService 
{ 
public: 

    /** 
    * @brief Add the Accelerometer Service to an existing BLE object, initialize with values for x, y and z readings, represented as doubles. 
    * @param _ble Reference to the BLE device 
    * @param _x Initial value for the x axis 
    * @param _y Initial value for the y axis 
    * @param _z Initial value for the z axis 
    */ 
    AccelerometerService(BLE &_ble, double _x = 0, double _y = 0, double _z = 0) : 
    ble(_ble), 
    x(_x), 
    y(_y), 
    z(_z), 
    xAngleCharacteristic(UUID_X_CHARACTERISTIC, &x, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY), 
    yAngleCharacteristic(UUID_Y_CHARACTERISTIC, &y, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY), 
    zAngleCharacteristic(UUID_Z_CHARACTERISTIC, &z, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) { 

     GattCharacteristic *readings[] = {&xAngleCharacteristic, &yAngleCharacteristic, &zAngleCharacteristic, }; 
     GattService   accelerometerService(UUID_ACCELEROMETER_SERVICE, readings, sizeof(readings)/sizeof(GattCharacteristic *)); 

     ble.addService(accelerometerService); 
    } 

    /** 
    * @brief Update the x axis rotation with a new value. 
    * @param _x - New x value from accelerometer 
    */ 
    void update_x(uint8_t _x) { 
     x = _x; 
     ble.gattServer().write(xAngleCharacteristic.getValueHandle(), &x, 1); 
    } 

    /** 
    * @brief Update the y axis rotation with a new value. 
    * @param _z - New y value from accelerometer 
    */ 
    void update_y(uint8_t _y) { 
     y = _y; 
     ble.gattServer().write(yAngleCharacteristic.getValueHandle(), &y, 1); 
    } 

    /** 
    * @brief Update the z axis rotation with a new value. 
    * @param _z - New z value from accelerometer 
    */ 
    void update_z(uint8_t _z) { 
     z = _z; 
     ble.gattServer().write(zAngleCharacteristic.getValueHandle(), &z, 1); 
    } 


protected: 

    /** 
    * A reference to the underlying BLE instance that this object is attached to. 
    * The services and characteristics will be registered in this BLE instance. 
    */ 
    BLE &ble; 

    /** 
    * The current x axis rotation, represented as a double 
    */ 
    uint8_t x; 
    /** 
    * The current y axis rotation, represented as a double 
    */ 
    uint8_t y; 
    /** 
    * The current z axis rotation, represented as a double 
    */ 
    uint8_t z; 

    /** 
    * A ReadOnlyGattCharacteristic that allows access to the peer device to the 
    * x axis rotation value through BLE. 
    */ 
    ReadOnlyGattCharacteristic<uint8_t> xAngleCharacteristic; 
    /** 
    * A ReadOnlyGattCharacteristic that allows access to the peer device to the 
    * y axis rotation value through BLE. 
    */ 
    ReadOnlyGattCharacteristic<uint8_t> yAngleCharacteristic; 
    /** 
    * A ReadOnlyGattCharacteristic that allows access to the peer device to the 
    * z axis rotation value through BLE. 
    */ 
    ReadOnlyGattCharacteristic<uint8_t> zAngleCharacteristic; 
}; 


#endif /* __BLE_ACCELEROMETER_SERVICE__ */ 

以下是我通過mbed.org使用的main.cpp文件。

#include "mbed.h" 
#include "ble/BLE.h" 
#include "AccelerometerService.h" 

DigitalOut led1(LED1); 
DigitalOut led2(LED2); 

static AccelerometerService *accelerometerServicePtr; 

// Function declarations 
void bleInitComplete(BLE::InitializationCompleteCallbackContext *); 
void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *); 

// Set device name and inital setup options 
static const char  DEVICE_NAME[]  = "nRF52"; 
static const uint16_t uuid16_list[]  = {0xFFFF}; 
static volatile bool triggerSensorPolling = false; 

static float   x = 10.0; // Dummy values for accelerometer for now 
static float   y = 15.0; 
static float   z = 18.0; 

/* 
* Initialization callback 
*/ 
void bleInitComplete(BLE::InitializationCompleteCallbackContext *params) 
{ 
    BLE &ble = params->ble; 
    ble_error_t error = params->error; 

    if (error != BLE_ERROR_NONE){ 
     printf("*** Error occured ***\n"); 
     return; 
    } 

    /* Ensure that it is the default instance of BLE */ 
    if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) { 
     return; 
    } 

    ble.gap().onDisconnection(disconnectionCallback); 

    // Setup primary service 
    accelerometerServicePtr = new AccelerometerService(ble, x, y, z); 

    // Setup advertising 
    ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); 

    // Advertising payload has a maximum of 31 bytes 
    // BLE only, no classic BT 
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | 
              GapAdvertisingData::LE_GENERAL_DISCOVERABLE); 
    // Add name 
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); 
    // UUIDs broadcast in advertising packet 
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); 
    // Set advertising interval 
    ble.gap().setAdvertisingInterval(100); //100ms 

    // Start advertising 
    ble.gap().startAdvertising(); 
} 

/** 
* Restart advertising on disconnection 
*/ 
void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *) 
{ 
    BLE::Instance(BLE::DEFAULT_INSTANCE).gap().startAdvertising(); 
} 

/** 
* This function is called when the ble initialization process has failed 
*/ 
void onBleInitError(BLE &ble, ble_error_t error) 
{ 
    /* Avoid compiler warnings */ 
    (void) ble; 
    (void) error; 
    /* Initialization error handling should go here */ 
} 

int main() 
{ 
    // Initialize program 
    printf("\n\r *** Starting Main Loop *** \r\n"); 

    BLE &ble = BLE::Instance(BLE::DEFAULT_INSTANCE); 
    ble.init(bleInitComplete); 

    while (ble.hasInitialized() == false) 
    { 
     while (true) 
     { 
      if (triggerSensorPolling && ble.gap().getState().connected) { 
       triggerSensorPolling = false; 

       accelerometerServicePtr->update_x(x); 
       accelerometerServicePtr->update_y(y); 
       accelerometerServicePtr->update_z(z); 
      } 
      else { 
       ble.waitForEvent(); // Infinite loop waiting for BLE interrupt events 
      } 
     } 
    } 
} 
+1

沒有更多的細節,幫助你很難。您面臨的問題具體是什麼,例如,外設不做廣告,無法發現服務,30秒後斷開連接等? –

+0

中央管理器找到外設(nRF52)並連接到它,但如果我調用[外設discoverServices:nil]方法,則不會發生任何事情。我甚至嘗試在外設的didDiscoverServices ...方法的開始處放置NSLog調試語句,但沒有任何反應。 –

+0

有沒有進一步的想法?謝謝! @JensMeder –

回答

1

這是錯誤的,你發送的是一個不好的廣告數據包。 (0xFFFF的==插入16位在此服務)

... 
uuid16_list[]  = {0xFFFF}; 
... 
... 
COMPLETE_LIST_128BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list) 

有藍牙保留的16個標識符,它使用保留的UUID空間。

查看本頁面:What range of Bluetooth UUIDs can be used for vendor defined profiles?

你需要做的是在指定的128位名單全部UUID什麼。

我不能編譯這一點,但嘗試這樣的事情

char 128bitlist[] = {,0x00,0x00,0x00,0x00 ,0x00,0x00 ,0x10,0x00 ,0x74,0x50 ,0xBE,0x2E,0x44,0xB0,0x6B,0x00}; 
... 
... 
ble.gap().accumulateAdvertisingPayload (GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, (uint8_t *) 128bitlist, 1); 

檢查廣告數據的優秀工具是Lightblue。它是免費的,真正的信息。您應該使用此工具檢查Android和IOS上的廣告。

另一件要檢查的是,你不要過度填充廣告數據包。如果您的設備名稱太長,加上128位的UUID,則可能導致數據包溢出並損壞。嘗試刪除名稱或將其縮短。