diff --git a/dbus_batrium_native/batrium.py b/dbus-batrium-native/batrium.py similarity index 92% rename from dbus_batrium_native/batrium.py rename to dbus-batrium-native/batrium.py index 94e93b5..0565b1f 100644 --- a/dbus_batrium_native/batrium.py +++ b/dbus-batrium-native/batrium.py @@ -85,12 +85,15 @@ class BatriumBattery(can.Listener): elif msg.arbitration_id == 0x00111900: logging.debug("Ah 0x00111900 received") - self.AhToFull = round((struct.unpack('>f', bytearray([msg.data[3], msg.data[2], msg.data[1], msg.data[0]])))[0] * 0.001, 2) - self.AhToEmpty = round((struct.unpack('>f', bytearray([msg.data[7], msg.data[6], msg.data[5], msg.data[4]])))[0] * 0.001, 2) - self.capacity = self.AhToEmpty + self.AhToFull - logging.debug("Ah to Full: %2.2f", self.AhToFull) - logging.debug("Ah to Empty: %2.2f", self.AhToEmpty) - logging.debug("Capacity: %2.2f", self.capacity) + + # message never arrived, batrium fw bug? + + #self.AhToFull = round((struct.unpack('>f', bytearray([msg.data[3], msg.data[2], msg.data[1], msg.data[0]])))[0] * 0.001, 2) + #self.AhToEmpty = round((struct.unpack('>f', bytearray([msg.data[7], msg.data[6], msg.data[5], msg.data[4]])))[0] * 0.001, 2) + #self.capacity = self.AhToEmpty + self.AhToFull + #logging.debug("Ah to Full: %2.2f", self.AhToFull) + #logging.debug("Ah to Empty: %2.2f", self.AhToEmpty) + #logging.debug("Capacity: %2.2f", self.capacity) elif msg.arbitration_id == 0x00140100: self.alarm_high_temperature = (msg.data[2] >> 3) & 1 @@ -101,8 +104,6 @@ class BatriumBattery(can.Listener): logging.debug("Low Temperature Alarm: %d", self.alarm_low_temperature) self.alarm_low_voltage = (msg.data[2] >> 0) & 1 logging.debug("Low Voltage Alarm: %d", self.alarm_low_voltage) - #self.alarm_low_soc = (msg.data[7] >> 2) & 1 - logging.debug("Low SOC Alarm: %d", self.alarm_low_soc) self.alarm_high_charge_current = (msg.data[3] >> 3) & 1 logging.debug("High Charge Current Alarm: %d", self.alarm_high_charge_current) self.alarm_high_discharge_current = (msg.data[3] >> 4) & 1 @@ -113,11 +114,11 @@ class BatriumBattery(can.Listener): logging.debug("Cell number in bypass: %d", self.NumberInBypass) elif msg.arbitration_id == 0x00111800: - self.TimeToEmpty = ((msg.data[5] * 256) + msg.data[4]) + self.TimeToEmpty = ((msg.data[5] * 256) + msg.data[4] * 60) logging.debug("Time to empty: %dmin", self.TimeToEmpty) elif msg.arbitration_id == 0x00111700: - self.TimeToFull = ((msg.data[5] * 256) + msg.data[4]) + self.TimeToFull = ((msg.data[5] * 256) + msg.data[4] * 60) logging.debug("Time to full: %dmin", self.TimeToFull) elif msg.arbitration_id == 0x00140400: diff --git a/dbus_batrium_native/dbus_batrium_native.py b/dbus-batrium-native/dbus-batrium-native.py similarity index 86% rename from dbus_batrium_native/dbus_batrium_native.py rename to dbus-batrium-native/dbus-batrium-native.py index fb4d867..6f8cdf6 100644 --- a/dbus_batrium_native/dbus_batrium_native.py +++ b/dbus-batrium-native/dbus-batrium-native.py @@ -38,8 +38,12 @@ def handle_changed_setting(setting, oldvalue, newvalue): class DbusBatteryService: def __init__(self, servicename, deviceinstance, productname='Batrium BMS', connection='can0'): self.minUpdateDone = 0 + self.secUpdateDone = 0 self.dailyResetDone = 0 self.lastUpdated = 0 + self.cell_balanced = 0 + self.ChargedEnergy = 0 + self.DischargedEnergy = 0 self._bat = BatriumBattery(connection=connection) self.notifier = can.Notifier(self._bat._ci, [self._bat]) @@ -62,9 +66,6 @@ class DbusBatteryService: self._dbusservice.add_path('/Connected', 0) # Create battery specific objects self._dbusservice.add_path('/Status', None, writeable=True) - self._dbusservice.add_path('/Soh', 100) - #self._dbusservice.add_path('/Capacity', None, writeable=True) - #self._dbusservice.add_path('/InstalledCapacity', None, writeable=True) self._dbusservice.add_path('/Dc/0/Temperature', None, writeable=True) self._dbusservice.add_path('/Info/BatteryLowVoltage', None, writeable=True) self._dbusservice.add_path('/Alarms/CellImbalance', None, writeable=True) @@ -88,8 +89,6 @@ class DbusBatteryService: self._dbusservice.add_path('/System/MaxVoltageCellId', None, writeable=True) self._dbusservice.add_path("/System/MinTemperatureCellId", None, writeable=True) self._dbusservice.add_path("/System/MaxTemperatureCellId", None, writeable=True) - #self._dbusservice.add_path('/System/MinCellTemperature', None, writeable=True) - #self._dbusservice.add_path('/System/MaxCellTemperature', None, writeable=True) self._settings = SettingsDevice( bus=dbus.SystemBus() if (platform.machine() == 'armv7l') else dbus.SessionBus(), @@ -110,7 +109,8 @@ class DbusBatteryService: '/Dc/0/Voltage': {'gettext': '%.2F V'}, '/Dc/0/Current': {'gettext': '%.2F A'}, '/Dc/0/Power': {'gettext': '%.0F W'}, - '/Soc': {'gettext': '%.0F %%'}, + '/Soc': {'gettext': '%.0F%%'}, + '/Soh': {'gettext': '%.0F%%'}, '/History/TotalAhDrawn': {'gettext': '%.0F Ah'}, '/History/DischargedEnergy': {'gettext': '%.2F kWh'}, '/History/ChargedEnergy': {'gettext': '%.2F kWh'}, @@ -134,13 +134,17 @@ class DbusBatteryService: self._dbusservice.add_path('/History/TimeSinceLastFullCharge', 0) self._dbusservice.add_path('/History/MinCellVoltage', self._settings['MinCellVoltage']) self._dbusservice.add_path('/History/MaxCellVoltage', self._settings['MaxCellVoltage']) - self._dbusservice['/ConsumedAmphours'] = self._bat.AhToEmpty + self._dbusservice['/Soh'] = 100 + self._dbusservice['/Status'] = 0 + logging.info("History cell voltage min: %.3f, max: %.3f, totalAhDrawn: %d", self._settings['MinCellVoltage'], self._settings['MaxCellVoltage'], self._settings['TotalAhDrawn']) - self._dbusservice['/History/ChargedEnergy'] = 0 - self._dbusservice['/History/DischargedEnergy'] = 0 + if self._bat.soc <= 99: + self._dbusservice['/Soc'] = self._bat.soc + elif self._bat.soc > 100: + self._dbusservice['/Soc'] = 100 GLib.timeout_add( self._settings['interval'], exit_on_error, self._update) @@ -154,7 +158,6 @@ class DbusBatteryService: self._safe_history() logging.info('Stopping dbus_Batrium') - def _safe_history(self): logging.debug('Saving history to localsettings') self._settings['AvgDischarge'] = self._dbusservice['/History/AverageDischarge'] @@ -162,18 +165,18 @@ class DbusBatteryService: self._settings['MinCellVoltage'] = self._dbusservice['/History/MinCellVoltage'] self._settings['MaxCellVoltage'] = self._dbusservice['/History/MaxCellVoltage'] - def _daily_stats(self): if (self._dbusservice['/History/DischargedEnergy'] == 0): return logging.info("Updating stats, SOC: %d, Discharged: %.2f, Charged: %.2f ",self._bat.soc, self._dbusservice['/History/DischargedEnergy'], self._dbusservice['/History/ChargedEnergy']) self._dbusservice['/History/AverageDischarge'] = (6*self._dbusservice['/History/AverageDischarge'] + self._dbusservice['/History/DischargedEnergy'])/7 #rolling week self._dbusservice['/History/ChargedEnergy'] = 0 + self.ChargedEnergy = 0 self._dbusservice['/History/DischargedEnergy'] = 0 + self.DischargedEnergy = 0 dt = datetime.now() - datetime.fromtimestamp( float(self._settings['TimeLastFull']) ) self.dailyResetDone = datetime.now().day - def _update(self): #logging.debug("Update CAN %d, Time Now: %d", self._bat.updated, self.lastUpdated) time = datetime.now() @@ -203,21 +206,24 @@ class DbusBatteryService: self._dbusservice['/Alarms/HighDischargeCurrent'] = 2 else: self._dbusservice['/Alarms/HighDischargeCurrent'] = 0 - if self._bat.alarm_low_soc: - self._dbusservice['/Alarms/LowSoc'] = 2 - else: - self._dbusservice['/Alarms/LowSoc'] = 0 if (self._bat.updated != -1 and self.lastUpdated == 0) or ((self.lastUpdated - self._bat.updated) < 10): self._dbusservice['/Connected'] = 1 else: self._dbusservice['/Connected'] = 0 - self._dbusservice['/Soc'] = self._bat.soc + if self._bat.soc <= 99: + self._dbusservice['/Soc'] = self._bat.soc + elif (self._bat.soc > 99) and (self.cell_balanced): + self._dbusservice['/Soc'] = 100 + if self._bat.NumberInBypass != 0: self._dbusservice['/Balancing'] = 1 else: self._dbusservice['/Balancing'] = 0 + + #self._dbusservice['/ConsumedAmphours'] = self._bat.AhToFull --- not working, Batrium not transmitting + self._dbusservice['/ConsumedAmphours'] = ((100 - self._dbusservice['/Soc']) / 100) * self._bat.capacity self._dbusservice['/InstalledCapacity'] = self._bat.capacity self._dbusservice['/Capacity'] = self._bat.capacity self._dbusservice['/Dc/0/Current'] = self._bat.current @@ -233,6 +239,7 @@ class DbusBatteryService: self._dbusservice['/Info/MaxChargeVoltage'] = self._bat.maxChargeVoltage self._dbusservice['/System/NrOfModulesOnline'] = self._bat.numberOfModules + self._dbusservice['/System/NrOfBatteriesBalancing'] = self._bat.NumberInBypass self._dbusservice['/System/BatteriesSeries'] = self._bat.numberOfModules #update energy statistics daily at 6:00, @@ -262,13 +269,34 @@ class DbusBatteryService: if self._bat.current > 0: #charging - self._dbusservice['/TimeToGo'] = self._bat.TimeToFull * 60 + if self._bat.NumberInBypass < 80000: + self._dbusservice['/TimeToGo'] = self._bat.TimeToFull + else: + self._dbusservice['/TimeToGo'] = None else : #discharging - self._dbusservice['/TimeToGo'] = self._bat.TimeToEmpty * 60 + if self._bat.NumberInBypass < 80000: + self._dbusservice['/TimeToGo'] = self._bat.TimeToEmpty + else: + self._dbusservice['/TimeToGo'] = None + + if self._bat.NumberInBypass == self._bat.numberOfModules: + self.cell_balanced = True + elif self._bat.NumberInBypass == 0: + self.cell_balanced = False self._safe_history() + if now.second != self.secUpdateDone: + self.secUpdateDone = now.second + #Workaround because of missing messages of Batrium BMS + if power > 0: + self.ChargedEnergy += (power / 3600.0) / 1000 + if power < 0: + self.DischargedEnergy += (power / 3600.0) / 1000 + self._dbusservice['/History/ChargedEnergy'] = abs(self.ChargedEnergy) + self._dbusservice['/History/DischargedEnergy'] = abs(self.DischargedEnergy) + return True def main(): diff --git a/dbus_batrium_native/requirements.sh b/dbus-batrium-native/requirements.sh similarity index 100% rename from dbus_batrium_native/requirements.sh rename to dbus-batrium-native/requirements.sh diff --git a/dbus_batrium_native/service/run b/dbus-batrium-native/service/run similarity index 58% rename from dbus_batrium_native/service/run rename to dbus-batrium-native/service/run index f65a430..5b4036f 100644 --- a/dbus_batrium_native/service/run +++ b/dbus-batrium-native/service/run @@ -1,3 +1,3 @@ #!/bin/sh exec 2>&1 -exec softlimit -d 100000000 -s 1000000 -a 100000000 python /data/dbus_batrium_native/dbus_batrium_native.py -i can0 -c 300 +exec softlimit -d 100000000 -s 1000000 -a 100000000 python /data/dbus-batrium-native/dbus-batrium-native.py