def update_byd(bydhvip: str, bydhvuser: str, bydhvpass: str): log.debug("Beginning update") response = requests.get('http://' + bydhvip + '/asp/RunData.asp', auth=(bydhvuser, bydhvpass)) response.raise_for_status() get_bat_value_store(1).set(BydParser.parse(response.text)) log.debug("Update completed successfully")
def update_using_cookie(address: str, cookie): aggregate = read_aggregate(address, cookie) get_bat_value_store(1).set( BatState(imported=aggregate["battery"]["energy_imported"], exported=aggregate["battery"]["energy_exported"], power=-aggregate["battery"]["instant_power"], soc=read_soc(address, cookie)))
def update_using_powerwall_client(client: PowerwallHttpClient): aggregate = client.get_json("/api/meters/aggregates") get_bat_value_store(1).set( BatState(imported=aggregate["battery"]["energy_imported"], exported=aggregate["battery"]["energy_exported"], power=-aggregate["battery"]["instant_power"], soc=client.get_json("/api/system_status/soe")["percentage"]))
def update_solaredge_battery(client: ModbusClient, slave_ids: Iterable[int]): all_socs = [client.read_holding_registers( 62852, ModbusDataType.FLOAT_32, wordorder=Endian.Little, unit=slave_id ) for slave_id in slave_ids] storage_powers = [ client.read_holding_registers( 62836, ModbusDataType.FLOAT_32, wordorder=Endian.Little, unit=slave_id ) for slave_id in slave_ids ] log.debug("Battery SoCs=%s, powers=%s", all_socs, storage_powers) get_bat_value_store(1).set(BatState(power=sum(storage_powers), soc=mean(all_socs)))
def update(bydhvip: str, bydhvuser: str, bydhvpass: str): '''BYD Speicher bieten zwei HTML-Seiten, auf denen Informationen abgegriffen werden können: /asp/Home.asp und /asp/RunData.asp. Aktuell (2022-03) ist die Leistungsangabe (Power) auf der RunData.asp auf ganze kW gerundet und somit für openWB nicht brauchbar. ''' log.debug("Beginning update") bat_info = ComponentInfo(None, "BYD", "bat") with SingleComponentUpdateContext(bat_info): # response = req.get_http_session().get('http://' + bydhvip + '/asp/RunData.asp', auth=(bydhvuser, bydhvpass)) response = req.get_http_session().get('http://' + bydhvip + '/asp/Home.asp', auth=(bydhvuser, bydhvpass)) get_bat_value_store(1).set(BydParser.parse(response.text)) log.debug("Update completed successfully")
def __init__(self, component_config: dict, tcp_client: modbus.ModbusClient) -> None: self.component_config = component_config self.__tcp_client = tcp_client self.__store = get_bat_value_store(component_config["id"]) self.component_info = ComponentInfo.from_component_config( component_config)
def __init__(self, device_id: int, component_config: Union[Dict, LgBatSetup]) -> None: self.__device_id = device_id self.component_config = dataclass_from_dict(LgBatSetup, component_config) self.__sim_count = simcount.SimCountFactory().get_sim_counter()() self.__simulation = {} self.__store = get_bat_value_store(self.component_config.id) self.component_info = ComponentInfo.from_component_config(self.component_config)
def __init__(self, device_id: int, component_config: dict) -> None: self.__device_id = device_id self.component_config = component_config self.__sim_count = simcount.SimCountFactory().get_sim_counter()() self.__simulation = {} self.__store = get_bat_value_store(component_config["id"]) self.component_info = ComponentInfo.from_component_config(component_config)
def __init__(self, component_config: Union[Dict, SmaSunnyIslandBatSetup], tcp_client: modbus.ModbusTcpClient_) -> None: self.component_config = dataclass_from_dict(SmaSunnyIslandBatSetup, component_config) self.__tcp_client = tcp_client self.__store = get_bat_value_store(self.component_config.id) self.component_info = ComponentInfo.from_component_config( self.component_config)
def update_e3dc_battery(addresses: Iterable[str], read_external: int, pv_other: bool): soc = 0 count = 0 battery_power = 0 # pv_external - > pv Leistung die als externe Produktion an e3dc angeschlossen ist # nur auslesen wenn als relevant parametrisiert (read_external = 1) , sonst doppelte Auslesung pv_external = 0 # pv -> pv Leistung die direkt an e3dc angeschlossen ist pv = 0 for address in addresses: log.debug("Battery Ip: %s, read_external %d pv_other %s", address, read_external, pv_other) count += 1 with ModbusClient(address, port=502) as client: # 40082 SoC soc += client.read_holding_registers(40082, ModbusDataType.INT_16, unit=1) # 40069 Speicherleistung battery_power += client.read_holding_registers(40069, ModbusDataType.INT_32, wordorder=Endian.Little, unit=1) # 40067 PV Leistung pv += (client.read_holding_registers(40067, ModbusDataType.INT_32, wordorder=Endian.Little, unit=1) * -1) if read_external == 1: # 40075 externe PV Leistung pv_external += client.read_holding_registers(40075, ModbusDataType.INT_32, wordorder=Endian.Little, unit=1) soc = soc / count log.debug("Battery soc %d battery_power %d pv %d pv_external %d count ip %d", soc, battery_power, pv, pv_external, count) counter_import, counter_export = SimCountFactory().get_sim_counter()().sim_count(battery_power, prefix="speicher") get_bat_value_store(1).set(BatState(power=battery_power, soc=soc, imported=counter_import, exported=counter_export)) # pv_other sagt aus, ob WR definiert ist, und dessen PV Leistung auch gilt # wenn 0 gilt nur PV und pv_external aus e3dc pv_total = pv + pv_external # Wenn wr1 nicht definiert ist, gilt nur die PV Leistung die hier im Modul ermittelt wurde # als gesamte PV Leistung für wr1 if not pv_other or pv_total != 0: # Wenn wr1 definiert ist, gilt die bestehende PV Leistung aus Wr1 und das was hier im Modul ermittelt wurde # als gesamte PV Leistung für wr1 if pv_other: try: pv_total = pv_total + files.pv[0].power.read() except: pass log.debug("wr update pv_other %s pv_total %d", pv_other, pv_total) _, counter_pv = SimCountFactory().get_sim_counter()().sim_count(pv_total, prefix="pv") get_inverter_value_store(1).set(InverterState(counter=counter_pv, power=pv_total))
def __init__(self, device_id: int, component_config: dict) -> None: self.__device_id = device_id self.component_config = component_config ip_address = component_config["configuration"]["ip_address"] self.__tcp_client = modbus.ModbusClient(ip_address, 502) self.__sim_count = simcount.SimCountFactory().get_sim_counter()() self.__simulation = {} self.__store = get_bat_value_store(component_config["id"]) self.component_info = ComponentInfo.from_component_config(component_config)
def __init__(self, modbus_id: int, component_config: Union[Dict, GoodWeBatSetup], tcp_client: modbus.ModbusTcpClient_) -> None: self.__modbus_id = modbus_id self.component_config = dataclass_from_dict(GoodWeBatSetup, component_config) self.__tcp_client = tcp_client self.__store = get_bat_value_store(self.component_config.id) self.component_info = ComponentInfo.from_component_config(self.component_config)
def __init__(self, device_id: int, component_config: dict, tcp_client: modbus.ModbusClient) -> None: self.component_config = component_config factory = kit_bat_version_factory( component_config["configuration"]["version"]) self.__client = factory(component_config["configuration"]["id"], tcp_client) self.__tcp_client = tcp_client self.__store = get_bat_value_store(component_config["id"]) self.component_info = ComponentInfo.from_component_config( component_config)
def __init__(self, device_id: int, component_config: Union[Dict, SolaredgeBatSetup], tcp_client: modbus.ModbusTcpClient_) -> None: self.__device_id = device_id self.component_config = dataclass_from_dict(SolaredgeBatSetup, component_config) self.__tcp_client = tcp_client self.__sim_count = simcount.SimCountFactory().get_sim_counter()() self.simulation = {} self.__store = get_bat_value_store(self.component_config.id) self.component_info = ComponentInfo.from_component_config(self.component_config)
def __init__( self, device_id: int, device_address: str, device_variant: int, component_config: Union[Dict, SonnenbatterieBatSetup]) -> None: self.__device_id = device_id self.__device_address = device_address self.__device_variant = device_variant self.component_config = dataclass_from_dict(SonnenbatterieBatSetup, component_config) self.__sim_count = simcount.SimCountFactory().get_sim_counter()() self.simulation = {} self.__store = get_bat_value_store(self.component_config.id) self.component_info = ComponentInfo.from_component_config( self.component_config)
def __init__(self, device_id: int, component_config: dict, tcp_client: modbus.ModbusClient) -> None: self.__device_id = device_id self.component_config = component_config factory = kit_bat_version_factory( component_config["configuration"]["version"]) self.__client = factory(component_config["configuration"]["id"], tcp_client) self.__tcp_client = tcp_client self.__sim_count = simcount.SimCountFactory().get_sim_counter()() self.simulation = {} self.__store = get_bat_value_store(component_config["id"]) self.component_info = ComponentInfo.from_component_config( component_config)
def __init__(self, component_config: dict, domain: str) -> None: self.__get_power = create_request_function( domain, component_config["configuration"]["power_path"]) self.__get_imported = create_request_function( domain, component_config["configuration"]["imported_path"]) self.__get_exported = create_request_function( domain, component_config["configuration"]["exported_path"]) self.__get_soc = create_request_function( domain, component_config["configuration"]["soc_path"]) self.component_config = component_config self.__store = get_bat_value_store(component_config["id"]) self.component_info = ComponentInfo.from_component_config( component_config)
def __init__(self, device_id: int, component_config: Union[Dict, BatKitFlexSetup], tcp_client: modbus.ModbusTcpClient_) -> None: self.__device_id = device_id self.component_config = dataclass_from_dict(BatKitFlexSetup, component_config) factory = kit_bat_version_factory( self.component_config.configuration.version) self.__client = factory(self.component_config.configuration.id, tcp_client) self.__tcp_client = tcp_client self.__sim_count = simcount.SimCountFactory().get_sim_counter()() self.simulation = {} self.__store = get_bat_value_store(self.component_config.id) self.component_info = ComponentInfo.from_component_config( self.component_config)
def __init__(self, device_id: int, component_config: Union[Dict, HttpBatSetup], url: str) -> None: self.__device_id = device_id self.component_config = dataclass_from_dict(HttpBatSetup, component_config) self.__sim_count = simcount.SimCountFactory().get_sim_counter()() self.simulation = {} self.__store = get_bat_value_store(self.component_config.id) self.component_info = ComponentInfo.from_component_config( self.component_config) self.__get_power = create_request_function( url, self.component_config.configuration.power_path) self.__get_imported = create_request_function( url, self.component_config.configuration.imported_path) self.__get_exported = create_request_function( url, self.component_config.configuration.exported_path) self.__get_soc = create_request_function( url, self.component_config.configuration.soc_path)
def read_legacy(component_type: str, ip_address: str, port: str, slave_id0: str, slave_id1: Optional[str] = None, slave_id2: Optional[str] = None, slave_id3: Optional[str] = None, batwrsame: Optional[int] = None, extprodakt: Optional[int] = None, zweiterspeicher: Optional[int] = None, subbat: Optional[int] = None, ip2address: Optional[str] = None, num: Optional[int] = None) -> None: def get_bat_state() -> Tuple[List, List]: def create_bat(modbus_id: int) -> bat.SolaredgeBat: component_config = SolaredgeBatSetup( id=num, configuration=SolaredgeBatConfiguration(modbus_id=modbus_id)) return bat.SolaredgeBat(dev.device_config.id, component_config, dev.client) bats = [create_bat(1)] if zweiterspeicher == 1: bats.append(create_bat(2)) soc_bat, power_bat = [], [] for battery in bats: state = battery.read_state() power_bat.append(state.power) soc_bat.append(state.soc) return power_bat, soc_bat def get_external_inverter_state(dev: Device, id: int) -> InverterState: component_config = SolaredgeExternalInverterSetup( id=num, configuration=SolaredgeExternalInverterConfiguration(modbus_id=id)) ext_inverter = external_inverter.SolaredgeExternalInverter( dev.device_config.id, component_config, dev.client) return ext_inverter.read_state() def create_inverter(modbus_id: int) -> inverter.SolaredgeInverter: component_config = SolaredgeInverterSetup( id=num, configuration=SolaredgeInverterConfiguration(modbus_id=modbus_id)) return inverter.SolaredgeInverter(dev.device_config.id, component_config, dev.client) log.debug("Solaredge IP: " + ip_address + ":" + str(port)) log.debug("Solaredge Slave-IDs: [" + str(slave_id0) + ", " + str(slave_id1) + ", " + str(slave_id2) + ", " + str(slave_id3) + "]") log.debug("Solaredge Bat-WR-gleiche IP: " + str(batwrsame) + ", Externer WR: " + str(extprodakt) + ", 2. Speicher: " + str(zweiterspeicher) + ", Speicherleistung subtrahieren: " + str(subbat) + " 2. IP: " + str(ip2address) + ", Num: " + str(num)) if port == "": parsed_url = parse_url(ip_address) ip_address = parsed_url.hostname if parsed_url.port: port = parsed_url.port else: port = 502 dev = Device( Solaredge(configuration=SolaredgeConfiguration(ip_address=ip_address, port=int(port)))) if component_type == "counter": dev.add_component( SolaredgeCounterSetup(id=num, configuration=SolaredgeCounterConfiguration( modbus_id=int(slave_id0)))) log.debug('Solaredge ModbusID: ' + str(slave_id0)) dev.update() elif component_type == "inverter": if ip2address == "none": modbus_ids = list( map( int, filter(lambda id: id.isnumeric(), [slave_id0, slave_id1, slave_id2, slave_id3]))) inverters = [ create_inverter(modbus_id) for modbus_id in modbus_ids ] with SingleComponentUpdateContext(inverters[0].component_info): total_power = 0 total_energy = 0 total_currents = [0.0] * 3 with dev.client: for inv in inverters: state = inv.read_state() total_power += state.power total_energy += state.exported total_currents = list( map(add, total_currents, state.currents)) if extprodakt: state = get_external_inverter_state( dev, int(slave_id0)) total_power -= state.power if batwrsame == 1: bat_power, soc_bat = get_bat_state() if subbat == 1: total_power -= sum(min(p, 0) for p in bat_power) else: total_power -= sum(bat_power) if batwrsame == 1: get_bat_value_store(1).set( BatState(power=sum(bat_power), soc=mean(soc_bat))) get_inverter_value_store(num).set( InverterState(exported=total_energy, power=min(0, total_power), currents=total_currents)) else: inv = create_inverter(int(slave_id0)) with SingleComponentUpdateContext(inv.component_info): with dev.client: state = inv.read_state() total_power = state.power * -1 total_energy = state.exported if batwrsame == 1: zweiterspeicher = 0 bat_power, _ = get_bat_state() total_power -= sum(bat_power) get_bat_value_store(1).set( BatState(power=sum(bat_power), soc=mean(soc_bat))) device_config = Solaredge(configuration=SolaredgeConfiguration( ip_address=ip2address)) dev = Device(device_config) inv = create_inverter(int(slave_id0)) with dev.client: state = inv.read_state() total_power -= state.power total_energy += state.exported if extprodakt: state = get_external_inverter_state( dev, int(slave_id0)) total_power -= state.power get_inverter_value_store(num).set( InverterState(exported=total_energy, power=total_power)) elif component_type == "bat": with SingleComponentUpdateContext( ComponentInfo(0, "Solaredge Speicher", "bat")): power_bat, soc_bat = get_bat_state() get_bat_value_store(1).set( BatState(power=sum(power_bat), soc=mean(soc_bat)))
def update_solar_edge(client: ModbusClient, slave_ids: List[int], batwrsame: int, extprodakt: int, zweiterspeicher: int, subbat: int): storage_slave_ids = slave_ids[0:1 + zweiterspeicher] storage_powers = [] if batwrsame == 1: all_socs = [ client.read_holding_registers(62852, ModbusDataType.FLOAT_32, wordorder=Endian.Little, unit=slave_id) for slave_id in storage_slave_ids ] storage_powers = [ client.read_holding_registers(62836, ModbusDataType.FLOAT_32, wordorder=Endian.Little, unit=slave_id) for slave_id in storage_slave_ids ] log.debug("Battery SoCs=%s, powers=%s", all_socs, storage_powers) get_bat_value_store(1).set( BatState(power=sum(storage_powers), soc=mean(all_socs))) total_energy = 0 total_power = 0 total_currents = [0, 0, 0] for slave_id in slave_ids: # 40083 = AC Power value (Watt), 40084 = AC Power scale factor power_base, power_scale = client.read_holding_registers( 40083, [ModbusDataType.INT_16] * 2, unit=slave_id) total_power -= power_base * math.pow(10, power_scale) # 40093 = AC Lifetime Energy production (Watt hours) energy_base, energy_scale = client.read_holding_registers( 40093, [ModbusDataType.UINT_32, ModbusDataType.INT_16], unit=slave_id) # 40072/40073/40074 = AC Phase A/B/C Current value (Amps) # 40075 = AC Current scale factor currents = client.read_holding_registers( 40072, [ModbusDataType.UINT_16] * 3 + [ModbusDataType.INT_16], unit=slave_id) # Registers that are not applicable to a meter class return the unsupported value. (e.g. Single Phase # meters will support only summary and phase A values): for i in range(3): if currents[i] == UINT16_UNSUPPORTED: currents[i] = 0 log.debug( "slave=%d: power=%d*10^%d, energy=%d*10^%d, currents=%s * 10^%d", slave_id, power_base, power_scale, energy_base, energy_scale, currents[0:3], currents[3]) total_energy += energy_base * math.pow(10, energy_scale) currents_scale = math.pow(10, currents[3]) for i in range(3): total_currents[i] += currents[i] * currents_scale if extprodakt == 1: # 40380 = "Meter 2/Total Real Power (sum of active phases)" (Watt) try: total_power -= client.read_holding_registers(40380, ModbusDataType.INT_16, unit=slave_ids[0]) except Exception: # catch wrong configured "extprodakt" log.error( "Unable to read secondary SmartMeter! Check configuration!") if subbat == 1: total_power -= sum(min(p, 0) for p in storage_powers) else: total_power -= sum(storage_powers) get_inverter_value_store(1).set( InverterState(counter=total_energy, power=min(0, total_power), currents=total_currents))
def __init__(self, component_config: Union[Dict, TeslaBatSetup]) -> None: self.component_config = dataclass_from_dict(TeslaBatSetup, component_config) self.__store = get_bat_value_store(self.component_config.id) self.component_info = ComponentInfo.from_component_config( self.component_config)