mirror of
https://github.com/flobz/psa_car_controller.git
synced 2026-08-26 10:17:18 +00:00
@@ -3,7 +3,7 @@ import logging
|
||||
import threading
|
||||
from datetime import datetime
|
||||
from os import environ
|
||||
from time import sleep
|
||||
import time
|
||||
|
||||
import paho.mqtt.client as mqtt
|
||||
from requests import RequestException
|
||||
@@ -82,19 +82,22 @@ class RemoteClient:
|
||||
elif msg.topic.startswith(MQTT_EVENT_TOPIC):
|
||||
charge_info = data["charging_state"]
|
||||
self.precond_programs[data["vin"]] = data["precond_state"]["programs"]
|
||||
if charge_info is not None and charge_info['remaining_time'] != 0:
|
||||
try:
|
||||
car = self.vehicles_list.get_car_by_vin(vin=msg.topic.split("/")[-1])
|
||||
if car and car.status.get_energy('Electric').charging.status != INPROGRESS:
|
||||
# fix a psa server bug where charge beginning without status api being properly updated
|
||||
logger.warning("charge begin but API isn't updated")
|
||||
sleep(60)
|
||||
self.wakeup(data["vin"])
|
||||
except (IndexError, AttributeError, RateLimitException):
|
||||
logger.exception("on_mqtt_message:")
|
||||
self._fix_not_updated_api(charge_info, data["vin"])
|
||||
except KeyError:
|
||||
logger.exception("on_mqtt_message:")
|
||||
|
||||
def _fix_not_updated_api(self, charge_info, vin):
|
||||
if charge_info is not None and charge_info['remaining_time'] != 0:
|
||||
try:
|
||||
car = self.vehicles_list.get_car_by_vin(vin=vin)
|
||||
if car and car.status.get_energy('Electric').charging.status != INPROGRESS:
|
||||
# fix a psa server bug where charge beginning without status api being properly updated
|
||||
logger.warning("charge begin but API isn't updated")
|
||||
time.sleep(60)
|
||||
self.wakeup(vin)
|
||||
except (IndexError, AttributeError, RateLimitException):
|
||||
logger.exception("on_mqtt_message:")
|
||||
|
||||
def start(self):
|
||||
if self.load_otp():
|
||||
self.mqtt_client = mqtt.Client(clean_session=True, protocol=mqtt.MQTTv311)
|
||||
@@ -172,7 +175,7 @@ class RemoteClient:
|
||||
return True
|
||||
except (RequestException, RateLimitException) as e:
|
||||
logger.exception("Can't refresh remote token %s", e)
|
||||
sleep(60)
|
||||
time.sleep(60)
|
||||
return False
|
||||
|
||||
def get_sms_otp_code(self):
|
||||
@@ -204,7 +207,7 @@ class RemoteClient:
|
||||
return res
|
||||
except RequestException as e:
|
||||
logger.error("Can't refresh remote token %s", e)
|
||||
sleep(60)
|
||||
time.sleep(60)
|
||||
return None
|
||||
|
||||
def horn(self, vin, count):
|
||||
|
||||
@@ -18,7 +18,7 @@ class CarModelRepository(metaclass=Singleton):
|
||||
yaml = ruamel.yaml.YAML()
|
||||
yaml.register_class(ElecModel)
|
||||
yaml.register_class(CarModel)
|
||||
self.models: List = yaml.load(models)
|
||||
self.models: List[CarModel] = yaml.load(models)
|
||||
|
||||
def find_model_by_vin(self, vin) -> CarModel:
|
||||
if vin != "vin":
|
||||
|
||||
@@ -3,14 +3,13 @@ from typing import Dict
|
||||
|
||||
from geojson import FeatureCollection
|
||||
|
||||
from psa_car_controller.common.mylogger import logger
|
||||
from psa_car_controller.psacc.application.trip_parser import TripParser
|
||||
|
||||
from psa_car_controller.psacc.model.trip import Trip
|
||||
from psa_car_controller.psacc.model.car import Cars
|
||||
from psa_car_controller.psacc.repository.db import Database
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Trips(list):
|
||||
def __init__(self, *args):
|
||||
@@ -47,8 +46,8 @@ class Trips(list):
|
||||
trips = Trips()
|
||||
vin = vin[0]
|
||||
res = conn.execute('SELECT Timestamp, VIN, longitude, latitude, mileage, level, moving, temperature, '
|
||||
'level_fuel, altitude FROM position WHERE VIN=? AND mileage NOT NULL ORDER BY Timestamp',
|
||||
(vin,)).fetchall()
|
||||
'level_fuel, altitude FROM position WHERE VIN=? '
|
||||
'AND mileage IS NOT NULL ORDER BY Timestamp', (vin,)).fetchall()
|
||||
if len(res) > 1:
|
||||
car = vehicles_list.get_car_by_vin(vin)
|
||||
assert car is not None
|
||||
|
||||
@@ -42,6 +42,7 @@ prospector = ">=1.3.0"
|
||||
pre-commit = "^2.17.0"
|
||||
coverage = "^6.3.2"
|
||||
deepdiff = "^5.7.0"
|
||||
greenery = "^3.3.5"
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core>=1.0.0"]
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import unittest
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from psa_car_controller.psa.RemoteClient import RemoteClient
|
||||
from psa_car_controller.psa.connected_car_api import Vehicles, ApiClient
|
||||
from psa_car_controller.psa.constants import DISCONNECTED
|
||||
from psa_car_controller.psacc.model.car import Car
|
||||
from tests.data.car_status import ELECTRIC_CAR_STATUS
|
||||
|
||||
|
||||
class TestUnit(unittest.TestCase):
|
||||
|
||||
def get_rc(self) -> RemoteClient:
|
||||
account_info = MagicMock()
|
||||
account_info.realm = ""
|
||||
return RemoteClient(account_info, Vehicles, None, None)
|
||||
|
||||
@patch('time.sleep', return_value=None)
|
||||
def test_fix_not_updated_api(self, patched_time_sleep):
|
||||
# GIVEN
|
||||
remote_client = self.get_rc()
|
||||
vin = "myvin"
|
||||
car = Car("a", "b", "c")
|
||||
car.status = ApiClient()._ApiClient__deserialize(ELECTRIC_CAR_STATUS, "Status")
|
||||
car.status.get_energy('Electric').charging.status = DISCONNECTED
|
||||
remote_client.vehicles_list.get_car_by_vin = MagicMock(return_value=car)
|
||||
remote_client.wakeup = MagicMock()
|
||||
# WHEN
|
||||
remote_client._fix_not_updated_api({'remaining_time': 1}, vin)
|
||||
# THEN
|
||||
remote_client.wakeup.assert_called_once_with(vin)
|
||||
@@ -7,6 +7,7 @@ from unittest.mock import MagicMock, patch
|
||||
|
||||
import reverse_geocode
|
||||
from dateutil.tz import tzutc
|
||||
from greenery.lego import parse, charclass
|
||||
from pytz import UTC
|
||||
|
||||
from psa_car_controller import psa
|
||||
@@ -302,6 +303,15 @@ class TestUnit(unittest.TestCase):
|
||||
f.write(" ")
|
||||
assert github_file_need_to_be_downloaded(GITHUB_USER, GITHUB_REPO, "", filename) is True
|
||||
|
||||
def test_regex(self):
|
||||
car_models = CarModelRepository().models
|
||||
for x in range(0, len(car_models)):
|
||||
for y in range(x + 1, len(car_models)):
|
||||
reg_a = car_models[x].reg
|
||||
reg_b = car_models[y].reg
|
||||
res: charclass = parse(reg_a) & parse(reg_b)
|
||||
self.assertTrue(res.empty(), msg=f"{reg_a} and {reg_b} can match the same string")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
my_logger(handler_level=os.environ.get("DEBUG_LEVEL", 20))
|
||||
|
||||
Reference in New Issue
Block a user