mirror of
https://github.com/flobz/psa_car_controller.git
synced 2026-08-22 09:26:16 +00:00
improve automatic refresh to avoid redundancy
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import json
|
||||
from copy import copy
|
||||
|
||||
from MyLogger import logger
|
||||
|
||||
@@ -20,6 +21,7 @@ class Car:
|
||||
self.battery_power = None
|
||||
self.fuel_capacity = None
|
||||
self.set_energy_capacity(battery_power, fuel_capacity)
|
||||
self.status = None
|
||||
|
||||
def set_energy_capacity(self, battery_power = None, fuel_capacity = None):
|
||||
if battery_power is not None and fuel_capacity is not None:
|
||||
@@ -37,8 +39,13 @@ class Car:
|
||||
def from_json(cls, data: dict):
|
||||
return cls(**data)
|
||||
|
||||
def to_dict(self):
|
||||
car_dict = copy(self.__dict__)
|
||||
car_dict.pop("status")
|
||||
return car_dict
|
||||
|
||||
def __str__(self):
|
||||
return str(self.__dict__)
|
||||
return str(self.to_dict())
|
||||
|
||||
class Cars(list):
|
||||
def __init__(self, *args):
|
||||
@@ -69,7 +76,7 @@ class Cars(list):
|
||||
return str(list(map(str, self)))
|
||||
|
||||
def save_cars(self, name="cars.json"):
|
||||
config_str = json.dumps(self, default=lambda o: o.__dict__, sort_keys=True, indent=4)
|
||||
config_str = json.dumps(self, default=lambda car: car.to_dict(), sort_keys=True, indent=4)
|
||||
with open(name, "w") as f:
|
||||
f.write(config_str)
|
||||
|
||||
@@ -79,5 +86,5 @@ class Cars(list):
|
||||
with open(name, "r") as f:
|
||||
json_str = f.read()
|
||||
return Cars.from_json(json.loads(json_str))
|
||||
except FileNotFoundError:
|
||||
return Cars()
|
||||
except (FileNotFoundError, TypeError):
|
||||
return Cars()
|
||||
|
||||
+14
-21
@@ -10,7 +10,6 @@ import pytz
|
||||
|
||||
from MyPSACC import MyPSACC
|
||||
from MyLogger import logger
|
||||
from psa_connectedcar.rest import ApiException
|
||||
|
||||
|
||||
class ChargeControl:
|
||||
@@ -23,7 +22,6 @@ class ChargeControl:
|
||||
self.set_stop_hour(stop_hour)
|
||||
self.psacc = psacc
|
||||
self.retry_count = 0
|
||||
self.thread: threading.Timer = None
|
||||
self.always_check = True
|
||||
|
||||
def set_stop_hour(self, stop_hour):
|
||||
@@ -36,9 +34,9 @@ class ChargeControl:
|
||||
if self._next_stop_hour < datetime.now():
|
||||
self._next_stop_hour += timedelta(days=1)
|
||||
|
||||
def start(self):
|
||||
periodicity = ChargeControl.periodicity
|
||||
def process(self):
|
||||
now = datetime.now()
|
||||
vehicle_status = self.psacc.vehicles_list.get_car_by_vin(self.vin).status
|
||||
try:
|
||||
if self._next_stop_hour is not None and self._next_stop_hour < now:
|
||||
stop_charge = True
|
||||
@@ -48,47 +46,41 @@ class ChargeControl:
|
||||
stop_charge = False
|
||||
|
||||
if self.percentage_threshold != 100 or stop_charge or self.always_check:
|
||||
res = None
|
||||
try:
|
||||
res = self.psacc.get_vehicle_info(self.vin)
|
||||
except ApiException:
|
||||
logger.error(traceback.format_exc())
|
||||
if res is not None:
|
||||
status = res.get_energy('Electric').charging.status
|
||||
level = res.get_energy('Electric').level
|
||||
if vehicle_status is not None:
|
||||
status = vehicle_status.get_energy('Electric').charging.status
|
||||
level = vehicle_status.get_energy('Electric').level
|
||||
logger.info("charging status of %s is %s, battery level: %d", self.vin, status, level)
|
||||
if status == "InProgress":
|
||||
# force update if the car doesn't send info during 10 minutes
|
||||
last_update = res.get_energy('Electric').updated_at
|
||||
last_update = vehicle_status.get_energy('Electric').updated_at
|
||||
if (datetime.utcnow().replace(tzinfo=pytz.UTC) - last_update).total_seconds() > 60 * 10:
|
||||
self.psacc.wakeup(self.vin)
|
||||
if (level >= self.percentage_threshold and self.retry_count < 2) or stop_charge:
|
||||
self.psacc.charge_now(self.vin, False)
|
||||
self.retry_count += 1
|
||||
sleep(ChargeControl.MQTT_TIMEOUT)
|
||||
res = self.psacc.get_vehicle_info(self.vin)
|
||||
status = res.get_energy('Electric').charging.status
|
||||
vehicle_status = self.psacc.get_vehicle_info(self.vin)
|
||||
status = vehicle_status.get_energy('Electric').charging.status
|
||||
if status == "InProgress":
|
||||
logger.warning("retry to stop the charge of %s", self.vin)
|
||||
self.psacc.charge_now(self.vin, False)
|
||||
self.retry_count += 1
|
||||
if self._next_stop_hour is not None:
|
||||
next_in_second = (self._next_stop_hour - now).total_seconds()
|
||||
if next_in_second < periodicity:
|
||||
if next_in_second < self.psacc.info_refresh_rate:
|
||||
periodicity = next_in_second
|
||||
self.thread = threading.Timer(periodicity, self.process, args=[vehicle_status])
|
||||
self.thread.start()
|
||||
else:
|
||||
self.retry_count = 0
|
||||
else:
|
||||
logger.error("error when get vehicle info of %s", self.vin)
|
||||
logger.error("error can't retrieve vehicle info of %s", self.vin)
|
||||
except:
|
||||
logger.error(traceback.format_exc())
|
||||
self.thread = threading.Timer(periodicity, self.start)
|
||||
self.thread.start()
|
||||
|
||||
def get_dict(self):
|
||||
chd = copy(self.__dict__)
|
||||
chd.pop("psacc")
|
||||
chd.pop("thread")
|
||||
return chd
|
||||
|
||||
|
||||
@@ -110,6 +102,7 @@ class ChargeControls:
|
||||
self._confighash = new_hash
|
||||
logger.info("save config change")
|
||||
|
||||
@staticmethod
|
||||
def load_config(psacc: MyPSACC, name="charge_config.json"):
|
||||
with open(name, "r") as f:
|
||||
config_str = f.read()
|
||||
@@ -127,4 +120,4 @@ class ChargeControls:
|
||||
|
||||
def start(self):
|
||||
for charge_control in self.list.values():
|
||||
charge_control.start()
|
||||
charge_control.psacc.info_callback.append(charge_control.process)
|
||||
|
||||
+19
-13
@@ -181,6 +181,8 @@ class MyPSACC:
|
||||
self.country_code = country_code
|
||||
self.mqtt_client = None
|
||||
self.precond_programs = {}
|
||||
self.info_callback = []
|
||||
self.info_refresh_rate = 120
|
||||
|
||||
def refresh_token(self):
|
||||
self.manager._refresh_token()
|
||||
@@ -200,21 +202,25 @@ class MyPSACC:
|
||||
self.manager.proxies = self._proxies
|
||||
|
||||
def get_vehicle_info(self, vin):
|
||||
res = self.api().get_vehicle_status(self.vehicles_list.get_car_by_vin(vin).vehicle_id, extension=["odometer"])
|
||||
# retry
|
||||
if res is None:
|
||||
res = self.api().get_vehicle_status(self.vehicles_list.get_car_by_vin(vin).vehicle_id,
|
||||
extension=["odometer"])
|
||||
if self._record_enabled:
|
||||
self.record_info(vin, res)
|
||||
car = self.vehicles_list.get_car_by_vin(vin)
|
||||
for attempt in range(0, 2):
|
||||
res = self.api().get_vehicle_status(car.vehicle_id, extension=["odometer"])
|
||||
if res is not None:
|
||||
car.status = res
|
||||
if self._record_enabled:
|
||||
self.record_info(vin, res)
|
||||
break
|
||||
return res
|
||||
|
||||
def refresh_vehicle_info(self, refresh=5):
|
||||
while True:
|
||||
sleep(refresh * 60)
|
||||
logger.info("refresh_vehicle_info")
|
||||
for car in self.vehicles_list:
|
||||
self.get_vehicle_info(car.vin)
|
||||
def refresh_vehicle_info(self):
|
||||
if self.info_refresh_rate is not None:
|
||||
while True:
|
||||
sleep(self.info_refresh_rate)
|
||||
logger.info("refresh_vehicle_info")
|
||||
for car in self.vehicles_list:
|
||||
self.get_vehicle_info(car.vin)
|
||||
for callback in self.info_callback:
|
||||
callback()
|
||||
|
||||
# monitor doesn't seem to work
|
||||
def newMonitor(self, vin, body):
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
prospector>=1.3.0
|
||||
pre-commit
|
||||
@@ -63,16 +63,21 @@ if __name__ == "__main__":
|
||||
client_password = input("mypeugeot password: ")
|
||||
web.app.myp.connect(client_email, client_password)
|
||||
logger.info(str(web.app.myp.get_vehicles()))
|
||||
if args.offline or args.remote_disable:
|
||||
logger.info("mqtt disabled")
|
||||
if args.offline:
|
||||
logger.info("offline mode")
|
||||
else:
|
||||
web.app.myp.start_mqtt()
|
||||
if args.charge_control:
|
||||
web.app.chc = ChargeControls.load_config(web.app.myp, name=args.charge_control)
|
||||
web.app.chc.start()
|
||||
if args.remote_disable:
|
||||
logger.info("mqtt disabled")
|
||||
else:
|
||||
web.app.myp.start_mqtt()
|
||||
if args.refresh or args.charge_control:
|
||||
if args.refresh:
|
||||
web.app.myp.info_refresh_rate = args.refresh * 60
|
||||
if args.charge_control:
|
||||
web.app.chc = ChargeControls.load_config(web.app.myp, name=args.charge_control)
|
||||
web.app.chc.start()
|
||||
Thread(target=web.app.myp.refresh_vehicle_info).start()
|
||||
|
||||
save_config(web.app.myp)
|
||||
t1 = Thread(target=start_app, args=["My car info", args.base_path, args.debug < 20, args.listen, int(args.port)])
|
||||
t1.start()
|
||||
|
||||
if args.refresh:
|
||||
Thread(target=web.app.myp.refresh_vehicle_info, args=[args.refresh]).start()
|
||||
|
||||
Reference in New Issue
Block a user