自宅状況モニタの作成にあたって、奇妙な不具合に遭遇しました。
修正コードは、GitHubにコミットしています。
事象
- InfluxDBサーバにアップロードする際、WIFI接続時は問題ないがEthernet接続時にエラーとなってしまう。
- 送信データのサイズが小さい場合は、Ethernet接続時でもエラーとならない。
原因
- Ethernet3ライブラリ内のデータ送信を行うsend()メソッド内で、サイズが2048byteを超える場合に超過分を削除しているため。(utility/socket.cpp)
- 結果、InfuluxDBのREST API側としては続きが送られてこないため、(約30秒の)タイムアウトエラーが発生してしまう。
uint16_t send(SOCKET s, const uint8_t * buf, uint16_t len)
{
uint8_t status=0;
uint16_t ret=0;
uint16_t freesize=0;
if (len > w5500.SSIZE)
ret = w5500.SSIZE; // check size not to exceed MAX size.
else
ret = len;
// if freebuf is available, start.
do
{
freesize = w5500.getTXFreeSize(s);
status = w5500.readSnSR(s);
if ((status != SnSR::ESTABLISHED) && (status != SnSR::CLOSE_WAIT))
{
ret = 0;
break;
}
}
while (freesize < ret);
// copy data
w5500.send_data_processing(s, (uint8_t *)buf, ret);
w5500.execCmdSn(s, Sock_SEND);
/* +2008.01 bj */
while ( (w5500.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK )
{
/* m2008.01 [bj] : reduce code */
if ( w5500.readSnSR(s) == SnSR::CLOSED )
{
close(s);
return 0;
}
}
/* +2008.01 bj */
w5500.writeSnIR(s, SnIR::SEND_OK);
return ret;
}
修正内容
- 上記のsend()メソッドを呼び出す側で、2048byte以下(1536byte)となるように区切って、複数回のメソッド呼び出しとなるようにした。(コードは、リンク先のGitHubを参照)