- CitrineOS core extracted (CSMS OCPP 2.0.1) - OpenOCPP extracted (firmware OCPP 1.6J/2.0.1) - ShapeShifter library installed (pip install -e) - ShapeShifter specification extracted - EVerest extracted TODO updated with progress
699 lines
21 KiB
Python
699 lines
21 KiB
Python
# SPDX-License-Identifier: Apache-2.0
|
|
# Copyright Pionix GmbH and Contributors to EVerest
|
|
|
|
import pytest
|
|
import asyncio
|
|
from datetime import datetime
|
|
|
|
# fmt: off
|
|
import logging
|
|
|
|
from everest.testing.core_utils.controller.test_controller_interface import TestController
|
|
|
|
from ocpp.routing import on, create_route_map
|
|
from ocpp.v201 import call as call201
|
|
from ocpp.v201 import call_result as call_result201
|
|
from ocpp.v201.enums import *
|
|
from ocpp.v201.datatypes import *
|
|
from everest.testing.ocpp_utils.fixtures import *
|
|
from everest_test_utils import * # Needs to be before the datatypes below since it overrides the v201 Action enum with the v16 one
|
|
from ocpp.v201.enums import (Action, IdTokenEnumType as IdTokenTypeEnum, SetVariableStatusEnumType, ClearCacheStatusEnumType, ConnectorStatusEnumType)
|
|
from validations import validate_status_notification_201
|
|
from everest.testing.core_utils._configuration.libocpp_configuration_helper import GenericOCPP2XConfigAdjustment, OCPP2XConfigVariableIdentifier
|
|
from everest.testing.ocpp_utils.charge_point_utils import wait_for_and_validate, TestUtility, ValidationMode, validate_incoming_messages
|
|
# fmt: on
|
|
|
|
log = logging.getLogger("transactionsTest")
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
@pytest.mark.ocpp_version("ocpp2.0.1")
|
|
async def test_E04(
|
|
central_system_v201: CentralSystem,
|
|
test_controller: TestController,
|
|
test_utility: TestUtility,
|
|
):
|
|
"""
|
|
E04.FR.01
|
|
...
|
|
"""
|
|
# prepare data for the test
|
|
evse_id1 = 1
|
|
connector_id = 1
|
|
|
|
evse_id2 = 2
|
|
|
|
# make an unknown IdToken
|
|
id_token = IdTokenType(id_token="8BADF00D", type=IdTokenTypeEnum.iso14443)
|
|
|
|
log.info(
|
|
"##################### E04: Transaction started while charging station is offline #################"
|
|
)
|
|
|
|
test_controller.start()
|
|
charge_point_v201 = await central_system_v201.wait_for_chargepoint(
|
|
wait_for_bootnotification=True
|
|
)
|
|
|
|
# expect StatusNotification with status available
|
|
assert await wait_for_and_validate(
|
|
test_utility,
|
|
charge_point_v201,
|
|
"StatusNotification",
|
|
call201.StatusNotification(
|
|
datetime.now().isoformat(),
|
|
ConnectorStatusEnumType.available,
|
|
evse_id=evse_id1,
|
|
connector_id=connector_id,
|
|
),
|
|
validate_status_notification_201,
|
|
)
|
|
assert await wait_for_and_validate(
|
|
test_utility,
|
|
charge_point_v201,
|
|
"StatusNotification",
|
|
call201.StatusNotification(
|
|
datetime.now().isoformat(),
|
|
ConnectorStatusEnumType.available,
|
|
evse_id=evse_id2,
|
|
connector_id=connector_id,
|
|
),
|
|
validate_status_notification_201,
|
|
)
|
|
|
|
# Enable AuthCacheCtrlr
|
|
r: call_result201.SetVariables = (
|
|
await charge_point_v201.set_config_variables_req(
|
|
"AuthCacheCtrlr", "Enabled", "true"
|
|
)
|
|
)
|
|
set_variable_result: SetVariableResultType = SetVariableResultType(
|
|
**r.set_variable_result[0]
|
|
)
|
|
assert set_variable_result.attribute_status == SetVariableStatusEnumType.accepted
|
|
|
|
# Enable LocalPreAuthorize
|
|
r: call_result201.SetVariables = (
|
|
await charge_point_v201.set_config_variables_req(
|
|
"AuthCtrlr", "LocalPreAuthorize", "true"
|
|
)
|
|
)
|
|
set_variable_result: SetVariableResultType = SetVariableResultType(
|
|
**r.set_variable_result[0]
|
|
)
|
|
assert set_variable_result.attribute_status == SetVariableStatusEnumType.accepted
|
|
|
|
# Set AuthCacheLifeTime
|
|
r: call_result201.SetVariables = (
|
|
await charge_point_v201.set_config_variables_req(
|
|
"AuthCacheCtrlr", "LifeTime", "86400"
|
|
)
|
|
)
|
|
set_variable_result: SetVariableResultType = SetVariableResultType(
|
|
**r.set_variable_result[0]
|
|
)
|
|
assert set_variable_result.attribute_status == SetVariableStatusEnumType.accepted
|
|
|
|
# Clear cache
|
|
r: call_result201.ClearCache = await charge_point_v201.clear_cache_req()
|
|
assert r.status == ClearCacheStatusEnumType.accepted
|
|
|
|
# E04.FR.03 the queued transaction messages must contain the flag 'offline' as TRUE
|
|
|
|
# Enable offline authorization for unknown ID
|
|
r: call_result201.SetVariables = (
|
|
await charge_point_v201.set_config_variables_req(
|
|
"AuthCtrlr", "OfflineTxForUnknownIdEnabled", "true"
|
|
)
|
|
)
|
|
set_variable_result: SetVariableResultType = SetVariableResultType(
|
|
**r.set_variable_result[0]
|
|
)
|
|
assert set_variable_result.attribute_status == SetVariableStatusEnumType.accepted
|
|
|
|
# Enable AlignedDataSignReadings (Not implemented yet)
|
|
r: call_result201.SetVariables = (
|
|
await charge_point_v201.set_config_variables_req(
|
|
"AlignedDataCtrlr", "SignReadings", "true"
|
|
)
|
|
)
|
|
set_variable_result: SetVariableResultType = SetVariableResultType(
|
|
**r.set_variable_result[0]
|
|
)
|
|
assert set_variable_result.attribute_status == SetVariableStatusEnumType.accepted
|
|
|
|
test_utility.messages.clear()
|
|
|
|
# Disconnect CS
|
|
log.debug(" Disconnect the CS from the CSMS")
|
|
test_controller.disconnect_websocket()
|
|
|
|
await asyncio.sleep(2)
|
|
|
|
# swipe id tag to authorize
|
|
test_controller.swipe(id_token.id_token)
|
|
|
|
# start charging session
|
|
test_controller.plug_in()
|
|
|
|
# charge for 30 seconds
|
|
await asyncio.sleep(30)
|
|
|
|
# swipe id tag to de-authorize
|
|
test_controller.swipe(id_token.id_token)
|
|
|
|
# stop charging session
|
|
test_controller.plug_out()
|
|
|
|
await asyncio.sleep(10)
|
|
|
|
# Connect CS
|
|
log.debug(" Connect the CS to the CSMS")
|
|
test_controller.connect_websocket()
|
|
|
|
# wait for reconnect
|
|
charge_point_v201 = await central_system_v201.wait_for_chargepoint(
|
|
wait_for_bootnotification=False
|
|
)
|
|
|
|
# All offline generated transaction messaages must be marked offline = True
|
|
|
|
# should send a Transaction event C15.FR.02
|
|
assert await wait_for_and_validate(
|
|
test_utility,
|
|
charge_point_v201,
|
|
"TransactionEvent",
|
|
{"eventType": "Started", "offline": True},
|
|
)
|
|
# should send a Transaction event C15.FR.02
|
|
assert await wait_for_and_validate(
|
|
test_utility,
|
|
charge_point_v201,
|
|
"TransactionEvent",
|
|
{"eventType": "Updated", "offline": True},
|
|
)
|
|
# should send a Transaction event C15.FR.02
|
|
assert await wait_for_and_validate(
|
|
test_utility,
|
|
charge_point_v201,
|
|
"TransactionEvent",
|
|
{"eventType": "Ended", "offline": True},
|
|
)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
@pytest.mark.ocpp_version("ocpp2.0.1")
|
|
@pytest.mark.inject_csms_mock
|
|
@pytest.mark.ocpp_config_adaptions(
|
|
GenericOCPP2XConfigAdjustment(
|
|
[
|
|
(
|
|
OCPP2XConfigVariableIdentifier(
|
|
"OCPPCommCtrlr", "MessageTimeout", "Actual"
|
|
),
|
|
"1",
|
|
),
|
|
(
|
|
OCPP2XConfigVariableIdentifier(
|
|
"OCPPCommCtrlr", "MessageAttemptInterval", "Actual"
|
|
),
|
|
"1",
|
|
),
|
|
(
|
|
OCPP2XConfigVariableIdentifier(
|
|
"OCPPCommCtrlr", "MessageAttempts", "Actual"
|
|
),
|
|
"3",
|
|
),
|
|
]
|
|
)
|
|
)
|
|
@pytest.mark.flaky(reruns=1)
|
|
async def test_cleanup_transaction_events_after_max_attempts_exhausted(
|
|
central_system: CentralSystem,
|
|
test_controller: TestController,
|
|
test_utility: TestUtility,
|
|
):
|
|
"""
|
|
Test if transaction events are properly cleaned up after the max message attempts
|
|
...
|
|
"""
|
|
# prepare data for the test
|
|
evse_id1 = 1
|
|
connector_id = 1
|
|
|
|
evse_id2 = 2
|
|
connector_id2 = 1
|
|
|
|
# make an unknown IdToken
|
|
id_token = IdTokenType(id_token="8BADF00D", type=IdTokenTypeEnum.iso14443)
|
|
|
|
test_controller.start()
|
|
charge_point_v201 = await central_system.wait_for_chargepoint(
|
|
wait_for_bootnotification=True
|
|
)
|
|
tx_event_attempt = SetVariableDataType(attribute_value="3", attribute_type=AttributeEnumType.actual,
|
|
component=ComponentType(name="OCPPCommCtrlr"), variable=VariableType(name="MessageAttempts", instance="TransactionEvent"))
|
|
tx_event_interval = SetVariableDataType(attribute_value="1", attribute_type=AttributeEnumType.actual,
|
|
component=ComponentType(name="OCPPCommCtrlr"), variable=VariableType(name="MessageAttemptInterval", instance="TransactionEvent"))
|
|
r: call_result201.SetVariables = (
|
|
await charge_point_v201.set_variables_req(set_variable_data=[tx_event_attempt, tx_event_interval])
|
|
)
|
|
set_variable_result: SetVariableResultType = SetVariableResultType(
|
|
**r.set_variable_result[0]
|
|
)
|
|
assert set_variable_result.attribute_status == SetVariableStatusEnumType.accepted
|
|
set_variable_result: SetVariableResultType = SetVariableResultType(
|
|
**r.set_variable_result[1]
|
|
)
|
|
assert set_variable_result.attribute_status == SetVariableStatusEnumType.accepted
|
|
|
|
# expect StatusNotification with status available
|
|
assert await wait_for_and_validate(
|
|
test_utility,
|
|
charge_point_v201,
|
|
"StatusNotification",
|
|
call201.StatusNotification(
|
|
datetime.now().isoformat(),
|
|
ConnectorStatusEnumType.available,
|
|
evse_id=evse_id1,
|
|
connector_id=connector_id,
|
|
),
|
|
validate_status_notification_201,
|
|
)
|
|
assert await wait_for_and_validate(
|
|
test_utility,
|
|
charge_point_v201,
|
|
"StatusNotification",
|
|
call201.StatusNotification(
|
|
datetime.now().isoformat(),
|
|
ConnectorStatusEnumType.available,
|
|
evse_id=evse_id2,
|
|
connector_id=connector_id2,
|
|
),
|
|
validate_status_notification_201,
|
|
)
|
|
|
|
# return a CALLERROR for the transaction event
|
|
central_system.mock.on_transaction_event.side_effect = [
|
|
NotImplementedError()]
|
|
|
|
# swipe id tag to authorize
|
|
test_controller.swipe(id_token.id_token)
|
|
|
|
# start charging session
|
|
test_controller.plug_in()
|
|
|
|
# should send a Transaction event
|
|
assert await wait_for_and_validate(
|
|
test_utility,
|
|
charge_point_v201,
|
|
"TransactionEvent",
|
|
{"eventType": "Started", "offline": False},
|
|
)
|
|
test_utility.validation_mode = ValidationMode.STRICT
|
|
|
|
assert await wait_for_and_validate(
|
|
test_utility,
|
|
charge_point_v201,
|
|
"TransactionEvent",
|
|
{"eventType": "Started", "offline": False},
|
|
)
|
|
|
|
assert await wait_for_and_validate(
|
|
test_utility,
|
|
charge_point_v201,
|
|
"TransactionEvent",
|
|
{"eventType": "Started", "offline": False},
|
|
)
|
|
|
|
assert await wait_for_and_validate(
|
|
test_utility,
|
|
charge_point_v201,
|
|
"TransactionEvent",
|
|
{"eventType": "Updated", "offline": False},
|
|
)
|
|
|
|
test_utility.validation_mode = ValidationMode.EASY
|
|
central_system.mock.on_transaction_event.reset()
|
|
|
|
# respond properly to transaction events again
|
|
central_system.mock.on_transaction_event.side_effect = [
|
|
call_result201.TransactionEvent()
|
|
]
|
|
|
|
# stop charging session
|
|
test_controller.plug_out()
|
|
|
|
assert await wait_for_and_validate(
|
|
test_utility,
|
|
charge_point_v201,
|
|
"TransactionEvent",
|
|
{"eventType": "Ended", "offline": False},
|
|
)
|
|
|
|
assert await wait_for_and_validate(
|
|
test_utility,
|
|
charge_point_v201,
|
|
"StatusNotification",
|
|
{"evseId": 1, "connectorId": 1, "connectorStatus": "Available"},
|
|
)
|
|
|
|
test_controller.stop()
|
|
# add a sleep to allow time for reboot
|
|
await asyncio.sleep(2)
|
|
test_controller.start()
|
|
|
|
# no attempts on delivering the transaction message should be made
|
|
assert await validate_incoming_messages(test_utility, charge_point_v201, "TransactionEvent", {}, timeout=10) is False
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
@pytest.mark.ocpp_version("ocpp2.0.1")
|
|
@pytest.mark.inject_csms_mock
|
|
@pytest.mark.ocpp_config_adaptions(
|
|
GenericOCPP2XConfigAdjustment(
|
|
[
|
|
(
|
|
OCPP2XConfigVariableIdentifier(
|
|
"AlignedDataCtrlr", "AlignedDataTxEndedInterval", "Actual"
|
|
),
|
|
"5",
|
|
)
|
|
]
|
|
)
|
|
)
|
|
async def test_two_parallel_transactions(
|
|
central_system: CentralSystem,
|
|
test_controller: TestController,
|
|
test_utility: TestUtility,
|
|
):
|
|
"""
|
|
Test if two parallel transactions work
|
|
...
|
|
"""
|
|
# prepare data for the test
|
|
evse_id1 = 1
|
|
connector_id = 1
|
|
|
|
evse_id2 = 2
|
|
connector_id2 = 1
|
|
|
|
# make an unknown IdToken
|
|
id_token = IdTokenType(id_token="8BADF00D", type=IdTokenTypeEnum.iso14443)
|
|
id_token2 = IdTokenType(id_token="ABAD1DEA", type=IdTokenTypeEnum.iso14443)
|
|
|
|
test_controller.start()
|
|
charge_point_v201 = await central_system.wait_for_chargepoint(
|
|
wait_for_bootnotification=True
|
|
)
|
|
|
|
# expect StatusNotification with status available
|
|
assert await wait_for_and_validate(
|
|
test_utility,
|
|
charge_point_v201,
|
|
"StatusNotification",
|
|
call201.StatusNotification(
|
|
datetime.now().isoformat(),
|
|
ConnectorStatusEnumType.available,
|
|
evse_id=evse_id1,
|
|
connector_id=connector_id,
|
|
),
|
|
validate_status_notification_201,
|
|
)
|
|
assert await wait_for_and_validate(
|
|
test_utility,
|
|
charge_point_v201,
|
|
"StatusNotification",
|
|
call201.StatusNotification(
|
|
datetime.now().isoformat(),
|
|
ConnectorStatusEnumType.available,
|
|
evse_id=evse_id2,
|
|
connector_id=connector_id2,
|
|
),
|
|
validate_status_notification_201,
|
|
)
|
|
|
|
# swipe id tag to authorize
|
|
test_controller.swipe(id_token.id_token, connectors=[1])
|
|
|
|
# start charging session
|
|
test_controller.plug_in(evse_id1)
|
|
|
|
# should send a Transaction event
|
|
assert await wait_for_and_validate(
|
|
test_utility,
|
|
charge_point_v201,
|
|
"TransactionEvent",
|
|
{"eventType": "Started", "offline": False},
|
|
)
|
|
|
|
# swipe id tag to authorize
|
|
test_controller.swipe(id_token2.id_token, connectors=[2])
|
|
|
|
# start charging session
|
|
test_controller.plug_in(evse_id2)
|
|
|
|
# should send a Transaction event
|
|
assert await wait_for_and_validate(
|
|
test_utility,
|
|
charge_point_v201,
|
|
"TransactionEvent",
|
|
{"eventType": "Started", "offline": False},
|
|
)
|
|
# let transactions run for a bit
|
|
await asyncio.sleep(10)
|
|
# # stop charging session
|
|
test_controller.plug_out(evse_id1)
|
|
|
|
assert await wait_for_and_validate(
|
|
test_utility,
|
|
charge_point_v201,
|
|
"TransactionEvent",
|
|
{"eventType": "Ended", "offline": False},
|
|
)
|
|
test_controller.plug_out(evse_id2)
|
|
assert await wait_for_and_validate(
|
|
test_utility,
|
|
charge_point_v201,
|
|
"TransactionEvent",
|
|
{"eventType": "Ended", "offline": False},
|
|
)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
@pytest.mark.ocpp_version("ocpp2.0.1")
|
|
async def test_id_token_info_updated_in_tx_event(
|
|
central_system_v201: CentralSystem,
|
|
test_controller: TestController,
|
|
test_utility: TestUtility,
|
|
):
|
|
# prepare data for the test
|
|
evse_id1 = 1
|
|
connector_id = 1
|
|
|
|
evse_id2 = 2
|
|
|
|
# make an unknown IdToken
|
|
id_token = IdTokenType(id_token="8BADF00D", type=IdTokenTypeEnum.iso14443)
|
|
|
|
log.info(
|
|
"##################### Transaction with token info updated in transaction event #################"
|
|
)
|
|
|
|
test_controller.start()
|
|
charge_point_v201 = await central_system_v201.wait_for_chargepoint(
|
|
wait_for_bootnotification=True
|
|
)
|
|
|
|
# expect StatusNotification with status available
|
|
assert await wait_for_and_validate(
|
|
test_utility,
|
|
charge_point_v201,
|
|
"StatusNotification",
|
|
call201.StatusNotification(
|
|
datetime.now().isoformat(),
|
|
ConnectorStatusEnumType.available,
|
|
evse_id=evse_id1,
|
|
connector_id=connector_id,
|
|
),
|
|
validate_status_notification_201,
|
|
)
|
|
assert await wait_for_and_validate(
|
|
test_utility,
|
|
charge_point_v201,
|
|
"StatusNotification",
|
|
call201.StatusNotification(
|
|
datetime.now().isoformat(),
|
|
ConnectorStatusEnumType.available,
|
|
evse_id=evse_id2,
|
|
connector_id=connector_id,
|
|
),
|
|
validate_status_notification_201,
|
|
)
|
|
|
|
@on(Action.transaction_event)
|
|
def on_transaction_event(**kwargs):
|
|
msg = call201.TransactionEvent(**kwargs)
|
|
if msg.id_token != None:
|
|
msg_token = IdTokenType(**msg.id_token)
|
|
return call_result201.TransactionEvent(
|
|
id_token_info=IdTokenInfoType(
|
|
status=AuthorizationStatusEnumType.accepted,
|
|
group_id_token=IdTokenType(
|
|
id_token="123", type=IdTokenTypeEnum.central
|
|
),
|
|
)
|
|
)
|
|
else:
|
|
return call_result201.TransactionEvent()
|
|
|
|
setattr(charge_point_v201, "on_transaction_event", on_transaction_event)
|
|
central_system_v201.chargepoint.route_map = create_route_map(
|
|
central_system_v201.chargepoint
|
|
)
|
|
# swipe id tag to authorize
|
|
test_controller.swipe(id_token.id_token)
|
|
assert await wait_for_and_validate(
|
|
test_utility,
|
|
charge_point_v201,
|
|
"Authorize",
|
|
{},
|
|
)
|
|
# start charging session
|
|
test_controller.plug_in()
|
|
assert await wait_for_and_validate(
|
|
test_utility,
|
|
charge_point_v201,
|
|
"TransactionEvent",
|
|
{"eventType": "Started"},
|
|
)
|
|
|
|
assert await wait_for_and_validate(
|
|
test_utility,
|
|
charge_point_v201,
|
|
"TransactionEvent",
|
|
{"eventType": "Updated"},
|
|
)
|
|
|
|
# charge for 10 seconds
|
|
await asyncio.sleep(10)
|
|
|
|
@on(Action.authorize)
|
|
def on_authorize(**kwargs):
|
|
msg = call201.Authorize(**kwargs)
|
|
msg_token = IdTokenType(**msg.id_token)
|
|
return call_result201.Authorize(
|
|
id_token_info=IdTokenInfoType(
|
|
status=AuthorizationStatusEnumType.accepted,
|
|
group_id_token=IdTokenType(
|
|
id_token="123", type=IdTokenTypeEnum.central
|
|
),
|
|
)
|
|
)
|
|
setattr(charge_point_v201, "on_authorize", on_authorize)
|
|
central_system_v201.chargepoint.route_map = create_route_map(
|
|
central_system_v201.chargepoint
|
|
)
|
|
# swipe id tag to de-authorize
|
|
id_token = IdTokenType(id_token="8BADF00A", type=IdTokenTypeEnum.iso14443)
|
|
test_controller.swipe(id_token.id_token)
|
|
assert await wait_for_and_validate(
|
|
test_utility,
|
|
charge_point_v201,
|
|
"Authorize",
|
|
{},
|
|
)
|
|
# should send a Transaction event C15.FR.02
|
|
assert await wait_for_and_validate(
|
|
test_utility,
|
|
charge_point_v201,
|
|
"TransactionEvent",
|
|
{"eventType": "Ended"},
|
|
)
|
|
|
|
# stop charging session
|
|
test_controller.plug_out()
|
|
|
|
@pytest.mark.asyncio
|
|
@pytest.mark.ocpp_version("ocpp2.0.1")
|
|
@pytest.mark.everest_core_config('everest-config-ocpp201-ps.yaml')
|
|
@pytest.mark.use_temporary_persistent_store
|
|
@pytest.mark.ocpp_config_adaptions(
|
|
GenericOCPP2XConfigAdjustment(
|
|
[
|
|
(
|
|
OCPP2XConfigVariableIdentifier(
|
|
"InternalCtrlr",
|
|
"ResumeTransactionsOnBoot",
|
|
"Actual",
|
|
),
|
|
"true",
|
|
),
|
|
]
|
|
)
|
|
)
|
|
async def test_stop_pending_transactions(
|
|
central_system_v201: CentralSystem,
|
|
test_controller: TestController,
|
|
test_utility: TestUtility,
|
|
):
|
|
logging.info("######### test_stop_pending_transactions #########")
|
|
|
|
# prepare data for the test
|
|
evse_id = 1
|
|
connector_id = 1
|
|
remote_start_id = 1
|
|
id_token = IdTokenType(id_token="DEADBEEF", type=IdTokenTypeEnum.iso14443)
|
|
|
|
test_controller.start()
|
|
charge_point_v201 = await central_system_v201.wait_for_chargepoint(
|
|
wait_for_bootnotification=True
|
|
)
|
|
|
|
|
|
await charge_point_v201.request_start_transaction_req(
|
|
id_token=id_token, remote_start_id=remote_start_id, evse_id=evse_id
|
|
)
|
|
|
|
test_controller.plug_in()
|
|
|
|
assert await wait_for_and_validate(
|
|
test_utility, charge_point_v201, "TransactionEvent", {
|
|
"eventType": "Started"}
|
|
)
|
|
|
|
assert await wait_for_and_validate(
|
|
test_utility,
|
|
charge_point_v201,
|
|
"TransactionEvent",
|
|
{"eventType": "Updated"},
|
|
)
|
|
|
|
# charge for some time...
|
|
logging.debug("Charging for a while...")
|
|
await asyncio.sleep(2)
|
|
|
|
test_controller.stop()
|
|
|
|
await asyncio.sleep(2)
|
|
|
|
test_controller.start()
|
|
|
|
charge_point_v201 = await central_system_v201.wait_for_chargepoint(
|
|
wait_for_bootnotification=False
|
|
)
|
|
|
|
await asyncio.sleep(2)
|
|
|
|
assert await wait_for_and_validate(
|
|
test_utility,
|
|
charge_point_v201,
|
|
"TransactionEvent",
|
|
{
|
|
"eventType": "Ended",
|
|
"transactionInfo": {
|
|
"stoppedReason": "PowerLoss"
|
|
}
|
|
},
|
|
) |