diff --git a/etc/dbus-serialbattery/battery.py b/etc/dbus-serialbattery/battery.py index 767be09d..20f16586 100644 --- a/etc/dbus-serialbattery/battery.py +++ b/etc/dbus-serialbattery/battery.py @@ -96,6 +96,8 @@ def init_values(self): self.temp_sensors = None self.temp1 = None self.temp2 = None + self.temp3 = None + self.temp4 = None self.temp_mos = None self.cells: List[Cell] = [] self.control_charging = None @@ -127,6 +129,15 @@ def test_connection(self) -> bool: # return false when failed, true if successful return False + def connection_name(self) -> str: + return "Serial " + self.port + + def custom_name(self) -> str: + return "SerialBattery(" + self.type + ")" + + def product_name(self) -> str: + return "SerialBattery(" + self.type + ")" + @abstractmethod def get_settings(self) -> bool: """ @@ -164,6 +175,10 @@ def to_temp(self, sensor: int, value: float) -> None: self.temp1 = min(max(value, -20), 100) if sensor == 2: self.temp2 = min(max(value, -20), 100) + if sensor == 3: + self.temp3 = min(max(value, -20), 100) + if sensor == 4: + self.temp4 = min(max(value, -20), 100) def manage_charge_voltage(self) -> None: """ @@ -804,14 +819,10 @@ def get_balancing(self) -> int: return 1 return 0 - def extract_from_temp_values(self, extractor) -> Union[float, None]: - if self.temp1 is not None and self.temp2 is not None: - return extractor(self.temp1, self.temp2) - if self.temp1 is not None and self.temp2 is None: - return self.temp1 - if self.temp1 is None and self.temp2 is not None: - return self.temp2 - else: + def get_temperatures(self) -> Union[List[float], None]: + temperatures = [self.temp1, self.temp2, self.temp3, self.temp4] + result = [(t, i) for (t, i) in enumerate(temperatures) if t is not None] + if not result: return None def get_temp(self) -> Union[float, None]: @@ -820,46 +831,93 @@ def get_temp(self) -> Union[float, None]: return self.temp1 elif utils.TEMP_BATTERY == 2: return self.temp2 + elif utils.TEMP_BATTERY == 3: + return self.temp3 + elif utils.TEMP_BATTERY == 4: + return self.temp4 else: - return self.extract_from_temp_values( - extractor=lambda temp1, temp2: round( - (float(temp1) + float(temp2)) / 2, 2 - ) - ) + temps = [ + t + for t in [self.temp1, self.temp2, self.temp3, self.temp4] + if t is not None + ] + n = len(temps) + if not temps or n == 0: + return None + data = sorted(temps) + if n % 2 == 1: + return data[n // 2] + else: + i = n // 2 + return (data[i - 1] + data[i]) / 2 except TypeError: return None def get_min_temp(self) -> Union[float, None]: try: - return self.extract_from_temp_values( - extractor=lambda temp1, temp2: min(temp1, temp2) - ) + temps = [ + t + for t in [self.temp1, self.temp2, self.temp3, self.temp4] + if t is not None + ] + if not temps: + return None + return min(temps) except TypeError: return None def get_min_temp_id(self) -> Union[str, None]: try: - if self.temp1 < self.temp2: + temps = [ + (t, i) + for i, t in enumerate([self.temp1, self.temp2, self.temp3, self.temp4]) + if t is not None + ] + if not temps: + return None + index = min(temps)[1] + if index == 0: return utils.TEMP_1_NAME - else: + if index == 1: return utils.TEMP_2_NAME + if index == 2: + return utils.TEMP_3_NAME + if index == 3: + return utils.TEMP_4_NAME except TypeError: return None def get_max_temp(self) -> Union[float, None]: try: - return self.extract_from_temp_values( - extractor=lambda temp1, temp2: max(temp1, temp2) - ) + temps = [ + t + for t in [self.temp1, self.temp2, self.temp3, self.temp4] + if t is not None + ] + if not temps: + return None + return max(temps) except TypeError: return None def get_max_temp_id(self) -> Union[str, None]: try: - if self.temp1 > self.temp2: + temps = [ + (t, i) + for i, t in enumerate([self.temp1, self.temp2, self.temp3, self.temp4]) + if t is not None + ] + if not temps: + return None + index = max(temps)[1] + if index == 0: return utils.TEMP_1_NAME - else: + if index == 1: return utils.TEMP_2_NAME + if index == 2: + return utils.TEMP_3_NAME + if index == 3: + return utils.TEMP_4_NAME except TypeError: return None diff --git a/etc/dbus-serialbattery/bms/lltjbd.py b/etc/dbus-serialbattery/bms/lltjbd.py index c1bf2ae3..4c091aff 100644 --- a/etc/dbus-serialbattery/bms/lltjbd.py +++ b/etc/dbus-serialbattery/bms/lltjbd.py @@ -5,6 +5,166 @@ from struct import unpack_from import struct +# Protocol registers +REG_ENTER_FACTORY = 0x00 +REG_EXIT_FACTORY = 0x01 +# REG_UNKNOWN = 0x02 +REG_GENERAL = 0x03 +REG_CELL = 0x04 +REG_HARDWARE = 0x05 +# Firmware 0x16+ +REG_USE_PASSWORD = 0x06 +REG_SET_PASSWORD = 0x07 +# REG_UNKNOWN2 = 0x08 - Maybe define master password? +REG_CLEAR_PASSWORD = 0x09 + +REG_FRESET = 0x0A + +REG_DESIGN_CAP = 0x10 +REG_CYCLE_CAP = 0x11 +REG_CAP_100 = 0x12 +REG_CAP_0 = 0x13 +REG_SELF_DSG_RATE = 0x14 +REG_MFG_DATE = 0x15 +REG_SERIAL_NUM = 0x16 +REG_CYCLE_CNT = 0x17 +REG_CHGOT = 0x18 +REG_CHGOT_REL = 0x19 +REG_CHGUT = 0x1A +REG_CHGUT_REL = 0x1B +REG_DSGOT = 0x1C +REG_DSGOT_REL = 0x1D +REG_DSGUT = 0x1E +REG_DSGUT_REL = 0x1F +REG_POVP = 0x20 +REG_POVP_REL = 0x21 +REG_PUVP = 0x22 +REG_PUVP_REL = 0x23 +REG_COVP = 0x24 +REG_COVP_REL = 0x25 +REG_CUVP = 0x26 +REG_CUVP_REL = 0x27 +REG_CHGOC = 0x28 +REG_DSGOC = 0x29 +REG_BAL_START = 0x2A +REG_BAL_WINDOW = 0x2B +REG_SHUNT_RES = 0x2C +REG_FUNC_CONFIG = 0x2D +REG_NTC_CONFIG = 0x2E +REG_CELL_CNT = 0x2F +REG_FET_TIME = 0x30 +REG_LED_TIME = 0x31 +REG_CAP_80 = 0x32 +REG_CAP_60 = 0x33 +REG_CAP_40 = 0x34 +REG_CAP_20 = 0x35 +REG_COVP_HIGH = 0x36 +REG_CUVP_HIGH = 0x37 +REG_SC_DSGOC2 = 0x38 +REG_CXVP_HIGH_DELAY_SC_REL = 0x39 +REG_CHG_T_DELAYS = 0x3A +REG_DSG_T_DELAYS = 0x3B +REG_PACK_V_DELAYS = 0x3C +REG_CELL_V_DELAYS = 0x3D +REG_CHGOC_DELAYS = 0x3E +REG_DSGOC_DELAYS = 0x3F +REG_GPSOFF = 0x40 +REG_GPSOFF_TIME = 0x41 +REG_CAP_90 = 0x42 +REG_CAP_70 = 0x43 +REG_CAP_50 = 0x44 +REG_CAP_30 = 0x45 +REG_CAP_10 = 0x46 +# REG_CAP2_100 = 0x47 + +# [0x48, 0x9F] - 87 registers + +REG_MFGNAME = 0xA0 +REG_MODEL = 0xA1 +REG_BARCODE = 0xA2 +REG_ERROR = 0xAA +# 0xAB +# 0xAC +REG_CAL_CUR_IDLE = 0xAD +REG_CAL_CUR_CHG = 0xAE +REG_CAL_CUR_DSG = 0xAF + +REG_CAL_V_CELL_01 = 0xB0 +REG_CAL_V_CELL_02 = 0xB1 +REG_CAL_V_CELL_03 = 0xB2 +REG_CAL_V_CELL_04 = 0xB3 +REG_CAL_V_CELL_05 = 0xB4 +REG_CAL_V_CELL_06 = 0xB5 +REG_CAL_V_CELL_07 = 0xB6 +REG_CAL_V_CELL_08 = 0xB7 +REG_CAL_V_CELL_09 = 0xB8 +REG_CAL_V_CELL_10 = 0xB9 +REG_CAL_V_CELL_11 = 0xBA +REG_CAL_V_CELL_12 = 0xBB +REG_CAL_V_CELL_13 = 0xBC +REG_CAL_V_CELL_14 = 0xBD +REG_CAL_V_CELL_15 = 0xBE +REG_CAL_V_CELL_16 = 0xBF +REG_CAL_V_CELL_17 = 0xC0 +REG_CAL_V_CELL_18 = 0xC1 +REG_CAL_V_CELL_19 = 0xC2 +REG_CAL_V_CELL_20 = 0xC3 +REG_CAL_V_CELL_21 = 0xC4 +REG_CAL_V_CELL_22 = 0xC5 +REG_CAL_V_CELL_23 = 0xC6 +REG_CAL_V_CELL_24 = 0xC7 +REG_CAL_V_CELL_25 = 0xC8 +REG_CAL_V_CELL_26 = 0xC9 +REG_CAL_V_CELL_27 = 0xCA +REG_CAL_V_CELL_28 = 0xCB +REG_CAL_V_CELL_29 = 0xCC +REG_CAL_V_CELL_30 = 0xCD +REG_CAL_V_CELL_31 = 0xCE +REG_CAL_V_CELL_32 = 0xCF + +REG_CAL_T_NTC_0 = 0xD0 +REG_CAL_T_NTC_1 = 0xD1 +REG_CAL_T_NTC_2 = 0xD2 +REG_CAL_T_NTC_3 = 0xD3 +REG_CAL_T_NTC_4 = 0xD4 +REG_CAL_T_NTC_5 = 0xD5 +REG_CAL_T_NTC_6 = 0xD6 +REG_CAL_T_NTC_7 = 0xD7 + +REG_CAP_REMAINING = 0xE0 +REG_CTRL_MOSFET = 0xE1 +REG_CTRL_BALANCE = 0xE2 +REG_RESET = 0xE3 + +# Protocol commands +CMD_ENTER_FACTORY_MODE = b"\x56\x78" +CMD_EXIT_FACTORY_MODE = b"\x00\x00" +CMD_EXIT_AND_SAVE_FACTORY_MODE = b"\x28\x28" + + +def checksum(payload): + return (0x10000 - sum(payload)) % 0x10000 + + +def cmd(op, reg, data): + payload = [reg, len(data)] + list(data) + chksum = checksum(payload) + data = [0xDD, op] + payload + [chksum, 0x77] + format = f">BB{len(payload)}BHB" + return struct.pack(format, *data) + + +def readCmd(reg, data=None): + if data is None: + data = [] + return cmd(0xA5, reg, data) + + +def writeCmd(reg, data=None): + if data is None: + data = [] + return cmd(0x5A, reg, data) + class LltJbdProtection(Protection): def __init__(self): @@ -51,37 +211,84 @@ def __init__(self, port, baud, address): super(LltJbd, self).__init__(port, baud, address) self.protection = LltJbdProtection() self.type = self.BATTERYTYPE + self._product_name: str = "" + self.has_settings = 0 + self.reset_soc = 100 + self.soc_to_set = None + self.factory_mode = False + self.writable = False # degree_sign = u'\N{DEGREE SIGN}' - command_general = b"\xDD\xA5\x03\x00\xFF\xFD\x77" - command_cell = b"\xDD\xA5\x04\x00\xFF\xFC\x77" - command_hardware = b"\xDD\xA5\x05\x00\xFF\xFB\x77" BATTERYTYPE = "LLT/JBD" LENGTH_CHECK = 6 LENGTH_POS = 3 + command_general = readCmd(REG_GENERAL) # b"\xDD\xA5\x03\x00\xFF\xFD\x77" + command_cell = readCmd(REG_CELL) # b"\xDD\xA5\x04\x00\xFF\xFC\x77" + command_hardware = readCmd(REG_HARDWARE) # b"\xDD\xA5\x05\x00\xFF\xFB\x77" + def test_connection(self): # call a function that will connect to the battery, send a command and retrieve the result. # The result or call should be unique to this BMS. Battery name or version, etc. # Return True if success, False for failure result = False try: - result = self.read_hardware_data() + result = self.get_settings() + if result: + result = result and self.read_hardware_data() # get first data to show in startup log if result: - self.refresh_data() + result = result and self.refresh_data() except Exception as err: logger.error(f"Unexpected {err=}, {type(err)=}") result = False return result + def product_name(self) -> str: + return self._product_name + def get_settings(self): - self.read_gen_data() + if not self.read_gen_data(): + return False self.max_battery_charge_current = utils.MAX_BATTERY_CHARGE_CURRENT self.max_battery_discharge_current = utils.MAX_BATTERY_DISCHARGE_CURRENT + with self.eeprom(writable=False): + charge_over_current = self.read_serial_data_llt(readCmd(REG_CHGOC)) + if charge_over_current: + self.max_battery_charge_current = float( + unpack_from(">h", charge_over_current)[0] / 100.0 + ) + discharge_over_current = self.read_serial_data_llt(readCmd(REG_DSGOC)) + if discharge_over_current: + self.max_battery_discharge_current = float( + unpack_from(">h", discharge_over_current)[0] / -100.0 + ) + return True + def reset_soc_callback(self, path, value): + if value is None: + return False + + if value < 0 or value > 100: + return False + + self.reset_soc = value + self.soc_to_set = value + return True + + def write_soc(self): + if self.soc_to_set is None or self.soc_to_set != 100 or not self.voltage: + return False + logger.info(f"write soc {self.soc_to_set}%") + self.soc_to_set = None # Reset value, so we will set it only once + # TODO implement logic to map current pack readings into + # REG_CAP_100, REG_CAP_90, REG_CAP_80, REG_CAP_70, REG_CAP_60, ... + with self.eeprom(writable=True): + pack_voltage = struct.pack(">H", int(self.voltage * 10)) + self.read_serial_data_llt(writeCmd(REG_CAP_100, pack_voltage)) + def refresh_data(self): result = self.read_gen_data() result = result and self.read_cell_data() @@ -200,7 +407,9 @@ def read_gen_data(self): self.capacity_remain = capacity_remain / 100 self.capacity = capacity / 100 self.to_cell_bits(balance, balance2) - self.version = float(str(version >> 4 & 0x0F) + "." + str(version & 0x0F)) + self.hardware_version = float( + str(version >> 4 & 0x0F) + "." + str(version & 0x0F) + ) self.to_fet_bits(fet) self.to_protection_bits(protection) self.max_battery_voltage = utils.MAX_CELL_VOLTAGE * self.cell_count @@ -234,24 +443,73 @@ def read_hardware_data(self): if hardware_data is False: return False - self.hardware_version = unpack_from( + self._product_name = unpack_from( ">" + str(len(hardware_data)) + "s", hardware_data )[0].decode() - logger.debug(self.hardware_version) + logger.debug(self._product_name) return True + @staticmethod + def validate_packet(data): + if not data: + return False + + if data is False: + return False + + start, op, status, payload_length = unpack_from("BBBB", data) + if start != 0xDD: + logger.error( + ">>> ERROR: Invalid response packet. Expected begin packet character 0xDD" + ) + if status != 0x0: + logger.warn(">>> WARN: BMS rejected request. Status " + status) + return False + if len(data) != payload_length + 7: + logger.error( + ">>> ERROR: BMS send insufficient data. Received " + + str(len(data)) + + " expected " + + str(payload_length + 7) + ) + return False + chk_sum, end = unpack_from(">HB", data, payload_length + 4) + if end != 0x77: + logger.error( + ">>> ERROR: Incorrect Reply. Expected end packet character 0x77" + ) + return False + if chk_sum != checksum(data[2:-3]): + logger.error(">>> ERROR: Invalid checksum.") + return False + + payload = data[4 : payload_length + 4] + + return payload + def read_serial_data_llt(self, command): data = read_serial_data( command, self.port, self.baud_rate, self.LENGTH_POS, self.LENGTH_CHECK ) - if data is False: - return False + return self.validate_packet(data) - start, flag, command_ret, length = unpack_from("BBBB", data) - checksum, end = unpack_from("HB", data, length + 4) + def __enter__(self): + if self.read_serial_data_llt( + writeCmd(REG_ENTER_FACTORY, CMD_ENTER_FACTORY_MODE) + ): + self.factory_mode = True - if end == 119: - return data[4 : length + 4] - else: - logger.error(">>> ERROR: Incorrect Reply") - return False + def __exit__(self, type, value, traceback): + cmd_value = ( + CMD_EXIT_AND_SAVE_FACTORY_MODE if self.writable else CMD_EXIT_FACTORY_MODE + ) + if self.factory_mode: + if not self.read_serial_data_llt(writeCmd(REG_EXIT_FACTORY, cmd_value)): + logger.error(">>> ERROR: Unable to exit factory mode.") + else: + self.factory_mode = False + self.writable = False + + def eeprom(self, writable=False): + self.writable = writable + return self diff --git a/etc/dbus-serialbattery/bms/lltjbd_ble.py b/etc/dbus-serialbattery/bms/lltjbd_ble.py index fa4b38da..de995492 100644 --- a/etc/dbus-serialbattery/bms/lltjbd_ble.py +++ b/etc/dbus-serialbattery/bms/lltjbd_ble.py @@ -3,13 +3,12 @@ import atexit import functools import threading +from asyncio import CancelledError from typing import Union, Optional from utils import logger -from struct import unpack_from from bleak import BleakClient, BleakScanner, BLEDevice from bms.lltjbd import LltJbdProtection, LltJbd - BLE_SERVICE_UUID = "0000ff00-0000-1000-8000-00805f9b34fb" BLE_CHARACTERISTICS_TX_UUID = "0000ff02-0000-1000-8000-00805f9b34fb" BLE_CHARACTERISTICS_RX_UUID = "0000ff01-0000-1000-8000-00805f9b34fb" @@ -21,7 +20,9 @@ class LltJbd_Ble(LltJbd): BATTERYTYPE = "LltJbd_Ble" def __init__(self, port: Optional[str], baud: Optional[int], address: str): - super(LltJbd_Ble, self).__init__(address.replace(":", "").lower(), -1, address) + super(LltJbd_Ble, self).__init__( + "ble" + address.replace(":", "").lower(), -1, address + ) self.address = address self.protection = LltJbdProtection() @@ -50,9 +51,14 @@ def on_disconnect(self, client): logger.info("BLE client disconnected") async def bt_main_loop(self): - self.device = await BleakScanner.find_device_by_address( - self.address, cb=dict(use_bdaddr=True) - ) + try: + self.device = await BleakScanner.find_device_by_address( + self.address, cb=dict(use_bdaddr=True) + ) + except Exception as e: + logger.error(">>> ERROR: Bluetooth stack failed.", e) + self.device = None + await asyncio.sleep(0.5) if not self.device: self.run = False @@ -155,22 +161,18 @@ async def async_read_serial_data_llt(self, command): def read_serial_data_llt(self, command): if not self.bt_loop: return False - data = asyncio.run(self.async_read_serial_data_llt(command)) - if not data: + try: + data = asyncio.run(self.async_read_serial_data_llt(command)) + return self.validate_packet(data) + except CancelledError as e: + logger.error(">>> ERROR: No reply - canceled - returning", e) return False - - start, flag, command_ret, length = unpack_from("BBBB", data) - checksum, end = unpack_from("HB", data, length + 4) - - if end == 119: - return data[4 : length + 4] - else: - logger.error(">>> ERROR: Incorrect Reply") + except Exception as e: + logger.error(">>> ERROR: No reply - returning", e) return False -""" -async def test_LltJbd_Ble(): +if __name__ == "__main__": import sys bat = LltJbd_Ble("Foo", -1, sys.argv[1]) @@ -178,8 +180,4 @@ async def test_LltJbd_Ble(): logger.error(">>> ERROR: Unable to connect") else: bat.refresh_data() - - -if __name__ == "__main__": - test_LltJbd_Ble() -""" + bat.get_settings() diff --git a/etc/dbus-serialbattery/bms/mnb.py b/etc/dbus-serialbattery/bms/mnb.py index 1ad1126e..84365866 100644 --- a/etc/dbus-serialbattery/bms/mnb.py +++ b/etc/dbus-serialbattery/bms/mnb.py @@ -169,9 +169,9 @@ def manage_charge_current(self): # Change depending on the cell_min_voltage values if self.cell_min_voltage < self.V_C_min + 0.05: - self.control_allow_dicharge = False + self.control_allow_discharge = False else: - self.control_allow_dicharge = True + self.control_allow_discharge = True if self.cell_min_voltage < self.V_C_min + 0.15: b = 10 * (self.cell_min_voltage - self.V_C_min - 0.05) diff --git a/etc/dbus-serialbattery/config.default.ini b/etc/dbus-serialbattery/config.default.ini index 4b11e9b5..e9b4f403 100644 --- a/etc/dbus-serialbattery/config.default.ini +++ b/etc/dbus-serialbattery/config.default.ini @@ -199,10 +199,12 @@ MIDPOINT_ENABLE = False ; Battery temperature -; Specifiy how the battery temperature is assembled -; 0 Get mean of temperature sensor 1 and temperature sensor 2 +; Specify how the battery temperature is assembled +; 0 Get mean of temperature sensor 1 to sensor 4 ; 1 Get only temperature from temperature sensor 1 ; 2 Get only temperature from temperature sensor 2 +; 3 Get only temperature from temperature sensor 3 +; 4 Get only temperature from temperature sensor 4 TEMP_BATTERY = 0 ; Temperature sensor 1 name @@ -211,6 +213,12 @@ TEMP_1_NAME = Temp 1 ; Temperature sensor 2 name TEMP_2_NAME = Temp 2 +; Temperature sensor 2 name +TEMP_3_NAME = Temp 3 + +; Temperature sensor 2 name +TEMP_4_NAME = Temp 4 + ; --------- BMS specific settings --------- diff --git a/etc/dbus-serialbattery/dbushelper.py b/etc/dbus-serialbattery/dbushelper.py index ccf7181e..0cca3187 100644 --- a/etc/dbus-serialbattery/dbushelper.py +++ b/etc/dbus-serialbattery/dbushelper.py @@ -113,19 +113,17 @@ def setup_vedbus(self): self._dbusservice.add_path( "/Mgmt/ProcessVersion", "Python " + platform.python_version() ) - self._dbusservice.add_path("/Mgmt/Connection", "Serial " + self.battery.port) + self._dbusservice.add_path("/Mgmt/Connection", self.battery.connection_name()) # Create the mandatory objects self._dbusservice.add_path("/DeviceInstance", self.instance) self._dbusservice.add_path("/ProductId", 0x0) - self._dbusservice.add_path( - "/ProductName", "SerialBattery(" + self.battery.type + ")" - ) + self._dbusservice.add_path("/ProductName", self.battery.product_name()) self._dbusservice.add_path("/FirmwareVersion", str(utils.DRIVER_VERSION)) self._dbusservice.add_path("/HardwareVersion", self.battery.hardware_version) self._dbusservice.add_path("/Connected", 1) self._dbusservice.add_path( - "/CustomName", "SerialBattery(" + self.battery.type + ")", writeable=True + "/CustomName", self.battery.custom_name(), writeable=True ) self._dbusservice.add_path( "/Serial", self.battery.unique_identifier, writeable=True @@ -231,6 +229,10 @@ def setup_vedbus(self): self._dbusservice.add_path("/System/MaxCellTemperature", None, writeable=True) 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/Temperature2", None, writeable=True) + self._dbusservice.add_path("/System/Temperature3", None, writeable=True) + self._dbusservice.add_path("/System/Temperature4", None, writeable=True) self._dbusservice.add_path( "/System/MaxCellVoltage", None, @@ -470,6 +472,10 @@ def publish_dbus(self): "/System/MaxTemperatureCellId" ] = 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/Temperature2"] = self.battery.temp2 + self._dbusservice["/System/Temperature3"] = self.battery.temp3 + self._dbusservice["/System/Temperature4"] = self.battery.temp4 # Voltage control self._dbusservice["/Info/MaxChargeVoltage"] = self.battery.control_voltage diff --git a/etc/dbus-serialbattery/utils.py b/etc/dbus-serialbattery/utils.py index e36782da..8b188446 100644 --- a/etc/dbus-serialbattery/utils.py +++ b/etc/dbus-serialbattery/utils.py @@ -294,6 +294,12 @@ def _get_list_from_config( # Temperature sensor 2 name TEMP_2_NAME = config["DEFAULT"]["TEMP_2_NAME"] +# Temperature sensor 3 name +TEMP_3_NAME = config["DEFAULT"]["TEMP_3_NAME"] + +# Temperature sensor 2 name +TEMP_4_NAME = config["DEFAULT"]["TEMP_4_NAME"] + # --------- BMS specific settings --------- diff --git a/requirements.txt b/requirements.txt index 8bec2184..6de24eea 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ pyserial==3.5 minimalmodbus==2.0.1 +bleak==0.20.0 \ No newline at end of file