Skip to content

Commit 2084ec3

Browse files
authored
Merge pull request #2 from Teslemetry/Bre77/add-docstrings
Add docstrings to public methods
2 parents 3fa7720 + 51bdc90 commit 2084ec3

File tree

2 files changed

+207
-21
lines changed

2 files changed

+207
-21
lines changed

README.md

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,3 +113,115 @@ async def main():
113113

114114
await stream.disconnect()
115115
```
116+
117+
## Public Methods in TeslemetryStream Class
118+
119+
### `__init__(self, session: aiohttp.ClientSession, access_token: str, server: str | None = None, vin: str | None = None, parse_timestamp: bool = False)`
120+
Initialize the TeslemetryStream client.
121+
122+
### `get_vehicle(self, vin: str) -> TeslemetryStreamVehicle`
123+
Create a vehicle stream.
124+
125+
### `connected(self) -> bool`
126+
Return if connected.
127+
128+
### `get_config(self, vin: str | None = None) -> None`
129+
Get the current stream config.
130+
131+
### `find_server(self) -> None`
132+
Find the server using metadata.
133+
134+
### `update_fields(self, fields: dict, vin: str) -> dict`
135+
Modify the Fleet Telemetry configuration.
136+
137+
### `replace_fields(self, fields: dict, vin: str) -> dict`
138+
Replace the Fleet Telemetry configuration.
139+
140+
### `config(self) -> dict`
141+
Return current configuration.
142+
143+
### `connect(self) -> None`
144+
Connect to the telemetry stream.
145+
146+
### `close(self) -> None`
147+
Close connection.
148+
149+
### `async_add_listener(self, callback: Callable, filters: dict | None = None) -> Callable[[], None]`
150+
Add listener for data updates.
151+
152+
### `listen(self)`
153+
Listen to the telemetry stream.
154+
155+
### `listen_Credits(self, callback: Callable[[dict[str, str | int]], None]) -> Callable[[], None]`
156+
Add listener for credit events.
157+
158+
### `listen_Balance(self, callback: Callable[[int], None]) -> Callable[[], None]`
159+
Add listener for credit balance.
160+
161+
## Public Methods in TeslemetryStreamVehicle Class
162+
163+
### `__init__(self, stream: TeslemetryStream, vin: str)`
164+
Initialize the TeslemetryStreamVehicle instance.
165+
166+
### `get_config(self) -> None`
167+
Get the current vehicle config.
168+
169+
### `update_fields(self, fields: dict) -> dict`
170+
Update Fleet Telemetry configuration for the vehicle.
171+
172+
### `replace_fields(self, fields: dict) -> dict`
173+
Replace Fleet Telemetry configuration for the vehicle.
174+
175+
### `config(self) -> dict`
176+
Return current configuration for the vehicle.
177+
178+
### `listen_*` Methods
179+
The `TeslemetryStreamVehicle` class contains several `listen_*` methods for various telemetry signals. These methods allow you to listen to specific signals and handle their data in a type-safe manner. The available `listen_*` methods and their callback types are:
180+
181+
- `listen_BatteryLevel(callback: Callable[[int], None])`
182+
- `listen_VehicleSpeed(callback: Callable[[int], None])`
183+
- `listen_Location(callback: Callable[[dict], None])`
184+
- `listen_ChargeState(callback: Callable[[str], None])`
185+
- `listen_DoorState(callback: Callable[[dict], None])`
186+
- `listen_HvacPower(callback: Callable[[str], None])`
187+
- `listen_ClimateKeeperMode(callback: Callable[[str], None])`
188+
- `listen_CabinOverheatProtectionMode(callback: Callable[[str], None])`
189+
- `listen_DefrostMode(callback: Callable[[str], None])`
190+
- `listen_SeatHeaterLeft(callback: Callable[[int], None])`
191+
- `listen_SeatHeaterRight(callback: Callable[[int], None])`
192+
- `listen_SeatHeaterRearLeft(callback: Callable[[int], None])`
193+
- `listen_SeatHeaterRearRight(callback: Callable[[int], None])`
194+
- `listen_SeatHeaterRearCenter(callback: Callable[[int], None])`
195+
- `listen_SentryMode(callback: Callable[[bool], None])`
196+
- `listen_ScheduledChargingMode(callback: Callable[[str], None])`
197+
- `listen_ScheduledChargingPending(callback: Callable[[bool], None])`
198+
- `listen_ScheduledChargingStartTime(callback: Callable[[str], None])`
199+
- `listen_ScheduledDepartureTime(callback: Callable[[str], None])`
200+
- `listen_SoftwareUpdateVersion(callback: Callable[[str], None])`
201+
- `listen_SoftwareUpdateDownloadPercentComplete(callback: Callable[[int], None])`
202+
- `listen_SoftwareUpdateExpectedDurationMinutes(callback: Callable[[int], None])`
203+
- `listen_SoftwareUpdateInstallationPercentComplete(callback: Callable[[int], None])`
204+
- `listen_SoftwareUpdateScheduledStartTime(callback: Callable[[str], None])`
205+
- `listen_ChargingCableType(callback: Callable[[str], None])`
206+
- `listen_FastChargerType(callback: Callable[[str], None])`
207+
- `listen_ChargePort(callback: Callable[[str], None])`
208+
- `listen_ChargePortLatch(callback: Callable[[str], None])`
209+
- `listen_ChargePortDoorOpen(callback: Callable[[bool], None])`
210+
- `listen_ChargeEnableRequest(callback: Callable[[bool], None])`
211+
- `listen_ChargeCurrentRequest(callback: Callable[[int], None])`
212+
- `listen_ChargeCurrentRequestMax(callback: Callable[[int], None])`
213+
- `listen_ChargeAmps(callback: Callable[[int], None])`
214+
- `listen_ChargerPhases(callback: Callable[[int], None])`
215+
- `listen_ChargeLimitSoc(callback: Callable[[int], None])`
216+
- `listen_ChargeState(callback: Callable[[str], None])`
217+
- `listen_ChargingCableType(callback: Callable[[str], None])`
218+
- `listen_FastChargerType(callback: Callable[[str], None])`
219+
- `listen_ChargePort(callback: Callable[[str], None])`
220+
- `listen_ChargePortLatch(callback: Callable[[str], None])`
221+
- `listen_ChargePortDoorOpen(callback: Callable[[bool], None])`
222+
- `listen_ChargeEnableRequest(callback: Callable[[bool], None])`
223+
- `listen_ChargeCurrentRequest(callback: Callable[[int], None])`
224+
- `listen_ChargeCurrentRequestMax(callback: Callable[[int], None])`
225+
- `listen_ChargeAmps(callback: Callable[[int], None])`
226+
- `listen_ChargerPhases(callback: Callable[[int], None])`
227+
- `listen_ChargeLimitSoc(callback: Callable[[int], None])`

teslemetry_stream/stream.py

Lines changed: 95 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,15 @@ def __init__(
2929
vin: str | None = None,
3030
parse_timestamp: bool = False,
3131
):
32+
"""
33+
Initialize the TeslemetryStream client.
34+
35+
:param session: An aiohttp ClientSession.
36+
:param access_token: Access token for authentication.
37+
:param server: Teslemetry server to connect to.
38+
:param vin: Vehicle Identification Number.
39+
:param parse_timestamp: Whether to parse timestamps.
40+
"""
3241
if server and not server.endswith(".teslemetry.com"):
3342
raise ValueError("Server must be on the teslemetry.com domain")
3443

@@ -44,7 +53,12 @@ def __init__(
4453
self.vehicle = self.get_vehicle(self.vin)
4554

4655
def get_vehicle(self, vin: str) -> TeslemetryStreamVehicle:
47-
"""Create a vehicle stream."""
56+
"""
57+
Create a vehicle stream.
58+
59+
:param vin: Vehicle Identification Number.
60+
:return: TeslemetryStreamVehicle instance.
61+
"""
4862
if self.vin is not None and self.vin != vin:
4963
raise AttributeError("Stream started in single vehicle mode")
5064
if vin not in self.vehicles:
@@ -53,19 +67,28 @@ def get_vehicle(self, vin: str) -> TeslemetryStreamVehicle:
5367

5468
@property
5569
def connected(self) -> bool:
56-
"""Return if connected."""
70+
"""
71+
Return if connected.
72+
73+
:return: True if connected, False otherwise.
74+
"""
5775
return self._response is not None
5876

5977
async def get_config(self, vin: str | None = None) -> None:
60-
"""Get the current stream config."""
78+
"""
79+
Get the current stream config.
80+
81+
:param vin: Vehicle Identification Number.
82+
"""
6183
if not self.server:
6284
await self.find_server()
6385
if hasattr(self, 'vehicle'):
6486
await self.vehicle.get_config()
6587

6688
async def find_server(self) -> None:
67-
"""Find the server using metadata."""
68-
89+
"""
90+
Find the server using metadata.
91+
"""
6992
req = await self._session.get(
7093
"https://api.teslemetry.com/api/metadata",
7194
headers=self._headers,
@@ -74,10 +97,14 @@ async def find_server(self) -> None:
7497
response = await req.json()
7598
self.server = f"{response["region"].lower()}.teslemetry.com"
7699

77-
78-
79100
async def update_fields(self, fields: dict, vin: str) -> dict:
80-
"""Update Fleet Telemetry configuration"""
101+
"""
102+
Update Fleet Telemetry configuration.
103+
104+
:param fields: Dictionary of fields to update.
105+
:param vin: Vehicle Identification Number.
106+
:return: Response JSON as a dictionary.
107+
"""
81108
resp = await self._session.patch(
82109
f"https://api.teslemetry.com/api/config/{self.vin}",
83110
headers=self._headers,
@@ -89,7 +116,13 @@ async def update_fields(self, fields: dict, vin: str) -> dict:
89116
return await resp.json()
90117

91118
async def replace_fields(self, fields: dict, vin: str) -> dict:
92-
"""Replace Fleet Telemetry configuration"""
119+
"""
120+
Replace Fleet Telemetry configuration.
121+
122+
:param fields: Dictionary of fields to replace.
123+
:param vin: Vehicle Identification Number.
124+
:return: Response JSON as a dictionary.
125+
"""
93126
resp = await self._session.post(
94127
f"https://api.teslemetry.com/api/config/{self.vin}",
95128
headers=self._headers,
@@ -102,13 +135,19 @@ async def replace_fields(self, fields: dict, vin: str) -> dict:
102135

103136
@property
104137
def config(self) -> dict:
105-
"""Return current configuration."""
138+
"""
139+
Return current configuration.
140+
141+
:return: Configuration dictionary.
142+
"""
106143
return {
107144
"hostname": self.server,
108145
}
109146

110147
async def connect(self) -> None:
111-
"""Connect to the telemetry stream."""
148+
"""
149+
Connect to the telemetry stream.
150+
"""
112151
self.active = True
113152
if not self.server:
114153
await self.get_config()
@@ -127,18 +166,30 @@ async def connect(self) -> None:
127166
)
128167

129168
def close(self) -> None:
130-
"""Close connection."""
169+
"""
170+
Close connection.
171+
"""
131172
if self._response is not None:
132173
LOGGER.debug("Disconnecting from %s", self.server)
133174
self._response.close()
134175
self._response = None
135176

136177
def __aiter__(self):
137-
"""Return"""
178+
"""
179+
Return an asynchronous iterator.
180+
181+
:return: Asynchronous iterator.
182+
"""
138183
return self
139184

140185
async def __anext__(self) -> dict:
141-
"""Return next event."""
186+
"""
187+
Return next event.
188+
189+
:return: Next event as a dictionary.
190+
:raises StopAsyncIteration: If the stream is stopped.
191+
:raises TeslemetryStreamEnded: If the stream is ended by the server.
192+
"""
142193
try:
143194
if self.active is False:
144195
# Stop the stream and loop
@@ -172,11 +223,19 @@ async def __anext__(self) -> dict:
172223
def async_add_listener(
173224
self, callback: Callable, filters: dict | None = None
174225
) -> Callable[[], None]:
175-
"""Listen for data updates."""
226+
"""
227+
Listen for data updates.
228+
229+
:param callback: Callback function to handle updates.
230+
:param filters: Filters to apply to the updates.
231+
:return: Function to remove the listener.
232+
"""
176233
schedule_refresh = not self._listeners
177234

178235
def remove_listener() -> None:
179-
"""Remove update listener."""
236+
"""
237+
Remove update listener.
238+
"""
180239
self._listeners.pop(remove_listener)
181240
if not self._listeners:
182241
self.active = False
@@ -190,8 +249,9 @@ def remove_listener() -> None:
190249
return remove_listener
191250

192251
async def listen(self):
193-
"""Listen to the telemetry stream."""
194-
252+
"""
253+
Listen to the telemetry stream.
254+
"""
195255
async for event in self:
196256
if event:
197257
for listener, filters in self._listeners.values():
@@ -203,23 +263,37 @@ async def listen(self):
203263
LOGGER.debug("Listen has finished")
204264

205265
def listen_Credits(self, callback: Callable[[dict[str, str | int]], None]) -> Callable[[], None]:
206-
"""Listen for credits update."""
266+
"""
267+
Listen for credits update.
207268
269+
:param callback: Callback function to handle credits update.
270+
:return: Function to remove the listener.
271+
"""
208272
return self.async_add_listener(
209273
lambda x: callback(x["credits"]),
210274
{"credits": None}
211275
)
212276

213277
def listen_Balance(self, callback: Callable[[int], None]) -> Callable[[], None]:
214-
"""Listen for credits balance."""
278+
"""
279+
Listen for credits balance.
215280
281+
:param callback: Callback function to handle credits balance.
282+
:return: Function to remove the listener.
283+
"""
216284
return self.async_add_listener(
217285
lambda x: callback(x["credits"]["balance"]),
218286
{"credits": {"balance": None}}
219287
)
220288

221289
def recursive_match(dict1, dict2):
222-
"""Recursively match dict1 with dict2."""
290+
"""
291+
Recursively match dict1 with dict2.
292+
293+
:param dict1: First dictionary.
294+
:param dict2: Second dictionary.
295+
:return: True if dict1 matches dict2, False otherwise.
296+
"""
223297
if dict1 is not None:
224298
for key, value1 in dict1.items():
225299
if key not in dict2:

0 commit comments

Comments
 (0)