Skip to content

Commit

Permalink
Merge pull request #104 from itchannel/1.17
Browse files Browse the repository at this point in the history
1.17
  • Loading branch information
itchannel authored Jun 16, 2021
2 parents 29514ec + 7c0d48f commit c970493
Show file tree
Hide file tree
Showing 8 changed files with 288 additions and 62 deletions.
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- https://github.com/clarkd - Initial Home Assistant automation idea and Python code (Lock/Unlock)
- https://github.com/pinballnewf - Figuring out the application ID issue
- https://github.com/degrashopper - Fixing 401 error for certain installs
- https://github.com/tonesto7 - Extra window statuses and sensors

## Install
Use HACS and add as a custom repo. Once the integration is installed go to your integrations and follow the configuration options to specify the below:
Expand Down Expand Up @@ -50,9 +51,11 @@ If you are experiencing any sign in issues, please trying clearing your tokens u
- Supports Multiple Regions
- Electric Vehicle Support
- TPMS Sensors
- Guard Mode (Only supported cars)
- Deep sleep status


## Coming Soon

- Alarm event (Anyone have the json output for this event would be appreciated :) )
- Will address the bugs/requests by the end of the month busy with work currently.
- Fordpass messages and alerts
- Next service due
27 changes: 27 additions & 0 deletions custom_components/fordpass/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,31 @@
"windowPosition": {"icon": "mdi:car-door"},
"lastRefresh": {"icon": "mdi:clock"},
"elVeh": {"icon": "mdi:ev-station"},
"deepSleepInProgress": {
"icon": "mdi:power-sleep",
"name": "Deep Sleep Mode Active",
},
"firmwareUpgInProgress": {
"icon": "mdi:one-up",
"name": "Firmware Update In Progress",
},
"remoteStartStatus": {"icon": "mdi:remote"},
"zoneLighting": {"icon": "mdi:spotlight-beam"},
}

SWITCHES = {"ignition": {"icon": "hass:power"}, "guardmode": {"icon": "mdi:shield-key"}}

WINDOW_POSITIONS = {
"CLOSED": {
"Fully_Closed": "Closed",
"Fully_closed_position": "Closed",
"Fully closed position": "Closed",
},
"OPEN": {
"Fully open position": "Open",
"Fully_Open": "Open",
"Btwn 10% and 60% open": "Open-Partial",
},
}

SWITCHES = {"ignition": {"icon": "hass:power"}, "guardmode": {"icon": "mdi:shield-key"}}
17 changes: 8 additions & 9 deletions custom_components/fordpass/fordpass_new.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,16 +150,15 @@ def writeToken(self, token):
def readToken(self):
# Get saved token from file
try:
with open(self.token_location) as token_file:
token = json.load(token_file)
return token
with open(self.token_location) as token_file:
token = json.load(token_file)
return token
except ValueError:
_LOGGER.debug("Fixing malformed token")
self.auth()
with open(self.token_location) as token_file:
token = json.load(token_file)
return token

_LOGGER.debug("Fixing malformed token")
self.auth()
with open(self.token_location) as token_file:
token = json.load(token_file)
return token

def clearToken(self):
if os.path.isfile("/tmp/fordpass_token.txt"):
Expand Down
2 changes: 1 addition & 1 deletion custom_components/fordpass/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"config_flow": true,
"documentation": "https://github.com/itchannel/fordpass-ha",
"issue_tracker": "https://github.com/itchannel/fordpass-ha/issues",
"version": "0.1.16",
"version": "0.1.17",
"requirements": ["dotted==0.1.8"],
"ssdp": [],
"zeroconf": [],
Expand Down
189 changes: 164 additions & 25 deletions custom_components/fordpass/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,18 @@
async def async_setup_entry(hass, config_entry, async_add_entities):
"""Add the Entities from the config."""
entry = hass.data[DOMAIN][config_entry.entry_id]
sensors = []

for key, value in SENSORS.items():
async_add_entities([CarSensor(entry, key, config_entry.options)], True)
sensor = CarSensor(entry, key, config_entry.options)
# Add support for only adding compatible sensors for the given vehicle
if key == "zoneLighting":
if "zoneLighting" in sensor.coordinator.data:
async_add_entities([sensor], True)
elif key == "elVeh":
if sensor.coordinator.data["elVehDTE"] != None:
async_add_entities([sensor], True)
else:
async_add_entities([sensor], True)


class CarSensor(
Expand Down Expand Up @@ -55,6 +64,10 @@ def get_value(self, ftype):
return self.coordinator.data[self.sensor]["value"]
elif self.sensor == "ignitionStatus":
return self.coordinator.data[self.sensor]["value"]
elif self.sensor == "firmwareUpgInProgress":
return self.coordinator.data[self.sensor]["value"]
elif self.sensor == "deepSleepInProgress":
return self.coordinator.data[self.sensor]["value"]
elif self.sensor == "doorStatus":
for key, value in self.coordinator.data[self.sensor].items():
if value["value"] == "Invalid":
Expand All @@ -65,16 +78,12 @@ def get_value(self, ftype):
elif self.sensor == "windowPosition":
if self.coordinator.data[self.sensor] == None:
return "Unsupported"
window_closed_status = [
"Fully_Closed",
"Fully_closed_position",
"Undefined_window_position",
"Undefined",
]
for key, value in self.coordinator.data[self.sensor].items():
if value["value"] not in window_closed_status:
if "open" in value["value"].lower():
return "Open"
return "Closed"
elif "closed" in value["value"].lower():
return "Closed"
return "Unsupported"
elif self.sensor == "lastRefresh":
return dt.as_local(
datetime.strptime(
Expand All @@ -86,6 +95,26 @@ def get_value(self, ftype):
return self.coordinator.data["chargingStatus"]["value"]
else:
return "Unsupported"
elif self.sensor == "zoneLighting":
if "zoneLighting" not in self.coordinator.data:
return "Unsupported"
if (
self.coordinator.data["zoneLighting"] != None
and self.coordinator.data["zoneLighting"]["activationData"] != None
):
return self.coordinator.data["zoneLighting"]["activationData"][
"value"
]
else:
return "Unsupported"
elif self.sensor == "remoteStartStatus":
if self.coordinator.data["remoteStartStatus"] == None:
return None
else:
if self.coordinator.data["remoteStartStatus"]["value"] == 1:
return "Active"
else:
return "Inactive"
elif ftype == "measurement":
if self.sensor == "odometer":
if self.options[CONF_UNIT] == "imperial":
Expand All @@ -106,12 +135,20 @@ def get_value(self, ftype):
return None
elif self.sensor == "ignitionStatus":
return None
elif self.sensor == "firmwareUpgInProgress":
return None
elif self.sensor == "deepSleepInProgress":
return None
elif self.sensor == "doorStatus":
return None
elif self.sensor == "windowsPosition":
return None
elif self.sensor == "lastRefresh":
return None
elif self.sensor == "zoneLighting":
return None
elif self.sensor == "remoteStartStatus":
return None
elif ftype == "attribute":
if self.sensor == "odometer":
return self.coordinator.data[self.sensor].items()
Expand Down Expand Up @@ -179,6 +216,10 @@ def get_value(self, ftype):
return self.coordinator.data[self.sensor].items()
elif self.sensor == "ignitionStatus":
return self.coordinator.data[self.sensor].items()
elif self.sensor == "firmwareUpgInProgress":
return self.coordinator.data[self.sensor].items()
elif self.sensor == "deepSleepInProgress":
return self.coordinator.data[self.sensor].items()
elif self.sensor == "doorStatus":
doors = dict()
for key, value in self.coordinator.data[self.sensor].items():
Expand All @@ -190,28 +231,126 @@ def get_value(self, ftype):
windows = dict()
for key, value in self.coordinator.data[self.sensor].items():
windows[key] = value["value"]
if "open" in value["value"].lower():
if "btwn" in value["value"].lower():
windows[key] = "Open-Partial"
else:
windows[key] = "Open"
elif "closed" in value["value"].lower():
windows[key] = "Closed"
return windows
elif self.sensor == "lastRefresh":
return None
elif self.sensor == "elVeh":
if self.coordinator.data["elVehDTE"] != None:
return {
"Plug Status": self.coordinator.data["plugStatus"]["value"],
"Charge Start Time": self.coordinator.data["chargeStartTime"][
"value"
],
"Charge End Time": self.coordinator.data["chargeEndTime"][
"value"
],
"Battery Fill Level": self.coordinator.data["batteryFillLevel"][
"value"
],
"Charger Power Type": self.coordinator.data["chargerPowertype"][
if self.coordinator.data["elVehDTE"] == None:
return None
else:
elecs = dict()
if (
self.coordinator.data["plugStatus"] != None
and self.coordinator.data["plugStatus"]["value"] != None
):
elecs["Plug Status"] = self.coordinator.data["plugStatus"][
"value"
],
}
]

if (
self.coordinator.data["chargeStartTime"] != None
and self.coordinator.data["chargeStartTime"]["value"] != None
):
elecs["Charge Start Time"] = self.coordinator.data[
"chargeStartTime"
]["value"]

if (
self.coordinator.data["chargeEndTime"] != None
and self.coordinator.data["chargeEndTime"]["value"] != None
):
elecs["Charge End Time"] = self.coordinator.data[
"chargeEndTime"
]["value"]

if (
self.coordinator.data["batteryFillLevel"] != None
and self.coordinator.data["batteryFillLevel"]["value"] != None
):
elecs["Battery Fill Level"] = self.coordinator.data[
"batteryFillLevel"
]["value"]

if (
self.coordinator.data["chargerPowertype"] != None
and self.coordinator.data["chargerPowertype"]["value"] != None
):
elecs["Charger Power Type"] = self.coordinator.data[
"chargerPowertype"
]["value"]

if (
self.coordinator.data["batteryChargeStatus"] != None
and self.coordinator.data["batteryChargeStatus"]["value"]
!= None
):
elecs["Battery Charge Status"] = self.coordinator.data[
"batteryChargeStatus"
]["value"]

if (
self.coordinator.data["batteryPerfStatus"] != None
and self.coordinator.data["batteryPerfStatus"]["value"] != None
):
elecs["Battery Performance Status"] = self.coordinator.data[
"batteryPerfStatus"
]["value"]

return elecs
elif self.sensor == "zoneLighting":
if "zoneLighting" not in self.coordinator.data:
return None
if (
self.coordinator.data[self.sensor] != None
and self.coordinator.data[self.sensor]["zoneStatusData"] != None
):
zone = dict()
if self.coordinator.data[self.sensor]["zoneStatusData"] != None:
for key, value in self.coordinator.data[self.sensor][
"zoneStatusData"
].items():
zone["zone_" + key] = value["value"]

if (
self.coordinator.data[self.sensor]["lightSwitchStatusData"]
!= None
):
for key, value in self.coordinator.data[self.sensor][
"lightSwitchStatusData"
].items():
zone[key] = value["value"]

if (
self.coordinator.data[self.sensor]["zoneLightingFaultStatus"]
!= None
):
zone["zoneLightingFaultStatus"] = self.coordinator.data[
self.sensor
]["zoneLightingFaultStatus"]["value"]
if (
self.coordinator.data[self.sensor][
"zoneLightingShutDownWarning"
]
!= None
):
zone["zoneLightingShutDownWarning"] = self.coordinator.data[
self.sensor
]["zoneLightingShutDownWarning"]["value"]
return zone
else:
return None
elif self.sensor == "remoteStartStatus":
if self.coordinator.data["remoteStart"] == None:
return None
else:
return self.coordinator.data["remoteStart"].items()

@property
def name(self):
Expand Down
2 changes: 2 additions & 0 deletions custom_components/fordpass/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,7 @@ refresh_status:
name: Vin
description: "Parse a vin number to only refresh the specified vehicle (Default refreshes all added vehicles)"
example: "1C4GJ25342B521742"
selector:
text:
clear_tokens:
description: "Clear the cached tokens"
Loading

0 comments on commit c970493

Please sign in to comment.