Innovenergy_trunk/firmware/opt/dbus-fz-sonick-48tl-with-s3/signals.py

375 lines
22 KiB
Python

# coding=utf-8
import config as cfg
from convert import mean, read_float, read_led_state, read_bool, count_bits, comma_separated, read_bitmap, return_in_list, first, read_hex_string
from data import BatterySignal, Battery, LedColor, ServiceSignal, BatteryStatus, LedState, CsvSignal
# noinspection PyUnreachableCode
if False:
from typing import List, Iterable
def read_voltage():
return read_float(register=999, scale_factor=0.01, offset=0)
def read_current():
return read_float(register=1000, scale_factor=0.01, offset=-10000)
def read_limb_bitmap():
return read_bitmap(1059)
def read_power(status):
return int(read_current()(status) * read_voltage()(status))
def interpret_limb_bitmap(bitmap_value):
string1_disabled = int((bitmap_value & 0b00001) != 0)
string2_disabled = int((bitmap_value & 0b00010) != 0)
string3_disabled = int((bitmap_value & 0b00100) != 0)
string4_disabled = int((bitmap_value & 0b01000) != 0)
string5_disabled = int((bitmap_value & 0b10000) != 0)
n_limb_strings = string1_disabled + string2_disabled + string3_disabled + string4_disabled + string5_disabled
return n_limb_strings
def limp_strings_value(status):
return interpret_limb_bitmap(read_limb_bitmap()(status))
def calc_power_limit_imposed_by_voltage_limit(v, i, v_limit, r_int):
dv = v_limit - v
di = dv / r_int
p_limit = v_limit * (i + di)
return p_limit
def calc_power_limit_imposed_by_current_limit(v, i, i_limit, r_int):
di = i_limit - i
dv = di * r_int
p_limit = i_limit * (v + dv)
return p_limit
def calc_max_charge_power(status):
n_strings = cfg.NUM_OF_STRINGS_PER_BATTERY - limp_strings_value(status)
i_max = n_strings * cfg.I_MAX_PER_STRING
v_max = cfg.V_MAX
r_int_min = cfg.R_STRING_MIN / n_strings
r_int_max = cfg.R_STRING_MAX / n_strings
v = read_voltage()(status)
i = read_current()(status)
p_limits = [
calc_power_limit_imposed_by_voltage_limit(v, i, v_max, r_int_min),
calc_power_limit_imposed_by_voltage_limit(v, i, v_max, r_int_max),
calc_power_limit_imposed_by_current_limit(v, i, i_max, r_int_min),
calc_power_limit_imposed_by_current_limit(v, i, i_max, r_int_max),
]
p_limit = min(p_limits)
p_limit = max(p_limit, 0)
return int(p_limit)
def calc_max_discharge_power(status):
n_strings = cfg.NUM_OF_STRINGS_PER_BATTERY - limp_strings_value(status)
max_discharge_current = n_strings * cfg.I_MAX_PER_STRING
return int(max_discharge_current * read_voltage()(status))
def read_switch_closed(status):
value = read_bool(base_register=1013, bit=0)(status)
if value:
return False
return True
def read_alarm_out_active(status):
value = read_bool(base_register=1013, bit=1)(status)
if value:
return False
return True
def read_aux_relay(status):
value = read_bool(base_register=1013, bit=4)(status)
if value:
return False
return True
def hex_string_to_ascii(hex_string):
hex_string = hex_string.replace(" ", "")
ascii_string = ''.join([chr(int(hex_string[i:i+2], 16)) for i in range(0, len(hex_string), 2)])
return ascii_string
def init_service_signals(batteries):
print("INSIDE INIT SERVICE SIGNALS")
n_batteries = len(batteries)
product_name = cfg.PRODUCT_NAME + ' x' + str(n_batteries)
return [
ServiceSignal('/NbOfBatteries', n_batteries),
ServiceSignal('/Mgmt/ProcessName', __file__),
ServiceSignal('/Mgmt/ProcessVersion', cfg.SOFTWARE_VERSION),
ServiceSignal('/Mgmt/Connection', cfg.CONNECTION),
ServiceSignal('/DeviceInstance', cfg.DEVICE_INSTANCE),
ServiceSignal('/ProductName', product_name),
ServiceSignal('/ProductId', cfg.PRODUCT_ID),
ServiceSignal('/Connected', 1)
]
def init_battery_signals():
print("START INIT SIGNALS")
battery_status_reader = read_hex_string(1060, 2)
def read_eoc_reached(status):
battery_status_string = battery_status_reader(status)
return hex_string_to_ascii(battery_status_string) == "EOC_"
def read_battery_cold(status):
return \
read_led_state(register=1004, led=LedColor.green)(status) >= LedState.blinking_slow and \
read_led_state(register=1004, led=LedColor.blue)(status) >= LedState.blinking_slow
def read_soc(status):
soc = read_float(register=1053, scale_factor=0.1, offset=0)(status)
if soc > 99.9 and not read_eoc_reached(status):
return 99.9
if soc >= 99.9 and read_eoc_reached(status):
return 100
return soc
def number_of_active_strings(status):
return cfg.NUM_OF_STRINGS_PER_BATTERY - limp_strings_value(status)
def max_discharge_current(status):
return number_of_active_strings(status) * cfg.I_MAX_PER_STRING
def max_charge_current(status):
return status.battery.ampere_hours / 2
return [
BatterySignal('/TimeToTOCRequest', max, read_float(register=1052)),
BatterySignal('/EOCReached', return_in_list, read_eoc_reached),
BatterySignal('/NumOfLimbStrings', return_in_list, limp_strings_value),
BatterySignal('/Dc/0/Voltage', mean, get_value=read_voltage(), unit='V'),
BatterySignal('/Dc/0/Current', sum, get_value=read_current(), unit='A'),
BatterySignal('/Dc/0/Power', sum, get_value=read_power, unit='W'),
BatterySignal('/BussVoltage', mean, read_float(register=1001, scale_factor=0.01, offset=0), unit='V'),
BatterySignal('/Soc', mean, read_soc, unit='%'),
BatterySignal('/LowestSoc', min, read_float(register=1053, scale_factor=0.1, offset=0), unit='%'),
BatterySignal('/Dc/0/Temperature', mean, read_float(register=1003, scale_factor=0.1, offset=-400), unit='C'),
BatterySignal('/Dc/0/LowestTemperature', min, read_float(register=1003, scale_factor=0.1, offset=-400), unit='C'),
BatterySignal('/WarningFlags/TaM1', return_in_list, read_bool(base_register=1005, bit=1)),
BatterySignal('/WarningFlags/TbM1', return_in_list, read_bool(base_register=1005, bit=4)),
BatterySignal('/WarningFlags/VBm1', return_in_list, read_bool(base_register=1005, bit=6)),
BatterySignal('/WarningFlags/VBM1', return_in_list, read_bool(base_register=1005, bit=8)),
BatterySignal('/WarningFlags/IDM1', return_in_list, read_bool(base_register=1005, bit=10)),
BatterySignal('/WarningFlags/vsm1', return_in_list, read_bool(base_register=1005, bit=22)),
BatterySignal('/WarningFlags/vsM1', return_in_list, read_bool(base_register=1005, bit=24)),
BatterySignal('/WarningFlags/iCM1', return_in_list, read_bool(base_register=1005, bit=26)),
BatterySignal('/WarningFlags/iDM1', return_in_list, read_bool(base_register=1005, bit=28)),
BatterySignal('/WarningFlags/MID1', return_in_list, read_bool(base_register=1005, bit=30)),
BatterySignal('/WarningFlags/BLPW', return_in_list, read_bool(base_register=1005, bit=32)),
BatterySignal('/WarningFlags/CCBF', return_in_list, read_bool(base_register=1005, bit=33)),
BatterySignal('/WarningFlags/Ah_W', return_in_list, read_bool(base_register=1005, bit=35)),
BatterySignal('/WarningFlags/MPMM', return_in_list, read_bool(base_register=1005, bit=38)),
BatterySignal('/WarningFlags/TCdi', return_in_list, read_bool(base_register=1005, bit=40)),
BatterySignal('/WarningFlags/LMPW', return_in_list, read_bool(base_register=1005, bit=44)),
BatterySignal('/WarningFlags/TOCW', return_in_list, read_bool(base_register=1005, bit=47)),
BatterySignal('/WarningFlags/BUSL', return_in_list, read_bool(base_register=1005, bit=49)),
BatterySignal('/AlarmFlags/Tam', return_in_list, read_bool(base_register=1005, bit=0)),
BatterySignal('/AlarmFlags/TaM2', return_in_list, read_bool(base_register=1005, bit=2)),
BatterySignal('/AlarmFlags/Tbm', return_in_list, read_bool(base_register=1005, bit=3)),
BatterySignal('/AlarmFlags/TbM2', return_in_list, read_bool(base_register=1005, bit=5)),
BatterySignal('/AlarmFlags/VBm2', return_in_list, read_bool(base_register=1005, bit=7)),
BatterySignal('/AlarmFlags/VBM2', return_in_list, read_bool(base_register=1005, bit=9)),
BatterySignal('/AlarmFlags/IDM2', return_in_list, read_bool(base_register=1005, bit=11)),
BatterySignal('/AlarmFlags/ISOB', return_in_list, read_bool(base_register=1005, bit=12)),
BatterySignal('/AlarmFlags/MSWE', return_in_list, read_bool(base_register=1005, bit=13)),
BatterySignal('/AlarmFlags/FUSE', return_in_list, read_bool(base_register=1005, bit=14)),
BatterySignal('/AlarmFlags/HTRE', return_in_list, read_bool(base_register=1005, bit=15)),
BatterySignal('/AlarmFlags/TCPE', return_in_list, read_bool(base_register=1005, bit=16)),
BatterySignal('/AlarmFlags/STRE', return_in_list, read_bool(base_register=1005, bit=17)),
BatterySignal('/AlarmFlags/CME', return_in_list, read_bool(base_register=1005, bit=18)),
BatterySignal('/AlarmFlags/HWFL', return_in_list, read_bool(base_register=1005, bit=19)),
BatterySignal('/AlarmFlags/HWEM', return_in_list, read_bool(base_register=1005, bit=20)),
BatterySignal('/AlarmFlags/ThM', return_in_list, read_bool(base_register=1005, bit=21)),
BatterySignal('/AlarmFlags/vsm2', return_in_list, read_bool(base_register=1005, bit=23)),
BatterySignal('/AlarmFlags/vsM2', return_in_list, read_bool(base_register=1005, bit=25)),
BatterySignal('/AlarmFlags/iCM2', return_in_list, read_bool(base_register=1005, bit=27)),
BatterySignal('/AlarmFlags/iDM2', return_in_list, read_bool(base_register=1005, bit=29)),
BatterySignal('/AlarmFlags/MID2', return_in_list, read_bool(base_register=1005, bit=31)),
BatterySignal('/AlarmFlags/HTFS', return_in_list, read_bool(base_register=1005, bit=42)),
BatterySignal('/AlarmFlags/DATA', return_in_list, read_bool(base_register=1005, bit=43)),
BatterySignal('/AlarmFlags/LMPA', return_in_list, read_bool(base_register=1005, bit=45)),
BatterySignal('/AlarmFlags/HEBT', return_in_list, read_bool(base_register=1005, bit=46)),
BatterySignal('/AlarmFlags/CURM', return_in_list, read_bool(base_register=1005, bit=48)),
BatterySignal('/Diagnostics/LedStatus/Red', first, read_led_state(register=1004, led=LedColor.red)),
BatterySignal('/Diagnostics/LedStatus/Blue', first, read_led_state(register=1004, led=LedColor.blue)),
BatterySignal('/Diagnostics/LedStatus/Green', first, read_led_state(register=1004, led=LedColor.green)),
BatterySignal('/Diagnostics/LedStatus/Amber', first, read_led_state(register=1004, led=LedColor.amber)),
BatterySignal('/Diagnostics/IoStatus/MainSwitchClosed', return_in_list, read_switch_closed),
BatterySignal('/Diagnostics/IoStatus/AlarmOutActive', return_in_list, read_alarm_out_active),
BatterySignal('/Diagnostics/IoStatus/InternalFanActive', return_in_list, read_bool(base_register=1013, bit=2)),
BatterySignal('/Diagnostics/IoStatus/VoltMeasurementAllowed', return_in_list, read_bool(base_register=1013, bit=3)),
BatterySignal('/Diagnostics/IoStatus/AuxRelay', return_in_list, read_aux_relay),
BatterySignal('/Diagnostics/IoStatus/RemoteState', return_in_list, read_bool(base_register=1013, bit=5)),
BatterySignal('/Diagnostics/IoStatus/RiscOn', return_in_list, read_bool(base_register=1013, bit=6)),
BatterySignal('/IoStatus/BatteryCold', any, read_battery_cold),
BatterySignal('/Info/MaxDischargeCurrent', sum, max_discharge_current, unit='A'),
BatterySignal('/Info/MaxChargeCurrent', sum, max_charge_current, unit='A'),
BatterySignal('/Info/MaxChargeVoltage', min, lambda bs: bs.battery.v_max, unit='V'),
BatterySignal('/Info/MinDischargeVoltage', max, lambda bs: bs.battery.v_min, unit='V'),
BatterySignal('/Info/BatteryLowVoltage', max, lambda bs: bs.battery.v_min - 2, unit='V'),
BatterySignal('/Info/NumberOfStrings', sum, number_of_active_strings),
BatterySignal('/Info/MaxChargePower', sum, calc_max_charge_power),
BatterySignal('/Info/MaxDischargePower', sum, calc_max_discharge_power),
BatterySignal('/FirmwareVersion', comma_separated, lambda bs: bs.battery.firmware_version),
BatterySignal('/HardwareVersion', comma_separated, lambda bs: bs.battery.hardware_version),
BatterySignal('/BmsVersion', comma_separated, lambda bs: bs.battery.bms_version)
]
def create_csv_signals(firmware_version):
total_current = read_float(register=1062, scale_factor=0.01, offset=-10000)
def read_total_current(status):
return total_current(status)
def read_heating_current(status):
return total_current(status) - read_current()(status)
def read_heating_power(status):
return read_voltage()(status) * read_heating_current(status)
soc_ah = read_float(register=1002, scale_factor=0.1, offset=-10000)
def read_soc_ah(status):
return soc_ah(status)
def return_led_state(status, color):
led_state = read_led_state(register=1004, led=color)(status)
if led_state == LedState.blinking_fast or led_state == LedState.blinking_slow:
return "Blinking"
elif led_state == LedState.on:
return "On"
elif led_state == LedState.off:
return "Off"
return "Unknown"
def return_led_state_blue(status):
return return_led_state(status, LedColor.blue)
def return_led_state_red(status):
return return_led_state(status, LedColor.red)
def return_led_state_green(status):
return return_led_state(status, LedColor.green)
def return_led_state_amber(status):
return return_led_state(status, LedColor.amber)
battery_status_reader = read_hex_string(1060, 2)
def read_eoc_reached(status):
battery_status_string = battery_status_reader(status)
return hex_string_to_ascii(battery_status_string) == "EOC_"
def read_serial_number(status):
serial_regs = [1055, 1056, 1057, 1058]
serial_parts = []
for reg in serial_regs:
hex_value_fun = read_hex_string(reg, 1)
hex_value = hex_value_fun(status)
serial_parts.append(hex_value.replace(' ', ''))
serial_number = ''.join(serial_parts).rstrip('0')
return serial_number
def time_since_toc_in_time_format(status):
time_in_minutes = read_float(register=1052)(status)
total_seconds = int(time_in_minutes * 60)
days = total_seconds // (24 * 3600)
total_seconds = total_seconds % (24 * 3600)
hours = total_seconds // 3600
total_seconds %= 3600
minutes = total_seconds // 60
seconds = total_seconds % 60
return "{}.{:02}:{:02}:{:02}".format(days, hours, minutes, seconds)
return [
CsvSignal('/Battery/Devices/FwVersion', firmware_version),
CsvSignal('/Battery/Devices/Dc/Power', read_power, 'W'),
CsvSignal('/Battery/Devices/Dc/Voltage', read_voltage(), 'V'),
CsvSignal('/Battery/Devices/Soc', read_float(register=1053, scale_factor=0.1, offset=0), '%'),
CsvSignal('/Battery/Devices/Temperatures/Cells/Average', read_float(register=1003, scale_factor=0.1, offset=-400), 'C'),
CsvSignal('/Battery/Devices/Dc/Current', read_current(), 'A'),
CsvSignal('/Battery/Devices/BusCurrent', read_total_current, 'A'),
CsvSignal('/Battery/Devices/CellsCurrent', read_current(), 'A'),
CsvSignal('/Battery/Devices/HeatingCurrent', read_heating_current, 'A'),
CsvSignal('/Battery/Devices/HeatingPower', read_heating_power, 'W'),
CsvSignal('/Battery/Devices/SOCAh', read_soc_ah),
CsvSignal('/Battery/Devices/Leds/Blue', return_led_state_blue),
CsvSignal('/Battery/Devices/Leds/Red', return_led_state_red),
CsvSignal('/Battery/Devices/Leds/Green', return_led_state_green),
CsvSignal('/Battery/Devices/Leds/Amber', return_led_state_amber),
CsvSignal('/Battery/Devices/BatteryStrings/String1Active', lambda status: int((read_limb_bitmap()(status) & 0b00001) != 0)),
CsvSignal('/Battery/Devices/BatteryStrings/String2Active', lambda status: int((read_limb_bitmap()(status) & 0b00010) != 0)),
CsvSignal('/Battery/Devices/BatteryStrings/String3Active', lambda status: int((read_limb_bitmap()(status) & 0b00100) != 0)),
CsvSignal('/Battery/Devices/BatteryStrings/String4Active', lambda status: int((read_limb_bitmap()(status) & 0b01000) != 0)),
CsvSignal('/Battery/Devices/BatteryStrings/String5Active', lambda status: int((read_limb_bitmap()(status) & 0b10000) != 0)),
CsvSignal('/Battery/Devices/IoStatus/ConnectedToDcBus', read_switch_closed),
CsvSignal('/Battery/Devices/IoStatus/AlarmOutActive', read_alarm_out_active),
CsvSignal('/Battery/Devices/IoStatus/InternalFanActive', read_bool(base_register=1013, bit=2)),
CsvSignal('/Battery/Devices/IoStatus/VoltMeasurementAllowed', read_bool(base_register=1013, bit=3)),
CsvSignal('/Battery/Devices/IoStatus/AuxRelayBus', read_aux_relay),
CsvSignal('/Battery/Devices/IoStatus/RemoteStateActive', read_bool(base_register=1013, bit=5)),
CsvSignal('/Battery/Devices/IoStatus/RiscActive', read_bool(base_register=1013, bit=6)),
CsvSignal('/Battery/Devices/Eoc', read_eoc_reached),
CsvSignal('/Battery/Devices/SerialNumber', read_serial_number),
CsvSignal('/Battery/Devices/TimeSinceTOC', time_since_toc_in_time_format),
CsvSignal('/Battery/Devices/MaxChargePower', calc_max_charge_power),
CsvSignal('/Battery/Devices/MaxDischargePower', calc_max_discharge_power),
]
def read_warning_and_alarm_flags():
return [
# Warnings
CsvSignal('/Battery/Devices/WarningFlags/TaM1', read_bool(base_register=1005, bit=1)),
CsvSignal('/Battery/Devices/WarningFlags/TbM1', read_bool(base_register=1005, bit=4)),
CsvSignal('/Battery/Devices/WarningFlags/VBm1', read_bool(base_register=1005, bit=6)),
CsvSignal('/Battery/Devices/WarningFlags/VBM1', read_bool(base_register=1005, bit=8)),
CsvSignal('/Battery/Devices/WarningFlags/IDM1', read_bool(base_register=1005, bit=10)),
CsvSignal('/Battery/Devices/WarningFlags/vsm1', read_bool(base_register=1005, bit=22)),
CsvSignal('/Battery/Devices/WarningFlags/vsM1', read_bool(base_register=1005, bit=24)),
CsvSignal('/Battery/Devices/WarningFlags/iCM1', read_bool(base_register=1005, bit=26)),
CsvSignal('/Battery/Devices/WarningFlags/iDM1', read_bool(base_register=1005, bit=28)),
CsvSignal('/Battery/Devices/WarningFlags/MID1', read_bool(base_register=1005, bit=30)),
CsvSignal('/Battery/Devices/WarningFlags/BLPW', read_bool(base_register=1005, bit=32)),
CsvSignal('/Battery/Devices/WarningFlags/CCBF', read_bool(base_register=1005, bit=33)),
CsvSignal('/Battery/Devices/WarningFlags/Ah_W', read_bool(base_register=1005, bit=35)),
CsvSignal('/Battery/Devices/WarningFlags/MPMM', read_bool(base_register=1005, bit=38)),
CsvSignal('/Battery/Devices/WarningFlags/TCdi', read_bool(base_register=1005, bit=40)),
CsvSignal('/Battery/Devices/WarningFlags/LMPW', read_bool(base_register=1005, bit=44)),
CsvSignal('/Battery/Devices/WarningFlags/TOCW', read_bool(base_register=1005, bit=47)),
CsvSignal('/Battery/Devices/WarningFlags/BUSL', read_bool(base_register=1005, bit=49)),
], [
# Alarms
CsvSignal('/Battery/Devices/AlarmFlags/Tam', read_bool(base_register=1005, bit=0)),
CsvSignal('/Battery/Devices/AlarmFlags/TaM2', read_bool(base_register=1005, bit=2)),
CsvSignal('/Battery/Devices/AlarmFlags/Tbm', read_bool(base_register=1005, bit=3)),
CsvSignal('/Battery/Devices/AlarmFlags/TbM2', read_bool(base_register=1005, bit=5)),
CsvSignal('/Battery/Devices/AlarmFlags/VBm2', read_bool(base_register=1005, bit=7)),
CsvSignal('/Battery/Devices/AlarmFlags/VBM2', read_bool(base_register=1005, bit=9)),
CsvSignal('/Battery/Devices/AlarmFlags/IDM2', read_bool(base_register=1005, bit=11)),
CsvSignal('/Battery/Devices/AlarmFlags/ISOB', read_bool(base_register=1005, bit=12)),
CsvSignal('/Battery/Devices/AlarmFlags/MSWE', read_bool(base_register=1005, bit=13)),
CsvSignal('/Battery/Devices/AlarmFlags/FUSE', read_bool(base_register=1005, bit=14)),
CsvSignal('/Battery/Devices/AlarmFlags/HTRE', read_bool(base_register=1005, bit=15)),
CsvSignal('/Battery/Devices/AlarmFlags/TCPE', read_bool(base_register=1005, bit=16)),
CsvSignal('/Battery/Devices/AlarmFlags/STRE', read_bool(base_register=1005, bit=17)),
CsvSignal('/Battery/Devices/AlarmFlags/CME', read_bool(base_register=1005, bit=18)),
CsvSignal('/Battery/Devices/AlarmFlags/HWFL', read_bool(base_register=1005, bit=19)),
CsvSignal('/Battery/Devices/AlarmFlags/HWEM', read_bool(base_register=1005, bit=20)),
CsvSignal('/Battery/Devices/AlarmFlags/ThM', read_bool(base_register=1005, bit=21)),
CsvSignal('/Battery/Devices/AlarmFlags/vsm2', read_bool(base_register=1005, bit=23)),
CsvSignal('/Battery/Devices/AlarmFlags/vsM2', read_bool(base_register=1005, bit=25)),
CsvSignal('/Battery/Devices/AlarmFlags/iCM2', read_bool(base_register=1005, bit=27)),
CsvSignal('/Battery/Devices/AlarmFlags/iDM2', read_bool(base_register=1005, bit=29)),
CsvSignal('/Battery/Devices/AlarmFlags/MID2', read_bool(base_register=1005, bit=31)),
CsvSignal('/Battery/Devices/AlarmFlags/HTFS', read_bool(base_register=1005, bit=42)),
CsvSignal('/Battery/Devices/AlarmFlags/DATA', read_bool(base_register=1005, bit=43)),
CsvSignal('/Battery/Devices/AlarmFlags/LMPA', read_bool(base_register=1005, bit=45)),
CsvSignal('/Battery/Devices/AlarmFlags/HEBT', read_bool(base_register=1005, bit=46)),
CsvSignal('/Battery/Devices/AlarmFlags/CURM', read_bool(base_register=1005, bit=48)),
]