Safety confirmation program for the elderly persons. (LPC1768)
Dependencies: EthernetInterface HTTPClient mbed-rtos mbed
main.cpp@0:928a824c31d7, 2015-02-13 (annotated)
- Committer:
- mkttanabe
- Date:
- Fri Feb 13 11:36:45 2015 +0000
- Revision:
- 0:928a824c31d7
first commit.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
mkttanabe | 0:928a824c31d7 | 1 | /* |
mkttanabe | 0:928a824c31d7 | 2 | * Copyright (C) 2015 KLab Inc. |
mkttanabe | 0:928a824c31d7 | 3 | * |
mkttanabe | 0:928a824c31d7 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
mkttanabe | 0:928a824c31d7 | 5 | * you may not use this file except in compliance with the License. |
mkttanabe | 0:928a824c31d7 | 6 | * You may obtain a copy of the License at |
mkttanabe | 0:928a824c31d7 | 7 | * |
mkttanabe | 0:928a824c31d7 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
mkttanabe | 0:928a824c31d7 | 9 | * |
mkttanabe | 0:928a824c31d7 | 10 | * Unless required by applicable law or agreed to in writing, software |
mkttanabe | 0:928a824c31d7 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
mkttanabe | 0:928a824c31d7 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
mkttanabe | 0:928a824c31d7 | 13 | * See the License for the specific language governing permissions and |
mkttanabe | 0:928a824c31d7 | 14 | * limitations under the License. |
mkttanabe | 0:928a824c31d7 | 15 | */ |
mkttanabe | 0:928a824c31d7 | 16 | |
mkttanabe | 0:928a824c31d7 | 17 | #include "mbed.h" |
mkttanabe | 0:928a824c31d7 | 18 | #include "EthernetInterface.h" |
mkttanabe | 0:928a824c31d7 | 19 | #include "HTTPClient.h" |
mkttanabe | 0:928a824c31d7 | 20 | |
mkttanabe | 0:928a824c31d7 | 21 | #define DEVELOP |
mkttanabe | 0:928a824c31d7 | 22 | #ifdef DEVELOP |
mkttanabe | 0:928a824c31d7 | 23 | #define dbg(...) printf(__VA_ARGS__) |
mkttanabe | 0:928a824c31d7 | 24 | #else |
mkttanabe | 0:928a824c31d7 | 25 | #define dbg(...) |
mkttanabe | 0:928a824c31d7 | 26 | #endif |
mkttanabe | 0:928a824c31d7 | 27 | |
mkttanabe | 0:928a824c31d7 | 28 | // Parse.com に設置ずみのの対向アプリの ID と RESTAPIKEY |
mkttanabe | 0:928a824c31d7 | 29 | #define PARSE_COM_APPID "** YOUR PARSE APP ID **" |
mkttanabe | 0:928a824c31d7 | 30 | #define PARSE_COM_RESTAPIKEY "** YOUR PARSE APP REST API KEY **" |
mkttanabe | 0:928a824c31d7 | 31 | |
mkttanabe | 0:928a824c31d7 | 32 | #define REQUEST_HEADER_FOR_PARSE_COM \ |
mkttanabe | 0:928a824c31d7 | 33 | "X-Parse-Application-Id: " PARSE_COM_APPID "\r\n" \ |
mkttanabe | 0:928a824c31d7 | 34 | "X-Parse-REST-API-Key: " PARSE_COM_RESTAPIKEY "\r\n" \ |
mkttanabe | 0:928a824c31d7 | 35 | "Content-Type: " "application/json" "\r\n" |
mkttanabe | 0:928a824c31d7 | 36 | |
mkttanabe | 0:928a824c31d7 | 37 | #define URL_POSTDATA "https://api.parse.com/1/functions/detected" |
mkttanabe | 0:928a824c31d7 | 38 | #define URL_SENDMAIL "https://api.parse.com/1/functions/sendmail" |
mkttanabe | 0:928a824c31d7 | 39 | |
mkttanabe | 0:928a824c31d7 | 40 | // for LM61BIZ |
mkttanabe | 0:928a824c31d7 | 41 | #define GAP_DIGREE_ZERO (600.0/3300.0) |
mkttanabe | 0:928a824c31d7 | 42 | #define DIGREE_PER_VALUE (10.0/3300.0) |
mkttanabe | 0:928a824c31d7 | 43 | |
mkttanabe | 0:928a824c31d7 | 44 | #define SW_ON 0 |
mkttanabe | 0:928a824c31d7 | 45 | #define LED_MAX 5 |
mkttanabe | 0:928a824c31d7 | 46 | #define HTTPS_REQUEST_INTERVAL 1800 // 30分 |
mkttanabe | 0:928a824c31d7 | 47 | |
mkttanabe | 0:928a824c31d7 | 48 | EthernetInterface eth; |
mkttanabe | 0:928a824c31d7 | 49 | HTTPClient http; |
mkttanabe | 0:928a824c31d7 | 50 | LocalFileSystem local("local"); |
mkttanabe | 0:928a824c31d7 | 51 | |
mkttanabe | 0:928a824c31d7 | 52 | #define DEVICEID_FILENAME "/local/id.txt" |
mkttanabe | 0:928a824c31d7 | 53 | #define DEVICEID_MAXLENGTH 16 |
mkttanabe | 0:928a824c31d7 | 54 | |
mkttanabe | 0:928a824c31d7 | 55 | DigitalOut LEDS[LED_MAX] = {p21, LED1, LED2, LED3, LED4}; |
mkttanabe | 0:928a824c31d7 | 56 | DigitalOut buzzer(p5); // 電子ブザー |
mkttanabe | 0:928a824c31d7 | 57 | AnalogIn sensorTEMP(p15); // 温度センサ |
mkttanabe | 0:928a824c31d7 | 58 | DigitalIn sensorPIR(p20); // 赤外線センサ |
mkttanabe | 0:928a824c31d7 | 59 | DigitalIn switchPUSH(p24); // 外付けプッシュボタン |
mkttanabe | 0:928a824c31d7 | 60 | Ticker timer; |
mkttanabe | 0:928a824c31d7 | 61 | char deviceId[DEVICEID_MAXLENGTH]; |
mkttanabe | 0:928a824c31d7 | 62 | |
mkttanabe | 0:928a824c31d7 | 63 | // すべてのLEDをON/OFF |
mkttanabe | 0:928a824c31d7 | 64 | void LedsShow(int OnOrOff) |
mkttanabe | 0:928a824c31d7 | 65 | { |
mkttanabe | 0:928a824c31d7 | 66 | for (int i = 0; i < LED_MAX; i++) { |
mkttanabe | 0:928a824c31d7 | 67 | LEDS[i] = OnOrOff; |
mkttanabe | 0:928a824c31d7 | 68 | } |
mkttanabe | 0:928a824c31d7 | 69 | } |
mkttanabe | 0:928a824c31d7 | 70 | |
mkttanabe | 0:928a824c31d7 | 71 | // すべてのLEDを順次点灯 |
mkttanabe | 0:928a824c31d7 | 72 | void LedsRotate(float interval) |
mkttanabe | 0:928a824c31d7 | 73 | { |
mkttanabe | 0:928a824c31d7 | 74 | LedsShow(0); |
mkttanabe | 0:928a824c31d7 | 75 | for (int i = 0; i < LED_MAX; i++) { |
mkttanabe | 0:928a824c31d7 | 76 | LEDS[i] = 1; |
mkttanabe | 0:928a824c31d7 | 77 | wait(interval); |
mkttanabe | 0:928a824c31d7 | 78 | } |
mkttanabe | 0:928a824c31d7 | 79 | LedsShow(0); |
mkttanabe | 0:928a824c31d7 | 80 | } |
mkttanabe | 0:928a824c31d7 | 81 | |
mkttanabe | 0:928a824c31d7 | 82 | // time() 用にダミー日時をセット |
mkttanabe | 0:928a824c31d7 | 83 | void setTime() |
mkttanabe | 0:928a824c31d7 | 84 | { |
mkttanabe | 0:928a824c31d7 | 85 | struct tm t; |
mkttanabe | 0:928a824c31d7 | 86 | t.tm_sec = 1; |
mkttanabe | 0:928a824c31d7 | 87 | t.tm_min = 1; |
mkttanabe | 0:928a824c31d7 | 88 | t.tm_hour = 1; |
mkttanabe | 0:928a824c31d7 | 89 | t.tm_mday = 1; |
mkttanabe | 0:928a824c31d7 | 90 | t.tm_mon = 1; |
mkttanabe | 0:928a824c31d7 | 91 | t.tm_year = 100; |
mkttanabe | 0:928a824c31d7 | 92 | time_t seconds = mktime(&t); |
mkttanabe | 0:928a824c31d7 | 93 | set_time(seconds); |
mkttanabe | 0:928a824c31d7 | 94 | } |
mkttanabe | 0:928a824c31d7 | 95 | |
mkttanabe | 0:928a824c31d7 | 96 | void handlerLedsRotate() |
mkttanabe | 0:928a824c31d7 | 97 | { |
mkttanabe | 0:928a824c31d7 | 98 | LedsRotate(0.1); |
mkttanabe | 0:928a824c31d7 | 99 | } |
mkttanabe | 0:928a824c31d7 | 100 | |
mkttanabe | 0:928a824c31d7 | 101 | void handlerLed1Blink() |
mkttanabe | 0:928a824c31d7 | 102 | { |
mkttanabe | 0:928a824c31d7 | 103 | LEDS[1] = !LEDS[1]; |
mkttanabe | 0:928a824c31d7 | 104 | } |
mkttanabe | 0:928a824c31d7 | 105 | |
mkttanabe | 0:928a824c31d7 | 106 | // 初期化 |
mkttanabe | 0:928a824c31d7 | 107 | int init() |
mkttanabe | 0:928a824c31d7 | 108 | { |
mkttanabe | 0:928a824c31d7 | 109 | int sts; |
mkttanabe | 0:928a824c31d7 | 110 | |
mkttanabe | 0:928a824c31d7 | 111 | // 押しボタン接続ポートの DigitalIn をプルアップ |
mkttanabe | 0:928a824c31d7 | 112 | switchPUSH.mode(PullUp); |
mkttanabe | 0:928a824c31d7 | 113 | |
mkttanabe | 0:928a824c31d7 | 114 | setTime(); |
mkttanabe | 0:928a824c31d7 | 115 | timer.attach(&handlerLedsRotate, 1); |
mkttanabe | 0:928a824c31d7 | 116 | |
mkttanabe | 0:928a824c31d7 | 117 | // イーサネットの初期化 |
mkttanabe | 0:928a824c31d7 | 118 | dbg("- start eth.init\r\n" ); |
mkttanabe | 0:928a824c31d7 | 119 | sts = eth.init(); //Use DHCP |
mkttanabe | 0:928a824c31d7 | 120 | if (sts != 0) { |
mkttanabe | 0:928a824c31d7 | 121 | dbg("- ech.init error!\r\n" ); |
mkttanabe | 0:928a824c31d7 | 122 | timer.detach(); |
mkttanabe | 0:928a824c31d7 | 123 | return -1; |
mkttanabe | 0:928a824c31d7 | 124 | } |
mkttanabe | 0:928a824c31d7 | 125 | |
mkttanabe | 0:928a824c31d7 | 126 | dbg("- start eth.connect\r\n" ); |
mkttanabe | 0:928a824c31d7 | 127 | sts = eth.connect(); |
mkttanabe | 0:928a824c31d7 | 128 | if (sts != 0) { |
mkttanabe | 0:928a824c31d7 | 129 | dbg("- eth.connect error!\r\n" ); |
mkttanabe | 0:928a824c31d7 | 130 | timer.detach(); |
mkttanabe | 0:928a824c31d7 | 131 | return -2; |
mkttanabe | 0:928a824c31d7 | 132 | } |
mkttanabe | 0:928a824c31d7 | 133 | dbg("- my IP Address = %s\r\n", eth.getIPAddress()); |
mkttanabe | 0:928a824c31d7 | 134 | |
mkttanabe | 0:928a824c31d7 | 135 | // 自デバイス名を id.txt から読み込む |
mkttanabe | 0:928a824c31d7 | 136 | strncpy(deviceId, eth.getIPAddress(), 15); |
mkttanabe | 0:928a824c31d7 | 137 | deviceId[15] = '\0'; |
mkttanabe | 0:928a824c31d7 | 138 | FILE *fp = fopen(DEVICEID_FILENAME, "r"); |
mkttanabe | 0:928a824c31d7 | 139 | if (!fp) { |
mkttanabe | 0:928a824c31d7 | 140 | // id.txt が存在しなければ新規作成し IP アドレスを書き込む |
mkttanabe | 0:928a824c31d7 | 141 | fp = fopen(DEVICEID_FILENAME, "w"); |
mkttanabe | 0:928a824c31d7 | 142 | if (fp) { |
mkttanabe | 0:928a824c31d7 | 143 | fprintf(fp, "%s", deviceId); |
mkttanabe | 0:928a824c31d7 | 144 | } |
mkttanabe | 0:928a824c31d7 | 145 | } else { |
mkttanabe | 0:928a824c31d7 | 146 | fgets(deviceId, DEVICEID_MAXLENGTH, fp); |
mkttanabe | 0:928a824c31d7 | 147 | for (int i = 0; i < DEVICEID_MAXLENGTH; i++) { |
mkttanabe | 0:928a824c31d7 | 148 | if (deviceId[i] == '\r' || deviceId[i] == '\n') { |
mkttanabe | 0:928a824c31d7 | 149 | deviceId[i] = '\0'; |
mkttanabe | 0:928a824c31d7 | 150 | break; |
mkttanabe | 0:928a824c31d7 | 151 | } |
mkttanabe | 0:928a824c31d7 | 152 | } |
mkttanabe | 0:928a824c31d7 | 153 | } |
mkttanabe | 0:928a824c31d7 | 154 | if (fp) { |
mkttanabe | 0:928a824c31d7 | 155 | fclose(fp); |
mkttanabe | 0:928a824c31d7 | 156 | } |
mkttanabe | 0:928a824c31d7 | 157 | dbg("- my DeviceId = %s\r\n", deviceId); |
mkttanabe | 0:928a824c31d7 | 158 | |
mkttanabe | 0:928a824c31d7 | 159 | // センサ安定化待ち |
mkttanabe | 0:928a824c31d7 | 160 | wait(4.0); |
mkttanabe | 0:928a824c31d7 | 161 | timer.detach(); |
mkttanabe | 0:928a824c31d7 | 162 | return 0; |
mkttanabe | 0:928a824c31d7 | 163 | } |
mkttanabe | 0:928a824c31d7 | 164 | |
mkttanabe | 0:928a824c31d7 | 165 | // Parse.com への POST |
mkttanabe | 0:928a824c31d7 | 166 | int postToParseCom(const char *ApiUrl, char *postData) |
mkttanabe | 0:928a824c31d7 | 167 | { |
mkttanabe | 0:928a824c31d7 | 168 | int sts; |
mkttanabe | 0:928a824c31d7 | 169 | char buf[256]; |
mkttanabe | 0:928a824c31d7 | 170 | HTTPText dataToPost(postData); |
mkttanabe | 0:928a824c31d7 | 171 | HTTPText resData(buf, sizeof(buf)); |
mkttanabe | 0:928a824c31d7 | 172 | http.setHeader(REQUEST_HEADER_FOR_PARSE_COM); |
mkttanabe | 0:928a824c31d7 | 173 | dbg("- start HTTPS request\r\n"); |
mkttanabe | 0:928a824c31d7 | 174 | sts = http.post(ApiUrl, dataToPost, &resData, HTTP_CLIENT_DEFAULT_TIMEOUT); |
mkttanabe | 0:928a824c31d7 | 175 | if (sts == HTTP_OK) { |
mkttanabe | 0:928a824c31d7 | 176 | dbg("- received HTTPS response\r\n"); |
mkttanabe | 0:928a824c31d7 | 177 | dbg("- head of data [%s]\r\n", buf); |
mkttanabe | 0:928a824c31d7 | 178 | dbg("- done\r\n\r\n"); |
mkttanabe | 0:928a824c31d7 | 179 | } else { |
mkttanabe | 0:928a824c31d7 | 180 | dbg("- HTTPS request error=%d, status=%d\r\n", sts, http.getHTTPResponseCode()); |
mkttanabe | 0:928a824c31d7 | 181 | dbg("- head of data [%s]\r\n", buf); |
mkttanabe | 0:928a824c31d7 | 182 | return sts; |
mkttanabe | 0:928a824c31d7 | 183 | } |
mkttanabe | 0:928a824c31d7 | 184 | return HTTP_OK; |
mkttanabe | 0:928a824c31d7 | 185 | } |
mkttanabe | 0:928a824c31d7 | 186 | |
mkttanabe | 0:928a824c31d7 | 187 | // エントリーポイント |
mkttanabe | 0:928a824c31d7 | 188 | int main() |
mkttanabe | 0:928a824c31d7 | 189 | { |
mkttanabe | 0:928a824c31d7 | 190 | time_t lastRequestTime = 0; |
mkttanabe | 0:928a824c31d7 | 191 | char reqData[128]; |
mkttanabe | 0:928a824c31d7 | 192 | int sts = init(); |
mkttanabe | 0:928a824c31d7 | 193 | if (sts != 0) { |
mkttanabe | 0:928a824c31d7 | 194 | // 初期化エラー時は LED 全点灯で終了 |
mkttanabe | 0:928a824c31d7 | 195 | LedsShow(1); |
mkttanabe | 0:928a824c31d7 | 196 | return -1; |
mkttanabe | 0:928a824c31d7 | 197 | } |
mkttanabe | 0:928a824c31d7 | 198 | while(1) { |
mkttanabe | 0:928a824c31d7 | 199 | int buttonPressedMsecs = 0; |
mkttanabe | 0:928a824c31d7 | 200 | // 緊急ボタン押下状態 |
mkttanabe | 0:928a824c31d7 | 201 | while (switchPUSH == SW_ON) { |
mkttanabe | 0:928a824c31d7 | 202 | LEDS[2] = 1; |
mkttanabe | 0:928a824c31d7 | 203 | // 長押し2秒でメール送信 |
mkttanabe | 0:928a824c31d7 | 204 | if (buttonPressedMsecs >= 2000) { |
mkttanabe | 0:928a824c31d7 | 205 | LEDS[1] = 1; |
mkttanabe | 0:928a824c31d7 | 206 | buzzer = 1; // ブザーを鳴らす |
mkttanabe | 0:928a824c31d7 | 207 | dbg("- long-pressed\r\n"); |
mkttanabe | 0:928a824c31d7 | 208 | // デバイス名 |
mkttanabe | 0:928a824c31d7 | 209 | sprintf(reqData, "{\"devid\" : \"%s\"}", deviceId); |
mkttanabe | 0:928a824c31d7 | 210 | sts = postToParseCom(URL_SENDMAIL, reqData); |
mkttanabe | 0:928a824c31d7 | 211 | if (sts != HTTP_OK) { |
mkttanabe | 0:928a824c31d7 | 212 | // あとで考える |
mkttanabe | 0:928a824c31d7 | 213 | } |
mkttanabe | 0:928a824c31d7 | 214 | break; |
mkttanabe | 0:928a824c31d7 | 215 | } |
mkttanabe | 0:928a824c31d7 | 216 | wait(0.2); |
mkttanabe | 0:928a824c31d7 | 217 | buttonPressedMsecs += 200; |
mkttanabe | 0:928a824c31d7 | 218 | } |
mkttanabe | 0:928a824c31d7 | 219 | LEDS[1] = LEDS[2] = 0; |
mkttanabe | 0:928a824c31d7 | 220 | buzzer = 0; |
mkttanabe | 0:928a824c31d7 | 221 | |
mkttanabe | 0:928a824c31d7 | 222 | // 赤外線センサ反応状態 |
mkttanabe | 0:928a824c31d7 | 223 | int detected = sensorPIR; |
mkttanabe | 0:928a824c31d7 | 224 | if (!detected) { |
mkttanabe | 0:928a824c31d7 | 225 | LEDS[0] = 0; |
mkttanabe | 0:928a824c31d7 | 226 | } else { |
mkttanabe | 0:928a824c31d7 | 227 | if (LEDS[0] == 0) { |
mkttanabe | 0:928a824c31d7 | 228 | LEDS[0] = 1; |
mkttanabe | 0:928a824c31d7 | 229 | dbg("- detected!\r\n"); |
mkttanabe | 0:928a824c31d7 | 230 | // 温度センサの出力電圧値を摂氏値に |
mkttanabe | 0:928a824c31d7 | 231 | float valueTemp = (sensorTEMP - GAP_DIGREE_ZERO) / DIGREE_PER_VALUE; |
mkttanabe | 0:928a824c31d7 | 232 | dbg("- temperature = %2.1f C\r\n", valueTemp); |
mkttanabe | 0:928a824c31d7 | 233 | |
mkttanabe | 0:928a824c31d7 | 234 | // 前回の送信から所定時間が経過していれば再び送信 |
mkttanabe | 0:928a824c31d7 | 235 | int elapsed = time(NULL) - lastRequestTime; |
mkttanabe | 0:928a824c31d7 | 236 | if (elapsed > HTTPS_REQUEST_INTERVAL) { |
mkttanabe | 0:928a824c31d7 | 237 | // 温度情報・デバイス名・ローカル IP アドレス |
mkttanabe | 0:928a824c31d7 | 238 | sprintf(reqData, "{\"temp\" : \"%2.1f\", \"devid\" : \"%s\", \"ip\" : \"%s\"}", |
mkttanabe | 0:928a824c31d7 | 239 | valueTemp, deviceId, eth.getIPAddress()); |
mkttanabe | 0:928a824c31d7 | 240 | timer.detach(); |
mkttanabe | 0:928a824c31d7 | 241 | LEDS[1] = 1; |
mkttanabe | 0:928a824c31d7 | 242 | |
mkttanabe | 0:928a824c31d7 | 243 | sts = postToParseCom(URL_POSTDATA, reqData); |
mkttanabe | 0:928a824c31d7 | 244 | if (sts == HTTP_OK) { |
mkttanabe | 0:928a824c31d7 | 245 | lastRequestTime = time(NULL); |
mkttanabe | 0:928a824c31d7 | 246 | LEDS[1] = 0; |
mkttanabe | 0:928a824c31d7 | 247 | } else { |
mkttanabe | 0:928a824c31d7 | 248 | // エラー時は LED1 を点滅状態に |
mkttanabe | 0:928a824c31d7 | 249 | timer.attach(&handlerLed1Blink, 1.0); |
mkttanabe | 0:928a824c31d7 | 250 | } |
mkttanabe | 0:928a824c31d7 | 251 | } else { |
mkttanabe | 0:928a824c31d7 | 252 | dbg("- HTTPS request is pending.. [%d/%d sec]\r\n", elapsed, HTTPS_REQUEST_INTERVAL); |
mkttanabe | 0:928a824c31d7 | 253 | } |
mkttanabe | 0:928a824c31d7 | 254 | } |
mkttanabe | 0:928a824c31d7 | 255 | } |
mkttanabe | 0:928a824c31d7 | 256 | wait(0.2); |
mkttanabe | 0:928a824c31d7 | 257 | } |
mkttanabe | 0:928a824c31d7 | 258 | eth.disconnect(); // unreachable |
mkttanabe | 0:928a824c31d7 | 259 | } |
mkttanabe | 0:928a824c31d7 | 260 |