MQTT-SN Gateway Advertisement and Discovery

MQTT-SN has  two mechanisms for a client to discover an MQTT-SN Gateway, they are:

  1. Client search
  2. Gateway Advertisement.

mqtt-sn-gateway
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:

  1. Send search Gateway Message (SEARCHGW)
  2. Wait for Gateway or client response (GWINFO)
  3. 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.

GWINFO-MQTT-SN
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

mqtt-sn-gateway-advertise

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.

download

Related tutorials and resources:

Please rate? And use Comments to let me know more

6 comments

    1. Henry
      RSMB does not support Gateway search on advertisements. If you download the Gateway then that supports Gateway search.

  1. 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

    1. 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.

      1. 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?

Leave a Reply

Your email address will not be published. Required fields are marked *