Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mqtt sets reconnection timeout to expire #521

Closed
laterdayi opened this issue Mar 16, 2024 · 30 comments
Closed

mqtt sets reconnection timeout to expire #521

laterdayi opened this issue Mar 16, 2024 · 30 comments

Comments

@laterdayi
Copy link

laterdayi commented Mar 16, 2024

mqtt sets reconnection timeout to expire ,mqtt_client reconnection timeout did not work

As currently configured, it will always be reconnected without connection timeouts or connection failures, without any ### errors

How can I achieve an error, connection exception or connection timeout if the connection exceeds 5S and be able to catch it

He keeps showing a connection, but the MQTT server is available, but has not been successfully reconnected, and is still connecting

class MqttUtil {

  MqttServerClient? mqttClient;
  MqttQos qos = MqttQos.atLeastOnce;
 
  static MqttUtil? _instance;
   static MqttUtil getInstance() {
    _instance ??= MqttUtil();
    return _instance!;
  }

  connect({
    String? server,
    int? port,
    String? clientIdentifier,
    String? username,
    String? password,
  }) async {
    try {
      mqttClient = MqttServerClient.withPort(
        AppEnv.kMQTTUrl,
        clientIdentifier ?? 'payton-pda-${UserStore.to.userInfo.user?.id}-${AppStore.to.appInfo.androidId}',
        AppEnv.kMQTTPort,
        maxConnectionAttempts: 1,
      );
      mqttClient?.logging(on: false);
      mqttClient?.keepAlivePeriod = 20;
      mqttClient?.onDisconnected = _onDisconnected;
      mqttClient?.onConnected = _onConnected;
      mqttClient?.onSubscribed = _onSubscribed;
      mqttClient?.onUnsubscribed = _onUnsubscribed;
      mqttClient?.onSubscribeFail = _onSubscribeFail;

      final connMessage = MqttConnectMessage().startClean().withWillQos(MqttQos.exactlyOnce);
      mqttClient?.connectionMessage = connMessage;
      UtilLog.info("connecting");
      return mqttClient?.connect(username, password);
    } catch (e) {
    }
  }

  Subscription? subscribeMessage(String subtopic) {
    return mqttClient?.subscribe(subtopic, qos);
  }

  unsubscribeMessage(String unSubtopic) {
    mqttClient?.unsubscribe(unSubtopic);
  }

  disconnect() {
    mqttClient?.disconnect();
  }
}
@shamblett
Copy link
Owner

Sorry I'm not understanding you, are you saying you want the client to stop trying to connect after 5 seconds if it doesn't succeed in connecting?

I don't know what this means 'He keeps showing a connection, but the MQTT server is available, but has not been successfully reconnected, and is still connecting'

@laterdayi
Copy link
Author

What I mean is that when the server is restarted, the client will try to reconnect, but it will always show the connection, and when the server MQTT is restarted successfully, it will still show the connection and will not reconnect successfully

@laterdayi
Copy link
Author

image

@laterdayi
Copy link
Author

More than half an hour later, it still shows a connection, no connection timeout, connection error, connection success

@shamblett
Copy link
Owner

I'll need a client log to see what's going on here, if you have disconnected which I assume you have as you have called on disconnected you have to call connect again to reconnect.

@laterdayi
Copy link
Author

I/flutter ( 5325): 1-2024-03-16 20:06:53.158738 -- Authenticating with username '{admin}' and password '{123456}'
I/flutter ( 5325): 1-2024-03-16 20:06:53.160350 -- MqttClient::connect - Connection timeout period is 5000 milliseconds
I/flutter ( 5325): 1-2024-03-16 20:06:53.163210 -- MqttClient::connect - keep alive is enabled with a value of 20 seconds
I/flutter ( 5325): 1-2024-03-16 20:06:53.164160 -- MqttConnectionKeepAlive:: Initialised with a keep alive value of 20 seconds
I/flutter ( 5325): 1-2024-03-16 20:06:53.164309 -- MqttConnectionKeepAlive:: Disconnect on no ping response is disabled
I/flutter ( 5325): 1-2024-03-16 20:06:53.165152 -- MqttConnectionHandlerBase::connect - server 10.100.10.85, port 9012
I/flutter ( 5325): 1-2024-03-16 20:06:53.167143 -- SynchronousMqttServerConnectionHandler::internalConnect entered
I/flutter ( 5325): 1-2024-03-16 20:06:53.167525 -- SynchronousMqttServerConnectionHandler::internalConnect - initiating connection try 0, auto reconnect in progress false
I/flutter ( 5325): 1-2024-03-16 20:06:53.167895 -- SynchronousMqttServerConnectionHandler::internalConnect - insecure TCP selected
I/flutter ( 5325): 1-2024-03-16 20:06:53.168659 -- SynchronousMqttServerConnectionHandler::internalConnect - calling connect
I/flutter ( 5325): 1-2024-03-16 20:06:53.169234 -- MqttNormalConnection::connect - entered
I/flutter ( 5325): 1-2024-03-16 20:07:13.176402 -- MqttConnectionKeepAlive::pingRequired
I/flutter ( 5325): 1-2024-03-16 20:07:13.176824 -- MqttConnectionKeepAlive::pingRequired - NOT sending ping - not connected
I/flutter ( 5325): 1-2024-03-16 20:07:13.176894 -- MqttConnectionKeepAlive::pingRequired - restarting ping timer

@laterdayi
Copy link
Author

I/flutter ( 5325): 1-2024-03-16 20:06:53.169234 -- MqttNormalConnection::connect - entered
I/flutter ( 5325): 1-2024-03-16 20:07:13.176402 -- MqttConnectionKeepAlive::pingRequired
I/flutter ( 5325): 1-2024-03-16 20:07:13.176824 -- MqttConnectionKeepAlive::pingRequired - NOT sending ping - not connected
I/flutter ( 5325): 1-2024-03-16 20:07:13.176894 -- MqttConnectionKeepAlive::pingRequired - restarting ping timer
I/flutter ( 5325): 1-2024-03-16 20:07:33.197554 -- MqttConnectionKeepAlive::pingRequired
I/flutter ( 5325): 1-2024-03-16 20:07:33.197792 -- MqttConnectionKeepAlive::pingRequired - NOT sending ping - not connected
I/flutter ( 5325): 1-2024-03-16 20:07:33.197947 -- MqttConnectionKeepAlive::pingRequired - restarting ping timer

@laterdayi
Copy link
Author

So far the log has been indicating /// Set the correct MQTT protocol for testing against mosquito, and I have no callback to handle manually disconnecting @shamblett

@laterdayi
Copy link
Author

I set up a timeout connection for 5S, and after 5S, there are no exceptions or event callbacks to let me know that the timeout has occurred

@shamblett
Copy link
Owner

The logs seem incomplete I cant see the sending of a connect message nor receipt of a connect ack.

Could you supply a complete client log of the initial connection and what happens when your MQTT broker disconnects.

@laterdayi
Copy link
Author

I/flutter ( 5325): ┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
I/flutter ( 5325): │ 21:37:00.466 (+0:00:00.002435)
I/flutter ( 5325): ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
I/flutter ( 5325): │ 💡 HomeController Mqtt -Connecting
I/flutter ( 5325): └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
I/flutter ( 5325): ┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
I/flutter ( 5325): │ 21:37:00.480 (+0:00:00.016625)
I/flutter ( 5325): ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
I/flutter ( 5325): │ 💡 Connecting 10.100.10.85
I/flutter ( 5325): └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
I/flutter ( 5325): 1-2024-03-16 21:37:00.491272 -- Authenticating with username '{admin}' and password '{123456}'
I/flutter ( 5325): 1-2024-03-16 21:37:00.492871 -- MqttClient::connect - Connection timeout period is 5000 milliseconds
I/flutter ( 5325): 1-2024-03-16 21:37:00.495914 -- MqttClient::connect - keep alive is enabled with a value of 5 seconds
I/flutter ( 5325): 1-2024-03-16 21:37:00.497245 -- MqttConnectionKeepAlive:: Initialised with a keep alive value of 5 seconds
I/flutter ( 5325): 1-2024-03-16 21:37:00.497523 -- MqttConnectionKeepAlive:: Disconnect on no ping response is enabled with a value of 5000 seconds
I/flutter ( 5325): 1-2024-03-16 21:37:00.498905 -- MqttConnectionHandlerBase::connect - server 10.100.10.85, port 9012
I/flutter ( 5325): 1-2024-03-16 21:37:00.500948 -- SynchronousMqttServerConnectionHandler::internalConnect entered
I/flutter ( 5325): 1-2024-03-16 21:37:00.501209 -- SynchronousMqttServerConnectionHandler::internalConnect - initiating connection try 0, auto reconnect in progress false
I/flutter ( 5325): 1-2024-03-16 21:37:00.501444 -- SynchronousMqttServerConnectionHandler::internalConnect - insecure TCP selected
I/flutter ( 5325): 1-2024-03-16 21:37:00.501955 -- SynchronousMqttServerConnectionHandler::internalConnect - calling connect
I/flutter ( 5325): 1-2024-03-16 21:37:00.502554 -- MqttNormalConnection::connect - entered
I/flutter ( 5325): 1-2024-03-16 21:37:05.501242 -- MqttConnectionKeepAlive::pingRequired
I/flutter ( 5325): 1-2024-03-16 21:37:05.501775 -- MqttConnectionKeepAlive::pingRequired - NOT sending ping - not connected
I/flutter ( 5325): 1-2024-03-16 21:37:05.501947 -- MqttConnectionKeepAlive::pingRequired - restarting ping timer
I/flutter ( 5325): 1-2024-03-16 21:37:05.502098 -- MqttConnectionKeepAlive::pingRequired - starting disconnect timer
I/flutter ( 5325): 1-2024-03-16 21:37:05.502303 -- MqttConnectionKeepAlive::noMessageSent - not disconnecting, not connected
I/flutter ( 5325): 1-2024-03-16 21:37:10.509325 -- MqttConnectionKeepAlive::pingRequired
I/flutter ( 5325): 1-2024-03-16 21:37:10.509615 -- MqttConnectionKeepAlive::pingRequired - NOT sending ping - not connected
I/flutter ( 5325): 1-2024-03-16 21:37:10.509775 -- MqttConnectionKeepAlive::pingRequired - restarting ping timer
I/flutter ( 5325): 1-2024-03-16 21:37:10.510014 -- MqttConnectionKeepAlive::pingRequired - starting disconnect timer
I/flutter ( 5325): 1-2024-03-16 21:37:10.510085 -- MqttConnectionKeepAlive::noMessageSent - not disconnecting, not connected
I/flutter ( 5325): 1-2024-03-16 21:37:15.520063 -- MqttConnectionKeepAlive::pingRequired
I/flutter ( 5325): 1-2024-03-16 21:37:15.520343 -- MqttConnectionKeepAlive::pingRequired - NOT sending ping - not connected

This is my entire log, and it says' NOT sending ping - not connected 'every 5s

What I am wondering now is, I set the timeout connection for 5s, why there is no exception after 5s

@laterdayi
Copy link
Author

@shamblett Looking forward to your help

@shamblett
Copy link
Owner

There is a gap in your logs of 5 seconds from here -

I/flutter ( 5325): 1-2024-03-16 21:37:00.502554 -- MqttNormalConnection::connect - entered

to here

I/flutter ( 5325): 1-2024-03-16 21:37:05.501242 -- MqttConnectionKeepAlive::pingRequired

It looks as though you are not connected but I don't know why, it should show the sending of your connect message as in the example below -

.....
I/flutter ( 3528): 1-2024-03-14 19:20:32.352038 -- MqttNormalConnection::connect - entered
I/flutter ( 3528): --------------------Instance of 'XMqttClient'
I/flutter ( 3528): 1-2024-03-14 19:20:32.482934 -- MqttServerConnection::_startListening
I/flutter ( 3528): 1-2024-03-14 19:20:32.485095 -- SynchronousMqttServerConnectionHandler::internalConnect - connection complete
I/flutter ( 3528): 1-2024-03-14 19:20:32.485327 -- SynchronousMqttServerConnectionHandler::internalConnect sending connect message
I/flutter ( 3528): 1-2024-03-14 19:20:32.486026 -- MqttConnectionHandlerBase::sendMessage - MQTTMessage of type MqttMessageType.connect
I/flutter ( 3528): Header: MessageType = MqttMessageType.connect, Duplicate = false, Retain = false, Qos = MqttQos.atMostOnce, Size = 0
I/flutter ( 3528): Connect Variable Header: ProtocolName=MQIsdp, ProtocolVersion=3, ConnectFlags=Connect Flags: Reserved1=false, CleanStart=true, WillFlag=true, WillQos=MqttQos.atLeastOnce, WillRetain=false, PasswordFlag=true, UserNameFlag=true, KeepAlive=0
.....

Looking at your code above you have this -

 mqttClient?.logging(on: false);

This should be set to true, also you do seem to have an onDisconnected callback -

 mqttClient?.onDisconnected = _onDisconnected;

The calling of this should also be logged, please supply a complete client log.

@laterdayi
Copy link
Author

This is already the complete log, MQTT is not connected, the connection time has expired and there are no exceptions or callbacks

@laterdayi
Copy link
Author

onDisconnected is not called, MQTT is always connected, with no timeout or exception

@laterdayi
Copy link
Author

@shamblett

@shamblett
Copy link
Owner

This is not a complete log from the MQTT client, please look through the issues for examples of complete logs also you say 'onDisconnected is not called, MQTT is always connected, with no timeout or exception' but your log above is showing its not connected -

I/flutter ( 5325): 1-2024-03-16 21:37:10.509325 -- MqttConnectionKeepAlive::pingRequired
I/flutter ( 5325): 1-2024-03-16 21:37:10.509615 -- MqttConnectionKeepAlive::pingRequired - NOT sending ping - not connected

@laterdayi
Copy link
Author

This is indeed all the logs, perhaps because the server is not starting service, but now I can't trigger any callbacks, and after 5S, there are no timeout exceptions

@laterdayi
Copy link
Author

ShareX_bXRbJ49Cpv.mp4

@laterdayi
Copy link
Author

@shamblett

@shamblett
Copy link
Owner

Sorry uouve lost me completely now, Ive never seen the client skip log entries also This is indeed all the logs, what does this mean 'perhaps because the server is not starting service, but now I can't trigger any callbacks, and after 5S, there are no timeout exceptions' What server? What service?

@laterdayi
Copy link
Author

ShareX_AZu05upVZc.mp4

This is all the logs in one minute, and I'll briefly describe the problem I encountered

  1. I set a timeout of five seconds. I hope that after five seconds, I can manually disconnect and reconnect. How should this be achieved?
  2. Now NOT sending ping - not connected will be repeated infinitely in the log. Is there a callback function that can handle it?
  3. What I want is that if the connection is not successful in 5S, I want to manually disconnect and reconnect manually.

Looking forward to your help

@shamblett

@laterdayi
Copy link
Author

class MqttUtil {
  // 
  MqttServerClient? mqttClient;
  MqttQos qos = MqttQos.atLeastOnce;
  //
  static MqttUtil? _instance;
  // 
  static MqttUtil getInstance() {
    _instance ??= MqttUtil();
    return _instance!;
  }

  // 
  Future<MqttClientConnectionStatus?> connect({
    String? server,
    int? port,
    String? clientIdentifier,
    String? username,
    String? password,
  }) async {
    try {
      mqttClient = MqttServerClient.withPort(
        AppEnv.kMQTTUrl,
        clientIdentifier ?? 'payton-pda-${UserStore.to.userInfo.user?.id}-${AppStore.to.appInfo.androidId}',
        AppEnv.kMQTTPort,
        maxConnectionAttempts: 1,
      );
      mqttClient?.logging(on: true);
      mqttClient?.keepAlivePeriod = 3;
      mqttClient?.onDisconnected = _onDisconnected;
      mqttClient?.onConnected = _onConnected;
      mqttClient?.onSubscribed = _onSubscribed;
      mqttClient?.onUnsubscribed = _onUnsubscribed;
      mqttClient?.onSubscribeFail = _onSubscribeFail;
      mqttClient?.pongCallback = () {
        UtilLog.info('pongCallback1111');
      };
      mqttClient?.connectTimeoutPeriod = 3000;
      mqttClient?.disconnectOnNoResponsePeriod = 3000;

      mqttClient?.onBadCertificate = (x) {
        UtilLog.info('onBadCertificate');
        return false;
      };
      mqttClient?.onAutoReconnected = () {
        UtilLog.info('onAutoReconnected');
      };
      mqttClient?.onAutoReconnect = () {
        UtilLog.info('onAutoReconnectComplete');
      };

      final connMessage = MqttConnectMessage().startClean().withWillQos(MqttQos.exactlyOnce);
      mqttClient?.connectionMessage = connMessage;
      UtilLog.info("Connecting ${AppEnv.kMQTTUrl}");
      return mqttClient?.connect(username, password);
    } catch (e) {
      UtilLog.error('MqttUtil connect', e);
    }
    return null;
  }

  // 
  Subscription? subscribeMessage(String subtopic) {
    return mqttClient?.subscribe(subtopic, qos);
  }


  unsubscribeMessage(String unSubtopic) {
    mqttClient?.unsubscribe(unSubtopic);
  }
  disconnect() {
    mqttClient?.disconnect();
  }
}
  connectMqtt() async {
    try {
      if (MqttUtil.getInstance().getMqttStatus() == MqttConnectionState.connected) {
        UtilLog.info('');
        MqttUtil.getInstance().subscribeMessage(Topics.awaitTakeOver);
      } else {
        UtilLog.info('HomeController Mqtt -Connecting');
        MqttClientConnectionStatus? status = await MqttUtil.getInstance().connect(
          username: 'admin',
          password: '123456',
        );
        connectMqtt();
        print(status);
      }
    } on Exception catch (e) {
      // 
      print(': $e');
    } on ConnectionException catch (e, s) {
      print(':$e');
    } on NoConnectionException catch (e, s) {
      print(':$e');
    } on SocketException catch (e, s) {
      print('Socket: $e');
    } catch (e, s) {
      print(':$e');
    }
    if (MqttUtil.getInstance().getMqttStatus() != MqttConnectionState.connected) {
      // MqttUtil.getInstance().disconnect();
    }
  }

@shamblett
Copy link
Owner

I can't see anywhere above where you set a timer for 5 seconds, however what I think you need to do is -

You have mqttClient?.connectTimeoutPeriod = 3000;, set this to 1000

You have maxConnectionAttempts 1, set this to 5

This will give you 5 connection attempts each 1 second apart, if the client is not connected after this period it will stop trying, giving you your 5 seconds, after that you can do your manual disconnect etc. You wont get an onDisconnected callback.

@laterdayi
Copy link
Author

laterdayi commented Mar 17, 2024

My understanding is that I set connectTimeoutPeriod = 3000. After more than 3S, mqtt_clicnt will help me disconnect and throw a timeout exception.

Do I now need to customize a timer to manually close the connection?

@shamblett

@shamblett
Copy link
Owner

Does the API documents say the client throws an exception after any kind of timeout? I don't think it does. Your understanding is wrong, please read the API docs.

You can start as many timers as you wish and do with them what you wish, anything that happens outside the client is not really of concern to this package.

Please identify any bugs you find or feature you want on added on the client, this is not a general purpose forum for how to handle MQTT clients.

@laterdayi
Copy link
Author

laterdayi commented Mar 17, 2024

If you want to add a callback or function when the connection times out, mqtt_client can throw a timeout exception.

@shamblett
Copy link
Owner

OK, so are you asking for a callback to be added in between connection attempts, i.e. if maxConnectionAttempts is 5 then you will trigger the callback on each failed connection attempt. If that's the case raise an issue for this documenting exactly what you want and which use case this will help with and I'll mark it as a feature request.

@laterdayi
Copy link
Author

laterdayi commented Mar 17, 2024

@shamblett #523 added a new request, describing the functionality and usage, looking forward to adding it, very urgent, thank you for the great work

@shamblett
Copy link
Owner

OK, closing this moving the work to #523

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants