Makoto TANABE / Anpi

Safety confirmation program for the elderly persons. (LPC1768)

Dependencies:   EthernetInterface HTTPClient mbed-rtos mbed

main.cpp

Committer:
mkttanabe
Date:
2015-02-13
Revision:
0:928a824c31d7

File content as of revision 0:928a824c31d7:

/*
* Copyright (C) 2015 KLab Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "mbed.h"
#include "EthernetInterface.h"
#include "HTTPClient.h"

#define DEVELOP
#ifdef DEVELOP
#define dbg(...) printf(__VA_ARGS__)
#else
#define dbg(...)
#endif

// Parse.com に設置ずみのの対向アプリの ID と RESTAPIKEY
#define PARSE_COM_APPID       "** YOUR PARSE APP ID **"
#define PARSE_COM_RESTAPIKEY  "** YOUR PARSE APP REST API KEY **"

#define REQUEST_HEADER_FOR_PARSE_COM \
    "X-Parse-Application-Id: " PARSE_COM_APPID      "\r\n" \
    "X-Parse-REST-API-Key: "   PARSE_COM_RESTAPIKEY "\r\n" \
    "Content-Type: "           "application/json"   "\r\n"

#define URL_POSTDATA  "https://api.parse.com/1/functions/detected"
#define URL_SENDMAIL  "https://api.parse.com/1/functions/sendmail"

// for LM61BIZ
#define GAP_DIGREE_ZERO  (600.0/3300.0)
#define DIGREE_PER_VALUE (10.0/3300.0)

#define SW_ON 0
#define LED_MAX 5
#define HTTPS_REQUEST_INTERVAL 1800 // 30分

EthernetInterface eth;
HTTPClient http;
LocalFileSystem local("local");

#define DEVICEID_FILENAME  "/local/id.txt"
#define DEVICEID_MAXLENGTH 16

DigitalOut LEDS[LED_MAX] = {p21, LED1, LED2, LED3, LED4};
DigitalOut buzzer(p5);     // 電子ブザー
AnalogIn sensorTEMP(p15);  // 温度センサ
DigitalIn sensorPIR(p20);  // 赤外線センサ
DigitalIn switchPUSH(p24); // 外付けプッシュボタン
Ticker timer;
char deviceId[DEVICEID_MAXLENGTH];

// すべてのLEDをON/OFF
void LedsShow(int OnOrOff)
{
    for (int i = 0; i < LED_MAX; i++) {
        LEDS[i] = OnOrOff;
    }
}

// すべてのLEDを順次点灯
void LedsRotate(float interval)
{
    LedsShow(0);
    for (int i = 0; i < LED_MAX; i++) {
        LEDS[i] = 1;
        wait(interval);
    }
    LedsShow(0);
}

// time() 用にダミー日時をセット
void setTime()
{
    struct tm t;
    t.tm_sec  = 1;
    t.tm_min  = 1;
    t.tm_hour = 1;
    t.tm_mday = 1;
    t.tm_mon  = 1;
    t.tm_year = 100;
    time_t seconds = mktime(&t);
    set_time(seconds);
}

void handlerLedsRotate()
{
    LedsRotate(0.1);
}

void handlerLed1Blink()
{
    LEDS[1] = !LEDS[1];
}

// 初期化
int init()
{
    int sts;

    // 押しボタン接続ポートの DigitalIn をプルアップ
    switchPUSH.mode(PullUp);

    setTime();
    timer.attach(&handlerLedsRotate, 1);

    // イーサネットの初期化
    dbg("- start eth.init\r\n" );
    sts = eth.init(); //Use DHCP
    if (sts != 0) {
        dbg("- ech.init error!\r\n" );
        timer.detach();
        return -1;
    }

    dbg("- start eth.connect\r\n" );
    sts = eth.connect();
    if (sts != 0) {
        dbg("- eth.connect error!\r\n" );
        timer.detach();
        return -2;
    }
    dbg("- my IP Address = %s\r\n", eth.getIPAddress());

    // 自デバイス名を id.txt から読み込む
    strncpy(deviceId, eth.getIPAddress(), 15);
    deviceId[15] = '\0';
    FILE *fp = fopen(DEVICEID_FILENAME, "r");
    if (!fp) {
        // id.txt が存在しなければ新規作成し IP アドレスを書き込む
        fp = fopen(DEVICEID_FILENAME, "w");
        if (fp) {
            fprintf(fp, "%s", deviceId);
        }
    } else {
        fgets(deviceId, DEVICEID_MAXLENGTH, fp);
        for (int i = 0; i < DEVICEID_MAXLENGTH; i++) {
            if (deviceId[i] == '\r' || deviceId[i] == '\n') {
                deviceId[i] = '\0';
                break;
            }
        }
    }
    if (fp) {
        fclose(fp);
    }
    dbg("- my DeviceId = %s\r\n", deviceId);

    // センサ安定化待ち
    wait(4.0);
    timer.detach();
    return 0;
}

// Parse.com への POST
int postToParseCom(const char *ApiUrl, char *postData)
{
    int sts;
    char buf[256];
    HTTPText dataToPost(postData);
    HTTPText resData(buf, sizeof(buf));
    http.setHeader(REQUEST_HEADER_FOR_PARSE_COM);
    dbg("- start HTTPS request\r\n");
    sts = http.post(ApiUrl, dataToPost, &resData, HTTP_CLIENT_DEFAULT_TIMEOUT);
    if (sts == HTTP_OK) {
        dbg("- received HTTPS response\r\n");
        dbg("- head of data [%s]\r\n", buf);
        dbg("- done\r\n\r\n");
    } else {
        dbg("- HTTPS request error=%d, status=%d\r\n", sts, http.getHTTPResponseCode());
        dbg("- head of data [%s]\r\n", buf);
        return sts;
    }
    return HTTP_OK;
}

// エントリーポイント
int main()
{
    time_t lastRequestTime = 0;
    char reqData[128];
    int sts = init();
    if (sts != 0) {
        // 初期化エラー時は LED 全点灯で終了
        LedsShow(1);
        return -1;
    }
    while(1) {
        int buttonPressedMsecs = 0;
        // 緊急ボタン押下状態
        while (switchPUSH == SW_ON) {
            LEDS[2] = 1;
            // 長押し2秒でメール送信
            if (buttonPressedMsecs >= 2000) {
                LEDS[1] = 1;
                buzzer = 1; // ブザーを鳴らす
                dbg("- long-pressed\r\n");
                // デバイス名
                sprintf(reqData, "{\"devid\" : \"%s\"}", deviceId);
                sts = postToParseCom(URL_SENDMAIL, reqData);
                if (sts != HTTP_OK) {
                    // あとで考える
                }
                break;
            }
            wait(0.2);
            buttonPressedMsecs += 200;
        }
        LEDS[1] = LEDS[2] = 0;
        buzzer = 0;

        // 赤外線センサ反応状態
        int detected = sensorPIR;
        if (!detected) {
            LEDS[0] = 0;
        } else {
            if (LEDS[0] == 0) {
                LEDS[0] = 1;
                dbg("- detected!\r\n");
                // 温度センサの出力電圧値を摂氏値に
                float valueTemp = (sensorTEMP - GAP_DIGREE_ZERO) / DIGREE_PER_VALUE;
                dbg("- temperature = %2.1f C\r\n", valueTemp);

                // 前回の送信から所定時間が経過していれば再び送信
                int elapsed = time(NULL) - lastRequestTime;
                if (elapsed > HTTPS_REQUEST_INTERVAL) {
                    // 温度情報・デバイス名・ローカル IP アドレス
                    sprintf(reqData, "{\"temp\" : \"%2.1f\", \"devid\" : \"%s\", \"ip\" : \"%s\"}",
                            valueTemp, deviceId, eth.getIPAddress());
                    timer.detach();
                    LEDS[1] = 1;

                    sts = postToParseCom(URL_POSTDATA, reqData);
                    if (sts == HTTP_OK) {
                        lastRequestTime = time(NULL);
                        LEDS[1] = 0;
                    } else {
                        // エラー時は LED1 を点滅状態に
                        timer.attach(&handlerLed1Blink, 1.0);
                    }
                } else {
                    dbg("- HTTPS request is pending.. [%d/%d sec]\r\n", elapsed, HTTPS_REQUEST_INTERVAL);
                }
            }
        }
        wait(0.2);
    }
    eth.disconnect(); // unreachable
}