From 8e3eb76e50d1e2c0f941f8db72f6555a4636fc88 Mon Sep 17 00:00:00 2001 From: "Haig (Hike) Hovsepian" Date: Wed, 30 Oct 2024 13:24:26 -0500 Subject: [PATCH 01/12] update reference.md --- REFERENCE.md | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/REFERENCE.md b/REFERENCE.md index 0de0d868..c49865f8 100644 --- a/REFERENCE.md +++ b/REFERENCE.md @@ -383,6 +383,42 @@ Returns a list of all the service records performed on the vehicle, filtered by --- +### `diagnostic_system_status(self)` + +Retrieve the status of various diagnostic systems in the vehicle. + +#### Return + +| Value | Type | Description | +| :---------------------------- | :--------------------- | :------------------------------------------------------------------- | +| `DiagnosticSystemStatus` | typing.NamedTuple | The returned object with diagnostic system statuses data | +| `DiagnosticSystemStatus.systems` | List[Dict] | List of system statuses, each with `system_id`, `status`, and `description` | +| `DiagnosticSystemStatus.meta` | collections.namedtuple | Smartcar response headers (`request_id`, `data_age`, and/or `unit_system`) | + +Each system entry contains: +- `system_id` (String): Unique identifier for the system. +- `status` (String): Status of the system, either "OK" or "ALERT". +- `description` (String, optional): Additional context or description for the status, if any. + +--- + +### `diagnostic_trouble_codes(self)` + +Retrieve active diagnostic trouble codes (DTCs) for the vehicle. + +#### Return + +| Value | Type | Description | +| :------------------------- | :--------------------- | :------------------------------------------------------- | +| `DiagnosticTroubleCodes` | typing.NamedTuple | The returned object with active diagnostic trouble codes | +| `DiagnosticTroubleCodes.active_codes` | List[Dict] | List of active DTCs, each with `code` and `timestamp` | +| `DiagnosticTroubleCodes.meta` | collections.namedtuple | Smartcar response headers (`request_id`, `data_age`, and/or `unit_system`) | + +Each trouble code entry contains: +- `code` (String): The DTC code representing the issue. +- `timestamp` (String, optional): ISO 8601 timestamp when the code was triggered. May be `null` if unavailable. + +--- ### `attributes(self)` Returns a single vehicle object, containing identifying information. From 81fac805047d239c2b5d5dddc731c15c83fa31fe Mon Sep 17 00:00:00 2001 From: "Haig (Hike) Hovsepian" Date: Wed, 30 Oct 2024 13:24:42 -0500 Subject: [PATCH 02/12] types, vehicle.py --- smartcar/types.py | 18 ++++++++++++++++++ smartcar/vehicle.py | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/smartcar/types.py b/smartcar/types.py index a721dc96..352c8341 100644 --- a/smartcar/types.py +++ b/smartcar/types.py @@ -186,6 +186,24 @@ def format_capabilities(capabilities_list: List[dict]) -> List[Capability]: ChargeLimit = NamedTuple("ChargeLimit", [("limit", float), ("meta", namedtuple)]) +class DiagnosticSystem: + system_id: str + status: str + description: Optional[str] = None + +DiagnosticSystemStatus = NamedTuple( + "DiagnosticSystemStatus", + [("systems", List[DiagnosticSystem]), ("meta", namedtuple)], +) + +class DiagnosticTroubleCode: + code: str # + timestamp: Optional[datetime.datetime] = None + +DiagnosticTroubleCodes = NamedTuple( + "DiagnosticTroubleCodes", [("active_codes", List[DiagnosticTroubleCode]), ("meta", namedtuple)] +) + class ServiceCost: total_cost: Optional[float] = None diff --git a/smartcar/vehicle.py b/smartcar/vehicle.py index 6d594fe8..8c6856a4 100644 --- a/smartcar/vehicle.py +++ b/smartcar/vehicle.py @@ -219,6 +219,44 @@ def service_history( response = helpers.requester("GET", url, headers=headers, params=params) return types.select_named_tuple(path, response) + def diagnostic_system_status(self) -> types.DiagnosticSystemStatus: + """ + GET Vehicle.diagnostic_system_status + + Returns: + DiagnosticSystemStatus: NamedTuple("DiagnosticSystemStatus", [ + ("systems", List[DiagnosticSystem]), + ("meta", namedtuple) + ]) + + Raises: + SmartcarException + """ + path = "diagnostics/system_status" + url = self._format_url(path) + headers = self._get_headers() + response = helpers.requester("GET", url, headers=headers) + return types.select_named_tuple(path, response) + + def diagnostic_trouble_codes(self) -> types.DiagnosticTroubleCodes: + """ + GET Vehicle.diagnostic_trouble_codes + + Returns: + DiagnosticTroubleCodes: NamedTuple("DiagnosticTroubleCodes", [ + ("active_codes", List[DiagnosticTroubleCode]), + ("meta", namedtuple) + ]) + + Raises: + SmartcarException + """ + path = "diagnostics/dtcs" + url = self._format_url(path) + headers = self._get_headers() + response = helpers.requester("GET", url, headers=headers) + return types.select_named_tuple(path, response) + def location(self) -> types.Location: """ GET Vehicle.location From 3a5f03a3b5de008a7e66aa221ed64b5591f4a7e3 Mon Sep 17 00:00:00 2001 From: "Haig (Hike) Hovsepian" Date: Wed, 30 Oct 2024 13:27:18 -0500 Subject: [PATCH 03/12] vehicle & batch tests for new endpoints --- tests/conftest.py | 1 + tests/e2e/test_vehicle.py | 44 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/tests/conftest.py b/tests/conftest.py index 3030b556..18a43949 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -163,6 +163,7 @@ def access_ford(client): "required:control_charge", "control_navigation", "read_service_history", + "read_diagnostics", ] ), "FORD", diff --git a/tests/e2e/test_vehicle.py b/tests/e2e/test_vehicle.py index 4fb5a3b0..94ec653b 100644 --- a/tests/e2e/test_vehicle.py +++ b/tests/e2e/test_vehicle.py @@ -170,6 +170,50 @@ def test_service_history(ford_car): assert response._fields == ("items", "meta") +def test_diagnostic_system_status(ford_car): + diagnostic_status = ford_car.diagnostic_system_status() + assert diagnostic_status is not None + assert type(diagnostic_status) == types.DiagnosticSystemStatus + assert diagnostic_status._fields == ("systems", "meta") + + for system in diagnostic_status.systems: + assert isinstance(system, types.DiagnosticSystem) + assert hasattr(system, "name") + assert hasattr(system, "status") + + +def test_diagnostic_trouble_codes(ford_car): + dtc_response = ford_car.diagnostic_trouble_codes() + assert dtc_response is not None + assert type(dtc_response) == types.DiagnosticTroubleCodes + assert dtc_response._fields == ("active_codes", "meta") + + for code in dtc_response.active_codes: + assert isinstance(code, types.DiagnosticTroubleCode) + assert hasattr(code, "code") + assert hasattr(code, "description") + + +def test_batch_diagnostics(ford_car): + batch_response = ford_car.batch(["/diagnostics/system_status", "/diagnostics/dtcs"]) + assert batch_response is not None + assert batch_response._fields == ("diagnostic_system_status", "diagnostic_trouble_codes", "meta") + + diagnostic_status = batch_response.diagnostic_system_status() + assert diagnostic_status is not None + for system in diagnostic_status.systems: + assert isinstance(system, types.DiagnosticSystem) + assert hasattr(system, "name") + assert hasattr(system, "status") + + dtc_response = batch_response.diagnostic_trouble_codes() + assert dtc_response is not None + for code in dtc_response.active_codes: + assert isinstance(code, types.DiagnosticTroubleCode) + assert hasattr(code, "code") + assert hasattr(code, "description") + + def test_batch_success(chevy_volt): batch = chevy_volt.batch( [ From 127358677f61f9f274eb478f31e6661bcefb8ea0 Mon Sep 17 00:00:00 2001 From: "Haig (Hike) Hovsepian" Date: Wed, 30 Oct 2024 13:46:32 -0500 Subject: [PATCH 04/12] map batch path to attribute --- smartcar/helpers.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/smartcar/helpers.py b/smartcar/helpers.py index 4cfe1295..6fe883f1 100644 --- a/smartcar/helpers.py +++ b/smartcar/helpers.py @@ -121,6 +121,8 @@ def format_path_and_attribute_for_batch(raw_path: str) -> tuple: "tires/pressure": "tire_pressure", "": "attributes", "security": "lock_status", + "diagnostics/system_status": "diagnostic_system_status", + "diagnostics/dtcs": "diagnostic_trouble_codes", } formatted_path = raw_path[1:] if raw_path[0] == "/" else raw_path formatted_attribute = mapper.get(formatted_path, formatted_path) From 9c3a0f788879bbf5dd9a495a55204e22e00cebfc Mon Sep 17 00:00:00 2001 From: "Haig (Hike) Hovsepian" Date: Wed, 30 Oct 2024 14:33:43 -0500 Subject: [PATCH 05/12] update select_named_tuple with diagnostics endpoints --- smartcar/types.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/smartcar/types.py b/smartcar/types.py index 352c8341..307fc846 100644 --- a/smartcar/types.py +++ b/smartcar/types.py @@ -448,6 +448,12 @@ def select_named_tuple(path: str, response_or_dict) -> NamedTuple: elif path == "service/history": return ServiceHistory(data, headers) + + elif path == "diagnostics/system_status": + return DiagnosticSystemStatus(data, headers) + + elif path == "diagnostics/dtcs": + return DiagnosticTroubleCodes(data, headers) elif path == "permissions": return Permissions( From 4036cf19161faf79086f626cb2b24bae65e09339 Mon Sep 17 00:00:00 2001 From: "Haig (Hike) Hovsepian" Date: Wed, 30 Oct 2024 15:00:38 -0500 Subject: [PATCH 06/12] update integration tests --- tests/auth_helpers.py | 1 + tests/e2e/test_vehicle.py | 35 +++++++++++++++++------------------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/tests/auth_helpers.py b/tests/auth_helpers.py index 8f4c14d2..1250985a 100644 --- a/tests/auth_helpers.py +++ b/tests/auth_helpers.py @@ -42,6 +42,7 @@ "required:read_engine_oil", "required:read_tires", "required:read_security", + "required:read_diagnostics", ] diff --git a/tests/e2e/test_vehicle.py b/tests/e2e/test_vehicle.py index 94ec653b..cc3180d8 100644 --- a/tests/e2e/test_vehicle.py +++ b/tests/e2e/test_vehicle.py @@ -175,11 +175,11 @@ def test_diagnostic_system_status(ford_car): assert diagnostic_status is not None assert type(diagnostic_status) == types.DiagnosticSystemStatus assert diagnostic_status._fields == ("systems", "meta") - - for system in diagnostic_status.systems: + + systems = [types.DiagnosticSystem(**s) if isinstance(s, dict) else s for s in diagnostic_status.systems] + for system in systems: assert isinstance(system, types.DiagnosticSystem) - assert hasattr(system, "name") - assert hasattr(system, "status") + def test_diagnostic_trouble_codes(ford_car): @@ -187,31 +187,30 @@ def test_diagnostic_trouble_codes(ford_car): assert dtc_response is not None assert type(dtc_response) == types.DiagnosticTroubleCodes assert dtc_response._fields == ("active_codes", "meta") - - for code in dtc_response.active_codes: + + active_codes = [types.DiagnosticTroubleCode(**c) if isinstance(c, dict) else c for c in dtc_response.active_codes] + for code in active_codes: assert isinstance(code, types.DiagnosticTroubleCode) - assert hasattr(code, "code") - assert hasattr(code, "description") + def test_batch_diagnostics(ford_car): batch_response = ford_car.batch(["/diagnostics/system_status", "/diagnostics/dtcs"]) assert batch_response is not None assert batch_response._fields == ("diagnostic_system_status", "diagnostic_trouble_codes", "meta") - + diagnostic_status = batch_response.diagnostic_system_status() assert diagnostic_status is not None - for system in diagnostic_status.systems: + systems = [types.DiagnosticSystem(**s) if isinstance(s, dict) else s for s in diagnostic_status.systems] + for system in systems: assert isinstance(system, types.DiagnosticSystem) - assert hasattr(system, "name") - assert hasattr(system, "status") - - dtc_response = batch_response.diagnostic_trouble_codes() - assert dtc_response is not None - for code in dtc_response.active_codes: + + trouble_codes = batch_response.diagnostic_trouble_codes() + assert trouble_codes is not None + active_codes = [types.DiagnosticTroubleCode(**c) if isinstance(c, dict) else c for c in trouble_codes.active_codes] + for code in active_codes: assert isinstance(code, types.DiagnosticTroubleCode) - assert hasattr(code, "code") - assert hasattr(code, "description") + def test_batch_success(chevy_volt): From 123848edb7d85905ea77599136a0e4a5c1d3ee07 Mon Sep 17 00:00:00 2001 From: "Haig (Hike) Hovsepian" Date: Wed, 30 Oct 2024 15:08:38 -0500 Subject: [PATCH 07/12] fix build err --- tests/auth_helpers.py | 1 - tests/e2e/test_vehicle.py | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/auth_helpers.py b/tests/auth_helpers.py index 1250985a..8f4c14d2 100644 --- a/tests/auth_helpers.py +++ b/tests/auth_helpers.py @@ -42,7 +42,6 @@ "required:read_engine_oil", "required:read_tires", "required:read_security", - "required:read_diagnostics", ] diff --git a/tests/e2e/test_vehicle.py b/tests/e2e/test_vehicle.py index cc3180d8..ee144669 100644 --- a/tests/e2e/test_vehicle.py +++ b/tests/e2e/test_vehicle.py @@ -206,7 +206,6 @@ def test_batch_diagnostics(ford_car): assert isinstance(system, types.DiagnosticSystem) trouble_codes = batch_response.diagnostic_trouble_codes() - assert trouble_codes is not None active_codes = [types.DiagnosticTroubleCode(**c) if isinstance(c, dict) else c for c in trouble_codes.active_codes] for code in active_codes: assert isinstance(code, types.DiagnosticTroubleCode) @@ -303,7 +302,7 @@ def test_permissions_with_paging(chevy_volt): assert permissions is not None assert type(permissions) == types.Permissions assert permissions._fields == ("permissions", "paging", "meta") - assert permissions.paging.count == len(ah.DEFAULT_SCOPE) + assert permissions.paging.count == len(ah.DEFAULT_SCOPE - + 1) assert permissions.paging.offset == 1 From 404605a77b48d1939de521e3472d8a005c0a13c6 Mon Sep 17 00:00:00 2001 From: "Haig (Hike) Hovsepian" Date: Wed, 30 Oct 2024 17:13:49 -0500 Subject: [PATCH 08/12] update tuples, tests --- smartcar/types.py | 34 ++++++++++++++++++++++------------ tests/e2e/test_vehicle.py | 31 +++++++++++++------------------ 2 files changed, 35 insertions(+), 30 deletions(-) diff --git a/smartcar/types.py b/smartcar/types.py index 307fc846..1d866459 100644 --- a/smartcar/types.py +++ b/smartcar/types.py @@ -186,22 +186,24 @@ def format_capabilities(capabilities_list: List[dict]) -> List[Capability]: ChargeLimit = NamedTuple("ChargeLimit", [("limit", float), ("meta", namedtuple)]) -class DiagnosticSystem: - system_id: str - status: str - description: Optional[str] = None +DiagnosticSystem = NamedTuple( + "DiagnosticSystem", + [("system_id", str), ("status", str), ("description", Optional[str])] +) DiagnosticSystemStatus = NamedTuple( "DiagnosticSystemStatus", - [("systems", List[DiagnosticSystem]), ("meta", namedtuple)], + [("systems", List[DiagnosticSystem]), ("meta", namedtuple)] ) -class DiagnosticTroubleCode: - code: str # - timestamp: Optional[datetime.datetime] = None +DiagnosticTroubleCode = NamedTuple( + "DiagnosticTroubleCode", + [("code", str), ("timestamp", Optional[datetime.datetime])] +) DiagnosticTroubleCodes = NamedTuple( - "DiagnosticTroubleCodes", [("active_codes", List[DiagnosticTroubleCode]), ("meta", namedtuple)] + "DiagnosticTroubleCodes", + [("active_codes", List[DiagnosticTroubleCode]), ("meta", namedtuple)] ) @@ -450,10 +452,18 @@ def select_named_tuple(path: str, response_or_dict) -> NamedTuple: return ServiceHistory(data, headers) elif path == "diagnostics/system_status": - return DiagnosticSystemStatus(data, headers) - + systems = [ + DiagnosticSystem(system_id=item["systemId"], status=item["status"], description=item.get("description")) + for item in data["systems"] + ] + return DiagnosticSystemStatus(systems=systems, meta=headers) + elif path == "diagnostics/dtcs": - return DiagnosticTroubleCodes(data, headers) + active_codes = [ + DiagnosticTroubleCode(code=item["code"], timestamp=item.get("timestamp")) + for item in data["activeCodes"] + ] + return DiagnosticTroubleCodes(active_codes=active_codes, meta=headers) elif path == "permissions": return Permissions( diff --git a/tests/e2e/test_vehicle.py b/tests/e2e/test_vehicle.py index ee144669..07976087 100644 --- a/tests/e2e/test_vehicle.py +++ b/tests/e2e/test_vehicle.py @@ -173,41 +173,36 @@ def test_service_history(ford_car): def test_diagnostic_system_status(ford_car): diagnostic_status = ford_car.diagnostic_system_status() assert diagnostic_status is not None - assert type(diagnostic_status) == types.DiagnosticSystemStatus + assert isinstance(diagnostic_status, types.DiagnosticSystemStatus) assert diagnostic_status._fields == ("systems", "meta") - - systems = [types.DiagnosticSystem(**s) if isinstance(s, dict) else s for s in diagnostic_status.systems] - for system in systems: - assert isinstance(system, types.DiagnosticSystem) + for system in diagnostic_status.systems: + assert isinstance(system, types.DiagnosticSystem) def test_diagnostic_trouble_codes(ford_car): dtc_response = ford_car.diagnostic_trouble_codes() assert dtc_response is not None - assert type(dtc_response) == types.DiagnosticTroubleCodes + assert isinstance(dtc_response, types.DiagnosticTroubleCodes) assert dtc_response._fields == ("active_codes", "meta") - - active_codes = [types.DiagnosticTroubleCode(**c) if isinstance(c, dict) else c for c in dtc_response.active_codes] - for code in active_codes: - assert isinstance(code, types.DiagnosticTroubleCode) + for code in dtc_response.active_codes: + assert isinstance(code, types.DiagnosticTroubleCode) def test_batch_diagnostics(ford_car): batch_response = ford_car.batch(["/diagnostics/system_status", "/diagnostics/dtcs"]) assert batch_response is not None assert batch_response._fields == ("diagnostic_system_status", "diagnostic_trouble_codes", "meta") - + diagnostic_status = batch_response.diagnostic_system_status() assert diagnostic_status is not None - systems = [types.DiagnosticSystem(**s) if isinstance(s, dict) else s for s in diagnostic_status.systems] - for system in systems: + for system in diagnostic_status.systems: assert isinstance(system, types.DiagnosticSystem) - - trouble_codes = batch_response.diagnostic_trouble_codes() - active_codes = [types.DiagnosticTroubleCode(**c) if isinstance(c, dict) else c for c in trouble_codes.active_codes] - for code in active_codes: + + dtc_response = batch_response.diagnostic_trouble_codes() + assert dtc_response is not None + for code in dtc_response.active_codes: assert isinstance(code, types.DiagnosticTroubleCode) @@ -302,7 +297,7 @@ def test_permissions_with_paging(chevy_volt): assert permissions is not None assert type(permissions) == types.Permissions assert permissions._fields == ("permissions", "paging", "meta") - assert permissions.paging.count == len(ah.DEFAULT_SCOPE - + 1) + assert permissions.paging.count == len(ah.DEFAULT_SCOPE) + 1 assert permissions.paging.offset == 1 From df43cc921c16bdca331f78af532629b4cada5443 Mon Sep 17 00:00:00 2001 From: "Haig (Hike) Hovsepian" Date: Thu, 31 Oct 2024 10:07:07 -0500 Subject: [PATCH 09/12] readjust permission count test --- tests/e2e/test_vehicle.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/test_vehicle.py b/tests/e2e/test_vehicle.py index 07976087..8068d755 100644 --- a/tests/e2e/test_vehicle.py +++ b/tests/e2e/test_vehicle.py @@ -297,7 +297,7 @@ def test_permissions_with_paging(chevy_volt): assert permissions is not None assert type(permissions) == types.Permissions assert permissions._fields == ("permissions", "paging", "meta") - assert permissions.paging.count == len(ah.DEFAULT_SCOPE) + 1 + assert permissions.paging.count == len(ah.DEFAULT_SCOPE) assert permissions.paging.offset == 1 From 8abdf81b7ea4246bf4c2f541adaab27db4e0e18a Mon Sep 17 00:00:00 2001 From: "Haig (Hike) Hovsepian" Date: Thu, 31 Oct 2024 11:19:24 -0500 Subject: [PATCH 10/12] skip send destination test --- tests/e2e/test_vehicle.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/tests/e2e/test_vehicle.py b/tests/e2e/test_vehicle.py index 8068d755..c297e5c5 100644 --- a/tests/e2e/test_vehicle.py +++ b/tests/e2e/test_vehicle.py @@ -138,13 +138,15 @@ def test_set_charge_limit(ford_car): assert type(response) == types.Action assert response._fields == ("status", "message", "meta") - -def test_send_destination(ford_car): - # The latitude and longitude of the Empire State Building in New York, USA. - response = ford_car.send_destination(40.748817, -73.985428) - assert response.status == "success" - assert type(response) == types.Action - assert response._fields == ("status", "message", "meta") +# Send destination tests are not working following a simulated mode merge project +# skipping for now + +# def test_send_destination(ford_car): +# # The latitude and longitude of the Empire State Building in New York, USA. +# response = ford_car.send_destination(40.748817, -73.985428) +# assert response.status == "success" +# assert type(response) == types.Action +# assert response._fields == ("status", "message", "meta") def test_service_history(ford_car): From aa0d2dc95e74a06f3b539e413f08ac038b509a42 Mon Sep 17 00:00:00 2001 From: "Haig (Hike) Hovsepian" Date: Thu, 31 Oct 2024 11:57:01 -0500 Subject: [PATCH 11/12] unskip test after fix deployment --- tests/e2e/test_vehicle.py | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/tests/e2e/test_vehicle.py b/tests/e2e/test_vehicle.py index c297e5c5..7689447b 100644 --- a/tests/e2e/test_vehicle.py +++ b/tests/e2e/test_vehicle.py @@ -138,15 +138,12 @@ def test_set_charge_limit(ford_car): assert type(response) == types.Action assert response._fields == ("status", "message", "meta") -# Send destination tests are not working following a simulated mode merge project -# skipping for now - -# def test_send_destination(ford_car): -# # The latitude and longitude of the Empire State Building in New York, USA. -# response = ford_car.send_destination(40.748817, -73.985428) -# assert response.status == "success" -# assert type(response) == types.Action -# assert response._fields == ("status", "message", "meta") +def test_send_destination(ford_car): + # The latitude and longitude of the Empire State Building in New York, USA. + response = ford_car.send_destination(40.748817, -73.985428) + assert response.status == "success" + assert type(response) == types.Action + assert response._fields == ("status", "message", "meta") def test_service_history(ford_car): From 9535000ea015f7d1e61a3a83a515d2f7d2a119dc Mon Sep 17 00:00:00 2001 From: "Haig (Hike) Hovsepian" Date: Thu, 31 Oct 2024 12:29:36 -0500 Subject: [PATCH 12/12] format code --- smartcar/types.py | 17 ++++++++++------- tests/e2e/test_vehicle.py | 8 ++++++-- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/smartcar/types.py b/smartcar/types.py index 1d866459..d5abe666 100644 --- a/smartcar/types.py +++ b/smartcar/types.py @@ -188,22 +188,21 @@ def format_capabilities(capabilities_list: List[dict]) -> List[Capability]: DiagnosticSystem = NamedTuple( "DiagnosticSystem", - [("system_id", str), ("status", str), ("description", Optional[str])] + [("system_id", str), ("status", str), ("description", Optional[str])], ) DiagnosticSystemStatus = NamedTuple( "DiagnosticSystemStatus", - [("systems", List[DiagnosticSystem]), ("meta", namedtuple)] + [("systems", List[DiagnosticSystem]), ("meta", namedtuple)], ) DiagnosticTroubleCode = NamedTuple( - "DiagnosticTroubleCode", - [("code", str), ("timestamp", Optional[datetime.datetime])] + "DiagnosticTroubleCode", [("code", str), ("timestamp", Optional[datetime.datetime])] ) DiagnosticTroubleCodes = NamedTuple( "DiagnosticTroubleCodes", - [("active_codes", List[DiagnosticTroubleCode]), ("meta", namedtuple)] + [("active_codes", List[DiagnosticTroubleCode]), ("meta", namedtuple)], ) @@ -450,10 +449,14 @@ def select_named_tuple(path: str, response_or_dict) -> NamedTuple: elif path == "service/history": return ServiceHistory(data, headers) - + elif path == "diagnostics/system_status": systems = [ - DiagnosticSystem(system_id=item["systemId"], status=item["status"], description=item.get("description")) + DiagnosticSystem( + system_id=item["systemId"], + status=item["status"], + description=item.get("description"), + ) for item in data["systems"] ] return DiagnosticSystemStatus(systems=systems, meta=headers) diff --git a/tests/e2e/test_vehicle.py b/tests/e2e/test_vehicle.py index 7689447b..3a8a0858 100644 --- a/tests/e2e/test_vehicle.py +++ b/tests/e2e/test_vehicle.py @@ -138,6 +138,7 @@ def test_set_charge_limit(ford_car): assert type(response) == types.Action assert response._fields == ("status", "message", "meta") + def test_send_destination(ford_car): # The latitude and longitude of the Empire State Building in New York, USA. response = ford_car.send_destination(40.748817, -73.985428) @@ -192,7 +193,11 @@ def test_diagnostic_trouble_codes(ford_car): def test_batch_diagnostics(ford_car): batch_response = ford_car.batch(["/diagnostics/system_status", "/diagnostics/dtcs"]) assert batch_response is not None - assert batch_response._fields == ("diagnostic_system_status", "diagnostic_trouble_codes", "meta") + assert batch_response._fields == ( + "diagnostic_system_status", + "diagnostic_trouble_codes", + "meta", + ) diagnostic_status = batch_response.diagnostic_system_status() assert diagnostic_status is not None @@ -205,7 +210,6 @@ def test_batch_diagnostics(ford_car): assert isinstance(code, types.DiagnosticTroubleCode) - def test_batch_success(chevy_volt): batch = chevy_volt.batch( [