【第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サーバーの作り方を説明したいとおもいます。