"""MPPT HEX Protocol specification.""" from dataclasses import dataclass import enum from . import schema from .hex import Register, Field import pint _ureg = pint.get_application_registry() class ID(enum.IntEnum): # Product information registers # 0x0100,Product Id,-,un32,- PRODUCT_ID = 0x0100 # 0x0104,Group Id,-,un8,- GROUP_ID = 0x0104 # 0x010A,Serial number,-,string,- SERIAL_NUMBER = 0x010A # 0x010B,Model name,-,string,- MODEL_NAME = 0x010B # 0x0140,Capabilities,-,un32,- CAPABILITIES = 0x0140 # Generic device control registers # 0x0200,Device mode,-,un8,- DEVICE_MODE = 0x0200 # 0x0201,Device state,-,un8,- DEVICE_STATE = 0x0201 # 0x0202,Remote control used,-,un32,- REMOTE_CONTROL_USED = 0x0202 # 0x0205,Device off reason,-,un8,- DEVICE_OFF_REASON = 0x0205 # 0x0207,Device off reason,-,un32,- DEVICE_OFF_REASON_EXTENDED = 0x0207 # Battery settings registers # 0xEDFF,Batterysafe mode,-,un8,0=off, 1=on BATTERYSAFE_MODE = 0xEDFF # 0xEDFE,Adaptive mode,-,un8,0=off, 1=on ADAPTIVE_MODE = 0xEDFE # 0xEDFD,Automatic equalisation mode,-,un8,0=off, 1..250 AUTOMATIC_EQUALISATION_MODE = 0xEDFD # 0xEDFC,Battery bulk time limit,0.01,un16,hours BATTERY_BULK_TIME_LIMIT = 0xEDFC # 0xEDFB,Battery absorption time limit,0.01,un16,hours BATTERY_ABSORPTION_TIME_LIMIT = 0xEDFB # 0xEDF7,Battery absorption voltage,0.01,un16,V BATTERY_ABSORPTION_VOLTAGE = 0xEDF7 # 0xEDF6,Battery float voltage,0.01,un16,V BATTERY_FLOAT_VOLTAGE = 0xEDF6 # 0xEDF4,Battery equalisation voltage,0.01,un16,V BATTERY_EQUALISATION_VOLTAGE = 0xEDF4 # 0xEDF2,Battery temp. compensation,0.01,sn16,mV/K BATTERY_TEMP_COMPENSATION = 0xEDF2 # 0XEDF1,BATTERY TYPE,1,UN8,0XFF = user BATTERY_TYPE = 0xEDF1 # 0xEDF0,Battery maximum current,0.1,un16,A BATTERY_MAXIMUM_CURRENT = 0xEDF0 # 0xEDEF,Battery voltage,1,un8,V BATTERY_VOLTAGE = 0xEDEF # 0xEDEA,Battery voltage setting,1,un8,V BATTERY_VOLTAGE_SETTING = 0xEDEA # 0xEDE8,BMS present,-,un8,0=no, 1=yes BMS_PRESENT = 0xEDE8 # 0xEDE7,Tail current,0.1,un16, TAIL_CURRENT = 0xEDE7 # 0xEDE6,Low temperature charge current,0.1,un16,A, 0xFFFF=use max LOW_TEMPERATURE_CHARGE_CURRENT = 0xEDE6 # 0xEDE5,Auto equalise stop on voltage,-,un8,0=no, 1=yes AUTO_EQUALISE_STOP_ON_VOLTAGE = 0xEDE5 # 0xEDE4,Equalisation current level,1,un8,% (of 0xEDF0) EQUALISATION_CURRENT_LEVEL = 0xEDE4 # 0xEDE3,Equalisation duration,0.01,un16,hours EQUALISATION_DURATION = 0xEDE3 # 0xED2E,Re-bulk voltage offset,0.01,un16,V RE_BULK_VOLTAGE_OFFSET = 0xED2E # 0xEDE0,Battery low temperature level,0.01,sn16,°C BATTERY_LOW_TEMPERATURE_LEVEL = 0xEDE0 # 0xEDCA,Voltage compensation,0.01,un16,V VOLTAGE_COMPENSATION = 0xEDCA # Charger data registers # 0xEDEC,Battery temperature,0.01,un16,K BATTERY_TEMPERATURE = 0xEDEC # 0xEDDF,Charger maximum current,0.01,un16,A CHARGER_MAXIMUM_CURRENT = 0xEDDF # 0xEDDD,System yield,0.01,un32,kWh SYSTEM_YIELD = 0xEDDD # 0xEDDC,User yield (*2),0.01,un32,kWh USER_YIELD = 0xEDDC # 0xEDDB,Charger internal temperature,0.01,sn16,°C CHARGER_INTERNAL_TEMPERATURE = 0xEDDB # 0xEDDA,Charger error code,-,un8,- CHARGER_ERROR_CODE = 0xEDDA # 0xEDD7,Charger current,0.1,un16,A CHARGER_CURRENT = 0xEDD7 # 0xEDD5,Charger voltage,0.01,un16,V CHARGER_VOLTAGE = 0xEDD5 # 0xEDD4,Additional charger state info,-,un8,- ADDITIONAL_CHARGER_STATE_INFO = 0xEDD4 # 0xEDD3,Yield today,0.01,(*4),kWh YIELD_TODAY = 0xEDD3 # 0xEDD2,Maximum power today,1,un16,W MAXIMUM_POWER_TODAY = 0xEDD2 # 0xEDD1,Yield yesterday,0.01,(*4),kWh YIELD_YESTERDAY = 0xEDD1 # 0xEDD0,Maximum power yesterday,1,un16,W MAXIMUM_POWER_YESTERDAY = 0xEDD0 # 0xEDCE,Voltage settings range,-,un16,- VOLTAGE_SETTINGS_RANGE = 0xEDCE # 0xEDCD,History version,-,un8,- HISTORY_VERSION = 0xEDCD # 0xEDCC,Streetlight version,-,un8,- STREETLIGHT_VERSION = 0xEDCC # 0x2211,Adjustable voltage minimum,0.01,un16,V ADJUSTABLE_VOLTAGE_MINIMUM = 0x2211 # 0x2212 Adjustable voltage maximum 0.01 un16 V ADJUSTABLE_VOLTAGE_MAXIMUM = 0x2212 # Solar panel data registers # 0xEDBC,Panel power,0.01,un32,W PANEL_POWER = 0xEDBC # 0xEDBB,Panel voltage,0.01,un16,V PANEL_VOLTAGE = 0xEDBB # 0xEDBD,Panel current,0.1,un16,A PANEL_CURRENT = 0xEDBD # 0xEDB8,Panel maximum voltage,0.01,un16,V PANEL_MAXIMUM_VOLTAGE = 0xEDB8 # 0xEDB3,Tracker mode,-,un8,- TRACKER_MODE = 0xEDB3 # Load output data/settings registers # 0xEDAD,Load current,0.1,un16,A LOAD_CURRENT = 0xEDAD # 0xEDAC,Load offset voltage,0.01,un16,V LOAD_OFFSET_VOLTAGE = 0xEDAC # 0xEDAB,Load output control,-,un8,- LOAD_OUTPUT_CONTROL = 0xEDAB # 0xEDA9,Load output voltage,0.01,un16,V LOAD_OUTPUT_VOLTAGE = 0xEDA9 # 0xEDA8,Load output state,-,un8,- LOAD_OUTPUT_STATE = 0xEDA8 # 0xED9D,Load switch high level,0.01,un16,V LOAD_SWITCH_HIGH_LEVEL = 0xED9D # 0xED9C,Load switch low level,0.01,un16,V LOAD_SWITCH_LOW_LEVEL = 0xED9C # 0xED91,Load output off reason,-,un8,- LOAD_OUTPUT_OFF_REASON = 0xED91 # 0xED90,Load AES timer,1,un16,minute LOAD_AES_TIMER = 0xED90 # Relay settings registers # 0xEDD9,Relay operation mode,-,un8,- RELAY_OPERATION_MODE = 0xEDD9 # 0x0350,Relay battery low voltage set,0.01,un16,V RELAY_BATTERY_LOW_VOLTAGE_SET = 0x0350 # 0x0351,Relay battery low voltage clear,0.01,un16,V RELAY_BATTERY_LOW_VOLTAGE_CLEAR = 0x0351 # 0x0352,Relay battery high voltage set,0.01,un16,V RELAY_BATTERY_HIGH_VOLTAGE_SET = 0x0352 # 0x0353,Relay battery high voltage clear,0.01,un16,V RELAY_BATTERY_HIGH_VOLTAGE_CLEAR = 0x0353 # 0xEDBA,Relay panel high voltage set,0.01,un16,V RELAY_PANEL_HIGH_VOLTAGE_SET = 0xEDBA # 0xEDB9,Relay panel high voltage clear,0.01,un16,V RELAY_PANEL_HIGH_VOLTAGE_CLEAR = 0xEDB9 # 0x100A Relay minimum enabled time 1 un16 minute RELAY_MINIMUM_ENABLED_TIME = 0x100A # Lighting controller timer # Timer events 0..5,-,un32,- TIMER_EVENT_0 = 0xEDA0 # 0xEDA7,Mid-point shift,1,sn16,min MID_POINT_SHIFT = 0xEDA7 # 0xED9B,Gradual dim speed,1,un8,s GRADUAL_DIM_SPEED = 0xED9B # 0xED9A,Panel voltage night,0.01,un16,V PANEL_VOLTAGE_NIGHT = 0xED9A # 0xED99,Panel voltage day,0.01,un16,V PANEL_VOLTAGE_DAY = 0xED99 # 0xED96,Sunset delay,1,un16,min SUNSET_DELAY = 0xED96 # 0xED97,Sunrise delay,1,un16,min SUNRISE_DELAY = 0xED97 # 0xED90,AES Timer,1,un16,min AES_TIMER = 0xED90 # 0x2030,Solar activity,-,un8,0=dark, 1=light SOLAR_ACTIVITY = 0x2030 # 0x2031 Time-of-day 1 un16 min, 0=mid-night TIME_OF_DAY = 0x2031 # VE.Direct port functions # 0xED9E,TX Port operation mode,-,un8,- TX_PORT_OPERATION_MODE = 0xED9E # 0xED98 RX Port operation mode - un8 - RX_PORT_OPERATION_MODE = 0xED98 # Restore factory defaults # 0x0004,Restore default RESTORE_DEFAULT = 0x0004 # History data # 0x1030,Clear history CLEAR_HISTORY = 0x1030 # 0x104F,Total history TOTAL_HISTORY = 0x104F # Items HISTORY_0 = 0x1050 # Pluggable display settings # 0x0400,Display backlight mode,,,un8 DISPLAY_BACKLIGHT_MODE = 0x0400 # 0x0401,Display backlight intensity,,un8, DISPLAY_BACKLIGHT_INTENSITY = 0x0401 # 0x0402,Display scroll text speed,,un8, DISPLAY_SCROLL_TEXT_SPEED = 0x0402 # 0x0403,Display setup lock (*2),,,un8 DISPLAY_SETUP_LOCK = 0x0403 # 0x0404,Display temperature unit (*2),,,un8 DISPLAY_TEMPERATURE_UNIT = 0x0404 # Remote control registers # 0x2000,Charge algorithm version,-,un8,- CHARGE_ALGORITHM_VERSION = 0x2000 # 0x2001,Charge voltage set-point,0.01,un16,V CHARGE_VOLTAGE_SET_POINT = 0x2001 # 0x2002,Battery voltage sense,0.01,un16,V BATTERY_VOLTAGE_SENSE = 0x2002 # 0x2003,Battery temperature sense,0.01,sn16,°C BATTERY_TEMPERATURE_SENSE = 0x2003 # 0x2004,Remote command,-,un8,- REMOTE_COMMAND = 0x2004 # 0x2007,Charge state elapsed time,1,un32,ms CHARGE_STATE_ELAPSED_TIME = 0x2007 # 0x2008,Absorption time,0.01,un16,hours ABSORPTION_TIME = 0x2008 # 0x2009,Error code,-,un8,- ERROR_CODE = 0x2009 # 0x200A,Battery charge current,0.001,sn32,A BATTERY_CHARGE_CURRENT = 0x200A # 0x200B,Battery idle voltage,0.01,un16,V BATTERY_IDLE_VOLTAGE = 0x200B # 0x200C,Device state,-,un8,- REMOTE_DEVICE_STATE = 0x200C # 0x200D,Network info,-,un8,- NETWORK_INFO = 0x200D # 0x200E,Network mode,-,un8,- NETWORK_MODE = 0x200E # 0x200F,Network status register,-,un8,- NETWORK_STATUS_REGISTER = 0x200F # 0x2013,Total charge current,0.001,sn32,A TOTAL_CHARGE_CURRENT = 0x2013 # 0x2014,Charge current percentage,1,un8,% CHARGE_CURRENT_PERCENTAGE = 0x2014 # 0x2015,Charge current limit,0.1,un16,A CHARGE_CURRENT_LIMIT = 0x2015 # 0x2018,Manual equalisation pending,-,un8,- MANUAL_EQUALISATION_PENDING = 0x2018 # 0x2027,Total DC input power,0.01,un32,W TOTAL_DC_INPUT_POWER = 0x2027 # Product information registers PRODUCT_ID = Register(0x0100, 'Product ID', 'xHx') GROUP_ID = Register(0x0104, 'Group ID', 'B') SERIAL_NUMBER = Register(0x010A, 'Serial number', 'S') MODEL_NAME = Register(0x010B, 'Model name', 'S') CAPABILITIES = Register(0x0140, 'Capabilities', 'I', None, None, schema.Capabilities) # Generic device control registers DEVICE_MODE = Register(0x0200, 'Device mode', 'B') DEVICE_STATE = Register(0x0201, 'Device state', 'B', None, None, schema.State) REMOTE_CONTROL_USED = Register(0x0202, 'Remote control used', 'I') DEVICE_OFF_REASON = Register(0x0205, 'Device off reason', 'B') DEVICE_OFF_REASON_EXTENDED = Register(0x0207, 'Device off reason', 'I') # Battery settings registers BATTERYSAFE_MODE = Register(0xEDFF, '') ADAPTIVE_MODE = Register(0xEDFE, 'Adaptive mode', 'B', None, None, bool) AUTOMATIC_EQUALISATION_MODE = Register(0xEDFD, 'Automatic equalisation mode', 'B') BATTERY_BULK_TIME_LIMIT = Register(0xEDFC, 'Battery bulk time limit', 'H', None, 0.01, _ureg.hour) BATTERY_ABSORPTION_TIME_LIMIT = Register(0xEDFB, 'Battery absorption time limit', 'H', None, 0.01, _ureg.hour) BATTERY_ABSORPTION_VOLTAGE = Register(0xEDF7, 'Battery absorption voltage', 'H', None, 0.01, _ureg.volt) BATTERY_FLOAT_VOLTAGE = Register(0xEDF6, 'Battery float voltage', 'H', None, 0.01, _ureg.volt) BATTERY_EQUALISATION_VOLTAGE = Register(0xEDF4, 'Battery equalisation voltage', 'H', None, 0.01, _ureg.volt) BATTERY_TEMP_COMPENSATION = Register(0xEDF2, 'Battery temp. compensation', 'h', None, 0.01, 'mV/K') BATTERY_TYPE = Register(0XEDF1, 'Battery type', 'B') BATTERY_MAXIMUM_CURRENT = Register(0xEDF0, 'Battery maximum current', 'H', None, 0.1, _ureg.ampere) BATTERY_VOLTAGE = Register(0xEDEF, 'Battery voltage', 'B', None, None, _ureg.volt) BATTERY_VOLTAGE_SETTING = Register(0xEDEA, 'Battery voltage setting', 'B', None, None, _ureg.volt) BMS_PRESENT = Register(0xEDE8, 'BMS present', 'B', None, 1, bool) TAIL_CURRENT = Register(0xEDE7, 'Tail current', 'H', None, 0.1, '') LOW_TEMPERATURE_CHARGE_CURRENT = Register(0xEDE6, 'Low temperature charge current', 'H', None, 0.1, _ureg.ampere) AUTO_EQUALISE_STOP_ON_VOLTAGE = Register(0xEDE5, 'Auto equalise stop on voltage', 'B', None, 1, bool) EQUALISATION_CURRENT_LEVEL = Register(0xEDE4, 'Equalisation current level', 'B') EQUALISATION_DURATION = Register(0xEDE3, 'Equalisation duration', 'H', None, 0.01, _ureg.hour) RE_BULK_VOLTAGE_OFFSET = Register(0xED2E, 'Re-bulk voltage offset', 'H', None, 0.01, _ureg.volt) BATTERY_LOW_TEMPERATURE_LEVEL = Register(0xEDE0, 'Battery low temperature level', 'h', None, 0.01, _ureg.degC) VOLTAGE_COMPENSATION = Register(0xEDCA, 'Voltage compensation', 'H', None, 0.01, _ureg.volt) # Charger data registers BATTERY_TEMPERATURE = Register(0xEDEC, 'Battery temperature', 'H', None, 0.01, _ureg.kelvin) CHARGER_MAXIMUM_CURRENT = Register(0xEDDF, 'Charger maximum current', 'H', None, 0.01, _ureg.ampere) SYSTEM_YIELD = Register(0xEDDD, 'System yield', 'I', None, 10, _ureg.watt_hour) USER_YIELD = Register(0xEDDC, 'User yield', 'I', None, 10, _ureg.watt_hour) CHARGER_INTERNAL_TEMPERATURE = Register(0xEDDB, 'Charger internal temperature', 'h', None, 0.01, _ureg.degC) CHARGER_ERROR_CODE = Register(0xEDDA, 'Charger error code', 'B', None, None, schema.Err) CHARGER_CURRENT = Register(0xEDD7, 'Charger current', 'H', None, 0.1, _ureg.ampere) CHARGER_VOLTAGE = Register(0xEDD5, 'Charger voltage', 'H', None, 0.01, _ureg.volt) ADDITIONAL_CHARGER_STATE_INFO = Register(0xEDD4, 'Additional charger state info', 'B', None, None, schema.AdditionalChargerState) YIELD_TODAY = Register(0xEDD3, 'Yield today', 'H', None, 10, _ureg.watt_hour) MAXIMUM_POWER_TODAY = Register(0xEDD2, 'Maximum power today', 'H', None, 1, _ureg.watt) YIELD_YESTERDAY = Register(0xEDD1, 'Yield yesterday', 'H', None, 10, _ureg.watt_hour) MAXIMUM_POWER_YESTERDAY = Register(0xEDD0, 'Maximum power yesterday', 'H', None, 1, _ureg.watt) VOLTAGE_SETTINGS_RANGE = Register( 0xEDCE, 'Voltage settings range', 'H', None, ) HISTORY_VERSION = Register(0xEDCD, 'History version', 'B') STREETLIGHT_VERSION = Register(0xEDCC, 'Streetlight version', 'B') ADJUSTABLE_VOLTAGE_MINIMUM = Register(0x2211, 'Adjustable voltage minimum', 'H', None, 0.01, _ureg.volt) ADJUSTABLE_VOLTAGE_MAXIMUM = Register(0x2212, 'Adjustable voltage maximum', 'H', None, 0.01, _ureg.volt) # Solar panel data registers PANEL_POWER = Register(0xEDBC, 'Panel power', 'I', None, 0.01, _ureg.watt) PANEL_VOLTAGE = Register(0xEDBB, 'Panel voltage', 'H', None, 0.01, _ureg.volt) PANEL_CURRENT = Register(0xEDBD, 'Panel current', 'H', None, 0.1, _ureg.ampere) PANEL_MAXIMUM_VOLTAGE = Register(0xEDB8, 'Panel maximum voltage', 'H', None, 0.01, _ureg.volt) TRACKER_MODE = Register(0xEDB3, 'Tracker mode', 'B', None, None, schema.TrackerMode) # Load output data/settings registers LOAD_CURRENT = Register(0xEDAD, 'Load current', 'H', None, 0.1, _ureg.ampere) # TODO: spec says H. LOAD_OFFSET_VOLTAGE = Register(0xEDAC, 'Load offset voltage', 'B', None, 0.01, _ureg.volt) LOAD_OUTPUT_CONTROL = Register(0xEDAB, 'Load output control', 'B', None, None, schema.LoadOutputControl) LOAD_OUTPUT_VOLTAGE = Register(0xEDA9, 'Load output voltage', 'H', None, 0.01, _ureg.volt) LOAD_OUTPUT_STATE = Register(0xEDA8, 'Load output state', 'B') LOAD_SWITCH_HIGH_LEVEL = Register(0xED9D, 'Load switch high level', 'H', None, 0.01, _ureg.volt) LOAD_SWITCH_LOW_LEVEL = Register(0xED9C, 'Load switch low level', 'H', None, 0.01, _ureg.volt) LOAD_OUTPUT_OFF_REASON = Register(0xED91, 'Load output off reason', 'B', None, None, schema.OffReason) LOAD_AES_TIMER = Register(0xED90, 'Load AES timer', 'H', None, 1, _ureg.minute) # Relay settings registers RELAY_OPERATION_MODE = Register(0xEDD9, 'Relay operation mode', 'B', None, None, schema.RelayMode) RELAY_BATTERY_LOW_VOLTAGE_SET = Register(0x0350, 'Relay battery low voltage set', 'H', None, 0.01, _ureg.volt) RELAY_BATTERY_LOW_VOLTAGE_CLEAR = Register(0x0351, 'Relay battery low voltage clear', 'H', None, 0.01, _ureg.volt) RELAY_BATTERY_HIGH_VOLTAGE_SET = Register(0x0352, 'Relay battery high voltage set', 'H', None, 0.01, _ureg.volt) RELAY_BATTERY_HIGH_VOLTAGE_CLEAR = Register( 0x0353, 'Relay battery high voltage clear', 'H', None, 0.01, _ureg.volt) RELAY_PANEL_HIGH_VOLTAGE_SET = Register(0xEDBA, 'Relay panel high voltage set', 'H', None, 0.01, _ureg.volt) RELAY_PANEL_HIGH_VOLTAGE_CLEAR = Register(0xEDB9, 'Relay panel high voltage clear', 'H', None, 0.01, _ureg.volt) RELAY_MINIMUM_ENABLED_TIME = Register(0x100A, 'Relay minimum enabled time', 'H', None, 1, _ureg.minute) # Lighting controller timer # TIMER_EVENT_0 = Register(, 'Timer events None, 0..5,un32,-,-') MID_POINT_SHIFT = Register(0xEDA7, 'Mid-point shift', 'h', None, 60, _ureg.second) GRADUAL_DIM_SPEED = Register(0xED9B, 'Gradual dim speed', 'B', None, 1, _ureg.second) PANEL_VOLTAGE_NIGHT = Register(0xED9A, 'Panel voltage night', 'H', None, 0.01, _ureg.volt) PANEL_VOLTAGE_DAY = Register(0xED99, 'Panel voltage day', 'H', None, 0.01, _ureg.volt) SUNSET_DELAY = Register(0xED96, 'Sunset delay', 'H', None, 60, _ureg.second) SUNRISE_DELAY = Register(0xED97, 'Sunrise delay', 'H', None, 60, _ureg.second) AES_TIMER = Register(0xED90, 'AES Timer', 'H', None, 60, _ureg.second) SOLAR_ACTIVITY = Register(0x2030, 'Solar activity', 'B', None, 1, bool) TIME_OF_DAY = Register(0x2031, 'Time-of-day', 'H') # VE.Direct port functions TX_PORT_OPERATION_MODE = Register(0xED9E, 'TX Port operation mode', 'B', None, None, schema.TXPortMode) RX_PORT_OPERATION_MODE = Register(0xED98, 'RX Port operation mode', 'B', None, None, schema.RXPortMode) # Restore factory defaults RESTORE_DEFAULT = Register(0x0004, 'Restore default') # History data # CLEAR_HISTORY = Register(0x1030, 'Total history') # HISTORY_0 = Register(0, 'Clear history') # TOTAL_HISTORY = Register(0x104F, 'Items') # Pluggable display settings DISPLAY_BACKLIGHT_MODE = Register(0x0400, 'Display backlight mode,,,un8') DISPLAY_BACKLIGHT_INTENSITY = Register(0x0401, 'Display backlight intensity', 'B') DISPLAY_SCROLL_TEXT_SPEED = Register(0x0402, 'Display scroll text speed', 'B', None) DISPLAY_SETUP_LOCK = Register(0x0403, 'Display setup lock', 'B') DISPLAY_TEMPERATURE_UNIT = Register(0x0404, 'Display temperature unit', 'B', None) # Remote control registers CHARGE_ALGORITHM_VERSION = Register(0x2000, 'Charge algorithm version', 'B', None) CHARGE_VOLTAGE_SET_POINT = Register(0x2001, 'Charge voltage set-point', 'H', None, 0.01, _ureg.volt) BATTERY_VOLTAGE_SENSE = Register(0x2002, 'Battery voltage sense', 'H', None, 0.01, _ureg.volt) BATTERY_TEMPERATURE_SENSE = Register(0x2003, 'Battery temperature sense', 'h', None, 0.01, _ureg.degC) REMOTE_COMMAND = Register(0x2004, 'Remote command', 'B') CHARGE_STATE_ELAPSED_TIME = Register(0x2007, 'Charge state elapsed time', 'I', None, 1e-3, _ureg.second) ABSORPTION_TIME = Register(0x2008, 'Absorption time', 'H', None, 0.01, _ureg.hour) ERROR_CODE = Register(0x2009, 'Error code', 'B') BATTERY_CHARGE_CURRENT = Register(0x200A, 'Battery charge current', 'i', None, 0.001, _ureg.ampere) BATTERY_IDLE_VOLTAGE = Register(0x200B, 'Battery idle voltage', 'H', None, 0.01, _ureg.volt) REMOTE_DEVICE_STATE = Register(0x200C, 'Device state', 'B') NETWORK_INFO = Register(0x200D, 'Network info', 'B') NETWORK_MODE = Register(0x200E, 'Network mode', 'B') NETWORK_STATUS_REGISTER = Register(0x200F, 'Network status register', 'B', None) TOTAL_CHARGE_CURRENT = Register(0x2013, 'Total charge current', 'i', None, 0.001, _ureg.ampere) CHARGE_CURRENT_PERCENTAGE = Register(0x2014, 'Charge current percentage', 'B') CHARGE_CURRENT_LIMIT = Register(0x2015, 'Charge current limit', 'H', None, 0.1, _ureg.ampere) MANUAL_EQUALISATION_PENDING = Register(0x2018, 'Manual equalisation pending', 'B') TOTAL_DC_INPUT_POWER = Register(0x2027, 'Total DC input power', 'I', None, 0.01, _ureg.watt) REGISTERS = { ID(r.id): r for r in globals().values() if isinstance(r, Register) } for register in REGISTERS.values(): assert register.mode is None, register if register.scale is not None: assert isinstance(register.scale, (float, int)), register @dataclass class Information: product_id: int = Field(PRODUCT_ID) # group_id: float = Field(GROUP_ID) serial_number: str = Field(SERIAL_NUMBER) model_name: str = Field(MODEL_NAME) capabilities: schema.Capabilities = Field(CAPABILITIES) @dataclass class Generic: mode: int = Field(DEVICE_MODE) state: schema.State = Field(DEVICE_STATE) @dataclass class Settings: absorption_time_limit: float = Field(BATTERY_ABSORPTION_TIME_LIMIT) absorption_voltage: float = Field(BATTERY_ABSORPTION_VOLTAGE) float_voltage: float = Field(BATTERY_FLOAT_VOLTAGE) equalisation_voltage: float = Field(BATTERY_EQUALISATION_VOLTAGE) temp_compensation: float = Field(BATTERY_TEMP_COMPENSATION) type: int = Field(BATTERY_TYPE) maximum_current: float = Field(BATTERY_MAXIMUM_CURRENT) voltage: float = Field(BATTERY_VOLTAGE) voltage_setting: float = Field(BATTERY_VOLTAGE_SETTING) @dataclass class Charger: maximum_current: float = Field(CHARGER_MAXIMUM_CURRENT) system_yield: float = Field(SYSTEM_YIELD) user_yield: float = Field(USER_YIELD) internal_temperature: float = Field(CHARGER_INTERNAL_TEMPERATURE) error_code: schema.Err = Field(CHARGER_ERROR_CODE) current: float = Field(CHARGER_CURRENT) voltage: float = Field(CHARGER_VOLTAGE) additional_state_info: schema.AdditionalChargerState = Field( ADDITIONAL_CHARGER_STATE_INFO) yield_today: float = Field(YIELD_TODAY) maximum_power_today: float = Field(MAXIMUM_POWER_TODAY) yield_yesterday: float = Field(YIELD_YESTERDAY) maximum_power_yesterday: float = Field(MAXIMUM_POWER_YESTERDAY) @dataclass class Solar: power: float = Field(PANEL_POWER) voltage: float = Field(PANEL_VOLTAGE) maximum_voltage: float = Field(PANEL_MAXIMUM_VOLTAGE) tracker_mode: schema.TrackerMode = Field(TRACKER_MODE) @dataclass class Load: current: float = Field(LOAD_CURRENT) offset_voltage: float = Field(LOAD_OFFSET_VOLTAGE) output_control: float = Field(LOAD_OUTPUT_CONTROL) output_state: float = Field(LOAD_OUTPUT_STATE) switch_high_level: float = Field(LOAD_SWITCH_HIGH_LEVEL) mswitch_low_level: float = Field(LOAD_SWITCH_LOW_LEVEL) GROUPS = (Information, Generic, Settings, Charger, Solar, Load) PRODUCT_IDS = { 0x203: 'BMV-700', 0x204: 'BMV-702', 0x205: 'BMV-700H', 0x0300: 'BlueSolar MPPT 70|15', 0xA040: 'BlueSolar MPPT 75|50', 0xA041: 'BlueSolar MPPT 150|35', 0xA042: 'BlueSolar MPPT 75|15', 0xA043: 'BlueSolar MPPT 100|15', 0xA044: 'BlueSolar MPPT 100|30', 0xA045: 'BlueSolar MPPT 100|50', 0xA046: 'BlueSolar MPPT 150|70', 0xA047: 'BlueSolar MPPT 150|100', 0xA049: 'BlueSolar MPPT 100|50 rev2', 0xA04A: 'BlueSolar MPPT 100|30 rev2', 0xA04B: 'BlueSolar MPPT 150|35 rev2', 0xA04C: 'BlueSolar MPPT 75|10', 0xA04D: 'BlueSolar MPPT 150|45', 0xA04E: 'BlueSolar MPPT 150|60', 0xA04F: 'BlueSolar MPPT 150|85', 0xA050: 'SmartSolar MPPT 250|100', 0xA051: 'SmartSolar MPPT 150|100', 0xA052: 'SmartSolar MPPT 150|85', 0xA053: 'SmartSolar MPPT 75|15', 0xA054: 'SmartSolar MPPT 75|10', 0xA055: 'SmartSolar MPPT 100|15', 0xA056: 'SmartSolar MPPT 100|30', 0xA057: 'SmartSolar MPPT 100|50', 0xA058: 'SmartSolar MPPT 150|35', 0xA059: 'SmartSolar MPPT 150|100 rev2', 0xA05A: 'SmartSolar MPPT 150|85 rev2', 0xA05B: 'SmartSolar MPPT 250|70', 0xA05C: 'SmartSolar MPPT 250|85', 0xA05D: 'SmartSolar MPPT 250|60', 0xA05E: 'SmartSolar MPPT 250|45', 0xA05F: 'SmartSolar MPPT 100|20', 0xA060: 'SmartSolar MPPT 100|20 48V', 0xA061: 'SmartSolar MPPT 150|45', 0xA062: 'SmartSolar MPPT 150|60', 0xA063: 'SmartSolar MPPT 150|70', 0xA064: 'SmartSolar MPPT 250|85 rev2', 0xA065: 'SmartSolar MPPT 250|100 rev2', 0xA066: 'BlueSolar MPPT 100|20', 0xA067: 'BlueSolar MPPT 100|20 48V', 0xA068: 'SmartSolar MPPT 250|60 rev2', 0xA069: 'SmartSolar MPPT 250|70 rev2', 0xA06A: 'SmartSolar MPPT 150|45 rev2', 0xA06B: 'SmartSolar MPPT 150|60 rev2', 0xA06C: 'SmartSolar MPPT 150|70 rev2', 0xA06D: 'SmartSolar MPPT 150|85 rev3', 0xA06E: 'SmartSolar MPPT 150|100 rev3', 0xA06F: 'BlueSolar MPPT 150|45 rev2', 0xA070: 'BlueSolar MPPT 150|60 rev2', 0xA071: 'BlueSolar MPPT 150|70 rev2', 0xA102: 'SmartSolar MPPT VE.Can 150/70', 0xA103: 'SmartSolar MPPT VE.Can 150/45', 0xA104: 'SmartSolar MPPT VE.Can 150/60', 0xA105: 'SmartSolar MPPT VE.Can 150/85', 0xA106: 'SmartSolar MPPT VE.Can 150/100', 0xA107: 'SmartSolar MPPT VE.Can 250/45', 0xA108: 'SmartSolar MPPT VE.Can 250/60', 0xA109: 'SmartSolar MPPT VE.Can 250/70', 0xA10A: 'SmartSolar MPPT VE.Can 250/85', 0xA10B: 'SmartSolar MPPT VE.Can 250/100', 0xA10C: 'SmartSolar MPPT VE.Can 150/70 rev2', 0xA10D: 'SmartSolar MPPT VE.Can 150/85 rev2', 0xA10E: 'SmartSolar MPPT VE.Can 150/100 rev2', 0xA10F: 'BlueSolar MPPT VE.Can 150/100', 0xA112: 'BlueSolar MPPT VE.Can 250/70', 0xA113: 'BlueSolar MPPT VE.Can 250/100', 0xA114: 'SmartSolar MPPT VE.Can 250/70 rev2', 0xA115: 'SmartSolar MPPT VE.Can 250/100 rev2', 0xA116: 'SmartSolar MPPT VE.Can 250/85 rev2', 0xA201: 'Phoenix Inverter 12V 250VA 230V', 0xA202: 'Phoenix Inverter 24V 250VA 230V', 0xA204: 'Phoenix Inverter 48V 250VA 230V', 0xA211: 'Phoenix Inverter 12V 375VA 230V', 0xA212: 'Phoenix Inverter 24V 375VA 230V', 0xA214: 'Phoenix Inverter 48V 375VA 230V', 0xA221: 'Phoenix Inverter 12V 500VA 230V', 0xA222: 'Phoenix Inverter 24V 500VA 230V', 0xA224: 'Phoenix Inverter 48V 500VA 230V', 0xA231: 'Phoenix Inverter 12V 250VA 230V', 0xA232: 'Phoenix Inverter 24V 250VA 230V', 0xA234: 'Phoenix Inverter 48V 250VA 230V', 0xA239: 'Phoenix Inverter 12V 250VA 120V', 0xA23A: 'Phoenix Inverter 24V 250VA 120V', 0xA23C: 'Phoenix Inverter 48V 250VA 120V', 0xA241: 'Phoenix Inverter 12V 375VA 230V', 0xA242: 'Phoenix Inverter 24V 375VA 230V', 0xA244: 'Phoenix Inverter 48V 375VA 230V', 0xA249: 'Phoenix Inverter 12V 375VA 120V', 0xA24A: 'Phoenix Inverter 24V 375VA 120V', 0xA24C: 'Phoenix Inverter 48V 375VA 120V', 0xA251: 'Phoenix Inverter 12V 500VA 230V', 0xA252: 'Phoenix Inverter 24V 500VA 230V', 0xA254: 'Phoenix Inverter 48V 500VA 230V', 0xA259: 'Phoenix Inverter 12V 500VA 120V', 0xA25A: 'Phoenix Inverter 24V 500VA 120V', 0xA25C: 'Phoenix Inverter 48V 500VA 120V', 0xA261: 'Phoenix Inverter 12V 800VA 230V', 0xA262: 'Phoenix Inverter 24V 800VA 230V', 0xA264: 'Phoenix Inverter 48V 800VA 230V', 0xA269: 'Phoenix Inverter 12V 800VA 120V', 0xA26A: 'Phoenix Inverter 24V 800VA 120V', 0xA26C: 'Phoenix Inverter 48V 800VA 120V', 0xA271: 'Phoenix Inverter 12V 1200VA 230V', 0xA272: 'Phoenix Inverter 24V 1200VA 230V', 0xA274: 'Phoenix Inverter 48V 1200VA 230V', 0xA279: 'Phoenix Inverter 12V 1200VA 120V', 0xA27A: 'Phoenix Inverter 24V 1200VA 120V', 0xA27C: 'Phoenix Inverter 48V 1200VA 120V', 0xA281: 'Phoenix Inverter 12V 1600VA 230V', 0xA282: 'Phoenix Inverter 24V 1600VA 230V', 0xA284: 'Phoenix Inverter 48V 1600VA 230V', 0xA291: 'Phoenix Inverter 12V 2000VA 230V', 0xA292: 'Phoenix Inverter 24V 2000VA 230V', 0xA294: 'Phoenix Inverter 48V 2000VA 230V', 0xA2A1: 'Phoenix Inverter 12V 3000VA 230V', 0xA2A2: 'Phoenix Inverter 24V 3000VA 230V', 0xA2A4: 'Phoenix Inverter 48V 3000VA 230V', 0xA340: 'Phoenix Smart IP43 Charger 12|50 (1+1)', 0xA341: 'Phoenix Smart IP43 Charger 12|50 (3)', 0xA342: 'Phoenix Smart IP43 Charger 24|25 (1+1)', 0xA343: 'Phoenix Smart IP43 Charger 24|25 (3)', 0xA344: 'Phoenix Smart IP43 Charger 12|30 (1+1)', 0xA345: 'Phoenix Smart IP43 Charger 12|30 (3)', 0xA346: 'Phoenix Smart IP43 Charger 24|16 (1+1)', 0xA347: 'Phoenix Smart IP43 Charger 24|16 (3)', }