Skip to content

Commit 0f5fd2e

Browse files
committed
Add EVC auto configuration
- Add EVC auto-configuration in async_automatic_config method - Add configure_car_arrays_for_evc method for dynamic EVC detection - Add EVC status sensor publishing and car array configuration in polling loop - Add 'evcs' to cspell dictionary - Update API URL to include page parameter
1 parent 66dd7f3 commit 0f5fd2e

2 files changed

Lines changed: 88 additions & 2 deletions

File tree

‎.cspell/custom-dictionary-workspace.txt‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ Energidataservice
8080
energydataservice
8181
epod
8282
euids
83+
evcs
8384
evse
8485
exportlimit
8586
fdpwr

‎apps/predbat/gecloud.py‎

Lines changed: 87 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -608,12 +608,13 @@ async def publish_registers(self, device, registers, select_key=None):
608608
self.base.dashboard_item(entity_id, state="on" if state else "off", attributes=attributes, app="gecloud")
609609
self.register_entity_map[entity_id] = {"device": device, "key": key}
610610

611-
async def async_automatic_config(self, devices):
611+
async def async_automatic_config(self, devices, evc_devices=None):
612612
"""
613613
Automatically configure predbat using GE Cloud auto-detected devices.
614614
'devices' is a dict with keys:
615615
- "ems": the EMS device serial
616616
- "battery": list of battery inverter serials (for battery-specific sensors)
617+
'evc_devices' is a list of EV charger device dicts
617618
"""
618619
if not devices or not devices["battery"]:
619620
self.log("GECloud: No battery devices found, cannot configure")
@@ -677,8 +678,76 @@ async def async_automatic_config(self, devices):
677678
self.base.args["load_power"] = ["sensor.predbat_gecloud_" + ems + "_consumption_power"] + [0 for _ in range(num_inverters - 1)]
678679
self.base.args["grid_power"] = ["sensor.predbat_gecloud_" + ems + "_grid_power"] + [0 for _ in range(num_inverters - 1)]
679680

681+
# Auto-configure EV chargers if any are detected
682+
if evc_devices:
683+
evc_serials = []
684+
self.log(f"GECloud: Processing {len(evc_devices)} EV charger devices for auto-configuration")
685+
for device_data in evc_devices:
686+
uuid = device_data.get("uuid")
687+
self.log(f"GECloud: Processing EV charger UUID: {uuid}")
688+
if uuid:
689+
try:
690+
# Get full device details to extract serial number
691+
full_device = await self.async_get_evc_device(uuid)
692+
self.log(f"GECloud: Retrieved device details: {full_device}")
693+
serial = full_device.get("serial_number")
694+
self.log(f"GECloud: Extracted serial number: {serial}")
695+
if serial:
696+
evc_serials.append(serial)
697+
except Exception as e:
698+
self.log(f"GECloud: Error getting device details for {uuid}: {e}")
699+
# Fallback to UUID if serial fetch fails
700+
evc_serials.append(uuid)
701+
702+
if evc_serials:
703+
# Store charger info for later use by Enode plugin
704+
self.evc_chargers = evc_serials
705+
706+
# Get current car_charging_planned array or create empty list
707+
current_planned = self.base.args.get("car_charging_planned", [])
708+
if not isinstance(current_planned, list):
709+
current_planned = []
710+
711+
# Append EVC status sensors to car_charging_planned
712+
for serial in evc_serials:
713+
evc_sensor = "sensor.predbat_gecloud_" + serial + "_evc_status"
714+
if evc_sensor not in current_planned:
715+
current_planned.append(evc_sensor)
716+
717+
self.base.args["car_charging_planned"] = current_planned
718+
719+
# Increment num_cars for each charger
720+
# The Enode plugin will manage the actual car arrays and try to match vehicles to chargers
721+
current_num_cars = self.base.args.get("num_cars", 0)
722+
self.base.args["num_cars"] = current_num_cars + len(evc_serials)
723+
724+
self.log(f"GECloud: Found {len(evc_serials)} EV chargers, increased num_cars from {current_num_cars} to {self.base.args['num_cars']}")
725+
self.log(f"GECloud: Updated car_charging_planned: {self.base.args['car_charging_planned']}")
726+
680727
self.log("GECloud: Automatic configuration complete")
681728

729+
async def configure_car_arrays_for_evc(self, serial, entity_name):
730+
"""
731+
Configure car arrays for a newly detected EV charger.
732+
This handles cases where EVCs are detected after initial startup.
733+
"""
734+
# Get current car_charging_planned array or create empty list
735+
current_planned = self.base.args.get("car_charging_planned", [])
736+
if not isinstance(current_planned, list):
737+
current_planned = []
738+
739+
# Add EVC status sensor to car_charging_planned if not already there
740+
if entity_name not in current_planned:
741+
current_planned.append(entity_name)
742+
self.base.args["car_charging_planned"] = current_planned
743+
744+
# Increment num_cars
745+
current_num_cars = self.base.args.get("num_cars", 0)
746+
self.base.args["num_cars"] = current_num_cars + 1
747+
748+
self.log(f"GECloud: Configured car arrays for EVC {serial}, added {entity_name} to car_charging_planned")
749+
self.log(f"GECloud: Increased num_cars from {current_num_cars} to {self.base.args['num_cars']}")
750+
682751
async def start(self):
683752
"""
684753
Start the client
@@ -713,7 +782,7 @@ async def start(self):
713782
self.pending_writes[device] = []
714783

715784
if self.automatic:
716-
await self.async_automatic_config(devices_dict)
785+
await self.async_automatic_config(devices_dict, evc_devices_dict)
717786

718787
seconds = 0
719788
while not self.stop_cloud and not self.base.fatal_error:
@@ -729,6 +798,22 @@ async def start(self):
729798
for uuid in evc_device_list:
730799
self.evc_device[uuid] = await self.async_get_evc_device(uuid)
731800
serial = self.evc_device[uuid].get("serial_number", "unknown")
801+
802+
# Publish EV charger status as sensor entity
803+
evc_status = self.evc_device[uuid].get("status", "unknown")
804+
entity_name = f"sensor.predbat_gecloud_{serial}_evc_status"
805+
entity_name = entity_name.lower()
806+
self.base.dashboard_item(entity_name, state=evc_status, attributes={"friendly_name": "EV Charger Status", "icon": "mdi:ev-station", "device_class": "enum"}, app="gecloud")
807+
self.log(f"GE Cloud EVC {serial}: Published status sensor with value '{evc_status}'")
808+
809+
# Configure car arrays when EV charger is first detected
810+
if uuid not in getattr(self, "configured_evcs", set()):
811+
await self.configure_car_arrays_for_evc(serial, entity_name)
812+
# Mark this EVC as configured
813+
if not hasattr(self, "configured_evcs"):
814+
self.configured_evcs = set()
815+
self.configured_evcs.add(uuid)
816+
732817
self.evc_data[uuid] = await self.async_get_evc_device_data(uuid)
733818
self.evc_sessions[uuid] = await self.async_get_evc_sessions(uuid)
734819
await self.publish_evc_data(serial, self.evc_data[uuid])

0 commit comments

Comments
 (0)