MDNSを使って、動作中のESP8266機の一覧を表示する

半年前にESP8266の小物を増やそうとして、WiFiルータ接続数の限界を迎えました。
その対策は最大256台接続のWiFiルータを導入して問題解決したのですが、
最近新たな問題が発生しました。
ESP8266小物がどんだけ動いているのか把握できねぇ（笑）
小物を何種類かを作り散らかして動作確認中なのですが、ソイツ等が動作中かダウン
してるかの確認をするのが大変になってきました。

そんな訳で今回は、MDNSを使って動作中の機器リストを作ることにしました。
もっともそれだけならArduino ESP8266ExampleにあるMDNS_Web_Serverで済むの
ですが、WebServerを少しマトモにしてiPad/iPhoneでも確認できる様にしました。


#ESP8266環境で必要なリソース
　特に無し


#機能
　iPad/iPhoneのsafariからESP8266.local/アクセスすることで
　mdnsのサービス http,tcp にエントリしている機器一覧が確認できる。

　エントリには　機器のIP.local/　でリンクを貼ってあります。


#使い方

メインソースはこんな風にします。

```ino:esp8266.ino:

#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <ESP8266WebServer.h>

const char* ssid = "guest";
const char* password = "guest";

ESP8266WebServer server(80);
// HTMLヘッダ
const char *ESPHTMLHeader ="<html lang=\"ja\">\n<head>\n\
<meta http-equiv=\"Content-Type\" content=\"text/html; charset=Shift_JIS\">\n\
<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n</head>\n";
//=====================================================================================
#define IPTABLES 256                  // 保持する端末数
String MDNShostname[IPTABLES];
IPAddress MDNSIPAddress[IPTABLES];
unsigned long MDNSmillis[IPTABLES];
#define MDNSDeleteMillis (5 * 60 * 1000)      // 端末が無くなったと判断するまでの時間
#define SEEKDELAY (60*1000)
unsigned long OldMillis;
//=====================================================================================
void MDNSseek( String name1, String name2 ){
  int n = MDNS.queryService(name1, name2); // Send out query for esp tcp services
  bool updateList = false;
  if (n != 0) {
    for (int iFound = 0; iFound < n; ++iFound) {
      bool boolFound = false;
      int unuseNumber = -1;
      for( int i=0 ; i<IPTABLES ; i++ ){
        if( MDNShostname[i]=="" ){ unuseNumber = i;  continue; }
        if( MDNS.hostname(iFound)==MDNShostname[i] ){
          boolFound = true;
          MDNSmillis[i] = millis();
        }
        if( millis() < MDNSmillis[i] ){
          MDNSmillis[i] = millis();
        }else{
          unsigned long Lastmillis = millis() - MDNSmillis[i];
          if( Lastmillis >  MDNSDeleteMillis ){
            Serial.print( MDNShostname[i] );  Serial.print( ":" );  Serial.println( Lastmillis );
            MDNShostname[i] = "";
            updateList = true;
          }
        }
      }
      if( boolFound == false && unuseNumber!=-1 ){
        MDNShostname[unuseNumber]  = MDNS.hostname(iFound);
        MDNSIPAddress[unuseNumber] = MDNS.IP(iFound);
        MDNSmillis[unuseNumber]    = millis();
        updateList = true;
      }
    }
  }else{
    for( int i=0 ; i<IPTABLES ; i++ ){
      if( MDNShostname[i]=="" ) continue;
      unsigned long Lastmillis = millis() - MDNSmillis[i];
      if( Lastmillis >  MDNSDeleteMillis ){
        Serial.print( MDNShostname[i] );  Serial.print( ":" );  Serial.println( Lastmillis );
        MDNShostname[i] = "";
        updateList = true;
      }
    }
  }
  if( updateList == true ){
    int iCount = 1;
    Serial.print("List update!! [");
    Serial.print( name1 );  Serial.print( ":" );  Serial.print( name2 );  Serial.println( "]" );
    for( int i=0 ; i<IPTABLES ; i++ ){
      if( MDNShostname[i]=="" ) continue;
      Serial.print(iCount); Serial.print(" : ");  Serial.print( MDNShostname[i] );
      Serial.print(" (");   Serial.print(MDNSIPAddress[i]); Serial.println(")");
      iCount++;
    }
    if( iCount==1 )          Serial.println( "none" );
  }
}
//=====================================================================================
void indexHtml() {
  Serial.println( "execute : index.html" );
  int count = 0;
  String output = ESPHTMLHeader;
  output += "MDNS PC list</br>\n";
  for( int i=0 ; i<IPTABLES ; i++ ) {
        if( MDNShostname[i]=="" ) continue;
        output += "<a href=\"http://";
        output += String(MDNSIPAddress[i][0]);  output += ".";
        output += String(MDNSIPAddress[i][1]);  output += ".";
        output += String(MDNSIPAddress[i][2]);  output += ".";
        output += String(MDNSIPAddress[i][3]);  output += "/\">";
        output += (count+1);
        output += ". ";
        output += MDNShostname[i];
        output += ".local/</a></br>\n";
        count ++;
  }
  output += "\n</form>\n</html>\n";
  server.send(200, "text/html", output);
}
//=====================================================================================
void setup(void)
{  
  Serial.begin(115200);
  
  // Connect to WiFi network
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.println("");  
  
  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  if (!MDNS.begin("esp8266")) {
    Serial.println("Error setting up MDNS responder!");
    while(1) { 
      delay(1000);
    }
  }
  Serial.println("mDNS responder started");
  
  // Start TCP (HTTP) server
  server.begin();
  Serial.println("TCP server started");

  // Add service to MDNS-SD
  MDNS.addService("http", "tcp", 80);

  //
  server.on("/index.html", indexHtml  );
  server.on("/",           indexHtml  );
  OldMillis = millis();
}
//=====================================================================================
void loop(void)
{
  server.handleClient( );
  MDNS.update();
  // 起動直後は頻繁に行うが、通常時は少し時間を空けて確認する様に変更予定
  if( (OldMillis+SEEKDELAY)>millis() )
    if( millis()>SEEKDELAY )
      if( OldMillis<millis() )  return;
  OldMillis = millis();
  MDNSseek( "http", "tcp" );
  Serial.print("*");
}

```


機器サンプルはArduinoIDEにあるMDNSサンプルのMDNS_web_server.inoになります。
実際は以下のコードぐらいで済みます。

```ino:unit.ino:
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>

void setup(void)
{  
  // wifi接続部
　　　～～　省略　～～
  // MDNS宣言部
  MDNS.begin("～～機器名～～");
  // MDNS-SDサービス
  MDNS.addService("http", "tcp", 80);
}

void loop(void)
{
  MDNS.update();
}
```