diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b40ecd4..1762738d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,12 +3,15 @@ ## v1.0.x * Added: Bluetooth: Show signal strength of BMS in log by @mr-manuel * Added: Create unique identifier, if not provided from BMS by @mr-manuel +* Added: Current average of the last 5 minutes by @mr-manuel * Added: Daly BMS: Auto reset SoC when changing to float (can be turned off in the config file) by @transistorgit * Added: Exclude a device from beeing used by the dbus-serialbattery driver by @mr-manuel * Added: Implement callback function for update by @seidler2547 * Added: JKBMS BLE - Show last five characters from the MAC address in the custom name (which is displayed in the device list) by @mr-manuel * Added: Load to bulk voltage every x days to reset the SoC to 100% for some BMS by @mr-manuel * Added: Save custom name and make it restart persistant by @mr-manuel +* Added: Temperature names to dbus and mqtt by @mr-manuel +* Added: Use current average of the last 300 cycles for time to go and time to SoC calculation by @mr-manuel * Added: Validate current, voltage, capacity and SoC for all BMS. This prevents that a device, which is no BMS, is detected as BMS. Fixes also https://github.com/Louisvdw/dbus-serialbattery/issues/479 by @mr-manuel * Changed: Enable BMS that are disabled by default by specifying it in the config file. No more need to edit scripts by @mr-manuel * Changed: Fix daly readsentence by @transistorgit @@ -22,6 +25,8 @@ * Changed: Improved driver reinstall when multiple Bluetooth BMS are enabled by @mr-manuel * Changed: Improved Jkbms_Ble driver by @seidler2547 & @mr-manuel * Changed: Reduce the big inrush current if the CVL jumps from Bulk/Absorbtion to Float https://github.com/Louisvdw/dbus-serialbattery/issues/659 by @Rikkert-RS & @ogurevich +* Changed: Time-to-Go and Time-to-SoC use the current average of the last 5 minutes for calculation by @mr-manuel +* Changed: Time-to-SoC calculate only positive points by @mr-manuel * Removed: Cronjob to restart Bluetooth service every 12 hours by @mr-manuel diff --git a/etc/dbus-serialbattery/battery.py b/etc/dbus-serialbattery/battery.py index af2f56ae..b6111786 100644 --- a/etc/dbus-serialbattery/battery.py +++ b/etc/dbus-serialbattery/battery.py @@ -83,6 +83,8 @@ def init_values(self): """ self.voltage = None self.current = None + self.current_avg = None + self.current_avg_lst = [] self.capacity_remain = None self.capacity = None self.cycles = None @@ -258,10 +260,12 @@ def prepare_voltage_management(self) -> None: or utils.BULK_AFTER_DAYS < bulk_last_reached_days_ago ) ): + """ logger.info( f"set bulk_requested to True: first time (0) or {utils.BULK_AFTER_DAYS}" + f" < {round(bulk_last_reached_days_ago, 2)}" ) + """ self.bulk_requested = True self.bulk_battery_voltage = round(utils.BULK_CELL_VOLTAGE * self.cell_count, 2) @@ -394,7 +398,7 @@ def manage_charge_voltage_linear(self) -> None: chargeMode = "Float" # reset bulk when going into float if self.bulk_requested: - logger.info("set bulk_requested to False") + # logger.info("set bulk_requested to False") self.bulk_requested = False # IDEA: Save "bulk_last_reached" in the dbus path com.victronenergy.settings # to make it restart persistent @@ -434,7 +438,7 @@ def manage_charge_voltage_linear(self) -> None: self.charge_mode += " (Linear Mode)" # uncomment for enabling debugging infos in GUI - # """ + """ self.charge_mode_debug = ( f"max_battery_voltage: {round(self.max_battery_voltage, 2)}V" ) @@ -548,7 +552,7 @@ def manage_charge_voltage_step(self) -> None: self.charge_mode = "Float" # reset bulk when going into float if self.bulk_requested: - logger.info("set bulk_requested to False") + # logger.info("set bulk_requested to False") self.bulk_requested = False self.bulk_last_reached = current_time @@ -879,6 +883,14 @@ def get_timeToSoc(self, socnum, crntPrctPerSec, onlyNumber=False) -> str: else: diffSoc = self.soc - socnum + """ + calculate only positive SoC points, since negative points have no sense + when charging only points above current SoC are shown + when discharging only points below current SoC are shown + """ + if diffSoc < 0: + return None + ttgStr = None if self.soc != socnum and (diffSoc > 0 or utils.TIME_TO_SOC_INC_FROM is True): secondstogo = int(diffSoc / crntPrctPerSec) diff --git a/etc/dbus-serialbattery/dbushelper.py b/etc/dbus-serialbattery/dbushelper.py index a9878dec..3266665f 100644 --- a/etc/dbus-serialbattery/dbushelper.py +++ b/etc/dbus-serialbattery/dbushelper.py @@ -210,9 +210,13 @@ def setup_vedbus(self): self._dbusservice.add_path("/System/MaxTemperatureCellId", None, writeable=True) self._dbusservice.add_path("/System/MOSTemperature", None, writeable=True) self._dbusservice.add_path("/System/Temperature1", None, writeable=True) + self._dbusservice.add_path("/System/Temperature1Name", None, writeable=True) self._dbusservice.add_path("/System/Temperature2", None, writeable=True) + self._dbusservice.add_path("/System/Temperature2Name", None, writeable=True) self._dbusservice.add_path("/System/Temperature3", None, writeable=True) + self._dbusservice.add_path("/System/Temperature3Name", None, writeable=True) self._dbusservice.add_path("/System/Temperature4", None, writeable=True) + self._dbusservice.add_path("/System/Temperature4Name", None, writeable=True) self._dbusservice.add_path( "/System/MaxCellVoltage", None, @@ -311,6 +315,12 @@ def setup_vedbus(self): # Create TimeToGo item if utils.TIME_TO_GO_ENABLE: self._dbusservice.add_path("/TimeToGo", None, writeable=True) + self._dbusservice.add_path( + "/CurrentAvg", + None, + writeable=True, + gettextcallback=lambda p, v: "{:0.2f}A".format(v), + ) # Create TimeToSoc items if len(utils.TIME_TO_SOC_POINTS) > 0: @@ -463,9 +473,13 @@ def publish_dbus(self): ] = self.battery.get_max_temp_id() self._dbusservice["/System/MOSTemperature"] = self.battery.get_mos_temp() self._dbusservice["/System/Temperature1"] = self.battery.temp1 + self._dbusservice["/System/Temperature1Name"] = utils.TEMP_1_NAME self._dbusservice["/System/Temperature2"] = self.battery.temp2 + self._dbusservice["/System/Temperature2Name"] = utils.TEMP_2_NAME self._dbusservice["/System/Temperature3"] = self.battery.temp3 + self._dbusservice["/System/Temperature3Name"] = utils.TEMP_3_NAME self._dbusservice["/System/Temperature4"] = self.battery.temp4 + self._dbusservice["/System/Temperature4Name"] = utils.TEMP_4_NAME # Voltage control self._dbusservice["/Info/MaxChargeVoltage"] = self.battery.control_voltage @@ -574,6 +588,30 @@ def publish_dbus(self): # Update TimeToGo and/or TimeToSoC try: + # calculate current average for the last 300 cycles + # if Time-To-Go or Time-To-SoC is enabled + if utils.TIME_TO_GO_ENABLE or len(utils.TIME_TO_SOC_POINTS) > 0: + if self.battery.current is not None: + self.battery.current_avg_lst.append(self.battery.current) + + # delete oldest value + if len(self.battery.current_avg_lst) > 300: + del self.battery.current_avg_lst[0] + + """ + logger.info( + str(self.battery.capacity) + + " - " + + str(utils.TIME_TO_GO_ENABLE) + + " - " + + str(len(utils.TIME_TO_SOC_POINTS)) + + " - " + + str(int(time()) - self.battery.time_to_soc_update) + + " - " + + str(utils.TIME_TO_SOC_RECALCULATE_EVERY) + ) + """ + if ( self.battery.capacity is not None and (utils.TIME_TO_GO_ENABLE or len(utils.TIME_TO_SOC_POINTS) > 0) @@ -583,35 +621,59 @@ def publish_dbus(self): ) ): self.battery.time_to_soc_update = int(time()) + + self.battery.current_avg = round( + sum(self.battery.current_avg_lst) + / len(self.battery.current_avg_lst), + 2, + ) + + self._dbusservice["/CurrentAvg"] = self.battery.current_avg + crntPrctPerSec = ( - abs(self.battery.current / (self.battery.capacity / 100)) / 3600 + abs(self.battery.current_avg / (self.battery.capacity / 100)) / 3600 ) # Update TimeToGo item if utils.TIME_TO_GO_ENABLE: - # Update TimeToGo item, has to be a positive int since it's used from dbus-systemcalc-py - self._dbusservice["/TimeToGo"] = ( - abs( - int( - self.battery.get_timeToSoc( - utils.SOC_LOW_WARNING, crntPrctPerSec, True + if self.battery.current_avg is not None: + # Update TimeToGo item, has to be a positive int since it's used from dbus-systemcalc-py + self._dbusservice["/TimeToGo"] = ( + abs( + int( + self.battery.get_timeToSoc( + # switch value depending on charging/discharging + utils.SOC_LOW_WARNING + if self.battery.current_avg < 0 + else 100, + crntPrctPerSec, + True, + ) ) ) + if self.battery.current_avg + and abs(self.battery.current_avg) > 0.1 + else None ) - if self.battery.current and abs(self.battery.current) > 0.1 - else None - ) + else: + self._dbusservice["/TimeToGo"] = None # Update TimeToSoc items if len(utils.TIME_TO_SOC_POINTS) > 0: for num in utils.TIME_TO_SOC_POINTS: self._dbusservice["/TimeToSoC/" + str(num)] = ( self.battery.get_timeToSoc(num, crntPrctPerSec) - if self.battery.current + if self.battery.current_avg else None ) except Exception: + exception_type, exception_object, exception_traceback = sys.exc_info() + file = exception_traceback.tb_frame.f_code.co_filename + line = exception_traceback.tb_lineno + logger.error( + f"Exception occurred: {repr(exception_object)} of type {exception_type} in {file} line #{line}" + ) pass if self.battery.soc is not None: diff --git a/etc/dbus-serialbattery/qml/PageBattery.qml b/etc/dbus-serialbattery/qml/PageBattery.qml index 286ce74c..ea7b44f5 100644 --- a/etc/dbus-serialbattery/qml/PageBattery.qml +++ b/etc/dbus-serialbattery/qml/PageBattery.qml @@ -94,6 +94,12 @@ MbPage { ] } + MbItemValue { + description: qsTr("Current (last 5 minutes avg.)") + item.bind: service.path("/CurrentAvg") + show: item.seen + } + MbItemValue { id: soc diff --git a/etc/dbus-serialbattery/utils.py b/etc/dbus-serialbattery/utils.py index 696d0028..081ee930 100644 --- a/etc/dbus-serialbattery/utils.py +++ b/etc/dbus-serialbattery/utils.py @@ -38,7 +38,7 @@ def _get_list_from_config( # Constants - Need to dynamically get them in future -DRIVER_VERSION = "1.0.20230711dev" +DRIVER_VERSION = "1.0.20230723dev" zero_char = chr(48) degree_sign = "\N{DEGREE SIGN}"