From a7fbfd4b054c599ab252c5717f3420db5a6820dc Mon Sep 17 00:00:00 2001 From: Alvaro Duarte <59612788+ad-ha@users.noreply.github.com> Date: Tue, 26 Nov 2024 12:22:50 +0100 Subject: [PATCH 1/3] Update manifest.json --- custom_components/mg_saic/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/mg_saic/manifest.json b/custom_components/mg_saic/manifest.json index 009b78c..749e63d 100644 --- a/custom_components/mg_saic/manifest.json +++ b/custom_components/mg_saic/manifest.json @@ -12,5 +12,5 @@ "pycryptodome", "saic-ismart-client-ng==0.5.2" ], - "version": "0.6.1" + "version": "0.6.2" } From 96493e99d3c5ee03a2aade9738ac484b1e2883cf Mon Sep 17 00:00:00 2001 From: Alvaro Duarte <59612788+ad-ha@users.noreply.github.com> Date: Tue, 26 Nov 2024 12:24:44 +0100 Subject: [PATCH 2/3] Adjust Current and Voltage Factors Adjust Current and Voltaga Factors for OnBoard data --- custom_components/mg_saic/const.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/custom_components/mg_saic/const.py b/custom_components/mg_saic/const.py index d0ddb62..ec33487 100644 --- a/custom_components/mg_saic/const.py +++ b/custom_components/mg_saic/const.py @@ -13,8 +13,8 @@ DATA_100_DECIMAL_CORRECTION = 0.01 # Conversion factors for charging data -CHARGING_CURRENT_FACTOR = 0.00095 -CHARGING_VOLTAGE_FACTOR = 0.151 +CHARGING_CURRENT_FACTOR = 0.05 +CHARGING_VOLTAGE_FACTOR = 0.25 # API Base Urls REGION_BASE_URIS = { From 522414c747a600e4633fa58073eb9820ceb31e75 Mon Sep 17 00:00:00 2001 From: Alvaro Duarte <59612788+ad-ha@users.noreply.github.com> Date: Tue, 26 Nov 2024 12:27:37 +0100 Subject: [PATCH 3/3] Adapt Charging Current Sensor and Charging Power Sensor --- custom_components/mg_saic/sensor.py | 102 +++++++++++++++++++++++++++- 1 file changed, 99 insertions(+), 3 deletions(-) diff --git a/custom_components/mg_saic/sensor.py b/custom_components/mg_saic/sensor.py index 83c86d6..0758dbe 100644 --- a/custom_components/mg_saic/sensor.py +++ b/custom_components/mg_saic/sensor.py @@ -292,7 +292,7 @@ async def async_setup_entry(hass, entry, async_add_entities): "chrgMgmtData", "charging", ), - SAICMGChargingSensor( + SAICMGChargingCurrentSensor( coordinator, entry, "Charging Current", @@ -997,6 +997,102 @@ def device_info(self): } +class SAICMGChargingCurrentSensor(CoordinatorEntity, SensorEntity): + """Representation of a MG SAIC charging current sensor""" + + def __init__( + self, + coordinator, + entry, + name, + field, + device_class, + unit, + icon, + state_class, + factor=None, + data_source="chrgMgmtData", + data_type="charging", + ): + """Initialize the sensor.""" + super().__init__(coordinator) + self._name = name + self._field = field + self._device_class = device_class + self._unit = unit + self._state_class = state_class + self._icon = icon + self._factor = factor + self._data_source = data_source + self._data_type = data_type + self._attr_device_class = device_class + self._attr_native_unit_of_measurement = unit + self._attr_icon = icon + self._attr_state_class = state_class + vin_info = self.coordinator.data["info"][0] + self._unique_id = f"{entry.entry_id}_{vin_info.vin}_{field}_charge" + + @property + def unique_id(self): + return self._unique_id + + @property + def name(self): + vin_info = self.coordinator.data["info"][0] + return f"{vin_info.brandName} {vin_info.modelName} {self._name}" + + @property + def available(self): + """Return True if the entity is available.""" + required_data = self.coordinator.data.get(self._data_type) + return self.coordinator.last_update_success and required_data is not None + + @property + def native_value(self): + """Return the state of the sensor""" + try: + charging_data = getattr( + self.coordinator.data.get("charging"), self._data_source, None + ) + if charging_data: + charging_status = getattr(charging_data, "bmsChrgSts", None) + + if charging_status in [0, 5]: + return 0 + + raw_value = getattr(charging_data, self._field, None) + + # Calculate Current + if raw_value is not None and self._factor is not None: + calculated_value = 1000 - (raw_value * self._factor) + return round(calculated_value, 2) + else: + return None + else: + LOGGER.error("No charging data available for %s", self._name) + return None + + except Exception as e: + LOGGER.error( + "Error retrieving charging current sensor %s: %s", + self._name, + e, + exc_info=True, + ) + return None + + @property + def device_info(self): + vin_info = self.coordinator.data["info"][0] + return { + "identifiers": {(DOMAIN, vin_info.vin)}, + "name": f"{vin_info.brandName} {vin_info.modelName}", + "manufacturer": vin_info.brandName, + "model": vin_info.modelName, + "serial_number": vin_info.vin, + } + + class SAICMGChargingPowerSensor(CoordinatorEntity, SensorEntity): """Sensor for Charging Power, calculated from voltage and current.""" @@ -1054,7 +1150,7 @@ def native_value(self): # Fetch the charging status to determine if the sensor should display data charging_status = getattr(charging_data, "bmsChrgSts", None) - if charging_status in [0, 5]: # Not charging or Charging Finished + if charging_status in [0, 5]: return 0 # Get raw current and voltage @@ -1063,7 +1159,7 @@ def native_value(self): if raw_current is not None and raw_voltage is not None: # Apply decoding to current and voltage - decoded_current = raw_current * CHARGING_CURRENT_FACTOR + decoded_current = 1000 - raw_current * CHARGING_CURRENT_FACTOR decoded_voltage = raw_voltage * CHARGING_VOLTAGE_FACTOR # Calculate power in kW