Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@ urllib3~=2.4.0

# binary butterfly shared libraries (https://git.binary-butterfly.de/public_libraries)
--extra-index-url https://git.binary-butterfly.de/api/v4/groups/262/-/packages/pypi/simple
flask-openapi~=2.1.3
validataclass-search-queries~=0.5.0
butterfly_pubsub~=2.0.0
flask-openapi~=2.1.4
validataclass-search-queries~=0.5.1
butterfly_pubsub~=2.1.1
2 changes: 0 additions & 2 deletions webapp/cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

from .bnetza_cli import bnetza_cli
from .chargeit_cli import chargeit_cli
from .giroe_cli import giroe_cli
from .import_cli import import_cli
from .match_cli import match_cli
from .source_cli import source_cli
Expand All @@ -31,7 +30,6 @@
def register_cli_to_app(app: Flask):
app.cli.add_command(bnetza_cli)
app.cli.add_command(chargeit_cli)
app.cli.add_command(giroe_cli)
app.cli.add_command(match_cli)
app.cli.add_command(import_cli)
app.cli.add_command(stadtnavi_cli)
Expand Down
110 changes: 0 additions & 110 deletions webapp/cli/giroe_cli.py

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,5 @@ def realtime_import_task(source: str):
def image_import_task():
from webapp.dependencies import dependencies

image_import_services: ImageImportService = dependencies.get_image_import_services()
image_import_services: ImageImportService = dependencies.get_image_import_service()
image_import_services.fetch_images()
1 change: 1 addition & 0 deletions webapp/services/import_services/giroe/giroe_mapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ def map_location_input_to_update(self, location_data: LocationInput) -> Location
def map_station_connector_to_evse_connector(self, station_input: StationInput, connector_input: ConnectorInput):
return EvseUpdate(
uid=connector_input.uid,
evse_id=connector_input.uid,
status=self.map_charge_connector_status_to_evse_status(connector_input.status),
capabilities=[
Capability.UNLOCK_CAPABLE,
Expand Down
113 changes: 89 additions & 24 deletions webapp/services/import_services/giroe/giroe_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,25 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""

from datetime import datetime
from typing import List, Optional
from datetime import datetime, timezone

from validataclass.exceptions import ValidationError
from validataclass.validators import DataclassValidator

from webapp.common.remote_helper import RemoteException, RemoteServerType
from webapp.models.source import SourceStatus
from webapp.services.import_services.base_import_service import BaseImportService, SourceInfo
from webapp.services.import_services.models import LocationUpdate
from webapp.services.import_services.models import EvseUpdate, LocationUpdate

from .giroe_mapper import GiroeMapper
from .giroe_validator import LocationInput, LocationListInput
from .giroe_validator import ConnectorInput, ItemListInput, LocationInput


class GiroeImportService(BaseImportService):
giroe_mapper: GiroeMapper
location_list_validator = DataclassValidator(LocationListInput)
item_list_validator = DataclassValidator(ItemListInput)
location_validator = DataclassValidator(LocationInput)
connector_validator = DataclassValidator(ConnectorInput)

source_info = SourceInfo(
uid='giroe',
Expand All @@ -47,44 +47,36 @@ def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.giroe_mapper = GiroeMapper(config_helper=self.config_helper)

def download_and_save(
self,
created_since: Optional[datetime] = None,
created_until: Optional[datetime] = None,
modified_since: Optional[datetime] = None,
modified_until: Optional[datetime] = None,
):
def fetch_static_data(self):
source = self.get_source()
location_updates: List[LocationUpdate] = []
location_updates: list[LocationUpdate] = []
static_error_count = 0
static_data_updated_at = datetime.now(timezone.utc)

try:
location_list_data = self.remote_helper.get(
remote_server_type=RemoteServerType.GIROE,
path='/api/server/v1/charge-locations',
params={
'technical_backend': 'tcc',
**({} if created_since is None else {'created_since': created_since}),
**({} if created_until is None else {'created_until': created_until}),
**({} if modified_since is None else {'modified_since': modified_since}),
**({} if modified_until is None else {'modified_until': modified_until}),
'public': True,
},
)
location_list_input: LocationListInput = self.location_list_validator.validate(location_list_data)
location_list_input: ItemListInput = self.item_list_validator.validate(location_list_data)
except (ValidationError, RemoteException) as e:
self.logger.info('import-giro-e', f'giro-e static data has error: {e.to_dict()}')
self.update_source(source, static_status=SourceStatus.FAILED)
return

location_dicts: List[dict] = location_list_input.items
location_dicts: list[dict] = location_list_input.items

while location_list_input.next_path:
try:
location_list_data = self.remote_helper.get(
remote_server_type=RemoteServerType.GIROE,
path=location_list_input.next_path,
)
location_list_input: LocationListInput = self.location_list_validator.validate(location_list_data)
location_list_input: ItemListInput = self.item_list_validator.validate(location_list_data)
location_dicts += location_list_input.items
except (ValidationError, RemoteException) as e:
self.logger.info('import-giro-e', f'giro-e static data has error: {e.to_dict()}')
Expand All @@ -102,11 +94,84 @@ def download_and_save(
static_error_count += 1
continue

if not location_input.public:
continue

location_updates.append(self.giroe_mapper.map_location_input_to_update(location_input))

self.save_location_updates(location_updates)

self.update_source(source=source, static_error_count=static_error_count)
self.update_source(
source=source,
static_status=SourceStatus.ACTIVE,
static_error_count=static_error_count,
static_data_updated_at=static_data_updated_at,
)

def fetch_realtime_data(self):
source = self.get_source()
# Don't fetch realtime updates if there is no static data
if source.static_status != SourceStatus.ACTIVE:
return

evse_updates: list[EvseUpdate] = []
realtime_error_count = 0
realtime_data_updated_at = datetime.now(timezone.utc)

params = {
'technical_backend': 'tcc',
'public': True,
}
if source.realtime_data_updated_at:
params['modified_since'] = source.realtime_data_updated_at.isoformat()
try:
connector_list_data = self.remote_helper.get(
remote_server_type=RemoteServerType.GIROE,
path='/api/server/v1/charge-connectors',
params=params,
)
connector_list_input: ItemListInput = self.item_list_validator.validate(connector_list_data)
except (ValidationError, RemoteException) as e:
self.logger.info('import-giro-e', f'giro-e realtime data has error: {e.to_dict()}')
self.update_source(source, realtime_status=SourceStatus.FAILED)
return

connector_dicts: list[dict] = connector_list_input.items

while connector_list_input.next_path:
try:
connector_list_data = self.remote_helper.get(
remote_server_type=RemoteServerType.GIROE,
path=connector_list_input.next_path,
)
connector_list_input: ItemListInput = self.item_list_validator.validate(connector_list_data)
connector_dicts += connector_list_input.items
except (ValidationError, RemoteException) as e:
self.logger.info('import-giro-e', f'giro-e realtime data has error: {e.to_dict()}')
self.update_source(source, realtime_status=SourceStatus.FAILED)
return

for connector_dict in connector_dicts:
try:
connector_input: ConnectorInput = self.connector_validator.validate(connector_dict)
except ValidationError as e:
self.logger.info(
'import-giro-e',
f'connector {connector_dict} has validation error: {e.to_dict()}',
)
realtime_error_count += 1
continue

evse_updates.append(
EvseUpdate(
uid=connector_input.uid,
evse_id=connector_input.uid,
last_updated=connector_input.modified,
),
)

self.save_evse_updates(evse_updates)

self.update_source(
source=source,
realtime_status=SourceStatus.ACTIVE,
realtime_error_count=realtime_error_count,
realtime_data_updated_at=realtime_data_updated_at,
)
2 changes: 1 addition & 1 deletion webapp/services/import_services/giroe/giroe_validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,6 @@ class LocationInput:


@validataclass
class LocationListInput:
class ItemListInput:
items: List[dict] = ListValidator(UnvalidatedDictValidator())
next_path: Optional[str] = StringValidator(), Default(None)