Code Monkey home page Code Monkey logo

ble's Introduction

mbed Bluetooth Low Energy Stack

This is the Github repo for the BLE_API used by developer.mbed.org. Please see the mbed BLE Homepage for all documentation, code examples and general help.

Supported Services

Supported GATT services and constantly being added and can be found in the ble/services/ folder.

Currently supported services include:

  • Battery
  • Device Firmware Update (DFU)
  • Device Information
  • Eddystone Configuration Service
  • Health Thermometer
  • Heart Rate
  • Link Loss
  • UART
  • UriBeacon
  • iBeacon

The documentation contains an overview on how to create new, application-specific services.

Getting Started

The mbed BLE API is meant to be used in projects on developer.mbed.org. Please see examples and sample project files there. A good starting point are these pages:

ble's People

Contributors

adfernandes avatar blackstoneengineering avatar bremoran avatar crespum avatar ddavidebor avatar iriark01 avatar jeremybrodt avatar jslater8 avatar metc avatar ojford avatar pan- avatar rgrover avatar rosterloh avatar schilit avatar schilitg avatar shirishb avatar sunsmilearm avatar xiongyihui avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ble's Issues

C version of the API?

I'm interested in using the BLE_API for a project I'm working on, but C++ is a showstopper. I'd hate to have to reinvent the wheel just for that. Any suggestions?

Thanks,
Myles

Lock and Unlock missing from URIBeacon2Service.h

Hi @rgrover

Lock and Unlock are missing from URIBeacon2Service.h

The Lock value should be stored in non-volatile memory. Lock value can be set to 0 to indicate unlocked, therefore Lock State can be based solely on Lock value.

A phone initiates a GATT connection, reads all characteristics including lock state. If updates are necessary it will check lock state and issue: unlock_, write+, lock_ (* optional).

The type is defined as uint128 but we are considering making uint8[] of any size. Let us know if you have a strong opinion on this.

Gap state is not updated when the advertising stop after the timeout

The state of the Gap is not properly updated when the advertising stop after a timeout.

Gap& gap = BLE::Instance().gap();

// advertising will last for 10 seconds
gap.setAdvertisingTimeout(10);
gap.startAdvertising();

Gap::GapState_t state = gap().getState(); // at this stage state.advertising is equal to true

// 11 seconds later advertising has stopped
Gap::GapState_t state = gap().getState(); // state.advertising is still equal to true

Roadmap

Is there a roadmap defined somewhere? Currently I'm working on the S130 device because I need to be able to operate as a server.

Would the following signatures be fine?

virtual ble_error_t startScanning(const GapScanningParams &) = 0;
virtual ble_error_t stopScanning(void)                    = 0;

What else do we need? How do you prefer to maintain the list of devices that have been scanned for?

And how do I make a distinction between functionality that only allows peripheral roles versus central roles (say the S110 vs the S120 vs the S130)?

Modes: UriBeacon and UriBeaconConfig

Hi @rgrover

Devices implementing UriBeacon have modes:

  1. UriBeacon ADV mode. Where they emit the UriBeacon
  2. Config ADV mode. Where they emit an ADV packet for the config servicebut if no connection is made in N seconds (30) then they revert to mode 1.

On the CSR and nRF51 we've been using hardware button press to move devices into Config mode.

Any thoughts on how this would work on mbed?

Gap::updateAdvertisingPayload should work for different length of data

The use of the function Gap::updateAdvertisingPayload can be improved:

  • It is not possible to update a payload field if the new data have size different than the previous one.
gap.accumulateAdvertisingPayload(Gap::COMPLETE_LOCAL_NAME, "foo", 3);

// this call will return an error 
gap.accumulateAdvertisingPayload(Gap::COMPLETE_LOCAL_NAME, "foobar", 6);
  • The user have to keep track of every field size if he want to update a field later

Need some help regarding the development of BLE network simulator

Hi Mr. Rohit,
@rgrover

I am really sorry for this as my post may sound unclear and weird but i am in need of some help. I was trying to develop a network simulator for BLE network so that we can simulate and check where to place the beacons depending upon the mobility pattern, varying different scan and advertising intervals. For this, we were trying to use NS3 and build BLE module. But BLE seems a lot complex.

But later i checked your BLE API and tried to build it in eclipse after importing from GitHub. But there occurs nothing. It is not getting built. So, how to build it? Kindly help me and show some guidelines. Also only header files have been declared. How will be the message passing process will be accompanied here. How to include the source files and add the mechanism here?

Any help will be appreciated.

Thanks

URIBeacon2Service Needs initial AdvertisedTxPowerLevels

Hi @rgrover @roywant

The UriBeaconConfigService (or the main.c) requires a default array for Advertised Tx Power Levels. Indexing by the current mode results in the dBm value transmitted in the ADV packet.

Since the value used for nRF51822n::setTxPower may not be the same as the Advertised value we also recommend an array for this purpose.

nRF51822n::setTxPower takes values of -40, -20, -16, -12, -8, -4, 0, 4

Suggest

// Values included in ADV packets for
// TX_POWER_MODE_LOWEST through TX_POWER_MODE_HIGH
// TODO: adjust these values using measurements for the packaged device
uint8_t[4] advertisedTxPowerLevels = {-40, -20, -12, 4};

// Values for nRF51822n::setTxPower for
// TX_POWER_MODE_LOWEST through TX_POWER_MODE_HIGH
uint8_t[4] firmwareTxPowerLevels = {-40, -20, -12, 4};

URIBeacon2Service configure()

What is the purpose of public methods like URIBeacon2Service ::setFlags

These call configure() but do not call ble.setAdvertisingPayload()

These methods do not call ble.updateCharacteristicValue so the values are never reflected in GATT.

Also configure() is called twice in onDataWritten for reset.

Clash With Definition and Enum Naming

When using the NRF51822 library with BLE_API there's a clash with some names.

Looking at blecommon.h, these enums are declared:

enum {
    BLE_UUID_UNKNOWN                             = 0x0000, /**< Reserved UUID. */
    BLE_UUID_SERVICE_PRIMARY                     = 0x2800, /**< Primary Service. */
    BLE_UUID_SERVICE_SECONDARY                   = 0x2801, /**< Secondary Service. */
    BLE_UUID_SERVICE_INCLUDE                     = 0x2802, /**< Include. */
    BLE_UUID_CHARACTERISTIC                      = 0x2803, /**< Characteristic. */
    BLE_UUID_DESCRIPTOR_CHAR_EXT_PROP            = 0x2900, /**< Characteristic Extended Properties Descriptor. */
    BLE_UUID_DESCRIPTOR_CHAR_USER_DESC           = 0x2901, /**< Characteristic User Description Descriptor. */
    BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG       = 0x2902, /**< Client Characteristic Configuration Descriptor. */
    BLE_UUID_DESCRIPTOR_SERVER_CHAR_CONFIG       = 0x2903, /**< Server Characteristic Configuration Descriptor. */
    BLE_UUID_DESCRIPTOR_CHAR_PRESENTATION_FORMAT = 0x2904, /**< Characteristic Presentation Format Descriptor. */
    BLE_UUID_DESCRIPTOR_CHAR_AGGREGATE_FORMAT    = 0x2905, /**< Characteristic Aggregate Format Descriptor. */

/* GATT specific UUIDs */
    BLE_UUID_GATT                                = 0x1801, /**< Generic Attribute Profile. */
    BLE_UUID_GATT_CHARACTERISTIC_SERVICE_CHANGED = 0x2A05, /**< Service Changed Characteristic. */

/* GAP specific UUIDs */
    BLE_UUID_GAP                                 = 0x1800, /**< Generic Access Profile. */
    BLE_UUID_GAP_CHARACTERISTIC_DEVICE_NAME      = 0x2A00, /**< Device Name Characteristic. */
    BLE_UUID_GAP_CHARACTERISTIC_APPEARANCE       = 0x2A01, /**< Appearance Characteristic. */
    BLE_UUID_GAP_CHARACTERISTIC_PPF              = 0x2A02, /**< Peripheral Privacy Flag Characteristic. */
    BLE_UUID_GAP_CHARACTERISTIC_RECONN_ADDR      = 0x2A03, /**< Reconnection Address Characteristic. */
    BLE_UUID_GAP_CHARACTERISTIC_PPCP             = 0x2A04, /**< Peripheral Preferred Connection Parameters Characteristic. */
};
/** @} */`

enum {
    BLE_APPEARANCE_UNKNOWN                             =    0, /**< Unknown. */
    BLE_APPEARANCE_GENERIC_PHONE                       =   64, /**< Generic Phone. */
    BLE_APPEARANCE_GENERIC_COMPUTER                    =  128, /**< Generic Computer. */
    BLE_APPEARANCE_GENERIC_WATCH                       =  192, /**< Generic Watch. */
    BLE_APPEARANCE_WATCH_SPORTS_WATCH                  =  193, /**< Watch: Sports Watch. */
    BLE_APPEARANCE_GENERIC_CLOCK                       =  256, /**< Generic Clock. */
    BLE_APPEARANCE_GENERIC_DISPLAY                     =  320, /**< Generic Display. */
    BLE_APPEARANCE_GENERIC_REMOTE_CONTROL              =  384, /**< Generic Remote Control. */
    BLE_APPEARANCE_GENERIC_EYE_GLASSES                 =  448, /**< Generic Eye-glasses. */
    BLE_APPEARANCE_GENERIC_TAG                         =  512, /**< Generic Tag. */
    BLE_APPEARANCE_GENERIC_KEYRING                     =  576, /**< Generic Keyring. */
    BLE_APPEARANCE_GENERIC_MEDIA_PLAYER                =  640, /**< Generic Media Player. */
    BLE_APPEARANCE_GENERIC_BARCODE_SCANNER             =  704, /**< Generic Barcode Scanner. */
    BLE_APPEARANCE_GENERIC_THERMOMETER                 =  768, /**< Generic Thermometer. */
    BLE_APPEARANCE_THERMOMETER_EAR                     =  769, /**< Thermometer: Ear. */
    BLE_APPEARANCE_GENERIC_HEART_RATE_SENSOR           =  832, /**< Generic Heart rate Sensor. */
    BLE_APPEARANCE_HEART_RATE_SENSOR_HEART_RATE_BELT   =  833, /**< Heart Rate Sensor: Heart Rate Belt. */
    BLE_APPEARANCE_GENERIC_BLOOD_PRESSURE              =  896, /**< Generic Blood Pressure. */
    BLE_APPEARANCE_BLOOD_PRESSURE_ARM                  =  897, /**< Blood Pressure: Arm. */
    BLE_APPEARANCE_BLOOD_PRESSURE_WRIST                =  898, /**< Blood Pressure: Wrist. */
    BLE_APPEARANCE_GENERIC_HID                         =  960, /**< Human Interface Device (HID). */
    BLE_APPEARANCE_HID_KEYBOARD                        =  961, /**< Keyboard (HID Subtype). */
    BLE_APPEARANCE_HID_MOUSE                           =  962, /**< Mouse (HID Subtype). */
    BLE_APPEARANCE_HID_JOYSTICK                        =  963, /**< Joystiq (HID Subtype). */
    BLE_APPEARANCE_HID_GAMEPAD                         =  964, /**< Gamepad (HID Subtype). */
    BLE_APPEARANCE_HID_DIGITIZERSUBTYPE                =  965, /**< Digitizer Tablet (HID Subtype). */
    BLE_APPEARANCE_HID_CARD_READER                     =  966, /**< Card Reader (HID Subtype). */
    BLE_APPEARANCE_HID_DIGITAL_PEN                     =  967, /**< Digital Pen (HID Subtype). */
    BLE_APPEARANCE_HID_BARCODE                         =  968, /**< Barcode Scanner (HID Subtype). */
    BLE_APPEARANCE_GENERIC_GLUCOSE_METER               = 1024, /**< Generic Glucose Meter. */
    BLE_APPEARANCE_GENERIC_RUNNING_WALKING_SENSOR      = 1088, /**< Generic Running Walking Sensor. */
    BLE_APPEARANCE_RUNNING_WALKING_SENSOR_IN_SHOE      = 1089, /**< Running Walking Sensor: In-Shoe. */
    BLE_APPEARANCE_RUNNING_WALKING_SENSOR_ON_SHOE      = 1090, /**< Running Walking Sensor: On-Shoe. */
    BLE_APPEARANCE_RUNNING_WALKING_SENSOR_ON_HIP       = 1091, /**< Running Walking Sensor: On-Hip. */
    BLE_APPEARANCE_GENERIC_CYCLING                     = 1152, /**< Generic Cycling. */
    BLE_APPEARANCE_CYCLING_CYCLING_COMPUTER            = 1153, /**< Cycling: Cycling Computer. */
    BLE_APPEARANCE_CYCLING_SPEED_SENSOR                = 1154, /**< Cycling: Speed Sensor. */
    BLE_APPEARANCE_CYCLING_CADENCE_SENSOR              = 1155, /**< Cycling: Cadence Sensor. */
    BLE_APPEARANCE_CYCLING_POWER_SENSOR                = 1156, /**< Cycling: Power Sensor. */
    BLE_APPEARANCE_CYCLING_SPEED_CADENCE_SENSOR        = 1157, /**< Cycling: Speed and Cadence Sensor. */
    BLE_APPEARANCE_GENERIC_PULSE_OXIMETER              = 3136, /**< Generic Pulse Oximeter. */
    BLE_APPEARANCE_PULSE_OXIMETER_FINGERTIP            = 3137, /**< Fingertip (Pulse Oximeter subtype). */
    BLE_APPEARANCE_PULSE_OXIMETER_WRIST_WORN           = 3138, /**< Wrist Worn(Pulse Oximeter subtype). */
    BLE_APPEARANCE_GENERIC_WEIGHT_SCALE                = 3200, /**< Generic Weight Scale. */
    BLE_APPEARANCE_GENERIC_OUTDOOR_SPORTS_ACT          = 5184, /**< Generic Outdoor Sports Activity. */
    BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_DISP         = 5185, /**< Location Display Device (Outdoor Sports Activity subtype). */
    BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_AND_NAV_DISP = 5186, /**< Location and Navigation Display Device (Outdoor Sports Activity subtype). */
    BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_POD          = 5187, /**< Location Pod (Outdoor Sports Activity subtype). */
    BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_AND_NAV_POD  = 5188, /**< Location and Navigation Pod (Outdoor Sports Activity subtype). */
};
/** @} */

Then looking at ble_types.h in the NRF51822 library, the following defines are used

/** @defgroup BLE_UUID_VALUES Assigned Values for BLE UUIDs
 * @{ */
/* Generic UUIDs, applicable to all services */
#define BLE_UUID_UNKNOWN                              0x0000 /**< Reserved UUID. */
#define BLE_UUID_SERVICE_PRIMARY                      0x2800 /**< Primary Service. */
#define BLE_UUID_SERVICE_SECONDARY                    0x2801 /**< Secondary Service. */
#define BLE_UUID_SERVICE_INCLUDE                      0x2802 /**< Include. */
#define BLE_UUID_CHARACTERISTIC                       0x2803 /**< Characteristic. */
#define BLE_UUID_DESCRIPTOR_CHAR_EXT_PROP             0x2900 /**< Characteristic Extended Properties Descriptor. */
#define BLE_UUID_DESCRIPTOR_CHAR_USER_DESC            0x2901 /**< Characteristic User Description Descriptor. */
#define BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG        0x2902 /**< Client Characteristic Configuration Descriptor. */
#define BLE_UUID_DESCRIPTOR_SERVER_CHAR_CONFIG        0x2903 /**< Server Characteristic Configuration Descriptor. */
#define BLE_UUID_DESCRIPTOR_CHAR_PRESENTATION_FORMAT  0x2904 /**< Characteristic Presentation Format Descriptor. */
#define BLE_UUID_DESCRIPTOR_CHAR_AGGREGATE_FORMAT     0x2905 /**< Characteristic Aggregate Format Descriptor. */
/* GATT specific UUIDs */
#define BLE_UUID_GATT                                 0x1801 /**< Generic Attribute Profile. */
#define BLE_UUID_GATT_CHARACTERISTIC_SERVICE_CHANGED  0x2A05 /**< Service Changed Characteristic. */
/* GAP specific UUIDs */
#define BLE_UUID_GAP                                  0x1800 /**< Generic Access Profile. */
#define BLE_UUID_GAP_CHARACTERISTIC_DEVICE_NAME       0x2A00 /**< Device Name Characteristic. */
#define BLE_UUID_GAP_CHARACTERISTIC_APPEARANCE        0x2A01 /**< Appearance Characteristic. */
#define BLE_UUID_GAP_CHARACTERISTIC_PPF               0x2A02 /**< Peripheral Privacy Flag Characteristic. */
#define BLE_UUID_GAP_CHARACTERISTIC_RECONN_ADDR       0x2A03 /**< Reconnection Address Characteristic. */
#define BLE_UUID_GAP_CHARACTERISTIC_PPCP              0x2A04 /**< Peripheral Preferred Connection Parameters Characteristic. */
/** @} */

/** @defgroup BLE_APPEARANCES Bluetooth Appearance values
 *  @note Retrieved from http://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.gap.appearance.xml
 * @{ */
#define BLE_APPEARANCE_UNKNOWN                                0 /**< Unknown. */
#define BLE_APPEARANCE_GENERIC_PHONE                         64 /**< Generic Phone. */
#define BLE_APPEARANCE_GENERIC_COMPUTER                     128 /**< Generic Computer. */
#define BLE_APPEARANCE_GENERIC_WATCH                        192 /**< Generic Watch. */
#define BLE_APPEARANCE_WATCH_SPORTS_WATCH                   193 /**< Watch: Sports Watch. */
#define BLE_APPEARANCE_GENERIC_CLOCK                        256 /**< Generic Clock. */
#define BLE_APPEARANCE_GENERIC_DISPLAY                      320 /**< Generic Display. */
#define BLE_APPEARANCE_GENERIC_REMOTE_CONTROL               384 /**< Generic Remote Control. */
#define BLE_APPEARANCE_GENERIC_EYE_GLASSES                  448 /**< Generic Eye-glasses. */
#define BLE_APPEARANCE_GENERIC_TAG                          512 /**< Generic Tag. */
#define BLE_APPEARANCE_GENERIC_KEYRING                      576 /**< Generic Keyring. */
#define BLE_APPEARANCE_GENERIC_MEDIA_PLAYER                 640 /**< Generic Media Player. */
#define BLE_APPEARANCE_GENERIC_BARCODE_SCANNER              704 /**< Generic Barcode Scanner. */
#define BLE_APPEARANCE_GENERIC_THERMOMETER                  768 /**< Generic Thermometer. */
#define BLE_APPEARANCE_THERMOMETER_EAR                      769 /**< Thermometer: Ear. */
#define BLE_APPEARANCE_GENERIC_HEART_RATE_SENSOR            832 /**< Generic Heart rate Sensor. */
#define BLE_APPEARANCE_HEART_RATE_SENSOR_HEART_RATE_BELT    833 /**< Heart Rate Sensor: Heart Rate Belt. */
#define BLE_APPEARANCE_GENERIC_BLOOD_PRESSURE               896 /**< Generic Blood Pressure. */
#define BLE_APPEARANCE_BLOOD_PRESSURE_ARM                   897 /**< Blood Pressure: Arm. */
#define BLE_APPEARANCE_BLOOD_PRESSURE_WRIST                 898 /**< Blood Pressure: Wrist. */
#define BLE_APPEARANCE_GENERIC_HID                          960 /**< Human Interface Device (HID). */
#define BLE_APPEARANCE_HID_KEYBOARD                         961 /**< Keyboard (HID Subtype). */
#define BLE_APPEARANCE_HID_MOUSE                            962 /**< Mouse (HID Subtype). */
#define BLE_APPEARANCE_HID_JOYSTICK                         963 /**< Joystiq (HID Subtype). */
#define BLE_APPEARANCE_HID_GAMEPAD                          964 /**< Gamepad (HID Subtype). */
#define BLE_APPEARANCE_HID_DIGITIZERSUBTYPE                 965 /**< Digitizer Tablet (HID Subtype). */
#define BLE_APPEARANCE_HID_CARD_READER                      966 /**< Card Reader (HID Subtype). */
#define BLE_APPEARANCE_HID_DIGITAL_PEN                      967 /**< Digital Pen (HID Subtype). */
#define BLE_APPEARANCE_HID_BARCODE                          968 /**< Barcode Scanner (HID Subtype). */
#define BLE_APPEARANCE_GENERIC_GLUCOSE_METER               1024 /**< Generic Glucose Meter. */
#define BLE_APPEARANCE_GENERIC_RUNNING_WALKING_SENSOR      1088 /**< Generic Running Walking Sensor. */
#define BLE_APPEARANCE_RUNNING_WALKING_SENSOR_IN_SHOE      1089 /**< Running Walking Sensor: In-Shoe. */
#define BLE_APPEARANCE_RUNNING_WALKING_SENSOR_ON_SHOE      1090 /**< Running Walking Sensor: On-Shoe. */
#define BLE_APPEARANCE_RUNNING_WALKING_SENSOR_ON_HIP       1091 /**< Running Walking Sensor: On-Hip. */
#define BLE_APPEARANCE_GENERIC_CYCLING                     1152 /**< Generic Cycling. */
#define BLE_APPEARANCE_CYCLING_CYCLING_COMPUTER            1153 /**< Cycling: Cycling Computer. */
#define BLE_APPEARANCE_CYCLING_SPEED_SENSOR                1154 /**< Cycling: Speed Sensor. */
#define BLE_APPEARANCE_CYCLING_CADENCE_SENSOR              1155 /**< Cycling: Cadence Sensor. */
#define BLE_APPEARANCE_CYCLING_POWER_SENSOR                1156 /**< Cycling: Power Sensor. */
#define BLE_APPEARANCE_CYCLING_SPEED_CADENCE_SENSOR        1157 /**< Cycling: Speed and Cadence Sensor. */
#define BLE_APPEARANCE_GENERIC_PULSE_OXIMETER              3136 /**< Generic Pulse Oximeter. */
#define BLE_APPEARANCE_PULSE_OXIMETER_FINGERTIP            3137 /**< Fingertip (Pulse Oximeter subtype). */
#define BLE_APPEARANCE_PULSE_OXIMETER_WRIST_WORN           3138 /**< Wrist Worn(Pulse Oximeter subtype). */
#define BLE_APPEARANCE_GENERIC_WEIGHT_SCALE                3200 /**< Generic Weight Scale. */
#define BLE_APPEARANCE_GENERIC_OUTDOOR_SPORTS_ACT          5184 /**< Generic Outdoor Sports Activity. */
#define BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_DISP         5185 /**< Location Display Device (Outdoor Sports Activity subtype). */
#define BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_AND_NAV_DISP 5186 /**< Location and Navigation Display Device (Outdoor Sports Activity subtype). */
#define BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_POD          5187 /**< Location Pod (Outdoor Sports Activity subtype). */
#define BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_AND_NAV_POD  5188 /**< Location and Navigation Pod (Outdoor Sports Activity subtype). */
/** @} */

As you can see, there's a direct clash. When exporting a program from the mbed compiler to Keil, it will complain that it expected an identifier.

Advertising data and scan response are committed into Gap object even if the underlying implementation failled

To illustrate the issue, I will just take the code from Gap::setAdvertisingPayload

    ble_error_t setAdvertisingPayload(const GapAdvertisingData &payload) {
        _advPayload = payload;
        return setAdvertisingData();
    }

    ble_error_t setAdvertisingData(void) {
        return setAdvertisingData(_advPayload, _scanResponse);
    }

    // this is provided by Gap implementation
    virtual ble_error_t setAdvertisingData(const GapAdvertisingData &, const GapAdvertisingData &) = 0;

The member _advPayload is updated even if the setAdvertisingData implementation fail. As a result, next calls to getAdvertisingPayload or updateAdvertisingPayload will use or return an invalid advertisingPayload.

Member functions which can commit invalid data are:

  • accumulateAdvertisingPayload
  • updateAdvertisingPayload
  • setAdvertisingPayload
  • accumulateScanResponse

ERROR: undefined reference to `createBLEInstance()'

white trying to compile source code offline i'm having the same issue over and over again.

it has been similarly reported here https://developer.mbed.org/questions/54408/Build-error/

i'm unable to find where is the problem in the linker, i'm using the 16k S110 version

Linking CXX executable BLE_HEART_RATE.elf
CMakeFiles/BLE_HEART_RATE.elf.dir/main.cpp.o: In function _GLOBAL__sub_I_IRLed': main.cpp:(.text.startup._GLOBAL__sub_I_IRLed+0x8a): undefined reference tocreateBLEInstance()'
collect2: error: ld returned 1 exit status
make[2]: *** [BLE_HEART_RATE.elf] Error 1
make[1]: *** [CMakeFiles/BLE_HEART_RATE.elf.dir/all] Error 2
make: *** [all] Error 2

Service Characteristics

Hi @rgrover

The BLE_API / services / URIBeacon2Service.h has incorrect
Characteristics.

Specifically the table in the specification does not include support for GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE

The unreliable write on Reset is a problem because this is the way to reset all values to known default settings before updating selected values.

Which are the allowed values for txPower? > BLEDevice::setTxPower(int8_t txPower)

Hello,

I am developing with the latest version of the BLE_API. So far, I have successfully created fairly complex Peripheral examples. However, I have been only partially capable of changing the TX power.

I have been trying different values for txPower,
ble_error_t BLEDevice::setTxPower(int8_t txPower)

However, so far I only could make it work for txPower = 0 (0 dBm) and txPower = 4 (dBm). I have tried some negative values with no success.

Is there any documentation on the subject?

Best regards,
Jose Angel

nRF51822 low-power operation

Hello,

There is problem with current consumption in Bluetooth applications and current version of mbed SDK.
I'm using nRF51822-EK board for tests.
I created test project based on BLE_HeartRate example with last versions of libraries: mbed-src, nRF51822, BLE_API.

/* mbed Microcontroller Library
 * Copyright (c) 2006-2013 ARM Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "mbed.h"
#include "BLEDevice.h"
#include "HeartRateService.h"
#include "BatteryService.h"
#include "DeviceInformationService.h"

BLEDevice  ble;

const static char     DEVICE_NAME[]        = "Nordic_HRM";
static const uint16_t uuid16_list[]        = {GattService::UUID_HEART_RATE_SERVICE,
                                              GattService::UUID_BATTERY_SERVICE,
                                              GattService::UUID_DEVICE_INFORMATION_SERVICE};
static volatile bool  triggerSensorPolling = false;

void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason)
{
    ble.startAdvertising(); // restart advertising
}

void periodicCallback(void)
{
    /* Note that the periodicCallback() executes in interrupt context, so it is safer to do
     * heavy-weight sensor polling from the main thread. */
    triggerSensorPolling = true;
}

int main(void)
{
    Ticker ticker;
    ticker.attach(periodicCallback, 1);

    ble.init();
    ble.onDisconnection(disconnectionCallback);

    /* Setup primary service. */
    uint8_t hrmCounter = 100;
    HeartRateService hrService(ble, hrmCounter, HeartRateService::LOCATION_FINGER);

    /* Setup auxiliary services. */
    BatteryService           battery(ble);
    DeviceInformationService deviceInfo(ble, "ARM", "Model1", "SN1", "hw-rev1", "fw-rev1", "soft-rev1");

    /* Setup advertising. */
    ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
    ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
    ble.accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_HEART_RATE_SENSOR);
    ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
    ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
    ble.setAdvertisingInterval(1600); /* 1000ms; in multiples of 0.625ms. */
    ble.startAdvertising();

    while (true) {
        if (triggerSensorPolling) {
            triggerSensorPolling = false;

            /* Do blocking calls or whatever is necessary for sensor polling. */
            /* In our case, we simply update the dummy HRM measurement. */
            hrmCounter++;
            if (hrmCounter == 175) {
                hrmCounter = 100;
            }

            hrService.updateHeartRate(hrmCounter);
        } else {
            ble.waitForEvent();
        }
    }
}

And results is that in advertising state device consumes 5uA in low-power mode (ble.waitForEvent()) with small current spikes when device send advertising packets. But when I connect to the device the current consumption rise up to 1mA continuous consumption with small spikes when device receive/send packets. When disconnecting device once again start advertising and consumes 5uA in low-power mode.
My assumption is that when in connected state somewhere HFCLK Timer is used instead of low-power timer based on RTC1.
Can someone check it out?

Make UARTService connection oriented

The UART service can only be used with one connection at the moment, as soon as a second connection happen on the device, the write operation stop working (see https://developer.mbed.org/forum/team-63-Bluetooth-Low-Energy-community/post/40093/ and the following response).

It would be great if each BLE connection can have its own UART connection.

UARTService* uartService;

// gap connection handle
void handleConnection(const Gap::ConnectionCallbackParams_t *params) {
    if(params->role == Gap::PERIPHERAL) {
         UARTService::Connection* uartConnection = uartService.getConnection(params->handle);
         // at this point the UART connection is usable ...
         uartConnection->onDataWriten(/* handle the RX */);
        uartConnection->writeString("...");
    }
}

BLEDevice::clearAdvertisingPayload doesn't clear the scan response PDU

There appears to be no way to clear the scan response stored in BLEDevice::scanResponse in the current API. The logical place for this is probably in clearAdvertisingPayload method as the scanResponse is just an extension of the advertising payload. However, if you don't want to change the semantics of the current API another method could be added to the API to do this i.e. clearScanResponse.

Initial value for _requiredSecurity member of GattCharacteristic class breaks existing code

The constructor for GattCharacteristic implicitly initialises the value of the _requiredSecurity member to Gap::SECURITY_MODE_NO_ACCESS (0). Read requests for any characteristic will therefore fail unless there is a call to the requireSecurity method to change it to something more permissive.

As a consequence all existing code that supports reads of a characteristic value will now return an error to the client whenever the client attempts to read the characteristic value.

This breakage could be fixed by explicitly setting the value of the _requiredSecurity member to Gap::SECURITY_MODE_ENCRYPTION_OPEN_LINK in the constructor for GattCharacteristic. If more restrictive access is desired, new code that is aware of the new security features of the API can request this with a call to the requireSecurity method.

Incorrect documentation on void setAdvertisingType()?

Hello,

According to the BLE_API documentation for BLEDevice::setAdvertisingType(),

"ADV_SCANNABLE_UNDIRECTED
Any central device can connect to this peripheral, and the secondary Scan Response payload will be included or available to central devices."

However, according to my interpretation of the BLE 4 specification (and hands-on tests), a scannable device is non-connectable, meaning that,

  • The Central is allowed to ask for additional data (SCAN_REQUEST) which the Peripheral should honor with a SCAN_RESPONSE.
  • The Central is not allowed to connect to the Peripheral.

Do you agree with my reading of the specification? If so, I suggest to update the documentation of the BLE_API, as its current wording indicates that you can connect a Central device to a Peripheral advertising in ADV_SCANNABLE_UNDIRECTED mode.

Thanks for your great work!

Best regards,
Jose Angel

add API to enable notifications

refer to https://developer.mbed.org/forum/team-63-Bluetooth-Low-Energy-community/topic/16517/?page=1#comment-38845

It could be that what's needed here is a simple API like: DiscoveredCharacteristic::enableNotification(), but then that would allow manipulation of only the CCCD. There may be other writable descriptors, which would then require a more generic API.

There's an API meant to discover descriptors for a Characteristic. https://github.com/mbedmicro/BLE_API/blob/master/ble/DiscoveredCharacteristic.h#L117
Unfortunately, we haven't implemented this for the nRF51 yet. The default implementation remains in effect: https://github.com/mbedmicro/BLE_API/blob/master/source/DiscoveredCharacteristic.cpp#L63

My thinking is that launching descriptor discovery should result in callbacks passing the DiscoveredDescriptors (which is a datatype which needs to be added to BLE_API). I'm not sure how best to handle the discovered descriptors following the callback. Perhaps they should be contained within the owning characteristic, or perhaps the user would issue reads/writes directly upon the discovered descriptors.

It would be lovely if the community comes together and proposes a solution (or even a pull request).

Infinite busy

Hello,

I tried this code on 3 boards to make a triangle to test central and device role at same time with S130 on nRF51.

frequently, i loop in busy (2) and never goes out. Maybe i did a mistake, this is my code.

include "mbed.h"

include "BLE.h"

include "UARTService.h"

include "ble/DiscoveredCharacteristic.h"

include "ble/DiscoveredService.h"

include "UARTService.h"

define SOFT_DEVICE_FATHER_HANDLE 3

define BOARDS_COUNT 3

const Gap::Address_t mac_board_0 = {0xb8, 0xac, 0x4e, 0x8d, 0x8b, 0xeb};
const Gap::Address_t mac_board_1 = {0x9c, 0x43, 0x62, 0x30, 0xaf, 0xd2};
const Gap::Address_t mac_board_2 = {0x5f, 0x1a, 0x9e, 0x6a, 0x63, 0xdd};

// tiny ble board

define LED_GREEN p21

define LED_RED p22

define LED_BLUE p23

define BUTTON_PIN p17

define BATTERY_PIN p1

define MPU6050_SDA p12

define MPU6050_SCL p13

define UART_TX p9

define UART_RX p11

define UART_CTS p8

define UART_RTS p10

DigitalOut led(LED_RED);
DigitalOut alivenessLED(LED_GREEN);
InterruptIn button(BUTTON_PIN);
AnalogIn battery(BATTERY_PIN);
Serial pc(UART_TX, UART_RX);

bool mac_equals(const Gap::Address_t mac_1, const Gap::Address_t mac_2)
{
#if 0
if (mac_1[0] != mac_2[0])
{
return false;
}
if (mac_1[1] != mac_2[1])
{
return false;
}
if (mac_1[2] != mac_2[2])
{
return false;
}
if (mac_1[3] != mac_2[3])
{
return false;
}
if (mac_1[4] != mac_2[4])
{
return false;
}
if (mac_1[5] != mac_2[5])
{
return false;
}
#else
for (int i = 0; i < 6; i++)
{
if (mac_1[i] != mac_2[i])
{
//pc.printf("0x%02x != 0x%02x at %d\r\n", mac_1[i], mac_2[i], i);
return false;
}
else
{
//pc.printf("0x%02x == 0x%02x at %d\r\n", mac_1[i], mac_2[i], i);
}
}
#endif
return true;
}

int get_board_index(const Gap::Address_t mac)
{
if (mac_equals(mac, mac_board_0))
{
return 0;
}
if (mac_equals(mac, mac_board_1))
{
return 1;
}
if (mac_equals(mac, mac_board_2))
{
return 2;
}

return -1;

}

void periodicCallback(void)
{
alivenessLED = !alivenessLED; /* do blinky on alivenessLED while we're waiting for BLE events */
}

// Mixed role ****************************************************
BLE ble;
Gap::Address_t my_mac;
int my_board_index = -1;

// Device role ****************************************************
UARTService * uartServicePtr = NULL;
const static char DEVICE_NAME[] = "ChangeMe!!"; // change this
static const uint16_t uuid16_list[] = {UARTServiceShortUUID};

// Central role ****************************************************
Gap::Handle_t connectionHandle = 0xFFFF;
DiscoveredCharacteristic uartTXCharacteristic;
DiscoveredCharacteristic uartRXCharacteristic;
bool foundUartRXCharacteristic = false;

// Device role ****************************************************
void onReceivedDataFromCentralCallback(const GattWriteCallbackParams *params)
{
if (uartServicePtr != NULL)
{
if ((params->handle == uartServicePtr->getTXCharacteristicHandle()) && (params->len >= 1))
{
if (params->data[0] != '0')
{
led = 1;
}
else
{
led = 0;
}

        for(int i = 0; i < params->len; i++) 
        {
            pc.printf("%c", params->data[i]);
        }

        pc.printf(" (%d, %d)\r\n", params->handle, params->connHandle);
    }
}

}

// Central role ****************************************************
void advertisementCallback(const Gap::AdvertisementCallbackParams_t *params)
{
// do connections like a triangle
int peer_board_index = get_board_index(params->peerAddr);

int next_board_index = my_board_index + 1;
if (next_board_index >= BOARDS_COUNT)
{
    next_board_index = 0;
}

//pc.printf("adv %d, %d, %d\r\n", peer_board_index, my_board_index, next_board_index);

if (peer_board_index == next_board_index)
{
    pc.printf("adv peerAddr[%02x %02x %02x %02x %02x %02x] rssi %d, isScanResponse %u, AdvertisementType %u\r\n",
           params->peerAddr[5], params->peerAddr[4], params->peerAddr[3], params->peerAddr[2], params->peerAddr[1], params->peerAddr[0],
           params->rssi, params->isScanResponse, params->type);

    ble.gap().connect(params->peerAddr, Gap::ADDR_TYPE_RANDOM_STATIC, NULL, NULL);
}

}

void serviceDiscoveryCallback(const DiscoveredService *service)
{
if (service->getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT)
{
pc.printf("S UUID-%x attrs[%u %u]\r\n", service->getUUID().getShortUUID(), service->getStartHandle(), service->getEndHandle());
}
else
{
pc.printf("S UUID-");
const uint8_t *longUUIDBytes = service->getUUID().getBaseUUID();
for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++)
{
pc.printf("%02x", longUUIDBytes[i]);
}
pc.printf(" attrs[%u %u]\r\n", service->getStartHandle(), service->getEndHandle());
}
}

void characteristicDiscoveryCallback(const DiscoveredCharacteristic characteristicP)
{
pc.printf(" C UUID-%x valueAttr[%u] props[%x]\r\n", characteristicP->getUUID().getShortUUID(), characteristicP->getValueHandle(), (uint8_t)characteristicP->getProperties().broadcast());
if (characteristicP->getUUID().getShortUUID() == UARTServiceTXCharacteristicShortUUID)
{
pc.printf("fit TX 0x%04x\r\n", UARTServiceTXCharacteristicShortUUID);
/
!ALERT! Alter this filter to suit your device. /
uartTXCharacteristic = *characteristicP;
}
else if (characteristicP->getUUID().getShortUUID() == UARTServiceRXCharacteristicShortUUID)
{
pc.printf("fit RX 0x%04x\r\n", UARTServiceRXCharacteristicShortUUID);
/
!ALERT! Alter this filter to suit your device. */
uartRXCharacteristic = *characteristicP;
foundUartRXCharacteristic = true;
}
}

void discoveryTerminationCallback(Gap::Handle_t connectionHandle)
{
pc.printf("terminated SD for handle %u\r\n", connectionHandle);
}

void onReceivedDataFromDeviceCallback(const GattHVXCallbackParams *params)
{
//pc.printf("received HVX callback for handle %u; type %s\r\r\n", params->handle, (params->type == BLE_HVX_NOTIFICATION) ? "notification" : "indication");
if (params->type == BLE_HVX_NOTIFICATION)
{
if ((params->handle == uartRXCharacteristic.getValueHandle()) && (params->len > 0))
{
for (int i = 0; i < params->len; i++)
{
pc.printf("%c", params->data[i]);
}

        pc.printf(" (%d, %d, %d)\r\n", params->handle, params->connHandle, uartRXCharacteristic.getValueHandle());
    }
}
//pc.printf("\r\n");

}

// Mixed role ****************************************************
void connectionCallback(const Gap::ConnectionCallbackParams_t params)
{
if (params->role == Gap::CENTRAL)
{
pc.printf("connected as central (handle = %d)\r\n\r", params->handle);
connectionHandle = params->handle;
ble.gattClient().onServiceDiscoveryTermination(discoveryTerminationCallback);
ble.gattClient().launchServiceDiscovery(params->handle, serviceDiscoveryCallback, characteristicDiscoveryCallback/
, 0xa000, 0xa001*/);
}
else
{
pc.printf("connected as device (handle = %d)\r\n\r", params->handle);

    pc.printf("Conn. params => min=%d, max=%d, slave=%d, supervision=%d\r\n", params->connectionParams->minConnectionInterval, params->connectionParams->maxConnectionInterval, params->connectionParams->slaveLatency, params->connectionParams->connectionSupervisionTimeout);

    Gap::ConnectionParams_t connectionParams;
    connectionParams.minConnectionInterval        = 6;
    connectionParams.maxConnectionInterval        = 12;
    connectionParams.slaveLatency                 = 0;
    connectionParams.connectionSupervisionTimeout = 500;

    if (ble.updateConnectionParams(params->handle, &connectionParams) != BLE_ERROR_NONE) 
    {
        pc.printf("failed to update connection parameter\r\n");
    }
}
pc.printf("own %02x:%02x:%02x:%02x:%02x:%02x (%s), peer %02x:%02x:%02x:%02x:%02x:%02x (%s)\r\n", params->ownAddr[5], params->ownAddr[4], params->ownAddr[3], params->ownAddr[2], params->ownAddr[1], params->ownAddr[0], (params->ownAddrType == Gap::ADDR_TYPE_PUBLIC) ? "public" : "random", params->peerAddr[5], params->peerAddr[4], params->peerAddr[3], params->peerAddr[2], params->peerAddr[1], params->peerAddr[0], (params->peerAddrType == Gap::ADDR_TYPE_PUBLIC) ? "public" : "random");

}

void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason)
{
pc.printf("disconnected (handle = %d)\r\n", handle);

if (handle == SOFT_DEVICE_FATHER_HANDLE)
{
    // restart advertising
    ble.startAdvertising(); 
}
else
{
    // restart scan
    ble.gap().startScan(advertisementCallback);
}

}

void serialTxCallback()
{

}

int rx_char = -1;
void serialRxCallback()
{
if (rx_char != -1)
{
pc.printf("overflow\r\n");
}

 //computer.putc(computer.getc());
 rx_char = pc.getc();

}

int main(void)
{
alivenessLED = 0;

pc.baud(115200);
//pc.attach(&serialTxCallback, Serial::TxIrq);
pc.attach(&serialRxCallback, Serial::RxIrq);

// clear terminal output
for (int k = 0; k < 255; k++)
{
    pc.printf("\r\n");    
}

pc.printf("Central and device\r\n");

Ticker ticker;
ticker.attach(periodicCallback, 1);


// Mixed role ****************************************************
ble.init();

Gap::AddressType_t my_mac_type;
ble.gap().getAddress(&my_mac_type, my_mac);
my_board_index = get_board_index(my_mac);
pc.printf("me %02x:%02x:%02x:%02x:%02x:%02x (%s)\r\n", my_mac[5], my_mac[4], my_mac[3], my_mac[2], my_mac[1], my_mac[0], (my_mac_type == Gap::ADDR_TYPE_PUBLIC) ? "public" : "random");


// try to speed up but looks like if it was ignored
Gap::ConnectionParams_t fast;
if (ble.getPreferredConnectionParams(&fast) != BLE_ERROR_NONE) 
{
    pc.printf("getPreferredConnectionParams failed\r\n");
}
else
{
    fast.minConnectionInterval = 16; // 20 ms
    fast.maxConnectionInterval = 32; // 40 ms
    fast.slaveLatency = 0;
    if (ble.gap().setPreferredConnectionParams(&fast) != BLE_ERROR_NONE) 
    {
        pc.printf("setPreferredConnectionParams failed\r\n");
    }
}
ble.gap().onConnection(connectionCallback);
ble.gap().onDisconnection(disconnectionCallback);

// Device role ****************************************************
ble.gattServer().onDataWritten(onReceivedDataFromCentralCallback);

UARTService uartService(ble);
uartServicePtr = &uartService;

// setup advertising
ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); // BLE only, no classic BT
ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); // add name
ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); // UUID's broadcast in advertising packet
ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); // advertising type
ble.setAdvertisingInterval(100); 

// Central role ****************************************************
ble.gattClient().onHVX(onReceivedDataFromDeviceCallback);
ble.gap().setScanParams(500, 450);


// start advertising and scan
ble.startAdvertising(); 
ble.gap().startScan(advertisementCallback);

while (true) 
{
      // allow notifications from device
      if (foundUartRXCharacteristic && !ble.gattClient().isServiceDiscoveryActive()) 
      {
        foundUartRXCharacteristic = false; /* need to do the following only once */

        uint16_t value = BLE_HVX_NOTIFICATION;
        ble.gattClient().write(GattClient::GATT_OP_WRITE_REQ,
                               connectionHandle,
                               uartRXCharacteristic.getValueHandle() + 1, /* HACK Alert. We're assuming that CCCD descriptor immediately follows the value attribute. */
                               sizeof(uint16_t),                          /* HACK Alert! size should be made into a BLE_API constant. */
                               reinterpret_cast<const uint8_t *>(&value));
    }

    // while a new char from computer is available
    while (rx_char != -1)
    {
        uint8_t command = rx_char;
        rx_char = -1;

        uint8_t temp[20];
        int length = 1;

        // if special char to test a 20 bytes frame
        if (command == '*')
        {
            pc.printf("20 chars\r\n");

            int c = 0;
            for (c = 0; c < 20; c++)
            {
                temp[c] = 'a' + c;
            }
            length = 20;
        }
        else
        {
            temp[0] = command;
        }

        // central to device 
        while (1)
        {                    
            int ret = uartTXCharacteristic.write(length, temp);
            if (ret == BLE_ERROR_NONE) 
            {
                break;
            }   
            else if (ret == BLE_STACK_BUSY) 
            {
                pc.printf("\r\nbusy (1)\r\n");
                //break;
            }
            else if (ret == BLE_ERROR_OPERATION_NOT_PERMITTED) 
            {
                pc.printf("\r\nnot connected (1)\r\n");
                break;
            }
            else
            {
                pc.printf("\r\ncode %d (1)\r\n", ret);
            }
        }

        // device to central
        while (1)
        {                        
            if (!ble.gap().getState().connected) 
            {
                break;
            }
            int ret = ble.gattServer().write(uartServicePtr->getRXCharacteristicHandle(), temp, length);
            if (ret == BLE_ERROR_NONE) 
            {
                break;
            }
            else if (ret == BLE_STACK_BUSY) 
            {
                pc.printf("\r\nbusy (2)\r\n");
                //break;
            }
            else if (ret == BLE_ERROR_OPERATION_NOT_PERMITTED) 
            {
                pc.printf("\r\nnot connected (2)\r\n");
                break;
            }
            else
            {
                pc.printf("\r\ncode %d (2)\r\n", ret);
            }
        }
    }

    ble.waitForEvent(); // save power
}

}

BLE::init() should be non-blocking

Currently the demo applications call init() and then expect to operate on the BLE instance rightaway. This model may not apply to stacks where initialization requires several rounds of blocking message passing between the host and the controller. BLE::init() should be non-blocking and should result in a completionCallback() when initialization is complete. It should also be possible for the application to determine if initailization is complete. Any use of a BLE instance before its initialization completes should return an error.

Typo in definition of UNIT_0_625_MS in Gap.h

This constant is currently defined as 650 when it should be defined as 625. I discovered this typo when attempting to set the advertising interval to 20ms (the minimum allowable value) and it was failing. With the typo corrected setting the advertising interval to 20ms now works.

we may want to introduce GattServer::addCharacteristic()

We currently only have GattServer::addService(), which requires us to collect the characteristics into an array before passing it into the service constructor. This forces an ugly pattern for construction. A better method would be:

GattService s(UUID,...);
ble.gattServer().addService(s);
GattCharacteristic c1(UUID,...);
ble.gattServer().addCharacteristic(c1);

or even better:
ble.gattServer() << s << c1 << ... ;

nRF51822 advertising interval problem

Hello,

There is a bug somewhere in the library regarding the advertising interval setting.
If using setAdvertisingInterval() I choose advertising interval <=4096 then all works fine, but if I choose advertising interval >4096 then device is not sending advertising packets.

why no BLEDevice::onDataWrite?

The framework has BLEDevice::onDataWritten that is called after write, but why no onDataWrite that would be called before write?

It seems generally useful to support characteristic value checking prior to write rather than the step of restoring characteristic values afterwards.

For example writing to TX Power Mode only accepts a uint8 in the range [0..3] and onDataWrite would return an error for other values.

It would also simplify the lock code checking in URIBeacon2Service.h

enableActiveScanning()

I am trying to start by passive scanning using enableActiveScanning(false) and then later when a certain data is received in the advertisement packet start active scanning( by using enableActiveScanning(true)).

It seems it is not possible to dynamically change between active and passive scanning as once the device starts with a particular activeScanning parameters, it is not possible to change ( active to passive or passive to active) later in the code.

URIBeacon2Service.h does not reset to defaults

Hi @rgrover

The reset operation in URIBeacon2Service.h should reset to default values:

Characteristic Default Value
Uri Data None
Uri Flags 0
TX Power Mode TX_POWER_MODE_LOW
Beacon Period 0 (disabled)
Lock 00000000-00000-0000-0000-000000000000

however beaconPeriodIn = 1000 and TX Power Mode is neither initialized or reset.

Also suggest originalURIData and similar be renamed to defaultUriData.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.