mirror of
https://github.com/Dielee/volvo2mqtt.git
synced 2026-07-22 02:13:01 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ebc3ba4e16 | ||
|
|
a1881a87d8 | ||
|
|
8c0ce8976e | ||
|
|
34a0b9b2a7 |
@@ -2,3 +2,5 @@
|
||||
venv
|
||||
src/settings.dev.json
|
||||
.env
|
||||
/src/volvo2mqtt.log
|
||||
/src/volvo2mqtt.log.1
|
||||
|
||||
+2
-1
@@ -15,6 +15,7 @@ RUN pip install -r requirements.txt
|
||||
|
||||
# copy the content of the local src directory to the working directory
|
||||
COPY / .
|
||||
RUN chmod a+x /volvoAAOS2mqtt/run.sh
|
||||
|
||||
# command to run on container start
|
||||
CMD [ "python", "-u", "./main.py" ]
|
||||
CMD [ "/volvoAAOS2mqtt/run.sh" ]
|
||||
+3
-1
@@ -1,10 +1,12 @@
|
||||
name: "Volvo2Mqtt"
|
||||
description: "Volvo AAOS MQTT bridge"
|
||||
version: "1.6.1"
|
||||
version: "1.6.5"
|
||||
slug: "volvo2mqtt"
|
||||
init: false
|
||||
url: "https://github.com/Dielee/volvo2mqtt"
|
||||
apparmor: true
|
||||
map:
|
||||
- addons:rw
|
||||
options:
|
||||
updateInterval: 300
|
||||
babelLocale: null
|
||||
|
||||
+28
-8
@@ -1,6 +1,6 @@
|
||||
from config import settings
|
||||
|
||||
VERSION = "v1.6.1"
|
||||
VERSION = "v1.6.5"
|
||||
|
||||
OAUTH_URL = "https://volvoid.eu.volvocars.com/as/token.oauth2"
|
||||
VEHICLES_URL = "https://api.volvocars.com/connected-vehicle/v1/vehicles"
|
||||
@@ -19,21 +19,21 @@ ENGINE_STATE_URL = "https://api.volvocars.com/connected-vehicle/v2/vehicles/{0}/
|
||||
BATTERY_CHARGE_STATE_URL = "https://api.volvocars.com/connected-vehicle/v2/vehicles/{0}/battery-charge-level"
|
||||
FUEL_STATE_URL = "https://api.volvocars.com/connected-vehicle/v2/vehicles/{0}/fuel"
|
||||
STATISTICS_URL = "https://api.volvocars.com/connected-vehicle/v2/vehicles/{0}/statistics"
|
||||
DISTANCE_TO_EMPTY_URL = "https://api.volvocars.com/extended-vehicle/v1/vehicles/{0}/resources/distanceToEmpty"
|
||||
WASHER_FLUID_LEVEL_URL = "https://api.volvocars.com/extended-vehicle/v1/vehicles/{0}/resources/washerFluidLevel"
|
||||
|
||||
units = {
|
||||
"en_GB": {
|
||||
"divider": 1.60934,
|
||||
"electric_range": {"unit": "mi"},
|
||||
"odometer": {"unit": "mi"},
|
||||
"average_speed": {"unit": "mph"}
|
||||
"average_speed": {"unit": "mph"},
|
||||
"distance_to_empty": {"unit": "mi"}
|
||||
},
|
||||
"en_US": {
|
||||
"divider": 1.60934,
|
||||
"electric_range": {"unit": "mi"},
|
||||
"odometer": {"unit": "mi"},
|
||||
"average_speed": {"unit": "mph"}
|
||||
"average_speed": {"unit": "mph"},
|
||||
"distance_to_empty": {"unit": "mi"}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,27 @@ charging_connection_states = {"CONNECTION_STATUS_DISCONNECTED": "Disconnected",
|
||||
window_states = {"CLOSED": "OFF", "OPEN": "ON"}
|
||||
door_states = {"CLOSED": "OFF", "OPEN": "ON"}
|
||||
|
||||
icon_states = {
|
||||
"lock_status": {"UNLOCKED": "lock-open-alert", "LOCKED": "lock"},
|
||||
"door_front_left": {"ON": "car-door", "OFF": "car-door-lock"},
|
||||
"door_front_right": {"ON": "car-door", "OFF": "car-door-lock"},
|
||||
"door_rear_left": {"ON": "car-door", "OFF": "car-door-lock"},
|
||||
"door_rear_right": {"ON": "car-door", "OFF": "car-door-lock"},
|
||||
"battery_charge_level": [
|
||||
{"from": 100, "to": 100, "icon": "battery"},
|
||||
{"from": 99, "to": 90, "icon": "battery-90"},
|
||||
{"from": 89, "to": 80, "icon": "battery-80"},
|
||||
{"from": 79, "to": 70, "icon": "battery-70"},
|
||||
{"from": 69, "to": 60, "icon": "battery-60"},
|
||||
{"from": 59, "to": 50, "icon": "battery-50"},
|
||||
{"from": 49, "to": 40, "icon": "battery-40"},
|
||||
{"from": 39, "to": 30, "icon": "battery-30"},
|
||||
{"from": 29, "to": 20, "icon": "battery-20"},
|
||||
{"from": 19, "to": 10, "icon": "battery-10"},
|
||||
{"from": 9, "to": 0, "icon": "battery-alert-variant-outline"},
|
||||
]
|
||||
}
|
||||
|
||||
supported_entities = [
|
||||
{"name": "Battery Charge Level", "domain": "sensor", "id": "battery_charge_level", "unit": "%", "icon": "car-battery", "url": RECHARGE_STATE_URL},
|
||||
{"name": "Battery Charge Level", "domain": "sensor", "id": "battery_charge_level", "unit": "%", "icon": "car-battery", "url": BATTERY_CHARGE_STATE_URL},
|
||||
@@ -81,7 +102,6 @@ supported_entities = [
|
||||
{"name": "Engine State", "domain": "sensor", "id": "engine_state", "icon": "engine", "url": ENGINE_STATE_URL},
|
||||
{"name": "Fuel Level", "domain": "sensor", "id": "fuel_level", "unit": "liters", "icon": "fuel", "url": FUEL_STATE_URL},
|
||||
{"name": "Average Fuel Consumption", "domain": "sensor", "id": "average_fuel_consumption", "unit": "liters", "icon": "fuel", "url": STATISTICS_URL},
|
||||
{"name": "Average Speed", "domain": "sensor", "id": "average_speed", "unit": "km/h" if not units.get(settings["babelLocale"]) else units[settings["babelLocale"]]["average_speed"]["unit"], "icon": "speedometer", "url": STATISTICS_URL},
|
||||
{"name": "Distance to Empty", "domain": "sensor", "id": "distance_to_empty", "unit": "km" if not units.get(settings["babelLocale"]) else units[settings["babelLocale"]]["odometer"]["unit"], "icon": "map-marker-distance", "url": DISTANCE_TO_EMPTY_URL},
|
||||
{"name": "Washer Fluid Level", "domain": "sensor", "id": "washer_fluid_level", "icon": "wiper-wash", "url": WASHER_FLUID_LEVEL_URL},
|
||||
{"name": "Distance to Empty", "domain": "sensor", "id": "distance_to_empty", "unit": "km" if not units.get(settings["babelLocale"]) else units[settings["babelLocale"]]["distance_to_empty"]["unit"], "icon": "map-marker-distance", "url": STATISTICS_URL},
|
||||
{"name": "Average Speed", "domain": "sensor", "id": "average_speed", "unit": "km/h" if not units.get(settings["babelLocale"]) else units[settings["babelLocale"]]["average_speed"]["unit"], "icon": "speedometer", "url": STATISTICS_URL}
|
||||
]
|
||||
|
||||
+5
-2
@@ -1,11 +1,14 @@
|
||||
import logging
|
||||
from volvo import authorize
|
||||
from mqtt import update_loop, connect
|
||||
from const import VERSION
|
||||
from util import set_tz
|
||||
from util import set_tz, setup_logging
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Starting volvo2mqtt version " + VERSION)
|
||||
set_tz()
|
||||
setup_logging()
|
||||
logging.info("Starting volvo2mqtt version " + VERSION)
|
||||
authorize()
|
||||
connect()
|
||||
update_loop()
|
||||
|
||||
+54
-6
@@ -1,3 +1,4 @@
|
||||
import logging
|
||||
import time
|
||||
import paho.mqtt.client as mqtt
|
||||
import json
|
||||
@@ -8,7 +9,7 @@ from datetime import datetime
|
||||
from babel.dates import format_datetime
|
||||
from config import settings
|
||||
from const import CLIMATE_START_URL, CLIMATE_STOP_URL, CAR_LOCK_URL, \
|
||||
CAR_UNLOCK_URL, availability_topic
|
||||
CAR_UNLOCK_URL, availability_topic, icon_states
|
||||
|
||||
|
||||
mqtt_client: mqtt.Client
|
||||
@@ -17,6 +18,7 @@ assumed_climate_state = {}
|
||||
last_data_update = None
|
||||
climate_timer = {}
|
||||
door_status = {}
|
||||
devices = {}
|
||||
|
||||
|
||||
def connect():
|
||||
@@ -48,14 +50,14 @@ def on_connect(client, userdata, flags, rc):
|
||||
|
||||
|
||||
def on_disconnect(client, userdata, rc):
|
||||
print("MQTT disconnected, reconnecting automatically")
|
||||
logging.warning("MQTT disconnected, reconnecting automatically")
|
||||
|
||||
|
||||
def on_message(client, userdata, msg):
|
||||
try:
|
||||
vin = msg.topic.split('/')[2].split('_')[0]
|
||||
except IndexError:
|
||||
print("Error - Cannot get vin from MQTT topic!")
|
||||
logging.error("Error - Cannot get vin from MQTT topic!")
|
||||
return None
|
||||
|
||||
payload = msg.payload.decode("UTF-8")
|
||||
@@ -111,10 +113,10 @@ def on_message(client, userdata, msg):
|
||||
def update_loop():
|
||||
create_ha_devices()
|
||||
while True:
|
||||
print("Sending mqtt update...")
|
||||
logging.info("Sending mqtt update...")
|
||||
send_heartbeat()
|
||||
update_car_data()
|
||||
print("Mqtt update done. Next run in " + str(settings["updateInterval"]) + " seconds.")
|
||||
logging.info("Mqtt update done. Next run in " + str(settings["updateInterval"]) + " seconds.")
|
||||
time.sleep(settings["updateInterval"])
|
||||
|
||||
|
||||
@@ -153,12 +155,58 @@ def update_car_data(force_update=False, overwrite={}):
|
||||
topic,
|
||||
json.dumps(state) if isinstance(state, dict) else state
|
||||
)
|
||||
update_ha_device(entity, vin, state)
|
||||
|
||||
|
||||
def update_ha_device(entity, vin, state):
|
||||
icon_config = icon_states.get(entity["id"])
|
||||
if icon_config and state:
|
||||
if state.replace(".", "").isnumeric():
|
||||
state = float(state)
|
||||
icon = util.get_icon_between(icon_config, state)
|
||||
else:
|
||||
icon = icon_config[state]
|
||||
else:
|
||||
return None
|
||||
|
||||
logging.debug("Updating icon to " + icon + " for " + entity["id"])
|
||||
config = {
|
||||
"name": entity['name'],
|
||||
"object_id": f"volvo_{vin}_{entity['id']}",
|
||||
"schema": "state",
|
||||
"icon": f"mdi:{icon}" if icon else f"mdi:{entity['icon']}",
|
||||
"state_topic": f"homeassistant/{entity['domain']}/{vin}_{entity['id']}/state",
|
||||
"device": devices[vin],
|
||||
"unique_id": f"volvoAAOS2mqtt_{vin}_{entity['id']}",
|
||||
"availability_topic": availability_topic
|
||||
}
|
||||
if entity.get("device_class"):
|
||||
config["device_class"] = entity["device_class"]
|
||||
|
||||
if entity.get("unit"):
|
||||
config["unit_of_measurement"] = entity["unit"]
|
||||
|
||||
if entity.get("domain") == "device_tracker":
|
||||
config["json_attributes_topic"] = f"homeassistant/{entity['domain']}/{vin}_{entity['id']}/attributes"
|
||||
|
||||
if entity.get("domain") in ["switch", "lock", "button"]:
|
||||
command_topic = f"homeassistant/{entity['domain']}/{vin}_{entity['id']}/command"
|
||||
config["command_topic"] = command_topic
|
||||
subscribed_topics.append(command_topic)
|
||||
mqtt_client.subscribe(command_topic)
|
||||
|
||||
mqtt_client.publish(
|
||||
f"homeassistant/{entity['domain']}/volvoAAOS2mqtt/{vin}_{entity['id']}/config",
|
||||
json.dumps(config),
|
||||
retain=True
|
||||
)
|
||||
|
||||
|
||||
def create_ha_devices():
|
||||
global subscribed_topics
|
||||
global subscribed_topics, devices
|
||||
for vin in volvo.vins:
|
||||
device = volvo.get_vehicle_details(vin)
|
||||
devices[vin] = device
|
||||
for entity in volvo.supported_endpoints[vin]:
|
||||
config = {
|
||||
"name": entity['name'],
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
export IS_HA_ADDON="true"
|
||||
|
||||
python -u main.py
|
||||
+44
@@ -1,11 +1,54 @@
|
||||
import logging
|
||||
import pytz
|
||||
import os
|
||||
import sys
|
||||
from logging import handlers
|
||||
from datetime import datetime
|
||||
from const import units
|
||||
from config import settings
|
||||
from pathlib import Path
|
||||
|
||||
TZ = None
|
||||
|
||||
|
||||
def get_icon_between(icon_list, state):
|
||||
icon = None
|
||||
for s in icon_list:
|
||||
if s["to"] <= state <= s["from"]:
|
||||
icon = s["icon"]
|
||||
return icon
|
||||
|
||||
|
||||
def setup_logging():
|
||||
log_location = "volvo2mqtt.log"
|
||||
if os.environ.get("IS_HA_ADDON"):
|
||||
check_existing_folder()
|
||||
log_location = "/addons/volvo2mqtt/log/volvo2mqtt.log"
|
||||
|
||||
logging.Formatter.converter = lambda *args: datetime.now(tz=TZ).timetuple()
|
||||
file_log_handler = logging.handlers.RotatingFileHandler(log_location, maxBytes=1000000, backupCount=1)
|
||||
formatter = logging.Formatter(
|
||||
'%(asctime)s volvo2mqtt [%(process)d] - %(levelname)s: %(message)s',
|
||||
'%b %d %H:%M:%S')
|
||||
file_log_handler.setFormatter(formatter)
|
||||
logger = logging.getLogger()
|
||||
|
||||
console_log_handler = logging.StreamHandler(sys.stdout)
|
||||
console_log_handler.setFormatter(formatter)
|
||||
|
||||
logger.addHandler(console_log_handler)
|
||||
logger.addHandler(file_log_handler)
|
||||
|
||||
logger.setLevel(logging.INFO)
|
||||
if "debug" in settings:
|
||||
if settings["debug"]:
|
||||
logger.setLevel(logging.DEBUG)
|
||||
|
||||
|
||||
def check_existing_folder():
|
||||
Path("/addons/volvo2mqtt/log/").mkdir(parents=True, exist_ok=True)
|
||||
|
||||
|
||||
def keys_exists(element, *keys):
|
||||
""""
|
||||
Check if *keys (nested) exists in `element` (dict).
|
||||
@@ -43,3 +86,4 @@ def convert_metric_values(value):
|
||||
return round((float(value) / divider), 2)
|
||||
else:
|
||||
return value
|
||||
|
||||
|
||||
+33
-43
@@ -1,3 +1,4 @@
|
||||
import logging
|
||||
import requests
|
||||
import mqtt
|
||||
import util
|
||||
@@ -55,7 +56,7 @@ def authorize():
|
||||
|
||||
|
||||
def refresh_auth():
|
||||
print("Refreshing credentials")
|
||||
logging.info("Refreshing credentials")
|
||||
global refresh_token
|
||||
headers = {
|
||||
"authorization": "Basic aDRZZjBiOlU4WWtTYlZsNnh3c2c1WVFxWmZyZ1ZtSWFEcGhPc3kxUENhVXNpY1F0bzNUUjVrd2FKc2U0QVpkZ2ZJZmNMeXc=",
|
||||
@@ -71,7 +72,7 @@ def refresh_auth():
|
||||
try:
|
||||
auth = requests.post(OAUTH_URL, data=body, headers=headers)
|
||||
except requests.exceptions.RequestException as e:
|
||||
print("Error refreshing credentials data: " + str(e))
|
||||
logging.error("Error refreshing credentials data: " + str(e))
|
||||
return None
|
||||
|
||||
if auth.status_code == 200:
|
||||
@@ -110,16 +111,14 @@ def get_vehicles():
|
||||
raise Exception("No vehicle found, exiting application!")
|
||||
else:
|
||||
initialize_climate(vins)
|
||||
print("Vin: " + str(vins) + " found!")
|
||||
logging.info("Vin: " + str(vins) + " found!")
|
||||
|
||||
|
||||
def get_vehicle_details(vin):
|
||||
response = session.get(VEHICLE_DETAILS_URL.format(vin), timeout=15)
|
||||
if response.status_code == 200:
|
||||
data = response.json()["data"]
|
||||
if "debug" in settings:
|
||||
if settings["debug"]:
|
||||
print(response.text)
|
||||
logging.debug(response.text)
|
||||
device = {
|
||||
"identifiers": [f"volvoAAOS2mqtt_{vin}"],
|
||||
"manufacturer": "Volvo",
|
||||
@@ -157,10 +156,10 @@ def check_supported_endpoints():
|
||||
state = ""
|
||||
|
||||
if state is not None:
|
||||
print("Success! " + entity["name"] + " is supported by your vehicle.")
|
||||
logging.info("Success! " + entity["name"] + " is supported by your vehicle.")
|
||||
supported_endpoints[vin].append(entity)
|
||||
else:
|
||||
print("Failed, " + entity["name"] + " is unfortunately not supported by your vehicle.")
|
||||
logging.info("Failed, " + entity["name"] + " is unfortunately not supported by your vehicle.")
|
||||
|
||||
|
||||
def initialize_climate(vins):
|
||||
@@ -169,7 +168,7 @@ def initialize_climate(vins):
|
||||
|
||||
|
||||
def disable_climate(vin):
|
||||
print("Turning climate off by timer!")
|
||||
logging.info("Turning climate off by timer!")
|
||||
mqtt.door_status[vin].do_run = False
|
||||
mqtt.assumed_climate_state[vin] = "OFF"
|
||||
mqtt.update_car_data()
|
||||
@@ -200,38 +199,39 @@ def api_call(url, method, vin, sensor_id=None, force_update=False):
|
||||
# Exception caught while getting data from volvo api, doing nothing
|
||||
return None
|
||||
elif method == "GET":
|
||||
print("Starting " + method + " call against " + url)
|
||||
logging.debug("Starting " + method + " call against " + url)
|
||||
try:
|
||||
response = session.get(url.format(vin), timeout=15)
|
||||
except requests.exceptions.RequestException as e:
|
||||
print("Error getting data: " + str(e))
|
||||
logging.error("Error getting data: " + str(e))
|
||||
return None
|
||||
elif method == "POST":
|
||||
print("Starting " + method + " call against " + url)
|
||||
logging.debug("Starting " + method + " call against " + url)
|
||||
try:
|
||||
response = session.post(url.format(vin), timeout=20)
|
||||
except requests.exceptions.RequestException as e:
|
||||
print("Error getting data: " + str(e))
|
||||
logging.error("Error getting data: " + str(e))
|
||||
return None
|
||||
else:
|
||||
print("Unkown method posted: " + method + ". Returning nothing")
|
||||
logging.error("Unkown method posted: " + method + ". Returning nothing")
|
||||
return None
|
||||
|
||||
logging.debug("Response status code: " + str(response.status_code))
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
if "debug" in settings:
|
||||
if settings["debug"]:
|
||||
print(response.text)
|
||||
logging.debug(response.text)
|
||||
else:
|
||||
logging.debug(response.text)
|
||||
if url == CLIMATE_START_URL and response.status_code == 503:
|
||||
print("Car in use, cannot start pre climatization")
|
||||
logging.warning("Car in use, cannot start pre climatization")
|
||||
mqtt.assumed_climate_state[vin] = "OFF"
|
||||
mqtt.update_car_data()
|
||||
elif "extended-vehicle" in url and response.status_code == 403:
|
||||
# Suppress 403 errors for unsupported extended-vehicle api cars
|
||||
logging.debug("Suppressed 403 for extended-vehicle API")
|
||||
return None
|
||||
else:
|
||||
print("API Call failed. Status Code: " + str(response.status_code) + ". Error: " + response.text)
|
||||
logging.error("API Call failed. Status Code: " + str(response.status_code) + ". Error: " + response.text)
|
||||
return None
|
||||
return parse_api_data(data, sensor_id)
|
||||
|
||||
@@ -240,11 +240,11 @@ def cached_request(url, method, vin, force_update=False):
|
||||
global cached_requests
|
||||
if not util.keys_exists(cached_requests, vin + "_" + url):
|
||||
# No API Data cached, get fresh data from API
|
||||
print("Starting " + method + " call against " + url)
|
||||
logging.debug("Starting " + method + " call against " + url)
|
||||
try:
|
||||
response = session.get(url.format(vin), timeout=15)
|
||||
except requests.exceptions.RequestException as e:
|
||||
print("Error getting data: " + str(e))
|
||||
logging.error("Error getting data: " + str(e))
|
||||
return None
|
||||
|
||||
data = {"response": response, "last_update": datetime.now(util.TZ)}
|
||||
@@ -255,11 +255,11 @@ def cached_request(url, method, vin, force_update=False):
|
||||
(datetime.now(util.TZ) - cached_requests[vin + "_" + url]
|
||||
["last_update"]).total_seconds() >= 2):
|
||||
# Old Data in Cache, or force mode active, updating
|
||||
print("Starting " + method + " call against " + url)
|
||||
logging.debug("Starting " + method + " call against " + url)
|
||||
try:
|
||||
response = session.get(url.format(vin), timeout=15)
|
||||
except requests.exceptions.RequestException as e:
|
||||
print("Error getting data: " + str(e))
|
||||
logging.error("Error getting data: " + str(e))
|
||||
return None
|
||||
data = {"response": response, "last_update": datetime.now(util.TZ)}
|
||||
cached_requests[vin + "_" + url] = data
|
||||
@@ -289,8 +289,7 @@ def parse_api_data(data, sensor_id=None):
|
||||
return data["estimatedChargingTime"]["value"] if util.keys_exists(data, "estimatedChargingTime") else ""
|
||||
else:
|
||||
return 0
|
||||
else:
|
||||
return None
|
||||
return None
|
||||
elif sensor_id == "estimated_charging_finish_time":
|
||||
if util.keys_exists(data, "chargingSystemStatus"):
|
||||
charging_system_state = charging_system_states[data["chargingSystemStatus"]["value"]]
|
||||
@@ -302,8 +301,7 @@ def parse_api_data(data, sensor_id=None):
|
||||
return format_datetime(charging_finished, format="medium", locale=settings["babelLocale"])
|
||||
else:
|
||||
return ""
|
||||
else:
|
||||
return None
|
||||
return None
|
||||
elif sensor_id == "lock_status":
|
||||
return data["carLocked"]["value"] if util.keys_exists(data, "carLocked") else None
|
||||
elif sensor_id == "odometer":
|
||||
@@ -360,10 +358,7 @@ def parse_api_data(data, sensor_id=None):
|
||||
fuel_amount = int(data["fuelAmount"]["value"])
|
||||
if fuel_amount > 0:
|
||||
return fuel_amount
|
||||
else:
|
||||
return None
|
||||
else:
|
||||
return None
|
||||
return None
|
||||
elif sensor_id == "average_fuel_consumption":
|
||||
if util.keys_exists(data, "averageFuelConsumption"):
|
||||
average_fuel_con = float(data["averageFuelConsumption"]["value"])
|
||||
@@ -376,10 +371,7 @@ def parse_api_data(data, sensor_id=None):
|
||||
elif multiplier < 1:
|
||||
multiplier = 1
|
||||
return average_fuel_con * multiplier
|
||||
else:
|
||||
return None
|
||||
else:
|
||||
return None
|
||||
return None
|
||||
elif sensor_id == "average_speed":
|
||||
if util.keys_exists(data, "averageSpeed"):
|
||||
average_speed = int(data["averageSpeed"]["value"])
|
||||
@@ -392,10 +384,7 @@ def parse_api_data(data, sensor_id=None):
|
||||
elif divider < 1:
|
||||
divider = 1
|
||||
return util.convert_metric_values(average_speed / divider)
|
||||
else:
|
||||
return None
|
||||
else:
|
||||
return None
|
||||
return None
|
||||
elif sensor_id == "location":
|
||||
coordinates = {}
|
||||
if util.keys_exists(data, "geometry"):
|
||||
@@ -406,9 +395,10 @@ def parse_api_data(data, sensor_id=None):
|
||||
"gps_accuracy": 1}
|
||||
return coordinates
|
||||
elif sensor_id == "distance_to_empty":
|
||||
return util.convert_metric_values(data["distanceToEmpty"]["value"]) \
|
||||
if util.keys_exists(data, "distanceToEmpty") else None
|
||||
elif sensor_id == "washer_fluid_level":
|
||||
return data["washerFluidLevel"]["value"] if util.keys_exists(data, "washerFluidLevel") else None
|
||||
if util.keys_exists(data, "distanceToEmpty"):
|
||||
distance_to_empty = int(data["distanceToEmpty"]["value"])
|
||||
if distance_to_empty > 0:
|
||||
return util.convert_metric_values(data["distanceToEmpty"]["value"])
|
||||
return None
|
||||
else:
|
||||
return None
|
||||
|
||||
Reference in New Issue
Block a user