Skip to content

Commit

Permalink
Start supporting component config instead of config.json for ocpp 2.0…
Browse files Browse the repository at this point in the history
….1 tests

Signed-off-by: Maaike Zijderveld, iolar <[email protected]>
  • Loading branch information
maaikez committed Aug 9, 2024
1 parent 8abca89 commit 2081fb5
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ class EverestTestEnvironmentSetup:
class _EverestEnvironmentTemporaryPaths:
""" Paths of the temporary configuration files / data """
certs_dir: Path # used by both OCPP and evse security
ocpp_config_path: Path
ocpp_config_file: Path
ocpp_user_config_file: Path
ocpp_database_dir: Path
Expand Down Expand Up @@ -142,6 +143,9 @@ def everest_core(self) -> EverestCore:
def _create_temporary_directory_structure(self, tmp_path: Path) -> _EverestEnvironmentTemporaryPaths:
ocpp_config_dir = tmp_path / "ocpp_config"
ocpp_config_dir.mkdir(exist_ok=True)
if self._ocpp_config.ocpp_version == OCPPVersion.ocpp201:
component_config_path = ocpp_config_dir / "component_config"
component_config_path.mkdir(exist_ok=True)
certs_dir = tmp_path / "certs"
certs_dir.mkdir(exist_ok=True)
ocpp_logs_dir = ocpp_config_dir / "logs"
Expand All @@ -153,6 +157,7 @@ def _create_temporary_directory_structure(self, tmp_path: Path) -> _EverestEnvir
logging.info(f"temp ocpp config files directory: {ocpp_config_dir}")

return self._EverestEnvironmentTemporaryPaths(
ocpp_config_path=ocpp_config_dir / "component_config",
ocpp_config_file=ocpp_config_dir / "config.json",
ocpp_user_config_file=ocpp_config_dir / "user_config.json",
ocpp_database_dir=ocpp_config_dir,
Expand All @@ -173,6 +178,7 @@ def _create_ocpp_module_configuration_strategy(self,
)
elif self._ocpp_config.ocpp_version == OCPPVersion.ocpp201:
ocpp_paths = OCPPModulePaths201(
ChargePointConfigPath=str(temporary_paths.ocpp_config_path),
MessageLogPath=str(temporary_paths.ocpp_message_log_directory),
CoreDatabasePath=str(temporary_paths.ocpp_database_dir),
DeviceModelDatabasePath=str(temporary_paths.ocpp_database_dir / "device_model_storage.db"),
Expand All @@ -199,12 +205,13 @@ def _setup_libocpp_configuration(self, temporary_paths: _EverestEnvironmentTempo
if self._ocpp_config.device_model_component_config_path \
else self._ocpp_config.libocpp_path / 'config/v201/component_config'


liboccp_configuration_helper.generate_ocpp_config(
central_system_port=self._ocpp_config.central_system_port,
central_system_host=self._ocpp_config.central_system_host,
source_ocpp_config_file=source_ocpp_config,
target_ocpp_config_file=temporary_paths.ocpp_config_file,
source_ocpp_config_path=source_ocpp_config,
target_ocpp_config_path=temporary_paths.ocpp_config_file \
if self._ocpp_config.ocpp_version == OCPPVersion.ocpp16 \
else temporary_paths.ocpp_config_path,
target_ocpp_user_config_file=temporary_paths.ocpp_user_config_file,
configuration_strategies=self._ocpp_config.configuration_strategies
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from __future__ import annotations

import os
from glob import glob
import json
import sys
from abc import ABC, abstractmethod
Expand Down Expand Up @@ -34,30 +36,40 @@ class LibOCPPConfigurationHelperBase(ABC):
""" Helper for parsing / adapting the LibOCPP configuration and dumping it a database file. """

def generate_ocpp_config(self,
target_ocpp_config_file: Path,
target_ocpp_config_path: Path,
target_ocpp_user_config_file: Path,
source_ocpp_config_file: Path,
source_ocpp_config_path: Path,
central_system_host: str,
central_system_port: Union[str, int],
configuration_strategies: list[OCPPConfigAdjustmentStrategy] | None = None):
config = json.loads(source_ocpp_config_file.read_text())
config = self._get_config(source_ocpp_config_path)

configuration_strategies = configuration_strategies if configuration_strategies else []

for v in [self._get_default_strategy(central_system_port, central_system_host)] + configuration_strategies:
config = v.adjust_ocpp_configuration(config)

with target_ocpp_config_file.open("w") as f:
json.dump(config, f)
self._store_config(self, target_ocpp_config_path)
target_ocpp_user_config_file.write_text("{}")

@abstractmethod
def _get_config(self, source_ocpp_config_path: Path):
pass

@abstractmethod
def _get_default_strategy(self, central_system_port: int | str,
central_system_host: str) -> OCPPConfigAdjustmentStrategy:
pass

@abstractmethod
def _store_config(self, config, target_ocpp_config_file):
pass


class LibOCPP16ConfigurationHelper(LibOCPPConfigurationHelperBase):
def _get_config(self, source_ocpp_config_path: Path):
return json.loads(source_ocpp_config_path.read_text())

def _get_default_strategy(self, central_system_port, central_system_host):
def adjust_ocpp_configuration(config: dict) -> dict:
config = deepcopy(config)
Expand All @@ -68,6 +80,10 @@ def adjust_ocpp_configuration(config: dict) -> dict:

return OCPPConfigAdjustmentStrategyWrapper(adjust_ocpp_configuration)

def _store_config(self, config, target_ocpp_config_file):
with target_ocpp_config_file.open("w") as f:
json.dump(config, f)


class _OCPP201NetworkConnectionProfileAdjustment(OCPPConfigAdjustmentStrategy):
""" Adjusts the OCPP 2.0.1 Network Connection Profile by injecting the right host, port and chargepoint id.
Expand Down Expand Up @@ -96,23 +112,49 @@ def adjust_ocpp_configuration(self, config: dict):
@staticmethod
def _get_value_from_v201_config(ocpp_config: json, component_name: str, variable_name: str,
variable_attribute_type: str):
for component in ocpp_config:
if (component["name"] == component_name):
return component["variables"][variable_name]["attributes"][variable_attribute_type]
for (component, schema) in ocpp_config:
if component == component_name:
attributes = schema["properties"][variable_name]["attributes"]
for attribute in attributes:
if attribute["type"] == variable_attribute_type:
return attribute["value"]

@staticmethod
def _set_value_in_v201_config(ocpp_config: json, component_name: str, variable_name: str,
variable_attribute_type: str,
value: str):
for component in ocpp_config:
if (component["name"] == component_name):
component["variables"][variable_name]["attributes"][variable_attribute_type] = value
return
for (component, schema) in ocpp_config:
if component == component_name:
attributes = schema["properties"][variable_name]["attributes"]
for attribute in attributes:
if attribute["type"] == variable_attribute_type:
attribute["value"] = value


class LibOCPP201ConfigurationHelper(LibOCPPConfigurationHelperBase):

def _get_config(self, source_ocpp_config_path: Path):
config = {}
file_list_standardized = glob(source_ocpp_config_path / "standardized/*.json")
file_list_custom = glob(source_ocpp_config_path / "custom/*.json")
file_list = file_list_standardized + file_list_custom
for file in file_list:
# Get component from file name
head, tail = os.path.split(file)
component_name, extension = os.path.splitext(tail)
# Store json in dict
with open(file) as f:
config[component_name] = json.load(f)
return config

def _get_default_strategy(self, central_system_port: int | str,
central_system_host: str) -> OCPPConfigAdjustmentStrategy:
return _OCPP201NetworkConnectionProfileAdjustment(central_system_port, central_system_host)

def _store_config(self, config, target_ocpp_config_path):
# Just store all in the 'standardized' folder
path = target_ocpp_config_path / "standardized"
for key, value in config.items():
file_name = path / key + '.json'
with file_name.open("w") as f:
json.dump(value, f)

0 comments on commit 2081fb5

Please sign in to comment.