2017-08-30 8 views
0

Je souhaite envoyer des valeurs d'accéléromètre via BLE à une application iOS à l'aide d'un nRF52 nordique. L'application fonctionne parfaitement avec les services BLE standard (HeartRate Measurement, Thermometer, etc.), mais pas lorsque j'essaie de définir un service d'accéléromètre BLE personnalisé. Y a-t-il quelque chose que je dois faire spécifiquement lors de la définition des UUID et des choses? Toute aide serait très appréciée, merci. Ci-dessous est ma classe d'accéléromètre personnalisée, et le main.cpp téléchargé sur le nRF52 ci-dessous.Accéléromètre BLE

#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__ */ 

Voici le fichier main.cpp que j'utilise via mbed.org.

#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

Il est un peu difficile de vous aider sans plus de détails. Quel est précisément le problème auquel vous faites face, par exemple, le périphérique ne fait pas de publicité, ne peut pas découvrir les services, se déconnecter après 30s, etc.? –

+0

Le gestionnaire central trouve le périphérique (nRF52) et s'y connecte, mais si j'appelle la méthode [périphérique discoverServices: nil], rien ne se passe. J'ai même essayé de mettre des instructions de débogage NSLog au début de la méthode didDiscoverServices du périphérique ... mais rien ne se passe. –

+0

D'autres idées? Merci! @JensMeder –

Répondre

1

Ceci est faux, vous envoyez un paquet de publicité négative. (0xFFFF == Insérer le service 16 bits ici)

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

Il y a Bluetooth réservés 16 identificateurs de bits qui utilisent l'espace réservé UUID.

Vérifiez cette page: What range of Bluetooth UUIDs can be used for vendor defined profiles?

Ce que vous devez faire est de spécifier la pleine UUID dans la liste de 128 bits.

Je ne peux pas compilé ce mais essayez quelque chose comme ça

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); 

Un outil exceptionnel pour vérifier vos données de publicité est Lightblue. C'est gratuit et vraiment instructif. Vous devriez vérifier la publicité sur Android et IOS avec cet outil.

Une autre chose à vérifier est que vous ne surchargez pas le paquet de publicité. Si le nom de votre périphérique est trop long, plus l'UUID 128 bits, vous pouvez surcharger et corrompre le paquet. Essayez de supprimer le nom ou de le rendre très court.