The mDNS Browser lets you see wireless Arduino devices advertising services on your local network. It helps you make a TCP Client connection to devices — such as an ESP8266 — by name.
What is mDNS?
mDNS, or multicast DNS, is a service that helps you find your wireless Arduino devices on the network without knowing their IP address. It is a standard protocol widely implemented for local printer discovery, wireless speakers, network storage devices etc. mDNS won’t let you find devices any where on the Internet, but mDNS can help if your sensor and computer are on the same local network.
mDNS support is built-into MegunoLink
MegunoLink contains a simple mDNS client (so it doesn’t require any external services such as Bonjour). The mDNS client periodically looks for devices on your network which advertise the services you are interested in. A service, is simply a named port that your Arduino program opens to communicate with the outside world. The Arduino advertises the name of the port using a MDNS
library, such as the ESP8266mDNS library for the ESP8266 WiFi module.
Each device can advertise many service end-points and many devices may advertise the same type of end-point. Each device should have a unique name, so you can choose the one you want to connect to. In MegunoLink, you’ll select your connection by the type of service and the name of the device.
Using the mDNS Browser
Open the mDNS Browser by selecting mDNS Configuration from MegunoLink’s gear menu. You can use the Start and Stop buttons to start and stop the mDNS client.
Click the Edit button to show the Manage Services window to setup the services you are interested in (you’ll need to stop the mDNS client first if it is running). Click the New to add a service name, Edit to change an existing name or Delete to remove an entry from the list. Enter the end-point of the service (see below). MegunoLink will search for devices advertising any service in the list.
Advertising your Arduino using mDNS
Your Arduino program needs to advertise its services so they can be found by mDNS clients. For mDNS, a service is a name, protocol and port number. The client trying to connect to your program will use this information to resolve the Arduino’s IP address and open the connection.
The ESP8266 tool-chain for Arduino includes a compatible mDNS server. To use this server, you’ll need to
- include
ESP8266mDNS.h
, start the mDNS server and register the service, - Call
MDNS.begin("name");
to start the server. Here,name
is the name that will identify your device on the network, so it should be unique. The example below creates a unique name by appending the chip id to the program name using the custom functionMakeMine(…)
. - Call
MDNS.addService("service-id", "protocol", port);
to advertise the service. The service end-point will be advertised as_service-id._protocol
. For example, if you callMDNS.addService("n8i-mlp", "tcp", 23);
in your Arduino program, the end-point will be named_n8i-mlp._tcp
. Add the end-point to MegunoLink’s list of services so it will find your device.
Figuring out the Service End-Point for the mDNS Browser
The Service end-point is the full name of the service. Services are registered with a service-id and protocol. Join the two together to create the end-point name.
So if your service id is n8i-mlp
and the protocol is tcp
, the end-point’s full name is: _n8i-mlp._tcp
.
You might see .local
added to the end-point in some mDNS browsers. MegunoLink’s library adds that automatically so you shouldn’t enter it when adding a service to MegunoLink.
mDNS Example for ESP8266
This example for an ESP8266 registers a service end-point named _n8i-mlp._tcp
on port 23. Any data received on the Arduino’s serial port is sent to connected TCP clients. Any data received from a TCP client is sent out the serial port.
You can find this example in MegunoLink by clicking Library Examples → MegunoLink → Other → mDNSExample
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
#include <ESP8266WiFi.h> #include <ESP8266mDNS.h> // Fill in your network information const char* ssid = "ENTER SSID"; const char* password = "ENTER PASSWORD"; // Maximum number of clients that can connect to this device #define MAX_SRV_CLIENTS 1 WiFiServer server(23); WiFiClient serverClients[MAX_SRV_CLIENTS]; String MakeMine(const char *Template) { uint16_t uChipId = ESP.getChipId(); String Result = String(Template) + String(uChipId, HEX); return Result; } void ConnectToWiFi() { WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); Serial.print("Connecting to "); Serial.println(ssid); uint8_t i = 0; while (WiFi.status() != WL_CONNECTED) { Serial.print('.'); delay(500); if ((++i % 16) == 0) { Serial.println(F(" still trying to connect")); } } Serial.print(F("Connected. My IP address is: ")); Serial.println(WiFi.localIP()); } void AdvertiseServices() { String MyName = MakeMine("WiFiSensor"); if (MDNS.begin(MyName.c_str())) { Serial.println(F("mDNS responder started")); Serial.print(F("My name is: ")); Serial.println(MyName.c_str()); // Add service to MDNS-SD MDNS.addService("n8i-mlp", "tcp", 23); } else { while (1) { Serial.println(F("Error setting up MDNS responder")); delay(1000); } } } void setup() { Serial.begin(115200); Serial.println(F("mDNS Test")); Serial.println(F("---------")); ConnectToWiFi(); AdvertiseServices(); // Start the TCP server server.begin(); server.setNoDelay(true); Serial.println("Ready."); } void loop() { uint8_t i; // check if there are any new clients wanting to connect if (server.hasClient()) { for(i = 0; i < MAX_SRV_CLIENTS; i++) { //find free/disconnected spot if (!serverClients[i] || !serverClients[i].connected()) { if(serverClients[i]) serverClients[i].stop(); serverClients[i] = server.available(); Serial.print("New client: "); Serial.print(i); break; } } //no free/disconnected spot so reject if ( i == MAX_SRV_CLIENTS) { WiFiClient serverClient = server.available(); serverClient.stop(); Serial.println("Connection rejected "); } } // check clients for data. Any data that is received is sent // out the local serial port. for(i = 0; i < MAX_SRV_CLIENTS; i++) { if (serverClients[i] && serverClients[i].connected()) { if (serverClients[i].available()) { //get data from the telnet client and push it to the UART while (serverClients[i].available()) { Serial.write(serverClients[i].read()); } } } } // Check UART for data. Any serial data received is sent to // connected TCP clients. if(Serial.available()) { size_t len = Serial.available(); uint8_t sbuf[len]; Serial.readBytes(sbuf, len); //push UART data to all connected telnet clients for(i = 0; i < MAX_SRV_CLIENTS; i++) { if (serverClients[i] && serverClients[i].connected()){ serverClients[i].write(sbuf, len); delay(1); } } } } |
Here’s a screen shot from MegunoLink showing a serial and TCP connection to an ESP8266 device. Messages sent to the serial port are relayed back via a TCP connection and vice versa.