hbmqtt icon indicating copy to clipboard operation
hbmqtt copied to clipboard

How to know if client is connected?

Open hongquan opened this issue 7 years ago • 8 comments

I'm using hbmqtt v0.9.0. My program, as an MQTT client, sometimes gets "Disconnected from broker" log and no longer receive new data from Mosquitto broker. I'm using default config (with auto-reconnect).

I have questions:

  • Does "auto-reconnect" work when connection is lost, while waiting for message in deliver_message()?
  • Any way to check if client is connected, so that I can call reconnect() and subscribe again?

hongquan avatar Oct 14 '17 16:10 hongquan

Log: https://paste.ee/p/VVAV0

hongquan avatar Oct 17 '17 17:10 hongquan

use MQTTClient(config={"auto_reconnect":True})

luchermans avatar Dec 19 '18 12:12 luchermans

@luchermans Please read my question carefully. I wrote:

I'm using default config (with auto-reconnect).

hongquan avatar Dec 19 '18 17:12 hongquan

Sorry did not look carefully. I have a related issue using python and MQTTClient gives "Disconnected from broker" (simulate by restarting the hbmqtt broker) "auto_reconnect" seems to do reconnect but not re-subscribe.

I have solved the issue by MQTTClient(config={'auto_reconnect':False}) then a Connection lost / Disconnected throws an error so I can handle the re-connect myself.

luchermans avatar Dec 24 '18 13:12 luchermans

@luchermans Thank you. I will try that option. My case also seems to be "not re-subscribed".

hongquan avatar Dec 25 '18 06:12 hongquan

class MockedMQTTClient(MQTTClient):
    @asyncio.coroutine
    def handle_connection_close(self):

        def cancel_tasks():
            self._no_more_connections.set()
            while self.client_tasks:
                task = self.client_tasks.popleft()
                if not task.done():
                    task.set_exception(ClientException("Connection lost"))

        self.logger.debug("Watch broker disconnection")
        # Wait for disconnection from broker (like connection lost)
        yield from self._handler.wait_disconnect()
        self.logger.warning("Disconnected from broker")

        # Block client API
        self._connected_state.clear()

        # stop an clean handler
        #yield from self._handler.stop()
        self._handler.detach()
        self.session.transitions.disconnect()

        if hasattr(self, 'on_connection_close'):
            if inspect.iscoroutinefunction(self.on_connection_close):
                yield from self.on_connection_close()
            else:
                self.on_connection_close()

        if self.config.get('auto_reconnect', False):
            # Try reconnection
            self.logger.debug("Auto-reconnecting")
            try:
                yield from self.reconnect()
            except ConnectException:
                # Cancel client pending tasks
                cancel_tasks()
        else:
            # Cancel client pending tasks
            cancel_tasks()

    def set_close_callback(self, callback):
        self.on_connection_close = callback

Have done for myself in this dirty way.

If some kind of callback`s applicable for current project. I'm glad to prepare PR

stas-dubrovskyi avatar Sep 26 '19 17:09 stas-dubrovskyi

@stas-dubrovskyi: Nice - but hbmqtt should really supply a means of setting on_connect / on_message callbacks, as paho does. It's not difficult - shame the pkg is neglected as there is call for it ...

sronsiek avatar Mar 02 '21 18:03 sronsiek

Yeah, looks like the only way is to not use the broken reconnect functionality:


    async def process_messages(self):
        while True:
            try:
                await self._cli.reconnect()
                await self._cli.subscribe([...])
                while True:
                    msg: hbmqtt.session.ApplicationMessage = await self._cli.deliver_message()
                    if not msg:
                        logger.warning("No message. Disconnected?")
                        raise RuntimeError('Disconnected?')
                    do_stuff(msg)
            except KeyboardInterrupt:
                raise
            except:
                logger.exception("whoops")
                await asyncio.sleep(5)

dirty but works

Equidamoid avatar Mar 04 '21 21:03 Equidamoid