Closed ChaitanyaYeole02 closed 1 year ago
@villekr To date, I have started a thread inside my on_connect. Inside the thread I have created an async loop that triggers remote_start_transaction. When I call my remote_start_transaction inside the thread, it waits for the response for a completed 30 seconds and when I call my remote_start_transaction inside any after action I get my response within seconds.
_onconnect
async def on_connect(self, context: RouterContext) -> bool:
print(
f"(CentralSystem) Charging Station id: {context.charging_station_id} subprotocol: "
f"{context.subprotocol} connected."
# noqa: E501
)
# You can inspect context.scope["headers"] and perform eg. basic authentication
ocpp_id = context.charging_station_id
print('Connected to:', ocpp_id)
thread = threading.Thread(target=self.some_function, args=(context))
thread.start()
return True
_somefunction
def some_function(self, context: RouterContext):
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.run_until_complete(self.async_function(context,))
loop.close()
_asyncfunction
async def async_function(self, context: RouterContext):
request = call.RemoteStartTransactionPayload(id_tag=user_id, connector_id=connector_id)
async with context.call_lock:
response = await v16_provisioning_router.call(message=request, context=context)
I think the simplest is to use asyncio.create_task
to run any logic when Charging Station connects. I briefly tested with the following code in class CentralSystem(ASGIApplication)
:
async def on_connect(self, context: RouterContext) -> bool:
print(
f"(CentralSystem) Charging Station id: {context.charging_station_id} subprotocol: {context.subprotocol} connected." # noqa: E501
)
# You can inspect context.scope["headers"] and perform e.g. basic authentication
allow_connection = True
if allow_connection:
# Create task for running any logic that happens during connection setup
asyncio.create_task(self.after_on_connect(context))
return allow_connection
async def after_on_connect(self, context: RouterContext):
# Example on how to send message to Charging Station e.g. after connection setup
await asyncio.sleep(1) # Give Charging Station some time once connected
if context.subprotocol == Subprotocol.ocpp16.value:
message = call16.RemoteStartTransactionPayload(id_tag="abc")
router = self.routers[context.subprotocol]
elif context.subprotocol == Subprotocol.ocpp20.value:
id_token = {"idToken": "abc", "type": "Central"}
message = call20.RequestStartTransactionPayload(
id_token=id_token, remote_start_id=123
)
router = self.routers[context.subprotocol]
elif context.subprotocol == Subprotocol.ocpp201.value:
id_token = {"idToken": "abc", "type": "Central"}
message = call201.RequestStartTransactionPayload(
id_token=id_token, remote_start_id=123
)
router = self.routers[context.subprotocol]
else:
raise ValueError(f"Unknown sub-protocol value: {context.subprotocol=}")
response = await router.call(message=message, context=context)
print(f"(Central System) Charging Station {id=} {response=}")
This does look a little strange, why CentralSystem should care about different ocpp protocol versions. So alternatively you could implement some generic functions in routers for all Central System initiated ocpp messages.
I want to send RemoteStartTransaction from a function called in on_connect. But as my context: RouterContext and send is implemented in HandlerContext. What can I do?