ESP8266: Query LinkIt Smart mDNS services

The objective of this post is to explain how to find mDNS services advertised in the LinkIt Smart using the ESP8266.

Introduction

The objective of this post is to explain how to find mDNS services advertised in the LinkIt Smart using the ESP8266.

Although we are creating a very simple use case, this will be an architecture that could be employed in real use case scenarios.

We assume the use of the ESP8266 libraries for the Arduino IDE. We also assume that the LinkIt Smart is already configured to connect to a WiFi network.


Creating the LinkIt Smart mDNS service

Setting the configuration file in the LinkIt Smart for the new service is pretty straightforward, and you can check a detailed explanation in this previous post.

The configuration file for this service will be very simple and is shown bellow. We just need to put it in the /etc/avahi/services directory so the Avahi daemon can advertise it. Name the file espserver.service and put it in the previously mentioned directory. The easiest way to do it is using the WinSCP tool.

<?xml version="1.0" standalone='no'?><!--*-nxml-*-->
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
<service-group>
 <name replace-wildcards="yes">ESP8266 server</name>
  <service>
   <type>_espserver._tcp</type>
   <port>90</port>
   <txt-record>path=/</txt-record>
  </service>
</service-group>

From the configuration file, we can easily see that our service will be called espserver and the transport protocol will be TCP. Also, the service will be available on port 90.

Naturally, we are just configuring the advertisement of a hypothetical service, since we will not implement it. So, it’s important to understand that we are not developing the actual service, just telling the other devices/applications in the network that there is a service available in the IP of the LinkIt Smart, on port 90, with the name espserver.

After uploading the configuration file, we just need to tell the avahi daemon to reload the service configuration files. To to do, just send the command bellow in the LinkIt Smart console.

avahi-daemon -r

The new mDNS service should now be visible to other applications. We can use, for example, the mDNS browser application for Google Chrome, which should list the new service, as seen in figure 1.

mdns-esp-service

Figure 1 – The new LinkIt Smart service advertised on the network.


ESP8266 code

First of all, we will need to include two libraries, one for the functionality needed to connect the ESP8266 to a WiFi network and the other for the mDNS methods.

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

We will do all our coding in the setup function. Since connecting to a WiFi network was already explained in this post, we will focus on the mDNS functionalities.

Most of the functionalities of the mDNS library are available through an extern variable called MDNS. This MDNS variable is an object of class MDNSResponder. Nevertheless, we don’t need to know the low level details since they are handled for us in an easy to use interface.

First, we start by calling the begin method on the MDNS object to setup the mDNS functionalities. This method receives as argument the name of the host, in this case, our ESP8266. We can call it  whatever we want, as long as the name is smaller than 63 characters.

Since the begin method returns false when some initialization problem occurs, it’s a good practice to check the return value of the function.

 if (!MDNS.begin("ESP")) {
    Serial.println("Error setting up mDNS");
 }

After that, if no error occurs, we can send our mDNS query to check for the service we want. In this case, we will use the queryService method, also on the MDNS object. This method receives as first argument the name of the service and as second argument the primary transport protocol.

From our .service configuration file, we specified the name of the service as “espserver” and the primary transport protocol as “tcp“. Those are the arguments to be used.

It’s important to take in consideration that the output of this method is an integer, indicating the number of services that match the name and protocol and are found in the network.

int n = MDNS.queryService("espserver", "tcp");

Finally, we check if some service was found and we can get the host, IP and port of the LinkIt Smart service.

To find the hostname, we just call the hostname method on the MDNS object. To get the IP, we call the IP method. To get the port, we call the port method. You can check the source code of those methods here.

Since many services could have been found, the 3 methods mentioned before receive as argument the index of the service to which we want to retrieve the information. In this case, since we are operating in a controlled use case, we know that we only have a LinkIt Smart with this service, so we can use index zero. Nevertheless, in a real application scenario, we should iterate all the services to decide which host we want to connect to.

if (n == 0) {
    Serial.println("No service found");
  }
  else {
    Serial.println("Service found");
    Serial.println("Host: " + String(MDNS.hostname(0)));
    Serial.print("IP  : " );
    Serial.println(MDNS.IP(0));
    Serial.println("Port: " + String(MDNS.port(0)));
  }

You can check the whole final code bellow, which also includes the connection to the WiFi network and the empty main loop function.


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

const char* ssid = "Your network";
const char* password =  "Your network password";

void setup() {
  Serial.begin(115200);
  delay(100);
  Serial.println();

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(250);
    Serial.print(".");
  }
  Serial.println("Connection to AP established");

  if (!MDNS.begin("ESP")) {
    Serial.println("Error setting up mDNS");
  }
  Serial.println("mDNS setup finished");

  Serial.println("Sending mDNS Query");
  int n = MDNS.queryService("espserver", "tcp");

  if (n == 0) {
    Serial.println("No service found");
  }
  else {
    Serial.println("Service found");
    Serial.println("Host: " + String(MDNS.hostname(0)));
    Serial.print("IP  : " );
    Serial.println(MDNS.IP(0));
    Serial.println("Port: " + String(MDNS.port(0)));
  }

}

void loop() {

}


Final result

After uploading the ESP8266 code, just open the serial monitor from the Arduino IDE and check the output. You should get something similar to figure 2.

esp8266-linkit-smart-mdns-service

Figure 2 – LinkIt Smart mDNS service information.

So, the host is “mylinkit”, which is the default host name configured in the LinkIt Smart for mDNS services.

The IP is the address of the LinkIt Smart on your WiFi network (which will most probably be different from mine).

Finally, the port is the one we specified in the .service configuration file.


Application use cases

Although all of the mDNS concept may seem a little complicated when we are working in a controlled environment where we can easily know the IPs of all the devices, in a real application IoT scenario we may not know the IPs that will be assigned to the deployed nodes.

So, mDNS offers a really useful solution to resolve names into IPs and to check the services available in a network without the need for a dedicated and centralized infra-structure.

If we think in a commercial application where the LinkIt Smart works as a gateway and there are many nodes implemented with ESP8266 devices, we want the user to be able to just connect the nodes and the nodes to automatically find the gateway.

With mDNS, this is easily done since all the ESP8266 can be programmed to look for a certain service name when they connect to a WiFi network. So, after they find it, they simply get the IP address of the gateway and the port where the gateway server is listening, and they can start communicating with it.


Related Posts

Related content


Technical details

  • ESP8266 libraries: v2.3.0
Advertisements
This entry was posted in ESP8266, LinkIt Smart and tagged , , , , , , , , , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s