MQTT-SN has two mechanisms for a client to discover an MQTT-SN Gateway, they are:
- Client search
- Gateway Advertisement.
both mechanisms require the use of multicast messages.
Client Search
The client can search for a gateway rather than wait for an advertise packet.
the process is:
- Send search Gateway Message (SEARCHGW)
- Wait for Gateway or client response (GWINFO)
- Update Gateway table
A client can search for a gateway using the SEARCHGW message.
Both clients and gateways can respond to the SEARCHGW message
A Gateway will respond to this message using a GWINFO message which contains the Gateway ID only.
Another client will respond to this message using a GWINFO message which contains the Gateway ID and the Gateway IP Address.
The contents of the GWINFO message in the responses are shown in the image below taken from the specification.
Note:SearchGW is not supported by RSMB but does work on the Paho Gateway.
Gateway Advertisement
The gateway can also advertise using the ADVERTISE multicast message at intervals which is determined by the configuration file.
The specification calls for a long interval of more than 15 minutes.However for testing I use a 30 second interval.
The advertise packet contains the , the gateway id and advertise duration in seconds.
The IP address and port number of the gateway(udp port) is also available from the UDP header.
On receipt of the advertise packet the client has the necessary information to connect to the Gateway.
The screen shot below shows the parameters available in the Python client.
def advertise(self,client,address, gwid, duration): m="advertise -address" + str(address)+"qwid= " +str(gwid)+"dur= " +str(duration) print ("found gateway at",m)
The screen shot below shows the following on receipt of an advertise packet from a gateway. The gateway consoles is also shown
From the above you can see that the client will need to send data to the broker at address 192.168.1.41 on port 10000.
The broker console shows that the multicast port is 10000 and the multicast address is 224.0.18.83. the gateway id is 33 and duration is 30 seconds.
The multicast port and the gateway port are the same in the example above but do not have to be.
The duration can be used to check for broker availability.
The following is the advertise callback of the python client:
class MyCallback(Callback): def advertise(self,client,address, gwid, duration): m="advertise -address" + str(address)+"qwid= " +str(gwid)+"dur= " +str(duration) print ("found gateway at",m) ip_address,port=address temp=[ip_address,port,str(gwid),str(duration)] gateways.append(temp) client.GatewayFound=True
Client Implementation
Generally the client will use a Gateway search to locate a gateway on starting.
It will then listen for Gateway advertise messages to keep the gateway table updated.
The client knows from the duration in the advertise packet how often it should receive an advertise packet and should then mark a gateway as inactive if it fails to receive an advertise after a certain time.It can then fall back to another gateway in it’s list.
Python Client Implementation
In the Python client I have added a method to the client class to add gateways to a dictionary and mark them active and inactive.
The code is shown below:
def set_gateway(self,gwid,active=False): 'set gateway to active or inactive' for i in range(len(self.gateways)): if gwid ==self.gateways[i]["gwid"]: self.gateways[i]["gwid"]["active"]=active def add_gateway(self,gwid,host,port,duration): 'keep track of gateways' add_flag=True for i in range(len(self.gateways)): if gwid ==self.gateways[i]["gwid"]: add_flag=False self_set_gateway(gwid,True)#mark active if debug or learning: print("already found this one") break if add_flag: self.gateways.append({"gwid":gwid,"host":host,\ "port":port,"duration":duration,"status":True}) self.GatewayFound=True
The client uses the gateway table to respond to any SEARCHGW messages and also to select a gateway.
The on_advertise callback is shown below:
def on_advertise(self,client,address, gwid, duration): m="advertise -address" + str(address)+"qwid= " +str(gwid)+"dur= " +str(duration) if debug: print ("found gateway at from advertise message",m) ip_address,port=address client.add_gateway(str(gwid),ip_address,port,str(duration)) client.GatewayFound=True
For the search gateway this is called in the python script using
client.Search_GWs(client.multicast_group,client.multicast_port)
The gateway or client will respond with the GWINFO message and triggers a callback.
Marking A Gateway Active and inactive
When the gateway is first discovered it is marked as active automatically.
When the client detects that the gateway is no longer available it can mark it inactive using the set_gateway method.
client.set_gateway(gateway["gwid"],False)
When the client sees the next advertise broadcast from the gateway it will again automatically be marked as active in the add_gateway method.
Demo Scripts
Because of changes made to the client code the scripts provided in the client script package may not work with the current client code so it is best to download these gateway scripts.
Related tutorials and resources:
- MQTT-SN Topic Names and Identifiers
- MQTT-SN RSMB Broker Overview,Install and Configuration
- Using The Python MQTT-SN Client
Hi Steve,
Thank you for your reply. I am using RSMB, i was following this video https://www.youtube.com/watch?v=qWX0DWVOCtY&t=208s
however, they cannot find the client in a local network. They always stop at starting scan in the multi-cast.py. When i try to debug by printing the data. it always Fail.
Appreciate your comment.
Regards,
Henry
Henry
RSMB does not support Gateway search on advertisements. If you download the Gateway then that supports Gateway search.
Hi Steve,
Thank you for your tutorial. I am encoutering some issues that there is no error when running gateway-discovery.py but always keep printing “waiting for gateway” despite the fact that I had started the broker.
————————–My config test.txt file:
trace_output protocol
#MQTT listener
listener 1993 INADDR_ANY mqtt
#MQTT-SN listener
listener 1885 INADDR_ANY mqtts
multicast_groups 224.0.18.83
advertise 225.0.18.83:1885 30 33
————————–gateway-disconvery.py
…
client.multicast_port=1885 #port gateways advertises on
client.multicast_address=”225.0.18.83″ #IP gateways advertises on
…
This is usually a port issue but they look ok check in the python script that they are not defined twice and get back to me. I assume you are using the scripts from the tutorial. I will check them again.
Hi Steve,
I can confirm that they are only defined once. I used to WireShark to capture and i can see the multicast package from Gateway but on either gateway-discovery.py or multicast-scan.py, they still cannot find the gateway. Am i missed something?
Are you using RSMB if so then Gateway discovery doesn’t work
Rgds
Steve