mirror of
https://github.com/Dielee/volvo2mqtt.git
synced 2026-07-22 02:13:01 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
37e663620b | ||
|
|
6021a57e6b | ||
|
|
e85b2ef31e | ||
|
|
8f210c9fd7 | ||
|
|
701551e7e4 | ||
|
|
01c7ef46d5 | ||
|
|
e6861ab872 |
@@ -73,6 +73,22 @@ Please let me know if your car works with this addon so I can expand the list!<b
|
|||||||
|
|
||||||
NOTE: Energy status currently available only for cars in the Europe / Middle East / Africa regions. [source](https://developer.volvocars.com/apis/energy/v1/overview/#availability)
|
NOTE: Energy status currently available only for cars in the Europe / Middle East / Africa regions. [source](https://developer.volvocars.com/apis/energy/v1/overview/#availability)
|
||||||
|
|
||||||
|
## OTP Authentication
|
||||||
|
|
||||||
|
As of version <b>v1.9.0</b>, this addon uses the same OTP authentication as the Volvo app.
|
||||||
|
The following steps are required for authentication in exactly this order:
|
||||||
|
|
||||||
|
1. Setup volvo2Mqtt, either via Docker, or via HA addon (take a look at the "Setup" section below)
|
||||||
|
2. Fill in your settings and start volvo2Mqtt
|
||||||
|
3. Your log will show the following lines <br>
|
||||||
|
```Waiting for otp code... Please check your mailbox and post your otp code to the following mqtt topic "volvoAAOS2mqtt/otp_code". Retry 0/15```<br>
|
||||||
|
```Waiting for otp code... Please check your mailbox and post your otp code to the following mqtt topic "volvoAAOS2mqtt/otp_code". Retry 1/15```<br>
|
||||||
|
```etc ...```
|
||||||
|
4. Now, open your mailbox and copy your OTP Code
|
||||||
|
5. Open HomeAssistant and search for the entity ID ```text.volvo_otp```
|
||||||
|
6. Paste your OTP into the text entity and press Enter
|
||||||
|
7. If everything has worked, your addon is now authenticated. In the future, OTP authentication only needs to be done when updating, not when restarting the container.
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
<b>Docker:</b>
|
<b>Docker:</b>
|
||||||
|
|
||||||
@@ -106,7 +122,6 @@ Here is what every option means:
|
|||||||
| `TZ` | `string` | | **required** | Container timezone eg "Europe/Berlin" from [here](https://docs.diladele.com/docker/timezones.html)|
|
| `TZ` | `string` | | **required** | Container timezone eg "Europe/Berlin" from [here](https://docs.diladele.com/docker/timezones.html)|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg
|
[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg
|
||||||
[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg
|
[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg
|
||||||
[armhf-shield]: https://img.shields.io/badge/armhf-yes-green.svg
|
[armhf-shield]: https://img.shields.io/badge/armhf-yes-green.svg
|
||||||
|
|||||||
+3
-2
@@ -1,5 +1,6 @@
|
|||||||
requests~=2.29.0
|
requests~=2.31.0
|
||||||
dynaconf~=3.1.12
|
dynaconf~=3.1.12
|
||||||
paho-mqtt~=1.6.1
|
paho-mqtt~=1.6.1
|
||||||
Babel~=2.12.1
|
Babel~=2.12.1
|
||||||
pytz~=2023.3
|
pytz~=2023.3
|
||||||
|
google_play_scraper~=1.2.6
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
name: "Volvo2Mqtt"
|
name: "Volvo2Mqtt"
|
||||||
description: "Volvo AAOS MQTT bridge"
|
description: "Volvo AAOS MQTT bridge"
|
||||||
version: "1.8.27"
|
version: "1.9.0"
|
||||||
slug: "volvo2mqtt"
|
slug: "volvo2mqtt"
|
||||||
init: false
|
init: false
|
||||||
url: "https://github.com/Dielee/volvo2mqtt"
|
url: "https://github.com/Dielee/volvo2mqtt"
|
||||||
|
|||||||
+5
-2
@@ -1,8 +1,9 @@
|
|||||||
from config import settings
|
from config import settings
|
||||||
|
|
||||||
VERSION = "v1.8.27"
|
VERSION = "v1.9.0"
|
||||||
|
|
||||||
OAUTH_URL = "https://volvoid.eu.volvocars.com/as/token.oauth2"
|
OAUTH_TOKEN_URL = "https://volvoid.eu.volvocars.com/as/token.oauth2"
|
||||||
|
OAUTH_AUTH_URL = "https://volvoid.eu.volvocars.com/as/authorization.oauth2"
|
||||||
VEHICLES_URL = "https://api.volvocars.com/connected-vehicle/v2/vehicles"
|
VEHICLES_URL = "https://api.volvocars.com/connected-vehicle/v2/vehicles"
|
||||||
VEHICLE_DETAILS_URL = "https://api.volvocars.com/connected-vehicle/v2/vehicles/{0}"
|
VEHICLE_DETAILS_URL = "https://api.volvocars.com/connected-vehicle/v2/vehicles/{0}"
|
||||||
WINDOWS_STATE_URL = "https://api.volvocars.com/connected-vehicle/v2/vehicles/{0}/windows"
|
WINDOWS_STATE_URL = "https://api.volvocars.com/connected-vehicle/v2/vehicles/{0}/windows"
|
||||||
@@ -137,3 +138,5 @@ supported_entities = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
old_entity_ids = ["months_to_service", "service_warning_trigger", "distance_to_empty"]
|
old_entity_ids = ["months_to_service", "service_warning_trigger", "distance_to_empty"]
|
||||||
|
otp_max_loops = 15
|
||||||
|
otp_mqtt_topic = "volvoAAOS2mqtt/otp_code"
|
||||||
+36
-8
@@ -10,7 +10,7 @@ from datetime import datetime
|
|||||||
from babel.dates import format_datetime
|
from babel.dates import format_datetime
|
||||||
from config import settings
|
from config import settings
|
||||||
from const import CLIMATE_START_URL, CLIMATE_STOP_URL, CAR_LOCK_URL, \
|
from const import CLIMATE_START_URL, CLIMATE_STOP_URL, CAR_LOCK_URL, \
|
||||||
CAR_UNLOCK_URL, availability_topic, icon_states, old_entity_ids
|
CAR_UNLOCK_URL, availability_topic, icon_states, old_entity_ids, otp_mqtt_topic
|
||||||
|
|
||||||
mqtt_client: mqtt.Client
|
mqtt_client: mqtt.Client
|
||||||
subscribed_topics = []
|
subscribed_topics = []
|
||||||
@@ -20,7 +20,7 @@ climate_timer = {}
|
|||||||
engine_status = {}
|
engine_status = {}
|
||||||
devices = {}
|
devices = {}
|
||||||
active_schedules = {}
|
active_schedules = {}
|
||||||
|
otp_code = None
|
||||||
|
|
||||||
def connect():
|
def connect():
|
||||||
client = mqtt.Client("volvoAAOS2mqtt") if os.environ.get("IS_HA_ADDON") \
|
client = mqtt.Client("volvoAAOS2mqtt") if os.environ.get("IS_HA_ADDON") \
|
||||||
@@ -37,6 +37,7 @@ def connect():
|
|||||||
port = settings["mqtt"]["port"]
|
port = settings["mqtt"]["port"]
|
||||||
client.connect(settings["mqtt"]["broker"], port)
|
client.connect(settings["mqtt"]["broker"], port)
|
||||||
client.loop_start()
|
client.loop_start()
|
||||||
|
client.subscribe("volvoAAOS2mqtt/otp_code")
|
||||||
client.on_message = on_message
|
client.on_message = on_message
|
||||||
client.on_disconnect = on_disconnect
|
client.on_disconnect = on_disconnect
|
||||||
client.on_connect = on_connect
|
client.on_connect = on_connect
|
||||||
@@ -45,6 +46,28 @@ def connect():
|
|||||||
mqtt_client = client
|
mqtt_client = client
|
||||||
|
|
||||||
|
|
||||||
|
def create_otp_input():
|
||||||
|
config = {
|
||||||
|
"name": "Volvo OTP",
|
||||||
|
"object_id": f"volvo_otp",
|
||||||
|
"schema": "state",
|
||||||
|
"command_topic": otp_mqtt_topic,
|
||||||
|
"unique_id": f"volvoAAOS2mqtt_otp",
|
||||||
|
"pattern": "\d{6}",
|
||||||
|
"icon": "mdi:two-factor-authentication"
|
||||||
|
}
|
||||||
|
|
||||||
|
mqtt_client.publish(
|
||||||
|
f"homeassistant/text/volvoAAOS2mqtt/volvo_otp/config",
|
||||||
|
json.dumps(config),
|
||||||
|
retain=True
|
||||||
|
)
|
||||||
|
|
||||||
|
def delete_otp_input():
|
||||||
|
topic = "homeassistant/text/volvoAAOS2mqtt/volvo_otp/config"
|
||||||
|
mqtt_client.publish(topic, payload="", retain=True)
|
||||||
|
|
||||||
|
|
||||||
def send_car_images(vin, data, device):
|
def send_car_images(vin, data, device):
|
||||||
if util.keys_exists(data, "images"):
|
if util.keys_exists(data, "images"):
|
||||||
for entity in [{"name": "Exterior Image", "id": "exterior_image"},
|
for entity in [{"name": "Exterior Image", "id": "exterior_image"},
|
||||||
@@ -94,13 +117,18 @@ def on_disconnect(client, userdata, rc):
|
|||||||
|
|
||||||
|
|
||||||
def on_message(client, userdata, msg):
|
def on_message(client, userdata, msg):
|
||||||
try:
|
|
||||||
vin = msg.topic.split('/')[2].split('_')[0]
|
|
||||||
except IndexError:
|
|
||||||
logging.error("Error - Cannot get vin from MQTT topic!")
|
|
||||||
return None
|
|
||||||
|
|
||||||
payload = msg.payload.decode("UTF-8")
|
payload = msg.payload.decode("UTF-8")
|
||||||
|
if msg.topic == otp_mqtt_topic:
|
||||||
|
global otp_code
|
||||||
|
otp_code = payload
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
vin = msg.topic.split('/')[2].split('_')[0]
|
||||||
|
except IndexError:
|
||||||
|
logging.error("Error - Cannot get vin from MQTT topic!")
|
||||||
|
return None
|
||||||
|
|
||||||
if "climate_status" in msg.topic:
|
if "climate_status" in msg.topic:
|
||||||
if payload == "ON":
|
if payload == "ON":
|
||||||
start_climate(vin)
|
start_climate(vin)
|
||||||
|
|||||||
+17
@@ -4,6 +4,8 @@ import os
|
|||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
import config
|
import config
|
||||||
|
import json
|
||||||
|
from google_play_scraper import app
|
||||||
from logging import handlers
|
from logging import handlers
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from const import units
|
from const import units
|
||||||
@@ -28,6 +30,21 @@ class SensitiveDataFilter(logging.Filter):
|
|||||||
record.msg = re.sub(pattern, "<REDACTED>", record.msg)
|
record.msg = re.sub(pattern, "<REDACTED>", record.msg)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def get_volvo_app_version():
|
||||||
|
result = app(
|
||||||
|
'se.volvo.vcc',
|
||||||
|
lang='en',
|
||||||
|
country='us'
|
||||||
|
)
|
||||||
|
|
||||||
|
if "version" in result:
|
||||||
|
return result["version"]
|
||||||
|
else:
|
||||||
|
return "5.37.0"
|
||||||
|
|
||||||
|
def save_to_json(data):
|
||||||
|
with open('.token', 'w', encoding='utf-8') as f:
|
||||||
|
json.dump(data, f, ensure_ascii=False, indent=4)
|
||||||
|
|
||||||
def get_icon_between(icon_list, state):
|
def get_icon_between(icon_list, state):
|
||||||
icon = None
|
icon = None
|
||||||
|
|||||||
+132
-27
@@ -1,18 +1,21 @@
|
|||||||
|
import json
|
||||||
import logging
|
import logging
|
||||||
import requests
|
import requests
|
||||||
import mqtt
|
import mqtt
|
||||||
import util
|
import util
|
||||||
import time
|
import time
|
||||||
import re
|
import re
|
||||||
|
import os.path
|
||||||
from threading import current_thread, Thread
|
from threading import current_thread, Thread
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from config import settings
|
from config import settings
|
||||||
from babel.dates import format_datetime
|
from babel.dates import format_datetime
|
||||||
from json import JSONDecodeError
|
from json import JSONDecodeError
|
||||||
from const import charging_system_states, charging_connection_states, door_states, window_states, \
|
from const import charging_system_states, charging_connection_states, door_states, window_states, \
|
||||||
OAUTH_URL, VEHICLES_URL, VEHICLE_DETAILS_URL, RECHARGE_STATE_URL, CLIMATE_START_URL, \
|
OAUTH_AUTH_URL, OAUTH_TOKEN_URL, VEHICLES_URL, VEHICLE_DETAILS_URL, RECHARGE_STATE_URL, CLIMATE_START_URL, \
|
||||||
WINDOWS_STATE_URL, LOCK_STATE_URL, TYRE_STATE_URL, supported_entities, FUEL_BATTERY_STATE_URL, \
|
WINDOWS_STATE_URL, LOCK_STATE_URL, TYRE_STATE_URL, supported_entities, FUEL_BATTERY_STATE_URL, \
|
||||||
STATISTICS_URL, ENGINE_DIAGNOSTICS_URL, VEHICLE_DIAGNOSTICS_URL, API_BACKEND_STATUS, WARNINGS_URL, engine_states
|
STATISTICS_URL, ENGINE_DIAGNOSTICS_URL, VEHICLE_DIAGNOSTICS_URL, API_BACKEND_STATUS, WARNINGS_URL, engine_states, \
|
||||||
|
otp_max_loops
|
||||||
|
|
||||||
session = requests.Session()
|
session = requests.Session()
|
||||||
session.headers = {
|
session.headers = {
|
||||||
@@ -30,37 +33,136 @@ vcc_api_keys = []
|
|||||||
backend_status = ""
|
backend_status = ""
|
||||||
|
|
||||||
|
|
||||||
def authorize():
|
def authorize(renew_tokenfile=False):
|
||||||
headers = {
|
global refresh_token
|
||||||
"authorization": "Basic aDRZZjBiOlU4WWtTYlZsNnh3c2c1WVFxWmZyZ1ZtSWFEcGhPc3kxUENhVXNpY1F0bzNUUjVrd2FKc2U0QVpkZ2ZJZmNMeXc=",
|
if os.path.isfile(".token") and not renew_tokenfile:
|
||||||
"content-type": "application/x-www-form-urlencoded",
|
logging.info("Using login from token file")
|
||||||
"accept": "application/json"
|
f = open('.token')
|
||||||
}
|
data = json.load(f)
|
||||||
|
|
||||||
body = {
|
|
||||||
"username": settings.volvoData["username"],
|
|
||||||
"password": settings.volvoData["password"],
|
|
||||||
"grant_type": "password",
|
|
||||||
"scope": "openid email profile care_by_volvo:financial_information:invoice:read care_by_volvo:financial_information:payment_method care_by_volvo:subscription:read customer:attributes customer:attributes:write order:attributes vehicle:attributes tsp_customer_api:all conve:brake_status conve:climatization_start_stop conve:command_accessibility conve:commands conve:diagnostics_engine_status conve:diagnostics_workshop conve:doors_status conve:engine_status conve:environment conve:fuel_status conve:honk_flash conve:lock conve:lock_status conve:navigation conve:odometer_status conve:trip_statistics conve:tyre_status conve:unlock conve:vehicle_relation conve:warnings conve:windows_status energy:battery_charge_level energy:charging_connection_status energy:charging_system_status energy:electric_range energy:estimated_charging_time energy:recharge_status vehicle:attributes"
|
|
||||||
}
|
|
||||||
auth = requests.post(OAUTH_URL, data=body, headers=headers)
|
|
||||||
if auth.status_code == 200:
|
|
||||||
data = auth.json()
|
|
||||||
session.headers.update({"authorization": "Bearer " + data["access_token"]})
|
|
||||||
|
|
||||||
global token_expires_at, refresh_token
|
|
||||||
token_expires_at = datetime.now(util.TZ) + timedelta(seconds=(data["expires_in"] - 30))
|
|
||||||
refresh_token = data["refresh_token"]
|
refresh_token = data["refresh_token"]
|
||||||
|
refresh_auth()
|
||||||
|
else:
|
||||||
|
logging.info("Starting login with OTP")
|
||||||
|
auth_session = requests.session()
|
||||||
|
auth_session.headers = {
|
||||||
|
"authorization": "Basic aDRZZjBiOlU4WWtTYlZsNnh3c2c1WVFxWmZyZ1ZtSWFEcGhPc3kxUENhVXNpY1F0bzNUUjVrd2FKc2U0QVpkZ2ZJZmNMeXc=",
|
||||||
|
"User-Agent": "vca-android/" + util.get_volvo_app_version(),
|
||||||
|
"Accept-Encoding": "gzip",
|
||||||
|
"Content-Type": "application/json; charset=utf-8"
|
||||||
|
}
|
||||||
|
|
||||||
get_vcc_api_keys()
|
url_params = ("?client_id=h4Yf0b"
|
||||||
get_vehicles()
|
"&response_type=code"
|
||||||
check_supported_endpoints()
|
"&acr_values=urn:volvoid:aal:bronze:2sv"
|
||||||
Thread(target=backend_status_loop).start()
|
"&response_mode=pi.flow"
|
||||||
|
"&scope=openid email profile care_by_volvo:financial_information:invoice:read care_by_volvo:financial_information:payment_method care_by_volvo:subscription:read customer:attributes customer:attributes:write order:attributes vehicle:attributes tsp_customer_api:all conve:brake_status conve:climatization_start_stop conve:command_accessibility conve:commands conve:diagnostics_engine_status conve:diagnostics_workshop conve:doors_status conve:engine_status conve:environment conve:fuel_status conve:honk_flash conve:lock conve:lock_status conve:navigation conve:odometer_status conve:trip_statistics conve:tyre_status conve:unlock conve:vehicle_relation conve:warnings conve:windows_status energy:battery_charge_level energy:charging_connection_status energy:charging_system_status energy:electric_range energy:estimated_charging_time energy:recharge_status vehicle:attributes")
|
||||||
|
|
||||||
|
auth = auth_session.get(OAUTH_AUTH_URL + url_params)
|
||||||
|
if auth.status_code == 200:
|
||||||
|
response = auth.json()
|
||||||
|
auth_state = response["status"]
|
||||||
|
|
||||||
|
if auth_state == "USERNAME_PASSWORD_REQUIRED":
|
||||||
|
auth_session.headers.update({"x-xsrf-header": "PingFederate"})
|
||||||
|
response = check_username_password(auth_session, response)
|
||||||
|
auth_state = response["status"]
|
||||||
|
|
||||||
|
if auth_state == "OTP_REQUIRED":
|
||||||
|
response = send_otp(auth_session, response)
|
||||||
|
response = continue_auth(auth_session, response)
|
||||||
|
token_data = get_token(auth_session, response)
|
||||||
|
else:
|
||||||
|
raise Exception("Unkown auth state " + auth_state)
|
||||||
|
elif auth_state == "OTP_REQUIRED":
|
||||||
|
response = send_otp(auth_session, response)
|
||||||
|
response = continue_auth(auth_session, response)
|
||||||
|
token_data = get_token(auth_session, response)
|
||||||
|
elif auth_state == "OTP_VERIFIED":
|
||||||
|
response = continue_auth(auth_session, response)
|
||||||
|
token_data = get_token(auth_session, response)
|
||||||
|
elif auth_state == "COMPLETED":
|
||||||
|
token_data = get_token(auth_session, response)
|
||||||
|
else:
|
||||||
|
raise Exception("Unkown auth state " + auth_state)
|
||||||
|
|
||||||
|
session.headers.update({"authorization": "Bearer " + token_data["access_token"]})
|
||||||
|
|
||||||
|
global token_expires_at
|
||||||
|
token_expires_at = datetime.now(util.TZ) + timedelta(seconds=(token_data["expires_in"] - 30))
|
||||||
|
refresh_token = token_data["refresh_token"]
|
||||||
|
|
||||||
|
util.save_to_json(token_data)
|
||||||
|
else:
|
||||||
|
message = auth.json()
|
||||||
|
raise Exception(message["details"][0]["userMessage"])
|
||||||
|
|
||||||
|
get_vcc_api_keys()
|
||||||
|
get_vehicles()
|
||||||
|
check_supported_endpoints()
|
||||||
|
Thread(target=backend_status_loop).start()
|
||||||
|
|
||||||
|
def continue_auth(auth_session, data):
|
||||||
|
next_url = data["_links"]["continueAuthentication"]["href"] + "?action=continueAuthentication"
|
||||||
|
auth = auth_session.get(next_url)
|
||||||
|
|
||||||
|
if auth.status_code == 200:
|
||||||
|
return auth.json()
|
||||||
else:
|
else:
|
||||||
message = auth.json()
|
message = auth.json()
|
||||||
|
raise Exception(message["details"][0]["userMessage"])
|
||||||
|
|
||||||
|
|
||||||
|
def get_token(auth_session, data):
|
||||||
|
auth_session.headers.update({"content-type": "application/x-www-form-urlencoded"})
|
||||||
|
body = {"code": data["authorizeResponse"]["code"], "grant_type": "authorization_code"}
|
||||||
|
token_auth = auth_session.post(OAUTH_TOKEN_URL, data=body)
|
||||||
|
|
||||||
|
if token_auth.status_code == 200:
|
||||||
|
return token_auth.json()
|
||||||
|
else:
|
||||||
|
message = token_auth.json()
|
||||||
raise Exception(message["error_description"])
|
raise Exception(message["error_description"])
|
||||||
|
|
||||||
|
|
||||||
|
def check_username_password(auth_session, data):
|
||||||
|
next_url = data["_links"]["checkUsernamePassword"]["href"] + "?action=checkUsernamePassword"
|
||||||
|
body = {"username": settings.volvoData["username"],
|
||||||
|
"password": settings.volvoData["password"]}
|
||||||
|
auth = auth_session.post(next_url, data=json.dumps(body))
|
||||||
|
|
||||||
|
if auth.status_code == 200:
|
||||||
|
return auth.json()
|
||||||
|
else:
|
||||||
|
message = auth.json()
|
||||||
|
raise Exception(message["details"][0]["userMessage"])
|
||||||
|
|
||||||
|
|
||||||
|
def send_otp(auth_session, data):
|
||||||
|
mqtt.create_otp_input()
|
||||||
|
next_url = data["_links"]["checkOtp"]["href"] + "?action=checkOtp"
|
||||||
|
body = {"otp": ""}
|
||||||
|
|
||||||
|
for i in range(otp_max_loops):
|
||||||
|
if mqtt.otp_code:
|
||||||
|
body["otp"] = mqtt.otp_code
|
||||||
|
break
|
||||||
|
|
||||||
|
logging.info("Waiting for otp code... Please check your mailbox and post your otp code to the following "
|
||||||
|
"mqtt topic \"volvoAAOS2mqtt/otp_code\". Retry " + str(i) + "/" + str(otp_max_loops))
|
||||||
|
time.sleep(5)
|
||||||
|
|
||||||
|
if not mqtt.otp_code:
|
||||||
|
raise Exception ("No OTP found, exting...")
|
||||||
|
|
||||||
|
mqtt.delete_otp_input()
|
||||||
|
auth = auth_session.post(next_url, data=json.dumps(body))
|
||||||
|
if auth.status_code == 200:
|
||||||
|
return auth.json()
|
||||||
|
else:
|
||||||
|
message = auth.json()
|
||||||
|
raise Exception(message["details"][0]["userMessage"])
|
||||||
|
|
||||||
|
|
||||||
def refresh_auth():
|
def refresh_auth():
|
||||||
logging.info("Refreshing credentials")
|
logging.info("Refreshing credentials")
|
||||||
global refresh_token
|
global refresh_token
|
||||||
@@ -76,18 +178,21 @@ def refresh_auth():
|
|||||||
}
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
auth = requests.post(OAUTH_URL, data=body, headers=headers)
|
auth = requests.post(OAUTH_TOKEN_URL, data=body, headers=headers)
|
||||||
except requests.exceptions.RequestException as e:
|
except requests.exceptions.RequestException as e:
|
||||||
logging.error("Error refreshing credentials data: " + str(e))
|
logging.error("Error refreshing credentials data: " + str(e))
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if auth.status_code == 200:
|
if auth.status_code == 200:
|
||||||
data = auth.json()
|
data = auth.json()
|
||||||
|
util.save_to_json(data)
|
||||||
session.headers.update({"authorization": "Bearer " + data["access_token"]})
|
session.headers.update({"authorization": "Bearer " + data["access_token"]})
|
||||||
|
|
||||||
global token_expires_at
|
global token_expires_at
|
||||||
token_expires_at = datetime.now(util.TZ) + timedelta(seconds=(data["expires_in"] - 30))
|
token_expires_at = datetime.now(util.TZ) + timedelta(seconds=(data["expires_in"] - 30))
|
||||||
refresh_token = data["refresh_token"]
|
refresh_token = data["refresh_token"]
|
||||||
|
else:
|
||||||
|
authorize(renew_tokenfile=True)
|
||||||
|
|
||||||
|
|
||||||
def get_vehicles():
|
def get_vehicles():
|
||||||
|
|||||||
Reference in New Issue
Block a user