span rel="">
+ Next the '_after_action' hook is executed.
+
+ """
+ try:
+ handlers = self.route_map[msg.action]
+ except KeyError:
+ _raise_key_error(msg.action, self._ocpp_version)
+ return
+
+ if not handlers.get("_skip_schema_validation", False):
+ validate_payload(msg, self._ocpp_version)
+ # OCPP uses camelCase for the keys in the payload. It's more pythonic
+ # to use snake_case for keyword arguments. Therefore the keys must be
+ # 'translated'. Some examples:
+ #
+ # * chargePointVendor becomes charge_point_vendor
+ # * firmwareVersion becomes firmwareVersion
+ if msg.payload is None:
+ msg.payload = {}
+ snake_case_payload = camel_to_snake_case(msg.payload)
+
+ try:
+ handler = handlers["_on_action"]
+ except KeyError:
+ _raise_key_error(msg.action, self._ocpp_version)
+
+ try:
+ response = handler(**snake_case_payload)
+ if inspect.isawaitable(response):
+ response = await response
+ except Exception as e:
+ LOGGER.exception("Error while handling request '%s'", msg)
+ response = msg.create_call_error(e).to_json()
+ await self._send(response)
+
+ return
+
+ temp_response_payload = asdict(response)
+
+ # Remove nones ensures that we strip out optional arguments
+ # which were not set and have a default value of None
+ response_payload = remove_nones(temp_response_payload)
+
+ # The response payload must be 'translated' from snake_case to
+ # camelCase. So:
+ #
+ # * charge_point_vendor becomes chargePointVendor
+ # * firmware_version becomes firmwareVersion
+ camel_case_payload = snake_to_camel_case(response_payload)
+
+ response = msg.create_call_result(camel_case_payload)
+
+ if not handlers.get("_skip_schema_validation", False):
+ validate_payload(response, self._ocpp_version)
+
+ await self._send(response.to_json())
+
+ try:
+ handler = handlers["_after_action"]
+ # Create task to avoid blocking when making a call inside the
+ # after handler
+ response = handler(**snake_case_payload)
+ if inspect.isawaitable(response):
+ asyncio.ensure_future(response)
+ except KeyError:
+ # '_on_after' hooks are not required. Therefore ignore exception
+ # when no '_on_after' hook is installed.
+ pass
+ return response
+
+
+class ChargePoint(cp):
+
+ @on(Action.BootNotification)
+ def on_boot_notification(
+ self, charge_point_vendor: str, charge_point_model: str, **kwargs):
+ pprint(kwargs)
+ return call_result.BootNotificationPayload(
+ current_time=datetime.utcnow().isoformat(),
+ interval=10,
+ status=RegistrationStatus.accepted,
+ )
+
+ @on(Action.Authorize)
+ def on_authorization(self, id_tag):
+ # pprint(kwargs)
+ idti = IdTagInfo(status=AuthorizationStatus.accepted)
+ # idti.status = AuthorizationStatus.accepted
+
+ return call_result.AuthorizePayload(
+ id_tag_info=idti
+ )
+
+ @on(Action.StatusNotification)
+ def on_status_notification(self, id_tag):
+ # pprint(kwargs)
+ # idti = IdTagInfo(status=AuthorizationStatus.accepted)
+ # idti.status = AuthorizationStatus.accepted
+ return call_result.StatusNotificationPayload()
+
+ @on(Action.Heartbeat, skip_schema_validation=True)
+ def on_heartbeat(self, **kwargs): # receives empty payload from CP
+ print("--HeartBeat--")
+ print(kwargs)
+ return call_result.HeartbeatPayload(
+ current_time=datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ")
+ )
+
+
+
+async def on_connect(websocket, path):
+ """For every new charge point that connects, create a ChargePoint
+ instance and start listening for messages.
+ """
+ try:
+ requested_protocols = websocket.request_headers["Sec-WebSocket-Protocol"]
+ except KeyError:
+ logging.error("Client hasn't requested any Subprotocol. Closing Connection")
+ return await websocket.close()
+ if websocket.subprotocol:
+ logging.info("Protocols Matched: %s", websocket.subprotocol)
+ else:
+ # In the websockets lib if no subprotocols are supported by the
+ # client and the server, it proceeds without a subprotocol,
+ # so we have to manually close the connection.
+ logging.warning(
+ "Protocols Mismatched | Expected Subprotocols: %s,"
+ " but client supports %s | Closing connection",
+ websocket.available_subprotocols,
+ requested_protocols,
+ )
+ return await websocket.close()
+
+ charge_point_id = path.strip("/")
+ cp = ChargePoint(charge_point_id, websocket)
+
+ await cp.start()
+
+
+async def main():
+ server = await websockets.serve(
+ on_connect, "0.0.0.0", 9000, subprotocols=["ocpp1.6"]
+ )
+
+ logging.info("Server Started listening to new connections...")
+ await server.wait_closed()
+
+
+if __name__ == "__main__":
+ # asyncio.run() is used when running this example with Python >= 3.7v
+ asyncio.run(main())
|
||
| 1 |
|
|