An IOT system consists of multiple devices, each of which will either collect and report data, listen for commands, or both. Thanks to protocols like mqtt, it's possible for devices to subscribe and publish without having know every other device that wants to listen to it.
But that does not solve the whole problem. An IOT device must know some central hub to which it can report and from which it can receive information. Even when using MQTT, every device has to know the location of the broker. The same is true for other protocols as well. When a device wakes up on your network, how will it know who to talk to?
Imagine that you have a hub for your IOT system and on that hub you have an MQTT broker. Somehow, the clients need to know the IP address for the broker. Hard coding IP addresses is too brittle to be useful. Routers can reassign IP addresses if your network uses DHCP. Even if the hub has an assigned IP address, any change will require you to change every device on the network. What is needed is a way to let devices dynamically discover where the hub is.
That's where UDP multicast comes in. UDP multicast provides a way for a computer to talk with multiple other hosts without knowing who they are. The UDP communication doesn't specify a recipient, it just specifies a "group" and a time-to-live describing how many hops out the message should propagate. If the TTL is set to one, it won't leave your local area network (and depending on your router, it might not let it out anyway without special configuration). What effectively happens is that a message is broadcast to any device on your LAN that is listening to that group. And if one of those devices is your hub, it can respond. The client can get the response, which will include the IP address.
A good general example for how to code UPD multicast can be found here. I've also coded up a short python module that will make UDP easy for this use case. The repository can be found here. The specific file is here.
Once you add that library to your PYTHONPATH, you can start a "UDP server." This server listens for UDP messages addressed to a particular group. For every message it receives, it sends out a message in reply. The "server" can be started by calling mve.udp.start_udp_server(callback). The call is non-blocking, so it will return immediately, although the server will be running. Here is an example that simply returns the string "Registered" in response to any request. Note that the response is currently limited to 16 bytes.
The sample code also has a corresponding client. The client function essentially does the inverse. It sends out a message and then listens for the response. It returns the message received along with the IP address from which it got a response.
But that does not solve the whole problem. An IOT device must know some central hub to which it can report and from which it can receive information. Even when using MQTT, every device has to know the location of the broker. The same is true for other protocols as well. When a device wakes up on your network, how will it know who to talk to?
Imagine that you have a hub for your IOT system and on that hub you have an MQTT broker. Somehow, the clients need to know the IP address for the broker. Hard coding IP addresses is too brittle to be useful. Routers can reassign IP addresses if your network uses DHCP. Even if the hub has an assigned IP address, any change will require you to change every device on the network. What is needed is a way to let devices dynamically discover where the hub is.
That's where UDP multicast comes in. UDP multicast provides a way for a computer to talk with multiple other hosts without knowing who they are. The UDP communication doesn't specify a recipient, it just specifies a "group" and a time-to-live describing how many hops out the message should propagate. If the TTL is set to one, it won't leave your local area network (and depending on your router, it might not let it out anyway without special configuration). What effectively happens is that a message is broadcast to any device on your LAN that is listening to that group. And if one of those devices is your hub, it can respond. The client can get the response, which will include the IP address.
A good general example for how to code UPD multicast can be found here. I've also coded up a short python module that will make UDP easy for this use case. The repository can be found here. The specific file is here.
Once you add that library to your PYTHONPATH, you can start a "UDP server." This server listens for UDP messages addressed to a particular group. For every message it receives, it sends out a message in reply. The "server" can be started by calling mve.udp.start_udp_server(callback). The call is non-blocking, so it will return immediately, although the server will be running. Here is an example that simply returns the string "Registered" in response to any request. Note that the response is currently limited to 16 bytes.
UDP Server |
The sample code also has a corresponding client. The client function essentially does the inverse. It sends out a message and then listens for the response. It returns the message received along with the IP address from which it got a response.
UDP Client |
Incidentally, there's nothing special about python here. The same server can reply, for example, to requests sent out from lua running on an ESP8266:
cu=net.createConnection(net.UDP)
cu:on('receive',rxPkt)
cu:send(10000,'224.3.29.71', 'register:'..wifi.sta.getmac())
In this example "rxPkt" is a lua function that can then store the IP address of the responder for later use.
Comments
Post a Comment