sd01 is a minimal service discovery protocol with strict implementation.
Development status: Beta. Suitable for production but test coverage needs to be improved.
sd01 is an alternative to mDNS which is implemented by Bonjour/Ahahi.
- Advertisement of a IP + port for a given service by name
- Timeout mechanism to remove services that have disappeared
- No service metadata (instance name or capabilites, for example). This should be implemented out of band by the protocol the service uses itself.
Current:
- Python 2/3 (reference implementation)
- Go
Planned:
- Embedded C
- ...
sd01 reveals the host (IP) and port for any similar services running.
sd01 works by sending a message specific to the service name and service port over a UDP broadcast, port 17823. As a UDP broadcast is used, only hosts on the same subnet can discover. The service host (IP) is taken from the UDP packet source attribute.
An IPv6 and/or IPv4 multicast extension is being considered for version 2.
There are many service discovery systems out there, most of them are much more complicated than normally required. Many systems implement a custom UDP broadcast; sd01 is just a standard way to do so, cross-platform.
sd01 is deliberately minimal. It just exposes the IP address and the port of a particular named service. Note that device descriptions, names, versioning and capabilities are deliberately left out; this should be implemented as an API on the service itself.
sd01 works nicely with an RPC mechanism such as gRPC.
- Host: a device or server running a service
- Service: Something listening on a port running on a host.
- Service name: Product name, max 55 characters. Do not encode version or capabilites.
- Service port: The port the service is listening on
A host emits a sd01 message every 10 seconds. If an announcer has not seen the sd01 message for 600 seconds, the host is considered non-existent.
sd01:[service_name]:[service_port]
Where, without brackets:
- The total message length is no more than 64 bytes (53 chars for service_name)
- The entire message is composed of ASCII characters only
- The message is prefixed with
sd01
- The service port is an integer string
For example with a service name "DS Light controller" running on port 80:
sd01:DS light controller:80
Both the announcer and discoverer are aware of the service_name
in advance.
sd01.py
is the reference implementation. Other implementations are expected
to follow the same design which consists of:
- Unit tests for valid and invalid messages. The implementation must be strict to avoid replying on undefined behaviour.
- Threaded announcer and discoverer
Discoverer.get_services
, a thread-safe method to return online (host,port) pairs.- Invalid sd01 messages are handled as errors (although these errors should not crash the program, they may be logged)
- Valid sd01 messages from a different service_name are ignored
- Debug logging
This sensor is stateless and should just work.
- ESP8266 based sensor module connects to wifi, using DHCP
- ESP8266 announces via sd01
DS Multisensor
port80
- Automation controller discovers a known multi sensor is listening on
192.168.59.32:80
, and knows the sensor speaks a specific HTTP JSON protocol - Automation controller queries the sensor, and recevies something like:
{ "id": "2ef8787", "temperature": 49, "humidity": 23 }
- The automation controller consumes the value, knowing the location of the sensor by looking up the ID in its database. It knows this sensor is located in the
Kitchen
Note that the sensor is effectively stateless. It has its own preconfigured ID, which happens to be derrived from its MAC address.