Smart Button

Dependencies:   BLE_API mbed nRF51822

main.cpp

Committer:
vshymanskyy
Date:
2016-10-16
Revision:
0:d7ba2329a303
Child:
1:795c0e3fbd4e

File content as of revision 0:d7ba2329a303:

/*

#define BUTTON_SERVICE_UUID     0xA000
#define BUTTON_STATE_CHAR_UUID  0xA001

#define LED_SERVICE_UUID        0xB000
#define LED_STATE_CHAR_UUID     0xB001
#define LED_STATUS_CHAR_UUID    0xB002
 
const static char     DEVICE_NAME[] = "Button";
static const uint16_t uuid16_list[] = {BUTTON_SERVICE_UUID, LED_SERVICE_UUID};
 
bool buttonPressed = false;

ReadOnlyGattCharacteristic<bool> buttonState(BUTTON_STATE_CHAR_UUID, &buttonPressed, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);

//static uint8_t readValue[10] = {0};
//ReadOnlyArrayGattCharacteristic<uint8_t, sizeof(readValue)> readChar(LED_STATUS_CHAR_UUID, readValue);
 
static uint8_t writeValue[10] = {0};
WriteOnlyArrayGattCharacteristic<uint8_t, sizeof(writeValue)> writeChar(LED_STATE_CHAR_UUID, writeValue);




void writeCharCallback(const GattWriteCallbackParams* params)
{
    // check to see what characteristic was written, by handle
    if(params->handle == writeChar.getValueHandle()) {
        // toggle LED if only 1 byte is written
        if(params->len == 1) {
            led2 = params->data[0] ? false : true;
        }
        // update the readChar with the value of writeChar
        //ble.updateCharacteristicValue(readChar.getValueHandle(),params->data,params->len);
    }
}



void buttonPressedCallback(void)
{
    buttonPressed = true;
    ble.updateCharacteristicValue(buttonState.getValueHandle(), (uint8_t *)&buttonPressed, sizeof(bool));
    //led2 = false;
}
 
void buttonReleasedCallback(void)
{
    buttonPressed = false;
    ble.updateCharacteristicValue(buttonState.getValueHandle(), (uint8_t *)&buttonPressed, sizeof(bool));
    //led2 = true;
}
 
void disconnectionCallback(const Gap::DisconnectionCallbackParams_t* reason)
{
    ble.startAdvertising();
    led1 = 1;
    led2 = 1;
}
 
void periodicCallback(void)
{
    led1 = !led1; // Do blinky on LED1 to indicate system aliveness. 
}
 
int main(void)
{
    led1 = 1;
    led2 = 1;
    Ticker ticker;
    ticker.attach(periodicCallback, 1);
    button.fall(buttonPressedCallback);
    button.rise(buttonReleasedCallback);
 
    ble.init();
    ble.onDisconnection(disconnectionCallback);
    ble.onDataWritten(writeCharCallback);
 
    GattCharacteristic *btnChars[] = {&buttonState};
    GattService         buttonService(BUTTON_SERVICE_UUID, btnChars, sizeof(btnChars) / sizeof(GattCharacteristic *));
    ble.addService(buttonService);

    // Set up custom service
    GattCharacteristic *ledChars[] = { &writeChar}; //&readChar,
    GattService        ledService(LED_SERVICE_UUID, ledChars, sizeof(ledChars) / sizeof(GattCharacteristic *));
    ble.addService(ledService);
    
    // 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::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
    ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
    ble.setAdvertisingInterval(Gap::MSEC_TO_GAP_DURATION_UNITS(1000)); // 1000ms.
    ble.startAdvertising();
 
    while (true) {
        ble.waitForEvent();
    }
}
*/

#include "mbed.h"
#include "BLE.h"

class ButtonService {
public:
    const static uint16_t BUTTON_SERVICE_UUID              = 0xA000;
    const static uint16_t BUTTON_STATE_CHARACTERISTIC_UUID = 0xA001;
 
    ButtonService(BLEDevice &_ble, bool buttonPressedInitial) :
        ble(_ble), buttonState(BUTTON_STATE_CHARACTERISTIC_UUID, &buttonPressedInitial, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY)
    {
        GattCharacteristic *charTable[] = {&buttonState};
        GattService         buttonService(ButtonService::BUTTON_SERVICE_UUID, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
        ble.gattServer().addService(buttonService);
    }
 
    void updateButtonState(bool newState)
    {
        ble.gattServer().write(buttonState.getValueHandle(), (uint8_t *)&newState, sizeof(bool));
    }
 
private:
    BLEDevice &ble;
    ReadOnlyGattCharacteristic<bool> buttonState;
};

class LEDService {
public:
    const static uint16_t LED_SERVICE_UUID              = 0xB000;
    const static uint16_t LED_STATE_CHARACTERISTIC_UUID = 0xB001;
 
    LEDService(BLEDevice &_ble, bool initialValueForLEDCharacteristic = false) :
        ble(_ble), ledState(LED_STATE_CHARACTERISTIC_UUID, &initialValueForLEDCharacteristic)
    {
        GattCharacteristic *charTable[] = {&ledState};
        GattService         ledService(LED_SERVICE_UUID, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
        ble.gattServer().addService(ledService);
    }
 
    GattAttribute::Handle_t getValueHandle() const
    {
        return ledState.getValueHandle();
    }
 
private:
    BLEDevice &ble;
    ReadWriteGattCharacteristic<bool> ledState;
};

class BuzzerService {
public:
    const static uint16_t BUZZ_SERVICE_UUID              = 0xC000;
    const static uint16_t BUZZ_STATE_CHARACTERISTIC_UUID = 0xC001;
 
    BuzzerService(BLEDevice &_ble, uint16_t initialValue = 0) :
        ble(_ble), buzzState(BUZZ_STATE_CHARACTERISTIC_UUID, &initialValue)
    {
        GattCharacteristic *charTable[] = {&buzzState};
        GattService         buzzService(BUZZ_SERVICE_UUID, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
        ble.gattServer().addService(buzzService);
    }
 
    GattAttribute::Handle_t getValueHandle() const
    {
        return buzzState.getValueHandle();
    }
 
private:
    BLEDevice &ble;
    ReadWriteGattCharacteristic<uint16_t> buzzState;
};

DigitalOut  led1(p14);
DigitalOut  led2(p15);
InterruptIn button(p16);
PwmOut*     buzzer = NULL;

void setBuzzer(uint16_t value) {
    if (value) {
        if (!buzzer) {
            buzzer = new PwmOut(p30);
        }
        buzzer->period(1.0/value);
        buzzer->write(0.5);
    } else {
        if (buzzer) {
            buzzer->write(0);
            delete buzzer;
            buzzer = NULL;
        }
    }
}

static const uint8_t device_name[] = "Nut2";
static const uint16_t uuid16_list[] = {
    ButtonService::BUTTON_SERVICE_UUID,
    LEDService::LED_SERVICE_UUID
};

BLEDevice      ble;
ButtonService *svcButton;
LEDService    *svcLed1;
LEDService    *svcLed2;
BuzzerService *svcBuzzer;
 
void buttonPressedCallback(void)
{
    svcButton->updateButtonState(true);
}
 
void buttonReleasedCallback(void)
{
    svcButton->updateButtonState(false);
}

void disconnectionCallback(const Gap::DisconnectionCallbackParams_t* reason)
{
    ble.startAdvertising();
    led1 = 1;
    led2 = 1;
    setBuzzer(0);
}

void onDataWrittenCallback(const GattWriteCallbackParams *params)
{
    if ((params->handle == svcLed1->getValueHandle()) && (params->len == 1)) {
        led1 = !*(params->data);
    } else if ((params->handle == svcLed2->getValueHandle()) && (params->len == 1)) {
        led2 = !*(params->data);
    } else if ((params->handle == svcBuzzer->getValueHandle()) && (params->len == 2)) {
        setBuzzer(*(uint16_t*)(params->data));
    }
}
 
int main(void)
{
    led1 = 1;
    led2 = 1;
    setBuzzer(0);
    //Ticker ticker;
    //ticker.attach([] { led1 = !led1; }, 1.0);
    button.fall(buttonPressedCallback);
    button.rise(buttonReleasedCallback);
 
    ble.init();
    ble.onDisconnection(disconnectionCallback);
    ble.gattServer().onDataWritten(onDataWrittenCallback);
 
    svcButton = new ButtonService(ble, false);
    svcLed1 = new LEDService(ble);
    svcLed2 = new LEDService(ble);
    svcBuzzer = new BuzzerService(ble);
 
    // 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::COMPLETE_LOCAL_NAME, device_name, sizeof(device_name));

    ble.gap().setDeviceName(device_name);
    ble.gap().setTxPower(4);
    ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
    ble.gap().setAdvertisingInterval(Gap::MSEC_TO_GAP_DURATION_UNITS(1000));
    ble.gap().setAdvertisingTimeout(0);
    ble.startAdvertising();
 
    while (true) {
        ble.waitForEvent();
    }
}