armmbed / ble Goto Github PK
View Code? Open in Web Editor NEWAPI to abstract working with Bluetooth Smart Controllers
License: Other
API to abstract working with Bluetooth Smart Controllers
License: Other
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.
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
This needs special handling since it is a reserved UUID. The present mechanism of adding descriptors through a table during construction doesn't work. Needs special handling.
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
Having a service similar to ble/services/iBeacon.h
but for Eddystone would be nice.
Eddystone protocol specification: https://github.com/google/eddystone/blob/master/protocol-specification.md
Sample source code: http://qiita.com/KazuyukiEguchi/items/a939a9aeae2d36c51df8
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.
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,
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
Hi @rgrover
The official name of the service is UriBeacon Configuration Service
We have an unpublished specification for UriBeacon Configuration Service V1 so that is why you are seeing V2. But for the purposes here we can keep the name simpler. Suggest UriBeaconConfigService since there may be other services, such as "telemetry" data.
Hi @rgrover
Devices implementing UriBeacon have modes:
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?
Hey.
getHandle returns a Handle_t, but updateCharacteristicValue expects an uint_16_t.
This was rather confusing, until i discovered that Handle_t was a typedef of uint_16_t.
May i suggest returning a uint_16_t from updateCharacteristicValue instead, as the discrepancy feels somewhat confusing?
it may be useful at times to construct DiscoveredCharacteristisc (and services) from persistent (cached) data. This will allow us to avoid service-discovery for every connection. BLE_API needs to be extended for this.
Hi @rgrover
The configure()
method does not seem to include a Service UUID field in the advertisement. It only sets the Service Data field.
Service UUID is necessary for background scanning on iOS.
http://developer.mbed.org/questions/7492/GattAttibute-Descriptors-preventing-Char/
the example code in GattAttribute.h does not refer to GattAttribute so isn't a great deal of help...
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.
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
Hi @rgrover
BLE_API / services / URIBeacon2Service.h
includes the definitions:
static const size_t MAX_SIZEOF_SERVICE_DATA_PAYLOAD = 27;
static const size_t MAX_SIZE_URI_DATA_CHAR_VALUE = 48;
However Uri Data must be between 0 and 18 bytes in length.
URIBeacon2Service.h
also treats Uri Data as unencoded but it is already encoded and should be treated as an opaque type.
The use of the function Gap::updateAdvertisingPayload can be improved:
gap.accumulateAdvertisingPayload(Gap::COMPLETE_LOCAL_NAME, "foo", 3);
// this call will return an error
gap.accumulateAdvertisingPayload(Gap::COMPLETE_LOCAL_NAME, "foobar", 6);
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.
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
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
}
}
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.
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("...");
}
}
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 to
createBLEInstance()'
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
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.
This is the root cause of: ARMmbed/ble-nrf51822#30
getPayload() should return the payload pointer regardless of len.
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 << ... ;
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).
Refer to the user request: https://developer.mbed.org/questions/61200/Setting-BLE-Characteristic-Units/
We need to support the presentation format descriptor when defining characteristics.
It would be nice if the "ScanResponse" API mirrored the "AdvertisingPayload" API.
In this regard, functions: setScanResponse
, getScanResponse
and updateScanResponse
are missing from the current GAP 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
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.
post instructions on building bootloader using armgcc.
It should be nice if we can use all roles of s130 at the same time.
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
Hi @rgrover
BLE_API / services / URIBeacon2Service.h
is missing Characteristic TX Power Mode
This characteristic provides an abstraction. Ideally TX_POWER_MODE_LOWEST
should equate to the nRF51822 whisper mode if running on an nRF51822, and lowest mode otherwise.
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.
is there a way for
void onDataWritten(const GattCharacteristicWriteCBParams *params)
to return a GATT error code (see error codes) when
the write attempt is made on a locked device?
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.
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.
Hi @rgrover,
I have the impression that the current version of ble is not "really" ported to mbedOS/minar as it still makes use of the "old" interfaces of Tickers and callbacks which get then executed in interupt context (e.g. https://github.com/ARMmbed/ble/blob/master/ble/services/EddystoneService.h#L490).
Can you confirm this and is there a version of the BLE stack which would use minar callbacks instaed?
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.
This was a poor choice for the original API. We should rectify it.
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)?
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 need to allow users to setup callbacks for handle-value update events (notifications and indications). There's also the need for APIs to enable these; that's going to be handled as a separate isssue.
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};
/work/iot/ble-examples/BLE_Thermometer/yotta_modules/ble/ble/services/HealthThermometerService.h:20:17: fatal error: BLE.h: No such file or directory
#include "BLE.h"
^
compilation terminated.
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?
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:
Hi @rgrover
setTxPowerLevel
should be setAdvertisedTxPowerLevels
to match the specification. The method takes an array int8[4]
for all the powerLevels
not a single mode
and txPowerIn
Also configure
should be called since changing the array can change the advertisement.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.