Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/ci #628

Merged
merged 6 commits into from
Oct 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,27 @@ on:
workflow_dispatch:
jobs:
test:
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
steps:
- name: Set up python
id: setup-python
uses: actions/setup-python@v2
with:
python-version: 3.7
- name: Install Poetry
uses: snok/install-poetry@v1
with:
virtualenvs-in-project: true
- uses: actions/checkout@v2
- name: Load cached venv
id: cached-poetry-dependencies
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: .venv
key: venv-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/poetry.lock') }}
- name: Install dependencies
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
run: poetry install --no-interaction --no-root
run: |
python -m pip install --upgrade pip
pip install poetry
sudo apt-get install libblas3 liblapack3 liblapack-dev libblas-dev gfortran libatlas-base-dev
poetry config --local virtualenvs.in-project true
poetry install --no-interaction
- name: check quality
run: |
source .venv/bin/activate
Expand Down
12 changes: 5 additions & 7 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
default_language_version:
python: python3.7
repos:
- repo: https://github.com/pre-commit/mirrors-autopep8
rev: 'v1.6.0' # Use the sha / tag you want to point at
rev: 'v2.0.4' # Use the sha / tag you want to point at
language: system
hooks:
- id: autopep8
language: system
args:
- "--exit-code 0"
- repo: https://github.com/PyCQA/prospector
rev: 1.7.7 # The version of Prospector to use, if not 'master' for latest
rev: v1.10.3 # The version of Prospector to use, if not 'master' for latest
hooks:
- id: prospector
language: system
language: system

5 changes: 4 additions & 1 deletion .prospector.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
doc-warnings: false
max-line-length: 120
autodetect: false
uses:
- flask
ignore-paths:
- tests
- connected_car_api
- psa_car_controller/psa/connected_car_api
pycodestyle:
disable:
- E722
Expand Down
5 changes: 4 additions & 1 deletion config.ini
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
[General]
currency = €
# define format for data export, can be csv or xlsx
export_format = csv
# minimum trip length in km so it's added to stats and map in website
minimum trip length = 10

# for future use
length unit = km
export format = csv
[Electricity config]
# price by kw/h
day price = 0.15
Expand Down
3 changes: 1 addition & 2 deletions psa_car_controller/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import sys

if sys.version_info[:2] >= (3, 8):
if sys.version_info >= (3, 8):
from importlib import metadata
else:
import importlib_metadata as metadata
Expand Down
6 changes: 4 additions & 2 deletions psa_car_controller/common/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from typing import List

import requests
TIMEOUT_IN_S = 10


def rate_limit(limit, every):
Expand All @@ -16,7 +17,7 @@ def wrapper(*args, **kwargs):
return func(*args, **kwargs)
finally: # don't catch but ensure semaphore release
timer = Timer(every, semaphore.release)
timer.setDaemon(True)
timer.daemon = True
timer.start()
else:
raise RateLimitException
Expand Down Expand Up @@ -56,5 +57,6 @@ def get_positions(locations):
locations_str += str(line[latitude]) + "," + str(line[longitude]) + "|"
locations_str = locations_str[:-1]
res = requests.get("https://api.opentopodata.org/v1/srtm30m",
params={"locations": locations_str})
params={"locations": locations_str},
timeout=TIMEOUT_IN_S)
return res.json()["results"]
2 changes: 1 addition & 1 deletion psa_car_controller/psa/RemoteClient.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ def __keep_mqtt(self): # avoid token expiration
except RateLimitException:
logger.exception("__keep_mqtt")
t = threading.Timer(timeout, self.__keep_mqtt)
t.setDaemon(True)
t.daemon = True
t.start()

def veh_charge_request(self, vin, hour, minute, charge_type):
Expand Down
6 changes: 2 additions & 4 deletions psa_car_controller/psa/oauth.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,8 @@ def __init__(self, service_information: ServiceInformation, proxies: Optional[di
self.refresh_callbacks = []

def _grant_password_request_realm(self, login: str, password: str, realm: str) -> dict:
return dict(grant_type='password',
username=login,
scope=' '.join(self.service_information.scopes),
password=password, realm=realm)
return {"grant_type": 'password', "username": login, "scope": ' '.join(self.service_information.scopes),
"password": password, "realm": realm}

def init_with_user_credentials_realm(self, login: str, password: str, realm: str):
self._token_request(self._grant_password_request_realm(login, password, realm), True)
Expand Down
5 changes: 4 additions & 1 deletion psa_car_controller/psa/otp/otp.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

# pylint: disable=invalid-name
CONFIG_NAME = "otp.bin"
TIMEOUT_IN_S = 10

logger = logging.getLogger(__name__)


Expand Down Expand Up @@ -161,7 +163,8 @@ def request(self, param, setup=False):
},
params=param,
proxies=self.proxies,
verify=self.proxies is None
verify=self.proxies is None,
timeout=TIMEOUT_IN_S
).text
try:
raw_xml = raw_xml[raw_xml.index("?>") + 2:]
Expand Down
11 changes: 7 additions & 4 deletions psa_car_controller/psa/setup/app_decoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
APP_VERSION = "1.33.0"
GITHUB_USER = "flobz"
GITHUB_REPO = "psa_apk"
TIMEOUT_IN_S = 10


def get_content_from_apk(filename: str, country_code: str) -> ApkParser:
Expand All @@ -42,7 +43,8 @@ def firstLaunchConfig(package_name, client_email, client_password, country_code,
"fields": {"USR_EMAIL": {"value": client_email},
"USR_PASSWORD": {"value": client_password}}
}
)}
)},
timeout=TIMEOUT_IN_S
)

token = res.json()["accessToken"]
Expand All @@ -54,7 +56,7 @@ def firstLaunchConfig(package_name, client_email, client_password, country_code,
except BaseException:
pass
logger.error(msg)
raise Exception(msg) from ex
raise ConnectionError(msg) from ex
try:
res2 = requests.post(
f"https://mw-{BRAND[package_name]['brand_code'].lower()}-m2c.mym.awsmpsa.com/api/v1/user",
Expand All @@ -73,6 +75,7 @@ def firstLaunchConfig(package_name, client_email, client_password, country_code,
"Version": APP_VERSION
},
cert=("certs/public.pem", "certs/private.pem"),
timeout=TIMEOUT_IN_S
)

res_dict = res2.json()["success"]
Expand All @@ -84,7 +87,7 @@ def firstLaunchConfig(package_name, client_email, client_password, country_code,
except BaseException:
pass
logger.error(msg)
raise Exception(msg) from ex
raise ConnectionError(msg) from ex
# Psacc
psacc = PSAClient(None, apk_parser.client_id, apk_parser.client_secret,
None, customer_id, BRAND[package_name]["realm"],
Expand All @@ -94,7 +97,7 @@ def firstLaunchConfig(package_name, client_email, client_password, country_code,
res = psacc.get_vehicles()

if len(res) == 0:
Exception("No vehicle in your account is compatible with this API, you vehicle is probably too old...")
raise ValueError("No vehicle in your account is compatible with this API, you vehicle is probably too old...")

for vehicle in res_dict["vehicles"]:
car = psacc.vehicles_list.get_car_by_vin(vehicle["vin"])
Expand Down
14 changes: 9 additions & 5 deletions psa_car_controller/psa/setup/github.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
import requests

logger = logging.getLogger(__name__)
TIMEOUT_IN_S = 10


def get_github_sha_from_file(user, repo, directory, filename):
res = requests.get("https://api.github.com/repos/{}/{}/git/trees/main:{}".format(user, repo, directory)).json()
res = requests.get("https://api.github.com/repos/{}/{}/git/trees/main:{}".format(user, repo, directory),
timeout=TIMEOUT_IN_S).json()
try:
file_info = next((file for file in res["tree"] if file['path'] == filename))
except KeyError as e:
Expand Down Expand Up @@ -36,12 +38,14 @@ def github_file_need_to_be_downloaded(user, repo, directory, filename):
def urlretrieve_from_github(user, repo, directory, filename, branch="main"):
if github_file_need_to_be_downloaded(user, repo, directory, filename):
with open(filename, 'wb') as f:
r = requests.get("https://github.com/{}/{}/raw/{}/{}{}".format(user, repo, branch, directory, filename),
url = "https://github.com/{}/{}/raw/{}/{}{}".format(user, repo, branch, directory, filename)
r = requests.get(url,
headers={
"Accept": "application/vnd.github.VERSION.raw"
},
stream=True
)
},
stream=True,
timeout=TIMEOUT_IN_S
)

r.raise_for_status()
for chunk in r.iter_content(1024):
Expand Down
3 changes: 2 additions & 1 deletion psa_car_controller/psacc/application/abrp.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from psa_car_controller.psacc.model.car import Car

logger = logging.getLogger(__name__)
TIMEOUT_IN_S = 10


class Abrp:
Expand Down Expand Up @@ -47,7 +48,7 @@ def call(self, car: Car, ext_temp: float = None):
tlm["ext_temp"] = ext_temp
params = {"tlm": json.dumps(tlm), "token": self.token, "api_key": self.api_key}
response = requests.request("POST", self.url, params=params, proxies=self.proxies,
verify=self.proxies is None)
verify=self.proxies is None, timeout=TIMEOUT_IN_S)
logger.debug(response.text)
try:
return json.loads(response.text)["status"] == "ok"
Expand Down
10 changes: 8 additions & 2 deletions psa_car_controller/psacc/application/battery_charge_curve.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
from psa_car_controller.psacc.model.charge import Charge
from psa_car_controller.psacc.repository.db import Database

DEFAULT_KM_BY_KW = 5.3
MINIMUM_AUTONOMY_FOR_GOOD_RESULT = 20


class BatteryChargeCurve:
def __init__(self, level, speed):
Expand All @@ -23,7 +26,10 @@ def dto_to_battery_curve(car: Car, charge: Charge, battery_curves_dto: List[Batt
battery_curves = []
if len(battery_curves_dto) > 0 and battery_curves_dto[-1].level > 0 and battery_curves_dto[-1].autonomy > 0:
battery_capacity = battery_curves_dto[-1].level * car.battery_power / 100
km_by_kw = 0.8 * battery_curves_dto[-1].autonomy / battery_capacity
if battery_curves_dto[-1].autonomy > MINIMUM_AUTONOMY_FOR_GOOD_RESULT:
km_by_kw = 0.8 * battery_curves_dto[-1].autonomy / battery_capacity
else:
km_by_kw = DEFAULT_KM_BY_KW
start = 0
speeds = []

Expand Down Expand Up @@ -51,7 +57,7 @@ def speed_in_kw_from_km(battery_curve_dto):
start = end
speeds = []
battery_curves.append(BatteryChargeCurve(charge.end_level, 0))
elif charge.end_level and charge.start_level:
elif charge.end_level and charge.start_level is not None:
speed = car.get_charge_speed(charge.end_level - charge.start_level, (stop_at - start_date).total_seconds())
battery_curves.append(BatteryChargeCurve(charge.start_level, speed))
battery_curves.append(BatteryChargeCurve(charge.end_level, speed))
Expand Down
10 changes: 9 additions & 1 deletion psa_car_controller/psacc/application/car_controller.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import argparse
import atexit
import logging
import socket
import threading
from os import environ, path

Expand Down Expand Up @@ -65,10 +66,14 @@ def start_remote_control(self):
self.chc = ChargeControls.load_config(self.myp, name=self.args.charge_control)
self.chc.init()
self.myp.start_refresh_thread()
except socket.timeout:
logger.error("Can't connect to mqtt broker your are not connected to internet or PSA MQTT server is "
"down !")
except ConfigException:
logger.error("start_remote_control failed redo otp config")

def load_app(self) -> bool:
# pylint: disable=too-many-branches
my_logger(handler_level=int(self.args.debug))
if self.args.config:
self.config_name = self.args.config
Expand Down Expand Up @@ -99,7 +104,10 @@ def load_app(self) -> bool:
self.is_good = True
else:
self.is_good = False
logger.error("Please reconnect by going to config web page")
if self.args.web_conf:
logger.error("Please reconnect by going to config web page")
else:
logger.error("Connection need to be updated, Please redo authentication process.")
if self.args.refresh:
self.myp.info_refresh_rate = self.args.refresh * 60
if self.is_good:
Expand Down
2 changes: 1 addition & 1 deletion psa_car_controller/psacc/application/charge_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def process(self):
if next_in_second < self.psacc.info_refresh_rate:
periodicity = next_in_second
thread = threading.Timer(periodicity, self.process)
thread.setDaemon(True)
thread.daemon = True
thread.start()
elif status == STOPPED and has_threshold and hit_threshold and self.__is_approaching_scheduled_time(now):
logger.info("Approaching scheduled charging time, but should not charge. Postponing charge hour!")
Expand Down
8 changes: 5 additions & 3 deletions psa_car_controller/psacc/application/ecomix.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

CO2_SIGNAL_REQ_INTERVAL = 600
CO2_SIGNAL_URL = "https://api.co2signal.com"

TIMEOUT_IN_S = 10
logger = logging.getLogger(__name__)


Expand All @@ -31,7 +31,8 @@ def get_data_france(start, end) -> Union[float, None]:
headers={
"Origin": "https://www.rte-france.com",
"Referer": "https://www.rte-france.com/eco2mix/les-emissions-de-co2-par-kwh-produit-en-france",
}
},
timeout=TIMEOUT_IN_S
)
except RequestException:
logger.exception("get_data_france: ")
Expand Down Expand Up @@ -71,7 +72,8 @@ def get_data_from_co2_signal(latitude, longitude, country_code_default):
return False
res = requests.get(CO2_SIGNAL_URL + "/v1/latest",
headers={"auth-token": Ecomix.co2_signal_key},
params={"countryCode": country_code})
params={"countryCode": country_code},
timeout=TIMEOUT_IN_S)
data = res.json()
value = data["data"]["carbonIntensity"]
assert isinstance(value, numbers.Number)
Expand Down
6 changes: 3 additions & 3 deletions psa_car_controller/psacc/application/psa_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def api(self) -> VehiclesApi:

def set_proxies(self, proxies):
if proxies is None:
proxies = dict(http='', https='')
proxies = {"http": '', "https": ''}
self.api_config.proxy = None
else:
self.api_config.proxy = proxies['http']
Expand Down Expand Up @@ -117,7 +117,7 @@ def __refresh_vehicle_info(self):
if self.refresh_thread and self.refresh_thread.is_alive():
logger.debug("refresh_vehicle_info: precedent task still alive")
self.refresh_thread = threading.Timer(self.info_refresh_rate, self.__refresh_vehicle_info)
self.refresh_thread.setDaemon(True)
self.refresh_thread.daemon = True
self.refresh_thread.start()
try:
logger.debug("refresh_vehicle_info")
Expand Down Expand Up @@ -162,7 +162,7 @@ def save_config(self, name=None, force=False):
def load_config(name="config.json"):
with open(name, "r", encoding="utf-8") as f:
config_str = f.read()
config = dict(**json.loads(config_str))
config = {**json.loads(config_str)}
if "country_code" not in config:
config["country_code"] = input("What is your country code ? (ex: FR, GB, DE, ES...)\n")
for new_el in ["abrp", "co2_signal_api"]:
Expand Down
Loading
Loading