micropython-lib icon indicating copy to clipboard operation
micropython-lib copied to clipboard

"OSError: -1" if use keepalive>0

Open leech001 opened this issue 6 years ago • 10 comments

Traceback (most recent call last): File "main.py", line 55, in File "umqtt/simple.py", line 202, in check_msg File "umqtt/simple.py", line 171, in wait_msg OSError: -1

leech001 avatar Oct 01 '17 16:10 leech001

Please try using the latest umqtt library and then provide a minimal reproducible test case that shows the error.

dpgeorge avatar Oct 03 '17 09:10 dpgeorge

guess i'll just take over this issue thread ;)

when using keepalive>0, server disconnects from client and client raises an exception in given line 171 in wait_msg. So the socket disconnection is being correctly detected.

disregard my error description below! (only if you have the same problem and need a solution) the solution was to connect to the mqtt server with mqtt.connect(False) as only then a persistent session is started and the subscriptions are stored between connection problems. see #186 I forgot that in the connect method at the beginning and did it only in the reconnect function.. the only problem i have left is that with a restart of mosquitto, mosquitto loses all subscriptions although persistence is on. but this is not an issue of this library.

now to the original issue: i did set a last will message that is correctly send by the server. After this exception my client tries to reconnect and does it correctly (mqtt.connect(False) or True, does not make a difference here). I confirm the connection by sending out an online status from the client. Sending a message to the client now does nothing. the client just does not appear to get the message.

my thoughts on this so far:

  • connection is there as the client sends a message to the server
  • function check_msg is called without an exception as i'm monitoring it with an output
  • the set callback is not called

Steps to reproduce:

  • set last will
  • catch exception in wait_msg, reconnect and let it send a message for proof
  • connect to server with keepalive>0 without sending any messages or pings
  • subscribe to a topic and have a callback printing new messages
  • wait until connection breaks
  • last will is being sent and shortly after that client sends the reconnection message proofing the connection
  • send something to the subscribed topic
  • that message should show up but it does not

maybe i have a misconfigured server, won't exclude that possibility although it would be rather strange if that is the problem. I'm using a recent version of the mosquitto server.

kevinkk525 avatar Oct 30 '17 22:10 kevinkk525

I had same problem with continue disconnecting from the mqtt server with keepalive > 0. But I figure it out that disconnection happens because there was no any activity from my board with mqtt server during the period of time like keepalive value of seconds. So if the board will publish any mqtt message ("i'm alive") - the connection will not drop. I program to send the current board time to the debug topic during the half of the keepalive value of seconds. And it is working like a charm!

If I correct this issue is not an issue it is a feature.

If you set keepalive value - you have to send something to mqtt server to inform that you are alive in less time than keepalive value of seconds.

Actpohomoc avatar Nov 22 '17 11:11 Actpohomoc

I'm not sure is it task for mqtt client to keep connection alive in time. The umqtt/simple.py lib is only sending information to the server about keepalive time. Nothing more. It looks that this task to user who use this lib.

MQTT v3.1.1 specification

The Keep Alive is a time interval measured in seconds. Expressed as a 16-bit word, it is the maximum time interval that is permitted to elapse between the point at which the Client finishes transmitting one Control Packet and the point it starts sending the next. It is the responsibility of the Client to ensure that the interval between Control Packets being sent does not exceed the Keep Alive value. In the absence of sending any other Control Packets, the Client MUST send a PINGREQ Packet [MQTT-3.1.2-23].

The Client can send PINGREQ at any time, irrespective of the Keep Alive value, and use the PINGRESP to determine that the network and the Server are working.

If the Keep Alive value is non-zero and the Server does not receive a Control Packet from the Client within one and a half times the Keep Alive time period, it MUST disconnect the Network Connection to the Client as if the network had failed [MQTT-3.1.2-24].

If a Client does not receive a PINGRESP Packet within a reasonable amount of time after it has sent a PINGREQ, it SHOULD close the Network Connection to the Server.

A Keep Alive value of zero (0) has the effect of turning off the keep alive mechanism. This means that, in this case, the Server is not required to disconnect the Client on the grounds of inactivity. Note that a Server is permitted to disconnect a Client that it determines to be inactive or non-responsive at any time, regardless of the Keep Alive value provided by that Client.

Non normative comment The actual value of the Keep Alive is application specific; typically this is a few minutes. The maximum value is 18 hours 12 minutes and 15 seconds.

Actpohomoc avatar Nov 22 '17 15:11 Actpohomoc

that's why I call mqtt.ping() regularly. Together with last will this shows the device state in home-assistant. But I do not check if the server actually answers the request. If the server is down, the socket breaks anyways, throwing an exception, so the only problem left would be a mqtt server that is stuck, but this should be really rare. I'm using about a minute as keepalive.

kevinkk525 avatar Nov 22 '17 21:11 kevinkk525

The problem remains unsolved. I also have this problem.

kiscore avatar Dec 05 '18 08:12 kiscore

Hi! look this project https://github.com/leech001/Security-fire-alarm-ESP8266 I think I solved the problem there

leech001 avatar Dec 08 '18 14:12 leech001

keepLiveTime = 120 c = MQTTClient(CLIENT_ID, server, 1883, username, password, keepLiveTime)

tim = Timer(-1) tim.init(period=keepLiveTime*1000, mode=Timer.PERIODIC, callback=lambda t: keepLiveTimeCb(c))

def keepLiveTimeCb(c): c.ping()

shell use ping() func

xhlinux avatar Apr 20 '21 01:04 xhlinux

I've explored this issue and its comments and believe it can be closed:

  • In the OPs example, the behaviour is expected - the client must periodically ping() the broker, or otherwise send the broker some traffic to communicate that it's still alive.
  • The "original issue" outlined by @kevinkk525 seems to be a different problem: messages not received after reconnecting - There are many reasons why this can occur: broker not set to support sessions, connect() called without clean_session=False, etc. If it is reproducible, some code, and a new issue would be great. However, it looks like this was resolved using a periodic ping()
  • Other comments contain helpful tips that could be considered for inclusion as examples.

ian-llewellyn avatar May 26 '23 08:05 ian-llewellyn

您好,您的邮件已收到。

kiscore avatar May 26 '23 08:05 kiscore