#!/usr/bin/env python import argparse import platform import logging import sys import os import time import datetime import serial import math import struct import decimal import codecs # setup timezone os.environ['TZ'] = 'Europe/Berlin' logging.basicConfig( format='%(asctime)s %(levelname)-8s %(message)s', level=logging.INFO, datefmt='%Y-%m-%d %H:%M:%S') # filename='log.txt') # connect and register to dbus driver = { 'name' : "Chargery BMS", 'servicename' : "chargerybms", 'instance' : 1, 'id' : 0x01, 'version' : 1.2, 'serial' : "CHGBMS11062020A1", 'connection' : "com.victronenergy.battery.ttyCHGBMS01" } parser = argparse.ArgumentParser(description = 'Chargery BMS driver') parser.add_argument('--version', action='version', version='%(prog)s v' + str(driver['version']) + ' (' + driver['serial'] + ')') parser.add_argument('--debug', action="store_true", help='enable debug logging') parser.add_argument('--test', action="store_true", help='test some stored examples network packets') parser.add_argument('-o', '--output', help='save data to OUTPUT') requiredArguments = parser.add_argument_group('required arguments') requiredArguments.add_argument('-d', '--device', help='serial device for data (eg /dev/ttyUSB0)', required=True) args = parser.parse_args() if args.debug: # switch to debug level logger = logging.getLogger() logger.setLevel(logging.DEBUG) serial_port = serial.Serial(args.device, 115200, timeout=1) serial_port.flushInput() logging.info(serial_port.name) PACKET_HEADER = 0x24 PACKET_STATUS_CELLS = 0x56 PACKET_STATUS_BMS = 0x57 PACKET_STATUS_IMPEDANCES = 0x58 PACKET_LENGTH_MINIMUM = 10 PACKET_LENGTH_STATUS_CELLS = [29, 45, 61] PACKET_LENGTH_STATUS_BMS = [15] # Special handling here: the impedances packet length is dynamically # and depends on how many cells are monitored. The minimum length of # the network packet with headers, command, length, currentmode1, current1 # and checksum is 8 bytes. On 6 monitored cells the packet length will # be 8+(2*6) = 20 bytes. Therefore, the smallest possible and valid # impedances network packet will be 10 bytes PACKET_LENGTH_STATUS_IMPEDANCES = 10 MIN_CELL_VOLTAGE = 1.0 MIN_CELL_IMPEDANCE = 0.0 BMS_STATUS = { 'bms' : { 'charged_end_voltage' : { 'value' : -1.000, 'text' : "" }, 'current_mode' : { 'value' : -1, 'text' : "" }, 'current' : { 'value' : -1, 'text' : "" }, 'temperature' : { 'sensor_t1' : { 'value' : -1.00, 'text' : "" }, 'sensor_t2' : { 'value' : -1.00, 'text' : "" } }, 'soc' : { 'value' : -1, 'text' : "" }, 'timestamp' : { 'value' : -1, 'text' : "" } }, 'voltages' : { 'cell01_voltage' : { 'value' : -1, 'text' : "" }, 'cell02_voltage' : { 'value' : -1, 'text' : "" }, 'cell03_voltage' : { 'value' : -1, 'text' : "" }, 'cell04_voltage' : { 'value' : -1, 'text' : "" }, 'cell05_voltage' : { 'value' : -1, 'text' : "" }, 'cell06_voltage' : { 'value' : -1, 'text' : "" }, 'cell07_voltage' : { 'value' : -1, 'text' : "" }, 'cell08_voltage' : { 'value' : -1, 'text' : "" }, 'cell09_voltage' : { 'value' : -1, 'text' : "" }, 'cell10_voltage' : { 'value' : -1, 'text' : "" }, 'cell11_voltage' : { 'value' : -1, 'text' : "" }, 'cell12_voltage' : { 'value' : -1, 'text' : "" }, 'cell13_voltage' : { 'value' : -1, 'text' : "" }, 'cell14_voltage' : { 'value' : -1, 'text' : "" }, 'cell15_voltage' : { 'value' : -1, 'text' : "" }, 'cell16_voltage' : { 'value' : -1, 'text' : "" }, 'cell17_voltage' : { 'value' : -1, 'text' : "" }, 'cell18_voltage' : { 'value' : -1, 'text' : "" }, 'cell19_voltage' : { 'value' : -1, 'text' : "" }, 'cell20_voltage' : { 'value' : -1, 'text' : "" }, 'cell21_voltage' : { 'value' : -1, 'text' : "" }, 'cell22_voltage' : { 'value' : -1, 'text' : "" }, 'cell23_voltage' : { 'value' : -1, 'text' : "" }, 'cell24_voltage' : { 'value' : -1, 'text' : "" }, 'agg_voltages' : { 'sum' : { 'value' : -1, 'text' : "" }, 'max' : { 'value' : -1, 'text' : "" }, 'min' : { 'value' : -1, 'text' : "" }, 'diff' : { 'value' : -1, 'text' : "" } }, 'battery_capacity_wh' : { 'value' : -1, 'text' : "" }, 'battery_capacity_ah' : { 'value' : -1, 'text' : "" }, 'timestamp' : { 'value' : -1, 'text' : "" } }, 'impedances' : { 'current_mode1' : { 'value' : -1, 'text' : "" }, 'current1' : { 'value' : -1, 'text' : "" }, 'cell01_impedance' : { 'value' : -1, 'text' : "" }, 'cell02_impedance' : { 'value' : -1, 'text' : "" }, 'cell03_impedance' : { 'value' : -1, 'text' : "" }, 'cell04_impedance' : { 'value' : -1, 'text' : "" }, 'cell05_impedance' : { 'value' : -1, 'text' : "" }, 'cell06_impedance' : { 'value' : -1, 'text' : "" }, 'cell07_impedance' : { 'value' : -1, 'text' : "" }, 'cell08_impedance' : { 'value' : -1, 'text' : "" }, 'cell09_impedance' : { 'value' : -1, 'text' : "" }, 'cell10_impedance' : { 'value' : -1, 'text' : "" }, 'cell11_impedance' : { 'value' : -1, 'text' : "" }, 'cell12_impedance' : { 'value' : -1, 'text' : "" }, 'cell13_impedance' : { 'value' : -1, 'text' : "" }, 'cell14_impedance' : { 'value' : -1, 'text' : "" }, 'cell15_impedance' : { 'value' : -1, 'text' : "" }, 'cell16_impedance' : { 'value' : -1, 'text' : "" }, 'cell17_impedance' : { 'value' : -1, 'text' : "" }, 'cell18_impedance' : { 'value' : -1, 'text' : "" }, 'cell19_impedance' : { 'value' : -1, 'text' : "" }, 'cell20_impedance' : { 'value' : -1, 'text' : "" }, 'cell21_impedance' : { 'value' : -1, 'text' : "" }, 'cell22_impedance' : { 'value' : -1, 'text' : "" }, 'cell23_impedance' : { 'value' : -1, 'text' : "" }, 'cell24_impedance' : { 'value' : -1, 'text' : "" }, 'agg_impedances' : { 'sum' : { 'value' : -1, 'text' : "" }, 'max' : { 'value' : -1, 'text' : "" }, 'min' : { 'value' : -1, 'text' : "" }, 'diff' : { 'value' : -1, 'text' : "" } }, 'battery_capacity_wh' : { 'value' : -1, 'text' : "" }, 'battery_capacity_ah' : { 'value' : -1, 'text' : "" }, 'timestamp' : { 'value' : -1, 'text' : "" } } } # example network packets form the chargery community protocol manual v1.25 BMS_TEST_PACKETS = { 1 : bytearray.fromhex('2424570F0E240100E6008100845B27'), 2 : bytearray.fromhex('2424570F0E240100E4008100845B25'), 3 : bytearray.fromhex('2424570F0E240100E1008300845B24'), 4 : bytearray.fromhex('2424562D0CFD0D040D040D020D030D040D060D010D080D020D050CFE0D060CFB0D0F0CFC76FED50263140E0095'), 5 : bytearray.fromhex('2424582801E4000100030003000300020003000000000001000100010000000500020003000300CC'), 6 : bytearray.fromhex('2424570F0E240100E4008300845B27'), 7 : bytearray.fromhex('24245814012a000900040007000b000b00070010') } # define special unicode characters here SPECIAL_DISPLAY_SYMBOLS = { 'degree' : u'\u00b0', 'ohm' : u'\u03A9' } def dfs_bms_status (f, bms_status, prefix=""): import functools, operator if "value" in bms_status: return [f(prefix, bms_status)] else: return functools.reduce(operator.add, [dfs_bms_status(f, bms_status[sub_dict], (prefix+"." if len(prefix)>0 else "") + sub_dict) for sub_dict in sorted(bms_status.keys())], []) def print_status_header (prefix, bms_status_leaf): return prefix def print_status_value (prefix, bms_status_leaf): return bms_status_leaf["value"] def reset_status_values(): BMS_STATUS['bms']['charged_end_voltage']['value'] = -1 BMS_STATUS['bms']['charged_end_voltage']['text'] = "" BMS_STATUS['bms']['current_mode']['value'] = -1 BMS_STATUS['bms']['current_mode']['text'] = "" BMS_STATUS['bms']['current']['value'] = -1 BMS_STATUS['bms']['current']['text'] = "" BMS_STATUS['bms']['temperature']['sensor_t1']['value'] = -1 BMS_STATUS['bms']['temperature']['sensor_t1']['text'] = "" BMS_STATUS['bms']['temperature']['sensor_t2']['value'] = -1 BMS_STATUS['bms']['temperature']['sensor_t2']['text'] = "" BMS_STATUS['bms']['soc']['value'] = -1 BMS_STATUS['bms']['soc']['text'] = "" BMS_STATUS['bms']['timestamp']['value'] = -1 BMS_STATUS['bms']['timestamp']['text'] = "" def reset_impedances_values(): BMS_STATUS['impedances']['current_mode1']['value'] = -1 BMS_STATUS['impedances']['current_mode1']['text'] = "" BMS_STATUS['impedances']['current1']['value'] = -1 BMS_STATUS['impedances']['current1']['text'] = "" BMS_STATUS['impedances']['cell01_impedance']['value'] = -1 BMS_STATUS['impedances']['cell01_impedance']['text'] = "" BMS_STATUS['impedances']['cell02_impedance']['value'] = -1 BMS_STATUS['impedances']['cell02_impedance']['text'] = "" BMS_STATUS['impedances']['cell03_impedance']['value'] = -1 BMS_STATUS['impedances']['cell03_impedance']['text'] = "" BMS_STATUS['impedances']['cell04_impedance']['value'] = -1 BMS_STATUS['impedances']['cell04_impedance']['text'] = "" BMS_STATUS['impedances']['cell05_impedance']['value'] = -1 BMS_STATUS['impedances']['cell05_impedance']['text'] = "" BMS_STATUS['impedances']['cell06_impedance']['value'] = -1 BMS_STATUS['impedances']['cell06_impedance']['text'] = "" BMS_STATUS['impedances']['cell07_impedance']['value'] = -1 BMS_STATUS['impedances']['cell07_impedance']['text'] = "" BMS_STATUS['impedances']['cell08_impedance']['value'] = -1 BMS_STATUS['impedances']['cell08_impedance']['text'] = "" BMS_STATUS['impedances']['cell09_impedance']['value'] = -1 BMS_STATUS['impedances']['cell09_impedance']['text'] = "" BMS_STATUS['impedances']['cell10_impedance']['value'] = -1 BMS_STATUS['impedances']['cell10_impedance']['text'] = "" BMS_STATUS['impedances']['cell11_impedance']['value'] = -1 BMS_STATUS['impedances']['cell11_impedance']['text'] = "" BMS_STATUS['impedances']['cell12_impedance']['value'] = -1 BMS_STATUS['impedances']['cell12_impedance']['text'] = "" BMS_STATUS['impedances']['cell13_impedance']['value'] = -1 BMS_STATUS['impedances']['cell13_impedance']['text'] = "" BMS_STATUS['impedances']['cell14_impedance']['value'] = -1 BMS_STATUS['impedances']['cell14_impedance']['text'] = "" BMS_STATUS['impedances']['cell15_impedance']['value'] = -1 BMS_STATUS['impedances']['cell15_impedance']['text'] = "" BMS_STATUS['impedances']['cell16_impedance']['value'] = -1 BMS_STATUS['impedances']['cell16_impedance']['text'] = "" BMS_STATUS['impedances']['cell17_impedance']['value'] = -1 BMS_STATUS['impedances']['cell17_impedance']['text'] = "" BMS_STATUS['impedances']['cell18_impedance']['value'] = -1 BMS_STATUS['impedances']['cell18_impedance']['text'] = "" BMS_STATUS['impedances']['cell19_impedance']['value'] = -1 BMS_STATUS['impedances']['cell19_impedance']['text'] = "" BMS_STATUS['impedances']['cell20_impedance']['value'] = -1 BMS_STATUS['impedances']['cell20_impedance']['text'] = "" BMS_STATUS['impedances']['cell21_impedance']['value'] = -1 BMS_STATUS['impedances']['cell21_impedance']['text'] = "" BMS_STATUS['impedances']['cell22_impedance']['value'] = -1 BMS_STATUS['impedances']['cell22_impedance']['text'] = "" BMS_STATUS['impedances']['cell23_impedance']['value'] = -1 BMS_STATUS['impedances']['cell23_impedance']['text'] = "" BMS_STATUS['impedances']['cell24_impedance']['value'] = -1 BMS_STATUS['impedances']['cell24_impedance']['text'] = "" BMS_STATUS['impedances']['agg_impedances']['sum']['value'] = -1 BMS_STATUS['impedances']['agg_impedances']['sum']['text'] = "" BMS_STATUS['impedances']['agg_impedances']['max']['value'] = -1 BMS_STATUS['impedances']['agg_impedances']['max']['text'] = "" BMS_STATUS['impedances']['agg_impedances']['min']['value'] = -1 BMS_STATUS['impedances']['agg_impedances']['min']['text'] = "" BMS_STATUS['impedances']['agg_impedances']['diff']['value'] = -1 BMS_STATUS['impedances']['agg_impedances']['diff']['text'] = "" BMS_STATUS['impedances']['battery_capacity_wh']['value'] = -1 BMS_STATUS['impedances']['battery_capacity_wh']['text'] = "" BMS_STATUS['impedances']['battery_capacity_ah']['value'] = -1 BMS_STATUS['impedances']['battery_capacity_ah']['text'] = "" BMS_STATUS['impedances']['timestamp']['value'] = -1 BMS_STATUS['impedances']['timestamp']['text'] = "" def reset_voltages_values(): BMS_STATUS['voltages']['cell01_voltage']['value'] = -1 BMS_STATUS['voltages']['cell01_voltage']['text'] = "" BMS_STATUS['voltages']['cell02_voltage']['value'] = -1 BMS_STATUS['voltages']['cell02_voltage']['text'] = "" BMS_STATUS['voltages']['cell03_voltage']['value'] = -1 BMS_STATUS['voltages']['cell03_voltage']['text'] = "" BMS_STATUS['voltages']['cell04_voltage']['value'] = -1 BMS_STATUS['voltages']['cell04_voltage']['text'] = "" BMS_STATUS['voltages']['cell05_voltage']['value'] = -1 BMS_STATUS['voltages']['cell05_voltage']['text'] = "" BMS_STATUS['voltages']['cell06_voltage']['value'] = -1 BMS_STATUS['voltages']['cell06_voltage']['text'] = "" BMS_STATUS['voltages']['cell07_voltage']['value'] = -1 BMS_STATUS['voltages']['cell07_voltage']['text'] = "" BMS_STATUS['voltages']['cell08_voltage']['value'] = -1 BMS_STATUS['voltages']['cell08_voltage']['text'] = "" BMS_STATUS['voltages']['cell09_voltage']['value'] = -1 BMS_STATUS['voltages']['cell09_voltage']['text'] = "" BMS_STATUS['voltages']['cell10_voltage']['value'] = -1 BMS_STATUS['voltages']['cell10_voltage']['text'] = "" BMS_STATUS['voltages']['cell11_voltage']['value'] = -1 BMS_STATUS['voltages']['cell11_voltage']['text'] = "" BMS_STATUS['voltages']['cell12_voltage']['value'] = -1 BMS_STATUS['voltages']['cell12_voltage']['text'] = "" BMS_STATUS['voltages']['cell13_voltage']['value'] = -1 BMS_STATUS['voltages']['cell13_voltage']['text'] = "" BMS_STATUS['voltages']['cell14_voltage']['value'] = -1 BMS_STATUS['voltages']['cell14_voltage']['text'] = "" BMS_STATUS['voltages']['cell15_voltage']['value'] = -1 BMS_STATUS['voltages']['cell15_voltage']['text'] = "" BMS_STATUS['voltages']['cell16_voltage']['value'] = -1 BMS_STATUS['voltages']['cell16_voltage']['text'] = "" BMS_STATUS['voltages']['cell17_voltage']['value'] = -1 BMS_STATUS['voltages']['cell17_voltage']['text'] = "" BMS_STATUS['voltages']['cell18_voltage']['value'] = -1 BMS_STATUS['voltages']['cell18_voltage']['text'] = "" BMS_STATUS['voltages']['cell19_voltage']['value'] = -1 BMS_STATUS['voltages']['cell19_voltage']['text'] = "" BMS_STATUS['voltages']['cell20_voltage']['value'] = -1 BMS_STATUS['voltages']['cell20_voltage']['text'] = "" BMS_STATUS['voltages']['cell21_voltage']['value'] = -1 BMS_STATUS['voltages']['cell21_voltage']['text'] = "" BMS_STATUS['voltages']['cell22_voltage']['value'] = -1 BMS_STATUS['voltages']['cell22_voltage']['text'] = "" BMS_STATUS['voltages']['cell23_voltage']['value'] = -1 BMS_STATUS['voltages']['cell23_voltage']['text'] = "" BMS_STATUS['voltages']['cell24_voltage']['value'] = -1 BMS_STATUS['voltages']['cell24_voltage']['text'] = "" BMS_STATUS['voltages']['agg_voltages']['sum']['value'] = -1 BMS_STATUS['voltages']['agg_voltages']['sum']['text'] = "" BMS_STATUS['voltages']['agg_voltages']['max']['value'] = -1 BMS_STATUS['voltages']['agg_voltages']['max']['text'] = "" BMS_STATUS['voltages']['agg_voltages']['min']['value'] = -1 BMS_STATUS['voltages']['agg_voltages']['min']['text'] = "" BMS_STATUS['voltages']['agg_voltages']['diff']['value'] = -1 BMS_STATUS['voltages']['agg_voltages']['diff']['text'] = "" BMS_STATUS['voltages']['battery_capacity_wh']['value'] = -1 BMS_STATUS['voltages']['battery_capacity_wh']['text'] = "" BMS_STATUS['voltages']['battery_capacity_ah']['value'] = -1 BMS_STATUS['voltages']['battery_capacity_ah']['text'] = "" BMS_STATUS['voltages']['timestamp']['value'] = -1 BMS_STATUS['voltages']['timestamp']['text'] = "" def debug_packet(packet): string_output = "" for packet_byte in packet: # print(packet_byte) byte_string = str((packet_byte)) + " [" + hex(packet_byte) + "] " string_output = string_output + byte_string logging.debug(string_output); def get_header_position(packet): # detect header position previous_packet_byte = "0" pos_iterator = -1 for packet_byte in packet: pos_iterator += 1 if (((previous_packet_byte) == PACKET_HEADER) and ((packet_byte) == PACKET_HEADER)): break previous_packet_byte = packet_byte return pos_iterator def get_voltage_value(byte1, byte2): return float((float(byte1 * 256) + float(byte2)) / 1000) def get_current_value(byte1, byte2): return float((float(byte1 * 256) + float(byte2)) / 10) def get_current1_value(byte1, byte2): return float((float(byte1) + float(byte2 * 256)) / 10) def get_temperature_value(byte1, byte2): return float((float(byte1 * 256) + float(byte2)) / 10) def get_battery_capacity(byte1, byte2, byte3, byte4): return float((float(byte1) + float(byte2 * 256) + float(byte3 * 256 * 256) + float(byte4 * 256 * 256 * 256)) / 1000) def get_cell_impedance(byte1, byte2): return float((float(byte1) + float(byte2 * 256)) / 10) def parse_packet(packet): logging.debug("Parse Packet [" + str(len(packet)) + "] bytes") debug_packet(packet) while (len(packet) >= PACKET_LENGTH_MINIMUM): header_position = get_header_position(packet) # now parse the packet if ((header_position == -1) or (header_position == len(packet) - 1)): logging.debug("Packet Invalid") packet = "" else: # strip packet packet = packet[(header_position - 1):] if (len(packet) >= 4): if (((packet[0]) == PACKET_HEADER) and ((packet[1]) == PACKET_HEADER)): packet_length = (packet[3]) logging.debug("Packet Length [" + str (packet_length) + " bytes]") debug_packet(packet) if ((packet[2]) == PACKET_STATUS_BMS): if (len(packet) < PACKET_LENGTH_STATUS_BMS[0]): logging.debug("Packet Status BMS too short, skip") packet = "" else: # delete old data reset_status_values() # checksum value checksum = (packet[packet_length-1]) checksum_check = 0 # calculate checksum for i in range(packet_length-1): checksum_check = checksum_check + (packet[i]) checksum_check = checksum_check % 256 logging.debug("Packet Checksum : " + str(checksum) + "|" + str(checksum_check)) # data integrity does match if (checksum == checksum_check): # charge end voltage BMS_STATUS['bms']['charged_end_voltage']['value'] = get_voltage_value((packet[4]), (packet[5])) BMS_STATUS['bms']['charged_end_voltage']['text'] = "{:.2f}".format(BMS_STATUS['bms']['charged_end_voltage']['value']) + "V" # actual current BMS_STATUS['bms']['current']['value'] = get_current_value((packet[7]), (packet[8])) # charge mode bms_current_mode = (packet[6]) if (bms_current_mode == 0x00): BMS_STATUS['bms']['current_mode']['value'] = 0 BMS_STATUS['bms']['current_mode']['text'] = "Discharge" BMS_STATUS['bms']['current']['text'] = "-" + str(BMS_STATUS['bms']['current']['value']) + "A" elif (bms_current_mode == 0x01): BMS_STATUS['bms']['current_mode']['value'] = 1 BMS_STATUS['bms']['current_mode']['text'] = "Charge" BMS_STATUS['bms']['current']['text'] = str(BMS_STATUS['bms']['current']['value']) + "A" elif (bms_current_mode == 0x02): BMS_STATUS['bms']['current_mode']['value'] = 2 BMS_STATUS['bms']['current_mode']['text'] = "Storage" BMS_STATUS['bms']['current']['text'] = str(BMS_STATUS['bms']['current']['value']) + "A" else: BMS_STATUS['bms']['current_mode']['value'] = -1 BMS_STATUS['bms']['current_mode']['text'] = "" BMS_STATUS['bms']['current']['text'] = "" # current temperatures BMS_STATUS['bms']['temperature']['sensor_t1']['value'] = get_temperature_value((packet[9]), (packet[10])) BMS_STATUS['bms']['temperature']['sensor_t1']['text'] = str(BMS_STATUS['bms']['temperature']['sensor_t1']['value']) + SPECIAL_DISPLAY_SYMBOLS['degree'] + "C" BMS_STATUS['bms']['temperature']['sensor_t2']['value'] = get_temperature_value((packet[11]), (packet[12])) BMS_STATUS['bms']['temperature']['sensor_t2']['text'] = str(BMS_STATUS['bms']['temperature']['sensor_t2']['value']) + SPECIAL_DISPLAY_SYMBOLS['degree'] + "C" # soc value BMS_STATUS['bms']['soc']['value'] = (packet[13]) BMS_STATUS['bms']['soc']['text'] = str((packet[13])) + "%" # update timestamp current_date = datetime.datetime.now() BMS_STATUS['bms']['timestamp']['value'] = time.time() BMS_STATUS['bms']['timestamp']['text'] = current_date.strftime('%a %d.%m.%Y %H:%M:%S') # print (BMS_STATUS) logging.info("BMS Status [SOC|" + BMS_STATUS['bms']['soc']['text'] + "][MODE|" + BMS_STATUS['bms']['current_mode']['text'] + "][CURRENT|" + BMS_STATUS['bms']['current']['text'] + "][T1|" + BMS_STATUS['bms']['temperature']['sensor_t1']['text'] + "][T2|" + BMS_STATUS['bms']['temperature']['sensor_t1']['text'] + "][MAX CHARGE VOLTAGE|" + BMS_STATUS['bms']['charged_end_voltage']['text'] + "]") else: logging.info("Packet Checksum wrong, skip packet") # strip packet packet = packet[packet_length:] elif ((packet[2]) == PACKET_STATUS_CELLS): if (len(packet) < PACKET_LENGTH_STATUS_CELLS[0]): logging.debug("Packet Status Cells too short, skip") packet = "" else: # delete old data reset_voltages_values() # checksum value checksum = -1 checksum_check = 0 if (packet_length == PACKET_LENGTH_STATUS_CELLS[0]): # packet from BMS8 logging.debug("Packet Status Cells BMS8") if (len(packet) < PACKET_LENGTH_STATUS_CELLS[0]): logging.debug("Packet Status Cells too short, skip") packet = "" else: checksum = (packet[packet_length-1]) # calculate checksum for i in range(packet_length-1): checksum_check = checksum_check + (packet[i]) checksum_check = checksum_check % 256 logging.debug("Packet Checksum BMS8: " + str(checksum) + "|" + str(checksum_check)) elif (packet_length == PACKET_LENGTH_STATUS_CELLS[1]): # packet from BMS16 logging.debug("Packet Status Cells BMS16") if (len(packet) < PACKET_LENGTH_STATUS_CELLS[1]): logging.debug("Packet Status Cells too short, skip") packet = "" else: checksum = (packet[packet_length-1]) # calculate checksum for i in range(packet_length-1): checksum_check = checksum_check + (packet[i]) checksum_check = checksum_check % 256 logging.debug("Packet Checksum BMS16: " + str(checksum) + "|" + str(checksum_check)) elif (packet_length == PACKET_LENGTH_STATUS_CELLS[2]): # packet from BMS24 logging.debug("Packet Status Cells BMS24") if (len(packet) < PACKET_LENGTH_STATUS_CELLS[2]): logging.debug("Packet Status Cells too short, skip") packet = "" else: checksum = (packet[packet_length-1]) # calculate checksum for i in range(packet_length-1): checksum_check = checksum_check + (packet[i]) checksum_check = checksum_check % 256 logging.debug("Packet Checksum BMS24: " + str(checksum) + "|" + str(checksum_check)) # data integrity does match if (checksum == checksum_check): # cell voltages BMS8 BMS_STATUS['voltages']['cell01_voltage']['value'] = get_voltage_value((packet[4]), (packet[5])) BMS_STATUS['voltages']['cell01_voltage']['text'] = "{:.3f}".format(BMS_STATUS['voltages']['cell01_voltage']['value']) + "V" BMS_STATUS['voltages']['cell02_voltage']['value'] = get_voltage_value((packet[6]), (packet[7])) BMS_STATUS['voltages']['cell02_voltage']['text'] = "{:.3f}".format(BMS_STATUS['voltages']['cell02_voltage']['value']) + "V" BMS_STATUS['voltages']['cell03_voltage']['value'] = get_voltage_value((packet[8]), (packet[9])) BMS_STATUS['voltages']['cell03_voltage']['text'] = "{:.3f}".format(BMS_STATUS['voltages']['cell03_voltage']['value']) + "V" BMS_STATUS['voltages']['cell04_voltage']['value'] = get_voltage_value((packet[10]), (packet[11])) BMS_STATUS['voltages']['cell04_voltage']['text'] = "{:.3f}".format(BMS_STATUS['voltages']['cell04_voltage']['value']) + "V" BMS_STATUS['voltages']['cell05_voltage']['value'] = get_voltage_value((packet[12]), (packet[13])) BMS_STATUS['voltages']['cell05_voltage']['text'] = "{:.3f}".format(BMS_STATUS['voltages']['cell05_voltage']['value']) + "V" BMS_STATUS['voltages']['cell06_voltage']['value'] = get_voltage_value((packet[14]), (packet[15])) BMS_STATUS['voltages']['cell06_voltage']['text'] = "{:.3f}".format(BMS_STATUS['voltages']['cell06_voltage']['value']) + "V" BMS_STATUS['voltages']['cell07_voltage']['value'] = get_voltage_value((packet[16]), (packet[17])) BMS_STATUS['voltages']['cell07_voltage']['text'] = "{:.3f}".format(BMS_STATUS['voltages']['cell07_voltage']['value']) + "V" BMS_STATUS['voltages']['cell08_voltage']['value'] = get_voltage_value((packet[18]), (packet[19])) BMS_STATUS['voltages']['cell08_voltage']['text'] = "{:.3f}".format(BMS_STATUS['voltages']['cell08_voltage']['value']) + "V" if (packet_length == PACKET_LENGTH_STATUS_CELLS[1]): # packet from BMS16 BMS_STATUS['voltages']['cell09_voltage']['value'] = get_voltage_value((packet[20]), (packet[21])) BMS_STATUS['voltages']['cell09_voltage']['text'] = "{:.3f}".format(BMS_STATUS['voltages']['cell09_voltage']['value']) + "V" BMS_STATUS['voltages']['cell10_voltage']['value'] = get_voltage_value((packet[22]), (packet[23])) BMS_STATUS['voltages']['cell10_voltage']['text'] = "{:.3f}".format(BMS_STATUS['voltages']['cell10_voltage']['value']) + "V" BMS_STATUS['voltages']['cell11_voltage']['value'] = get_voltage_value((packet[24]), (packet[25])) BMS_STATUS['voltages']['cell11_voltage']['text'] = "{:.3f}".format(BMS_STATUS['voltages']['cell11_voltage']['value']) + "V" BMS_STATUS['voltages']['cell12_voltage']['value'] = get_voltage_value((packet[26]), (packet[27])) BMS_STATUS['voltages']['cell12_voltage']['text'] = "{:.3f}".format(BMS_STATUS['voltages']['cell12_voltage']['value']) + "V" BMS_STATUS['voltages']['cell13_voltage']['value'] = get_voltage_value((packet[28]), (packet[29])) BMS_STATUS['voltages']['cell13_voltage']['text'] = "{:.3f}".format(BMS_STATUS['voltages']['cell13_voltage']['value']) + "V" BMS_STATUS['voltages']['cell14_voltage']['value'] = get_voltage_value((packet[30]), (packet[31])) BMS_STATUS['voltages']['cell14_voltage']['text'] = "{:.3f}".format(BMS_STATUS['voltages']['cell14_voltage']['value']) + "V" BMS_STATUS['voltages']['cell15_voltage']['value'] = get_voltage_value((packet[32]), (packet[33])) BMS_STATUS['voltages']['cell15_voltage']['text'] = "{:.3f}".format(BMS_STATUS['voltages']['cell15_voltage']['value']) + "V" BMS_STATUS['voltages']['cell16_voltage']['value'] = get_voltage_value((packet[34]), (packet[35])) BMS_STATUS['voltages']['cell16_voltage']['text'] = "{:.3f}".format(BMS_STATUS['voltages']['cell16_voltage']['value']) + "V" if (packet_length == PACKET_LENGTH_STATUS_CELLS[2]): # packet from BMS24 BMS_STATUS['voltages']['cell17_voltage']['value'] = get_voltage_value((packet[36]), (packet[37])) BMS_STATUS['voltages']['cell17_voltage']['text'] = "{:.3f}".format(BMS_STATUS['voltages']['cell17_voltage']['value']) + "V" BMS_STATUS['voltages']['cell18_voltage']['value'] = get_voltage_value((packet[38]), (packet[39])) BMS_STATUS['voltages']['cell18_voltage']['text'] = "{:.3f}".format(BMS_STATUS['voltages']['cell18_voltage']['value']) + "V" BMS_STATUS['voltages']['cell19_voltage']['value'] = get_voltage_value((packet[40]), (packet[41])) BMS_STATUS['voltages']['cell19_voltage']['text'] = "{:.3f}".format(BMS_STATUS['voltages']['cell19_voltage']['value']) + "V" BMS_STATUS['voltages']['cell20_voltage']['value'] = get_voltage_value((packet[42]), (packet[43])) BMS_STATUS['voltages']['cell20_voltage']['text'] = "{:.3f}".format(BMS_STATUS['voltages']['cell20_voltage']['value']) + "V" BMS_STATUS['voltages']['cell21_voltage']['value'] = get_voltage_value((packet[44]), (packet[45])) BMS_STATUS['voltages']['cell21_voltage']['text'] = "{:.3f}".format(BMS_STATUS['voltages']['cell21_voltage']['value']) + "V" BMS_STATUS['voltages']['cell22_voltage']['value'] = get_voltage_value((packet[46]), (packet[47])) BMS_STATUS['voltages']['cell22_voltage']['text'] = "{:.3f}".format(BMS_STATUS['voltages']['cell22_voltage']['value']) + "V" BMS_STATUS['voltages']['cell23_voltage']['value'] = get_voltage_value((packet[48]), (packet[49])) BMS_STATUS['voltages']['cell23_voltage']['text'] = "{:.3f}".format(BMS_STATUS['voltages']['cell23_voltage']['value']) + "V" BMS_STATUS['voltages']['cell24_voltage']['value'] = get_voltage_value((packet[50]), (packet[51])) BMS_STATUS['voltages']['cell24_voltage']['text'] = "{:.3f}".format(BMS_STATUS['voltages']['cell24_voltage']['value']) + "V" # get min/max voltages to calculate the diff cell_voltages = [] if (BMS_STATUS['voltages']['cell01_voltage']['value'] >= MIN_CELL_VOLTAGE): cell_voltages.append(BMS_STATUS['voltages']['cell01_voltage']['value']) if (BMS_STATUS['voltages']['cell02_voltage']['value'] >= MIN_CELL_VOLTAGE): cell_voltages.append(BMS_STATUS['voltages']['cell02_voltage']['value']) if (BMS_STATUS['voltages']['cell03_voltage']['value'] >= MIN_CELL_VOLTAGE): cell_voltages.append(BMS_STATUS['voltages']['cell03_voltage']['value']) if (BMS_STATUS['voltages']['cell04_voltage']['value'] >= MIN_CELL_VOLTAGE): cell_voltages.append(BMS_STATUS['voltages']['cell04_voltage']['value']) if (BMS_STATUS['voltages']['cell05_voltage']['value'] >= MIN_CELL_VOLTAGE): cell_voltages.append(BMS_STATUS['voltages']['cell05_voltage']['value']) if (BMS_STATUS['voltages']['cell06_voltage']['value'] >= MIN_CELL_VOLTAGE): cell_voltages.append(BMS_STATUS['voltages']['cell06_voltage']['value']) if (BMS_STATUS['voltages']['cell07_voltage']['value'] >= MIN_CELL_VOLTAGE): cell_voltages.append(BMS_STATUS['voltages']['cell07_voltage']['value']) if (BMS_STATUS['voltages']['cell08_voltage']['value'] >= MIN_CELL_VOLTAGE): cell_voltages.append(BMS_STATUS['voltages']['cell08_voltage']['value']) if (BMS_STATUS['voltages']['cell09_voltage']['value'] >= MIN_CELL_VOLTAGE): cell_voltages.append(BMS_STATUS['voltages']['cell09_voltage']['value']) if (BMS_STATUS['voltages']['cell10_voltage']['value'] >= MIN_CELL_VOLTAGE): cell_voltages.append(BMS_STATUS['voltages']['cell10_voltage']['value']) if (BMS_STATUS['voltages']['cell11_voltage']['value'] >= MIN_CELL_VOLTAGE): cell_voltages.append(BMS_STATUS['voltages']['cell11_voltage']['value']) if (BMS_STATUS['voltages']['cell12_voltage']['value'] >= MIN_CELL_VOLTAGE): cell_voltages.append(BMS_STATUS['voltages']['cell12_voltage']['value']) if (BMS_STATUS['voltages']['cell13_voltage']['value'] >= MIN_CELL_VOLTAGE): cell_voltages.append(BMS_STATUS['voltages']['cell13_voltage']['value']) if (BMS_STATUS['voltages']['cell14_voltage']['value'] >= MIN_CELL_VOLTAGE): cell_voltages.append(BMS_STATUS['voltages']['cell14_voltage']['value']) if (BMS_STATUS['voltages']['cell15_voltage']['value'] >= MIN_CELL_VOLTAGE): cell_voltages.append(BMS_STATUS['voltages']['cell15_voltage']['value']) if (BMS_STATUS['voltages']['cell16_voltage']['value'] >= MIN_CELL_VOLTAGE): cell_voltages.append(BMS_STATUS['voltages']['cell16_voltage']['value']) if (BMS_STATUS['voltages']['cell17_voltage']['value'] >= MIN_CELL_VOLTAGE): cell_voltages.append(BMS_STATUS['voltages']['cell17_voltage']['value']) if (BMS_STATUS['voltages']['cell18_voltage']['value'] >= MIN_CELL_VOLTAGE): cell_voltages.append(BMS_STATUS['voltages']['cell18_voltage']['value']) if (BMS_STATUS['voltages']['cell19_voltage']['value'] >= MIN_CELL_VOLTAGE): cell_voltages.append(BMS_STATUS['voltages']['cell19_voltage']['value']) if (BMS_STATUS['voltages']['cell20_voltage']['value'] >= MIN_CELL_VOLTAGE): cell_voltages.append(BMS_STATUS['voltages']['cell20_voltage']['value']) if (BMS_STATUS['voltages']['cell21_voltage']['value'] >= MIN_CELL_VOLTAGE): cell_voltages.append(BMS_STATUS['voltages']['cell21_voltage']['value']) if (BMS_STATUS['voltages']['cell22_voltage']['value'] >= MIN_CELL_VOLTAGE): cell_voltages.append(BMS_STATUS['voltages']['cell22_voltage']['value']) if (BMS_STATUS['voltages']['cell23_voltage']['value'] >= MIN_CELL_VOLTAGE): cell_voltages.append(BMS_STATUS['voltages']['cell23_voltage']['value']) if (BMS_STATUS['voltages']['cell24_voltage']['value'] >= MIN_CELL_VOLTAGE): cell_voltages.append(BMS_STATUS['voltages']['cell24_voltage']['value']) BMS_STATUS['voltages']['agg_voltages']['sum']['value'] = sum(cell_voltages) BMS_STATUS['voltages']['agg_voltages']['sum']['text'] = "{:.2f}".format(BMS_STATUS['voltages']['agg_voltages']['sum']['value']) + "V" BMS_STATUS['voltages']['agg_voltages']['max']['value'] = max(cell_voltages) BMS_STATUS['voltages']['agg_voltages']['max']['text'] = "{:.3f}".format(BMS_STATUS['voltages']['agg_voltages']['max']['value']) + "V" BMS_STATUS['voltages']['agg_voltages']['min']['value'] = min(cell_voltages) BMS_STATUS['voltages']['agg_voltages']['min']['text'] = "{:.3f}".format(BMS_STATUS['voltages']['agg_voltages']['min']['value']) + "V" BMS_STATUS['voltages']['agg_voltages']['diff']['value'] = BMS_STATUS['voltages']['agg_voltages']['max']['value'] - BMS_STATUS['voltages']['agg_voltages']['min']['value'] BMS_STATUS['voltages']['agg_voltages']['diff']['text'] = "{:.0f}".format(BMS_STATUS['voltages']['agg_voltages']['diff']['value'] * 1000) + "mV" if (packet_length == PACKET_LENGTH_STATUS_CELLS[0]): # packet from BMS8 # get battery capacity BMS_STATUS['voltages']['battery_capacity_wh']['value'] = get_battery_capacity((packet[20]), (packet[21]), (packet[22]), (packet[23])) BMS_STATUS['voltages']['battery_capacity_wh']['text'] = "{:.0f}".format(BMS_STATUS['voltages']['battery_capacity_wh']['value']) + "Wh" BMS_STATUS['voltages']['battery_capacity_ah']['value'] = get_battery_capacity((packet[24]), (packet[25]), (packet[26]), (packet[27])) BMS_STATUS['voltages']['battery_capacity_ah']['text'] = "{:.0f}".format(BMS_STATUS['voltages']['battery_capacity_ah']['value']) + "Ah" elif (packet_length == PACKET_LENGTH_STATUS_CELLS[1]): # packet from BMS16 # get battery capacity BMS_STATUS['voltages']['battery_capacity_wh']['value'] = get_battery_capacity((packet[36]), (packet[37]), (packet[38]), (packet[39])) BMS_STATUS['voltages']['battery_capacity_wh']['text'] = "{:.0f}".format(BMS_STATUS['voltages']['battery_capacity_wh']['value']) + "Wh" BMS_STATUS['voltages']['battery_capacity_ah']['value'] = get_battery_capacity((packet[40]), (packet[41]), (packet[42]), (packet[43])) BMS_STATUS['voltages']['battery_capacity_ah']['text'] = "{:.0f}".format(BMS_STATUS['voltages']['battery_capacity_ah']['value']) + "Ah" elif (packet_length == PACKET_LENGTH_STATUS_CELLS[2]): # packet from BMS24 # get battery capacity BMS_STATUS['voltages']['battery_capacity_wh']['value'] = get_battery_capacity((packet[52]), (packet[53]), (packet[54]), (packet[55])) BMS_STATUS['voltages']['battery_capacity_wh']['text'] = "{:.0f}".format(BMS_STATUS['voltages']['battery_capacity_wh']['value']) + "Wh" BMS_STATUS['voltages']['battery_capacity_ah']['value'] = get_battery_capacity((packet[56]), (packet[57]), (packet[58]), (packet[59])) BMS_STATUS['voltages']['battery_capacity_ah']['text'] = "{:.0f}".format(BMS_STATUS['voltages']['battery_capacity_ah']['value']) + "Ah" # update timestamp current_date = datetime.datetime.now() BMS_STATUS['voltages']['timestamp']['value'] = time.time() BMS_STATUS['voltages']['timestamp']['text'] = current_date.strftime('%a %d.%m.%Y %H:%M:%S') # print (BMS_STATUS) if (packet_length == PACKET_LENGTH_STATUS_CELLS[0]): # packet from BMS8 logging.info("BMS Voltages " + "[CAPACITYAH|" + BMS_STATUS['voltages']['battery_capacity_ah']['text'] + "][CAPACITYWH|" + BMS_STATUS['voltages']['battery_capacity_wh']['text'] + "][DIFF|" + BMS_STATUS['voltages']['agg_voltages']['diff']['text'] + "][SUM|" + BMS_STATUS['voltages']['agg_voltages']['sum']['text'] + "][#1|" + BMS_STATUS['voltages']['cell01_voltage']['text'] + "][#2|" + BMS_STATUS['voltages']['cell02_voltage']['text'] + "][#3|" + BMS_STATUS['voltages']['cell03_voltage']['text'] + "][#4|" + BMS_STATUS['voltages']['cell04_voltage']['text'] + "][#5|" + BMS_STATUS['voltages']['cell05_voltage']['text'] + "][#6|" + BMS_STATUS['voltages']['cell06_voltage']['text'] + "][#7|" + BMS_STATUS['voltages']['cell07_voltage']['text'] + "][#8|" + BMS_STATUS['voltages']['cell08_voltage']['text'] + "]") elif (packet_length == PACKET_LENGTH_STATUS_CELLS[1]): # packet from BMS16 logging.info("BMS Voltages " + "[CAPACITYAH|" + BMS_STATUS['voltages']['battery_capacity_ah']['text'] + "][CAPACITYWH|" + BMS_STATUS['voltages']['battery_capacity_wh']['text'] + "][DIFF|" + BMS_STATUS['voltages']['agg_voltages']['diff']['text'] + "][SUM|" + BMS_STATUS['voltages']['agg_voltages']['sum']['text'] + "][#1|" + BMS_STATUS['voltages']['cell01_voltage']['text'] + "][#2|" + BMS_STATUS['voltages']['cell02_voltage']['text'] + "][#3|" + BMS_STATUS['voltages']['cell03_voltage']['text'] + "][#4|" + BMS_STATUS['voltages']['cell04_voltage']['text'] + "][#5|" + BMS_STATUS['voltages']['cell05_voltage']['text'] + "][#6|" + BMS_STATUS['voltages']['cell06_voltage']['text'] + "][#7|" + BMS_STATUS['voltages']['cell07_voltage']['text'] + "][#8|" + BMS_STATUS['voltages']['cell08_voltage']['text'] + "][#9|" + BMS_STATUS['voltages']['cell09_voltage']['text'] + "][#10|" + BMS_STATUS['voltages']['cell10_voltage']['text'] + "][#11|" + BMS_STATUS['voltages']['cell11_voltage']['text'] + "][#12|" + BMS_STATUS['voltages']['cell12_voltage']['text'] + "][#13|" + BMS_STATUS['voltages']['cell13_voltage']['text'] + "][#14|" + BMS_STATUS['voltages']['cell14_voltage']['text'] + "][#15|" + BMS_STATUS['voltages']['cell15_voltage']['text'] + "][#16|" + BMS_STATUS['voltages']['cell16_voltage']['text'] + "]") elif (packet_length == PACKET_LENGTH_STATUS_CELLS[2]): # packet from BMS24 logging.info("BMS Voltages " + "[CAPACITYAH|" + BMS_STATUS['voltages']['battery_capacity_ah']['text'] + "][CAPACITYWH|" + BMS_STATUS['voltages']['battery_capacity_wh']['text'] + "][DIFF|" + BMS_STATUS['voltages']['agg_voltages']['diff']['text'] + "][SUM|" + BMS_STATUS['voltages']['agg_voltages']['sum']['text'] + "][#1|" + BMS_STATUS['voltages']['cell01_voltage']['text'] + "][#2|" + BMS_STATUS['voltages']['cell02_voltage']['text'] + "][#3|" + BMS_STATUS['voltages']['cell03_voltage']['text'] + "][#4|" + BMS_STATUS['voltages']['cell04_voltage']['text'] + "][#5|" + BMS_STATUS['voltages']['cell05_voltage']['text'] + "][#6|" + BMS_STATUS['voltages']['cell06_voltage']['text'] + "][#7|" + BMS_STATUS['voltages']['cell07_voltage']['text'] + "][#8|" + BMS_STATUS['voltages']['cell08_voltage']['text'] + "][#9|" + BMS_STATUS['voltages']['cell09_voltage']['text'] + "][#10|" + BMS_STATUS['voltages']['cell10_voltage']['text'] + "][#11|" + BMS_STATUS['voltages']['cell11_voltage']['text'] + "][#12|" + BMS_STATUS['voltages']['cell12_voltage']['text'] + "][#13|" + BMS_STATUS['voltages']['cell13_voltage']['text'] + "][#14|" + BMS_STATUS['voltages']['cell14_voltage']['text'] + "][#15|" + BMS_STATUS['voltages']['cell15_voltage']['text'] + "][#16|" + BMS_STATUS['voltages']['cell16_voltage']['text'] + "][#17|" + BMS_STATUS['voltages']['cell17_voltage']['text'] + "][#18|" + BMS_STATUS['voltages']['cell18_voltage']['text'] + "][#19|" + BMS_STATUS['voltages']['cell19_voltage']['text'] + "][#20|" + BMS_STATUS['voltages']['cell20_voltage']['text'] + "][#21|" + BMS_STATUS['voltages']['cell21_voltage']['text'] + "][#22|" + BMS_STATUS['voltages']['cell22_voltage']['text'] + "][#23|" + BMS_STATUS['voltages']['cell23_voltage']['text'] + "][#24|" + BMS_STATUS['voltages']['cell24_voltage']['text'] + "]") else: logging.debug("Packet Checksum wrong, skip packet") # strip packet packet = packet[packet_length:] elif ((packet[2]) == PACKET_STATUS_IMPEDANCES): if (len(packet) < PACKET_LENGTH_STATUS_IMPEDANCES): logging.debug("Packet Impedances Cells too short, skip") packet = "" else: # delete old data reset_impedances_values() cell_count = (packet_length - 8) // 2; logging.debug("Packet Impedances, detected cells: #" + str(cell_count)) # checksum value checksum = (packet[packet_length-1]) checksum_check = 0 # calculate checksum for i in range(packet_length-1): checksum_check = checksum_check + (packet[i]) checksum_check = checksum_check % 256 logging.debug("Packet Checksum BMS: " + str(checksum) + "|" + str(checksum_check)) # data integrity does match if (checksum == checksum_check): # Chargery protocol manual: # Current 1 (A), It is instant current when measure cell impedance BMS_STATUS['impedances']['current1']['value'] = get_current1_value((packet[5]), (packet[6])) # Chargery protocol manual: # Current mode 1 means battery is in charging or discharging when cell impedance is measured bms_current_mode1 = (packet[4]) if (bms_current_mode1 == 0x00): BMS_STATUS['impedances']['current_mode1']['value'] = 0 BMS_STATUS['impedances']['current_mode1']['text'] = "Discharge" BMS_STATUS['impedances']['current1']['text'] = "-" + str(BMS_STATUS['impedances']['current1']['value']) + "A" elif (bms_current_mode1 == 0x01): BMS_STATUS['impedances']['current_mode1']['value'] = 1 BMS_STATUS['impedances']['current_mode1']['text'] = "Charge" BMS_STATUS['impedances']['current1']['text'] = str(BMS_STATUS['impedances']['current1']['value']) + "A" else: BMS_STATUS['impedances']['current_mode1']['value'] = -1 BMS_STATUS['impedances']['current_mode1']['text'] = "" BMS_STATUS['impedances']['current1']['text'] = "" for i in range(1, cell_count+1): BMS_STATUS['impedances']['cell'+"{:02d}".format(i)+'_impedance']['value'] = get_cell_impedance((packet[7+(2*(i-1))]), (packet[8+(2*(i-1))])) BMS_STATUS['impedances']['cell'+"{:02d}".format(i)+'_impedance']['text'] = "{:.1f}".format(BMS_STATUS['impedances']['cell'+"{:02d}".format(i)+'_impedance']['value']) + "m" + SPECIAL_DISPLAY_SYMBOLS['ohm'] # get min/max impedances to calculate the diff cell_impedances = [] if (BMS_STATUS['impedances']['cell01_impedance']['value'] >= MIN_CELL_IMPEDANCE): cell_impedances.append(BMS_STATUS['impedances']['cell01_impedance']['value']) if (BMS_STATUS['impedances']['cell02_impedance']['value'] >= MIN_CELL_IMPEDANCE): cell_impedances.append(BMS_STATUS['impedances']['cell02_impedance']['value']) if (BMS_STATUS['impedances']['cell03_impedance']['value'] >= MIN_CELL_IMPEDANCE): cell_impedances.append(BMS_STATUS['impedances']['cell03_impedance']['value']) if (BMS_STATUS['impedances']['cell04_impedance']['value'] >= MIN_CELL_IMPEDANCE): cell_impedances.append(BMS_STATUS['impedances']['cell04_impedance']['value']) if (BMS_STATUS['impedances']['cell05_impedance']['value'] >= MIN_CELL_IMPEDANCE): cell_impedances.append(BMS_STATUS['impedances']['cell05_impedance']['value']) if (BMS_STATUS['impedances']['cell06_impedance']['value'] >= MIN_CELL_IMPEDANCE): cell_impedances.append(BMS_STATUS['impedances']['cell06_impedance']['value']) if (BMS_STATUS['impedances']['cell07_impedance']['value'] >= MIN_CELL_IMPEDANCE): cell_impedances.append(BMS_STATUS['impedances']['cell07_impedance']['value']) if (BMS_STATUS['impedances']['cell08_impedance']['value'] >= MIN_CELL_IMPEDANCE): cell_impedances.append(BMS_STATUS['impedances']['cell08_impedance']['value']) if (BMS_STATUS['impedances']['cell09_impedance']['value'] >= MIN_CELL_IMPEDANCE): cell_impedances.append(BMS_STATUS['impedances']['cell09_impedance']['value']) if (BMS_STATUS['impedances']['cell10_impedance']['value'] >= MIN_CELL_IMPEDANCE): cell_impedances.append(BMS_STATUS['impedances']['cell10_impedance']['value']) if (BMS_STATUS['impedances']['cell11_impedance']['value'] >= MIN_CELL_IMPEDANCE): cell_impedances.append(BMS_STATUS['impedances']['cell11_impedance']['value']) if (BMS_STATUS['impedances']['cell12_impedance']['value'] >= MIN_CELL_IMPEDANCE): cell_impedances.append(BMS_STATUS['impedances']['cell12_impedance']['value']) if (BMS_STATUS['impedances']['cell13_impedance']['value'] >= MIN_CELL_IMPEDANCE): cell_impedances.append(BMS_STATUS['impedances']['cell13_impedance']['value']) if (BMS_STATUS['impedances']['cell14_impedance']['value'] >= MIN_CELL_IMPEDANCE): cell_impedances.append(BMS_STATUS['impedances']['cell14_impedance']['value']) if (BMS_STATUS['impedances']['cell15_impedance']['value'] >= MIN_CELL_IMPEDANCE): cell_impedances.append(BMS_STATUS['impedances']['cell15_impedance']['value']) if (BMS_STATUS['impedances']['cell16_impedance']['value'] >= MIN_CELL_IMPEDANCE): cell_impedances.append(BMS_STATUS['impedances']['cell16_impedance']['value']) if (BMS_STATUS['impedances']['cell17_impedance']['value'] >= MIN_CELL_IMPEDANCE): cell_impedances.append(BMS_STATUS['impedances']['cell17_impedance']['value']) if (BMS_STATUS['impedances']['cell18_impedance']['value'] >= MIN_CELL_IMPEDANCE): cell_impedances.append(BMS_STATUS['impedances']['cell18_impedance']['value']) if (BMS_STATUS['impedances']['cell19_impedance']['value'] >= MIN_CELL_IMPEDANCE): cell_impedances.append(BMS_STATUS['impedances']['cell19_impedance']['value']) if (BMS_STATUS['impedances']['cell20_impedance']['value'] >= MIN_CELL_IMPEDANCE): cell_impedances.append(BMS_STATUS['impedances']['cell20_impedance']['value']) if (BMS_STATUS['impedances']['cell21_impedance']['value'] >= MIN_CELL_IMPEDANCE): cell_impedances.append(BMS_STATUS['impedances']['cell21_impedance']['value']) if (BMS_STATUS['impedances']['cell22_impedance']['value'] >= MIN_CELL_IMPEDANCE): cell_impedances.append(BMS_STATUS['impedances']['cell22_impedance']['value']) if (BMS_STATUS['impedances']['cell23_impedance']['value'] >= MIN_CELL_IMPEDANCE): cell_impedances.append(BMS_STATUS['impedances']['cell23_impedance']['value']) if (BMS_STATUS['impedances']['cell24_impedance']['value'] >= MIN_CELL_IMPEDANCE): cell_impedances.append(BMS_STATUS['impedances']['cell24_impedance']['value']) BMS_STATUS['impedances']['agg_impedances']['sum']['value'] = sum(cell_impedances) BMS_STATUS['impedances']['agg_impedances']['sum']['text'] = "{:.1f}".format(BMS_STATUS['impedances']['agg_impedances']['sum']['value']) + "m" + SPECIAL_DISPLAY_SYMBOLS['ohm'] BMS_STATUS['impedances']['agg_impedances']['max']['value'] = max(cell_impedances) BMS_STATUS['impedances']['agg_impedances']['max']['text'] = "{:.1f}".format(BMS_STATUS['impedances']['agg_impedances']['max']['value']) + "m" + SPECIAL_DISPLAY_SYMBOLS['ohm'] BMS_STATUS['impedances']['agg_impedances']['min']['value'] = min(cell_impedances) BMS_STATUS['impedances']['agg_impedances']['min']['text'] = "{:.1f}".format(BMS_STATUS['impedances']['agg_impedances']['min']['value']) + "m" + SPECIAL_DISPLAY_SYMBOLS['ohm'] BMS_STATUS['impedances']['agg_impedances']['diff']['value'] = BMS_STATUS['impedances']['agg_impedances']['max']['value'] - BMS_STATUS['impedances']['agg_impedances']['min']['value'] BMS_STATUS['impedances']['agg_impedances']['diff']['text'] = "{:.1f}".format(BMS_STATUS['impedances']['agg_impedances']['diff']['value']) + "m" + SPECIAL_DISPLAY_SYMBOLS['ohm'] # update timestamp current_date = datetime.datetime.now() BMS_STATUS['impedances']['timestamp']['value'] = time.time() BMS_STATUS['impedances']['timestamp']['text'] = current_date.strftime('%a %d.%m.%Y %H:%M:%S') logging.info("BMS Impedances " + "][MODE1|" + BMS_STATUS['impedances']['current_mode1']['text'] + "][CURRENT1|" + BMS_STATUS['impedances']['current1']['text'] + "][SUM|" + BMS_STATUS['impedances']['agg_impedances']['sum']['text'] + "][#1|" + BMS_STATUS['impedances']['cell01_impedance']['text'] + "][#2|" + BMS_STATUS['impedances']['cell02_impedance']['text'] + "][#3|" + BMS_STATUS['impedances']['cell03_impedance']['text'] + "][#4|" + BMS_STATUS['impedances']['cell04_impedance']['text'] + "][#5|" + BMS_STATUS['impedances']['cell05_impedance']['text'] + "][#6|" + BMS_STATUS['impedances']['cell06_impedance']['text'] + "][#7|" + BMS_STATUS['impedances']['cell07_impedance']['text'] + "][#8|" + BMS_STATUS['impedances']['cell08_impedance']['text'] + "][#9|" + BMS_STATUS['impedances']['cell09_impedance']['text'] + "][#10|" + BMS_STATUS['impedances']['cell10_impedance']['text'] + "][#11|" + BMS_STATUS['impedances']['cell11_impedance']['text'] + "][#12|" + BMS_STATUS['impedances']['cell12_impedance']['text'] + "][#13|" + BMS_STATUS['impedances']['cell13_impedance']['text'] + "][#14|" + BMS_STATUS['impedances']['cell14_impedance']['text'] + "][#15|" + BMS_STATUS['impedances']['cell15_impedance']['text'] + "][#16|" + BMS_STATUS['impedances']['cell16_impedance']['text'] + "][#17|" + BMS_STATUS['impedances']['cell17_impedance']['text'] + "][#18|" + BMS_STATUS['impedances']['cell18_impedance']['text'] + "][#19|" + BMS_STATUS['impedances']['cell19_impedance']['text'] + "][#20|" + BMS_STATUS['impedances']['cell20_impedance']['text'] + "][#21|" + BMS_STATUS['impedances']['cell21_impedance']['text'] + "][#22|" + BMS_STATUS['impedances']['cell22_impedance']['text'] + "][#23|" + BMS_STATUS['impedances']['cell23_impedance']['text'] + "][#24|" + BMS_STATUS['impedances']['cell24_impedance']['text'] + "]") else: logging.debug("Packet Checksum wrong, skip packet") # strip packet packet = packet[packet_length:] else: # debug_packet(packet) logging.debug("Packet Unknown [1]") packet = "" else: logging.debug("Packet Unknown [2]") packet = "" else: logging.debug("Packet too short, skip") packet = "" def handle_serial_data(test_packet = ''): try: if (len(test_packet) > 0): # for testing the example packets form the chargery manual parse_packet(test_packet) else: serial_packet = "" if (serial_port.in_waiting > 0): logging.debug("Data Waiting [" + str(serial_port.in_waiting) + " bytes]") if (serial_port.in_waiting >= (PACKET_LENGTH_MINIMUM * 2)): data_buffer_array = serial_port.read(serial_port.in_waiting) logging.debug("Data Received [" + str(len(data_buffer_array)) + " bytes]") if (len(data_buffer_array) > 0): parse_packet(bytearray(data_buffer_array)) data_buffer_array = "" except KeyboardInterrupt: pass if args.test: print("\n".join(dfs_bms_status(print_status_header, BMS_STATUS))) for item in BMS_TEST_PACKETS.items(): handle_serial_data((item[1])) print(str(dfs_bms_status(print_status_value, BMS_STATUS)).strip('[]')) else: if args.output is not None: output_file = open(args.output) print(",".join(dfs_bms_status(print_status_header, BMS_STATUS)), file=output_file) while True: handle_serial_data() print(str(dfs_bms_status(print_status_value, BMS_STATUS)).strip('[]'), file=output_file) time.sleep(1) else: while True: handle_serial_data() time.sleep(1)