mirror of
https://github.com/Dielee/volvo2mqtt.git
synced 2026-08-12 10:49:52 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c6ddd71021 | ||
|
|
1f0612ca4a | ||
|
|
6306c9a4b3 | ||
|
|
8bd0388690 | ||
|
|
245dd82c82 | ||
|
|
8e471d8eb0 |
@@ -87,7 +87,7 @@ The following steps are required for authentication in exactly this order:
|
|||||||
```etc ...```
|
```etc ...```
|
||||||
4. Now, open your mailbox and copy your OTP Code
|
4. Now, open your mailbox and copy your OTP Code
|
||||||
5. Open HomeAssistant and search for the entity ID ```text.volvo_otp```
|
5. Open HomeAssistant and search for the entity ID ```text.volvo_otp```
|
||||||
6. Paste your OTP into the text entity and press Enter
|
6. Paste your OTP into the text entity and **<ins>press Enter</ins>**
|
||||||
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.
|
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
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
requests~=2.31.0
|
requests~=2.32.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
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
name: "Volvo2Mqtt"
|
name: "Volvo2Mqtt"
|
||||||
description: "Volvo AAOS MQTT bridge"
|
description: "Volvo AAOS MQTT bridge"
|
||||||
version: "1.9.0"
|
version: "1.9.2"
|
||||||
slug: "volvo2mqtt"
|
slug: "volvo2mqtt"
|
||||||
init: false
|
init: false
|
||||||
url: "https://github.com/Dielee/volvo2mqtt"
|
url: "https://github.com/Dielee/volvo2mqtt"
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
from config import settings
|
from config import settings
|
||||||
|
|
||||||
VERSION = "v1.9.0"
|
VERSION = "v1.9.2"
|
||||||
|
|
||||||
OAUTH_TOKEN_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"
|
OAUTH_AUTH_URL = "https://volvoid.eu.volvocars.com/as/authorization.oauth2"
|
||||||
@@ -139,5 +139,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_max_loops = 24
|
||||||
otp_mqtt_topic = "volvoAAOS2mqtt/otp_code"
|
otp_mqtt_topic = "volvoAAOS2mqtt/otp_code"
|
||||||
+19
-7
@@ -47,25 +47,37 @@ def connect():
|
|||||||
|
|
||||||
|
|
||||||
def create_otp_input():
|
def create_otp_input():
|
||||||
|
state_topic = otp_mqtt_topic + "/state"
|
||||||
config = {
|
config = {
|
||||||
"name": "Volvo OTP",
|
"name": "Volvo OTP",
|
||||||
"object_id": f"volvo_otp",
|
"object_id": f"volvo_otp",
|
||||||
"schema": "state",
|
"schema": "state",
|
||||||
"command_topic": otp_mqtt_topic,
|
"command_topic": otp_mqtt_topic,
|
||||||
"unique_id": f"volvoAAOS2mqtt_otp",
|
"state_topic": state_topic,
|
||||||
"pattern": "\d{6}",
|
"unique_id": "volvoAAOS2mqtt_otp",
|
||||||
"icon": "mdi:two-factor-authentication"
|
"pattern": r"\d{6}",
|
||||||
|
"icon": "mdi:two-factor-authentication",
|
||||||
|
"mode": "text"
|
||||||
}
|
}
|
||||||
|
|
||||||
mqtt_client.publish(
|
mqtt_client.publish(
|
||||||
f"homeassistant/text/volvoAAOS2mqtt/volvo_otp/config",
|
"homeassistant/text/volvoAAOS2mqtt/volvo_otp/config",
|
||||||
json.dumps(config),
|
json.dumps(config),
|
||||||
retain=True
|
retain=True
|
||||||
)
|
)
|
||||||
|
|
||||||
def delete_otp_input():
|
mqtt_client.publish(
|
||||||
topic = "homeassistant/text/volvoAAOS2mqtt/volvo_otp/config"
|
state_topic,
|
||||||
mqtt_client.publish(topic, payload="", retain=True)
|
"000000",
|
||||||
|
retain=True
|
||||||
|
)
|
||||||
|
|
||||||
|
def set_otp_state():
|
||||||
|
mqtt_client.publish(
|
||||||
|
otp_mqtt_topic + "/state",
|
||||||
|
otp_code,
|
||||||
|
retain=True
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def send_car_images(vin, data, device):
|
def send_car_images(vin, data, device):
|
||||||
|
|||||||
+13
-5
@@ -42,8 +42,16 @@ def get_volvo_app_version():
|
|||||||
else:
|
else:
|
||||||
return "5.37.0"
|
return "5.37.0"
|
||||||
|
|
||||||
def save_to_json(data):
|
def get_token_path():
|
||||||
with open('.token', 'w', encoding='utf-8') as f:
|
token_path = ".token"
|
||||||
|
if os.environ.get("IS_HA_ADDON"):
|
||||||
|
check_existing_folder("/addons/volvo2mqtt/token/")
|
||||||
|
token_path = "/addons/volvo2mqtt/token/.token"
|
||||||
|
|
||||||
|
return token_path
|
||||||
|
|
||||||
|
def save_to_json(data, token_path):
|
||||||
|
with open(token_path, 'w', encoding='utf-8') as f:
|
||||||
json.dump(data, f, ensure_ascii=False, indent=4)
|
json.dump(data, f, ensure_ascii=False, indent=4)
|
||||||
|
|
||||||
def get_icon_between(icon_list, state):
|
def get_icon_between(icon_list, state):
|
||||||
@@ -57,7 +65,7 @@ def get_icon_between(icon_list, state):
|
|||||||
def setup_logging():
|
def setup_logging():
|
||||||
log_location = "volvo2mqtt.log"
|
log_location = "volvo2mqtt.log"
|
||||||
if os.environ.get("IS_HA_ADDON"):
|
if os.environ.get("IS_HA_ADDON"):
|
||||||
check_existing_folder()
|
check_existing_folder("/addons/volvo2mqtt/log/")
|
||||||
log_location = "/addons/volvo2mqtt/log/volvo2mqtt.log"
|
log_location = "/addons/volvo2mqtt/log/volvo2mqtt.log"
|
||||||
|
|
||||||
logging.Formatter.converter = lambda *args: datetime.now(tz=TZ).timetuple()
|
logging.Formatter.converter = lambda *args: datetime.now(tz=TZ).timetuple()
|
||||||
@@ -90,8 +98,8 @@ def setup_logging():
|
|||||||
logger.setLevel(logging.ERROR)
|
logger.setLevel(logging.ERROR)
|
||||||
|
|
||||||
|
|
||||||
def check_existing_folder():
|
def check_existing_folder(path):
|
||||||
Path("/addons/volvo2mqtt/log/").mkdir(parents=True, exist_ok=True)
|
Path(path).mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
|
||||||
def keys_exists(element, *keys):
|
def keys_exists(element, *keys):
|
||||||
|
|||||||
+8
-5
@@ -35,9 +35,11 @@ backend_status = ""
|
|||||||
|
|
||||||
def authorize(renew_tokenfile=False):
|
def authorize(renew_tokenfile=False):
|
||||||
global refresh_token
|
global refresh_token
|
||||||
if os.path.isfile(".token") and not renew_tokenfile:
|
|
||||||
|
token_path = util.get_token_path()
|
||||||
|
if os.path.isfile(token_path) and not renew_tokenfile:
|
||||||
logging.info("Using login from token file")
|
logging.info("Using login from token file")
|
||||||
f = open('.token')
|
f = open(token_path)
|
||||||
data = json.load(f)
|
data = json.load(f)
|
||||||
refresh_token = data["refresh_token"]
|
refresh_token = data["refresh_token"]
|
||||||
refresh_auth()
|
refresh_auth()
|
||||||
@@ -91,7 +93,7 @@ def authorize(renew_tokenfile=False):
|
|||||||
token_expires_at = datetime.now(util.TZ) + timedelta(seconds=(token_data["expires_in"] - 30))
|
token_expires_at = datetime.now(util.TZ) + timedelta(seconds=(token_data["expires_in"] - 30))
|
||||||
refresh_token = token_data["refresh_token"]
|
refresh_token = token_data["refresh_token"]
|
||||||
|
|
||||||
util.save_to_json(token_data)
|
util.save_to_json(token_data, token_path)
|
||||||
else:
|
else:
|
||||||
message = auth.json()
|
message = auth.json()
|
||||||
raise Exception(message["details"][0]["userMessage"])
|
raise Exception(message["details"][0]["userMessage"])
|
||||||
@@ -154,7 +156,7 @@ def send_otp(auth_session, data):
|
|||||||
if not mqtt.otp_code:
|
if not mqtt.otp_code:
|
||||||
raise Exception ("No OTP found, exting...")
|
raise Exception ("No OTP found, exting...")
|
||||||
|
|
||||||
mqtt.delete_otp_input()
|
mqtt.set_otp_state()
|
||||||
auth = auth_session.post(next_url, data=json.dumps(body))
|
auth = auth_session.post(next_url, data=json.dumps(body))
|
||||||
if auth.status_code == 200:
|
if auth.status_code == 200:
|
||||||
return auth.json()
|
return auth.json()
|
||||||
@@ -184,8 +186,9 @@ def refresh_auth():
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
if auth.status_code == 200:
|
if auth.status_code == 200:
|
||||||
|
token_path = util.get_token_path()
|
||||||
data = auth.json()
|
data = auth.json()
|
||||||
util.save_to_json(data)
|
util.save_to_json(data, token_path)
|
||||||
session.headers.update({"authorization": "Bearer " + data["access_token"]})
|
session.headers.update({"authorization": "Bearer " + data["access_token"]})
|
||||||
|
|
||||||
global token_expires_at
|
global token_expires_at
|
||||||
|
|||||||
Reference in New Issue
Block a user