Skip to content

Commit 059726e

Browse files
committed
feat(ble): return decoded response payload from infotainment commands
1 parent dbe24c9 commit 059726e

2 files changed

Lines changed: 55 additions & 2 deletions

File tree

‎tesla_fleet_api/tesla/vehicle/commands.py‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -849,15 +849,26 @@ async def _command(
849849
}
850850
if response.HasField("vehicleData"):
851851
return {"response": response.vehicleData}
852+
# Any other populated response_msg oneof member (e.g.
853+
# getManagedChargingSitesResponse) is returned as the decoded
854+
# proto under its field name, alongside result/reason, so an
855+
# empty payload is distinguishable from an undecoded one.
856+
payload_field = response.WhichOneof("response_msg")
857+
data: dict[str, Any] = {}
858+
if payload_field is not None:
859+
data[payload_field] = getattr(response, payload_field)
852860
if response.HasField("actionStatus"):
853861
return {
854862
"response": {
855863
"result": response.actionStatus.result
856864
== OperationStatus_E.OPERATIONSTATUS_OK,
857865
"reason": response.actionStatus.result_reason.plain_text
858866
or "",
867+
**data,
859868
}
860869
}
870+
if data:
871+
return {"response": {"result": True, "reason": "", **data}}
861872

862873
return {"response": {"result": True, "reason": ""}}
863874

‎tests/test_ble_charging_utility_commands.py‎

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,18 @@
55
parallel flattened API - see ``commands.py`` docstrings.
66
"""
77

8-
from tesla_protocol.command.car_server_pb2 import Action, SetRateTariffRequest
9-
from tesla_protocol.command.universal_message_pb2 import Domain
8+
from tesla_protocol.command.car_server_pb2 import (
9+
Action,
10+
GetManagedChargingSitesResponse,
11+
ManagedChargingSite,
12+
Response,
13+
SetRateTariffRequest,
14+
)
15+
from tesla_protocol.command.universal_message_pb2 import (
16+
Destination,
17+
Domain,
18+
RoutableMessage,
19+
)
1020

1121
from ble_mocked_transport import (
1222
MockedBleTransportTestCase,
@@ -117,3 +127,35 @@ async def test_sends_discharge_limit(self) -> None:
117127

118128
vehicle_action = _decode_vehicle_action(vehicle, send.await_args.args[0])
119129
self.assertEqual(vehicle_action.setDischargeLimitAction.discharge_limit, 50)
130+
131+
132+
class GetManagedChargingSitesDecodeTests(MockedBleTransportTestCase):
133+
def _reply(self, sites: list[ManagedChargingSite]) -> RoutableMessage:
134+
body = Response(
135+
getManagedChargingSitesResponse=GetManagedChargingSitesResponse(sites=sites)
136+
)
137+
return RoutableMessage(
138+
from_destination=Destination(domain=Domain.DOMAIN_INFOTAINMENT),
139+
protobuf_message_as_bytes=body.SerializeToString(),
140+
)
141+
142+
async def test_returns_decoded_sites(self) -> None:
143+
vehicle, send = self.make_vehicle()
144+
send.return_value = self._reply([ManagedChargingSite(public_key="k1")])
145+
146+
result = await vehicle.get_managed_charging_sites()
147+
148+
resp = result["response"]
149+
self.assertTrue(resp["result"])
150+
sites = resp["getManagedChargingSitesResponse"].sites
151+
self.assertEqual([s.public_key for s in sites], ["k1"])
152+
153+
async def test_empty_list_is_distinguishable_from_undecoded(self) -> None:
154+
vehicle, send = self.make_vehicle()
155+
send.return_value = self._reply([])
156+
157+
result = await vehicle.get_managed_charging_sites()
158+
159+
resp = result["response"]
160+
self.assertIn("getManagedChargingSitesResponse", resp)
161+
self.assertEqual(len(resp["getManagedChargingSitesResponse"].sites), 0)

0 commit comments

Comments
 (0)