IM920地温観測システム CQ 2017ARMセミナー用サンプルプログラム

Dependencies:   C027_Support_ForIM920

Fork of C027_SupportTest by u-blox

main.cpp

Committer:
ntaka206
Date:
2017-07-09
Revision:
34:1cbf923d4ca7
Parent:
33:e27f40fada64
Child:
35:7838543282c2

File content as of revision 34:1cbf923d4ca7:

#include "mbed.h"

//------------------------------------------------------------------------------------
/* This example was tested on C027-U20 and C027-G35 with the on board modem. 
   
   Additionally it was tested with a shield where the SARA-G350/U260/U270 RX/TX/PWRON 
   is connected to D0/D1/D4 and the GPS SCL/SDA is connected D15/D15. In this 
   configuration the following platforms were tested (it is likely that others 
   will work as well)
   - U-BLOX:    C027-G35, C027-U20, C027-C20 (for shield set define C027_FORCE_SHIELD)
   - NXP:       LPC1549v2, LPC4088qsb
   - Freescale: FRDM-KL05Z, FRDM-KL25Z, FRDM-KL46Z, FRDM-K64F
   - STM:       NUCLEO-F401RE, NUCLEO-F030R8
                mount resistors SB13/14 1k, SB62/63 0R
*/
#include "GPS.h"
#include "MDM.h"
#include "DebugPrint.h"

//------------------------------------------------------------------------------------
// You need to configure these cellular modem / SIM parameters.
// These parameters are ignored for LISA-C200 variants and can be left NULL.
//------------------------------------------------------------------------------------
//! Set your secret SIM pin here (e.g. "1234"). Check your SIM manual.
#define SIMPIN      "0000"
/*! The APN of your network operator SIM, sometimes it is "internet" check your 
    contract with the network operator. You can also try to look-up your settings in 
    google: https://www.google.de/search?q=APN+list */
#define APN         "soracom.io"
//! Set the user name for your APN, or NULL if not needed
#define USERNAME    "sora"
//! Set the password for your APN, or NULL if not needed
#define PASSWORD    "sora"
//------------------------------------------------------------------------------------

//#define CELLOCATE

#define IM920_TX  P4_28
#define IM920_RX  P4_29
Serial im920(IM920_TX, IM920_RX);

#define AD_NUM 3
#define MV_LSB (1500/1024.) 
#define DEGC_MV (1/10.)
#define PV_LSB (2*1.5/1024)

#define M2X_SERVER   "api-m2x.att.com"
#define M2X_DEVICE_ID   "964d05b1a6f4a8bb02c2a5aaf6e7e268"
#define M2X_API_KEY "602d38e9e8dfcf62e7f87a59c80784ec"
#define M2X_CHID_TEMP0  "temp0"


/*
IM920から受信したADデータをデコードする
sn: IM920 SN
*ad: ADデータ配列 LSB
ret: 0=OK -1=ERR
*/
int im920_conv(char *in, int *sn, int *ad)
{
    char *p;
    char *endptr;
    int l, h;
    int i;
    
    p = strtok(in, ",");
    // SN
    p = strtok(NULL, ",");
    *sn = strtol(p, &endptr, 16);
    // SUM
    p = strtok(NULL, ":");
//    printf("%s ", p);
    // AD0-2
    for(i = 0; i < AD_NUM; i++) {
        p = strtok(NULL, ",");
//    printf("%s ", p);
        l = strtol(p, &endptr, 16);
        p = strtok(NULL, ",");
//    printf("%s ", p);
        h = strtol(p, &endptr, 16);
        ad[i] = l + h*256;
    }
    
    return 0;
}

/**
 * M2X HTTP送信
 * @param http HTTP送信する文字列
 * @param hostname 
 * @return 0=OK -1=ERR
 */
int cloud_http_socket_send(MDMSerial *mdm, char *http, const char *hostname)
{
    int socket;
    char data[512];  // receive
    char    *strtokptr;
    char    *ptr;

    socket = mdm->socketSocket(MDMParser::IPPROTO_TCP);
    if (socket >= 0) {
        mdm->socketSetBlocking(socket, 60*1000); // timeout im msec
        // 指定されたhostにSocket Connect
        if (!mdm->socketConnect(socket, hostname, 80)) {
            ERROR("ERROR socket connect\r\n");
            ERROR("hostname=%s\r\n", hostname);
            return -1;
        }
        TRACE("socketConnect() OK\r\n");
    } else {
        ERROR("sockeSocket() < 0\r\n");
        ERROR("hostname=%s\r\n", hostname);
        return -1;
    }
    int ret = mdm->socketSend(socket, http, strlen(http));
    TRACE("socketSend()=%d\r\n", ret);
    // Recv responce 十分な大きさの変数を渡す必要あり
    ret = mdm->socketRecv(socket, data, sizeof(data)-1);
    TRACE("socketRecv()=%d\r\n", ret);
    // 毎回Socket Closeが必要みたい
    mdm->socketClose(socket);
    mdm->socketFree(socket);
    // HTTPレスポンス受信出来た
    if (ret > 0) {
        TRACE("Socket Recv \"%s\"\r\n", data);
        // HTTPレスポンスcheck
        // ERR retryは呼び出し元でしている
        // 1行目抽出
        ptr = strtok_r(data, "\r\n", &strtokptr);
        // Status Code抽出
        ptr = strtok_r(ptr, " ", &strtokptr);
        ptr = strtok_r(NULL, " ", &strtokptr);
        int code = atoi(ptr);
        // ログにレスポンスコードout
        INFO("HTTP Res=%d\r\n", code);
        // Code=200番台以外ならばエラー
        // m2x 202(Accepted)
        if (code < 200 || code >= 300) {
            ERROR("HTTP Response ERR code=%d\r\n", code);
            return -1;
        }
    } else {
        // レスポンス受信できず
        ERROR("HTTP Response rcv ERR ret=%d\r\n", ret);
        return -1;
    }
    return 0;
}
/**
 * M2X にHTTP PUT送信する
 * HTTPデータを作って送信する
 * API V2 POST
 * @param *data JSONデータ (mag+powerv data)
 * @return 0=OK -1=ERR
 */
static char m2x_http_send(MDMSerial *mdm, int sn, int *ad)
{
    char http_data[512];
    char    data[128];
//    char    buf[128];

#if 0
    data[0] = 0;
    strncat(data, "{\"values\": {\r\n", sizeof(data));
    sprintf(buf, "\"%s\": [\r\n", M2X_CHID_TEMP0);
    strncat(data, buf, sizeof(data));
    
    sprintf(buf, "{ \"value\":%6.1f}", (ad[0]*MV_LSB-500)*DEGC_MV);
    strncat(data, buf, sizeof(data));
    strncat(data, "],\r\n", sizeof(data));
    strncat(data, "}}", sizeof(data));
#endif
    sprintf(data, "{ \"value\": \"%6.1f\" }", (ad[0]*MV_LSB-500)*DEGC_MV);
       
    // HTTP PUTデータ作る
    snprintf(http_data, sizeof(http_data), "PUT /v2/devices/%s/streams/%04d-temp0/value HTTP/1.0\r\n"
        "X-M2X-KEY: %s\r\n"
        "Host: %s\r\n"
        "Content-Type: application/json\r\n"
        "Content-Length: %d\r\n\r\n%s\r\n",
        M2X_DEVICE_ID, sn, M2X_API_KEY, M2X_SERVER,
        strlen(data), data);
    TRACE(http_data);
    // HTTP PUTする
    return cloud_http_socket_send(mdm, http_data, M2X_SERVER);
}

int main(void)
{
    int ret;
#ifdef LARGE_DATA
    char buf[2048] = "";
#else
    char buf[512] = "";
#endif
    const int wait = 100;
    int ad[AD_NUM];
    int sn;

    im920.baud(19200);
    im920.format(8, Serial::None, 1);

    // Create the GPS object
#if 1   // use GPSI2C class
//    GPSI2C gps;
#else   // or GPSSerial class 
//    GPSSerial gps; 
#endif
    // Create the modem object
    MDMSerial mdm; // use mdm(D1,D0) if you connect the cellular shield to a C027
    //mdm.setDebug(4); // enable this for debugging issues 
    // initialize the modem 
    MDMParser::DevStatus devStatus = {};
    MDMParser::NetStatus netStatus = {};
    bool mdmOk = mdm.init(SIMPIN, &devStatus);
    mdm.dumpDevStatus(&devStatus);
    if (mdmOk) {
        // wait until we are connected
        mdmOk = mdm.registerNet(&netStatus);
        mdm.dumpNetStatus(&netStatus);
    }
    if (mdmOk)
    {
        // join the internet connection 
        MDMParser::IP ip = mdm.join(APN,USERNAME,PASSWORD);
        if (ip == NOIP)
            printf("Not able to join network");
        else
        {
            mdm.dumpIp(ip);
        }
    } else {
        goto ErrOut;
    }
    /*
        MAIN LOOP
    */
    printf("LOOP START\r\n");
    while(true) {
        if (im920.gets(buf, 128) > 0) {
            printf("%s", buf);
            if (!im920_conv(buf, &sn, ad)) {
                printf ("IM920: %06d, %04d, %04d, %04d\r\n", sn, ad[0], ad[1], ad[2]);
                printf ("IM920: %06d, %f, %f, %f\r\n", sn, (ad[0]*MV_LSB-500)*DEGC_MV,  (ad[1]*MV_LSB-500)*DEGC_MV, ad[2]*PV_LSB);
                m2x_http_send(&mdm, sn, ad);
            }
        }
#ifdef RTOS_H
        Thread::wait(wait);
#else
        ::wait_ms(wait);
#endif
    }
ErrOut:
//    gps.powerOff();
    mdm.powerOff();
    return 0;
}