Skip to content

Commit 14912c8

Browse files
authored
fix(ble): send gateway DIN in add_managed_charging_site (#154)
* feat(ble): send gateway DIN in add_managed_charging_site Bump tesla-protocol to 2.2.0 for SiteController.din, the field the vehicle uses to match a registered managed-charging site to its gateway. add_managed_charging_site() previously sent an empty SiteController, so any site it registered never matched. * docs(agents): stop hardcoding HA's protobuf pin The pinned version drifts (HA moved 6.32.0 -> 7.36.0); point at the authoritative file instead of a stale number. * no-mistakes(document): docs(agents): fix stale add_managed_charging_site API description
1 parent c0618e0 commit 14912c8

7 files changed

Lines changed: 42 additions & 25 deletions

File tree

AGENTS.md

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -204,22 +204,24 @@ shims, not generated code. To pick up new message definitions, bump the floor in
204204
`pyproject.toml` — there is no local regeneration step.
205205

206206
**Runtime-version pin (Home Assistant compatibility).** protobuf refuses to load
207-
gencode stamped *newer* than the installed runtime. Home Assistant core pins
208-
`protobuf==6.32.0`, so any `tesla-protocol` version depended on must stamp
209-
gencode **≤ 6.32.0** and declare a `protobuf` requirement compatible with
210-
`==6.32.0` — check both before bumping. Keep `pyproject.toml`'s `protobuf` floor
211-
in sync with what `tesla-protocol` requires, and keep the `tesla-protocol` floor
212-
at `>=1.4.0` (earlier `.pyi` imports fail strict pyright; 1.4.0 is also the first
213-
release allowing protobuf 7).
207+
gencode stamped *newer* than the installed runtime. Check Home Assistant core's
208+
current `protobuf` pin (`homeassistant/package_constraints.txt`) before bumping
209+
`tesla-protocol` — any version depended on must stamp gencode at or below that
210+
pin and declare a `protobuf` requirement compatible with it. Keep
211+
`pyproject.toml`'s `protobuf` floor in sync with what `tesla-protocol` requires.
214212

215213
Command coverage is locked by `tests/test_proto_coverage_lock.py`, which fails if
216214
any `VehicleAction`/`GetVehicleData` field has no wrapper (`commands.py`) or
217215
reader (`bluetooth.py`) and is not allowlisted with a reason — keep that test in
218216
sync with a `tesla-protocol` bump rather than special-casing new fields. Naming:
219217
`legacy_vehicle_state()` (`bluetooth.py`) reads CarServer's `GetVehicleState`
220218
sub-state; `vehicle_state()` is the VCSEC `VehicleStatus`, a different
221-
message/domain. `set_rate_tariff`/`add_managed_charging_site` take
222-
`tesla_protocol` message types directly rather than a parallel flattened API.
219+
message/domain. `set_rate_tariff` takes `tesla_protocol` message types directly
220+
rather than a parallel flattened API. `add_managed_charging_site` takes a
221+
flattened `(public_key, din, lat, lon)` API; `public_key` must already be
222+
converted from DER to a raw EC point (the Fleet API route does that
223+
conversion server-side, this one does not), and `din` is the gateway's DIN
224+
the vehicle uses to match the registration to the site controller.
223225

224226
## Code Style
225227

CLAUDE.md

Lines changed: 0 additions & 1 deletion
This file was deleted.

CLAUDE.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<!-- Points Claude at AGENTS.md via import; edit AGENTS.md, not this file. -->
2+
@AGENTS.md

pyproject.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ requires = ["setuptools>=77.0"]
44

55
[project]
66
name = "tesla_fleet_api"
7-
version = "1.14.1"
7+
version = "1.15.0"
88
license = "Apache-2.0"
99
description = "Tesla Fleet API library for Python"
1010
readme = "README.md"
@@ -21,8 +21,8 @@ dependencies = [
2121
"aiofiles>=24",
2222
"aiolimiter>=1",
2323
"cryptography>=43",
24-
"protobuf>=6.32.0",
25-
"tesla-protocol>=1.4.0",
24+
"protobuf>=6.33.5",
25+
"tesla-protocol>=2.2.0",
2626
"bleak>=0.22",
2727
"bleak-retry-connector>=3.9",
2828
]

tesla_fleet_api/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""Tesla Fleet API"""
22

33
__author__ = "hello@teslemetry.com"
4-
__version__ = "1.14.1"
4+
__version__ = "1.15.0"
55

66
from tesla_fleet_api.const import Region, is_valid_region
77
from tesla_fleet_api.funnel import (

tesla_fleet_api/tesla/vehicle/commands.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2992,16 +2992,25 @@ async def get_rate_tariff(self) -> dict[str, Any]:
29922992
)
29932993

29942994
async def add_managed_charging_site(
2995-
self, public_key: str, lat: float, lon: float
2995+
self, public_key: str, din: str, lat: float, lon: float
29962996
) -> dict[str, Any]:
2997-
"""Registers a managed charging site (utility managed-charging program) for this vehicle."""
2997+
"""Registers a managed charging site (utility managed-charging program) for this vehicle.
2998+
2999+
`public_key` is the raw EC point string the vehicle expects, not the DER
3000+
the gateway's `get_signed_commands_public_key` returns; convert DER to a
3001+
raw EC point before calling this (the Fleet API's equivalent route does
3002+
this conversion server-side). `din` is the gateway's DIN, which the
3003+
vehicle uses to match this registration to the site controller.
3004+
"""
29983005
return await self._sendInfotainment(
29993006
Action(
30003007
vehicleAction=VehicleAction(
30013008
addManagedChargingSiteRequest=AddManagedChargingSiteRequest(
30023009
site=ManagedChargingSite(
30033010
public_key=public_key,
3004-
manager_type=ManagerType(site_controller=SiteController()),
3011+
manager_type=ManagerType(
3012+
site_controller=SiteController(din=din)
3013+
),
30053014
lat_lon=LatLong(latitude=lat, longitude=lon),
30063015
)
30073016
)

tests/test_ble_charging_utility_commands.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,16 +63,21 @@ async def test_sends_get_rate_tariff_request(self) -> None:
6363

6464

6565
class AddManagedChargingSiteTests(MockedBleTransportTestCase):
66-
async def test_sends_public_key_and_coordinates(self) -> None:
66+
async def test_sends_public_key_din_and_coordinates(self) -> None:
6767
vehicle, send = self.make_vehicle()
6868
send.return_value = infotainment_action_ok_reply()
6969

70-
await vehicle.add_managed_charging_site("pubkey-bytes", 37.3230, -122.0322)
70+
await vehicle.add_managed_charging_site(
71+
"pubkey-bytes", "1232100-00-E-1234567890AB", 37.3230, -122.0322
72+
)
7173

7274
vehicle_action = _decode_vehicle_action(vehicle, send.await_args.args[0])
7375
site = vehicle_action.addManagedChargingSiteRequest.site
7476
self.assertEqual(site.public_key, "pubkey-bytes")
7577
self.assertTrue(site.manager_type.HasField("site_controller"))
78+
self.assertEqual(
79+
site.manager_type.site_controller.din, "1232100-00-E-1234567890AB"
80+
)
7681
# LatLong lat/lon are 32-bit floats, so compare at reduced precision.
7782
self.assertAlmostEqual(site.lat_lon.latitude, 37.3230, places=4)
7883
self.assertAlmostEqual(site.lat_lon.longitude, -122.0322, places=4)

uv.lock

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)