チラシの裏の電子工作

電子工作、PC関係の備忘録というか、チラシの裏

ESP-WROOM-02 WebServerで長いCSVなどを返す

Arduino1.6.7+esp8266-2.1.0

ESP8266WebServerで、センサーから得たデータをcsvなんかで表示する場合、例えば

String text="";
for(int i=0;i<RECORD_LENGTH;i++){
  text+=temp[i]+","+hum[i]+","+baro[i]+"\r\n";
}
webServer.send(200,"text/plain",text);

こんな感じで処理すればいいわけだけど、当然レコードが結構長くなるとメモリ不足に陥る。
何かいい方法ないかなー、、と、ESP8266WebServer.cppを眺めてた。

どうやらhttpヘッダから直接自分で作って送ってしまえば行けそうな感じだったので、試してみた。

String header;
header ="HTTP/1.1 200 OK\r\n";
header+="Content-Type: text/plain\r\n";
header+="Content-Length: "+String(contentLength)+"\r\n";
header+="Connection: close\r\n";
header+="Access-Control-Allow-Origin: *\r\n";
header+="\r\n";
webServer.sendContent(header);

String text="";
for(int i=0;i<RECORD_LENGTH;i++){
  text=temp[i]+","+hum[i]+","+baro[i]+"\r\n";
  webServer.sendContent(text);
}

こんなことをやれば、1レコードずつ送信できるのでメモリ不足を回避できた。
ただ、1行ごとにsendすると非常に遅いので、何行かバッファして纏めてsendした方がいいかも。

例えばこんな感じ。

String text="";
for(int i=0;i<RECORD_LENGTH;i++){
  text+=temp[i]+","+hum[i]+","+baro[i]+"\r\n";
  if(i % 50 ==0){
    webServer.sendContent(buff);
    text="";
  }
}
webServer.sendContent(text);

ここまで書いて、contentLengthの存在を忘れてた。
レコードを固定長にして、レコード数と掛け算してcontentLengthを計算するようにした方がいいかも。


んで、出力URLをjavascriptのグラフライブラリに食わせたら、割と簡単にグラフ化できる。
espgraph.png  
今回使ったのはDygraphs。
特にこのグラフライブラリが優れてるわけではなく、過去に使ったことがあるって理由で採用したので、今はもっと良いのがあるかも。


スポンサーサイト

カテゴリ:未分類

ESP-WROOM-02 ネットワークが定期的に切断する

ESP-WROOM-02で遊んでて、およそ5分毎に無線LANが切断される現象。
(Arduino1.6.7+esp8266core2.0.0)

wl_status_tの遷移を記録してみたら、こんな感じに。

6 (WL_DISCONNECTED)
1 (WL_NO_SSID_AVAIL)
3 (WL_CONNECTED)

5分ぐらい無通信が続くと…

4 (WL_CONNECT_FAILED)
1 (WL_NO_SSID_AVAIL)
3 (WL_CONNECTED)

ずっと無通信だったら、これを5分毎に繰り返す。
wifi_set_sleep_typeを変えてみてもこの現象は発生する。
外部からpingを打ち続けたらこの現象は発生せず。
WL_CONNECT_FAILDからWL_CONNECTEDに遷移する間はホントに切断されてるようで、この瞬間はpingも落とす。
不具合なのか、そう言う仕様なのか…

とおもったら、esp8266core2.1.0で改善されてた
ただ、2.1.0ってコンパイルするとwarningがいっぱい出てちょっと気持ち悪い。
あんまり問題があるような内容じゃないので無視でいいんだけども…
取り敢えずコンパイラの警告をAllからMoreに下げておいた。

カテゴリ:電子工作

ESP-WROOM-02 BASIC認証

ESP8266 ArduinoCore2.1.0から、BASIC認証がESP8266WebServerに実装されました。
が、動きません。
サンプル(HttpBasicAuth)のコンパイルは通るけど、認証を通した段階でException(2)でスタック吐いて止まる。
色んな意味で期待を裏切りません。
※2.3.0で修正された模様。

と言うわけで中身を調査。

ライブラリ本体はイカの場所に。
C:\Users\%USERNAME%\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.1.0\libraries\ESP8266WebServer\src\ESP8266WebServer.cpp


bool ESP8266WebServer::authenticate(const char * username, const char * password)

この関数を抜けるときにほぼ必ず「Exception (2)」でこける。

コケ方がどうにも不可解で、107行目の

sprintf(toencode, "%s:%s", username, password);

を通ると必ずコケる。
どう考えても怪しいのはtoencode。
初期化はこうなっていた。

char toencodeLen = strlen(username)+strlen(password)+1;
char *toencode = new char[toencodeLen];

toencodeLenがなんでcharなのかっていうツッコミはおいといて…
username="hoge"、password="fuga"だとして、sprintfで出力されるのは"hoge:fuga"で9バイト。
toencodeLenも9になる。
あれ?sprintfって最後に\0が入るよな…って事は1バイト足らんじゃないの。

と言うわけで、96行目のtoencodeの初期化を1バイト増やす。

char *toencode = new char[toencodeLen+1];

動いた動いた。


カテゴリ:電子工作

ESP-WROOM-02 DHCPクライアントの切り替え

ESP-WROOM-02の電源再投入操作無しに、DHCPと固定IPを切り替える方法が無いか調べてみました。

固定IPにする方法は、ライブラリにちゃんと定義がありますね。(esp2866-2.0.0)

ESP8266WiFi.h

void config(IPAddress local_ip, IPAddress gateway, IPAddress subnet);
void config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns);

ってワケで、arduino公式の物(多分WiFiシールド用?)とは引数の順番が違うので、注意が必要です。
そもそもmaskは省略不可でない事自体がおかしい気がするんだけど、WiFiシールドはどうなってるんだ…

で、ESP8266WiFi.cppを読んでて気になったのが

wifi_station_dhcpc_stop();
wifi_station_dhcpc_start();

これってDHCPクライアントを止めたり動かしたりできるんでない?
定義自体を探してみたらあった。

user_interface.h

enum dhcp_status {
    DHCP_STOPPED,
    DHCP_STARTED
};
bool wifi_station_dhcpc_start(void);
bool wifi_station_dhcpc_stop(void);
enum dhcp_status wifi_station_dhcpc_status(void);


実際にESP8266WiFi.cppの内部では以下のように使用されていた。

wifi_station_dhcpc_start();
 WiFi.begin()の時のみ。(但しIPを固定にしてない場合)

wifi_station_dhcpc_stop();
 WiFi.config()つまりIPを固定にしたときのみ。

つまるところ、IPを固定にするときは何も考えずにWiFi.config()を叩けばよろしい。

一度固定IPにした後、DHCPからIPを得たければ

if(wifi_station_dhcpc_status()==DHCP_STOPPED){
  wifi_station_dhcpc_start();
}

こんな感じでいいんじゃないかな。



カテゴリ:電子工作

FC2Ad