From 3ebc48903af44b733550cab0a26fe94356b5961b Mon Sep 17 00:00:00 2001 From: Florian Bezannier Date: Fri, 5 Mar 2021 21:01:40 +0100 Subject: [PATCH] WHIP handle hybrid car --- Car.py | 72 ++++++++++++++++++ MyPSACC.py | 196 +++++++++++------------------------------------- Trip.py | 151 +++++++++++++++++++++++++++++++++---- server.py | 2 +- web/callback.py | 8 +- web/db.py | 8 -- 6 files changed, 256 insertions(+), 181 deletions(-) create mode 100644 Car.py diff --git a/Car.py b/Car.py new file mode 100644 index 0000000..a7499b0 --- /dev/null +++ b/Car.py @@ -0,0 +1,72 @@ +import json + +from MyLogger import logger + +ENERGY_CAPACITY = {'SUV 3008': {'BATTERY_POWER': 10.8, 'FUEL_CAPACITY': 43}, + '208': {'BATTERY_POWER': 46, 'FUEL_CAPACITY': 0}, + '2008': {'BATTERY_POWER': 46, 'FUEL_CAPACITY': 0} + } +DEFAULT_BATTERY_POWER = 46 +DEFAULT_FUEL_CAPACITY = 0 + + +class Car: + def __init__(self, vin, vehicle_id, brand, label="unknown", battery_power=None, fuel_capacity=None): + self.vin = vin + self.vehicle_id = vehicle_id + self.label = label + self.brand = brand + if battery_power is not None and fuel_capacity is not None: + self.battery_power = battery_power + self.fuel_capacity = fuel_capacity + elif label in ENERGY_CAPACITY: + self.battery_power = ENERGY_CAPACITY[label]["BATTERY_POWER"] + self.fuel_capacity = ENERGY_CAPACITY[label]["FUEL_CAPACITY"] + else: + logger.warn("Can't get car model please check cars.json") + self.battery_power = DEFAULT_BATTERY_POWER + self.fuel_capacity = DEFAULT_FUEL_CAPACITY + + @classmethod + def from_json(cls, data: dict): + return cls(**data) + +class Cars(list): + def __init__(self, *args): + list.__init__(self, *args) + + def get_car_by_vin(self, vin) -> Car: + for car in self: + if car.vin == vin: + return car + + def get_car_by_id(self, vehicle_id) -> Car: + for car in self: + if car.vehicle_id == vehicle_id: + return car + + def add(self, car: Car): + if self.get_car_by_id(car.vehicle_id) is None: + self.append(car) + + @classmethod + def from_json(cls, data: list): + students = list(map(Car.from_json, data)) + return cls(students) + + def __str__(self): + return str(self.__dict__) + + def save_cars(self, name="cars.json"): + config_str = json.dumps(self, default=lambda o: o.__dict__, sort_keys=True, indent=4) + with open(name, "w") as f: + f.write(config_str) + + @staticmethod + def load_cars(name="cars.json"): + try: + with open(name, "r") as f: + json_str = f.read() + return Cars.from_json(json.loads(json_str)) + except: + return Cars() \ No newline at end of file diff --git a/MyPSACC.py b/MyPSACC.py index a369377..1d719ac 100644 --- a/MyPSACC.py +++ b/MyPSACC.py @@ -17,7 +17,7 @@ from requests import Response from typing import List import psa_connectedcar as psac -from Trip import Trip +from Car import Cars, Car from ecomix import Ecomix from otp.Otp import load_otp, new_otp_session, save_otp from psa_connectedcar import ApiClient @@ -25,14 +25,9 @@ from psa_connectedcar.rest import ApiException from MyLogger import logger from threading import Semaphore, Timer from functools import wraps -import sqlite3 from web.db import get_db -ENERGY_CAPACITY = {'SUV 3008': {'BATTERY_POWER': 10.8, 'FUEL_CAPACITY': 43}, - '208': {'BATTERY_POWER': 46, 'FUEL_CAPACITY': 0}, # to be verified by an e208 owner - to be changed in ENERGY_CAPACITY and in get_trip function vehicle_model default value - } - oauhth_url = {"clientsB2CPeugeot": "https://idpcvs.peugeot.com/am/oauth2/access_token", "clientsB2CCitroen": "https://idpcvs.citroen.com/am/oauth2/access_token", "clientsB2CDS": "https://idpcvs.driveds.com/am/oauth2/access_token", @@ -132,8 +127,8 @@ class OauthAPIClient(ApiClient): def correlation_id(date): date_str = date.strftime("%Y%m%d%H%M%S%f")[:-3] uuid_str = str(uuid.uuid4()).replace("-", "") - correlation_id = uuid_str + date_str - return correlation_id + correlationId = uuid_str + date_str + return correlationId class MyPSACC: @@ -142,7 +137,8 @@ class MyPSACC: def connect(self, user, password): self.manager.init_with_user_credentials(user, password, self.realm) - def __init__(self, refresh_token, client_id, client_secret, remote_refresh_token, customer_id, realm, proxies=None, weather_api = None): + def __init__(self, refresh_token, client_id, client_secret, remote_refresh_token, customer_id, realm, country_code, + proxies=None, weather_api=None): self.realm = realm self.service_information = ServiceInformation(authorize_service, oauhth_url[self.realm], @@ -156,7 +152,7 @@ class MyPSACC: self.manager.refresh_token = refresh_token self.remote_refresh_token = remote_refresh_token self.remote_access_token = None - self.vehicles_list = None + self.vehicles_list = Cars.load_cars() self.setProxies(proxies) self.customer_id = customer_id self._confighash = None @@ -172,6 +168,8 @@ class MyPSACC: self._record_enabled = False self.otp = None self.weather_api = weather_api + self.country_code = country_code + self.mqtt_client = None def refresh_token(self): self.manager._refresh_token() @@ -191,37 +189,30 @@ class MyPSACC: self.manager.proxies = self._proxies def get_vehicle_info(self, vin): - res = self.api().get_vehicle_status(self.get_vehicle_id_with_vin(vin), extension=["odometer"]) + 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.get_vehicle_id_with_vin(vin), extension=["odometer"]) + 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) return res # monitor doesn't seem to work def newMonitor(self, vin, body): - res = self.manager.post("https://api.groupe-psa.com/connectedcar/v4/user/vehicles/" + self.vehicles_list[vin][ - "id"] + "/status?client_id=" + self.client_id, headers=self.headers, data=body) + res = self.manager.post("https://api.groupe-psa.com/connectedcar/v4/user/vehicles/" + + self.vehicles_list.get_car_by_vin(vin).id + "/status?client_id=" + self.client_id, + headers=self.headers, data=body) data = res.json() return data def get_vehicles(self): res = self.api().get_vehicles_by_device() - self.vehicles_list = {} for vehicle in res.embedded.vehicles: vin = vehicle.vin - self.vehicles_list[vin] = {"id": vehicle.id,"brand": vehicle.brand, "label": vehicle.label} + self.vehicles_list.add(Car(vin, vehicle.id, vehicle.brand, vehicle.label)) + self.vehicles_list.save_cars() return self.vehicles_list - def get_vehicle_id_with_vin(self, vin): - return self.vehicles_list[vin]["id"] - - def getVIN(self): - if self.vehicles_list is None: - self.get_vehicles() - return list(self.vehicles_list.keys()) - def load_otp(self): otp_session = load_otp() if otp_session is None: @@ -278,13 +269,12 @@ class MyPSACC: self.mqtt_client.username_pw_set("IMA_OAUTH_ACCESS_TOKEN", self.remote_access_token) return res - def on_mqtt_connect(self, client, userdata, rc, a): try: logger.info("Connected with result code " + str(rc)) topics = [MQTT_RESP_TOPIC + self.customer_id + "/#"] - for vin in self.getVIN(): - topics.append(MQTT_EVENT_TOPIC + vin) + for car in self.vehicles_list: + topics.append(MQTT_EVENT_TOPIC + car.vin) for topic in topics: client.subscribe(topic) logger.info("subscribe to " + topic) @@ -350,7 +340,7 @@ class MyPSACC: def __keep_mqtt(self): # avoid token expiration timeout = 3600 * 24 # 1 day try: - self.get_state(list(self.vehicles_list.keys())[0]) + self.get_state(self.vehicles_list[0].vin) except: logger.warn("keep_mqtt error") threading.Timer(timeout, self.__keep_mqtt).start() @@ -421,7 +411,7 @@ class MyPSACC: self.mqtt_client.publish(MQTT_REQ_TOPIC + self.customer_id + "/VehCharge/state", msg) return True - #get state from server by mqtt + # get state from server by mqtt def get_state(self, vin): logger.info("ask state to " + vin) msg = self.mqtt_request(vin, {"action": "state"}) @@ -467,7 +457,10 @@ class MyPSACC: def load_config(name="config.json"): with open(name, "r") as f: str = f.read() - return MyPSACC(**json.loads(str)) + config = dict(**json.loads(str)) + if "country_code" not in config: + config["country_code"] = input("What is your country code ? (ex: FR, GB, DE, ES...)\n") + return MyPSACC(**config) def set_record(self, value: bool): self._record_enabled = value @@ -482,7 +475,9 @@ class MyPSACC: charge_date = status.get_energy('Electric').updated_at level_fuel = status.get_energy('Fuel').level moving = status.kinetic.moving - logger.debug(f"vin:{vin} longitude:{longitude} latitude:{latitude} date:{date} mileage:{mileage} level:{level} charging_status:{charging_status} charge_date:{charge_date} level_fuel:{level_fuel} moving:{moving}") + logger.debug( + f"vin:{vin} longitude:{longitude} latitude:{latitude} date:{date} mileage:{mileage} level:{level} " + f"charging_status:{charging_status} charge_date:{charge_date} level_fuel:{level_fuel} moving:{moving}") conn = get_db() if mileage == 0: # fix a bug of the api logger.error(f"The api return a wrong mileage for {vin} : {mileage}") @@ -494,15 +489,18 @@ class MyPSACC: weather_rep = requests.get("https://api.openweathermap.org/data/2.5/onecall", params={"lat": latitude, "lon": longitude, "exclude": "minutely,hourly,daily,alerts", - "appid": "f8ee4124ea074950b696fd3e956a7069", "units": "metric"}) + "appid": self.weather_api, + "units": "metric"}) temp = weather_rep.json()["current"]["temp"] logger.debug(f"Temperature :{temp}c") except Exception as e: logger.error(f"Unable to get temperature from openweathermap :{e}") - if level_fuel == 0: # fix fuel level not provided when car is off + if level_fuel == 0: # fix fuel level not provided when car is off try: - level_fuel = conn.execute("SELECT level_fuel FROM position WHERE level_fuel>0 AND VIN=? ORDER BY Timestamp DESC LIMIT 1",(vin,)).fetchone()[0] + level_fuel = conn.execute( + "SELECT level_fuel FROM position WHERE level_fuel>0 AND VIN=? ORDER BY Timestamp DESC LIMIT 1", + (vin,)).fetchone()[0] logger.info(f"level_fuel fixed with last real value {level_fuel} for {vin}") except TypeError: level_fuel = None @@ -540,12 +538,12 @@ class MyPSACC: else: try: start_at, stop_at, start_level = conn.execute( - "SELECT start_at, stop_at, start_level from battery WHERE VIN=? ORDER BY start_at " - "DESC limit 1", (vin,)).fetchone() + "SELECT start_at, stop_at, start_level from battery WHERE VIN=? ORDER BY start_at " + "DESC limit 1", (vin,)).fetchone() in_progress = stop_at is None if in_progress: co2_per_kw = Ecomix.get_co2_per_kw(start_at, charge_date, latitude, longitude) - kw = (level - start_level) / 100 * BATTERY_POWER + kw = (level - start_level) / 100 * self.vehicles_list.get_car_by_vin(vin).battery_power res = conn.execute( "UPDATE battery set stop_at=?, end_level=?, co2=?, kw=? WHERE start_at=? and VIN=?", (charge_date, level, co2_per_kw, kw, start_at, vin)) @@ -565,119 +563,14 @@ class MyPSACC: features_list = [] for row in res: feature = Feature(geometry=Point((row["longitude"], row["latitude"])), - properties={"vin": row["vin"], "date": row["Timestamp"].strftime("%x %X"), "mileage": row["mileage"], - "level": row["level"],"level_fuel": row["level_fuel"]}) + properties={"vin": row["vin"], "date": row["Timestamp"].strftime("%x %X"), + "mileage": row["mileage"], + "level": row["level"], "level_fuel": row["level_fuel"]}) features_list.append(feature) feature_collection = FeatureCollection(features_list) conn.close() return geo_dumps(feature_collection, sort_keys=True) - @staticmethod - def get_trips(vehicle_model='208') -> List[Trip]: # to be verified by an e208 owner - to be changed in ENERGY_CAPACITY and in get_trip function vehicle_model default value - # we should add vin parameter - # we should think moving this method in Trip.py - conn = get_db() - res = conn.execute('SELECT * FROM position ORDER BY Timestamp').fetchall() - trips = [] - if len(res) > 1: - start = res[0] - end = res[1] - tr = Trip() - #res = list(map(dict,res)) - for x in range(0, len(res) - 2): - logger.debug(f"{res[x]['Timestamp']} mileage:{res[x]['mileage']} level:{res[x]['level']} level_fuel:{res[x]['level_fuel']}") - next_el = res[x + 2] - distance = end["mileage"] - start["mileage"] - duration = (end["Timestamp"] - start["Timestamp"]).total_seconds() / 3600 - try: - speed_average = distance / duration - except ZeroDivisionError: - speed_average = 0 - charge = end["level"] - start["level"] - if end["level_fuel"] != None and start["level_fuel"] != None: - refuel = end["level_fuel"] - start["level_fuel"] - else: - refuel = 0 - restart_trip = False - if refuel > 0: - restart_trip = True - logger.debug(f"refuel detected") - elif distance == 0 and charge > 2: - restart_trip = True - logger.debug(f"charge detected") - elif speed_average < 0.2 and duration > 0.05: # think again if duration is really needed - #end["mileage"] - start["mileage"] == 0 #or \ - #(end["Timestamp"] - start["Timestamp"]).total_seconds() / 3600 > 10: # condition useless ??? - restart_trip = True - logger.debug(f"low speed detected") - if restart_trip: - start = end - tr = Trip() - logger.debug(f"restart trip at {start['Timestamp']} {start['mileage']}km level:{start['level']} level_fuel:{start['level_fuel']}") - else: - distance = next_el["mileage"] - end["mileage"] # km - duration = (next_el["Timestamp"] - end["Timestamp"]).total_seconds() / 3600 - try: - speed_average = distance / duration - except ZeroDivisionError: - speed_average = 0 - charge = next_el["level"] - end["level"] - if next_el["level_fuel"] != None and end["level_fuel"] != None: - refuel = next_el["level_fuel"] - end["level_fuel"] - else: - refuel = 0 - end_trip = False - if refuel > 0: - end_trip = True - logger.debug(f"refuel detected") - elif distance == 0 and charge > 2: - end_trip = True - logger.debug(f"charge detected {charge}") - elif speed_average < 0.2 and duration > 0.05: - #(distance == 0 and duration > 0.08) or duration > 2 or # check the speed to handle missing point - end_trip = True - logger.debug(f"low speed detected") - elif duration > 2: - end_trip = True - logger.debug(f"too much time detected") - elif x == len(res)-3: # last record detected - # think if add point is needed - end = next_el - end_trip = True - logger.debug(f"last position found") - if end_trip: - logger.debug(f"stop trip at {end['Timestamp']} {end['mileage']}km level:{end['level']} level_fuel:{end['level_fuel']}") - tr.distance = end["mileage"] - start["mileage"] # km - if tr.distance > 0: - tr.start_at = start["Timestamp"] - tr.end_at = end["Timestamp"] - tr.add_points(end["longitude"], end["latitude"]) - tr.duration = (end["Timestamp"] - start["Timestamp"]).total_seconds() / 3600 - tr.speed_average = tr.distance / tr.duration - diff_level = start["level"] - end["level"] - tr.consumption = diff_level / 100 * ENERGY_CAPACITY[vehicle_model]['BATTERY_POWER'] # kw - tr.consumption_km = 100 * tr.consumption / tr.distance # kw/100 km - if start["level_fuel"] != None and end["level_fuel"] != None: - diff_level_fuel = start["level_fuel"] - end["level_fuel"] - tr.consumption_fuel = round(diff_level_fuel / 100 * ENERGY_CAPACITY[vehicle_model]['FUEL_CAPACITY'],2) # L - tr.consumption_fuel_km = round(100 * tr.consumption_fuel / tr.distance,2) # L/100 km - tr.mileage = end["mileage"] - logger.debug( - f"Trip: {tr.start_at} -> {tr.end_at} {tr.distance:.1f}km {tr.duration:.2f}h {tr.speed_average:.0f}km/h " - f"{tr.consumption:.2f}kw {tr.consumption_km:.2f}kw/100km {tr.consumption_fuel}L {tr.consumption_fuel_km}L/100km " - f"{tr.mileage:.1f}km") - # filter bad value - if tr.consumption_km < 70 and (tr.consumption_fuel_km == None or tr.consumption_fuel_km < 30): - trips.append(tr) - else: - logger.debug(f"trip discarded") - start = next_el - tr = Trip() - else: - tr.add_points(end["longitude"], end["latitude"]) - end = next_el - return trips - @staticmethod def get_chargings(min=None, max=None): conn = get_db() @@ -696,20 +589,19 @@ class MyPSACC: class MyPeugeotEncoder(JSONEncoder): def default(self, mp: MyPSACC): data = copy(mp.__dict__) - mpd = {} - mpd["proxies"] = data["_proxies"] - mpd["refresh_token"] = mp.manager.refresh_token - mpd["client_secret"] = mp.service_information.client_secret - for el in ["client_id", "realm", "remote_refresh_token", "customer_id","weather_api"]: + mpd = {"proxies": data["_proxies"], "refresh_token": mp.manager.refresh_token, + "client_secret": mp.service_information.client_secret} + for el in ["client_id", "realm", "remote_refresh_token", "customer_id", "weather_api", "country_code"]: mpd[el] = data[el] return mpd -#add method to class Energy -def get_energy(self,energy_type): +# add method to class Energy +def get_energy(self, energy_type): for energy in self._energy: if energy.type == energy_type: return energy return psac.models.energy.Energy(charging=psac.models.energy_charging.EnergyCharging()) + psac.models.status.Status.get_energy = get_energy diff --git a/Trip.py b/Trip.py index 05b94ca..528eca8 100644 --- a/Trip.py +++ b/Trip.py @@ -1,9 +1,12 @@ from typing import List -from dateutil.tz import tzlocal -from geojson import Feature, Point, FeatureCollection, MultiLineString -from geojson import dumps as geo_dumps +from geojson import Feature, FeatureCollection, MultiLineString +from Car import Cars +from MyLogger import logger +from web.db import get_db + +DEBUG = False class Points(): def __init__(self, latitude, longitude): @@ -14,15 +17,6 @@ class Points(): return self.latitude, self.longitude -class Trips(list): - def __init__(self, *args): - list.__init__(self, *args) - - def to_geo_json(self): - feature_collection = FeatureCollection(self) - return feature_collection - - class Trip: def __init__(self): self.start_at = None @@ -60,6 +54,135 @@ class Trip: "average consumption fuel": self.consumption_fuel_km}) def get_info(self): - res = {"start_at": self.start_at.astimezone(None).strftime("%x %X"), "end_at": self.end_at.astimezone(None).strftime("%x %X"), "duration": self.duration*60, - "speed_average": self.speed_average, "consumption_km": self.consumption_km, "consumption_fuel_km": self.consumption_fuel_km, "distance": self.distance, "mileage": self.mileage} + res = {"start_at": self.start_at.astimezone(None).strftime("%x %X"), + "end_at": self.end_at.astimezone(None).strftime("%x %X"), "duration": self.duration * 60, + "speed_average": self.speed_average, "consumption_km": self.consumption_km, + "consumption_fuel_km": self.consumption_fuel_km, "distance": self.distance, "mileage": self.mileage} return res + + +class Trips(list): + def __init__(self, *args): + list.__init__(self, *args) + + def to_geo_json(self): + feature_collection = FeatureCollection(self) + return feature_collection + + @staticmethod + def get_trips(vehicles_list: Cars) -> List[Trip]: + conn = get_db() + vehicles = conn.execute( + "SELECT DISTINCT vin FROM position;").fetchall() + for vin in vehicles: + vin = vin[0] # todo handle multiple vin + car = vehicles_list.get_car_by_vin(vin) + battery_capacity = car.battery_power + fuel_capacity = car.fuel_capacity + res = conn.execute('SELECT * FROM position ORDER BY Timestamp').fetchall() + trips = [] + if len(res) > 1: + start = res[0] + end = res[1] + tr = Trip() + # res = list(map(dict,res)) + for x in range(0, len(res) - 2): + if DEBUG: + logger.debug( + f"{res[x]['Timestamp']} mileage:{res[x]['mileage']} level:{res[x]['level']} level_fuel:{res[x]['level_fuel']}") + next_el = res[x + 2] + distance = end["mileage"] - start["mileage"] + duration = (end["Timestamp"] - start["Timestamp"]).total_seconds() / 3600 + try: + speed_average = distance / duration + except ZeroDivisionError: + speed_average = 0 + charge = end["level"] - start["level"] + if end["level_fuel"] is not None and start["level_fuel"] is not None: + refuel = end["level_fuel"] - start["level_fuel"] + else: + refuel = 0 + restart_trip = False + if refuel > 0: + restart_trip = True + logger.debug(f"refuel detected") + elif distance == 0 and charge > 2: + restart_trip = True + logger.debug(f"charge detected") + elif speed_average < 0.2 and duration > 0.05: # think again if duration is really needed + # end["mileage"] - start["mileage"] == 0 #or \ + # (end["Timestamp"] - start["Timestamp"]).total_seconds() / 3600 > 10: # condition useless ??? + restart_trip = True + logger.debug(f"low speed detected") + if restart_trip: + start = end + tr = Trip() + logger.debug(f"restart trip at {start['Timestamp']} {start['mileage']}km level:" + f"{start['level']} level_fuel:{start['level_fuel']}") + else: + distance = next_el["mileage"] - end["mileage"] # km + duration = (next_el["Timestamp"] - end["Timestamp"]).total_seconds() / 3600 + try: + speed_average = distance / duration + except ZeroDivisionError: + speed_average = 0 + charge = next_el["level"] - end["level"] + if next_el["level_fuel"] is not None and end["level_fuel"] is not None: + refuel = next_el["level_fuel"] - end["level_fuel"] + else: + refuel = 0 + end_trip = False + if refuel > 0: + end_trip = True + logger.debug(f"refuel detected") + elif distance == 0 and charge > 2: + end_trip = True + logger.debug(f"charge detected {charge}") + elif speed_average < 0.2 and duration > 0.05: + # (distance == 0 and duration > 0.08) or duration > 2 or + # check the speed to handle missing point + end_trip = True + logger.debug(f"low speed detected") + elif duration > 2: + end_trip = True + logger.debug(f"too much time detected") + elif x == len(res) - 3: # last record detected + # think if add point is needed + end = next_el + end_trip = True + logger.debug(f"last position found") + if end_trip: + logger.debug(f"stop trip at {end['Timestamp']} {end['mileage']}km level:{end['level']} " + f"level_fuel:{end['level_fuel']}") + tr.distance = end["mileage"] - start["mileage"] # km + if tr.distance > 0: + tr.start_at = start["Timestamp"] + tr.end_at = end["Timestamp"] + tr.add_points(end["longitude"], end["latitude"]) + tr.duration = (end["Timestamp"] - start["Timestamp"]).total_seconds() / 3600 + tr.speed_average = tr.distance / tr.duration + diff_level = start["level"] - end["level"] + tr.consumption = diff_level / 100 * battery_capacity # kw + tr.consumption_km = 100 * tr.consumption / tr.distance # kw/100 km + if start["level_fuel"] is not None and end["level_fuel"] is not None: + diff_level_fuel = start["level_fuel"] - end["level_fuel"] + tr.consumption_fuel = round(diff_level_fuel / 100 * fuel_capacity, 2) # L + tr.consumption_fuel_km = round(100 * tr.consumption_fuel / tr.distance, + 2) # L/100 km + tr.mileage = end["mileage"] + logger.debug( + f"Trip: {tr.start_at} -> {tr.end_at} {tr.distance:.1f}km {tr.duration:.2f}h {tr.speed_average:.0f}km/h " + f"{tr.consumption:.2f}kw {tr.consumption_km:.2f}kw/100km {tr.consumption_fuel}L {tr.consumption_fuel_km}L/100km " + f"{tr.mileage:.1f}km") + # filter bad value + if tr.consumption_km < 70 and ( + tr.consumption_fuel_km == None or tr.consumption_fuel_km < 30): + trips.append(tr) + else: + logger.debug(f"trip discarded") + start = next_el + tr = Trip() + else: + tr.add_points(end["longitude"], end["latitude"]) + end = next_el + return trips \ No newline at end of file diff --git a/server.py b/server.py index 662751b..7b25c2a 100755 --- a/server.py +++ b/server.py @@ -60,7 +60,7 @@ if __name__ == "__main__": client_email = input("mypeugeot email: ") client_password = input("mypeugeot password: ") web.app.myp.connect(client_email, client_password) - logger.info(web.app.myp.get_vehicles()) + logger.info(str(web.app.myp.get_vehicles())) if args.offline or args.remote_disable: logger.info("mqtt disabled") else: diff --git a/web/callback.py b/web/callback.py index d86e44e..eb426e3 100644 --- a/web/callback.py +++ b/web/callback.py @@ -10,6 +10,7 @@ from MyLogger import logger from flask import jsonify, request, Response as FlaskResponse from MyPSACC import MyPSACC +from Trip import Trips from web import figures from web.app import app, dash_app, myp, chc @@ -114,16 +115,11 @@ def update_trips(): global trips, chargings logger.info("update_data") try: - if myp.vehicles_list == None: # mandatory for offline mode right now - trips = MyPSACC.get_trips() - else: - vehicle_model = list(myp.vehicles_list.values())[0]['label'] # workaround here as vin is not managed yet in the dashboard - trips = MyPSACC.get_trips(vehicle_model) + trips = Trips.get_trips(myp.vehicles_list) chargings = MyPSACC.get_chargings() except: logger.error("update_trips: " + traceback.format_exc()) - try: web.db.callback_fct = update_trips update_trips() diff --git a/web/db.py b/web/db.py index c9f3e34..f877e98 100644 --- a/web/db.py +++ b/web/db.py @@ -23,14 +23,6 @@ def get_db(db_file=default_db_file): conn.execute("ALTER TABLE position ADD level_fuel INTEGER;") except: pass - try: - conn.execute("ALTER TABLE position ADD moving BOOLEAN;") - except: - pass - try: - conn.execute("ALTER TABLE position ADD temperature INTEGER;") - except: - pass conn.execute("CREATE TABLE IF NOT EXISTS battery (start_at DATETIME PRIMARY KEY,stop_at DATETIME,VIN TEXT, " "start_level INTEGER, end_level INTEGER, co2 INTEGER, kw INTEGER);") conn.create_function("update_trips", 0, update_callback)