スマートロックソフトウェア(BLE nano用)

Dependencies:   BLE_API mbed nRF51822

Files at this revision

API Documentation at this revision

Comitter:
toshiyukisaito
Date:
Fri Sep 04 13:29:59 2015 +0000
Commit message:
SmartLock Version1

Changed in this revision

BLE_API.lib Show annotated file Show diff for this revision Revisions of this file
Servo.cpp Show annotated file Show diff for this revision Revisions of this file
Servo.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
nRF51822.lib Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BLE_API.lib	Fri Sep 04 13:29:59 2015 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/teams/Bluetooth-Low-Energy/code/BLE_API/#8d316a3271a8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Servo.cpp	Fri Sep 04 13:29:59 2015 +0000
@@ -0,0 +1,42 @@
+/*
+
+Copyright (c) 2012-2014 RedBearLab
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
+and associated documentation files (the "Software"), to deal in the Software without restriction, 
+including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 
+and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, 
+subject to the following conditions:
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 
+PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 
+FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include "Servo.h"
+
+Servo::Servo(PinName pin) : _servo(pin)
+{
+    _servo.period_ms(20);
+}
+
+Servo::~Servo(void)
+{
+    
+}
+
+void Servo::write(unsigned char degree)
+{
+    convert(degree);
+    _servo.pulsewidth_us(pulse);
+}
+
+void Servo::convert(unsigned char degree)
+{
+    // 0~180 degree correspond to 500~2500
+    pulse = degree * 11 + 500;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Servo.h	Fri Sep 04 13:29:59 2015 +0000
@@ -0,0 +1,40 @@
+/*
+
+Copyright (c) 2012-2014 RedBearLab
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
+and associated documentation files (the "Software"), to deal in the Software without restriction, 
+including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 
+and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, 
+subject to the following conditions:
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 
+PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 
+FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/
+
+#ifndef _SERVO_H
+#define _SERVO_H
+
+#include "mbed.h"
+
+class Servo
+{
+public:
+    Servo(PinName pin);
+    ~Servo(void);
+    
+    void write(unsigned char degree);
+
+private:
+    void convert(unsigned char degree);
+    
+    PwmOut _servo;
+    unsigned int pulse;
+};
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Fri Sep 04 13:29:59 2015 +0000
@@ -0,0 +1,261 @@
+#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();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Fri Sep 04 13:29:59 2015 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/8ed44a420e5c
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nRF51822.lib	Fri Sep 04 13:29:59 2015 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/teams/Nordic-Semiconductor/code/nRF51822/#ca9c9c2cfc6a