![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
スマートロックソフトウェア(BLE nano用)
Dependencies: BLE_API mbed nRF51822
main.cpp
- Committer:
- toshiyukisaito
- Date:
- 2015-09-04
- Revision:
- 0:fcfa8140d2db
File content as of revision 0:fcfa8140d2db:
#include "mbed.h" #include "ble/BLE.h" #include "Servo.h" #define LOCAL_NAME "SmartLock" #define TXRX_BUF_LEN 20 #define SERVO_PIN P0_8 // RTS #define SERVO_PWR_PIN P0_11 // RXD #define SWITCH_PIN P0_9 // TXD #define SERVO_ON_TIME 1 // s #define SWITCH_WATCH_INTERVAL 2 // s #define UNLOCK_PHRASE "O" #define LOCK_PHRASE "C" #define STATUS_PHRASE "S" #define PAIRING_PHRASE "PAIR" #define PASSPHRASE "PSS_" #define SET_PASSPHRASE "PHRASE" #define ALREADY_PAIRING "ALREADY" #define PASSPHRASE_LENGTH 10 #define UNLOCK_SERVO_POS 90 #define LOCK_SERVO_POS 0 #define ADVERTISING_INTERVAL 1000 // ms BLE ble; Servo servo(SERVO_PIN); DigitalOut sw(SERVO_PWR_PIN); DigitalIn toggle(SWITCH_PIN); DigitalOut led(P0_19); #define DEBUG 0 #if DEBUG Serial pc(USBTX, USBRX); #endif static const uint8_t uart_base_uuid[] = {0x71, 0x3D, 0x00, 0x00, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E}; static const uint8_t uart_tx_uuid[] = {0x71, 0x3D, 0x00, 0x03, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E}; static const uint8_t uart_rx_uuid[] = {0x71, 0x3D, 0x00, 0x02, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E}; static const uint8_t uart_base_uuid_rev[] = {0x1E, 0x94, 0x8D, 0xF1, 0x48, 0x31, 0x94, 0xBA, 0x75, 0x4C, 0x3E, 0x50, 0x00, 0x00, 0x3D, 0x71}; uint8_t txPayload[TXRX_BUF_LEN] = {0,}; uint8_t rxPayload[TXRX_BUF_LEN] = {0,}; GattCharacteristic txCharacteristic (uart_tx_uuid, txPayload, 1, TXRX_BUF_LEN, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE); GattCharacteristic rxCharacteristic (uart_rx_uuid, rxPayload, 1, TXRX_BUF_LEN, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY); GattCharacteristic *uartChars[] = {&txCharacteristic, &rxCharacteristic}; GattService uartService(uart_base_uuid, uartChars, sizeof(uartChars) / sizeof(GattCharacteristic *)); bool isUnlock = false; // ロック状態 bool isPairing = false; // ペアリング状態 bool onPairing = false; // ペアリング中フラグ char phrase[TXRX_BUF_LEN] = {0,}; // パスフレーズ /* 文字列prefix+s1とs2の比較を行います。 */ bool str_equal(const char* prefix, const char* s1, uint8_t* s2) { int i = 0; while (prefix[i] != '\0') { if (prefix[i] != (char) s2[i]) { return false; } i++; } int j = 0; while(s1[j] != '\0') { if (s1[j] != (char) s2[i]) { return false; } i++; j++; } return true; } /* char*の文字列をuint8_t*の文字列にコピーします。 */ void uintstr_cpy(uint8_t* dest, const char* src) { int i; for (i = 0; src[i] != '\0'; i++) { dest[i] = src[i]; } dest[i] = '\0'; } /* ロック状態のステータス更新 */ void UpdateStatus() { // ペアリングされていなければUpdateしない。 if (!isPairing) return; uint8_t buf[2]; uintstr_cpy(buf, isUnlock ? UNLOCK_PHRASE : LOCK_PHRASE); ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), buf, 2); } /* サムターン回転処理。unlock=trueで開錠。 */ void Thumbturn(bool unlock) { isUnlock = unlock; sw.write(1); wait(0.05); servo.write(isUnlock ? UNLOCK_SERVO_POS : LOCK_SERVO_POS); wait(SERVO_ON_TIME); UpdateStatus(); sw.write(0); wait(0.05); } /* BLEのコールバック。centralと接続が切れた場合の処理。 */ void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason) { ble.startAdvertising(); } /* BLEのコールバック。centralから書き込みがあった場合の処理 */ void WrittenHandler(const GattWriteCallbackParams *Handler) { uint8_t buf[TXRX_BUF_LEN]; uint16_t bytesRead; if (Handler->handle == txCharacteristic.getValueAttribute().getHandle()) { ble.readCharacteristicValue(txCharacteristic.getValueAttribute().getHandle(), buf, &bytesRead); memset(txPayload, 0, TXRX_BUF_LEN); memcpy(txPayload, buf, bytesRead); #if DEBUG pc.printf("Receive: %d, %s\r\n", bytesRead, buf); #endif // ペアリングしていなくて、ステータスチェックが来たら if (!isPairing && str_equal(STATUS_PHRASE, "", buf)) { // ペアリングの必要があるよ。 uint8_t buf[TXRX_BUF_LEN]; memset(txPayload, 0, TXRX_BUF_LEN); uintstr_cpy(buf, PAIRING_PHRASE); ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), buf, 5); return; } // ペアリング要求 if (str_equal(PAIRING_PHRASE, "", buf)) { #if DEBUG pc.printf("Receive: PAIRING REQUEST\r\n", bytesRead, buf); #endif if (!isPairing) { // パスフレーズ要求 onPairing = true; uint8_t buf[TXRX_BUF_LEN]; memset(txPayload, 0, TXRX_BUF_LEN); uintstr_cpy(buf, SET_PASSPHRASE); ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), buf, 7); } else { // ペアリング不可。電源を落としてください。 uint8_t buf[TXRX_BUF_LEN]; memset(txPayload, 0, TXRX_BUF_LEN); uintstr_cpy(buf, ALREADY_PAIRING); ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), buf, 8); } return; } // ペアリング処理中 if (onPairing) { if (str_equal(PASSPHRASE, "", buf)) { // appから10桁のコードをもらう for (int i = 0; i < PASSPHRASE_LENGTH; i++) { phrase[i] = buf[i + strlen(PASSPHRASE)]; } phrase[PASSPHRASE_LENGTH+1] = '\0'; onPairing = false; isPairing = true; led.write(1); wait(0.5); } return; } // ペアリング済み if(str_equal(UNLOCK_PHRASE, phrase, buf)) { Thumbturn(true); } else if(str_equal(LOCK_PHRASE, phrase, buf)) { Thumbturn(false); } else if(str_equal(STATUS_PHRASE, phrase, buf)) { UpdateStatus(); } } } /* ステータスチェック。 タイマーで一定時間ごとに呼び出される。 */ void StatusCheckHundler() { #if DEBUG pc.printf("SC %d %d\r\n", isPairing, onPairing); #endif if (isPairing) { // ペアリング済みならtoggleボタンでUnlock/Lockできる if (toggle.read() == 0) { if (isUnlock) { Thumbturn(false); } else { Thumbturn(true); } } } else { // 未ペアリング // onPairgingになったときにLEDを点滅させる if (onPairing) { if (led.read() != 0) { led.write(0); } else { led.write(1); } } } } int main(void) { #if DEBUG pc.baud(9600); pc.printf("INIT\r\n"); #endif Ticker ticker; ticker.attach_us(StatusCheckHundler, SWITCH_WATCH_INTERVAL * 1000 * 1000); ble.init(); ble.onDisconnection(disconnectionCallback); ble.onDataWritten(WrittenHandler); // setup advertising ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED); ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME, (const uint8_t *)LOCAL_NAME, sizeof(LOCAL_NAME) - 1); ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, (const uint8_t *)uart_base_uuid_rev, sizeof(uart_base_uuid)); ble.setDeviceName(LOCAL_NAME); ble.setAdvertisingInterval(ADVERTISING_INTERVAL/0.625); ble.addService(uartService); ble.startAdvertising(); // 起動時に、Lock状態にして、LEDを点灯させる(未ペアリングのため。) Thumbturn(false); led.write(0); toggle.mode(PullUp); while(true) { ble.waitForEvent(); } }