BLE Application to open a Garage door
Dependencies: BLE_API Crypto RNG mbed nRF51822
Fork of BLE_LED by
main.cpp@15:88ea59cb2b9e, 2017-05-01 (annotated)
- Committer:
- duststorm
- Date:
- Mon May 01 00:33:07 2017 +0000
- Revision:
- 15:88ea59cb2b9e
- Parent:
- 13:bc1be947b497
force address for Nano to F2:9B:4B:03:02:01 to match the prefix expected by the app
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
dgomes | 13:bc1be947b497 | 1 | //#define DEBUG |
dgomes | 9:329af8cdc923 | 2 | |
dgomes | 9:329af8cdc923 | 3 | #ifndef DEBUG |
dgomes | 9:329af8cdc923 | 4 | #define DEVICE_SERIAL 0 //disable SERIAL so me can use P0_8 (shared with serial) |
dgomes | 9:329af8cdc923 | 5 | #define DBG(...) |
dgomes | 9:329af8cdc923 | 6 | #else |
dgomes | 9:329af8cdc923 | 7 | #define DBG printf |
dgomes | 9:329af8cdc923 | 8 | #endif |
rgrover1 | 0:ed5c53845de7 | 9 | |
rgrover1 | 0:ed5c53845de7 | 10 | #include "mbed.h" |
rgrover1 | 6:fca54d71d10e | 11 | #include "BLE.h" |
dgomes | 9:329af8cdc923 | 12 | #include "GaragemService.h" |
dgomes | 11:3de9b542eeac | 13 | #include "SecurityService.h" |
dgomes | 9:329af8cdc923 | 14 | #include "ble/services/iBeacon.h" |
dgomes | 9:329af8cdc923 | 15 | #include "DeviceInformationService.h" |
dgomes | 9:329af8cdc923 | 16 | |
dgomes | 11:3de9b542eeac | 17 | // HOW-TO TEST: |
dgomes | 11:3de9b542eeac | 18 | //create a string to write to the characteristic 2000:2001 |
dgomes | 10:80850cd6c29e | 19 | //openssl enc -aes-128-cbc -K 9734062BA852A049CF5D40593B769014 -iv A2685636521871D02306E2EB8F7027B3 -out /dev/stdout -in inputfile |
dgomes | 10:80850cd6c29e | 20 | // TTTTIIIISSSSSSSS |
dgomes | 10:80850cd6c29e | 21 | // T -> 4 bytes Timestamp uint32_t |
dgomes | 10:80850cd6c29e | 22 | // I -> 4 bytes ID (chars) |
dgomes | 10:80850cd6c29e | 23 | // S -> 8 bytes SHARED_SECRET (chars) |
dgomes | 10:80850cd6c29e | 24 | |
dgomes | 12:eaee29bfa1c7 | 25 | // Generating K and iv: |
dgomes | 12:eaee29bfa1c7 | 26 | //openssl enc -aes-128-cbc -pass pass:********** -nosalt -P |
dgomes | 12:eaee29bfa1c7 | 27 | |
dgomes | 9:329af8cdc923 | 28 | #define SHARED_KEY "figueiredo" |
dgomes | 9:329af8cdc923 | 29 | #define DEVICE_NAME "Garagem" |
rgrover1 | 0:ed5c53845de7 | 30 | |
rgrover1 | 7:c9271599ec5f | 31 | BLE ble; |
dgomes | 9:329af8cdc923 | 32 | DigitalOut actuatedLED(P0_19); |
dgomes | 9:329af8cdc923 | 33 | Timeout offRelay; |
dgomes | 12:eaee29bfa1c7 | 34 | bool boot; |
dgomes | 9:329af8cdc923 | 35 | #ifndef DEBUG |
dgomes | 9:329af8cdc923 | 36 | DigitalOut relay(P0_8); |
dgomes | 9:329af8cdc923 | 37 | #endif |
dgomes | 9:329af8cdc923 | 38 | |
dgomes | 11:3de9b542eeac | 39 | static const uint16_t uuid16_list[] = {GaragemService::GARAGEM_SERVICE_UUID, SecurityService::SECURITY_SERVICE_UUID}; |
rgrover1 | 0:ed5c53845de7 | 40 | |
dgomes | 9:329af8cdc923 | 41 | GaragemService *garagemServicePtr; |
dgomes | 11:3de9b542eeac | 42 | SecurityService *securityServicePtr; |
rgrover1 | 0:ed5c53845de7 | 43 | |
dgomes | 9:329af8cdc923 | 44 | void switchOffRelay() |
dgomes | 9:329af8cdc923 | 45 | { |
dgomes | 9:329af8cdc923 | 46 | actuatedLED = !actuatedLED; |
dgomes | 9:329af8cdc923 | 47 | DBG("JA CHEGA...\r\n"); |
dgomes | 9:329af8cdc923 | 48 | #ifndef DEBUG |
dgomes | 9:329af8cdc923 | 49 | relay = 0; |
dgomes | 9:329af8cdc923 | 50 | #endif |
dgomes | 9:329af8cdc923 | 51 | } |
dgomes | 9:329af8cdc923 | 52 | |
rgrover1 | 0:ed5c53845de7 | 53 | void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason) |
dgomes | 9:329af8cdc923 | 54 | { |
dgomes | 9:329af8cdc923 | 55 | ble.startAdvertising(); |
rgrover1 | 0:ed5c53845de7 | 56 | } |
dgomes | 11:3de9b542eeac | 57 | |
rgrover1 | 7:c9271599ec5f | 58 | void onDataWrittenCallback(const GattWriteCallbackParams *params) { |
dgomes | 9:329af8cdc923 | 59 | DBG("onDataWrittenCallback: handle = %d len = %d\r\n", params->handle, params->len); |
dgomes | 10:80850cd6c29e | 60 | garagemServicePtr->nextLastOpen(params->data, params->len); |
dgomes | 10:80850cd6c29e | 61 | |
dgomes | 9:329af8cdc923 | 62 | if ((params->handle == garagemServicePtr->getChallengeHandle()) && (params->len ==16)) { |
dgomes | 10:80850cd6c29e | 63 | DBG("We have Challenge: data = %s\r\n", (char *) (params->data)); |
dgomes | 9:329af8cdc923 | 64 | |
dgomes | 9:329af8cdc923 | 65 | uint8_t msg[16]; |
dgomes | 11:3de9b542eeac | 66 | securityServicePtr->decode(msg, (uint8_t *) params->data, 16); |
dgomes | 9:329af8cdc923 | 67 | |
dgomes | 9:329af8cdc923 | 68 | if(garagemServicePtr->checkMessage(msg) == GARAGEM_OK) { |
dgomes | 10:80850cd6c29e | 69 | DBG("ABRE-TE SESAMO!\r\n"); |
dgomes | 10:80850cd6c29e | 70 | |
dgomes | 9:329af8cdc923 | 71 | #ifndef DEBUG |
dgomes | 9:329af8cdc923 | 72 | relay = 1; |
dgomes | 9:329af8cdc923 | 73 | #endif |
dgomes | 10:80850cd6c29e | 74 | actuatedLED = !actuatedLED; |
dgomes | 9:329af8cdc923 | 75 | //please cleanup afterwards |
dgomes | 9:329af8cdc923 | 76 | offRelay.attach(&switchOffRelay, 1.0); |
dgomes | 9:329af8cdc923 | 77 | |
dgomes | 9:329af8cdc923 | 78 | } else { |
dgomes | 9:329af8cdc923 | 79 | DBG("NO SUCH LUCK...\r\n"); |
dgomes | 9:329af8cdc923 | 80 | } |
dgomes | 12:eaee29bfa1c7 | 81 | } if(boot && (params->handle == securityServicePtr->getKeyHandle()) && (params->len > 0)) { |
dgomes | 11:3de9b542eeac | 82 | securityServicePtr->setKey((char *) params->data); |
dgomes | 11:3de9b542eeac | 83 | } |
dgomes | 12:eaee29bfa1c7 | 84 | boot = false; |
rgrover1 | 0:ed5c53845de7 | 85 | } |
rgrover1 | 0:ed5c53845de7 | 86 | |
rgrover1 | 0:ed5c53845de7 | 87 | int main(void) |
rgrover1 | 0:ed5c53845de7 | 88 | { |
dgomes | 9:329af8cdc923 | 89 | DBG("Garagem v0\r\n"); |
rgrover1 | 0:ed5c53845de7 | 90 | |
dgomes | 12:eaee29bfa1c7 | 91 | boot = true; |
dgomes | 9:329af8cdc923 | 92 | actuatedLED = true; |
dgomes | 9:329af8cdc923 | 93 | #ifndef DEBUG |
dgomes | 9:329af8cdc923 | 94 | relay = 0; |
dgomes | 9:329af8cdc923 | 95 | #endif |
rgrover1 | 0:ed5c53845de7 | 96 | |
rgrover1 | 0:ed5c53845de7 | 97 | ble.init(); |
duststorm | 15:88ea59cb2b9e | 98 | |
duststorm | 15:88ea59cb2b9e | 99 | // Note that the Garagem app that is in the Google Play store has the prefix for the BLE Nano hardcoded as F2:9B:4B, but newer Nanos do not have this prefix |
duststorm | 15:88ea59cb2b9e | 100 | // The following line changes the address on your Nano to ensure it will work with the app as is. |
duststorm | 15:88ea59cb2b9e | 101 | const uint8_t address1[] = {0x01,0x02,0x03,0x4B,0x9B,0xF2}; ble.setAddress(Gap::ADDR_TYPE_PUBLIC, address1); |
duststorm | 15:88ea59cb2b9e | 102 | |
dgomes | 9:329af8cdc923 | 103 | ble.onDisconnection(disconnectionCallback); |
rgrover1 | 7:c9271599ec5f | 104 | ble.gattServer().onDataWritten(onDataWrittenCallback); |
rgrover1 | 0:ed5c53845de7 | 105 | |
dgomes | 9:329af8cdc923 | 106 | /** |
dgomes | 9:329af8cdc923 | 107 | * The Beacon payload has the following composition: |
dgomes | 9:329af8cdc923 | 108 | * 128-Bit / 16byte UUID = E2 0A 39 F4 73 F5 4B C4 A1 2F 17 D1 AD 07 A9 61 |
dgomes | 9:329af8cdc923 | 109 | * Major/Minor = 0x1122 / 0x3344 |
dgomes | 9:329af8cdc923 | 110 | * Tx Power = 0xC8 = 200, 2's compliment is 256-200 = (-56dB) |
dgomes | 9:329af8cdc923 | 111 | * |
dgomes | 9:329af8cdc923 | 112 | * Note: please remember to calibrate your beacons TX Power for more accurate results. |
dgomes | 9:329af8cdc923 | 113 | */ |
dgomes | 9:329af8cdc923 | 114 | const uint8_t uuid[] = {0xE2, 0x0A, 0x39, 0xF4, 0x73, 0xF5, 0x4B, 0xC4, |
dgomes | 9:329af8cdc923 | 115 | 0xA1, 0x2F, 0x17, 0xD1, 0xAD, 0x07, 0xA9, 0x61}; |
dgomes | 9:329af8cdc923 | 116 | uint16_t majorNumber = 3800; |
dgomes | 9:329af8cdc923 | 117 | uint16_t minorNumber = 1423; |
dgomes | 9:329af8cdc923 | 118 | uint16_t txPower = 0xBE; |
dgomes | 9:329af8cdc923 | 119 | iBeacon ibeacon(ble, uuid, majorNumber, minorNumber, txPower); |
dgomes | 12:eaee29bfa1c7 | 120 | |
dgomes | 12:eaee29bfa1c7 | 121 | DeviceInformationService deviceInfo(ble, "diogogomes.com", DEVICE_NAME, "SN1", "hw-rev1", "fw-rev1", "soft-rev1"); |
dgomes | 9:329af8cdc923 | 122 | |
dgomes | 9:329af8cdc923 | 123 | GaragemService garagemService(ble); |
dgomes | 9:329af8cdc923 | 124 | garagemServicePtr = &garagemService; |
dgomes | 11:3de9b542eeac | 125 | |
dgomes | 12:eaee29bfa1c7 | 126 | SecurityService securityService(ble); |
dgomes | 12:eaee29bfa1c7 | 127 | securityService.init(SHARED_KEY); |
dgomes | 11:3de9b542eeac | 128 | securityServicePtr = &securityService; |
dgomes | 9:329af8cdc923 | 129 | |
rgrover1 | 0:ed5c53845de7 | 130 | /* setup advertising */ |
rgrover1 | 7:c9271599ec5f | 131 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); |
rgrover1 | 7:c9271599ec5f | 132 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); |
rgrover1 | 7:c9271599ec5f | 133 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); |
rgrover1 | 7:c9271599ec5f | 134 | ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); |
dgomes | 9:329af8cdc923 | 135 | |
dgomes | 9:329af8cdc923 | 136 | |
rgrover1 | 7:c9271599ec5f | 137 | ble.gap().setAdvertisingInterval(1000); /* 1000ms. */ |
rgrover1 | 7:c9271599ec5f | 138 | ble.gap().startAdvertising(); |
rgrover1 | 0:ed5c53845de7 | 139 | |
rgrover1 | 0:ed5c53845de7 | 140 | while (true) { |
rgrover1 | 0:ed5c53845de7 | 141 | ble.waitForEvent(); |
rgrover1 | 0:ed5c53845de7 | 142 | } |
rgrover1 | 0:ed5c53845de7 | 143 | } |