def test_multiple_classes_with_same_name_for_handler(): class ChargerA(cp): @on(Action.Heartbeat) def heartbeat(self, **kwargs): pass class ChargerB(cp): @on(Action.Heartbeat) def heartbeat(self, **kwargs): pass A = ChargerA("A", None) B = ChargerB("B", None) route_mapA = create_route_map(A) route_mapB = create_route_map(B) assert route_mapA["Heartbeat"] != route_mapB["Heartbeat"]
async def test_route_message_with_existing_route(base_central_system, boot_notification_call): """ Test if the correct handler is called when routing a message. Also test if payload of request is injected correctly in handler. """ @on("BootNotification") def on_boot_notification(reason, charging_station, **kwargs): assert reason == 'PowerUp' assert charging_station == { 'vendor_name': 'ICU Eve Mini', 'firmware_version': "#1:3.4.0-2990#N:217H;1.0-223", 'model': 'ICU Eve Mini', } return call_result.BootNotificationPayload( current_time='2018-05-29T17:37:05.495259', interval=350, status='Accepted', ) @after("BootNotification") def after_boot_notification(reason, charging_station, **kwargs): assert reason == 'PowerUp' assert charging_station == { 'vendor_name': 'ICU Eve Mini', 'firmware_version': "#1:3.4.0-2990#N:217H;1.0-223", 'model': 'ICU Eve Mini', } setattr(base_central_system, 'on_boot_notification', on_boot_notification) setattr(base_central_system, 'after_boot_notification', after_boot_notification) base_central_system.route_map = create_route_map(base_central_system) await base_central_system.route_message(boot_notification_call) base_central_system._connection.send.assert_called_once_with( json.dumps([ 3, "1", { 'currentTime': '2018-05-29T17:37:05.495259', 'interval': 350, 'status': 'Accepted', } ], separators=(',', ':')))
async def test_route_message_without_validation(base_central_system): @on(Action.BootNotification, skip_schema_validation=True) def on_boot_notification(**kwargs): # noqa assert kwargs['firmware_version'] == "#1:3.4.0-2990#N:217H;1.0-223" return call_result.BootNotificationPayload( current_time='2018-05-29T17:37:05.495259', interval=350, # 'Yolo' is not a valid value for for field status. status='Yolo', ) setattr(base_central_system, 'on_boot_notification', on_boot_notification) base_central_system.route_map = create_route_map(base_central_system) await base_central_system.route_message(json.dumps([ 2, 1, "BootNotification", { # The payload is missing the required fields 'chargepointVendor' # and 'chargePointModel'. "firmwareVersion": "#1:3.4.0-2990#N:217H;1.0-223" } ], separators=(',', ':') )) base_central_system._connection.send.call_args == \ mock.call(json.dumps([ 3, "1", { 'currentTime': '2018-05-29T17:37:05.495259', 'interval': 350, 'status': 'Yolo', } ], separators=(',', ':') ))
def __init__(self, id, connection, response_timeout=30): """ Args: charger_id (str): ID of the charger. connection: Connection to CP. response_timeout (int): When no response on a request is received within this interval, a asyncio.TimeoutError is raised. """ self.id = id # The maximum time in seconds it may take for a CP to respond to a # CALL. An asyncio.TimeoutError will be raised if this limit has been # exceeded. self._response_timeout = response_timeout # A connection to the client. Currently this is an instance of gh self._connection = connection # A dictionary that hooks for Actions. So if the CS receives a it will # look up the Action into this map and execute the corresponding hooks # if exists. self.route_map = create_route_map(self) self._call_lock = asyncio.Lock() # A queue used to pass CallResults and CallErrors from # the self.serve() task to the self.call() task. self._response_queue = asyncio.Queue() # Function used to generate unique ids for CALLs. By default # uuid.uuid4() is used, but it can be changed. This is meant primarily # for testing purposes to have predictable unique ids. self._unique_id_generator = uuid.uuid4