Skip to content
Open

1.80 #591

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
17cc664
New Config flow to generate tokens on first login for original API.
itchannel May 25, 2024
2569cf8
updaed info.md
itchannel May 25, 2024
913e8ea
Updated README for new changes
itchannel May 25, 2024
f487ad5
Fix missing region dictionary
itchannel May 26, 2024
65774fa
fix country_code error
itchannel May 26, 2024
e2c31ff
fix for token error
itchannel May 26, 2024
8224360
fix token errors
itchannel May 26, 2024
7ce4929
fix missing return
itchannel May 26, 2024
c58f14f
Login Fix
itchannel May 26, 2024
8171d20
fix missing code_verifider
itchannel May 26, 2024
db58f4d
add Canada and fix lowercase country id
itchannel May 29, 2024
8f46130
updated sensor.py
itchannel May 29, 2024
9ffa71b
README updates, const.py updates that appear to be working for North …
theUNSTABLE May 30, 2024
63b671a
Formatting
theUNSTABLE May 30, 2024
3f6f96e
Added Netherlands (NL) as region
TheLizard Jun 26, 2024
d9011bc
Moved countrycode to the const parameters
TheLizard Jun 26, 2024
8710574
Merge pull request #517 from TheLizard/1.70
SquidBytes Jun 28, 2024
197cdf0
Improved dutch translations (some were in a different languages)
TheLizard Jul 2, 2024
50340e0
Updated deprecated constant: Changed GPS source type
TheLizard Jul 2, 2024
c28ba19
Migrate hass.config_entries.async_forward_entry_setup to async_forwar…
TheLizard Jul 3, 2024
fa05c3e
Corrected default region from North America & Canada to USA and moved…
TheLizard Jul 3, 2024
4e56a02
Merge pull request #521 from TheLizard/async_forward_entry_setups
SquidBytes Jul 9, 2024
37b7fb5
Merge pull request #519 from TheLizard/1.70
SquidBytes Jul 9, 2024
4e5bc48
Merge pull request #522 from TheLizard/region_improvements
SquidBytes Jul 9, 2024
bbcd80f
Resolved all but 1 flake8 messages
TheLizard Jul 11, 2024
618c01d
Resolved some python warnings, used CONF_URL const from home assistant
TheLizard Jul 13, 2024
8247100
Corrected region settings for UK
TheLizard Jul 22, 2024
d893438
Update const.py - Fix Australia URL auth
beanonymous Jul 31, 2024
70731e5
fix Australia login endpoint.
itchannel Sep 29, 2024
92e6c40
Update sensor.py
delphiactual Dec 18, 2024
f6def2e
Merge pull request #551 from delphiactual/patch-2
SquidBytes Dec 18, 2024
63f4947
Merge branch '1.70' into 1.70
SquidBytes Dec 18, 2024
43d06dd
Merge pull request #526 from TheLizard/1.70
SquidBytes Dec 18, 2024
93ceb80
Merge branch '1.70' of github.com:itchannel/fordpass-ha into 1.70
theUNSTABLE Jan 19, 2025
5e8b751
VS Code went weird on me. Changing this back.
theUNSTABLE Jan 19, 2025
b4e0e3a
Avoid deprecated setting of config_entry
N3rdix Feb 4, 2025
c4fe6d3
Fix EU login URL
gac3k Mar 4, 2025
1ddc4ae
Merge pull request #528 from beanonymous/patch-1
SquidBytes Mar 17, 2025
e819cba
Merge pull request #566 from N3rdix/patch-1
SquidBytes Mar 17, 2025
220c88e
Merge pull request #572 from gac3k/1.70
SquidBytes Mar 17, 2025
f103512
Major overhaul of code and token handling. WIP
itchannel Jun 4, 2025
808bf19
update const.py with storage constants
itchannel Jun 5, 2025
a270643
updated help line
itchannel Jun 6, 2025
e70cc42
updated translations
itchannel Jun 6, 2025
731e0cc
fix manifest version
itchannel Jun 6, 2025
7629294
add async to refresh status service
itchannel Jun 6, 2025
fcadfee
status function rewritten with auto updating after command success
itchannel Jun 6, 2025
5dae5ab
Fixed remote start status on switch toggle
itchannel Jun 6, 2025
bc1b34f
upated info.md
itchannel Jun 6, 2025
ec43db7
Update const.py
itchannel Sep 5, 2025
7c46602
Update __init__.py
itchannel Sep 5, 2025
7f98230
Update info.md
itchannel Sep 5, 2025
ad49767
Fix API issue
itchannel Nov 7, 2025
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
112 changes: 54 additions & 58 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,41 +4,39 @@

[!["Buy Me A Coffee"](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/itchannel)

<!-- Wrote up a little note thing for the breaking change. Not sure if you want to use it but I figured this could be a good start or something since I was already editing the readme. -->
> [!WARNING]
> Due to what looks like a Ford API change the integration isn't currently working as of 08/05/2024. I recommend disabling it for the time being until we can take a look at what has changed.
> # Breaking Change
> This update changes how tokens are handled, in order to prevent deletion during future updates or changes. Tokens are now handled by the HA storage system and will persist updates and reboots properly.
This change will ensure that the token is preserved during updates. This will require reconfiguration of your setup.
> Please see the Installation section, or the Wiki for help.

<!-- Tried to update the update with the new information -->
> [!IMPORTANT]
> # FordConnect API
>
> For anyone who wants to try there is a version 1.70 which works but is more fiddly to setup. Please see https://github.com/itchannel/fordpass-ha/wiki/Obtaining-Tokens-(As-of-25-05-2024) for instructions
> Dear FordPass Integration Users,
> As you know there have been many challenges with the Ford API. We > are actively working on developments but please note that these developments **will take time.**
> - **FordConnect API:** Ford has enabled developer accounts and released their `FordConnect API`. However, this API and its documentation currently **lack many data points** or **are not fully >implemented**. It is presently supported only in North America.
> - **FordPass APP:** Ford has also released their refreshed `FordPass App`. This refreshed app includes some new features while also >removing certain items, similar to the FordConnect API.
>
> It is important to understand that our integration depends on the data provided by either the `FordConnect API` or the `FordPass App`, >which may limit some functionalities.

## Future Updates:

# Important Update: New Ford API Challenges and Updates
- **Enhancements:** We are committed to enhancing the integration and ensuring its functionality. However, we both have limited time to allocate to this effort.

Dear FordPass Integration Users,
- **Implementation:** We are actively working on integrating the new `FordConnect API` to ensure users who can access it will benefit from its features. At the same time, we will maintain functionality for users who are unable to use this new API.

We want to keep you informed about the latest developments regarding the integration. Ford has recently introduced a new API, which has presented both opportunities and challenges. Here are some key points to note:

## Challenges and Issues:

- **Increased Complexity:** The new API has brought about several challenges and complexities. While it has enabled new attributes and sensors for different vehicles, it has also made integration more intricate.

- **Vehicle Variety:** In addition to an entirely new data structure, it is difficult to determine the variety of vehicles that can be supported - without knowing their capabilities. We are assessing which vehicles contain the information necessary to enable different sensors.

- **Unstable Nature of the New API:** Currently, the API appears to be unstable and/or changing. Any changes to its structure can disrupt sensor data. It is difficult to determine why: vehicles may still be in the process of migration, needing an update, or have a different data structure. Either way, instability has been noticed, and any updates or changes to the API can impact this integration.

## Ongoing Work and Future Updates:

- **Ongoing Work:** We both want to continue enhancing the integration and ensuring its functionality. However, it's important to note that we have limited time to allocate to this effort.

- **Future Updates:** We are continuing our efforts to adapt to new changes and persue further enhancments.


#### Please understand that there may be issues, or disruptions, to different sensors during this process.
#### Please be aware that there may be issues or disruptions during this process.

If you have any questions or concerns, please either open a new issue or comment on an existing issue related to yours.

Thank you,

itchannel and SquidBytes


## Credit
- https://github.com/clarkd - Initial Home Assistant automation idea and Python code (Lock/Unlock)
- https://github.com/pinballnewf - Figuring out the application ID issue
Expand All @@ -48,70 +46,68 @@ itchannel and SquidBytes
- https://github.com/heehoo59 - French Translation
- https://github.com/SquidBytes - EV updates and documentation

## Account Warning (Sep 2023)
A number of users have encountered their accounts being banned for containing "+" symbols in their email. It appears Ford thinks this is a disposable email. So if you have a + in your email I recommend changing it.

## **Changelog**
[Updates](info.md)

## Installation
Use [HACS](https://hacs.xyz/) to add this repository as a custom repo. Upon installation navigate to your integrations, and follow the configuration options. You will need to provide:
- Username (Fordpass App)
- Password (Fordpass App)
Use [HACS](https://hacs.xyz/) to add this repository as a custom repo.

Upon installation navigate to your integrations, and follow the configuration options. You will need to provide:
- Fordpass Email
- Region (Where you are based, required for tokens to work correctly)

## Requirement
You will then be prompted with `Setup Token`

Follow the instructions on the [Wiki](https://github.com/itchannel/fordpass-ha/wiki/Obtaining-Tokens-(As-of-25-05-2024)) to obtain your token

## Usage
Your car must have the lastest onboard modem functionality and have registered/authorised the fordpass application

## Services

### Car Refresh
I have added a service to poll the car for updates, due to the battery drain I have left this up to you to set the interval. The service to be called is "refresh_status" and can be accessed in home assistant using "fordpass.refresh_status".
<!-- I haven't looked into these services, but it might be easier to maintain a Wiki with the various services compared to the README. Just a thought. -->
### Car Refresh
I have added a service to poll the car for updates, due to the battery drain I have left this up to you to set the interval. The service to be called is "refresh_status" and can be accessed in home assistant using "fordpas.refresh_status".

Optionally you can add the "vin" parameter followed by your VIN number to only refresh one vehicle. By default this service will refresh all registered cars in HA.

**This will take up to 5 mins to update from the car once the service has been run**

### Unit Conversion
###
Click on options and choose imperial or metric to display in km/miles. Takes effect on next restart of home assistant. Default is Metric

<!-- These might need to be updated since its now different -->
### Clear Tokens
If you are experiencing any sign in issues, please trying clearing your tokens using the "clear_tokens" service call.

### Poll API
This service allows you to manually refresh/poll the API without waiting the set poll interval. Handy if you need quicker updates e.g. when driving for gps coordinates


## Currently Working
Depending on your vehicles capability
## Sensors
### Currently Working
**Sensors may change as the integration is being developed**
<!-- Keeping this the same, but it will probably change and update alongside Fordconnect and the new app features -->

### Switches
- Guard Mode
- Lock/Unlock
- Remote Start

### Sensors
- Alarm Status
- Battery Status (12v)
- Coolant Temperature
- Deep sleep status
- Diesel System
- Door Status
- Electric Vehicle Support
- Firmware Update Status
- Fuel Level
- Ignition Status
- Indicators (Value of various vehicles indicators)
- Last Refresh
- FordPass messages and alerts
- Odometer
- Lock/Unlock
- Oil Status
- Outside Temperature
- Speed
- Last known GPS Coordinates/Map
- Tyre Status
- TPMS Sensors
- Battery Status
- Ignition Status
- Alarm Status
- Individual door statuses
- Remote Start
- Window Status (Only if your car supports it!)
- Last Car Refresh status
- Car Tracker
- Window Status
- Supports Multiple Regions
- Electric Vehicle Support
- TPMS Sensors
- Guard Mode (Only supported cars)
- Deep sleep status
- Fordpass messages and alerts

## Disclaimer

This integration is not officially supported by Ford and as such using this integration could result in your account being locked out!
121 changes: 69 additions & 52 deletions custom_components/fordpass/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,24 @@
DataUpdateCoordinator,
UpdateFailed,
)
from homeassistant.helpers.storage import Store

from .const import (
CONF_DISTANCE_UNIT,
CONF_PRESSURE_UNIT,
DEFAULT_DISTANCE_UNIT,
DEFAULT_PRESSURE_UNIT,
DEFAULT_REGION,
DOMAIN,
MANUFACTURER,
REGION,
VEHICLE,
VIN,
UPDATE_INTERVAL,
UPDATE_INTERVAL_DEFAULT,
COORDINATOR
COORDINATOR,
STORAGE_VERSION,
STORAGE_KEY_PREFIX,
)
from .fordpass_new import Vehicle

Expand Down Expand Up @@ -61,8 +65,14 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
region = entry.data[REGION]
else:
_LOGGER.debug("CANT GET REGION")
region = "North America & Canada"
coordinator = FordPassDataUpdateCoordinator(hass, user, password, vin, region, update_interval, 1)
region = DEFAULT_REGION

# Create token store for this user
token_store = Store(hass, STORAGE_VERSION, f"{STORAGE_KEY_PREFIX}_{user}")

coordinator = FordPassDataUpdateCoordinator(
hass, user, password, vin, region, update_interval, token_store
)

await coordinator.async_refresh() # Get initial data

Expand All @@ -79,21 +89,57 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
"fordpass_options_listener": fordpass_options_listener
}

for component in PLATFORMS:
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(entry, component)
)
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)

async def async_refresh_status_service(service_call):
await hass.async_add_executor_job(
refresh_status, hass, service_call, coordinator
)
await coordinator.async_request_refresh()
"""Handle refresh status for specific VIN or all vehicles"""
target_vin = service_call.data.get("vin", "")

if target_vin:
# Refresh specific vehicle
_LOGGER.debug(f"Refreshing status for VIN: {target_vin}")
try:
# Use the async request_update method directly
result = await coordinator.vehicle.request_update(target_vin)
if result:
_LOGGER.debug("Refresh command succeeded, updating coordinator data")
# Wait a moment for the vehicle to process the command
await asyncio.sleep(2)
# Force refresh the coordinator data
await coordinator.async_request_refresh()
else:
_LOGGER.warning("Refresh command failed")
except Exception as e:
_LOGGER.error(f"Error during refresh: {e}")
else:
# Refresh all vehicles for this account
all_entries = hass.config_entries.async_entries(DOMAIN)
current_username = entry.data[CONF_USERNAME]

for config_entry in all_entries:
if config_entry.data.get(CONF_USERNAME) == current_username:
entry_coordinator = hass.data[DOMAIN][config_entry.entry_id][COORDINATOR]
_LOGGER.debug(f"Refreshing status for VIN: {entry_coordinator.vin}")
try:
# Use the async request_update method directly
result = await entry_coordinator.vehicle.request_update()
if result:
_LOGGER.debug("Refresh command succeeded, updating coordinator data")
# Wait a moment for the vehicle to process the command
await asyncio.sleep(2)
# Force refresh the coordinator data
await entry_coordinator.async_request_refresh()
else:
_LOGGER.warning(f"Refresh command failed for VIN: {entry_coordinator.vin}")
except Exception as e:
_LOGGER.error(f"Error during refresh for VIN {entry_coordinator.vin}: {e}")

async def async_clear_tokens_service(service_call):
await hass.async_add_executor_job(clear_tokens, hass, service_call, coordinator)
"""Clear tokens for this user account"""
await coordinator.vehicle.clear_token()

async def poll_api_service(service_call):
"""Poll API for this vehicle"""
await coordinator.async_request_refresh()

async def handle_reload(service):
Expand Down Expand Up @@ -152,24 +198,6 @@ async def options_update_listener(hass: HomeAssistant, entry: ConfigEntry):
_LOGGER.debug("OPTIONS CHANGE")
await hass.config_entries.async_reload(entry.entry_id)


def refresh_status(hass, service, coordinator):
"""Get latest vehicle status from vehicle, actively polls the car"""
_LOGGER.debug("Running Service")
vin = service.data.get("vin", "")
status = coordinator.vehicle.request_update(vin)
if status:
_LOGGER.debug("Refresh Sent")
return True
return False


def clear_tokens(hass, service, coordinator):
"""Clear the token file in config directory, only use in emergency"""
_LOGGER.debug("Clearing Tokens")
coordinator.vehicle.clear_token()


async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry."""

Expand All @@ -182,12 +210,11 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
class FordPassDataUpdateCoordinator(DataUpdateCoordinator):
"""DataUpdateCoordinator to handle fetching new data about the vehicle."""

def __init__(self, hass, user, password, vin, region, update_interval, save_token=False):
def __init__(self, hass, user, password, vin, region, update_interval, token_store):
"""Initialize the coordinator and set up the Vehicle object."""
self._hass = hass
self.vin = vin
config_path = hass.config.path("custom_components/fordpass/" + user + "_fordpass_token.txt")
self.vehicle = Vehicle(user, password, vin, region, save_token, config_path)
self.vehicle = Vehicle(user, password, vin, region, token_store, hass)
self._available = True

super().__init__(
Expand All @@ -201,21 +228,13 @@ async def _async_update_data(self):
"""Fetch data from FordPass."""
try:
async with async_timeout.timeout(30):
data = await self._hass.async_add_executor_job(
self.vehicle.status # Fetch new status
)
data = await self.vehicle.status()

# Temporarily removed due to Ford backend API changes
# data["guardstatus"] = await self._hass.async_add_executor_job(
# self.vehicle.guardStatus # Fetch new status
# )

data["messages"] = await self._hass.async_add_executor_job(
self.vehicle.messages
)
data["vehicles"] = await self._hass.async_add_executor_job(
self.vehicle.vehicles
)
# data["guardstatus"] = await self.vehicle.guardStatus()

#data["messages"] = await self.vehicle.messages()
data["vehicles"] = await self.vehicle.vehicles()
_LOGGER.debug(data)
# If data has now been fetched but was previously unavailable, log and reset
if not self._available:
Expand All @@ -224,14 +243,12 @@ async def _async_update_data(self):

return data
except Exception as ex:
# self._available = False # Mark as unavailable
self._available = False # Mark as unavailable
_LOGGER.warning(str(ex))
_LOGGER.warning("Error communicating with FordPass for %s", self.vin)
_LOGGER.warning("Returning Stale data to prevent unavaliable status")
if self.data:
if "metrics" in self.data:
return self.data
raise UpdateFailed(f"Error communicating with FordPass for {self.vin}") from ex
raise UpdateFailed(
f"Error communicating with FordPass for {self.vin}"
) from ex


class FordPassEntity(CoordinatorEntity):
Expand Down
Loading