Example #1
0
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=(',', ':')
        ))
Example #4
0
    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