Toshiyuki Saito / Mbed 2 deprecated SmartLock-BLE-nano

Dependencies:   BLE_API mbed nRF51822

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include "mbed.h"
00002 #include "ble/BLE.h"
00003 #include "Servo.h"
00004 
00005 #define LOCAL_NAME             "SmartLock"
00006 #define TXRX_BUF_LEN           20
00007 #define SERVO_PIN              P0_8        // RTS
00008 #define SERVO_PWR_PIN          P0_11       // RXD
00009 #define SWITCH_PIN             P0_9        // TXD
00010 
00011 #define SERVO_ON_TIME          1           // s
00012 #define SWITCH_WATCH_INTERVAL  2           // s
00013 #define UNLOCK_PHRASE          "O"
00014 #define LOCK_PHRASE            "C"
00015 #define STATUS_PHRASE          "S"
00016 #define PAIRING_PHRASE         "PAIR"
00017 #define PASSPHRASE             "PSS_"
00018 #define SET_PASSPHRASE               "PHRASE"
00019 #define ALREADY_PAIRING        "ALREADY"
00020 #define PASSPHRASE_LENGTH      10
00021 
00022 #define UNLOCK_SERVO_POS       90
00023 #define LOCK_SERVO_POS         0
00024 
00025 #define ADVERTISING_INTERVAL   1000        // ms
00026 
00027 BLE ble;
00028 Servo servo(SERVO_PIN);
00029 DigitalOut sw(SERVO_PWR_PIN);
00030 DigitalIn toggle(SWITCH_PIN);
00031 DigitalOut led(P0_19);
00032 
00033 #define DEBUG 0
00034 
00035 #if DEBUG
00036 Serial pc(USBTX, USBRX);
00037 #endif
00038 
00039 static const uint8_t uart_base_uuid[]     = {0x71, 0x3D, 0x00, 0x00, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E};
00040 static const uint8_t uart_tx_uuid[]       = {0x71, 0x3D, 0x00, 0x03, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E};
00041 static const uint8_t uart_rx_uuid[]       = {0x71, 0x3D, 0x00, 0x02, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E};
00042 static const uint8_t uart_base_uuid_rev[] = {0x1E, 0x94, 0x8D, 0xF1, 0x48, 0x31, 0x94, 0xBA, 0x75, 0x4C, 0x3E, 0x50, 0x00, 0x00, 0x3D, 0x71};
00043 
00044 uint8_t txPayload[TXRX_BUF_LEN] = {0,};
00045 uint8_t rxPayload[TXRX_BUF_LEN] = {0,};
00046 
00047 GattCharacteristic  txCharacteristic (uart_tx_uuid, txPayload, 1, TXRX_BUF_LEN, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE);
00048 GattCharacteristic  rxCharacteristic (uart_rx_uuid, rxPayload, 1, TXRX_BUF_LEN, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
00049 GattCharacteristic *uartChars[] = {&txCharacteristic, &rxCharacteristic};
00050 GattService         uartService(uart_base_uuid, uartChars, sizeof(uartChars) / sizeof(GattCharacteristic *));
00051 
00052 bool isUnlock = false; // ロック状態
00053 bool isPairing = false; // ペアリング状態
00054 bool onPairing = false; // ペアリング中フラグ
00055 char phrase[TXRX_BUF_LEN] = {0,}; // パスフレーズ
00056 
00057 /*
00058   文字列prefix+s1とs2の比較を行います。
00059 */
00060 bool str_equal(const char* prefix, const char* s1, uint8_t* s2) {
00061     int i = 0;
00062     while (prefix[i] != '\0') {
00063         if (prefix[i] != (char) s2[i]) {
00064             return false;
00065         }
00066         i++;
00067     }
00068     int j = 0;
00069     while(s1[j] != '\0') {
00070         if (s1[j] != (char) s2[i]) {
00071             return false;
00072         }
00073         i++;
00074         j++;
00075     }
00076     return true;
00077 }
00078 
00079 /*
00080   char*の文字列をuint8_t*の文字列にコピーします。
00081 */
00082 void uintstr_cpy(uint8_t* dest, const char* src) {
00083     int i;
00084     for (i = 0; src[i] != '\0'; i++) {
00085         dest[i] = src[i];
00086     }
00087     dest[i] = '\0';
00088 }
00089 
00090 /*
00091   ロック状態のステータス更新
00092 */
00093 void UpdateStatus() {
00094     // ペアリングされていなければUpdateしない。
00095     if (!isPairing) return;
00096     uint8_t buf[2];
00097     uintstr_cpy(buf, isUnlock ? UNLOCK_PHRASE : LOCK_PHRASE);
00098     ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), buf, 2);
00099 }
00100 
00101 /*
00102     サムターン回転処理。unlock=trueで開錠。
00103 */
00104 void Thumbturn(bool unlock) {
00105     isUnlock = unlock;
00106     sw.write(1);
00107     wait(0.05);
00108     servo.write(isUnlock ? UNLOCK_SERVO_POS : LOCK_SERVO_POS);
00109     wait(SERVO_ON_TIME);
00110     UpdateStatus();
00111     sw.write(0);
00112     wait(0.05);
00113 }
00114 
00115 /*
00116   BLEのコールバック。centralと接続が切れた場合の処理。
00117 */
00118 void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason) {
00119     ble.startAdvertising();
00120 }
00121 
00122 /*
00123   BLEのコールバック。centralから書き込みがあった場合の処理
00124 */
00125 void WrittenHandler(const GattWriteCallbackParams *Handler) {
00126     uint8_t buf[TXRX_BUF_LEN];
00127     uint16_t bytesRead;
00128 
00129     if (Handler->handle == txCharacteristic.getValueAttribute().getHandle()) {
00130         ble.readCharacteristicValue(txCharacteristic.getValueAttribute().getHandle(), buf, &bytesRead);
00131         memset(txPayload, 0, TXRX_BUF_LEN);
00132         memcpy(txPayload, buf, bytesRead);
00133 #if DEBUG
00134         pc.printf("Receive: %d, %s\r\n", bytesRead, buf);
00135 #endif
00136 
00137         // ペアリングしていなくて、ステータスチェックが来たら
00138         if (!isPairing && str_equal(STATUS_PHRASE, "", buf)) {
00139                 // ペアリングの必要があるよ。
00140             uint8_t buf[TXRX_BUF_LEN];
00141             memset(txPayload, 0, TXRX_BUF_LEN);
00142             uintstr_cpy(buf, PAIRING_PHRASE);
00143             ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), buf, 5);
00144             return;
00145         }
00146 
00147         // ペアリング要求
00148         if (str_equal(PAIRING_PHRASE, "", buf)) {
00149 #if DEBUG
00150         pc.printf("Receive: PAIRING REQUEST\r\n", bytesRead, buf);
00151 #endif
00152             if (!isPairing) {
00153                     // パスフレーズ要求
00154                 onPairing = true;
00155                 uint8_t buf[TXRX_BUF_LEN];
00156                 memset(txPayload, 0, TXRX_BUF_LEN);
00157                 uintstr_cpy(buf, SET_PASSPHRASE);
00158                 ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), buf, 7);
00159             } else {
00160                 // ペアリング不可。電源を落としてください。
00161                 uint8_t buf[TXRX_BUF_LEN];
00162                 memset(txPayload, 0, TXRX_BUF_LEN);
00163                 uintstr_cpy(buf, ALREADY_PAIRING);
00164                 ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), buf, 8);
00165             }
00166             return;
00167         }
00168 
00169         // ペアリング処理中
00170         if (onPairing) {
00171             if (str_equal(PASSPHRASE, "", buf)) {
00172                 // appから10桁のコードをもらう
00173                 for (int i = 0; i < PASSPHRASE_LENGTH; i++) {
00174                     phrase[i] = buf[i + strlen(PASSPHRASE)];
00175                 }
00176                 phrase[PASSPHRASE_LENGTH+1] = '\0';
00177                 onPairing = false;
00178                 isPairing = true;
00179                 led.write(1);
00180                 wait(0.5);
00181             }
00182             return;
00183         }
00184 
00185         // ペアリング済み
00186         if(str_equal(UNLOCK_PHRASE, phrase, buf)) {
00187             Thumbturn(true);
00188         } else if(str_equal(LOCK_PHRASE, phrase, buf)) {
00189             Thumbturn(false);
00190         } else if(str_equal(STATUS_PHRASE, phrase, buf)) {
00191             UpdateStatus();
00192         }
00193     }
00194 }
00195 
00196 /*
00197   ステータスチェック。
00198   タイマーで一定時間ごとに呼び出される。
00199 */
00200 void StatusCheckHundler() {
00201 #if DEBUG
00202     pc.printf("SC %d %d\r\n", isPairing, onPairing);
00203 #endif
00204     if (isPairing) {
00205         // ペアリング済みならtoggleボタンでUnlock/Lockできる
00206         if (toggle.read() == 0) {
00207             if (isUnlock) {
00208                 Thumbturn(false);
00209             } else {
00210                 Thumbturn(true);
00211             }
00212         }
00213     } else {
00214         // 未ペアリング
00215 
00216         // onPairgingになったときにLEDを点滅させる
00217         if (onPairing) {
00218             if (led.read() != 0) {
00219                 led.write(0);
00220             } else {
00221                 led.write(1);
00222             }
00223         }
00224     }
00225 }
00226 
00227 int main(void) {
00228 #if DEBUG
00229     pc.baud(9600);
00230     pc.printf("INIT\r\n");
00231 #endif
00232 
00233     Ticker ticker;
00234     ticker.attach_us(StatusCheckHundler, SWITCH_WATCH_INTERVAL * 1000 * 1000);
00235 
00236     ble.init();
00237     ble.onDisconnection(disconnectionCallback);
00238     ble.onDataWritten(WrittenHandler);
00239 
00240     // setup advertising
00241     ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED);
00242     ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
00243     ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME,
00244                                     (const uint8_t *)LOCAL_NAME, sizeof(LOCAL_NAME) - 1);
00245     ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,
00246                                     (const uint8_t *)uart_base_uuid_rev, sizeof(uart_base_uuid));
00247     ble.setDeviceName(LOCAL_NAME);
00248     ble.setAdvertisingInterval(ADVERTISING_INTERVAL/0.625);
00249     ble.addService(uartService);
00250 
00251     ble.startAdvertising();
00252 
00253     // 起動時に、Lock状態にして、LEDを点灯させる(未ペアリングのため。)
00254     Thumbturn(false);
00255     led.write(0);
00256     toggle.mode(PullUp);
00257 
00258     while(true) {
00259         ble.waitForEvent();
00260     }
00261 }