ocpp
ocpp copied to clipboard
No timeout for message when websocket connection is down
I've set up a simple charging station and central system script like in the examples and they can communicate with each other via a localhost websocket connection. However, there is an issue where the websocket connection is broken (for example, by terminating the central system process) and when an OCPP message has just been sent from the charging station to the CS, or is sent right after the disconnect. As a result, the OCPP message is not answered. If this happens when the websocket connection is still live, there's a timeout triggered in ocpp/charge_point.py and the process resumes as expected.
In my implementation, the websocket client immediately tries to reconnect. So when the connection is restored -by restarting the central system- the charging station has again a valid websocket connection with the server.
However: There is no longer OCPP traffic coming through. The automated HeartbeatMessages are no longer being sent, statuses are not sent through, etc. I believe that this is a result of the async def call() function in the charge_point.py file, where it is said in the documentation:
"A timeout is raised when no response has arrived before expiring of the configured timeout.
When waiting for a response no other Call message can be send. So this function will wait before response arrives or response timeout has expired. This is in line the OCPP specification"
After a day of testing, I believe that this is where the issue originates: because we're still waiting for a response that will never come (original websocket connection was broken) and subsequently, all other OCPP traffic is blocked. This would explain the missing Heartbeats and Status messages.
It's possible to make the implementation a little bit more robust, by checking if there's a websocket connection present before sending any messages in the _send() function in the charge_point.py file:
class ChargePoint:
async def _send(self, message):
if self._connection.closed:
LOGGER.info('%s: send %s', self.id, "No websocket connection, not sending message...")
else:
LOGGER.info('%s: send %s', self.id, message)
await self._connection.send(message)
However, this will not be of any help when an OCPP message is sent to the central system and the central system does not respond immediately and in that time, the websocket connection drops. As a result, we would still end up with all the OCPP traffic blocked, even when the connection is restored shortly thereafter.