|
1 | 1 | """Websocket class for OpenEVSE HTTP."""
|
2 | 2 |
|
3 | 3 | import asyncio
|
| 4 | +import datetime |
4 | 5 | import json
|
5 | 6 | import logging
|
6 | 7 |
|
|
13 | 14 | ERROR_AUTH_FAILURE = "Authorization failure"
|
14 | 15 | ERROR_TOO_MANY_RETRIES = "Too many retries"
|
15 | 16 | ERROR_UNKNOWN = "Unknown"
|
| 17 | +ERROR_PING_TIMEOUT = "No pong reply" |
16 | 18 |
|
17 | 19 | SIGNAL_CONNECTION_STATE = "websocket_state"
|
18 | 20 | STATE_CONNECTED = "connected"
|
@@ -41,6 +43,8 @@ def __init__(
|
41 | 43 | self.failed_attempts = 0
|
42 | 44 | self._error_reason = None
|
43 | 45 | self._client = None
|
| 46 | + self._ping = None |
| 47 | + self._pong = None |
44 | 48 |
|
45 | 49 | @property
|
46 | 50 | def state(self):
|
@@ -86,6 +90,8 @@ async def running(self):
|
86 | 90 | msg = message.json()
|
87 | 91 | msgtype = "data"
|
88 | 92 | await self.callback(msgtype, msg, None)
|
| 93 | + if "pong" in msg.keys: |
| 94 | + self._pong = datetime.datetime.now() |
89 | 95 |
|
90 | 96 | elif message.type == aiohttp.WSMsgType.CLOSED:
|
91 | 97 | _LOGGER.warning("Websocket connection closed")
|
@@ -139,13 +145,22 @@ async def close(self):
|
139 | 145 |
|
140 | 146 | async def keepalive(self):
|
141 | 147 | """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 | + |
142 | 156 | data = json.dumps({"ping": 1})
|
143 | 157 | _LOGGER.debug("Sending message: %s to websocket.", data)
|
144 | 158 | try:
|
145 | 159 | await self._client.send_str(data)
|
| 160 | + self._ping = datetime.datetime.now() |
146 | 161 | _LOGGER.debug("Ping message sent.")
|
147 | 162 | except TypeError as err:
|
148 | 163 | _LOGGER.error("Attempt to send ping data failed: %s", err)
|
149 | 164 | except Exception as err: # pylint: disable=broad-exception-caught
|
150 | 165 | _LOGGER.error("Problem sending ping request: %s", err)
|
151 |
| - await OpenEVSEWebsocket.state.fset(self, STATE_STOPPED) |
| 166 | + await OpenEVSEWebsocket.state.fset(self, STATE_DISCONNECTED) |
0 commit comments