@@ -51,14 +51,14 @@ def __init__(
5151 self ,
5252 client : ClientSession ,
5353 token_manager : AccessTokenManager ,
54- vin : str ,
5554 api_key : str ,
55+ vin : str = "" ,
5656 ) -> None :
5757 """Initialize Volvo Cars API."""
5858 self ._client = client
5959 self ._token_manager = token_manager
60- self ._vin = vin
61- self ._api_key = api_key
60+ self .api_key = api_key
61+ self .vin = vin
6262
6363 async def async_get_api_status (self ) -> dict [str , VolvoCarsValue ]:
6464 """Check the API status."""
@@ -81,84 +81,84 @@ async def async_get_api_status(self) -> dict[str, VolvoCarsValue]:
8181
8282 return {"apiStatus" : VolvoCarsValue (message )}
8383
84- async def async_get_brakes_status (self ) -> dict [str , VolvoCarsValueField | None ]:
84+ async def async_get_brakes_status (self , vin : str = "" ) -> dict [str , VolvoCarsValueField | None ]:
8585 """Get brakes status.
8686
8787 Required scopes: openid conve:brake_status
8888 """
89- return await self ._async_get_field (_API_CONNECTED_ENDPOINT , "brakes" )
89+ return await self ._async_get_field (_API_CONNECTED_ENDPOINT , "brakes" , vin )
9090
9191 async def async_get_command_accessibility (
92- self ,
92+ self , vin : str = ""
9393 ) -> dict [str , VolvoCarsValueField | None ]:
9494 """Get availability status.
9595
9696 Required scopes: openid conve:command_accessibility
9797 """
9898 return await self ._async_get_field (
99- _API_CONNECTED_ENDPOINT , "command-accessibility"
99+ _API_CONNECTED_ENDPOINT , "command-accessibility" , vin
100100 )
101101
102- async def async_get_commands (self ) -> list [VolvoCarsAvailableCommand | None ]:
102+ async def async_get_commands (self , vin : str = "" ) -> list [VolvoCarsAvailableCommand | None ]:
103103 """Get available commands.
104104
105105 Required scopes: openid conve:commands
106106 """
107- body = await self ._async_get (_API_CONNECTED_ENDPOINT , "commands" )
107+ body = await self ._async_get (_API_CONNECTED_ENDPOINT , "commands" , vin )
108108 items = self ._get_data_list (body )
109109 return [VolvoCarsAvailableCommand .from_dict (item ) for item in items ]
110110
111- async def async_get_diagnostics (self ) -> dict [str , VolvoCarsValueField | None ]:
111+ async def async_get_diagnostics (self , vin : str = "" ) -> dict [str , VolvoCarsValueField | None ]:
112112 """Get diagnostics.
113113
114114 Required scopes: openid conve:diagnostics_workshop
115115 """
116- return await self ._async_get_field (_API_CONNECTED_ENDPOINT , "diagnostics" )
116+ return await self ._async_get_field (_API_CONNECTED_ENDPOINT , "diagnostics" , vin )
117117
118- async def async_get_doors_status (self ) -> dict [str , VolvoCarsValueField | None ]:
118+ async def async_get_doors_status (self , vin : str = "" ) -> dict [str , VolvoCarsValueField | None ]:
119119 """Get doors status.
120120
121121 Required scopes: openid conve:doors_status conve:lock_status
122122 """
123- return await self ._async_get_field (_API_CONNECTED_ENDPOINT , "doors" )
123+ return await self ._async_get_field (_API_CONNECTED_ENDPOINT , "doors" , vin )
124124
125- async def async_get_engine_status (self ) -> dict [str , VolvoCarsValueField | None ]:
125+ async def async_get_engine_status (self , vin : str = "" ) -> dict [str , VolvoCarsValueField | None ]:
126126 """Get engine status.
127127
128128 Required scopes: openid conve:engine_status
129129 """
130- return await self ._async_get_field (_API_CONNECTED_ENDPOINT , "engine-status" )
130+ return await self ._async_get_field (_API_CONNECTED_ENDPOINT , "engine-status" , vin )
131131
132- async def async_get_engine_warnings (self ) -> dict [str , VolvoCarsValueField | None ]:
132+ async def async_get_engine_warnings (self , vin : str = "" ) -> dict [str , VolvoCarsValueField | None ]:
133133 """Get engine warnings.
134134
135135 Required scopes: openid conve:diagnostics_engine_status
136136 """
137- return await self ._async_get_field (_API_CONNECTED_ENDPOINT , "engine" )
137+ return await self ._async_get_field (_API_CONNECTED_ENDPOINT , "engine" , vin )
138138
139- async def async_get_fuel_status (self ) -> dict [str , VolvoCarsValueField | None ]:
139+ async def async_get_fuel_status (self , vin : str = "" ) -> dict [str , VolvoCarsValueField | None ]:
140140 """Get fuel status.
141141
142142 Required scopes: openid conve:fuel_status conve:battery_charge_level
143143 """
144- return await self ._async_get_field (_API_CONNECTED_ENDPOINT , "fuel" )
144+ return await self ._async_get_field (_API_CONNECTED_ENDPOINT , "fuel" , vin )
145145
146- async def async_get_location (self ) -> dict [str , VolvoCarsLocation | None ]:
146+ async def async_get_location (self , vin : str = "" ) -> dict [str , VolvoCarsLocation | None ]:
147147 """Get location.
148148
149149 Required scopes: openid location:read
150150 """
151- data = await self ._async_get_data_dict (_API_LOCATION_ENDPOINT , "location" )
151+ data = await self ._async_get_data_dict (_API_LOCATION_ENDPOINT , "location" , vin )
152152 return {"location" : VolvoCarsLocation .from_dict (data )}
153153
154- async def async_get_odometer (self ) -> dict [str , VolvoCarsValueField | None ]:
154+ async def async_get_odometer (self , vin : str = "" ) -> dict [str , VolvoCarsValueField | None ]:
155155 """Get odometer.
156156
157157 Required scopes: openid conve:odometer_status
158158 """
159- return await self ._async_get_field (_API_CONNECTED_ENDPOINT , "odometer" )
159+ return await self ._async_get_field (_API_CONNECTED_ENDPOINT , "odometer" , vin )
160160
161- async def async_get_recharge_status (self ) -> dict [str , VolvoCarsValueField | None ]:
161+ async def async_get_recharge_status (self , vin : str = "" ) -> dict [str , VolvoCarsValueField | None ]:
162162 """Get recharge status.
163163
164164 Required scopes: openid
@@ -169,21 +169,21 @@ async def async_get_recharge_status(self) -> dict[str, VolvoCarsValueField | Non
169169 energy:charging_system_status energy:charging_current_limit
170170 energy:target_battery_level
171171 """
172- return await self ._async_get_field (_API_ENERGY_ENDPOINT , "recharge-status" )
172+ return await self ._async_get_field (_API_ENERGY_ENDPOINT , "recharge-status" , vin )
173173
174- async def async_get_statistics (self ) -> dict [str , VolvoCarsValueField | None ]:
174+ async def async_get_statistics (self , vin : str = "" ) -> dict [str , VolvoCarsValueField | None ]:
175175 """Get statistics.
176176
177177 Required scopes: openid conve:trip_statistics
178178 """
179- return await self ._async_get_field (_API_CONNECTED_ENDPOINT , "statistics" )
179+ return await self ._async_get_field (_API_CONNECTED_ENDPOINT , "statistics" , vin )
180180
181- async def async_get_tyre_states (self ) -> dict [str , VolvoCarsValueField | None ]:
181+ async def async_get_tyre_states (self , vin : str = "" ) -> dict [str , VolvoCarsValueField | None ]:
182182 """Get tyre states.
183183
184184 Required scopes: openid conve:tyre_status
185185 """
186- return await self ._async_get_field (_API_CONNECTED_ENDPOINT , "tyres" )
186+ return await self ._async_get_field (_API_CONNECTED_ENDPOINT , "tyres" , vin )
187187
188188 async def async_get_vehicles (self ) -> list [str ]:
189189 """Get vehicles.
@@ -195,30 +195,30 @@ async def async_get_vehicles(self) -> list[str]:
195195 items = self ._get_data_list (body )
196196 return [item ["vin" ] for item in items ]
197197
198- async def async_get_vehicle_details (self ) -> VolvoCarsVehicle | None :
198+ async def async_get_vehicle_details (self , vin : str = "" ) -> VolvoCarsVehicle | None :
199199 """Get vehicle details.
200200
201201 Required scopes: openid conve:vehicle_relation
202202 """
203203 data = await self ._async_get_data_dict (_API_CONNECTED_ENDPOINT , "" )
204204 return VolvoCarsVehicle .from_dict (data )
205205
206- async def async_get_warnings (self ) -> dict [str , VolvoCarsValueField | None ]:
206+ async def async_get_warnings (self , vin : str = "" ) -> dict [str , VolvoCarsValueField | None ]:
207207 """Get warnings.
208208
209209 Required scopes: openid conve:warnings
210210 """
211- return await self ._async_get_field (_API_CONNECTED_ENDPOINT , "warnings" )
211+ return await self ._async_get_field (_API_CONNECTED_ENDPOINT , "warnings" , vin )
212212
213- async def async_get_window_states (self ) -> dict [str , VolvoCarsValueField | None ]:
213+ async def async_get_window_states (self , vin : str = "" ) -> dict [str , VolvoCarsValueField | None ]:
214214 """Get window states.
215215
216216 Required scopes: openid conve:windows_status
217217 """
218- return await self ._async_get_field (_API_CONNECTED_ENDPOINT , "windows" )
218+ return await self ._async_get_field (_API_CONNECTED_ENDPOINT , "windows" , vin )
219219
220220 async def async_execute_command (
221- self , command : str , body : dict [str , Any ] | None = None
221+ self , command : str , body : dict [str , Any ] | None = None , vin : str = ""
222222 ) -> VolvoCarsCommandResult | None :
223223 """Execute a command.
224224
@@ -235,45 +235,48 @@ async def async_execute_command(
235235 - unlock: conve:unlock
236236 """
237237 body = await self ._async_post (
238- _API_CONNECTED_ENDPOINT , f"commands/{ command } " , body
238+ _API_CONNECTED_ENDPOINT , f"commands/{ command } " , body = body , vin = vin
239239 )
240240 data : dict = body .get ("data" , {})
241241 data ["invoke_status" ] = data .pop ("invokeStatus" , None )
242242 return VolvoCarsCommandResult .from_dict (data )
243243
244244 async def _async_get_field (
245- self , endpoint : str , operation : str
245+ self , endpoint : str , operation : str , vin : str = ""
246246 ) -> dict [str , VolvoCarsValueField | None ]:
247- body = await self ._async_get (endpoint , operation )
247+ body = await self ._async_get (endpoint , operation , vin )
248248 data : dict = body .get ("data" , {})
249249 return {
250250 key : VolvoCarsValueField .from_dict (value ) for key , value in data .items ()
251251 }
252252
253253 async def _async_get_data_dict (
254- self , endpoint : str , operation : str
254+ self , endpoint : str , operation : str , vin : str = ""
255255 ) -> dict [str , Any ]:
256- body = await self ._async_get (endpoint , operation )
256+ body = await self ._async_get (endpoint , operation , vin )
257257 return cast (dict [str , Any ], body .get ("data" , {}))
258258
259- async def _async_get (self , endpoint : str , operation : str ) -> dict [str , Any ]:
260- url = self ._create_vin_url (endpoint , operation )
261- return await self ._async_request (hdrs .METH_GET , url , operation = operation )
259+ async def _async_get (self , endpoint : str , operation : str , vin : str = "" ) -> dict [str , Any ]:
260+ url = self ._create_vin_url (endpoint , operation , vin )
261+ return await self ._async_request (hdrs .METH_GET , url , operation = operation , vin = vin )
262262
263263 async def _async_post (
264- self , endpoint : str , operation : str , body : dict [str , Any ] | None = None
264+ self , endpoint : str , operation : str , * , body : dict [str , Any ] | None = None , vin : str = ""
265265 ) -> dict [str , Any ]:
266- url = self ._create_vin_url (endpoint , operation )
267- return await self ._async_request (hdrs .METH_POST , url , operation = operation , body = body )
266+ url = self ._create_vin_url (endpoint , operation , vin )
267+ return await self ._async_request (hdrs .METH_POST , url , operation = operation , body = body , vin = vin )
268268
269269 def _get_data_list (self , body : dict [str , Any ]) -> list [Any ]:
270270 return cast (list [Any ], body .get ("data" , []))
271271
272- def _create_vin_url (self , endpoint : str , operation : str ) -> str :
272+ def _create_vin_url (self , endpoint : str , operation : str , vin : str = "" ) -> str :
273+ if not vin :
274+ vin = self .vin
275+
273276 return (
274- f"{ _API_URL } { endpoint } /{ self . _vin } /{ operation } "
277+ f"{ _API_URL } { endpoint } /{ vin } /{ operation } "
275278 if operation
276- else f"{ _API_URL } { endpoint } /{ self . _vin } "
279+ else f"{ _API_URL } { endpoint } /{ vin } "
277280 )
278281
279282 async def _async_request (
@@ -283,11 +286,12 @@ async def _async_request(
283286 * ,
284287 operation : str ,
285288 body : dict [str , Any ] | None = None ,
289+ vin : str = "" ,
286290 ) -> dict [str , Any ]:
287291 access_token = await self ._token_manager .async_get_access_token ()
288292 headers = {
289293 hdrs .AUTHORIZATION : f"Bearer { access_token } " ,
290- "vcc-api-key" : self ._api_key ,
294+ "vcc-api-key" : self .api_key ,
291295 }
292296
293297 if method == hdrs .METH_POST :
@@ -300,7 +304,7 @@ async def _async_request(
300304 "Request [%s]: %s %s" ,
301305 operation ,
302306 method ,
303- redact_url (url , self . _vin ),
307+ redact_url (url , vin ),
304308 )
305309 async with self ._client .request (
306310 method , url , headers = headers , json = body , timeout = _API_REQUEST_TIMEOUT
@@ -324,13 +328,13 @@ async def _async_request(
324328 if ex .status == 422 and "/commands" in url :
325329 return {
326330 "data" : {
327- "vin" : self . _vin ,
331+ "vin" : vin ,
328332 "invokeStatus" : "UNKNOWN" ,
329333 "message" : "" ,
330334 }
331335 }
332336
333- redacted_exception = RedactedClientResponseError (ex , self . _vin )
337+ redacted_exception = RedactedClientResponseError (ex , vin )
334338 message = redacted_exception .message
335339
336340 if data and (error_data := data .get ("error" )):
0 commit comments