The DNS Dilemma
DNS is essentially a naming system for computers and services connected to a network. It's a way of mapping an IP address to a name and keeping that connection even if the IP Address Changes. You could visit google by going to http://184.108.40.206/ but it's much easier to remember and type http://google.com/ into your browser instead. So far we've been accessing our ESP device by typing http://192.168.4.1/ as a URL but there is a way to set up a local DNS server on the device so that it too can have it's own named URL.
For this tutorial we're going to go right back to the basic access point code. This code creates a local access point with a simple user name and password and responds to the browser with a simple piece of text. Being the wonderful arduino environment there is already a library written to enable you to do this with just two lines of text, the first to include the library and the second to tell it which URL you want.
Voila, now when you go to the browser and visit http://esp.local/ it takes you to your device.
All is good, in theory. It can't be that simple though other wise I wouldn't be having such a dilemma about DNS. The trouble is this only appears to work from my iPhone. When I go to my android phone or my laptop I can't access the device in the same way. This is also part of the problem with arduino, we're only using the libraries we don't really understand how they work. There's usually some workaround though and in this case there is a second DNS library readily available which appears to do the same thing so lets look at that.
The DNSServer library is a bit more involved (but still not a lot). The header file has to be included, an instance of the dns server declared, the server needs to be set up with the domain name (and DNS port) and finally it needs to be called in the main loop to ensure the requests are processed.
This has the rather disappointing effect that it doesn't appear to work on either iPhone or Android so it seems like a funny thing to include it here. Well the DNSServer library does have one interesting feature that actually proves to be quite useful. If you do not specify a domain name and instead use a wildcard, '*', it is supposed to be able to capture all requests and direct them to the correct URL. This is know as a captive portal and public wifi spots use them to direct your browser to their own login pages. The captive portal functionality finally allows us to connect to http://esp.local/ on the android (and laptop) device. In fact we can connect to anything we want it all goes to the same location.
The trouble is it doesn't work on the iPhone, and here is the dilemma. With the two obvious DNS libraries neither of them actually does a complete job. The world is not ending though, it is possible to use both libraries at the same time and between them they seem to cover all bases. So that's the little work around for now (full code here)
Arduino being open source, it is actually possible to delve deep inside these libraries and figure out how they work, what they're doing or not doing in the specific iPhone/Android cases and it should be perfectly possible to fix one of these libraries to work with both systems, that all takes time though, I guess I know what I'll be doing next week.