Skip to content

Commit 1c7f795

Browse files
authored
fix: attempt to add ping/pong timeout logic to websocket (#403)
* fix: attempt to add ping/pong timeout logic to websocket * library version bump
1 parent ae2095d commit 1c7f795

File tree

3 files changed

+19
-2
lines changed

3 files changed

+19
-2
lines changed

openevsehttp/__main__.py

+2
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ async def _update_status(self, msgtype, data, error):
261261
self.websocket.uri,
262262
)
263263
self._ws_listening = False
264+
self.ws_start()
264265
# Stopped websockets without errors are expected during shutdown
265266
# and ignored
266267
elif data == STATE_STOPPED and error:
@@ -270,6 +271,7 @@ async def _update_status(self, msgtype, data, error):
270271
error,
271272
)
272273
self._ws_listening = False
274+
self.ws_disconnect()
273275

274276
elif msgtype == "data":
275277
_LOGGER.debug("Websocket data: %s", data)

openevsehttp/websocket.py

+16-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""Websocket class for OpenEVSE HTTP."""
22

33
import asyncio
4+
import datetime
45
import json
56
import logging
67

@@ -13,6 +14,7 @@
1314
ERROR_AUTH_FAILURE = "Authorization failure"
1415
ERROR_TOO_MANY_RETRIES = "Too many retries"
1516
ERROR_UNKNOWN = "Unknown"
17+
ERROR_PING_TIMEOUT = "No pong reply"
1618

1719
SIGNAL_CONNECTION_STATE = "websocket_state"
1820
STATE_CONNECTED = "connected"
@@ -41,6 +43,8 @@ def __init__(
4143
self.failed_attempts = 0
4244
self._error_reason = None
4345
self._client = None
46+
self._ping = None
47+
self._pong = None
4448

4549
@property
4650
def state(self):
@@ -86,6 +90,8 @@ async def running(self):
8690
msg = message.json()
8791
msgtype = "data"
8892
await self.callback(msgtype, msg, None)
93+
if "pong" in msg.keys:
94+
self._pong = datetime.datetime.now()
8995

9096
elif message.type == aiohttp.WSMsgType.CLOSED:
9197
_LOGGER.warning("Websocket connection closed")
@@ -139,13 +145,22 @@ async def close(self):
139145

140146
async def keepalive(self):
141147
"""Send ping requests to websocket."""
148+
if self._ping and self._pong:
149+
time_delta = self._pong - self._ping
150+
if time_delta < 0:
151+
# Negitive time should indicate no pong reply so consider the
152+
# websocket disconnected.
153+
await OpenEVSEWebsocket.state.fset(self, STATE_DISCONNECTED)
154+
self._error_reason = ERROR_PING_TIMEOUT
155+
142156
data = json.dumps({"ping": 1})
143157
_LOGGER.debug("Sending message: %s to websocket.", data)
144158
try:
145159
await self._client.send_str(data)
160+
self._ping = datetime.datetime.now()
146161
_LOGGER.debug("Ping message sent.")
147162
except TypeError as err:
148163
_LOGGER.error("Attempt to send ping data failed: %s", err)
149164
except Exception as err: # pylint: disable=broad-exception-caught
150165
_LOGGER.error("Problem sending ping request: %s", err)
151-
await OpenEVSEWebsocket.state.fset(self, STATE_STOPPED)
166+
await OpenEVSEWebsocket.state.fset(self, STATE_DISCONNECTED)

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
PROJECT_DIR = Path(__file__).parent.resolve()
88
README_FILE = PROJECT_DIR / "README.md"
9-
VERSION = "0.1.67"
9+
VERSION = "0.1.68"
1010

1111
setup(
1212
name="python_openevse_http",

0 commit comments

Comments
 (0)