How to prevent multiple instances of a driver

I'm coding an mqtt client driver ..to test it i enter in an invalid ip to test error handling. but if i change ip and re initialize, i end up with multiple instances running.
How do I check for, prevent multiple instances.. or halt a running driver .

1 Like

Probably a question for @chuck.schwer . I'm guessing there will probably need to be some kind of change in the library to prevent multiple instances.

So am I to understand that there is no way to stop , reset or check for a running driver.

Typically the interface clients (like the websocket and telnet client) are singletons to the driver instance I think. There was a bug that was squashed with the websocket client but for the most part I have never seen a driver interface client myself end up with multiple instances. So, if that is happening it's either a bug or intended for some other purpose. Either way, I haven't used the MQTT client yet so I will still defer to Chuck.

Yes... The websocket/socket/telnet interfaces are singletons... but they are shared by all the threads running for a specific device... When you update the code for an app/driver, or sometimes (depending on the app/driver) update the settings, you can get situations where there are multiple threads running.

When this happens, it is usually short-lived... Once a running thread terminates, any newly created threads will inherit the new code or new preferences... If you are getting threads that do not terminate in a timely manner, then you probably have an endless loop or a semaphore deadlock or some other disasterous bug in your code... When I have runn into such situations, I found that the only way to terminate these rogue threads is to disable the app/device, reboot the HE, fix the code then re-enable the app/device.

1 Like

Drivers are typically triggered by some incoming message or by an app running a method and usually take less than a second to complete. What is it that you have running, how can you tell that you have 2 instances running?

The simplest way is to call disconnect() before connect(). That will ensure that when your driver gets re-initialized that the precious connection is properly closed first.

A call to disconnect() should be harmless even if the device isn’t connected.

So my code block looks like this

def refresh(){
    if(interfaces.mqtt.isConnected()) return
     retry = settings?.retrypause.toInteger()
    if (logEnable) log.info "Connecting to ${settings?.MQTTBroker} as `${settings?.clientname}-${device.getName()}`"
    try {
        interfaces.mqtt.connect("tcp://" + settings?.MQTTBroker + ":1883,", settings?.clientname + "-" + device.getName(), settings?.username,settings?.password)
        pauseExecution(2000)
      }
    catch(e) {
        log.warn "Communication error : ${e.message}"
        if (settings?.retrypause !="0") { 
            log.info "Retrying in ${settings?.retrypause} seconds" 
            pauseExecution(settings?.retrypause.toInteger() * 2000)
            refresh()
        }

    }

in the settings, retrycount is set to user entered number of seconds to wait before retrying connection.. so disconnect() after if(interfaces.mqtt.isConnected()) return
should stop the loop and restart it clean ??

this is an mqtt driver that, if a connection cannot be made to the designated mqtt server, it keeps trying to connect at a setup choice number of minutes, say every 1 minute it will attempt reconnect . i can tell there is more than 1 instance as I can see in the log attempts to connect to the ip.. If i change the ip in the setup.. i can see attempts to connect to both ip 's.. the first instance continues..

You have an infinite loop there: refresh method calls refresh method again.

Instead of pauseExecution and calling refresh() directly, you should use the runIn() method.

1 Like

I don't think that the "refresh" method is the appropriate place for your connection handling code. Ideally, the refresh method should reload (or poll) the current state of the driver...

Your initialize() method should be setting up the connection... (however, many drivers abstract this function by calling a custom connection control function)... you also require a mqttClientStatus() method that will receive status updates to the connection that you open. This function will tell your driver when a connection is dropped and you can then schedule (using runIn) the reconnect function.

Any control of the connection needs to be carefully controlled.... Your update() function, which accepts parameter changes submitted through the user interface should do whatever driver specific update processing is required and call the initialize() function. Your initialize function should have the appropriate logic to determine if the connection needs to be closed and reopened..

Any other function that is callable from the user interface (such as refresh(), poll(), on(), etc) should not be able to affect (open or close) the connection... Because a user that decided to mash on the "on" button will cause your driver to go sideways VERY quickly if the function tries to do more that just send data...

1 Like

Thanks so much for the help..I'm just learning , never coded anything except apps in basic, rexx, vb and c..so steep learning curve..Never coded drivers before..so learning new language, mqtt, drivers etc.. Again really appreciate the help.. Looks like i need to recode the whole driver..