前回投稿より1年近くが経ってしまいました。途中、投稿しとこうかと思った事も幾つかあったのですが、ついついコードを書く事が優先して気がつくと何を書こうとしたのかも忘れてしまう有様でした。
そろそろボケが入って来たのかな?
W5500搭載 ATOM PoEキット
現在IoT 関連のプログラムを趣味のように書いていますが、その中で
こんな物を見つけたのでWi-Fiが使えない&電源を取るのが難しいという状況でセンサーが使えそうだなということで早速購入して遊んでみました。
W5500については以前ブログにアップしていたので簡単に動くかと思ったのですが・・・
当時のplatformio.iniは
[env:esp32doit-devkit-v1]
platform = espressif32
board = esp32doit-devkit-v1
framework = arduino
lib_deps =
adafruit/Ethernet2@^1.0.4
khoih.prog/MDNS_Generic@^1.0.1
こんな感じだったのですが、既にこのバージョンは古くなって使えなくなっていました。
ならばと最新版でコンパイルするとコンパイルエラーが多発してうまくいきません。
GitHubのサンプルResolvingHostNames.inoを見ると
// To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error
#include <MDNS_Generic.h>
のようなコメントもありましたが、依存関係を見るとWiFiを参照していたりと本来ネットワーク媒体には非依存で作成すべきなところがだいぶ複雑になっていそうです。
そこでもっと軽いライブラリはないかなと探してみたところ、やはりいました。
ArduinoMDNS
PlatformIOにもありましたので早速使うことにしました。
依存関係も無くすっきりとしたライブラリのようです。
今回のplatformio.iniは
[env:m5stack-atom]
platform = espressif32
board = m5stack-atom
framework = arduino
monitor_speed = 115200
lib_deps =
m5stack/M5Atom@^0.1.0
arduino-libraries/Ethernet@^2.0.2
arduino-libraries/ArduinoMDNS@^0.0.0
こんな感じです。
早速テストして見ると、パニックを起こしてしまいます。
どうやらアドレスエラーのようです・・・
前回同様またソースを見ることになるとは(( _ _ ))..zzzZZ
_finishedResolvingNameが原因でした
ソースを見るとどうやら_finishedResolvingNameメソッドでアドレス例外を出しているようです。
void MDNS::_finishedResolvingName(char* name, const byte ipAddr[4])
{
if (NULL != this->_nameFoundCallback) {
if (NULL != name) {
uint8_t* n = this->_findFirstDotFromRight((const uint8_t*)name);
*(n-1) = '\0';
}
this->_nameFoundCallback((const char*)name, IPAddress(ipAddr));
}
my_free(this->_resolveNames[0]);
this->_resolveNames[0] = NULL;
}
このメソッドは名前解決が出来た時に呼び出されてコールバック関数を呼び出すのですが、ソースを検索すると、名前解決できなかった時も呼び出されているます。但しipAddrがNULLで呼び出されていました!(前回調査時と同じ不具合)ということでその部分を以下のように変更して問題は解決しました。
this->_nameFoundCallback((const char*)name,
(ipAddr == NULL ? INADDR_NONE : IPAddress(ipAddr)));
resolveNameサンプル
ヘッダファイル:
DNSClient dns;
EthernetUDP udp;
MDNS mdns = MDNS(udp);
ソースファイル:
/* ****************************************************************************
* DNS
******************************************************************************/
IPAddress resolved_ip_address;
void nameFound(const char* name, IPAddress ip) {
resolved_ip_address = ip;
Serial.println(ip == INADDR_NONE ? " failed !!!" : " successed !");
}
IPAddress NetworkClientW5500Class::resolveName(const char *name) {
IPAddress ipAddress;
boolean rc = ipAddress.fromString(name);
if(!rc) { // IP指定だった場合は名前解決不要
if(this->useDNS) {
int ret = this->dns.getHostByName(name, ipAddress);
if (ret != 1) {
// mDNS初期化
if(!this->beginMDNS) {
if (!this->mdns.begin(Ethernet.localIP(), this->client_name)) {
// mDNS初期化エラー
Serial.println("Error setting up MDNS(W5500) responder!!!");
while(true) {
delay(1000);
Serial.print(".");
}
}
this->beginMDNS = true;
this->mdns.setNameResolvedCallback(nameFound);
Serial.println("mdns.begin is success !");
}
Serial.print("host(");
Serial.print(name);
Serial.print(") IP address resolving ");
int count = 0;
resolved_ip_address = INADDR_NONE;
while(true) {
if (!this->mdns.isResolvingName()) {
this->mdns.resolveName(name, 5000);
count++;
if(count > DNS_RETRY_COUNT)
break;
else if(count > 1)
Serial.print("retry resolving ");
}
Serial.print(".");
this->mdns.run();
if(resolved_ip_address != INADDR_NONE) {
ipAddress = resolved_ip_address;
count = 0;
break;
}
delay(100);
}
if(count > 0) {
// 名前解決できず
Serial.println(" was ended in failure!!!");
while(true) {
delay(1000);
Serial.print(".");
}
}
}
Serial.print("host(");
Serial.print(name);
Serial.print(") IP address : ");
Serial.println(ipAddress);
} else {
Serial.print("host(");
Serial.print(name);
Serial.print(") name resolution failed !!!");
while(true) {
delay(1000);
Serial.print(".");
}
}
}
return ipAddress;
}