Skip to content

Commit a4e952f

Browse files
Decouple octopus direct from Predbat using database (#2825)
* Re-work octopus direct to use HA interface * Typo * Join events via selector * [pre-commit.ci lite] apply automatic fixes * Typos * Fix unit test --------- Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
1 parent ee11b9d commit a4e952f

6 files changed

Lines changed: 266 additions & 193 deletions

File tree

‎apps/predbat/components.py‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,11 @@
107107
"required": True,
108108
"config": "octopus_api_account",
109109
},
110+
"automatic": {
111+
"required": False,
112+
"default": True,
113+
"config": "octopus_automatic",
114+
},
110115
},
111116
},
112117
"ohme": {

‎apps/predbat/fetch.py‎

Lines changed: 28 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1061,18 +1061,10 @@ def fetch_sensor_data(self):
10611061
# Log current values
10621062
self.log("Current data so far today: load {} kWh import {} kWh export {} kWh pv {} kWh".format(dp2(self.load_minutes_now), dp2(self.import_today_now), dp2(self.export_today_now), dp2(self.pv_today_now)))
10631063

1064-
octopus_api_direct = self.components.get_component("octopus")
10651064
if "rates_import_octopus_url" in self.args:
10661065
# Fixed URL for rate import
10671066
self.log("Downloading import rates directly from URL {}".format(self.get_arg("rates_import_octopus_url", indirect=False)))
10681067
self.rate_import = self.download_octopus_rates(self.get_arg("rates_import_octopus_url", indirect=False))
1069-
elif octopus_api_direct:
1070-
self.log("Downloading import rates directly from Octopus API")
1071-
self.rate_import = self.get_octopus_direct("import")
1072-
if not self.rate_import:
1073-
self.log("Error: Unable to download rates from Octopus API")
1074-
self.record_status(message="Error: Unable to download rates from Octopus API", had_errors=True)
1075-
raise ValueError
10761068
elif "metric_octopus_import" in self.args:
10771069
# Octopus import rates
10781070
entity_id = self.get_arg("metric_octopus_import", None, indirect=False)
@@ -1094,12 +1086,7 @@ def fetch_sensor_data(self):
10941086
self.rate_import = self.basic_rates(self.get_arg("rates_import", [], indirect=False), "rates_import")
10951087

10961088
# Gas rates if set
1097-
if octopus_api_direct:
1098-
self.log("Downloading gas rates directly from Octopus API")
1099-
self.rate_gas = self.get_octopus_direct("gas")
1100-
self.rate_gas, self.rate_gas_replicated = self.rate_replicate(self.rate_gas, is_import=False, is_gas=False)
1101-
self.rate_scan_gas(self.rate_gas, print=True)
1102-
elif "metric_octopus_gas" in self.args:
1089+
if "metric_octopus_gas" in self.args:
11031090
entity_id = self.get_arg("metric_octopus_gas", None, indirect=False)
11041091
self.rate_gas = self.fetch_octopus_rates(entity_id)
11051092
if not self.rate_gas:
@@ -1138,40 +1125,28 @@ def fetch_sensor_data(self):
11381125
# Work out current car SoC and limit
11391126
self.car_charging_loss = 1 - float(self.get_arg("car_charging_loss"))
11401127

1141-
slot_is_configured = "octopus_intelligent_slot" in self.args
1128+
entity_id = self.get_arg("octopus_intelligent_slot", indirect=False)
11421129
ohme_automatic = self.get_arg("ohme_automatic", False)
11431130

1144-
if (octopus_api_direct and octopus_api_direct.get_intelligent_device()) or (not octopus_api_direct and slot_is_configured):
1131+
if entity_id:
11451132
completed = []
11461133
planned = []
1147-
vehicle = {}
1148-
vehicle_pref = {}
1149-
1150-
if octopus_api_direct and not ohme_automatic:
1151-
completed = octopus_api_direct.get_intelligent_completed_dispatches()
1152-
planned = octopus_api_direct.get_intelligent_planned_dispatches()
1153-
vehicle = octopus_api_direct.get_intelligent_vehicle()
1154-
vehicle_pref = vehicle
1155-
self.log("Octopus API planned and completed slots: {} - {}".format(completed, planned))
1156-
else:
1157-
entity_id = self.get_arg("octopus_intelligent_slot", indirect=False)
1158-
if entity_id and "octopus_intelligent_slot_action_config" in self.args:
1159-
config_entry = self.get_arg("octopus_intelligent_slot_action_config", None, indirect=False)
1160-
service_name = entity_id.replace(".", "/")
1161-
result = self.call_service_wrapper(service_name, config_entry=config_entry, return_response=True)
1162-
if result and ("slots" in result):
1163-
planned = result["slots"]
1164-
else:
1165-
self.log("Warn: Unable to get data from {} - octopus_intelligent_slot using action config {} result was {}".format(entity_id, config_entry, result))
1134+
1135+
if entity_id and "octopus_intelligent_slot_action_config" in self.args:
1136+
config_entry = self.get_arg("octopus_intelligent_slot_action_config", None, indirect=False)
1137+
service_name = entity_id.replace(".", "/")
1138+
result = self.call_service_wrapper(service_name, config_entry=config_entry, return_response=True)
1139+
if result and ("slots" in result):
1140+
planned = result["slots"]
11661141
else:
1167-
try:
1168-
completed = self.get_state_wrapper(entity_id=entity_id, attribute="completedDispatches") or self.get_state_wrapper(entity_id=entity_id, attribute="completed_dispatches")
1169-
planned = self.get_state_wrapper(entity_id=entity_id, attribute="plannedDispatches") or self.get_state_wrapper(entity_id=entity_id, attribute="planned_dispatches")
1170-
vehicle = self.get_state_wrapper(entity_id=entity_id, attribute="registeredKrakenflexDevice")
1171-
vehicle_pref = self.get_state_wrapper(entity_id=entity_id, attribute="vehicleChargingPreferences")
1172-
except (ValueError, TypeError):
1173-
self.log("Warn: Unable to get data from {} - octopus_intelligent_slot may not be set correctly".format(entity_id))
1174-
self.record_status(message="Error: octopus_intelligent_slot not set correctly", had_errors=True)
1142+
self.log("Warn: Unable to get data from {} - octopus_intelligent_slot using action config {} result was {}".format(entity_id, config_entry, result))
1143+
else:
1144+
try:
1145+
completed = self.get_state_wrapper(entity_id=entity_id, attribute="completed_dispatches") or self.get_state_wrapper(entity_id=entity_id, attribute="completedDispatches")
1146+
planned = self.get_state_wrapper(entity_id=entity_id, attribute="planned_dispatches") or self.get_state_wrapper(entity_id=entity_id, attribute="plannedDispatches")
1147+
except (ValueError, TypeError):
1148+
self.log("Warn: Unable to get data from {} - octopus_intelligent_slot may not be set correctly".format(entity_id))
1149+
self.record_status(message="Error: octopus_intelligent_slot not set correctly", had_errors=True)
11751150

11761151
# Completed and planned slots
11771152
if completed:
@@ -1186,33 +1161,18 @@ def fetch_sensor_data(self):
11861161

11871162
if self.num_cars >= 1:
11881163
# Extract vehicle data if we can get it
1189-
if vehicle or (octopus_api_direct and not ohme_automatic):
1190-
self.car_charging_battery_size[0] = float(vehicle.get("vehicleBatterySizeInKwh", self.car_charging_battery_size[0]))
1191-
self.car_charging_rate[0] = float(vehicle.get("chargePointPowerInKw", self.car_charging_rate[0]))
1192-
else:
1193-
size = self.get_state_wrapper(entity_id=entity_id, attribute="vehicle_battery_size_in_kwh")
1194-
rate = self.get_state_wrapper(entity_id=entity_id, attribute="charge_point_power_in_kw")
1195-
if size:
1196-
self.car_charging_battery_size[0] = size
1197-
if rate:
1198-
self.car_charging_rate[0] = rate
1164+
size = self.get_state_wrapper(entity_id=entity_id, attribute="vehicle_battery_size_in_kwh")
1165+
rate = self.get_state_wrapper(entity_id=entity_id, attribute="charge_point_power_in_kw")
1166+
if size:
1167+
self.car_charging_battery_size[0] = size
1168+
if rate:
1169+
self.car_charging_rate[0] = rate
11991170

12001171
# Get car charging limit again from car based on new battery size
12011172
self.car_charging_limit[0] = dp3((float(self.get_arg("car_charging_limit", 100.0, index=0)) * self.car_charging_battery_size[0]) / 100.0)
12021173

12031174
# Extract vehicle preference if we can get it
1204-
if (vehicle_pref or (octopus_api_direct and not ohme_automatic)) and self.octopus_intelligent_charging:
1205-
octopus_limit = max(float(vehicle_pref.get("weekdayTargetSoc", 100)), float(vehicle_pref.get("weekendTargetSoc", 100)))
1206-
octopus_ready_time = vehicle_pref.get("weekdayTargetTime", None)
1207-
if not octopus_ready_time:
1208-
octopus_ready_time = self.car_charging_plan_time[0]
1209-
else:
1210-
if isinstance(octopus_ready_time, str) and len(octopus_ready_time) == 5:
1211-
octopus_ready_time += ":00"
1212-
self.car_charging_plan_time[0] = octopus_ready_time
1213-
octopus_limit = dp3(octopus_limit * self.car_charging_battery_size[0] / 100.0)
1214-
self.car_charging_limit[0] = min(self.car_charging_limit[0], octopus_limit)
1215-
elif self.octopus_intelligent_charging:
1175+
if self.octopus_intelligent_charging:
12161176
octopus_ready_time = self.get_arg("octopus_ready_time", None)
12171177
if isinstance(octopus_ready_time, str) and len(octopus_ready_time) == 5:
12181178
octopus_ready_time += ":00"
@@ -1229,8 +1189,7 @@ def fetch_sensor_data(self):
12291189
if octopus_ready_time:
12301190
self.car_charging_plan_time[0] = octopus_ready_time
12311191

1232-
# Use octopus slots for charging?
1233-
if self.octopus_intelligent_charging:
1192+
# Use octopus slots for charging?
12341193
self.octopus_slots = self.add_now_to_octopus_slot(self.octopus_slots, self.now_utc)
12351194
if not self.octopus_intelligent_ignore_unplugged or self.car_charging_planned[0]:
12361195
self.car_charging_slots[0] = self.load_octopus_slots(self.octopus_slots, self.octopus_intelligent_consider_full)
@@ -1262,9 +1221,6 @@ def fetch_sensor_data(self):
12621221
# Fixed URL for rate export
12631222
self.log("Downloading export rates directly from URL {}".format(self.get_arg("rates_export_octopus_url", indirect=False)))
12641223
self.rate_export = self.download_octopus_rates(self.get_arg("rates_export_octopus_url", indirect=False))
1265-
elif octopus_api_direct:
1266-
self.log("Downloading export rates directly from Octopus API")
1267-
self.rate_export = self.get_octopus_direct("export")
12681224
elif "metric_octopus_export" in self.args:
12691225
# Octopus export rates
12701226
entity_id = self.get_arg("metric_octopus_export", None, indirect=False)
@@ -1287,12 +1243,8 @@ def fetch_sensor_data(self):
12871243
self.octopus_free_slots, self.octopus_saving_slots = self.fetch_octopus_sessions()
12881244

12891245
# Standing charge
1290-
if octopus_api_direct:
1291-
self.metric_standing_charge = self.get_standing_charge_direct()
1292-
self.log("Octopus Import standing charge is set to {} p".format(self.metric_standing_charge))
1293-
else:
1294-
self.metric_standing_charge = self.get_arg("metric_standing_charge", 0.0) * 100.0
1295-
self.log("Standing charge is set to {} p".format(self.metric_standing_charge))
1246+
self.metric_standing_charge = self.get_arg("metric_standing_charge", 0.0) * 100.0
1247+
self.log("Standing charge is set to {} p".format(self.metric_standing_charge))
12961248

12971249
# futurerate data
12981250
futurerate = FutureRate(self)

0 commit comments

Comments
 (0)