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

Dependencies:   C027_Support_ForIM920

Fork of C027_SupportTest by u-blox

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include "mbed.h"
00002 #include "rtos.h"
00003 
00004 //------------------------------------------------------------------------------------
00005 /*
00006  地中温度観測システム親機プログラム
00007  C027_SupportTestをベースにしているがmain.cのコードはほとんで入れ替え
00008  (c) NT System Design
00009 */
00010 #include "MDM.h"
00011 #include "DebugPrint.h"
00012 #include "RingBuf.h"
00013 
00014 //------------------------------------------------------------------------------------
00015 // You need to configure these cellular modem / SIM parameters.
00016 // These parameters are ignored for LISA-C200 variants and can be left NULL.
00017 //------------------------------------------------------------------------------------
00018 //! Set your secret SIM pin here (e.g. "1234"). Check your SIM manual.
00019 #define SIMPIN      "0000"
00020 /*! The APN of your network operator SIM, sometimes it is "internet" check your 
00021     contract with the network operator. You can also try to look-up your settings in 
00022     google: https://www.google.de/search?q=APN+list */
00023 #define APN         "soracom.io"
00024 //! Set the user name for your APN, or NULL if not needed
00025 #define USERNAME    "sora"
00026 //! Set the password for your APN, or NULL if not needed
00027 #define PASSWORD    "sora"
00028 //------------------------------------------------------------------------------------
00029 
00030 #define IM920_TX  P4_28
00031 #define IM920_RX  P4_29
00032 Serial im920(IM920_TX, IM920_RX);
00033 
00034 #define AD_NUM 3
00035 #define MV_LSB (1500/1024.) 
00036 #define DEGC_MV (1/10.)
00037 #define PV_LSB (2*1.5/1024)
00038 
00039 #define M2X_SERVER   "api-m2x.att.com"
00040 #define M2X_DEVICE_ID   "964d05b1a6f4a8bb02c2a5aaf6e7e268"
00041 #define M2X_API_KEY "602d38e9e8dfcf62e7f87a59c80784ec"
00042 #define M2X_CHID_TEMP0  "temp0"
00043 
00044 DigitalOut led(LED1);
00045 
00046 // リングバッファサイズ
00047 #define RINGBUF_SIZE    60    // 毎分データで1時間ぶん
00048 // リングバッファ
00049 RingBuf ring(RINGBUF_SIZE);
00050 
00051 /*
00052 IM920から受信したADデータをデコードする
00053 sn: IM920 SN
00054 *ad: ADデータ配列 LSB
00055 ret: 0=OK -1=ERR
00056 */
00057 int im920_conv(char *in, int *sn, int *ad)
00058 {
00059     char *p;
00060     char *endptr;
00061     int l, h;
00062     int i;
00063     
00064     p = strtok(in, ",");
00065     // SN
00066     p = strtok(NULL, ",");
00067     *sn = strtol(p, &endptr, 16);
00068     // SUM
00069     p = strtok(NULL, ":");
00070 //    printf("%s ", p);
00071     // AD0-2
00072     for(i = 0; i < AD_NUM; i++) {
00073         p = strtok(NULL, ",");
00074 //    printf("%s ", p);
00075         l = strtol(p, &endptr, 16);
00076         p = strtok(NULL, ",");
00077 //    printf("%s ", p);
00078         h = strtol(p, &endptr, 16);
00079         ad[i] = l + h*256;
00080     }
00081     
00082     return 0;
00083 }
00084 
00085 /**
00086  * M2X HTTP送信
00087  * @param http HTTP送信する文字列
00088  * @param hostname 
00089  * @return 0=OK -1=ERR
00090  */
00091 int cloud_http_socket_send(MDMSerial *mdm, char *http, const char *hostname)
00092 {
00093     int socket;
00094     char data[512];  // receive
00095     char    *strtokptr;
00096     char    *ptr;
00097 
00098     socket = mdm->socketSocket(MDMParser::IPPROTO_TCP);
00099     if (socket >= 0) {
00100         mdm->socketSetBlocking(socket, 60*1000); // timeout im msec
00101         // 指定されたhostにSocket Connect
00102         if (!mdm->socketConnect(socket, hostname, 80)) {
00103             ERROR("ERROR socket connect\r\n");
00104             ERROR("hostname=%s\r\n", hostname);
00105             return -1;
00106         }
00107         TRACE("socketConnect() OK\r\n");
00108     } else {
00109         ERROR("sockeSocket() < 0\r\n");
00110         ERROR("hostname=%s\r\n", hostname);
00111         return -1;
00112     }
00113     int ret = mdm->socketSend(socket, http, strlen(http));
00114     TRACE("socketSend()=%d\r\n", ret);
00115     // Recv responce 十分な大きさの変数を渡す必要あり
00116     ret = mdm->socketRecv(socket, data, sizeof(data)-1);
00117     TRACE("socketRecv()=%d\r\n", ret);
00118     // 毎回Socket Closeが必要みたい
00119     mdm->socketClose(socket);
00120     mdm->socketFree(socket);
00121     // HTTPレスポンス受信出来た
00122     if (ret > 0) {
00123         TRACE("Socket Recv \"%s\"\r\n", data);
00124         // HTTPレスポンスcheck
00125         // 1行目抽出
00126         ptr = strtok_r(data, "\r\n", &strtokptr);
00127         // Status Code抽出
00128         ptr = strtok_r(ptr, " ", &strtokptr);
00129         ptr = strtok_r(NULL, " ", &strtokptr);
00130         int code = atoi(ptr);
00131         // ログにレスポンスコードout
00132         INFO("HTTP Res=%d\r\n", code);
00133         // Code=200番台以外ならばエラー
00134         // m2x 202(Accepted)
00135         if (code < 200 || code >= 300) {
00136             ERROR("HTTP Response ERR code=%d\r\n", code);
00137             return -1;
00138         }
00139     } else {
00140         // レスポンス受信できず
00141         ERROR("HTTP Response rcv ERR ret=%d\r\n", ret);
00142         return -1;
00143     }
00144     return 0;
00145 }
00146 /**
00147  * M2X にHTTP PUT送信する
00148  * HTTPデータを作って送信する
00149  * API V2 POST
00150  * @param *data JSONデータ (mag+powerv data)
00151  * @return 0=OK -1=ERR
00152  */
00153 static char m2x_http_send(MDMSerial *mdm, RingBufType *rd)
00154 {
00155     char http_data[512];
00156     char    json[128];
00157     // JSONデータ作る
00158 //    sprintf(json, "{ \"value\": \"%6.1f\" }", (rd->ad[0]*MV_LSB-500)*DEGC_MV);
00159     sprintf(json, "{ \"values\": {\"%04d-temp0\": %6.2f,\"%04d-temp1\": %6.2f,\"%04d-power\": %6.2f}}",
00160         rd->sn, (rd->ad[0]*MV_LSB-500)*DEGC_MV,
00161         rd->sn, (rd->ad[1]*MV_LSB-500)*DEGC_MV,
00162         rd->sn, rd->ad[2]*PV_LSB);
00163 
00164     // HTTP PUTデータ作る
00165 //    snprintf(http_data, sizeof(http_data), "PUT /v2/devices/%s/streams/%04d-temp0/value HTTP/1.0\r\n"
00166     snprintf(http_data, sizeof(http_data), "POST /v2/devices/%s/update HTTP/1.0\r\n"
00167         "X-M2X-KEY: %s\r\n"
00168         "Host: %s\r\n"
00169         "Content-Type: application/json\r\n"
00170         "Content-Length: %d\r\n\r\n%s\r\n",
00171         M2X_DEVICE_ID, M2X_API_KEY, M2X_SERVER,
00172         strlen(json), json);
00173     TRACE(http_data);
00174     // HTTP PUTする
00175     return cloud_http_socket_send(mdm, http_data, M2X_SERVER);
00176 }
00177 /*
00178  M2Xへの送信スレッド
00179 */
00180 void m2x_post_thread(void const *args) {
00181     RingBufType *rd;
00182     MDMSerial *mdm = (MDMSerial*)args; // 3Gモデムのインスタンス
00183     
00184     while (true) {
00185         // リングバッファにデータあれば送信
00186         if (ring.len_get() > 0) {
00187             led = 1;
00188             rd = ring.pop();    // リングバッファからPOP
00189             m2x_http_send(mdm, rd); // M2Xへデータ送信
00190             led = 0;
00191         }
00192         Thread::wait(1000); // 1sec
00193     }
00194 }
00195 
00196 int main(void)
00197 {
00198     int ret;
00199     char buf[512] = "";
00200     const int wait = 100;
00201     int ad[AD_NUM];
00202     int sn;
00203     RingBufType data_im920;
00204 
00205     led = 1;
00206     printf("start\r\n");
00207     im920.baud(19200);
00208     im920.format(8, Serial::None, 1);
00209 
00210     // modem object
00211     MDMSerial mdm;
00212     //mdm.setDebug(4); // enable this for debugging issues 
00213     // initialize the modem 
00214     MDMParser::DevStatus devStatus = {};
00215     MDMParser::NetStatus netStatus = {};
00216     bool mdmOk = mdm.init(SIMPIN, &devStatus);
00217     mdm.dumpDevStatus(&devStatus);
00218     if (mdmOk) {
00219         // wait until we are connected
00220         mdmOk = mdm.registerNet(&netStatus);
00221         mdm.dumpNetStatus(&netStatus);
00222     }
00223     if (mdmOk)
00224     {
00225         // join the internet connection 
00226         MDMParser::IP ip = mdm.join(APN,USERNAME,PASSWORD);
00227         if (ip == NOIP)
00228             printf("Not able to join network");
00229         else
00230         {
00231             mdm.dumpIp(ip);
00232         }
00233     } else {
00234         printf("Modem init ERROR!");
00235         return 0;
00236     }
00237     led = 0;
00238     // M2X送信スレッド
00239     Thread thread(m2x_post_thread,&mdm);
00240     /*
00241         MAIN LOOP
00242     */
00243     printf("LOOP START\r\n");
00244     while(true) {
00245         if (im920.gets(buf, 128) > 0) {
00246             printf("%s", buf);
00247             if (!im920_conv(buf, &sn, ad)) {
00248                 printf ("IM920: %06d, %04d, %04d, %04d\r\n", sn, ad[0], ad[1], ad[2]);
00249                 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);
00250                 // リングバッファに保存
00251                 data_im920.sn = sn;
00252                 for(int i = 0; i < AD_NUM; i++) {
00253                     data_im920.ad[i] = ad[i];
00254                 }
00255                 ring.push(&data_im920);
00256             }
00257         }
00258         Thread::wait(wait);
00259     }
00260     mdm.powerOff();
00261     return 0;
00262 }