diff --git a/CHANGELOG.md b/CHANGELOG.md index ff93cc963..7bc698c14 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,36 @@ - [#421](https://github.com/mobilityhouse/ocpp/issues/421) Type of v16.datatypes.SampledValue.context is incorrect +## 0.25.0 (2024-01-08) + +- [#366](https://github.com/mobilityhouse/ocpp/issues/366) Fix type hint of OCPP 1.6 ChangeConfiguration.value +- [#431](https://github.com/mobilityhouse/ocpp/issues/431) Attributes with 'v2x' are serialized as 'V2x', but should be serialized as 'V2X' +- [#554](https://github.com/mobilityhouse/ocpp/issues/554) OCPP 2.0.1 Edition 2 Errata 2023-12 document added +- [#548](https://github.com/mobilityhouse/ocpp/issues/548) OCPP 2.0.1 MessageInfoType attribute name correction +- [#300](https://github.com/mobilityhouse/ocpp/issues/300) OCPP 2.0.1 add reference components and variables +- [#518](https://github.com/mobilityhouse/ocpp/issues/518) OCPP 2.0.1 add additional reason codes from v1.3 + +## 0.24.0 (2023-12-07) + +- [#539](https://github.com/mobilityhouse/ocpp/issues/539) feat: Add ChargePoint._handle_call return value. Thanks [@wafa-yah](https://github.com/wafa-yah) +- [#266](https://github.com/mobilityhouse/ocpp/issues/266) fix: Central System documentation link. +- [#516](https://github.com/mobilityhouse/ocpp/issues/516) OCPP 2.0.1 add additional security events from v1.3. +- [#537](https://github.com/mobilityhouse/ocpp/pull/537) Fix DataTransfer data types. Thanks [@mdwcrft](https://github.com/mdwcrft) + +## 0.23.0 (2023-11-30) + +- [#531] Feat: Add 1.6 security extension datatypes. Thanks [@proelke](https://github.com/proelke) +- [#528](https://github.com/mobilityhouse/ocpp/issues/528) v2.0.1 CertificateHashDataChainType childCertificateHashData requires the default of None. +- [#510](https://github.com/mobilityhouse/ocpp/issues/510) v2.0.1 UnitOfMeasureType - Enums missing and update docstring to allow use for variableCharacteristics. +- [#508](https://github.com/mobilityhouse/ocpp/issues/508) Exception - OccurrenceConstraintViolationError doc string correction. + +## 0.22.0 (2023-11-03) + +- [#493](https://github.com/mobilityhouse/ocpp/issues/493) Reduce use of NotSupportedError in favor of NotImplementedError. Thanks [drc38](@https://github.com/drc38). +- [#278](https://github.com/mobilityhouse/ocpp/pull/278) Fix types for attributes of OCPP 1.6's type `IdTagInfo`. Thanks [@chan-vince](https://github.com/chan-vince) +- [#504](https://github.com/mobilityhouse/ocpp/pull/504) Add missing tech_info attribute to v2.0.1 EventDataType. Thanks [@LokiHokie](https://github.com/LokiHokie) +- [#381](https://github.com/mobilityhouse/ocpp/issues/381) Add FormationError and OccurrenceConstraintViolationError. + ## 0.21.0 (2023-10-19) - [#492] Minor fixes _handle_call doc string - Thanks @drc38 diff --git a/README.rst b/README.rst index 1a7662234..0df940525 100644 --- a/README.rst +++ b/README.rst @@ -50,7 +50,7 @@ Central system The code snippet below creates a simple OCPP 2.0 central system which is able to handle BootNotification calls. You can find a detailed explanation of the -code in the `Central System documentation_`. +code in the `Central System documentation`_. .. code-block:: python diff --git a/docs/source/conf.py b/docs/source/conf.py index e0041a60b..592b903c2 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -23,7 +23,7 @@ author = "Auke Willem Oosterhoff" # The full version, including alpha/beta/rc tags -release = "0.21.0" +release = "0.25.0" # -- General configuration --------------------------------------------------- diff --git a/docs/v201/OCPP-2.0.1_edition2_errata_2023-12.pdf b/docs/v201/OCPP-2.0.1_edition2_errata_2023-12.pdf new file mode 100644 index 000000000..9b55afbbc Binary files /dev/null and b/docs/v201/OCPP-2.0.1_edition2_errata_2023-12.pdf differ diff --git a/examples/v201/central_system.py b/examples/v201/central_system.py index 0f5fb515e..54a880d89 100644 --- a/examples/v201/central_system.py +++ b/examples/v201/central_system.py @@ -42,8 +42,6 @@ async def on_connect(websocket, path): try: requested_protocols = websocket.request_headers["Sec-WebSocket-Protocol"] except KeyError: - logging.info("Client hasn't requested any Subprotocol. " "Closing Connection") - return await websocket.close() logging.error("Client hasn't requested any Subprotocol. Closing Connection") return await websocket.close() if websocket.subprotocol: diff --git a/ocpp/charge_point.py b/ocpp/charge_point.py index 78f56549e..997943de7 100644 --- a/ocpp/charge_point.py +++ b/ocpp/charge_point.py @@ -7,7 +7,7 @@ from dataclasses import asdict from typing import Dict, List, Union -from ocpp.exceptions import NotSupportedError, OCPPError +from ocpp.exceptions import NotImplementedError, NotSupportedError, OCPPError from ocpp.messages import Call, MessageType, unpack, validate_payload from ocpp.routing import create_route_map @@ -44,7 +44,7 @@ def camel_to_snake_case(data): def snake_to_camel_case(data): """ - Convert all keys of a all dictionaries inside given argument from + Convert all keys of all dictionaries inside given argument from snake_case to camelCase. Inspired by: https://stackoverflow.com/a/19053800/1073222 @@ -53,6 +53,7 @@ def snake_to_camel_case(data): camel_case_dict = {} for key, value in data.items(): key = key.replace("soc", "SoC") + key = key.replace("_v2x", "V2X") components = key.split("_") key = components[0] + "".join(x[:1].upper() + x[1:] for x in components[1:]) camel_case_dict[key] = snake_to_camel_case(value) @@ -79,6 +80,39 @@ def remove_nones(data: Union[List, Dict]) -> Union[List, Dict]: return data +def _raise_key_error(action, version): + """ + Checks whether a keyerror returned by _handle_call + is supported by the OCPP version or is simply + not implemented by the server/client and raises + the appropriate error. + """ + + from ocpp.v16.enums import Action as v16_Action + from ocpp.v201.enums import Action as v201_Action + + if version == "1.6": + if hasattr(v16_Action, action): + raise NotImplementedError( + details={"cause": f"No handler for {action} registered."} + ) + else: + raise NotSupportedError( + details={"cause": f"{action} not supported by OCPP{version}."} + ) + elif version in ["2.0", "2.0.1"]: + if hasattr(v201_Action, action): + raise NotImplementedError( + details={"cause": f"No handler for {action} registered."} + ) + else: + raise NotSupportedError( + details={"cause": f"{action} not supported by OCPP{version}."} + ) + + return + + class ChargePoint: """ Base Element containing all the necessary OCPP1.6J messages for messages @@ -165,7 +199,8 @@ async def _handle_call(self, msg): First the '_on_action' hook is executed and its response is returned to the client. If there is no '_on_action' hook for Action in the message - a CallError with a NotSupportedError is returned. + a CallError with a NotImplementedError is returned. If the Action is + not supported by the OCPP version a NotSupportedError is returned. Next the '_after_action' hook is executed. @@ -173,9 +208,8 @@ async def _handle_call(self, msg): try: handlers = self.route_map[msg.action] except KeyError: - raise NotSupportedError( - details={"cause": f"No handler for {msg.action} registered."} - ) + _raise_key_error(msg.action, self._ocpp_version) + return if not handlers.get("_skip_schema_validation", False): validate_payload(msg, self._ocpp_version) @@ -190,9 +224,7 @@ async def _handle_call(self, msg): try: handler = handlers["_on_action"] except KeyError: - raise NotSupportedError( - details={"cause": f"No handler for {msg.action} registered."} - ) + _raise_key_error(msg.action, self._ocpp_version) try: response = handler(**snake_case_payload) @@ -236,6 +268,7 @@ async def _handle_call(self, msg): # '_on_after' hooks are not required. Therefore ignore exception # when no '_on_after' hook is installed. pass + return response async def call(self, payload, suppress=True, unique_id=None): """ diff --git a/ocpp/exceptions.py b/ocpp/exceptions.py index 6c570425f..cefba9549 100644 --- a/ocpp/exceptions.py +++ b/ocpp/exceptions.py @@ -35,14 +35,14 @@ def __str__(self): class NotImplementedError(OCPPError): code = "NotImplemented" - default_description = "Requested Action is not known by receiver" + default_description = ( + "Request Action is recognized but not supported by the receiver" + ) class NotSupportedError(OCPPError): code = "NotSupported" - default_description = ( - "Request Action is recognized but not supported by " "the receiver" - ) + default_description = "Requested Action is not known by receiver" class InternalError(OCPPError): @@ -68,12 +68,31 @@ class SecurityError(OCPPError): class FormatViolationError(OCPPError): + """ + Not strict OCPP 1.6 - see FormationViolationError + Valid OCPP 2.0.1 + """ + code = "FormatViolation" default_description = ( "Payload for Action is syntactically incorrect or " "structure for Action" ) +class FormationViolationError(OCPPError): + """ + To allow for strict OCPP 1.6 compliance + 5. Known issues that will not be fixed + 5.2. Page 14, par 4.2.3. CallError: incorrect name in enum: FormationViolation + Incorrect name in enum: FormationViolation + """ + + code = "FormationViolation" + default_description = ( + "Payload for Action is syntactically incorrect or structure for Action" + ) + + class PropertyConstraintViolationError(OCPPError): code = "PropertyConstraintViolation" default_description = ( @@ -83,6 +102,15 @@ class PropertyConstraintViolationError(OCPPError): class OccurenceConstraintViolationError(OCPPError): + """ + To allow for strict OCPP 1.6 compliance + ocpp-j-1.6-errata-sheet.pdf + 5. Known issues that will not be fixed + 5.1. Page 14, par 4.2.3: CallError: Typo in enum + Typo in enum: OccurenceConstraintViolation + Valid in 2.0.1 + """ + code = "OccurenceConstraintViolation" default_description = ( "Payload for Action is syntactically correct but " @@ -91,6 +119,21 @@ class OccurenceConstraintViolationError(OCPPError): ) +class OccurrenceConstraintViolationError(OCPPError): + """ + Not strict OCPP 1.6 - see OccurenceConstraintViolationError + Not valid OCPP 2.0.1 + Valid in OCPP 2.1 + """ + + code = "OccurrenceConstraintViolation" + default_description = ( + "Payload for Action is syntactically correct but " + "at least one of the fields violates occurence " + "constraints" + ) + + class TypeConstraintViolationError(OCPPError): code = "TypeConstraintViolation" default_description = ( diff --git a/ocpp/v16/call.py b/ocpp/v16/call.py index 54e35c4d6..fe07e7d6d 100644 --- a/ocpp/v16/call.py +++ b/ocpp/v16/call.py @@ -1,5 +1,5 @@ from dataclasses import dataclass, field -from typing import Any, Dict, List, Optional +from typing import Dict, List, Optional from ocpp.v16.enums import ( AvailabilityType, @@ -55,7 +55,7 @@ class ChangeAvailabilityPayload: @dataclass class ChangeConfigurationPayload: key: str - value: Any + value: str @dataclass diff --git a/ocpp/v16/call_result.py b/ocpp/v16/call_result.py index 03deb0553..4e105d33b 100644 --- a/ocpp/v16/call_result.py +++ b/ocpp/v16/call_result.py @@ -1,6 +1,7 @@ from dataclasses import dataclass from typing import Dict, List, Optional +from ocpp.v16.datatypes import IdTagInfo from ocpp.v16.enums import ( AvailabilityStatus, CancelReservationStatus, @@ -46,7 +47,7 @@ @dataclass class AuthorizePayload: - id_tag_info: Dict + id_tag_info: IdTagInfo @dataclass @@ -94,7 +95,7 @@ class MeterValuesPayload: @dataclass class StartTransactionPayload: transaction_id: int - id_tag_info: Dict + id_tag_info: IdTagInfo @dataclass @@ -104,7 +105,7 @@ class StatusNotificationPayload: @dataclass class StopTransactionPayload: - id_tag_info: Optional[Dict] = None + id_tag_info: Optional[IdTagInfo] = None # The CALLRESULT messages that flow from Charge Point to Central System are diff --git a/ocpp/v16/datatypes.py b/ocpp/v16/datatypes.py index 4f49f0e93..36c751a7c 100644 --- a/ocpp/v16/datatypes.py +++ b/ocpp/v16/datatypes.py @@ -7,6 +7,7 @@ ChargingProfilePurposeType, ChargingRateUnitType, CiStringType, + HashAlgorithm, Location, Measurand, Phase, @@ -121,3 +122,45 @@ class MeterValue: timestamp: str sampled_value: List[SampledValue] + + +# Security Extension + + +@dataclass +class CertificateHashData: + """ + CertificateHashDataType is used by: + DeleteCertificate.req, GetInstalledCertificateIds.conf + """ + + hash_algorithm: HashAlgorithm + issuer_name_hash: str + issuer_key_hash: str + serial_number: str + + +@dataclass +class Firmware: + """ + Represents a copy of the firmware that can be loaded/updated on the Charge Point. + FirmwareType is used by: SignedUpdateFirmware.req + """ + + location: str + retrieve_date_time: str + signing_certificate: str + install_date_time: Optional[str] = None + signature: Optional[str] = None + + +@dataclass +class LogParameters: + """ + Class for detailed information the retrieval of logging entries. + LogParametersType is used by: GetLog.req + """ + + remote_location: str + oldest_timestamp: Optional[str] = None + latest_timestamp: Optional[str] = None diff --git a/ocpp/v201/call.py b/ocpp/v201/call.py index f97f9a1e1..bff98238b 100644 --- a/ocpp/v201/call.py +++ b/ocpp/v201/call.py @@ -90,7 +90,7 @@ class CustomerInformationPayload: class DataTransferPayload: vendor_id: str message_id: Optional[str] = None - data: Optional[str] = None + data: Optional[Any] = None custom_data: Optional[Dict[str, Any]] = None diff --git a/ocpp/v201/call_result.py b/ocpp/v201/call_result.py index 6f3b25f0b..3a59b07a2 100644 --- a/ocpp/v201/call_result.py +++ b/ocpp/v201/call_result.py @@ -87,7 +87,7 @@ class CustomerInformationPayload: class DataTransferPayload: status: str status_info: Optional[Dict] = None - data: Optional[Dict] = None + data: Optional[Any] = None custom_data: Optional[Dict[str, Any]] = None diff --git a/ocpp/v201/datatypes.py b/ocpp/v201/datatypes.py index 0c01b70ab..b9a2fabd7 100644 --- a/ocpp/v201/datatypes.py +++ b/ocpp/v201/datatypes.py @@ -67,7 +67,7 @@ class CertificateHashDataChainType: certificate_type: enums.GetCertificateIdUseType certificate_hash_data: CertificateHashDataType - child_certificate_hash_data: Optional[List[CertificateHashDataType]] + child_certificate_hash_data: Optional[List[CertificateHashDataType]] = None @dataclass @@ -395,6 +395,7 @@ class EventDataType: variable: VariableType cause: Optional[int] = None tech_code: Optional[str] = None + tech_info: Optional[str] = None cleared: Optional[bool] = None transaction_id: Optional[str] = None variable_monitoring_id: Optional[int] = None @@ -529,7 +530,7 @@ class MessageInfoType: message: MessageContentType state: Optional[enums.MessageStateType] = None start_date_time: Optional[str] = None - end_data_time: Optional[str] = None + end_date_time: Optional[str] = None transaction_id: Optional[str] = None display: Optional[ComponentType] = None diff --git a/ocpp/v201/enums.py b/ocpp/v201/enums.py index 30b12a756..625fafbf3 100644 --- a/ocpp/v201/enums.py +++ b/ocpp/v201/enums.py @@ -91,7 +91,8 @@ class AttributeType(str, Enum): getVariables:GetVariablesRequest.GetVariableDataType , getVariables:GetVariablesResponse.GetVariableResultType , setVariables:SetVariablesRequest.SetVariableDataType , - setVariables:SetVariablesResponse.SetVariableResultType + setVariables:SetVariablesResponse.SetVariableResultType , + ConnectedEV component variable AttributeType """ actual = "Actual" @@ -1244,7 +1245,8 @@ class UnitOfMeasureType(str, Enum): """ Allowable values of the optional "unit" field of a Value element, as used in MeterValues.req and StopTransaction.req messages. Default value of - "unit" is always "Wh". + "unit" is always "Wh". Also used in component/variables - + specifically the unit in variableCharacteristics. """ asu = "ASU" @@ -1283,7 +1285,9 @@ class UnitOfMeasureType(str, Enum): class StatusInfoReasonType(str, Enum): - """Standardized reason codes for StatusInfo defined in Appendix 5.""" + """ + Standardized reason codes for StatusInfo defined in Appendix 5. v1.3 + """ cs_not_accepted = "CSNotAccepted" duplicate_profile = "DuplicateProfile" @@ -1294,11 +1298,13 @@ class StatusInfoReasonType(str, Enum): invalid_certificate = "InvalidCertificate" invalid_csr = "InvalidCSR" invalid_id_token = "InvalidIdToken" + invalid_message_sequence = "InvalidMessageSequence" invalid_profile = "InvalidProfile" invaild_schedule = "InvalidSchedule" invalid_stack_level = "InvalidStackLevel" invalid_url = "InvalidURL" invalid_value = "InvalidValue" + missing_device_model_info = "MissingDeviceModelInfo" missing_param = "MissingParam" no_cable = "NoCable" no_error = "NoError" @@ -1329,7 +1335,9 @@ class StatusInfoReasonType(str, Enum): class SecurityEventType(str, Enum): - """Security Events as listed in Appendices (Appendix 1. Security Events)""" + """ + Security Events as listed in Appendices (Appendix 1. Security Events) v1.3 + """ firmware_updated = "FirmwareUpdated" failed_to_authenticate_at_csms = "FailedToAuthenticateAtCsms" @@ -1349,3 +1357,1350 @@ class SecurityEventType(str, Enum): invalid_charging_station_certificate = "InvalidChargingStationCertificate" invalid_tls_version = "InvalidTLSVersion" invalid_tls_cipher_suite = "InvalidTLSCipherSuite" + maintenance_login_accepted = "MaintenanceLoginAccepted" + maintenance_login_failed = "MaintenanceLoginFailed" + + +class ControllerComponentName(str, Enum): + """ + Referenced Controller Components (Logical Components) + Sourced from ocpp 2.0.1 part 2 appendices 3.1 v1.3, in + appendices_CSV_v1.3.zip dm_components_vars.csv and components.csv. + """ + + aligned_data_ctrlr = "AlignedDataCtrlr" + auth_cache_ctrlr = "AuthCacheCtrlr" + auth_ctrlr = "AuthCtrlr" + chademo_ctrlr = "CHAdeMOCtrlr" + clock_ctrlr = "ClockCtrlr" + customization_ctrlr = "CustomizationCtrlr" + device_data_ctrlr = "DeviceDataCtrlr" + display_message_ctrlr = "DisplayMessageCtrlr" + iso15118_ctrlr = "ISO15118Ctrlr" + local_auth_list_ctrlr = "LocalAuthListCtrlr" + monitoring_ctrlr = "MonitoringCtrlr" + ocpp_comm_ctrlr = "OCPPCommCtrlr" + reservation_ctrlr = "ReservationCtrlr" + sampled_data_ctrlr = "SampledDataCtrlr" + security_ctrlr = "SecurityCtrlr" + smart_charging_ctrlr = "SmartChargingCtrlr" + tariff_cost_ctrlr = "TariffCostCtrlr" + tx_ctrlr = "TxCtrlr" + + +class PhysicalComponentName(str, Enum): + """ + Referenced Physical Components - sourced from dm_components_vars.csv. + Note: specific variables for each component are sourced from a union of + ocpp 2.0.1 part 2 appendices 3.2 v1.3 and dm_components_vars.csv + from appendices_CSV_v1.3.zip. That is for all Physical Components in + section 3.2. expressed in this module as enums, + e.g. the variables of ControllerVariableName enum + """ + + access_barrier = "AccessBarrier" + ac_dc_converter = "AcDcConverter" + ac_phase_selector = "AcPhaseSelector" + actuator = "Actuator" + air_cooling_system = "AirCoolingSystem" + area_ventilation = "AreaVentilation" + bay_occupancy_sensor = "BayOccupancySensor" + beacon_lighting = "BeaconLighting" + cable_breakaway_sensor = "CableBreakawaySensor" + case_access_sensor = "CaseAccessSensor" + charging_station = "ChargingStation" + charging_status_indicator = "ChargingStatusIndicator" + connected_ev = "ConnectedEV" + connector = "Connector" + connector_holster_release = "ConnectorHolsterRelease" + connector_holster_sensor = "ConnectorHolsterSensor" + connector_plug_retention_lock = "ConnectorPlugRetentionLock" + connector_protection_release = "ConnectorProtectionRelease" + controller = "Controller" + control_metering = "ControlMetering" + cppwm_controller = "CPPWMController" + data_link = "DataLink" + display = "Display" + distribution_panel = "DistributionPanel" + electrical_feed = "ElectricalFeed" + elv_supply = "ELVSupply" + emergency_stop_sensor = "EmergencyStopSensor" + environmental_lighting = "EnvironmentalLighting" + ev_retention_lock = "EVRetentionLock" + evse = "EVSE" + external_temperature_sensor = "ExternalTemperatureSensor" + fiscal_metering = "FiscalMetering" + flood_sensor = "FloodSensor" + ground_isolation_protection = "GroundIsolationProtection" + heater = "Heater" + humidity_sensor = "HumiditySensor" + light_sensor = "LightSensor" + liquid_cooling_system = "LiquidCoolingSystem" + local_availability_sensor = "LocalAvailabilitySensor" + local_controller = "LocalController" + local_energy_storage = "LocalEnergyStorage" + over_current_protection = "OverCurrentProtection" + over_current_protection_recloser = "OverCurrentProtectionRecloser" + power_contactor = "PowerContactor" + rcd = "RCD" + rcd_recloser = "RCDRecloser" + real_time_clock = "RealTimeClock" + shock_sensor = "ShockSensor" + spaces_count_signage = "SpacesCountSignage" + switch = "Switch" + temperature_sensor = "TemperatureSensor" + tilt_sensor = "TiltSensor" + token_reader = "TokenReader" + ui_input = "UIInput" + upstream_protection_trigger = "UpstreamProtectionTrigger" + vehicle_id_sensor = "VehicleIdSensor" + + +class GenericVariableName(str, Enum): + """ + Variable names where the component type is non-specific + derived from a union of in appendices_CSV_v1.3.zip, + dm_components_vars.csv (Generic) and variables.csv + """ + + ac_current = "ACCurrent" + active = "Active" + ac_voltage = "ACVoltage" + allow_reset = "AllowReset" + angle = "Angle" + attempts = "Attempts" + availability_state = "AvailabilityState" + available = "Available" + certificate = "Certificate" + charge_protocol = "ChargeProtocol" + charging_complete_bulk = "ChargingCompleteBulk" + charging_complete_full = "ChargingCompleteFull" + charging_time = "ChargingTime" + color = "Color" + complete = "Complete" + connected_time = "ConnectedTime" + connector_type = "ConnectorType" + count = "Count" + currency = "Currency" + current_imbalance = "CurrentImbalance" + data_text = "DataText" + date_time = "DateTime" + dc_current = "DCCurrent" + dc_voltage = "DCVoltage" + departure_time = "DepartureTime" + ec_variant = "ECVariant" + enabled = "Enabled" + energy = "Energy" + energy_capacity = "EnergyCapacity" + energy_export = "EnergyExport" + energy_export_register = "EnergyExportRegister" + energy_import = "EnergyImport" + energy_import_register = "EnergyImportRegister" + entries = "Entries" + evse_id = "EvseId" + fallback = "Fallback" + fan_speed = "FanSpeed" + firmware_version = "FirmwareVersion" + force = "Force" + formats = "Formats" + frequency = "Frequency" + fuse_rating = "FuseRating" + height = "Height" + humidity = "Humidity" + hysteresis = "Hysteresis" + iccid = "ICCID" + impedance = "Impedance" + imsi = "IMSI" + interval = "Interval" + length = "Length" + light = "Light" + manufacturer = "Manufacturer" + message = "Message" + minimum_status_duration = "MinimumStatusDuration" + mode = "Mode" + model = "Model" + network_address = "NetworkAddress" + operated = "Operated" + operating_times = "OperatingTimes" + overload = "Overload" + percent = "Percent" + phase_rotation = "PhaseRotation" + post_charging_time = "PostChargingTime" + power = "Power" + problem = "Problem" + protecting = "Protecting" + remaining_time_bulk = "RemainingTimeBulk" + remaining_time_full = "RemainingTimeFull" + secc_id = "SeccId" + serial_number = "SerialNumber" + signal_strength = "SignalStrength" + state = "State" + state_of_charge = "StateOfCharge" + state_of_charge_bulk = "StateOfChargeBulk" + storage = "Storage" + supply_phases = "SupplyPhases" + suspending = "Suspending" + suspension = "Suspension" + temperature = "Temperature" + time = "Time" + time_offset = "TimeOffset" + timeout = "Timeout" + token = "Token" + token_type = "TokenType" + tries = "Tries" + tripped = "Tripped" + vehicle_id = "VehicleId" + version_date = "VersionDate" + version_number = "VersionNumber" + voltage_imbalance = "VoltageImbalance" + + +class AlignedDataCtrlrVariableName(str, Enum): + """ + Variable names where the component type is AlignedDataCtrlr + See ControllerComponentName for referenced logical component + """ + + available = "Available" + enabled = "Enabled" + interval = "Interval" + measurands = "Measurands" + send_during_idle = "SendDuringIdle" + sign_readings = "SignReadings" + tx_ended_interval = "TxEndedInterval" + tx_ended_measurands = "TxEndedMeasurands" + + +class AuthCacheCtrlrVariableName(str, Enum): + """ + Variable names where the component type is AuthCacheCtrlr + See ControllerComponentName for referenced logical component + """ + + available = "Available" + enabled = "Enabled" + life_time = "LifeTime" + policy = "Policy" + storage = "Storage" + disable_post_authorize = "DisablePostAuthorize" + + +class AuthCtrlrVariableName(str, Enum): + """ + Variable names where the component type is AuthCtrlr + See ControllerComponentName for referenced logical component + """ + + additional_info_items_per_message = "AdditionalInfoItemsPerMessage" + authorize_remote_start = "AuthorizeRemoteStart" + enabled = "Enabled" + local_authorize_offline = "LocalAuthorizeOffline" + local_pre_authorize = "LocalPreAuthorize" + master_pass_group_id = "MasterPassGroupId" + offline_tx_for_unknown_id_enabled = "OfflineTxForUnknownIdEnabled" + disable_remote_authorization = "DisableRemoteAuthorization" + + +class CHAdeMOCtrlrVariableName(str, Enum): + """ + Variable names where the component type is CHAdeMOCtrlr + See ControllerComponentName for referenced logical component + """ + + enabled = "Enabled" + active = "Active" + complete = "Complete" + tripped = "Tripped" + problem = "Problem" + selftest_active = "SelftestActive" + selftest_active_set = "SelftestActive(Set)" + chademo_protocol_number = "CHAdeMOProtocolNumber" + vehicle_status = "VehicleStatus" + dynamic_control = "DynamicControl" + high_current_control = "HighCurrentControl" + high_voltage_control = "HighVoltageControl" + auto_manufacturer_code = "AutoManufacturerCode" + + +class ClockCtrlrVariableName(str, Enum): + """ + Variable names where the component type is ClockCtrlr + See ControllerComponentName for referenced logical component + """ + + date_time = "DateTime" + next_time_offset_transition_date_time = "NextTimeOffsetTransitionDateTime" + ntp_server_uri = "NtpServerUri" + ntp_source = "NtpSource" + time_adjustment_reporting_threshold = "TimeAdjustmentReportingThreshold" + time_offset = "TimeOffset" + time_source = "TimeSource" + time_zone = "TimeZone" + + +class CustomizationCtrlrVariableName(str, Enum): + """ + Variable names where the component type is CustomizationCtrlr + See ControllerComponentName for referenced logical component + """ + + custom_implementation_enabled = "CustomImplementationEnabled" + + +class DeviceDataCtrlrVariableName(str, Enum): + """ + Variable names where the component type is DeviceDataCtrlr + See ControllerComponentName for referenced logical component + """ + + bytes_per_message = "BytesPerMessage" + configuration_value_size = "ConfigurationValueSize" + items_per_message = "ItemsPerMessage" + reporting_value_size = "ReportingValueSize" + value_size = "ValueSize" + + +class DeviceDataCtrlrInstanceName(str, Enum): + """ + Instance names where the component type is DeviceDataCtrlr + """ + + get_report = "GetReport" + get_variables = "GetVariables" + set_variables = "SetVariables" + + +class DisplayMessageCtrlrVariableName(str, Enum): + """ + Variable names where the component type is DisplayMessageCtrlr + See ControllerComponentName for referenced logical component + """ + + available = "Available" + display_messages = "DisplayMessages" + enabled = "Enabled" + personal_message_size = "PersonalMessageSize" + supported_formats = "SupportedFormats" + supported_priorities = "SupportedPriorities" + + +class ISO15118CtrlrVariableName(str, Enum): + """ + Variable names where the component type is ISO15118Ctrlr + See ControllerComponentName for referenced logical component + """ + + active = "Active" + enabled = "Enabled" + central_contract_validation_allowed = "CentralContractValidationAllowed" + complete = "Complete" + contract_validation_offline = "ContractValidationOffline" + secc_id = "SeccId" + selftest_active = "SelftestActive" + selftest_active_set = "SelftestActive(Set)" + max_schedule_entries = "MaxScheduleEntries" + requested_energy_transfer_mode = "RequestedEnergyTransferMode" + request_metering_receipt = "RequestMeteringReceipt" + country_name = "CountryName" + organization_name = "OrganizationName" + pnc_enabled = "PnCEnabled" + problem = "Problem" + tripped = "Tripped" + v2g_certificate_installation_enabled = "V2GCertificateInstallationEnabled" + contract_certificate_installation_enabled = "ContractCertificateInstallationEnabled" + + +class LocalAuthListCtrlrVariableName(str, Enum): + """ + Variable names where the component type is LocalAuthListCtrlr + See ControllerComponentName for referenced logical component + """ + + available = "Available" + bytes_per_message = "BytesPerMessage" + enabled = "Enabled" + entries = "Entries" + items_per_message = "ItemsPerMessage" + storage = "Storage" + disable_post_authorize = "DisablePostAuthorize" + + +class MonitoringCtrlrVariableName(str, Enum): + """ + Variable names where the component type is MonitoringCtrlr + See ControllerComponentName for referenced logical component + """ + + available = "Available" + bytes_per_message = "BytesPerMessage" + enabled = "Enabled" + items_per_message = "ItemsPerMessage" + offline_queuing_severity = "OfflineQueuingSeverity" + monitoring_base = "MonitoringBase" + monitoring_level = "MonitoringLevel" + active_monitoring_base = "ActiveMonitoringBase" + active_monitoring_level = "ActiveMonitoringLevel" + + +class MonitoringCtrlrInstanceName(str, Enum): + """ + Instance names where the component type is MonitoringCtrlr + """ + + clear_variable_monitoring = "ClearVariableMonitoring" + set_variable_monitoring = "SetVariableMonitoring" + + +class OCPPCommCtrlrVariableName(str, Enum): + """ + Variable names where the component type is OCPPCommCtrlr + See ControllerComponentName for referenced logical component + """ + + active_network_profile = "ActiveNetworkProfile" + file_transfer_protocols = "FileTransferProtocols" + heartbeat_interval = "HeartbeatInterval" + message_timeout = "MessageTimeout" + message_attempt_interval = "MessageAttemptInterval" + message_attempts = "MessageAttempts" + minimum_status_duration = "MinimumStatusDuration" + network_configuration_priority = "NetworkConfigurationPriority" + network_profile_connection_attempts = "NetworkProfileConnectionAttempts" + offline_threshold = "OfflineThreshold" + public_key_with_signed_meter_value = "PublicKeyWithSignedMeterValue" + queue_all_messages = "QueueAllMessages" + reset_retries = "ResetRetries" + retry_back_off_random_range = "RetryBackOffRandomRange" + retry_back_off_repeat_times = "RetryBackOffRepeatTimes" + retry_back_off_wait_minimum = "RetryBackOffWaitMinimum" + unlock_on_ev_side_disconnect = "UnlockOnEVSideDisconnect" + web_socket_ping_interval = "WebSocketPingInterval" + field_length = "FieldLength" + + +class OCPPCommCtrlrInstanceName(str, Enum): + """ + Instance names where the component type is OCPPCommCtrlr + """ + + default = "Default" + transaction_event = "TransactionEvent" + + +class ReservationCtrlrVariableName(str, Enum): + """ + Variable names where the component type is ReservationCtrlr + See ControllerComponentName for referenced logical component + """ + + available = "Available" + enabled = "Enabled" + non_evse_specific = "NonEvseSpecific" + + +class SampledDataCtrlrVariableName(str, Enum): + """ + Variable names where the component type is SampledDataCtrlr + See ControllerComponentName for referenced logical component + """ + + available = "Available" + enabled = "Enabled" + sign_readings = "SignReadings" + tx_ended_interval = "TxEndedInterval" + tx_ended_measurands = "TxEndedMeasurands" + tx_started_measurands = "TxStartedMeasurands" + tx_updated_interval = "TxUpdatedInterval" + tx_updated_measurands = "TxUpdatedMeasurands" + register_values_without_phases = "RegisterValuesWithoutPhases" + + +class SecurityCtrlrVariableName(str, Enum): + """ + Variable names where the component type is SampledDataCtrlr + See ControllerComponentName for referenced logical component + """ + + additional_root_certificate_check = "AdditionalRootCertificateCheck" + basic_auth_password = "BasicAuthPassword" + certificate_entries = "CertificateEntries" + cert_signing_repeat_times = "CertSigningRepeatTimes" + cert_signing_wait_minimum = "CertSigningWaitMinimum" + identity = "Identity" + max_certificate_chain_size = "MaxCertificateChainSize" + organization_name = "OrganizationName" + security_profile = "SecurityProfile" + + +class SmartChargingCtrlrVariableName(str, Enum): + """ + Variable names where the component type is SmartChargingCtrlr + See ControllerComponentName for referenced logical component + """ + + ac_phase_switching_supported = "ACPhaseSwitchingSupported" + available = "Available" + enabled = "Enabled" + entries = "Entries" + external_control_signals_enabled = "ExternalControlSignalsEnabled" + limit_change_significance = "LimitChangeSignificance" + notify_charging_limit_with_schedules = "NotifyChargingLimitWithSchedules" + periods_per_schedule = "PeriodsPerSchedule" + phases_3to1 = "Phases3to1" + profile_stack_level = "ProfileStackLevel" + rate_unit = "RateUnit" + + +class SmartChargingCtrlrInstanceName(str, Enum): + """ + Instance names where the component type is SmartChargingCtrlr + """ + + charging_profiles = "ChargingProfiles" + + +class TariffCostCtrlrVariableName(str, Enum): + """ + Variable names where the component type is TariffCostCtrlr + See ControllerComponentName for referenced logical component + """ + + available = "Available" + currency = "Currency" + enabled = "Enabled" + tariff_fallback_message = "TariffFallbackMessage" + total_cost_fallback_message = "TotalCostFallbackMessage" + + +class TariffCostCtrlrInstanceName(str, Enum): + """ + Instance names where the component type is TariffCostCtrlr + """ + + tariff = "Tariff" + cost = "Cost" + + +class TxCtrlrVariableName(str, Enum): + """ + Instance names where the component type is TxCtrlr + See ControllerComponentName for referenced logical component + """ + + charging_time = "ChargingTime" + ev_connection_time_out = "EVConnectionTimeOut" + max_energy_on_invalid_id = "MaxEnergyOnInvalidId" + stop_tx_on_ev_side_disconnect = "StopTxOnEVSideDisconnect" + stop_tx_on_invalid_id = "StopTxOnInvalidId" + tx_before_accepted_enabled = "TxBeforeAcceptedEnabled" + tx_start_point = "TxStartPoint" + tx_stop_point = "TxStopPoint" + + +class AccessBarrierVariableName(str, Enum): + """ + Variable names where the component type is AccessBarrier + See PhysicalComponentName for referenced physical component + """ + + enabled = "Enabled" + active = "Active" + problem = "Problem" + + +class AcDcConverterVariableName(str, Enum): + """ + Variable names where the component type is AcDcConverter + See PhysicalComponentName for referenced physical component + """ + + dc_current = "DCCurrent" + dc_voltage = "DCVoltage" + enabled = "Enabled" + fan_speed = "FanSpeed" + overload = "Overload" + power = "Power" + problem = "Problem" + temperature = "Temperature" + tripped = "Tripped" + + +class AcPhaseSelectorVariableName(str, Enum): + """ + Variable names where the component type is AcPhaseSelector + See PhysicalComponentName for referenced physical component + """ + + active = "Active" + enabled = "Enabled" + phase_rotation = "PhaseRotation" + problem = "Problem" + + +class ActuatorVariableName(str, Enum): + """ + Variable names where the component type is Actuator + See PhysicalComponentName for referenced physical component + """ + + active = "Active" + enabled = "Enabled" + problem = "Problem" + state = "State" + + +class AirCoolingSystemVariableName(str, Enum): + """ + Variable names where the component type is AirCoolingSystem + See PhysicalComponentName for referenced physical component + """ + + active = "Active" + enabled = "Enabled" + problem = "Problem" + fan_speed = "FanSpeed" + + +class AreaVentilationVariableName(str, Enum): + """ + Variable names where the component type is AreaVentilation + See PhysicalComponentName for referenced physical component + """ + + active = "Active" + enabled = "Enabled" + problem = "Problem" + fan_speed = "FanSpeed" + + +class BayOccupancySensorVariableName(str, Enum): + """ + Variable names where the component type is BayOccupancySensor + See PhysicalComponentName for referenced physical component + """ + + active = "Active" + enabled = "Enabled" + percent = "Percent" + + +class BeaconLightingVariableName(str, Enum): + """ + Variable names where the component type is BeaconLighting + See PhysicalComponentName for referenced physical component + """ + + active = "Active" + color = "Color" + enabled = "Enabled" + enabled_set = "Enabled(Set)" + percent = "Percent" + percent_set = "Percent(Set)" + power = "Power" + problem = "Problem" + + +class CableBreakawaySensorVariableName(str, Enum): + """ + Variable names where the component type is CableBreakawaySensor + See PhysicalComponentName for referenced physical component + """ + + active = "Active" + enabled = "Enabled" + tripped = "Tripped" + + +class CaseAccessSensorVariableName(str, Enum): + """ + Variable names where the component type is CaseAccessSensor + See PhysicalComponentName for referenced physical component + """ + + active = "Active" + enabled = "Enabled" + enabled_set = "Enabled(Set)" + problem = "Problem" + tripped = "Tripped" + + +class ChargingStationVariableName(str, Enum): + """ + Variable names where the component type is ChargingStation + See PhysicalComponentName for referenced physical component + """ + + ac_current = "ACCurrent" + ac_voltage = "ACVoltage" + ac_voltage_max_limit = "ACVoltage(MaxLimit)" + allow_new_sessions_pending_firmware_update = "AllowNewSessionsPendingFirmwareUpdate" + available = "Available" + availability_state = "AvailabilityState" + charge_protocol = "ChargeProtocol" + current_imbalance = "CurrentImbalance" + ec_variant = "ECVariant" + enabled = "Enabled" + identity = "Identity" + model = "Model" + operating_times = "OperatingTimes" + overload = "Overload" + phase_rotation = "PhaseRotation" + power = "Power" + power_max_limit = "Power(MaxLimit)" + problem = "Problem" + serial_number = "SerialNumber" + supply_phases = "SupplyPhases" + supply_phases_max_limit = "SupplyPhases(MaxLimit)" + tripped = "Tripped" + vendor_name = "VendorName" + voltage_imbalance = "VoltageImbalance" + + +class ChargingStatusIndicatorVariableName(str, Enum): + """ + Variable names where the component type is ChargingStatusIndicator + See PhysicalComponentName for referenced physical component + """ + + active = "Active" + color = "Color" + + +class ConnectedEVVariableName(str, Enum): + """ + Variable names where the component type is ConnectedEV + See PhysicalComponentName for referenced physical component + """ + + protocol_agreed = "ProtocolAgreed" + protocol_supported_by_ev = "ProtocolSupportedByEV" + vehicle_id = "VehicleId" + # Voltage and current values + ac_current = "ACCurrent" + ac_voltage = "ACVoltage" + dc_current = "DCCurrent" + dc_voltage = "DCVoltage" + # Power, energy and time values + power = "Power" + energy_import = "EnergyImport" + departure_time = "DepartureTime" + energy_capacity = "EnergyCapacity" + remaining_time_bulk = "RemainingTimeBulk" + remaining_time_full = "RemainingTimeFull" + state_of_charge = "StateOfCharge" + state_of_charge_bulk = "StateOfChargeBulk" + charging_complete_bulk = "ChargingCompleteBulk" + charging_complete_full = "ChargingCompleteFull" + + +class ChargingStateVariableName(str, Enum): + """ + Variable names where the component type is ChargingState + """ + + # Status values - ChargingState + battery_overvoltage = "BatteryOvervoltage" + battery_undervoltage = "BatteryUndervoltage" + charging_current_deviation = "ChargingCurrentDeviation" + battery_temperature = "BatteryTemperature" + voltage_deviation = "VoltageDeviation" + charging_system_error = "ChargingSystemError" + vehicle_shift_position = "VehicleShiftPosition" + vehicle_charging_enabled = "VehicleChargingEnabled" + charging_system_incompatibility = "ChargingSystemIncompatibility" + charger_connector_lock_fault = "ChargerConnectorLockFault" + + +class ConnectorVariableName(str, Enum): + """ + Variable names where the component type is Connector + See PhysicalComponentName for referenced physical component + """ + + availability_state = "AvailabilityState" + available = "Available" + charge_protocol = "ChargeProtocol" + connector_type = "ConnectorType" + enabled = "Enabled" + phase_rotation = "PhaseRotation" + problem = "Problem" + supply_phases = "SupplyPhases" + supply_phases_max_limit = "SupplyPhases(MaxLimit)" + tripped = "Tripped" + + +class ConnectorHolsterReleaseVariableName(str, Enum): + """ + Variable names where the component type is ConnectorHolsterRelease + See PhysicalComponentName for referenced physical component + """ + + enabled = "Enabled" + active = "Active" + problem = "Problem" + state = "State" + + +class ConnectorHolsterSensorVariableName(str, Enum): + """ + Variable names where the component type is ConnectorHolsterSensor + See PhysicalComponentName for referenced physical component + """ + + enabled = "Enabled" + active = "Active" + problem = "Problem" + + +class ConnectorPlugRetentionLockVariableName(str, Enum): + """ + Variable names where the component type is ConnectorPlugRetentionLock + See PhysicalComponentName for referenced physical component + """ + + enabled = "Enabled" + active = "Active" + problem = "Problem" + tripped = "Tripped" + tries = "Tries" + tries_set_limit = "Tries(SetLimit)" + tries_max_limit = "Tries(MaxLimit)" + + +class ConnectorProtectionReleaseVariableName(str, Enum): + """ + Variable names where the component type is ConnectorProtectionRelease + See PhysicalComponentName for referenced physical component + """ + + enabled = "Enabled" + active = "Active" + problem = "Problem" + tripped = "Tripped" + + +class ControllerVariableName(str, Enum): + """ + Variable names where the component type is Controller + See PhysicalComponentName for referenced physical component + """ + + active = "Active" + ec_variant = "ECVariant" + firmware_version = "FirmwareVersion" + interval_heartbeat = "Interval[Heartbeat]" + manufacturer = "Manufacturer" + max_msg_elements = "MaxMsgElements" + model = "Model" + problem = "Problem" + selftest_active = "SelftestActive" + selftest_active_set = "SelftestActive(Set)" + serial_number = "SerialNumber" + version_date = "VersionDate" + version_number = "VersionNumber" + + +class ControlMeteringVariableName(str, Enum): + """ + Variable names where the component type is ControlMetering + See PhysicalComponentName for referenced physical component + """ + + power = "Power" + ac_current = "ACCurrent" + dc_current = "DCCurrent" + dc_voltage = "DCVoltage" + + +class CPPWMControllerVariableName(str, Enum): + """ + Variable names where the component type is CPPWMController + See PhysicalComponentName for referenced physical component + """ + + active = "Active" + dc_voltage = "DCVoltage" + enabled = "Enabled" + percentage = "Percentage" + problem = "Problem" + selftest_active = "SelftestActive" + selftest_active_set = "SelftestActive(Set)" + state = "State" + + +class DataLinkVariableName(str, Enum): + """ + Variable names where the component type is DataLink + See PhysicalComponentName for referenced physical component + """ + + active = "Active" + complete = "Complete" + enabled = "Enabled" + fallback = "Fallback" + iccid = "ICCID" + imsi = "IMSI" + network_address = "NetworkAddress" + problem = "Problem" + signal_strength = "SignalStrength" + + +class DisplayVariableName(str, Enum): + """ + Variable names where the component type is Display + See PhysicalComponentName for referenced physical component + """ + + color = "Color" + count_height_in_chars = "Count[HeightInChars]" + count_width_in_chars = "Count[WidthInChars]" + data_text_visible = "DataText[Visible]" + enabled = "Enabled" + problem = "Problem" + state = "State" + + +class DistributionPanelVariableName(str, Enum): + """ + Variable names where the component type is DistributionPanel + See PhysicalComponentName for referenced physical component + """ + + charging_station = "ChargingStation" + distribution_panel = "DistributionPanel" + fuse = "Fuse" + instance_name = "InstanceName" + + +class ElectricalFeedVariableName(str, Enum): + """ + Variable names where the component type is ElectricalFeed + See PhysicalComponentName for referenced physical component + """ + + ac_voltage = "ACVoltage" + active = "Active" + dc_voltage = "DCVoltage" + enabled = "Enabled" + energy = "Energy" + phase_rotation = "PhaseRotation" + power = "Power" + power_type = "PowerType" + problem = "Problem" + supply_phases = "SupplyPhases" + + +class ELVSupplyVariableName(str, Enum): + """ + Variable names where the component type is ELVSupply + See PhysicalComponentName for referenced physical component + """ + + energy_import_register = "EnergyImportRegister" + fallback = "Fallback" + fallback_max_limit = "Fallback(MaxLimit)" + power = "Power" + power_max_limit = "Power(MaxLimit)" + state_of_charge = "StateOfCharge" + time = "Time" + + +class EmergencyStopSensorVariableName(str, Enum): + """ + Variable names where the component type is EmergencyStopSensor + See PhysicalComponentName for referenced physical component + """ + + enabled = "Enabled" + active = "Active" + tripped = "Tripped" + + +class EnvironmentalLightingVariableName(str, Enum): + """ + Variable names where the component type is EnvironmentalLighting + See PhysicalComponentName for referenced physical component + """ + + active = "Active" + color = "Color" + enabled = "Enabled" + enabled_set = "Enabled(Set)" + percent = "Percent" + percent_set = "Percent(Set)" + power = "Power" + problem = "Problem" + + +class EVRetentionLockVariableName(str, Enum): + """ + Variable names where the component type is EVRetentionLock + See PhysicalComponentName for referenced physical component + """ + + active = "Active" + complete = "Complete" + enabled = "Enabled" + problem = "Problem" + + +class EVSEVariableName(str, Enum): + """ + Variable names where the component type is EVSE + See PhysicalComponentName for referenced physical component + """ + + ac_current = "ACCurrent" + ac_voltage = "ACVoltage" + available = "Available" + availability_state = "AvailabilityState" + allow_reset = "AllowReset" + charge_protocol = "ChargeProtocol" + charging_time = "ChargingTime" + count_charging_profiles_max_limit = "Count[ChargingProfiles](MaxLimit)" + count_charging_profiles = "Count[ChargingProfiles]" + current_imbalance = "CurrentImbalance" + dc_current = "DCCurrent" + dc_voltage = "DCVoltage" + enabled = "Enabled" + evse_id = "EvseId" + iso15118_evse_id = "ISO15118EvseId" + overload = "Overload" + phase_rotation = "PhaseRotation" + post_charging_time = "PostChargingTime" + power = "Power" + problem = "Problem" + supply_phases = "SupplyPhases" + tripped = "Tripped" + voltage_imbalance = "VoltageImbalance" + + +class ExternalTemperatureSensorVariableName(str, Enum): + """ + Variable names where the component type is ExternalTemperatureSensor + See PhysicalComponentName for referenced physical component + """ + + active = "Active" + problem = "Problem" + temperature = "Temperature" + + +class FiscalMeteringVariableName(str, Enum): + """ + Variable names where the component type is FiscalMetering + See PhysicalComponentName for referenced physical component + """ + + problem = "Problem" + certificate = "Certificate" + ec_variant = "ECVariant" + energy_export = "EnergyExport" + energy_export_register = "EnergyExportRegister" + energy_import = "EnergyImport" + energy_import_register = "EnergyImportRegister" + manufacturer_ct = "Manufacturer[CT]" + manufacturer_meter = "Manufacturer[Meter]" + model_ct = "Model[CT]" + model_meter = "Model[Meter]" + options_set_meter_value_aligned_data = "OptionsSet[MeterValueAlignedData]" + options_set_txn_stopped_aligned_data = "OptionsSet[TxnStoppedAlignedData]" + serial_number_ct = "SerialNumber[CT]" + serial_number_meter = "SerialNumber[Meter]" + + +class FloodSensorVariableName(str, Enum): + """ + Variable names where the component type is FloodSensor + See PhysicalComponentName for referenced physical component + """ + + active = "Active" + enabled = "Enabled" + height = "Height" + percent = "Percent" + tripped = "Tripped" + + +class GroundIsolationProtectionVariableName(str, Enum): + """ + Variable names where the component type is GroundIsolationProtection + See PhysicalComponentName for referenced physical component + """ + + active = "Active" + complete = "Complete" + enabled = "Enabled" + impedance = "Impedance" + problem = "Problem" + + +class HeaterVariableName(str, Enum): + """ + Variable names where the component type is Heater + See PhysicalComponentName for referenced physical component + """ + + active = "Active" + enabled = "Enabled" + problem = "Problem" + tripped = "Tripped" + power = "Power" + power_max_limit = "Power(MaxLimit)" + power_max_set = "Power(MaxSet)" + temperature_min_set = "Temperature(MinSet)" + temperature_max_set = "Temperature(MaxSet)" + + +class HumiditySensorVariableName(str, Enum): + """ + Variable names where the component type is HumiditySensor + See PhysicalComponentName for referenced physical component + """ + + enabled = "Enabled" + humidity = "Humidity" + problem = "Problem" + + +class LightSensorVariableName(str, Enum): + """ + Variable names where the component type is LightSensor + See PhysicalComponentName for referenced physical component + """ + + enabled = "Enabled" + light = "Light" + problem = "Problem" + + +class LiquidCoolingSystemVariableName(str, Enum): + """ + Variable names where the component type is LiquidCoolingSystem + See PhysicalComponentName for referenced physical component + """ + + active = "Active" + enabled = "Enabled" + problem = "Problem" + temperature = "Temperature" + + +class LocalAvailabilitySensorVariableName(str, Enum): + """ + Variable names where the component type is LocalAvailabilitySensor + See PhysicalComponentName for referenced physical component + """ + + active = "Active" + enabled = "Enabled" + problem = "Problem" + + +class LocalControllerVariableName(str, Enum): + """ + Variable names where the component type is LocalController + See PhysicalComponentName for referenced physical component + """ + + charging_station = "ChargingStation" + distribution_panel = "DistributionPanel" + ec_variant = "ECVariant" + enabled = "Enabled" + identity = "Identity" + manufacturer = "Manufacturer" + model = "Model" + problem = "Problem" + serial_number = "SerialNumber" + tripped = "Tripped" + + +class LocalEnergyStorageVariableName(str, Enum): + """ + Variable names where the component type is LocalEnergyStorage + See PhysicalComponentName for referenced physical component + """ + + capacity = "Capacity" + energy_capacity = "EnergyCapacity" + identity = "Identity" + + +class OverCurrentProtectionVariableName(str, Enum): + """ + Variable names where the component type is OverCurrentProtection + See PhysicalComponentName for referenced physical component + """ + + ac_current = "ACCurrent" + active = "Active" + operated = "Operated" + + +class OverCurrentProtectionRecloserVariableName(str, Enum): + """ + Variable names where the component type is OverCurrentProtectionRecloser + See PhysicalComponentName for referenced physical component + """ + + active = "Active" + active_set = "Active(Set)" + enabled = "Enabled" + complete = "Complete" + problem = "Problem" + mode = "Mode" + tries = "Tries" + tries_set_limit = "Tries(SetLimit)" + tries_max_limit = "Tries(MaxLimit)" + + +class PowerContactorVariableName(str, Enum): + """ + Variable names where the component type is PowerContactor + See PhysicalComponentName for referenced physical component + """ + + active = "Active" + problem = "Problem" + tripped = "Tripped" + + +class RCDVariableName(str, Enum): + """ + Variable names where the component type is RCD + See PhysicalComponentName for referenced physical component + """ + + operated = "Operated" + tripped = "Tripped" + + +class RCDRecloserVariableName(str, Enum): + """ + Variable names where the component type is RCDRecloser + See PhysicalComponentName for referenced physical component + """ + + active = "Active" + active_set = "Active(Set)" + complete = "Complete" + enabled = "Enabled" + problem = "Problem" + tries = "Tries" + tries_max_limit = "Tries(MaxLimit)" + tries_set_limit = "Tries(SetLimit)" + + +class RealTimeClockVariableName(str, Enum): + """ + Variable names where the component type is RealTimeClock + See PhysicalComponentName for referenced physical component + """ + + active = "Active" + dc_voltage = "DCVoltage" + fallback = "Fallback" + fallback_max_limit = "Fallback(MaxLimit)" + problem = "Problem" + + +class ShockSensorVariableName(str, Enum): + """ + Variable names where the component type is ShockSensor + See PhysicalComponentName for referenced physical component + """ + + active = "Active" + enabled = "Enabled" + force = "Force" + + +class SpacesCountSignageVariableName(str, Enum): + """ + Variable names where the component type is SpacesCountSignage + See PhysicalComponentName for referenced physical component + """ + + active = "Active" + count = "Count" + enabled = "Enabled" + + +class SwitchVariableName(str, Enum): + """ + Variable names where the component type is Switch + See PhysicalComponentName for referenced physical component + """ + + active = "Active" + enabled = "Enabled" + state = "State" + + +class TemperatureSensorVariableName(str, Enum): + """ + Variable names where the component type is TemperatureSensor + See PhysicalComponentName for referenced physical component + """ + + active = "Active" + problem = "Problem" + temperature = "Temperature" + + +class TiltSensorVariableName(str, Enum): + """ + Variable names where the component type is TiltSensor + See PhysicalComponentName for referenced physical component + """ + + active = "Active" + enabled = "Enabled" + angle = "Angle" + + +class TokenReaderVariableName(str, Enum): + """ + Variable names where the component type is TokenReader + See PhysicalComponentName for referenced physical component + """ + + enabled = "Enabled" + enabled_set = "Enabled(Set)" + operated = "Operated" + problem = "Problem" + token = "Token" + token_type = "TokenType" + + +class UIInputVariableName(str, Enum): + """ + Variable names where the component type is UIInput + See PhysicalComponentName for referenced physical component + """ + + active = "Active" + enabled = "Enabled" + operated = "Operated" + + +class UpstreamProtectionTriggerVariableName(str, Enum): + """ + Variable names where the component type is UpstreamProtectionTrigger + See PhysicalComponentName for referenced physical component + """ + + active_set = "Active(Set)" + enabled = "Enabled" + problem = "Problem" + tripped = "Tripped" + + +class VehicleIdSensorVariableName(str, Enum): + """ + Variable names where the component type is VehicleIdSensor + See PhysicalComponentName for referenced physical component + """ + + active = "Active" + enabled = "Enabled" diff --git a/pyproject.toml b/pyproject.toml index ef8db3c42..fa17c9d27 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "ocpp" -version = "0.21.0" +version = "0.25.0" description = "Python package implementing the JSON version of the Open Charge Point Protocol (OCPP)." authors = [ "André Duarte ", diff --git a/tests/test_charge_point.py b/tests/test_charge_point.py index de505baad..e6b320ef0 100644 --- a/tests/test_charge_point.py +++ b/tests/test_charge_point.py @@ -65,6 +65,8 @@ def test_camel_to_snake_case(test_input, expected): [ ({"transaction_id": "74563478"}, {"transactionId": "74563478"}), ({"full_soc": 100}, {"fullSoC": 100}), + ({"ev_min_v2x_energy_request": 200}, {"evMinV2XEnergyRequest": 200}), + ({"v2x_charging_ctrlr": 200}, {"v2xChargingCtrlr": 200}), ], ) def test_snake_to_camel_case(test_input, expected): diff --git a/tests/v16/conftest.py b/tests/v16/conftest.py index d747bf420..a8dfc365f 100644 --- a/tests/v16/conftest.py +++ b/tests/v16/conftest.py @@ -17,6 +17,11 @@ def heartbeat_call(): return Call(unique_id=1, action=Action.Heartbeat, payload={}).to_json() +@pytest.fixture +def not_supported_call(): + return Call(unique_id=1, action="InvalidAction", payload={}).to_json() + + @pytest.fixture def boot_notification_call(): return Call( diff --git a/tests/v16/test_v16_charge_point.py b/tests/v16/test_v16_charge_point.py index 5471e1618..9d07acf23 100644 --- a/tests/v16/test_v16_charge_point.py +++ b/tests/v16/test_v16_charge_point.py @@ -108,6 +108,43 @@ def on_boot_notification(**kwargs): # noqa ) +@pytest.mark.asyncio +async def test_route_message_not_supported(base_central_system, not_supported_call): + """ + Test that a CALLERROR is sent back, reporting that it is + not supported by OCPP version. + + """ + + @on(Action.BootNotification) + 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(not_supported_call) + base_central_system._connection.send.assert_called_once_with( + json.dumps( + [ + 4, + 1, + "NotSupported", + "Requested Action is not known by receiver", + {"cause": "InvalidAction not supported by OCPP1.6."}, + ], + separators=(",", ":"), + ) + ) + + @pytest.mark.asyncio async def test_route_message_with_no_route(base_central_system, heartbeat_call): """ @@ -124,7 +161,7 @@ async def test_route_message_with_no_route(base_central_system, heartbeat_call): [ 4, 1, - "NotSupported", + "NotImplemented", "Request Action is recognized but not supported by the receiver", {"cause": "No handler for Heartbeat registered."}, ], diff --git a/tests/v20/test_v20_charge_point.py b/tests/v20/test_v20_charge_point.py index 9226b8ba4..bb0a04aa2 100644 --- a/tests/v20/test_v20_charge_point.py +++ b/tests/v20/test_v20_charge_point.py @@ -76,7 +76,7 @@ async def test_route_message_with_no_route(base_central_system, heartbeat_call): [ 4, 1, - "NotSupported", + "NotImplemented", "Request Action is recognized but not supported by the receiver", {"cause": "No handler for Heartbeat registered."}, ], diff --git a/tests/v201/test_v201_charge_point.py b/tests/v201/test_v201_charge_point.py index 8624c90ca..ddbd33808 100644 --- a/tests/v201/test_v201_charge_point.py +++ b/tests/v201/test_v201_charge_point.py @@ -76,7 +76,7 @@ async def test_route_message_with_no_route(base_central_system, heartbeat_call): [ 4, 1, - "NotSupported", + "NotImplemented", "Request Action is recognized but not supported by the receiver", {"cause": "No handler for Heartbeat registered."}, ],