Skip to content

Commit ad3232c

Browse files
authored
feat: add manual ping requests on websocket (#401)
* feat: add manual ping requests on websocket * linting * more linting
1 parent 96852e3 commit ad3232c

File tree

3 files changed

+32
-1
lines changed

3 files changed

+32
-1
lines changed

openevsehttp/__main__.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ def _start_listening(self):
240240

241241
if not self._ws_listening:
242242
self._loop.create_task(self.websocket.listen())
243+
self._loop.create_task(self.repeat(300, self.websocket.keepalive()))
243244
pending = asyncio.all_tasks()
244245
self._ws_listening = True
245246
try:
@@ -301,6 +302,20 @@ def ws_state(self) -> Any:
301302
assert self.websocket
302303
return self.websocket.state
303304

305+
async def repeat(self, interval, func, *args, **kwargs):
306+
"""Run func every interval seconds.
307+
308+
If func has not finished before *interval*, will run again
309+
immediately when the previous iteration finished.
310+
311+
*args and **kwargs are passed as the arguments to func.
312+
"""
313+
while True:
314+
await asyncio.gather(
315+
func(*args, **kwargs),
316+
asyncio.sleep(interval),
317+
)
318+
304319
async def get_schedule(self) -> Union[Dict[str, str], Dict[str, Any]]:
305320
"""Return the current schedule."""
306321
url = f"{self.url}schedule"

openevsehttp/websocket.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""Websocket class for OpenEVSE HTTP."""
22

33
import asyncio
4+
import json
45
import logging
56

67
import aiohttp # type: ignore
@@ -39,6 +40,7 @@ def __init__(
3940
self._state = None
4041
self.failed_attempts = 0
4142
self._error_reason = None
43+
self._client = None
4244

4345
@property
4446
def state(self):
@@ -74,6 +76,7 @@ async def running(self):
7476
) as ws_client:
7577
await OpenEVSEWebsocket.state.fset(self, STATE_CONNECTED)
7678
self.failed_attempts = 0
79+
self._client = ws_client
7780

7881
async for message in ws_client:
7982
if self.state == STATE_STOPPED:
@@ -133,3 +136,16 @@ async def listen(self):
133136
async def close(self):
134137
"""Close the listening websocket."""
135138
await OpenEVSEWebsocket.state.fset(self, STATE_STOPPED)
139+
140+
async def keepalive(self):
141+
"""Send ping requests to websocket."""
142+
data = json.dumps({"ping": 1})
143+
_LOGGER.debug("Sending message: %s to websocket.", data)
144+
try:
145+
await self._client.send_str(data)
146+
_LOGGER.debug("Ping message sent.")
147+
except TypeError as err:
148+
_LOGGER.error("Attempt to send ping data failed: %s", err)
149+
except Exception as err: # pylint: disable=broad-exception-caught
150+
_LOGGER.error("Problem sending ping request: %s", err)
151+
await OpenEVSEWebsocket.state.fset(self, STATE_STOPPED)

setup.py

Lines changed: 1 addition & 1 deletion
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.66"
9+
VERSION = "0.1.67"
1010

1111
setup(
1212
name="python_openevse_http",

0 commit comments

Comments
 (0)