It’s been a week since the last blog post about mDNS and the nodeMCU.
I’ve promised further updates and well here they are.
The bonjour user module can now question other mDNS / bonjour devices for their IP and other info.
A lot has changed in the API, and some more changes will come, but i hope to have covered the major things now. As it is now:
-
requests, responses = bonjour:parse(frame)
will now return request and responses. Some responses are completely parsed (Type A, CNAME and SRV) more types are to come
-
bonjour:create_request({request1, request2, ..})
now generates a mDNS frame containing the requests. A request itself is a table with name, type and class fields. I.e.
request1 = { name="domain-name.local", type=bonjour.TYPE.A, class=bonjour.CLASS.IN }
-
bonjour:create_response({response1, response2, ..})
now generates a mDNS frame containing the requests. A request itself is a table with name, type, class, and ttl filled. I.e.
response1 = { name="esp-8266.local", type=bonjour.TYPE.A, class=bonjour.CLASS.IN, ttl=64, ip=wifi.sta.getip() }
- to fill the fields,
bonjour.TYPE
and
bonjour.CLASS
contain the required constants. Named as in RF1035. I.e. bonjour.TYPE.A
- the field
bonjour.VERSION
contains a version id (16bit, high byte = mahor, low byte = minor version)
Depending on the type, also (A): ip, (CNAME): cname, (SRV): host, port, priority and weight must be present.
So what?
Querries! 🙂
Want to find other nodeMCU devices running the mDNS responder or your Fruit-Branded Smartphone? Just ask them for their IP now.
The source file of the bonjour module can be found here.
I have added an extended version of the same mDNS responder lua file for the latest Demo Firmware I had provided with the last demo:
if ((bonjour ~= nil) and (bonjour.VERSION >= 0x0002)) then bonjourRequestIP = {} if (wifi.sta.getip() == nil) then print("mDNS requires an ip address. Please connect to a station.") else srv = net.createServer(net.UDP) conn = net.createConnection(net.UDP, 0) conn:connect(5353, "224.0.0.251") srv:on("receive", function (s, c) -- get requests from frame requests, responses = bonjour:parse(c) if (requests ~= nil) then for index, request in pairs(requests) do tmr.wdclr() ; print("Request mDNS["..index.."]: "..request.name.."(Type: "..request.type..")") if ((request.name:lower() == "esp-8266.local") and (request.type == bonjour.TYPE.A)) then conn:send ( bonjour:create_response({{name = request.name, type=bonjour.TYPE.A, class=1, ttl=64, ip=wifi.sta.getip()}}) ) end end end if (responses ~= nil) then for index, response in pairs(responses) do tmr.wdclr() ; if (response.type == bonjour.TYPE.A) then if (bonjourRequestIP.Name ~= nil) then if (bonjourRequestIP.Name:lower() == response.name:lower()) then bonjourRequestIP.IP = response.ip bonjourRequestIP.Callback(response.ip) bonjourRequestIP.Name = nil ; else print("Response mDNS["..index.."]: "..response.name.."(A: ip="..response.ip..")") end else print("Response mDNS["..index.."]: "..response.name.."(A: ip="..response.ip..")") end elseif (response.type == bonjour.TYPE.CNAME) then print("Response mDNS["..index.."]: "..response.name.."(CNAME: cname="..response.cname..")") else print("Response mDNS["..index.."]: "..response.name.."(Type: "..response.type..")") end end end end ) srv:listen(5353) net.multicastJoin(wifi.sta.getip(), "224.0.0.251") end function RequestBonjourIP(localname, callback) bonjourRequestIP.Name = localname bonjourRequestIP.Callback = callback bonjourRequestIP.IP = "" bonjourRequestIP.Retry = 0 bonjourRequestIP.Done = 0 conn:send(bonjour:create_request({{name = bonjourRequestIP.Name, type = bonjour.TYPE.A, class=bonjour.CLASS.IN}})) tmr.alarm(0,300, 1, function() if (bonjourRequestIP.IP == "") then if (bonjourRequestIP.Retry > 8) then bonjourRequestIP.Done = 1 bonjourRequestIP.Callback(nil) tmr.stop(0) end conn:send(bonjour:create_request({{name = bonjourRequestIP.Name, type = bonjour.TYPE.A, class=.CLASS.IN}})) bonjourRequestIP.Retry = bonjourRequestIP.Retry + 1 ; else bonjourRequestIP.Done = 1 end end ) end else print("mDNS Server requires user module Bonjour v0.02 or higher.") ; end
A lot of error checking was added and more will be done.
There might be crashes with huge mDNS requests (i.e. a 1010 byte request a local device sends sometimes here seems to trigger a reset) but further investigation is required to rule out that this is simply the watchdog for taking too long or if the request is using up too much memory.
Several mDNS response formats need to be parsed. right now they will be sent and received ignoring their actual payload.
This leaves me to say:
Have fun!