【第11回】 ArduinoからHTTP POSTする

前回、電力量の計算までの実装が終わりましたので、いよいよWebサーバーに電力量をアップロードする機能を追加したいと思います。

Arduinoの拡張ボード「イーサネットシールド」を用いることにより、簡単にインターネットに接続することが出来ます。

必要なコードは、以下の通り。

1.ヘッダファイルの宣言

2.定数及び共通変数の宣言

3.起動時の初期化処理

4.電力量送信処理

順を追って説明します

1.ヘッダファイルの宣言

必要なヘッダファイルは以下の2点

イーサネットシールドは「SPI」通信という通信方法を用いて、Arduinoと通信をしますので、「SPI.h」を宣言します。

あと、イーサネット通信のためのクラスなどが宣言された「Ethernet.h」をインクルードします。

#include <SPI.h>
#include <Ethernet.h>

2.定数及び共通変数の宣言

以下の通り、定数及び、共通変数の宣言を行います。

各定義のコメントのところに説明を記します。

//イーサネットシールドのMACアドレスを定義
//イーサネットシールドの裏に12桁の16進数文字のシールが貼ってある場合は??のところを書き換えてください。
//MACアドレスのシールが貼ってない場合は、家に未使用のLANカードや、ルーター等がある場合は、そのMACアドレスを使用してください
byte mac[] = { 0x??, 0x??, 0x??, 0x??, 0x??, 0x?? };
//Webサーバーのドメインを定義
//AppEngineでWebページを作成した際にドメインを取得できますので、そのドメインに書き換えてください
char serverName[] = "?????.appspot.com";
//Webサーバーのポート番号を定義
//これは書き換える必要はないです
int serverPort = 80;
//上記のドメイン設定以降のURLを記載します
//ここに記載するのは、http postを受け取るWebページのURLになります。
//例えば、http postを受け取るページが
//http://?????.appspot.com/hoge/post
//なら、char pageName[] = "/hoge/post";としてください
char pageName[] = "/????/????";
//これはそのままでよいです
EthernetClient client;
int totalCount = 0; 
//リクエスト送信時のパラメータを格納する配列です
//64バイトあれば十分と思います(不足する場合は64以上を設定してください)
char params[64];
//HTTP接続タイムアウト時間です
//現時点では10秒で設定してあります
#define delayMillis 10000UL
//HTTP Post間隔(s)
//5分(300秒)に1回電力量を送信するための秒数定義
#define WAIT_SEND_SEC_CNT (300) 

3.起動時の初期化処理

Ethernetシールドを使えるようにするための初期設定をします

以下の通り、定数及び、共通変数の宣言を行います。

void setup() {}内に記述します。
      //----------------------------------------------
      //Ethernetシールドの初期化
      //----------------------------------------------
      //SDカードを無効にする
      pinMode(4,OUTPUT);
      digitalWrite(4,HIGH);
      //MACアドレスの設定とIPアドレスの取得
      Serial.print(F("Starting ethernet..."));
      if(!Ethernet.begin(mac)) Serial.println(F("failed"));
      else Serial.println(Ethernet.localIP());
      //2秒間待つ
      delay(2000);
      Serial.println(F("Ready"));

4.電力量送信処理

電力量の送信は、CH4の電力量計算終了後送信するようにしています。

CH1~CH4の電力は1秒に1回計測しているため、5分に1回送信するために、300秒のカウントをし、300秒経ったときにHTTPPOSTするようにしています。

(おそらく、HTTPPOSTを実行している間に、電力・電圧計測の割り込みが走り、処理の干渉が起きているかもしれませんが、現状はこのあたりは妥協して作ってあります)

     case STATE_CALC4: //======= CH4 =========
       Serial.println("--4--");
       watt4 = calc_watt(myArrayA, myArrayV);
       state_calc = STATE_START;
       //----------------------------------------------
       //全チャンネル回ったら、1秒間の電力を合計値に加算
       //----------------------------------------------
       g_watt1 += watt1;   //各チャンネルの1秒間の電力を加算
       g_watt2 += watt2;   //各チャンネルの1秒間の電力を加算
       g_watt3 += watt3;   //各チャンネルの1秒間の電力を加算
       g_watt4 += watt4;   //各チャンネルの1秒間の電力を加算
       sec_cnt=sec_cnt+1;  //経過した秒数をカウント
       
       //debug用
       Serial.println("--");
       Serial.println(watt1);
       Serial.println(watt2);
       Serial.println(watt3);
       Serial.println(watt4);
       Serial.println(sec_cnt);
       
       //----------------------------------------------
       //WAIT_SEND_SEC_CNT満了したら、HTTPPost実行
       //----------------------------------------------
       if(sec_cnt == WAIT_SEND_SEC_CNT){
         sec_cnt = 0;
         //debug用
         Serial.println("--------");
         Serial.println(g_watt1 / WAIT_SEND_SEC_CNT);
         Serial.println(g_watt2 / WAIT_SEND_SEC_CNT);
         Serial.println(g_watt3 / WAIT_SEND_SEC_CNT);
         Serial.println(g_watt4 / WAIT_SEND_SEC_CNT);
         Serial.println("--------");
         
         //Postメッセージの作成
         //watt_value1:CH1とCH2の電力加算値
         //watt_value2:CH3とCH4の電力加算値
         //reserve1,2は今のところ未使用。POST時のパスワードに利用予定
         sprintf(params,"watt_value1=%i&watt_value2=%i&reserve1=0&reserve2=0",
             (int)((g_watt1 + g_watt2) / WAIT_SEND_SEC_CNT),    //発電電力(watt_value1)    
             (int)((g_watt3 + g_watt4) / WAIT_SEND_SEC_CNT));   //消費電力(watt_value2) 
         //HTTPサーバーへ送信
         if(!postPage(serverName,serverPort,pageName,params)) Serial.print(F("POST Fail "));
         else Serial.print(F("POST Pass "));
         Serial.println(totalCount,DEC);
         
         g_watt1 = 0;
         g_watt2 = 0;
         g_watt3 = 0;
         g_watt4 = 0;
       }
       break;
     }
 }
≪省略≫
//####################################################
//HTTP Postを送信する
//ここは、サンプルソースそのままになっています
//####################################################
byte postPage(char* domainBuffer,int thisPort,char* page,char* thisData)
{
   int inChar;
   char outBuf[64];
   Serial.print(F("connecting..."));
   if(client.connect(domainBuffer,thisPort))
   {
     Serial.println(F("connected"));
     // send the header
     sprintf(outBuf,"POST %s HTTP/1.1",page);
     client.println(outBuf);
     sprintf(outBuf,"Host: %s",domainBuffer);
     client.println(outBuf);
     client.println(F("Connection: close\r\nContent-Type: application/x-www-form-urlencoded"));
     sprintf(outBuf,"Content-Length: %u\r\n",strlen(thisData));
     client.println(outBuf);
     // send the body (variables)
     client.print(thisData);
   } 
   else
   {
     Serial.println(F("failed"));
     return 0;
   }
   int connectLoop = 0;
   while(client.connected())
   {
     while(client.available())
     {
       inChar = client.read();
       Serial.write(inChar);
       connectLoop = 0;
     }
     delay(1);
     connectLoop++;
     if(connectLoop > delayMillis)
     {
       Serial.println();
       Serial.println(F("Timeout"));
       client.stop();
     }
   }
   Serial.println();
   Serial.println(F("disconnecting."));
   client.stop();
   return 1;
}

これで、HTTP POSTで、電力をWebサーバに送信するコードが完成しました。

が、Webサーバーを立ち上げないと、送信失敗するだけなので、次回はWebサーバーの作り方を説明したいとおもいます。

③電力量のWebページを作る