Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: BLE_API mbed nRF51822
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 }
Generated on Wed Jul 13 2022 01:30:39 by
1.7.2