Example #1
0
def update(num: int, speichermodul: str, wrkostalpikoip: str):
    log.debug('Wechselrichter Kostal Piko Var 1 Speicher: ' + speichermodul)
    log.debug('Wechselrichter Kostal Piko Var 1 IP: ' + wrkostalpikoip)

    # Auslesen eines Kostal Piko WR über die integrierte API des WR. Rückgabewert ist die aktuelle Wattleistung.
    if speichermodul != "none":
        params = (('dxsEntries', ['33556736', '251658753)']), )
        pvwatttmp = requests.get('http://' + wrkostalpikoip + '/api/dxs.json',
                                 params=params,
                                 timeout=5).json()
    else:
        params = (('dxsEntries', ['67109120', '251658753)']), )
        pvwatttmp = requests.get('http://' + wrkostalpikoip + '/api/dxs.json',
                                 params=params,
                                 timeout=5).json()

    # aktuelle Ausgangsleistung am WR [W]
    pvwatt = int(pvwatttmp["dxsEntries"][0]["value"])

    if pvwatt > 5:
        pvwatt = pvwatt * -1

    log.debug('WR Leistung: ' + str(pvwatt))
    # Gesamtzählerstand am WR [kWh]
    pvkwh = int(pvwatttmp['dxsEntries'][1]['value'])

    get_inverter_value_store(num).set(
        InverterState(counter=pvkwh * 1000, power=pvwatt))
Example #2
0
def read_legacy(ip1: str, webbox: int, ip2: str, ip3: str, ip4: str, version: int, num: int) -> None:
    def create_webbox_inverter(address: str):
        config = inverter_webbox.get_default_config()
        config["id"] = num
        return inverter_webbox.SmaWebboxInverter(0, address, config)

    def create_modbus_inverter(address: str):
        config = inverter_modbus_tcp.get_default_config()
        config["id"] = num
        config["configuration"]["version"] = SmaInverterVersion(version)
        return inverter_modbus_tcp.SmaModbusTcpInverter(0, address, config)

    inverter1 = (create_webbox_inverter if webbox else create_modbus_inverter)(ip1)
    inverters_additional = (create_modbus_inverter(address) for address in [ip2, ip3, ip4] if address != "none")
    # In legacy we were able to configure multiple IP-Addresses for a single SMA-component, effectively creating a
    # virtual component that represents the sum of its subcomponents. This was probably done in order to circumvent
    # the limitation to have a maximum of two inverters configured in legacy.
    # Since openWB 2 does not have a limitation on the number of inverters we do not implement this there. However
    # we still need to implement this for the read_legacy-bridge.
    # Here we act like we only update the first inverter, while we actually query all inverters and sum them up:
    with SingleComponentUpdateContext(inverter1.component_info):
        total_power = 0
        total_energy = 0
        for inverter in itertools.chain((inverter1,), inverters_additional):
            state = inverter.read_inverter_state()
            total_power += state.power
            total_energy += state.counter
        get_inverter_value_store(num).set(InverterState(counter=total_energy, power=total_power))
Example #3
0
def update_sma_modbus(addresses: Iterable[str]):
    power_total = 0
    energy_total = 0

    for ipaddress in addresses:
        with ModbusClient(ipaddress) as client:
            # AC Wirkleistung über alle Phasen (W) [Pac]:
            power = client.read_holding_registers(30775,
                                                  ModbusDataType.INT_32,
                                                  unit=3)
            # Gesamtertrag (Wh) [E-Total]:
            energy = client.read_holding_registers(30529,
                                                   ModbusDataType.UINT_32,
                                                   unit=3)

            log.debug("%s: power = %d W, energy = %d Wh", ipaddress, power,
                      energy)
            if power == SMA_INT32_NAN:
                log.debug("Power value is NaN - ignoring")
            else:
                power_total += power
            energy_total += energy

    power_total = -max(power_total, 0)
    get_inverter_value_store(1).set(
        InverterState(counter=energy_total, power=power_total))
Example #4
0
def update_using_cookie(address: str, cookie):
    aggregate = read_aggregate(address, cookie)
    pv_watt = aggregate["solar"]["instant_power"]
    if pv_watt > 5:
        pv_watt = pv_watt * -1
    get_inverter_value_store(1).set(
        InverterState(counter=aggregate["solar"]["energy_exported"],
                      power=pv_watt))
Example #5
0
def update_using_powerwall_client(client: PowerwallHttpClient):
    aggregate = client.get_json("/api/meters/aggregates")
    pv_watt = aggregate["solar"]["instant_power"]
    if pv_watt > 5:
        pv_watt = pv_watt * -1
    get_inverter_value_store(1).set(
        InverterState(counter=aggregate["solar"]["energy_exported"],
                      power=pv_watt))
Example #6
0
def read_legacy(component_type: str,
                address: str,
                bat_module: str,
                bat_ip: str,
                bat_username: str,
                bat_password: str,
                num: Optional[int] = None) -> None:
    dev = Device(
        KostalPiko(configuration=KostalPikoConfiguration(ip_address=address)))
    if component_type in COMPONENT_TYPE_TO_MODULE:
        component_config = COMPONENT_TYPE_TO_MODULE[
            component_type].component_descriptor.configuration_factory()
    else:
        raise Exception("illegal component type " + component_type +
                        ". Allowed values: " +
                        ','.join(COMPONENT_TYPE_TO_MODULE.keys()))
    component_config.id = num
    dev.add_component(component_config)

    log.debug('KostalPiko IP-Adresse: ' + address)
    log.debug('KostalPiko Speicher: ' + bat_module)

    if component_type == "inverter":
        with SingleComponentUpdateContext(
                dev.components["component" + str(num)].component_info):
            power, exported = dev.components["component" +
                                             str(num)].get_values()
            if bat_module == "speicher_bydhv":
                bat_power = _get_byd_bat_power(bat_ip, bat_username,
                                               bat_password, num)
                power -= bat_power
            get_inverter_value_store(num).set(
                InverterState(power=power, exported=exported))
    elif component_type == "counter":
        with SingleComponentUpdateContext(
                dev.components["componentNone"].component_info):
            home_consumption, powers = dev.components[
                "componentNone"].get_values()
            if bat_module == "speicher_bydhv":
                bat_power = _get_byd_bat_power(bat_ip, bat_username,
                                               bat_password, num)
                home_consumption += bat_power

            dev.add_component(KostalPikoInverterSetup(id=num))
            inverter_power, _ = dev.components["component" +
                                               str(num)].get_values()

            power = home_consumption + inverter_power
            imported, exported = simcount.SimCountFactory().get_sim_counter()(
            ).sim_count(power, topic="topic_str", data={}, prefix="bezug")
            counter_state = CounterState(imported=imported,
                                         exported=exported,
                                         power=power,
                                         powers=powers)
            get_counter_value_store(None).set(counter_state)
Example #7
0
def update(num: int, wr_piko2_url: str, wr_piko2_user: str,
           wr_piko2_pass: str):
    log.debug("Beginning update")
    response = requests.get(wr_piko2_url,
                            verify=False,
                            auth=(wr_piko2_user, wr_piko2_pass),
                            timeout=10)
    response.raise_for_status()
    get_inverter_value_store(num).set(
        parse_kostal_piko_var2_html(response.text))
    log.debug("Update completed successfully")
Example #8
0
def update_sma_webbox(address: str):
    data = {
        'RPC':
        '{"version": "1.0","proc": "GetPlantOverview","id": "1","format": "JSON"}'
    }
    response = requests.post('http://' + address + '/rpc',
                             data=data,
                             timeout=3)
    response.raise_for_status()
    response_data = response.json()
    get_inverter_value_store(1).set(
        InverterState(
            counter=float(response_data["result"]["overview"][2]["value"]) *
            1000,
            power=-int(response_data["result"]["overview"][0]["value"])))
Example #9
0
 def __init__(self, component_config: Union[Dict,
                                            TeslaInverterSetup]) -> None:
     self.component_config = dataclass_from_dict(TeslaInverterSetup,
                                                 component_config)
     self.__store = get_inverter_value_store(self.component_config.id)
     self.component_info = ComponentInfo.from_component_config(
         self.component_config)
Example #10
0
 def __init__(self, component_config: dict,
              tcp_client: modbus.ModbusClient) -> None:
     self.component_config = component_config
     self.__tcp_client = tcp_client
     self.__store = get_inverter_value_store(component_config["id"])
     self.component_info = ComponentInfo.from_component_config(
         component_config)
Example #11
0
 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_inverter_value_store(component_config["id"])
     self.component_info = ComponentInfo.from_component_config(component_config)
Example #12
0
 def __init__(self, device_id: int, device_address: str,
              component_config: dict) -> None:
     self.__device_address = device_address
     self.component_config = component_config
     self.__store = get_inverter_value_store(component_config["id"])
     self.component_info = ComponentInfo.from_component_config(
         component_config)
Example #13
0
 def __init__(self, component_config: Union[Dict, StuderInverterSetup],
              tcp_client: modbus.ModbusTcpClient_) -> None:
     self.component_config = dataclass_from_dict(StuderInverterSetup,
                                                 component_config)
     self.__tcp_client = tcp_client
     self.__store = get_inverter_value_store(self.component_config.id)
     self.component_info = ComponentInfo.from_component_config(
         self.component_config)
Example #14
0
 def __init__(self, device_id: int, component_config: dict, tcp_client: modbus.ModbusClient) -> None:
     self.component_config = component_config
     factory = kit_counter_inverter_version_factory(
         component_config["configuration"]["version"])
     self.__client = factory(component_config["configuration"]["id"], tcp_client)
     self.__tcp_client = tcp_client
     self.__store = get_inverter_value_store(component_config["id"])
     self.component_info = ComponentInfo.from_component_config(component_config)
Example #15
0
 def __init__(self,
              device_id: int,
              component_config: Union[Dict, KostalPikoInverterSetup],
              ip_address: str) -> None:
     self.component_config = dataclass_from_dict(KostalPikoInverterSetup, component_config)
     self.ip_address = ip_address
     self.__store = get_inverter_value_store(self.component_config.id)
     self.component_info = ComponentInfo.from_component_config(self.component_config)
Example #16
0
 def __init__(self, component_config: dict, ip_address: str,
              password: str) -> None:
     self.component_config = component_config
     self.ip_address = ip_address
     self.password = password
     self.__store = get_inverter_value_store(component_config["id"])
     self.component_info = ComponentInfo.from_component_config(
         component_config)
Example #17
0
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))
Example #18
0
def read_inverter(ip1: str, webbox: int, ip2: str, ip3: str, ip4: str,
                  version: int, hybrid: int, num: int,
                  sunny_boy_smart_energy: int):
    def create_webbox_inverter(address: str):
        return SmaWebboxInverter(address, SmaWebboxInverterSetup(id=num))

    def create_modbus_inverter(address: str):
        config = SmaSunnyBoyInverterSetup(
            id=num,
            configuration=SmaSunnyBoyInverterConfiguration(
                hybrid=bool(hybrid), version=SmaInverterVersion(version)))
        return inverter.SmaSunnyBoyInverter(
            0, config, modbus.ModbusTcpClient_(address, 502))

    inverter1 = (create_webbox_inverter
                 if webbox else create_modbus_inverter)(ip1)
    inverters_additional = (create_modbus_inverter(address)
                            for address in [ip2, ip3, ip4]
                            if address != "none")
    # In legacy we were able to configure multiple IP-Addresses for a single SMA-component, effectively creating a
    # virtual component that represents the sum of its subcomponents. This was probably done in order to circumvent
    # the limitation to have a maximum of two inverters configured in legacy.
    # Since openWB 2 does not have a limitation on the number of inverters we do not implement this there. However
    # we still need to implement this for the read_legacy-bridge.
    # Here we act like we only update the first inverter, while we actually query all inverters and sum them up:
    with SingleComponentUpdateContext(inverter1.component_info):
        total_power = 0
        total_energy = 0
        for inv in itertools.chain((inverter1, ), inverters_additional):
            state = inv.read()
            total_power += state.power
            total_energy += state.exported
        if hybrid == 1:
            if sunny_boy_smart_energy == 0:
                bat_comp = bat.SunnyBoyBat(0, SmaSunnyBoyBatSetup(),
                                           modbus.ModbusTcpClient_(ip1, 502))
            else:
                bat_comp = bat_smart_energy.SunnyBoySmartEnergyBat(
                    0, SmaSunnyBoySmartEnergyBatSetup(),
                    modbus.ModbusTcpClient_(ip1, 502))
            bat_state = bat_comp.read()
            total_power -= bat_state.power
            total_energy = total_energy + bat_state.imported - bat_state.exported
        get_inverter_value_store(num).set(
            InverterState(exported=total_energy, power=total_power))
Example #19
0
 def __init__(
         self, device_address: str,
         component_config: Union[Dict, SmaWebboxInverterSetup]) -> None:
     self.__device_address = device_address
     self.component_config = dataclass_from_dict(SmaWebboxInverterSetup,
                                                 component_config)
     self.__store = get_inverter_value_store(self.component_config.id)
     self.component_info = ComponentInfo.from_component_config(
         self.component_config)
Example #20
0
 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_inverter_value_store(component_config["id"])
     self.component_info = ComponentInfo.from_component_config(component_config)
Example #21
0
 def __init__(self, component_config: dict, domain: str) -> None:
     self.__get_power = create_request_function(
         domain, component_config["configuration"]["power_path"])
     self.__get_counter = create_request_function(
         domain, component_config["configuration"]["counter_path"])
     self.component_config = component_config
     self.__store = get_inverter_value_store(component_config["id"])
     self.component_info = ComponentInfo.from_component_config(
         component_config)
Example #22
0
 def __init__(self, device_id: int,
              component_config: Union[Dict, LgInverterSetup]) -> None:
     self.__device_id = device_id
     self.component_config = dataclass_from_dict(LgInverterSetup,
                                                 component_config)
     self.__sim_count = simcount.SimCountFactory().get_sim_counter()()
     self.__simulation = {}
     self.__store = get_inverter_value_store(self.component_config.id)
     self.component_info = ComponentInfo.from_component_config(
         self.component_config)
Example #23
0
def create_component(component_config: dict):
    store = get_inverter_value_store(component_config["id"])

    def persister(reading: CounterState):
        store.set(
            InverterState(counter=reading.exported,
                          power=reading.power,
                          currents=reading.currents))

    return DiscovergyComponent(component_config, persister)
Example #24
0
 def __init__(self, device_id: int,
              component_config: Union[Dict, SolaxInverterSetup],
              tcp_client: modbus.ModbusTcpClient_, modbus_id: int) -> None:
     self.component_config = dataclass_from_dict(SolaxInverterSetup,
                                                 component_config)
     self.__modbus_id = modbus_id
     self.__tcp_client = tcp_client
     self.__store = get_inverter_value_store(self.component_config.id)
     self.component_info = ComponentInfo.from_component_config(
         self.component_config)
Example #25
0
def update(bezug_solarlog_ip: str):
    log.debug('Wechselrichter Solarlog IP: ' + bezug_solarlog_ip)

    data = {"801": {"170": None}}
    data = json.dumps(data)
    response = requests.post("http://" + bezug_solarlog_ip + '/getjp',
                             data=data,
                             timeout=3).json()
    pv_watt = float(response["801"]["170"]["101"])
    pv_kwh = float(response["801"]["170"]["109"])

    if pv_watt > 5:
        pv_watt = pv_watt * -1

    log.debug('WR Leistung: ' + str(pv_watt))
    log.debug('WR Energie: ' + str(pv_kwh))

    get_inverter_value_store(1).set(
        InverterState(exported=pv_kwh, power=pv_watt))
Example #26
0
    def __init__(self, component_config: Union[Dict, SunwaysInverterSetup],
                 ip_address: str, password: str) -> None:

        self.component_config = dataclass_from_dict(SunwaysInverterSetup,
                                                    component_config)
        self.ip_address = ip_address
        self.password = password
        self.__store = get_inverter_value_store(self.component_config.id)
        self.component_info = ComponentInfo.from_component_config(
            self.component_config)
Example #27
0
 def __init__(self,
              device_id: int,
              component_config: Union[Dict, VictronInverterSetup],
              tcp_client: modbus.ModbusTcpClient_) -> None:
     self.__device_id = device_id
     self.component_config = dataclass_from_dict(VictronInverterSetup, component_config)
     self.__tcp_client = tcp_client
     self.__sim_count = simcount.SimCountFactory().get_sim_counter()()
     self.simulation = {}
     self.__store = get_inverter_value_store(self.component_config.id)
     self.component_info = ComponentInfo.from_component_config(self.component_config)
Example #28
0
def read_legacy(
        component_type: str,
        ip_address: str,
        meter_id: int,
        variant: int,
        ip_address2: str = "none",
        num: Optional[int] = None) -> None:

    device_config = Fronius()
    device_config.configuration.ip_address = ip_address
    dev = Device(device_config)
    if component_type in COMPONENT_TYPE_TO_MODULE:
        component_config = COMPONENT_TYPE_TO_MODULE[component_type].component_descriptor.configuration_factory()
        if component_type == "bat":
            component_config.configuration.meter_id = meter_id
        elif component_type == "counter_sm":
            component_config.configuration.variant = variant
            component_config.configuration.meter_id = meter_id
    else:
        raise Exception(
            "illegal component type " + component_type + ". Allowed values: " +
            ','.join(COMPONENT_TYPE_TO_MODULE.keys())
        )
    component_config.id = num
    dev.add_component(component_config)

    log.debug('Fronius IP-Adresse: ' + ip_address)

    if component_type == "bat" or "counter" in component_type:
        dev.update()
    elif component_type == "inverter" and num:
        inverter1 = inverter.FroniusInverter(num, component_config, dev.device_config.configuration)
        with SingleComponentUpdateContext(inverter1.component_info):
            total_power = inverter1.read_power()
            if ip_address2 != "none":
                dev.device_config.configuration.ip_address = ip_address2
                inverter2 = inverter.FroniusInverter(num, component_config, dev.device_config.configuration)
                total_power += inverter2.read_power()
            get_inverter_value_store(num).set(inverter1.fill_inverter_state(total_power))
    else:
        raise Exception("illegal component num " + str(num) + ". Should be an int if it is an inverter.")
Example #29
0
def update(wr_smartme_url: str, wr_smartme_user: str, wr_smartme_pass: str):
    log.debug('Wechselrichter smartme URL: ' + wr_smartme_url)
    log.debug('Wechselrichter smartme User: '******'Wechselrichter smartme Passwort: ' + wr_smartme_pass)

    # Daten einlesen
    response = requests.get(wr_smartme_url,
                            auth=(wr_smartme_user, wr_smartme_pass),
                            timeout=3).json()
    # Aktuelle Leistung (kW --> W)
    wattwr = response["ActivePower"]
    wattwr = round(wattwr * 1000)

    # Zählerstand Export (kWh --> Wh)
    pvkwh = response["CounterReadingExport"]
    pvkwh = round(pvkwh * 1000, 3)

    log.debug('WR Leistung: ' + str(wattwr))
    log.debug('WR Energie: ' + str(pvkwh))

    get_inverter_value_store(1).set(InverterState(counter=pvkwh, power=wattwr))
Example #30
0
 def __init__(
         self, device_id: int, device_address: str, device_variant: int,
         component_config: Union[Dict,
                                 SonnenbatterieInverterSetup]) -> None:
     self.__device_id = device_id
     self.__device_address = device_address
     self.__device_variant = device_variant
     self.component_config = dataclass_from_dict(
         SonnenbatterieInverterSetup, component_config)
     self.__sim_count = simcount.SimCountFactory().get_sim_counter()()
     self.simulation = {}
     self.__store = get_inverter_value_store(self.component_config.id)
     self.component_info = ComponentInfo.from_component_config(
         self.component_config)