From a81bf055beded89f9fd3c15c2f24d6b9a42a0b90 Mon Sep 17 00:00:00 2001 From: Manuel <mr-manuel@outlook.it> Date: Sat, 10 Jun 2023 19:14:10 +0200 Subject: [PATCH] changed unique identifier from string to function function can be overridden by BMS battery class --- CHANGELOG.md | 1 + etc/dbus-serialbattery/battery.py | 24 +++++++++++++------ .../bms/battery_template.py | 14 +++++++---- etc/dbus-serialbattery/bms/daly.py | 14 +++++++---- etc/dbus-serialbattery/bms/heltecmodbus.py | 11 +++++++-- etc/dbus-serialbattery/bms/jkbms.py | 11 +++++++-- etc/dbus-serialbattery/bms/jkbms_ble.py | 11 ++++++++- etc/dbus-serialbattery/dbushelper.py | 2 +- 8 files changed, 65 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 94b8e2ab..84bfb4bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## v1.0.x * Added: Bluetooth: Show signal strenght of BMS in log by @mr-manuel +* Added: Create unique identifier, if not provided from BMS by @mr-manuel * 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 diff --git a/etc/dbus-serialbattery/battery.py b/etc/dbus-serialbattery/battery.py index 79ddce46..a8c410a3 100644 --- a/etc/dbus-serialbattery/battery.py +++ b/etc/dbus-serialbattery/battery.py @@ -71,15 +71,12 @@ def __init__(self, port, baud, address): self.max_battery_discharge_current = None self.has_settings = 0 - self.init_values() - - # used to identify a BMS when multiple BMS are connected - planned for future use - self.unique_identifier = None - # fetched from the BMS from a field where the user can input a custom string # only if available self.custom_field = None + self.init_values() + def init_values(self): self.voltage = None self.current = None @@ -131,6 +128,20 @@ def test_connection(self) -> bool: # return false when failed, true if successful return False + def unique_identifier(self) -> str: + """ + Used to identify a BMS when multiple BMS are connected + If not provided by the BMS/driver then the hardware version and capacity is used, + since it can be changed by small amounts to make a battery unique. + On +/- 5 Ah you can identify 11 batteries + """ + return ( + "".join(filter(str.isalnum, self.hardware_version)) + + "_" + + str(self.capacity) + + "Ah" + ) + def connection_name(self) -> str: return "Serial " + self.port @@ -1005,8 +1016,7 @@ def log_settings(self) -> None: logger.info( f"> CCCM SOC: {str(utils.CCCM_SOC_ENABLE).ljust(5)} | DCCM SOC: {utils.DCCM_SOC_ENABLE}" ) - if self.unique_identifier is not None: - logger.info(f"Serial Number/Unique Identifier: {self.unique_identifier}") + logger.info(f"Serial Number/Unique Identifier: {self.unique_identifier()}") return diff --git a/etc/dbus-serialbattery/bms/battery_template.py b/etc/dbus-serialbattery/bms/battery_template.py index e32e424b..92c7fa49 100644 --- a/etc/dbus-serialbattery/bms/battery_template.py +++ b/etc/dbus-serialbattery/bms/battery_template.py @@ -36,6 +36,15 @@ def test_connection(self): return result + def unique_identifier(self) -> str: + """ + Used to identify a BMS when multiple BMS are connected + Provide a unique identifier from the BMS to identify a BMS, if multiple same BMS are connected + e.g. the serial number + If there is no such value, please remove this function + """ + return self.serialnumber + def get_settings(self): # After successful connection get_settings will be call to set up the battery. # Set the current limits, populate cell count, etc @@ -53,11 +62,6 @@ def get_settings(self): self.max_battery_voltage = utils.MAX_CELL_VOLTAGE * self.cell_count self.min_battery_voltage = utils.MIN_CELL_VOLTAGE * self.cell_count - # provide a unique identifier from the BMS to identify a BMS, if multiple same BMS are connected - # e.g. the serial number - # If there is no such value, please leave the line commented. In this case the capacity is used, - # since it can be changed by small amounts to make a battery unique. On +/- 5 Ah you can identify 11 batteries - # self.unique_identifier = str() return True def refresh_data(self): diff --git a/etc/dbus-serialbattery/bms/daly.py b/etc/dbus-serialbattery/bms/daly.py index 87510c48..732af406 100644 --- a/etc/dbus-serialbattery/bms/daly.py +++ b/etc/dbus-serialbattery/bms/daly.py @@ -522,13 +522,17 @@ def read_battery_code(self, ser): " ", (battery_code.strip()), ) - self.unique_identifier = self.custom_field.replace(" ", "_") - else: - self.unique_identifier = ( - str(self.production) + "_" + str(int(self.capacity)) - ) return True + def unique_identifier(self) -> str: + """ + Used to identify a BMS when multiple BMS are connected + """ + if self.custom_field != "": + return self.custom_field.replace(" ", "_") + else: + return str(self.production) + "_" + str(int(self.capacity)) + def reset_soc_callback(self, path, value): if value is None: return False diff --git a/etc/dbus-serialbattery/bms/heltecmodbus.py b/etc/dbus-serialbattery/bms/heltecmodbus.py index e7f866a0..1ceaa43e 100644 --- a/etc/dbus-serialbattery/bms/heltecmodbus.py +++ b/etc/dbus-serialbattery/bms/heltecmodbus.py @@ -30,6 +30,7 @@ class HeltecModbus(Battery): def __init__(self, port, baud, address): super(HeltecModbus, self).__init__(port, baud, address) self.type = "Heltec_Smart" + self.unique_identifier_tmp = "" def test_connection(self): # call a function that will connect to the battery, send a command and retrieve the result. @@ -174,7 +175,7 @@ def read_status_data(self): time.sleep(SLPTIME) serial1 = mbdev.read_registers(2, number_of_registers=4) - self.unique_identifier = "-".join( + self.unique_identifier_tmp = "-".join( "{:04x}".format(x) for x in serial1 ) time.sleep(SLPTIME) @@ -234,7 +235,7 @@ def read_status_data(self): logger.info(self.hardware_version) logger.info("Heltec-" + self.hwTypeName) logger.info(" Dev name: " + self.devName) - logger.info(" Serial: " + self.unique_identifier) + logger.info(" Serial: " + self.unique_identifier_tmp) logger.info(" Made on: " + self.production_date) logger.info(" Cell count: " + str(self.cell_count)) logger.info(" Cell type: " + self.cellType) @@ -245,6 +246,12 @@ def read_status_data(self): return True + def unique_identifier(self) -> str: + """ + Used to identify a BMS when multiple BMS are connected + """ + return self.unique_identifier_tmp + def read_soc_data(self): mbdev = mbdevs[self.address] diff --git a/etc/dbus-serialbattery/bms/jkbms.py b/etc/dbus-serialbattery/bms/jkbms.py index 5fc87901..8925d824 100644 --- a/etc/dbus-serialbattery/bms/jkbms.py +++ b/etc/dbus-serialbattery/bms/jkbms.py @@ -10,6 +10,7 @@ class Jkbms(Battery): def __init__(self, port, baud, address): super(Jkbms, self).__init__(port, baud, address) self.type = self.BATTERYTYPE + self.unique_identifier_tmp = "" BATTERYTYPE = "Jkbms" LENGTH_CHECK = 1 @@ -184,9 +185,9 @@ def read_status_data(self): )[0].decode() offset = cellbyte_count + 197 - self.unique_identifier = sub( + self.unique_identifier_tmp = sub( " +", - " ", + "_", ( unpack_from(">24s", self.get_data(status_data, b"\xBA", offset, 24))[0] .decode() @@ -209,6 +210,12 @@ def read_status_data(self): # logger.info(self.hardware_version) return True + def unique_identifier(self) -> str: + """ + Used to identify a BMS when multiple BMS are connected + """ + return self.unique_identifier_tmp + def to_fet_bits(self, byte_data): tmp = bin(byte_data)[2:].rjust(3, utils.zero_char) self.charge_fet = is_bit_set(tmp[2]) diff --git a/etc/dbus-serialbattery/bms/jkbms_ble.py b/etc/dbus-serialbattery/bms/jkbms_ble.py index d687e42a..6a2e3011 100644 --- a/etc/dbus-serialbattery/bms/jkbms_ble.py +++ b/etc/dbus-serialbattery/bms/jkbms_ble.py @@ -19,6 +19,7 @@ def __init__(self, port, baud, address): self.address = address self.type = self.BATTERYTYPE self.jk = Jkbms_Brn(address) + self.unique_identifier_tmp = "" logger.info("Init of Jkbms_Ble at " + address) @@ -91,7 +92,9 @@ def get_settings(self): tmp = self.jk.get_status()["device_info"]["manufacturing_date"] self.production = "20" + tmp if tmp and tmp != "" else None - self.unique_identifier = self.jk.get_status()["device_info"]["serial_number"] + self.unique_identifier_tmp = self.jk.get_status()["device_info"][ + "serial_number" + ] for c in range(self.cell_count): self.cells.append(Cell(False)) @@ -109,6 +112,12 @@ def get_settings(self): logger.info("BAT: " + self.hardware_version) return True + def unique_identifier(self) -> str: + """ + Used to identify a BMS when multiple BMS are connected + """ + return self.unique_identifier_tmp + def use_callback(self, callback: Callable) -> bool: self.jk.set_callback(callback) return callback is not None diff --git a/etc/dbus-serialbattery/dbushelper.py b/etc/dbus-serialbattery/dbushelper.py index 9edc57b1..946eb4d6 100644 --- a/etc/dbus-serialbattery/dbushelper.py +++ b/etc/dbus-serialbattery/dbushelper.py @@ -129,7 +129,7 @@ def setup_vedbus(self): onchangecallback=self.battery.custom_name_callback, ) self._dbusservice.add_path( - "/Serial", self.battery.unique_identifier, writeable=True + "/Serial", self.battery.unique_identifier(), writeable=True ) self._dbusservice.add_path( "/DeviceName", self.battery.custom_field, writeable=True