Smart Button

Dependencies:   BLE_API mbed nRF51822

Committer:
vshymanskyy
Date:
Sun Oct 16 14:18:27 2016 +0000
Revision:
0:d7ba2329a303
Child:
1:795c0e3fbd4e
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
vshymanskyy 0:d7ba2329a303 1 /*
vshymanskyy 0:d7ba2329a303 2
vshymanskyy 0:d7ba2329a303 3 #define BUTTON_SERVICE_UUID 0xA000
vshymanskyy 0:d7ba2329a303 4 #define BUTTON_STATE_CHAR_UUID 0xA001
vshymanskyy 0:d7ba2329a303 5
vshymanskyy 0:d7ba2329a303 6 #define LED_SERVICE_UUID 0xB000
vshymanskyy 0:d7ba2329a303 7 #define LED_STATE_CHAR_UUID 0xB001
vshymanskyy 0:d7ba2329a303 8 #define LED_STATUS_CHAR_UUID 0xB002
vshymanskyy 0:d7ba2329a303 9
vshymanskyy 0:d7ba2329a303 10 const static char DEVICE_NAME[] = "Button";
vshymanskyy 0:d7ba2329a303 11 static const uint16_t uuid16_list[] = {BUTTON_SERVICE_UUID, LED_SERVICE_UUID};
vshymanskyy 0:d7ba2329a303 12
vshymanskyy 0:d7ba2329a303 13 bool buttonPressed = false;
vshymanskyy 0:d7ba2329a303 14
vshymanskyy 0:d7ba2329a303 15 ReadOnlyGattCharacteristic<bool> buttonState(BUTTON_STATE_CHAR_UUID, &buttonPressed, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
vshymanskyy 0:d7ba2329a303 16
vshymanskyy 0:d7ba2329a303 17 //static uint8_t readValue[10] = {0};
vshymanskyy 0:d7ba2329a303 18 //ReadOnlyArrayGattCharacteristic<uint8_t, sizeof(readValue)> readChar(LED_STATUS_CHAR_UUID, readValue);
vshymanskyy 0:d7ba2329a303 19
vshymanskyy 0:d7ba2329a303 20 static uint8_t writeValue[10] = {0};
vshymanskyy 0:d7ba2329a303 21 WriteOnlyArrayGattCharacteristic<uint8_t, sizeof(writeValue)> writeChar(LED_STATE_CHAR_UUID, writeValue);
vshymanskyy 0:d7ba2329a303 22
vshymanskyy 0:d7ba2329a303 23
vshymanskyy 0:d7ba2329a303 24
vshymanskyy 0:d7ba2329a303 25
vshymanskyy 0:d7ba2329a303 26 void writeCharCallback(const GattWriteCallbackParams* params)
vshymanskyy 0:d7ba2329a303 27 {
vshymanskyy 0:d7ba2329a303 28 // check to see what characteristic was written, by handle
vshymanskyy 0:d7ba2329a303 29 if(params->handle == writeChar.getValueHandle()) {
vshymanskyy 0:d7ba2329a303 30 // toggle LED if only 1 byte is written
vshymanskyy 0:d7ba2329a303 31 if(params->len == 1) {
vshymanskyy 0:d7ba2329a303 32 led2 = params->data[0] ? false : true;
vshymanskyy 0:d7ba2329a303 33 }
vshymanskyy 0:d7ba2329a303 34 // update the readChar with the value of writeChar
vshymanskyy 0:d7ba2329a303 35 //ble.updateCharacteristicValue(readChar.getValueHandle(),params->data,params->len);
vshymanskyy 0:d7ba2329a303 36 }
vshymanskyy 0:d7ba2329a303 37 }
vshymanskyy 0:d7ba2329a303 38
vshymanskyy 0:d7ba2329a303 39
vshymanskyy 0:d7ba2329a303 40
vshymanskyy 0:d7ba2329a303 41 void buttonPressedCallback(void)
vshymanskyy 0:d7ba2329a303 42 {
vshymanskyy 0:d7ba2329a303 43 buttonPressed = true;
vshymanskyy 0:d7ba2329a303 44 ble.updateCharacteristicValue(buttonState.getValueHandle(), (uint8_t *)&buttonPressed, sizeof(bool));
vshymanskyy 0:d7ba2329a303 45 //led2 = false;
vshymanskyy 0:d7ba2329a303 46 }
vshymanskyy 0:d7ba2329a303 47
vshymanskyy 0:d7ba2329a303 48 void buttonReleasedCallback(void)
vshymanskyy 0:d7ba2329a303 49 {
vshymanskyy 0:d7ba2329a303 50 buttonPressed = false;
vshymanskyy 0:d7ba2329a303 51 ble.updateCharacteristicValue(buttonState.getValueHandle(), (uint8_t *)&buttonPressed, sizeof(bool));
vshymanskyy 0:d7ba2329a303 52 //led2 = true;
vshymanskyy 0:d7ba2329a303 53 }
vshymanskyy 0:d7ba2329a303 54
vshymanskyy 0:d7ba2329a303 55 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t* reason)
vshymanskyy 0:d7ba2329a303 56 {
vshymanskyy 0:d7ba2329a303 57 ble.startAdvertising();
vshymanskyy 0:d7ba2329a303 58 led1 = 1;
vshymanskyy 0:d7ba2329a303 59 led2 = 1;
vshymanskyy 0:d7ba2329a303 60 }
vshymanskyy 0:d7ba2329a303 61
vshymanskyy 0:d7ba2329a303 62 void periodicCallback(void)
vshymanskyy 0:d7ba2329a303 63 {
vshymanskyy 0:d7ba2329a303 64 led1 = !led1; // Do blinky on LED1 to indicate system aliveness.
vshymanskyy 0:d7ba2329a303 65 }
vshymanskyy 0:d7ba2329a303 66
vshymanskyy 0:d7ba2329a303 67 int main(void)
vshymanskyy 0:d7ba2329a303 68 {
vshymanskyy 0:d7ba2329a303 69 led1 = 1;
vshymanskyy 0:d7ba2329a303 70 led2 = 1;
vshymanskyy 0:d7ba2329a303 71 Ticker ticker;
vshymanskyy 0:d7ba2329a303 72 ticker.attach(periodicCallback, 1);
vshymanskyy 0:d7ba2329a303 73 button.fall(buttonPressedCallback);
vshymanskyy 0:d7ba2329a303 74 button.rise(buttonReleasedCallback);
vshymanskyy 0:d7ba2329a303 75
vshymanskyy 0:d7ba2329a303 76 ble.init();
vshymanskyy 0:d7ba2329a303 77 ble.onDisconnection(disconnectionCallback);
vshymanskyy 0:d7ba2329a303 78 ble.onDataWritten(writeCharCallback);
vshymanskyy 0:d7ba2329a303 79
vshymanskyy 0:d7ba2329a303 80 GattCharacteristic *btnChars[] = {&buttonState};
vshymanskyy 0:d7ba2329a303 81 GattService buttonService(BUTTON_SERVICE_UUID, btnChars, sizeof(btnChars) / sizeof(GattCharacteristic *));
vshymanskyy 0:d7ba2329a303 82 ble.addService(buttonService);
vshymanskyy 0:d7ba2329a303 83
vshymanskyy 0:d7ba2329a303 84 // Set up custom service
vshymanskyy 0:d7ba2329a303 85 GattCharacteristic *ledChars[] = { &writeChar}; //&readChar,
vshymanskyy 0:d7ba2329a303 86 GattService ledService(LED_SERVICE_UUID, ledChars, sizeof(ledChars) / sizeof(GattCharacteristic *));
vshymanskyy 0:d7ba2329a303 87 ble.addService(ledService);
vshymanskyy 0:d7ba2329a303 88
vshymanskyy 0:d7ba2329a303 89 // setup advertising
vshymanskyy 0:d7ba2329a303 90 ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
vshymanskyy 0:d7ba2329a303 91 ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
vshymanskyy 0:d7ba2329a303 92 ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
vshymanskyy 0:d7ba2329a303 93 ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
vshymanskyy 0:d7ba2329a303 94 ble.setAdvertisingInterval(Gap::MSEC_TO_GAP_DURATION_UNITS(1000)); // 1000ms.
vshymanskyy 0:d7ba2329a303 95 ble.startAdvertising();
vshymanskyy 0:d7ba2329a303 96
vshymanskyy 0:d7ba2329a303 97 while (true) {
vshymanskyy 0:d7ba2329a303 98 ble.waitForEvent();
vshymanskyy 0:d7ba2329a303 99 }
vshymanskyy 0:d7ba2329a303 100 }
vshymanskyy 0:d7ba2329a303 101 */
vshymanskyy 0:d7ba2329a303 102
vshymanskyy 0:d7ba2329a303 103 #include "mbed.h"
vshymanskyy 0:d7ba2329a303 104 #include "BLE.h"
vshymanskyy 0:d7ba2329a303 105
vshymanskyy 0:d7ba2329a303 106 class ButtonService {
vshymanskyy 0:d7ba2329a303 107 public:
vshymanskyy 0:d7ba2329a303 108 const static uint16_t BUTTON_SERVICE_UUID = 0xA000;
vshymanskyy 0:d7ba2329a303 109 const static uint16_t BUTTON_STATE_CHARACTERISTIC_UUID = 0xA001;
vshymanskyy 0:d7ba2329a303 110
vshymanskyy 0:d7ba2329a303 111 ButtonService(BLEDevice &_ble, bool buttonPressedInitial) :
vshymanskyy 0:d7ba2329a303 112 ble(_ble), buttonState(BUTTON_STATE_CHARACTERISTIC_UUID, &buttonPressedInitial, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY)
vshymanskyy 0:d7ba2329a303 113 {
vshymanskyy 0:d7ba2329a303 114 GattCharacteristic *charTable[] = {&buttonState};
vshymanskyy 0:d7ba2329a303 115 GattService buttonService(ButtonService::BUTTON_SERVICE_UUID, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
vshymanskyy 0:d7ba2329a303 116 ble.gattServer().addService(buttonService);
vshymanskyy 0:d7ba2329a303 117 }
vshymanskyy 0:d7ba2329a303 118
vshymanskyy 0:d7ba2329a303 119 void updateButtonState(bool newState)
vshymanskyy 0:d7ba2329a303 120 {
vshymanskyy 0:d7ba2329a303 121 ble.gattServer().write(buttonState.getValueHandle(), (uint8_t *)&newState, sizeof(bool));
vshymanskyy 0:d7ba2329a303 122 }
vshymanskyy 0:d7ba2329a303 123
vshymanskyy 0:d7ba2329a303 124 private:
vshymanskyy 0:d7ba2329a303 125 BLEDevice &ble;
vshymanskyy 0:d7ba2329a303 126 ReadOnlyGattCharacteristic<bool> buttonState;
vshymanskyy 0:d7ba2329a303 127 };
vshymanskyy 0:d7ba2329a303 128
vshymanskyy 0:d7ba2329a303 129 class LEDService {
vshymanskyy 0:d7ba2329a303 130 public:
vshymanskyy 0:d7ba2329a303 131 const static uint16_t LED_SERVICE_UUID = 0xB000;
vshymanskyy 0:d7ba2329a303 132 const static uint16_t LED_STATE_CHARACTERISTIC_UUID = 0xB001;
vshymanskyy 0:d7ba2329a303 133
vshymanskyy 0:d7ba2329a303 134 LEDService(BLEDevice &_ble, bool initialValueForLEDCharacteristic = false) :
vshymanskyy 0:d7ba2329a303 135 ble(_ble), ledState(LED_STATE_CHARACTERISTIC_UUID, &initialValueForLEDCharacteristic)
vshymanskyy 0:d7ba2329a303 136 {
vshymanskyy 0:d7ba2329a303 137 GattCharacteristic *charTable[] = {&ledState};
vshymanskyy 0:d7ba2329a303 138 GattService ledService(LED_SERVICE_UUID, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
vshymanskyy 0:d7ba2329a303 139 ble.gattServer().addService(ledService);
vshymanskyy 0:d7ba2329a303 140 }
vshymanskyy 0:d7ba2329a303 141
vshymanskyy 0:d7ba2329a303 142 GattAttribute::Handle_t getValueHandle() const
vshymanskyy 0:d7ba2329a303 143 {
vshymanskyy 0:d7ba2329a303 144 return ledState.getValueHandle();
vshymanskyy 0:d7ba2329a303 145 }
vshymanskyy 0:d7ba2329a303 146
vshymanskyy 0:d7ba2329a303 147 private:
vshymanskyy 0:d7ba2329a303 148 BLEDevice &ble;
vshymanskyy 0:d7ba2329a303 149 ReadWriteGattCharacteristic<bool> ledState;
vshymanskyy 0:d7ba2329a303 150 };
vshymanskyy 0:d7ba2329a303 151
vshymanskyy 0:d7ba2329a303 152 class BuzzerService {
vshymanskyy 0:d7ba2329a303 153 public:
vshymanskyy 0:d7ba2329a303 154 const static uint16_t BUZZ_SERVICE_UUID = 0xC000;
vshymanskyy 0:d7ba2329a303 155 const static uint16_t BUZZ_STATE_CHARACTERISTIC_UUID = 0xC001;
vshymanskyy 0:d7ba2329a303 156
vshymanskyy 0:d7ba2329a303 157 BuzzerService(BLEDevice &_ble, uint16_t initialValue = 0) :
vshymanskyy 0:d7ba2329a303 158 ble(_ble), buzzState(BUZZ_STATE_CHARACTERISTIC_UUID, &initialValue)
vshymanskyy 0:d7ba2329a303 159 {
vshymanskyy 0:d7ba2329a303 160 GattCharacteristic *charTable[] = {&buzzState};
vshymanskyy 0:d7ba2329a303 161 GattService buzzService(BUZZ_SERVICE_UUID, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
vshymanskyy 0:d7ba2329a303 162 ble.gattServer().addService(buzzService);
vshymanskyy 0:d7ba2329a303 163 }
vshymanskyy 0:d7ba2329a303 164
vshymanskyy 0:d7ba2329a303 165 GattAttribute::Handle_t getValueHandle() const
vshymanskyy 0:d7ba2329a303 166 {
vshymanskyy 0:d7ba2329a303 167 return buzzState.getValueHandle();
vshymanskyy 0:d7ba2329a303 168 }
vshymanskyy 0:d7ba2329a303 169
vshymanskyy 0:d7ba2329a303 170 private:
vshymanskyy 0:d7ba2329a303 171 BLEDevice &ble;
vshymanskyy 0:d7ba2329a303 172 ReadWriteGattCharacteristic<uint16_t> buzzState;
vshymanskyy 0:d7ba2329a303 173 };
vshymanskyy 0:d7ba2329a303 174
vshymanskyy 0:d7ba2329a303 175 DigitalOut led1(p14);
vshymanskyy 0:d7ba2329a303 176 DigitalOut led2(p15);
vshymanskyy 0:d7ba2329a303 177 InterruptIn button(p16);
vshymanskyy 0:d7ba2329a303 178 PwmOut* buzzer = NULL;
vshymanskyy 0:d7ba2329a303 179
vshymanskyy 0:d7ba2329a303 180 void setBuzzer(uint16_t value) {
vshymanskyy 0:d7ba2329a303 181 if (value) {
vshymanskyy 0:d7ba2329a303 182 if (!buzzer) {
vshymanskyy 0:d7ba2329a303 183 buzzer = new PwmOut(p30);
vshymanskyy 0:d7ba2329a303 184 }
vshymanskyy 0:d7ba2329a303 185 buzzer->period(1.0/value);
vshymanskyy 0:d7ba2329a303 186 buzzer->write(0.5);
vshymanskyy 0:d7ba2329a303 187 } else {
vshymanskyy 0:d7ba2329a303 188 if (buzzer) {
vshymanskyy 0:d7ba2329a303 189 buzzer->write(0);
vshymanskyy 0:d7ba2329a303 190 delete buzzer;
vshymanskyy 0:d7ba2329a303 191 buzzer = NULL;
vshymanskyy 0:d7ba2329a303 192 }
vshymanskyy 0:d7ba2329a303 193 }
vshymanskyy 0:d7ba2329a303 194 }
vshymanskyy 0:d7ba2329a303 195
vshymanskyy 0:d7ba2329a303 196 static const uint8_t device_name[] = "Nut2";
vshymanskyy 0:d7ba2329a303 197 static const uint16_t uuid16_list[] = {
vshymanskyy 0:d7ba2329a303 198 ButtonService::BUTTON_SERVICE_UUID,
vshymanskyy 0:d7ba2329a303 199 LEDService::LED_SERVICE_UUID
vshymanskyy 0:d7ba2329a303 200 };
vshymanskyy 0:d7ba2329a303 201
vshymanskyy 0:d7ba2329a303 202 BLEDevice ble;
vshymanskyy 0:d7ba2329a303 203 ButtonService *svcButton;
vshymanskyy 0:d7ba2329a303 204 LEDService *svcLed1;
vshymanskyy 0:d7ba2329a303 205 LEDService *svcLed2;
vshymanskyy 0:d7ba2329a303 206 BuzzerService *svcBuzzer;
vshymanskyy 0:d7ba2329a303 207
vshymanskyy 0:d7ba2329a303 208 void buttonPressedCallback(void)
vshymanskyy 0:d7ba2329a303 209 {
vshymanskyy 0:d7ba2329a303 210 svcButton->updateButtonState(true);
vshymanskyy 0:d7ba2329a303 211 }
vshymanskyy 0:d7ba2329a303 212
vshymanskyy 0:d7ba2329a303 213 void buttonReleasedCallback(void)
vshymanskyy 0:d7ba2329a303 214 {
vshymanskyy 0:d7ba2329a303 215 svcButton->updateButtonState(false);
vshymanskyy 0:d7ba2329a303 216 }
vshymanskyy 0:d7ba2329a303 217
vshymanskyy 0:d7ba2329a303 218 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t* reason)
vshymanskyy 0:d7ba2329a303 219 {
vshymanskyy 0:d7ba2329a303 220 ble.startAdvertising();
vshymanskyy 0:d7ba2329a303 221 led1 = 1;
vshymanskyy 0:d7ba2329a303 222 led2 = 1;
vshymanskyy 0:d7ba2329a303 223 setBuzzer(0);
vshymanskyy 0:d7ba2329a303 224 }
vshymanskyy 0:d7ba2329a303 225
vshymanskyy 0:d7ba2329a303 226 void onDataWrittenCallback(const GattWriteCallbackParams *params)
vshymanskyy 0:d7ba2329a303 227 {
vshymanskyy 0:d7ba2329a303 228 if ((params->handle == svcLed1->getValueHandle()) && (params->len == 1)) {
vshymanskyy 0:d7ba2329a303 229 led1 = !*(params->data);
vshymanskyy 0:d7ba2329a303 230 } else if ((params->handle == svcLed2->getValueHandle()) && (params->len == 1)) {
vshymanskyy 0:d7ba2329a303 231 led2 = !*(params->data);
vshymanskyy 0:d7ba2329a303 232 } else if ((params->handle == svcBuzzer->getValueHandle()) && (params->len == 2)) {
vshymanskyy 0:d7ba2329a303 233 setBuzzer(*(uint16_t*)(params->data));
vshymanskyy 0:d7ba2329a303 234 }
vshymanskyy 0:d7ba2329a303 235 }
vshymanskyy 0:d7ba2329a303 236
vshymanskyy 0:d7ba2329a303 237 int main(void)
vshymanskyy 0:d7ba2329a303 238 {
vshymanskyy 0:d7ba2329a303 239 led1 = 1;
vshymanskyy 0:d7ba2329a303 240 led2 = 1;
vshymanskyy 0:d7ba2329a303 241 setBuzzer(0);
vshymanskyy 0:d7ba2329a303 242 //Ticker ticker;
vshymanskyy 0:d7ba2329a303 243 //ticker.attach([] { led1 = !led1; }, 1.0);
vshymanskyy 0:d7ba2329a303 244 button.fall(buttonPressedCallback);
vshymanskyy 0:d7ba2329a303 245 button.rise(buttonReleasedCallback);
vshymanskyy 0:d7ba2329a303 246
vshymanskyy 0:d7ba2329a303 247 ble.init();
vshymanskyy 0:d7ba2329a303 248 ble.onDisconnection(disconnectionCallback);
vshymanskyy 0:d7ba2329a303 249 ble.gattServer().onDataWritten(onDataWrittenCallback);
vshymanskyy 0:d7ba2329a303 250
vshymanskyy 0:d7ba2329a303 251 svcButton = new ButtonService(ble, false);
vshymanskyy 0:d7ba2329a303 252 svcLed1 = new LEDService(ble);
vshymanskyy 0:d7ba2329a303 253 svcLed2 = new LEDService(ble);
vshymanskyy 0:d7ba2329a303 254 svcBuzzer = new BuzzerService(ble);
vshymanskyy 0:d7ba2329a303 255
vshymanskyy 0:d7ba2329a303 256 // setup advertising
vshymanskyy 0:d7ba2329a303 257 ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
vshymanskyy 0:d7ba2329a303 258 ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
vshymanskyy 0:d7ba2329a303 259 ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, device_name, sizeof(device_name));
vshymanskyy 0:d7ba2329a303 260
vshymanskyy 0:d7ba2329a303 261 ble.gap().setDeviceName(device_name);
vshymanskyy 0:d7ba2329a303 262 ble.gap().setTxPower(4);
vshymanskyy 0:d7ba2329a303 263 ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
vshymanskyy 0:d7ba2329a303 264 ble.gap().setAdvertisingInterval(Gap::MSEC_TO_GAP_DURATION_UNITS(1000));
vshymanskyy 0:d7ba2329a303 265 ble.gap().setAdvertisingTimeout(0);
vshymanskyy 0:d7ba2329a303 266 ble.startAdvertising();
vshymanskyy 0:d7ba2329a303 267
vshymanskyy 0:d7ba2329a303 268 while (true) {
vshymanskyy 0:d7ba2329a303 269 ble.waitForEvent();
vshymanskyy 0:d7ba2329a303 270 }
vshymanskyy 0:d7ba2329a303 271 }