diff --git a/CHANGELOG.md b/CHANGELOG.md index 240a30ed..94b8e2ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * 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: Save custom name and make it restart persistant by @mr-manuel * Changed: Fixed error in `reinstall-local.sh` script for Bluetooth installation by @mr-manuel * Changed: Fixed typo in `config.ini` sample by @hoschult * Changed: Improved driver reinstall when multiple Bluetooth BMS are enabled by @mr-manuel diff --git a/etc/dbus-serialbattery/battery.py b/etc/dbus-serialbattery/battery.py index 1ce3c5be..79ddce46 100644 --- a/etc/dbus-serialbattery/battery.py +++ b/etc/dbus-serialbattery/battery.py @@ -7,6 +7,8 @@ import math from time import time from abc import ABC, abstractmethod +import re +import sys class Protection(object): @@ -133,7 +135,16 @@ def connection_name(self) -> str: return "Serial " + self.port def custom_name(self) -> str: - return "SerialBattery(" + self.type + ")" + """ + Check if the custom name is present in the config file, else return default name + """ + if len(utils.CUSTOM_BATTERY_NAMES) > 0: + for name in utils.CUSTOM_BATTERY_NAMES: + tmp = name.split(":") + if tmp[0].strip() == self.port: + return tmp[1].strip() + else: + return "SerialBattery(" + self.type + ")" def product_name(self) -> str: return "SerialBattery(" + self.type + ")" @@ -999,6 +1010,146 @@ def log_settings(self) -> None: return + # save custom name to config file + def custom_name_callback(self, path, value): + try: + if path == "/CustomName": + file = open( + "/data/etc/dbus-serialbattery/" + utils.PATH_CONFIG_USER, "r" + ) + lines = file.readlines() + last = len(lines) + + # remove not allowed characters + value = value.replace(":", "").replace("=", "").replace(",", "").strip() + + # empty string to save new config file + config_file_new = "" + + # make sure we are in the [DEFAULT] section + current_line_in_default_section = False + default_section_checked = False + + # check if already exists + exists = False + + # count lines + i = 0 + # looping through the file + for line in lines: + # increment by one + i += 1 + + # stripping line break + line = line.strip() + + # check, if current line is after the [DEFAULT] section + if line == "[DEFAULT]": + current_line_in_default_section = True + + # check, if current line starts a new section + if line != "[DEFAULT]" and re.match(r"^\[.*\]", line): + # set default_section_checked to true, if it was already checked and a new section comes on + if current_line_in_default_section and not exists: + default_section_checked = True + current_line_in_default_section = False + + # check, if the current line is the last line + if i == last: + default_section_checked = True + + # insert or replace only in [DEFAULT] section + if current_line_in_default_section and re.match( + r"^CUSTOM_BATTERY_NAMES.*", line + ): + # set that the setting was found, else a new one is created + exists = True + + # remove setting name + line = re.sub( + "^CUSTOM_BATTERY_NAMES\s*=\s*", "", line # noqa: W605 + ) + + # change only the name of the current BMS + result = [] + bms_name_list = line.split(",") + for bms_name_pair in bms_name_list: + tmp = bms_name_pair.split(":") + if tmp[0] == self.port: + result.append(tmp[0] + ":" + value) + else: + result.append(bms_name_pair) + + new_line = "CUSTOM_BATTERY_NAMES = " + ",".join(result) + + else: + if default_section_checked and not exists: + exists = True + + # add before current line + if i != last: + new_line = ( + "CUSTOM_BATTERY_NAMES = " + + self.port + + ":" + + value + + "\n\n" + + line + ) + + # add at the end if last line + else: + new_line = ( + line + + "\n\n" + + "CUSTOM_BATTERY_NAMES = " + + self.port + + ":" + + value + ) + else: + new_line = line + # concatenate the new string and add an end-line break + config_file_new = config_file_new + new_line + "\n" + + # close the file + file.close() + # Open file in write mode + write_file = open( + "/data/etc/dbus-serialbattery/" + utils.PATH_CONFIG_USER, "w" + ) + # overwriting the old file contents with the new/replaced content + write_file.write(config_file_new) + # close the file + write_file.close() + + # logger.error("value (saved): " + str(value)) + + """ + # this removes all comments and tranfsorm the values to lowercase + utils.config.set( + "DEFAULT", + "CUSTOM_BATTERY_NAMES", + self.port + ":" + value, + ) + + # Writing our configuration file to 'example.ini' + with open( + "/data/etc/dbus-serialbattery/" + utils.PATH_CONFIG_USER, "w" + ) as configfile: + type(utils.config.write(configfile)) + """ + + 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}" + ) + + return value + def reset_soc_callback(self, path, value): # callback for handling reset soc request return diff --git a/etc/dbus-serialbattery/config.default.ini b/etc/dbus-serialbattery/config.default.ini index 559de8bd..35d01f4c 100644 --- a/etc/dbus-serialbattery/config.default.ini +++ b/etc/dbus-serialbattery/config.default.ini @@ -195,6 +195,12 @@ BMS_TYPE = ; Example: /dev/ttyUSB2, /dev/ttyUSB4 EXCLUDED_DEVICES = +; Enter custom battery names here or change it over the GUI +; Example: +; /dev/ttyUSB0:My first battery +; /dev/ttyUSB0:My first battery,/dev/ttyUSB1:My second battery +CUSTOM_BATTERY_NAMES = + ; Publish the config settings to the dbus path "/Info/Config/" PUBLISH_CONFIG_VALUES = 1 diff --git a/etc/dbus-serialbattery/dbus-serialbattery.py b/etc/dbus-serialbattery/dbus-serialbattery.py index 29fd624e..7794071d 100644 --- a/etc/dbus-serialbattery/dbus-serialbattery.py +++ b/etc/dbus-serialbattery/dbus-serialbattery.py @@ -58,7 +58,7 @@ if battery_type["bms"].__name__ == utils.BMS_TYPE or utils.BMS_TYPE == "" ] -print("") +logger.info("") logger.info("Starting dbus-serialbattery") diff --git a/etc/dbus-serialbattery/dbushelper.py b/etc/dbus-serialbattery/dbushelper.py index 0cca3187..9edc57b1 100644 --- a/etc/dbus-serialbattery/dbushelper.py +++ b/etc/dbus-serialbattery/dbushelper.py @@ -123,7 +123,10 @@ def setup_vedbus(self): self._dbusservice.add_path("/HardwareVersion", self.battery.hardware_version) self._dbusservice.add_path("/Connected", 1) self._dbusservice.add_path( - "/CustomName", self.battery.custom_name(), writeable=True + "/CustomName", + self.battery.custom_name(), + writeable=True, + onchangecallback=self.battery.custom_name_callback, ) self._dbusservice.add_path( "/Serial", self.battery.unique_identifier, writeable=True diff --git a/etc/dbus-serialbattery/utils.py b/etc/dbus-serialbattery/utils.py index 8ea766ba..ca64c12a 100644 --- a/etc/dbus-serialbattery/utils.py +++ b/etc/dbus-serialbattery/utils.py @@ -15,10 +15,13 @@ logger = logging.getLogger("SerialBattery") logger.setLevel(logging.INFO) +PATH_CONFIG_DEFAULT = "config.default.ini" +PATH_CONFIG_USER = "config.ini" + config = configparser.ConfigParser() path = Path(__file__).parents[0] -default_config_file_path = path.joinpath("config.default.ini").absolute().__str__() -custom_config_file_path = path.joinpath("config.ini").absolute().__str__() +default_config_file_path = path.joinpath(PATH_CONFIG_DEFAULT).absolute().__str__() +custom_config_file_path = path.joinpath(PATH_CONFIG_USER).absolute().__str__() config.read([default_config_file_path, custom_config_file_path]) @@ -275,10 +278,20 @@ def _get_list_from_config( # Ant, MNB, Sinowealth BMS_TYPE = config["DEFAULT"]["BMS_TYPE"] +# Exclute this serial devices from the driver startup +# Example: /dev/ttyUSB2, /dev/ttyUSB4 EXCLUDED_DEVICES = _get_list_from_config( "DEFAULT", "EXCLUDED_DEVICES", lambda v: str(v) ) +# Enter custom battery names here or change it over the GUI +# Example: +# /dev/ttyUSB0:My first battery +# /dev/ttyUSB0:My first battery, /dev/ttyUSB1:My second battery +CUSTOM_BATTERY_NAMES = _get_list_from_config( + "DEFAULT", "CUSTOM_BATTERY_NAMES", lambda v: str(v) +) + # Publish the config settings to the dbus path "/Info/Config/" PUBLISH_CONFIG_VALUES = int(config["DEFAULT"]["PUBLISH_CONFIG_VALUES"]) @@ -526,6 +539,7 @@ def read_serialport_data( locals_copy = locals().copy() +# Publish config variables to dbus def publish_config_variables(dbusservice): for variable, value in locals_copy.items(): if variable.startswith("__"):