diff --git a/.gitignore b/.gitignore index fdc1fe4..babe516 100644 --- a/.gitignore +++ b/.gitignore @@ -188,4 +188,7 @@ fabric.properties tests/test_saic_api_no_mock.py run_decoder.sh -junit/ \ No newline at end of file +junit/ + +# CodeBuddy +.codebuddy/ \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 7b3eca1..0481372 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [tool.poetry] name = "saic_ismart_client_ng" homepage = "https://github.com/SAIC-iSmart-API/saic-python-client-ng" -version = "0.5.2" +version = "0.5.3" description = "SAIC next gen client library (MG iSMART)" authors = [ "Giovanni Condello ", diff --git a/src/saic_ismart_client_ng/api/vehicle_charging/__init__.py b/src/saic_ismart_client_ng/api/vehicle_charging/__init__.py index 3c5c08f..c88da39 100644 --- a/src/saic_ismart_client_ng/api/vehicle_charging/__init__.py +++ b/src/saic_ismart_client_ng/api/vehicle_charging/__init__.py @@ -55,6 +55,14 @@ async def control_charging(self, vin: str, *, stop_charging: bool) -> ChargingCo ) return await self.send_vehicle_charging_control(vin, body) + async def control_v2x(self, vin: str, *, stop_v2x: bool) -> ChargingControlResp: + body = ChargingControlRequest( + chrgCtrlReq=0, + tboxV2XReq=2 if stop_v2x else 1, + tboxEleccLckCtrlReq=0, + ) + return await self.send_vehicle_charging_control(vin, body) + async def send_vehicle_charging_reservation( self, vin: str, @@ -170,6 +178,15 @@ async def send_vehicle_charging_settings(self, vin: str, body: ChargingSettingRe out_type=ChargingSettingResp ) + async def get_vehicle_charging_settings(self, vin: str) -> ChargingSettingResp: + body = ChargingSettingRequest( + altngChrgCrntReq=0, + onBdChrgTrgtSOCReq=0, + tboxV2XSpSOCReq=0, + vin=sha256_hex_digest(vin) + ) + return await self.send_vehicle_charging_settings(vin, body) + async def set_target_battery_soc( self, vin: str, @@ -183,3 +200,16 @@ async def set_target_battery_soc( vin=sha256_hex_digest(vin) ) return await self.send_vehicle_charging_settings(vin, body) + + async def set_v2x_target_battery_soc( + self, + vin: str, + target_soc: TargetBatteryCode + ) -> ChargingSettingResp: + body = ChargingSettingRequest( + onBdChrgTrgtSOCReq=0, + altngChrgCrntReq=0, + tboxV2XSpSOCReq=target_soc.value, + vin=sha256_hex_digest(vin) + ) + return await self.send_vehicle_charging_settings(vin, body) diff --git a/src/saic_ismart_client_ng/api/vehicle_charging/schema.py b/src/saic_ismart_client_ng/api/vehicle_charging/schema.py index 0a186dd..5fad1b0 100644 --- a/src/saic_ismart_client_ng/api/vehicle_charging/schema.py +++ b/src/saic_ismart_client_ng/api/vehicle_charging/schema.py @@ -104,6 +104,7 @@ def to_code(code: int): class TargetBatteryCode(Enum): + P_IGNORE = 0 P_40 = 1 P_50 = 2 P_60 = 3 @@ -257,6 +258,14 @@ def charge_target_soc(self) -> Optional[TargetBatteryCode]: except ValueError: return None + @property + def charge_current_limit(self) -> Optional[ChargeCurrentLimitCode]: + raw_charge_current_limit = self.bmsAltngChrgCrntDspCmd + try: + return ChargeCurrentLimitCode(raw_charge_current_limit) + except ValueError: + return None + @property def is_battery_heating(self) -> bool: return self.bmsPTCHeatReqDspCmd == 1 @@ -349,6 +358,30 @@ class ChargingSettingResp: def rvc_req_sts_decoded(self) -> Optional[bytes]: return decode_bytes(input_value=self.rvcReqSts, field_name='rvcReqSts') + @property + def charge_target_soc(self) -> Optional[TargetBatteryCode]: + raw_target_soc = self.bmsOnBdChrgTrgtSOCDspCmd + try: + return TargetBatteryCode(raw_target_soc) + except ValueError: + return None + + @property + def charge_current_limit(self) -> Optional[ChargeCurrentLimitCode]: + raw_charge_current_limit = self.bmsAltngChrgCrntDspCmd + try: + return ChargeCurrentLimitCode(raw_charge_current_limit) + except ValueError: + return None + + @property + def v2x_target_soc(self) -> Optional[TargetBatteryCode]: + raw_target_soc = self.imcuDschrgTrgtSOCDspCmd + try: + return TargetBatteryCode(raw_target_soc) + except ValueError: + return None + @dataclass class ScheduledChargingRequest: @@ -399,6 +432,7 @@ def heating_stop_reason(self) -> HeatingStopReason | None: return HeatingStopReason.to_code(self.ptcHeatResp) return None + @dataclass class ChargingControlRequest: chrgCtrlReq: int = None @@ -477,6 +511,22 @@ def charge_target_soc(self) -> Optional[TargetBatteryCode]: except ValueError: return None + @property + def charge_current_limit(self) -> Optional[ChargeCurrentLimitCode]: + raw_charge_current_limit = self.bmsAltngChrgCrntDspCmd + try: + return ChargeCurrentLimitCode(raw_charge_current_limit) + except ValueError: + return None + + @property + def v2x_target_soc(self) -> Optional[TargetBatteryCode]: + raw_target_soc = self.imcuDschrgTrgtSOCDspCmd + try: + return TargetBatteryCode(raw_target_soc) + except ValueError: + return None + @property def is_battery_heating(self) -> bool: return self.bmsPTCHeatReqDspCmd == 1