Skip to content

Commit

Permalink
fix: attempt to add ping/pong timeout logic to websocket
Browse files Browse the repository at this point in the history
  • Loading branch information
firstof9 committed Jan 9, 2025
1 parent 7bb4b80 commit 08c0906
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 1 deletion.
2 changes: 2 additions & 0 deletions openevsehttp/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ async def _update_status(self, msgtype, data, error):
self.websocket.uri,
)
self._ws_listening = False
self.ws_start()
# Stopped websockets without errors are expected during shutdown
# and ignored
elif data == STATE_STOPPED and error:
Expand All @@ -270,6 +271,7 @@ async def _update_status(self, msgtype, data, error):
error,
)
self._ws_listening = False
self.ws_disconnect()

elif msgtype == "data":
_LOGGER.debug("Websocket data: %s", data)
Expand Down
17 changes: 16 additions & 1 deletion openevsehttp/websocket.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Websocket class for OpenEVSE HTTP."""

import asyncio
import datetime
import json
import logging

Expand All @@ -13,6 +14,7 @@
ERROR_AUTH_FAILURE = "Authorization failure"
ERROR_TOO_MANY_RETRIES = "Too many retries"
ERROR_UNKNOWN = "Unknown"
ERROR_PING_TIMEOUT = "No pong reply"

SIGNAL_CONNECTION_STATE = "websocket_state"
STATE_CONNECTED = "connected"
Expand Down Expand Up @@ -41,6 +43,8 @@ def __init__(
self.failed_attempts = 0
self._error_reason = None
self._client = None
self._ping = None
self._pong = None

@property
def state(self):
Expand Down Expand Up @@ -86,6 +90,8 @@ async def running(self):
msg = message.json()
msgtype = "data"
await self.callback(msgtype, msg, None)
if "pong" in msg.keys:
self._pong = datetime.datetime.now()

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

async def keepalive(self):
"""Send ping requests to websocket."""
if self._ping and self._pong:
time_delta = self._pong - self._ping
if time_delta < 0:
# Negitive time should indicate no pong reply so consider the
# websocket disconnected.
await OpenEVSEWebsocket.state.fset(self, STATE_DISCONNECTED)
self._error_reason = ERROR_PING_TIMEOUT

data = json.dumps({"ping": 1})
_LOGGER.debug("Sending message: %s to websocket.", data)
try:
await self._client.send_str(data)
self._ping = datetime.datetime.now()
_LOGGER.debug("Ping message sent.")
except TypeError as err:
_LOGGER.error("Attempt to send ping data failed: %s", err)
except Exception as err: # pylint: disable=broad-exception-caught
_LOGGER.error("Problem sending ping request: %s", err)
await OpenEVSEWebsocket.state.fset(self, STATE_STOPPED)
await OpenEVSEWebsocket.state.fset(self, STATE_DISCONNECTED)

0 comments on commit 08c0906

Please sign in to comment.