Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BLE: user can optionally send characteristic value with/without ACK. #1901

Merged
merged 13 commits into from Sep 9, 2019

Conversation

@XuGuohui
Copy link
Contributor

commented Sep 4, 2019

Problem

For local characteristic with NOTIFY and INDICATE property, it will only send notification even if peer device subscribed indication.

For peer characteristic with NOTIFY and INDICATE property, it will only subscribe notification.

For peer characteristic with WRITE and WRITE_WO_RSP property, it will only send data without response.

Solution

  • Introduces BleCharacteristic::setValue(..., BleTxRxType) API for user to optionally send data with/without acknowledgement.
  • Subscribes both notification and indication if both properties are presented with peer characteristic.

Steps to Test

  1. Build and flash the below example app to two Gen3 devices respectively.
  2. Connect two devices to serial terminal respectively.
  3. Simply type '1', '2', and '3' on one side terminal to see if another terminal can successfully receive these characters, and vice versa.

Example App

BLE Peripheral:

#include "Particle.h"

#define UART_TX_BUF_SIZE        20

SYSTEM_MODE(MANUAL);

void onDataReceived(const uint8_t* data, size_t len, const BlePeerDevice& peer, void* context);

const char* serviceUuid = "6E400001-B5A3-F393-E0A9-E50E24DCCA9E";
const char* rxUuid = "6E400002-B5A3-F393-E0A9-E50E24DCCA9E";
const char* txUuid = "6E400003-B5A3-F393-E0A9-E50E24DCCA9E";

BleCharacteristic txCharacteristic("tx",
                                   BleCharacteristicProperty::NOTIFY | BleCharacteristicProperty::INDICATE,
                                   txUuid,
                                   serviceUuid);

BleCharacteristic rxCharacteristic("rx",
                                   BleCharacteristicProperty::WRITE_WO_RSP | BleCharacteristicProperty::WRITE,
                                   rxUuid,
                                   serviceUuid,
                                   onDataReceived, &rxCharacteristic);

uint8_t txBuf[UART_TX_BUF_SIZE];
size_t txLen = 0;

void onDataReceived(const uint8_t* data, size_t len, const BlePeerDevice& peer, void* context) {
    for (uint8_t i = 0; i < len; i++) {
        Serial.write(data[i]);
    }
}

void setup() {
    Serial.begin(115200);

    LOG(TRACE, "Application started.");

    BLE.addCharacteristic(txCharacteristic);
    BLE.addCharacteristic(rxCharacteristic);

    BleAdvertisingData data;
    data.appendServiceUUID(serviceUuid);
    BLE.advertise(&data);
}

void loop() {
    if (BLE.connected()) {
        while (Serial.available() && txLen < UART_TX_BUF_SIZE) {
            txBuf[txLen++] = Serial.read();
            Serial.write(txBuf[txLen - 1]);
        }

        if (txLen > 0) {
            if (txBuf[0] == '1') {
                txCharacteristic.setValue(txBuf, txLen);
            } else if (txBuf[0] == '2') {
                txCharacteristic.setValue(txBuf, txLen, BleTxRxType::ACK);
            } else {
                txCharacteristic.setValue(txBuf, txLen, BleTxRxType::NACK);
            }
            txLen = 0;
        }
    }
}

BLE Central:

#include "Particle.h"

SYSTEM_MODE(MANUAL);

#define UART_TX_BUF_SIZE        20
#define SCAN_RESULT_COUNT       20

BleScanResult results[SCAN_RESULT_COUNT];

BleCharacteristic peerTxCharacteristic;
BleCharacteristic peerRxCharacteristic;
BlePeerDevice peer;

uint8_t txBuf[UART_TX_BUF_SIZE];
size_t txLen = 0;

void onDataReceived(const uint8_t* data, size_t len, const BlePeerDevice& peer, void* context) {
    for (uint8_t i = 0; i < len; i++) {
        Serial.write(data[i]);
    }
}

void setup() {
    Serial.begin(115200);
    peerTxCharacteristic.onDataReceived(onDataReceived, &peerTxCharacteristic);
}

void loop() {
    if (BLE.connected()) {
        while (Serial.available() && txLen < UART_TX_BUF_SIZE) {
            txBuf[txLen++] = Serial.read();
            Serial.write(txBuf[txLen - 1]);
        }
        if (txLen > 0) {
            if (txBuf[0] == '1') {
                peerRxCharacteristic.setValue(txBuf, txLen);
            } else if (txBuf[0] == '2') {
                peerRxCharacteristic.setValue(txBuf, txLen, BleTxRxType::ACK);
            } else {
                peerRxCharacteristic.setValue(txBuf, txLen, BleTxRxType::NACK);
            }
            txLen = 0;
        }
    }
    else {
        delay(3000);
        size_t count = BLE.scan(results, SCAN_RESULT_COUNT);
        if (count > 0) {
            for (uint8_t i = 0; i < count; i++) {
                BleUuid foundServiceUUID;
                size_t svcCount = results[i].advertisingData.serviceUUID(&foundServiceUUID, 1);
                if (svcCount > 0 && foundServiceUUID == "6E400001-B5A3-F393-E0A9-E50E24DCCA9E") {
                    peer = BLE.connect(results[i].address);
                    if (peer.connected()) {
                        peer.getCharacteristicByDescription(peerTxCharacteristic, "tx");
                        peer.getCharacteristicByUUID(peerRxCharacteristic, "6E400002-B5A3-F393-E0A9-E50E24DCCA9E");
                    }
                    break;
                }
            }
        }
    }
}

References

N/A

@XuGuohui XuGuohui requested a review from avtolstoy Sep 4, 2019

@XuGuohui XuGuohui added needs review ble and removed in progress labels Sep 4, 2019

@XuGuohui XuGuohui added this to the 1.4.0 milestone Sep 4, 2019

@avtolstoy
Copy link
Member

left a comment

@XuGuohui We don't normally put enhancements and features straight into a default (non-rc) release and most of the times not even between rcs. If we are to make such an exception, I will have to ask to rework the test apps from the PR description in the form of tests (much like i2c_master_slave) and include them in this PR, so that they can be run without much interaction during the release process and verify that things function as intended.

hal/inc/ble_hal_defines.h Outdated Show resolved Hide resolved
wiring/inc/spark_wiring_ble.h Outdated Show resolved Hide resolved
wiring/inc/spark_wiring_ble.h Outdated Show resolved Hide resolved
wiring/src/spark_wiring_ble.cpp Outdated Show resolved Hide resolved
wiring/inc/spark_wiring_ble.h Outdated Show resolved Hide resolved
@avtolstoy avtolstoy referenced this pull request Sep 5, 2019

@XuGuohui XuGuohui requested a review from avtolstoy Sep 5, 2019

wiring/src/spark_wiring_ble.cpp Outdated Show resolved Hide resolved

@XuGuohui XuGuohui requested a review from avtolstoy Sep 5, 2019

@avtolstoy
Copy link
Member

left a comment

LGTM. Still, please add the tests.

wiring/inc/spark_wiring_ble.h Outdated Show resolved Hide resolved

@XuGuohui XuGuohui force-pushed the fix/ble_notification branch from 36eb5d8 to f4d9c99 Sep 5, 2019

@XuGuohui XuGuohui requested a review from avtolstoy Sep 5, 2019

@avtolstoy avtolstoy force-pushed the fix/ble_notification branch from 627934f to 0ba780c Sep 9, 2019

@avtolstoy avtolstoy merged commit d06b6ba into develop Sep 9, 2019

3 of 4 checks passed

Codacy/PR Quality Review Not up to standards. This pull request quality could be better.
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details
continuous-integration/travis-ci/push The Travis CI build passed
Details
coverage/coveralls Coverage remained the same at 42.422%
Details

@avtolstoy avtolstoy deleted the fix/ble_notification branch Sep 9, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.