Beispiel #1
0
def parse_datagram(sma_data: dict):
    def get_power(phase_str: str = ""):
        # "consume" and "supply" are always >= 0. Thus we need to check both "supply" and "consume":
        power_import = sma_data["p" + phase_str + "consume"]
        return -sma_data["p" + phase_str +
                         "supply"] if power_import == 0 else power_import

    powers = [get_power(str(phase)) for phase in range(1, 4)]

    counter_state = CounterState(
        imported=sma_data['pconsumecounter'] * 1000,
        exported=sma_data['psupplycounter'] * 1000,
        power=get_power(),
        voltages=[sma_data["u" + str(phase)] for phase in range(1, 4)],
        # currents reported are always absolute values. We get the sign from power:
        currents=[
            copysign(sma_data["i" + str(phase)], powers[phase - 1])
            for phase in range(1, 4)
        ],
        powers=powers,
        power_factors=[
            sma_data["cosphi" + str(phase)] for phase in range(1, 4)
        ])
    frequency = sma_data.get("frequency")
    if frequency:
        counter_state.frequency = frequency

    return counter_state
Beispiel #2
0
    def update(self, resp: Dict) -> None:
        log.MainLogger().debug("Komponente " + self.component_config["name"] +
                               " auslesen.")
        power = resp["2913"]["0"]
        frequency = resp["2914"]["0"] / 100
        powers = self.__parse_list_values(resp, 2897)
        voltages = self.__parse_list_values(resp, 2833, 100)
        currents = self.__parse_list_values(resp, 2865, 100)
        try:
            power_factors = self.__parse_list_values(resp, 2881)
        except KeyError:
            log.MainLogger().debug(
                "Powerfaktor sollte laut Doku enthalten sein, ID 2881 kann aber nicht ermittelt werden."
            )
            power_factors = None
        topic_str = "openWB/set/system/device/{}/component/{}/".format(
            self.__device_id, self.component_config["id"])
        imported, exported = self.__sim_count.sim_count(power,
                                                        topic=topic_str,
                                                        data=self.simulation,
                                                        prefix="bezug")

        counter_state = CounterState(imported=imported,
                                     exported=exported,
                                     power=power,
                                     powers=powers,
                                     currents=currents,
                                     voltages=voltages,
                                     frequency=frequency)
        if power_factors:
            counter_state.power_factors = power_factors
        self.__store.set(counter_state)
Beispiel #3
0
def test_current_sign():
    assert vars(CounterState(currents=[-5, -5, 5],
                             powers=[-1150, -1150,
                                     1150])) == vars(counter_state)
    assert vars(CounterState(currents=[5, 5, 5],
                             powers=[-1150, -1150,
                                     1150])) == vars(counter_state)
Beispiel #4
0
def update_using_powerwall_client(client: PowerwallHttpClient):
    # read firmware version
    status = client.get_json("/api/status")
    log.debug('Firmware: ' + status["version"])
    # read aggregate
    aggregate = client.get_json("/api/meters/aggregates")
    try:
        # read additional info if firmware supports
        meters_site = client.get_json("/api/meters/site")
        powerwall_state = CounterState(
            imported=aggregate["site"]["energy_imported"],
            exported=aggregate["site"]["energy_exported"],
            power=aggregate["site"]["instant_power"],
            voltages=[
                meters_site[0]["Cached_readings"]["v_l" + str(phase) + "n"]
                for phase in range(1, 4)
            ],
            currents=[
                meters_site[0]["Cached_readings"]["i_" + phase + "_current"]
                for phase in ["a", "b", "c"]
            ],
            powers=[
                meters_site[0]["Cached_readings"]["real_power_" + phase]
                for phase in ["a", "b", "c"]
            ])
    except (KeyError, HTTPError):
        log.debug(
            "Firmware seems not to provide detailed phase measurements. Fallback to total power only."
        )
        powerwall_state = CounterState(
            imported=aggregate["site"]["energy_imported"],
            exported=aggregate["site"]["energy_exported"],
            power=aggregate["site"]["instant_power"])
    get_counter_value_store(1).set(powerwall_state)
Beispiel #5
0
    def update(self):
        log.MainLogger().debug("Komponente " + self.component_config["name"] +
                               " auslesen.")

        time.sleep(0.1)
        power = self.__tcp_client.read_holding_registers(
            37113, ModbusDataType.INT_32, unit=self.__modbus_id) * -1
        time.sleep(0.1)
        currents = [
            val / -100 for val in self.__tcp_client.read_holding_registers(
                37107, [ModbusDataType.INT_32] * 3, unit=self.__modbus_id)
        ]

        topic_str = "openWB/set/system/device/{}/component/{}/".format(
            self.__device_id, self.component_config["id"])
        imported, exported = self.__sim_count.sim_count(power,
                                                        topic=topic_str,
                                                        data=self.simulation,
                                                        prefix="bezug")

        counter_state = CounterState(currents=currents,
                                     imported=imported,
                                     exported=exported,
                                     power=power)
        self.__store.set(counter_state)
Beispiel #6
0
    def update(self):
        with self.__tcp_client:
            power = self.__tcp_client.read_input_registers(
                70,
                ModbusDataType.INT_32,
                wordorder=Endian.Little,
                unit=self.__modbus_id) * -1
            frequency = self.__tcp_client.read_input_registers(
                7, ModbusDataType.UINT_16, unit=self.__modbus_id) / 100
            try:
                powers = [
                    -value for value in self.__tcp_client.read_input_registers(
                        130, [ModbusDataType.INT_32] * 3,
                        wordorder=Endian.Little,
                        unit=self.__modbus_id)
                ]
            except Exception:
                powers = None
            exported, imported = [
                value * 10 for value in self.__tcp_client.read_input_registers(
                    72, [ModbusDataType.UINT_32] * 2,
                    wordorder=Endian.Little,
                    unit=self.__modbus_id)
            ]

        counter_state = CounterState(imported=imported,
                                     exported=exported,
                                     power=power,
                                     powers=powers,
                                     frequency=frequency)
        self.__store.set(counter_state)
Beispiel #7
0
    def update(self):
        with self.__tcp_client:
            power_factors = [
                val / 1000 for val in self.__tcp_client.read_holding_registers(
                    36010, [ModbusDataType.UINT_16] * 3, unit=self.__modbus_id)
            ]
            exported = self.__tcp_client.read_holding_registers(
                36015, ModbusDataType.FLOAT_32, unit=self.__modbus_id)
            imported = self.__tcp_client.read_holding_registers(
                36017, ModbusDataType.FLOAT_32, unit=self.__modbus_id)
            powers = [
                val * -1 for val in self.__tcp_client.read_holding_registers(
                    36005, [ModbusDataType.INT_16] * 3, unit=self.__modbus_id)
            ]
            power = self.__tcp_client.read_holding_registers(
                36008, ModbusDataType.INT_16, unit=self.__modbus_id) * -1

            frequency = self.__tcp_client.read_holding_registers(
                36014, ModbusDataType.UINT_16, unit=self.__modbus_id) / 100

        counter_state = CounterState(powers=powers,
                                     imported=imported,
                                     exported=exported,
                                     power=power,
                                     power_factors=power_factors,
                                     frequency=frequency)
        self.__store.set(counter_state)
Beispiel #8
0
def update(ipaddress: str):
    log.debug("Beginning update")
    client = ModbusClient(ipaddress, port=502)
    #40074 EVU Punkt negativ -> Einspeisung in Watt
    power_all = client.read_holding_registers(40073,
                                              ModbusDataType.INT_32,
                                              wordorder=Endian.Little,
                                              unit=1)
    #40130 Phasenleistung in Watt
    # max 6 Leistungsmesser verbaut ab 410105, typ 1 ist evu
    # bei den meisten e3dc auf 40128
    #for i in range (40104,40132,4):
    for i in range(40128, 40103, -4):
        #powers = client.read_holding_registers(40129, [ModbusDataType.INT_16] * 3, unit=1)
        powers = client.read_holding_registers(i, [ModbusDataType.INT_16] * 4,
                                               unit=1)
        log.debug("I: %d, p[0] typ %d p[1] a1 %d p[2] a2 %d p[3] a3 %d", i,
                  powers[0], powers[1], powers[2], powers[3])
        if powers[0] == 1:
            log.debug("Evu Leistungsmessung gefunden")
            break
    counter_import, counter_export = SimCountFactory().get_sim_counter()(
    ).sim_count(power_all, prefix="bezug")
    get_counter_value_store(1).set(
        CounterState(imported=counter_import,
                     exported=counter_export,
                     power=power_all,
                     powers=powers[1:]))
    log.debug("Update completed successfully")
Beispiel #9
0
    def update(self):
        with self.__tcp_client:
            power = self.__tcp_client.read_holding_registers(
                19026, ModbusDataType.FLOAT_32, unit=1)
            powers = self.__tcp_client.read_holding_registers(
                19020, [ModbusDataType.FLOAT_32] * 3, unit=1)
            currents = self.__tcp_client.read_holding_registers(
                19012, [ModbusDataType.FLOAT_32] * 3, unit=1)
            voltages = self.__tcp_client.read_holding_registers(
                19000, [ModbusDataType.FLOAT_32] * 3, unit=1)
            power_factors = self.__tcp_client.read_holding_registers(
                19044, [ModbusDataType.FLOAT_32] * 3, unit=1)
            frequency = self.__tcp_client.read_holding_registers(
                19050, ModbusDataType.FLOAT_32, unit=1)

        topic_str = "openWB/set/system/device/{}/component/{}/".format(
            self.__device_id, self.component_config.id)
        imported, exported = self.__sim_count.sim_count(power,
                                                        topic=topic_str,
                                                        data=self.simulation,
                                                        prefix="bezug")

        counter_state = CounterState(imported=imported,
                                     exported=exported,
                                     power=power,
                                     powers=powers,
                                     currents=currents,
                                     voltages=voltages,
                                     frequency=frequency,
                                     power_factors=power_factors)
        self.__store.set(counter_state)
Beispiel #10
0
 def __update_variant_1(self) -> CounterState:
     # Auslesen einer Sonnenbatterie 8 oder 10 über die integrierte JSON-API v1 des Batteriesystems
     '''
     example data:
     {
         "Apparent_output": 225,
         "BackupBuffer": "0",
         "BatteryCharging": false,
         "BatteryDischarging": false,
         "Consumption_Avg": 2114,
         "Consumption_W": 2101,
         "Fac": 49.97200393676758,
         "FlowConsumptionBattery": false,
         "FlowConsumptionGrid": true,
         "FlowConsumptionProduction": false,
         "FlowGridBattery": false,
         "FlowProductionBattery": false,
         "FlowProductionGrid": false,
         "GridFeedIn_W": -2106,
         "IsSystemInstalled": 1,
         "OperatingMode": "2",
         "Pac_total_W": -5,
         "Production_W": 0,
         "RSOC": 6,
         "RemainingCapacity_Wh": 2377,
         "Sac1": 75,
         "Sac2": 75,
         "Sac3": 75,
         "SystemStatus": "OnGrid",
         "Timestamp": "2021-12-13 07:54:48",
         "USOC": 0,
         "Uac": 231,
         "Ubat": 48,
         "dischargeNotAllowed": true,
         "generator_autostart": false,
         "NVM_REINIT_STATUS": 0
     }
     '''
     counter_state = self.__read_variant_1()
     grid_power = -counter_state["GridFeedIn_W"]
     log.debug('EVU Leistung: ' + str(grid_power))
     # Es wird nur eine Spannung ausgegeben
     grid_voltage = counter_state["Uac"]
     log.debug('EVU Spannung: ' + str(grid_voltage))
     grid_frequency = counter_state["Fac"]
     log.debug('EVU Netzfrequenz: ' + str(grid_frequency))
     topic_str = "openWB/set/system/device/" + str(
         self.__device_id) + "/component/" + str(
             self.component_config.id) + "/"
     imported, exported = self.__sim_count.sim_count(grid_power,
                                                     topic=topic_str,
                                                     data=self.simulation,
                                                     prefix="bezug")
     return CounterState(
         power=grid_power,
         voltages=[grid_voltage] * 3,
         frequency=grid_frequency,
         imported=imported,
         exported=exported,
     )
Beispiel #11
0
    def update(self):
        MainLogger().debug("Komponente " + self.component_config["name"] +
                           " auslesen.")
        with self.__tcp_client:
            power_factors = [
                val / 1000 for val in self.__tcp_client.read_holding_registers(
                    36010, [ModbusDataType.UINT_16] * 3, unit=self.__modbus_id)
            ]
            exported = self.__tcp_client.read_holding_registers(
                36015, ModbusDataType.FLOAT_32, unit=self.__modbus_id)
            imported = self.__tcp_client.read_holding_registers(
                36017, ModbusDataType.FLOAT_32, unit=self.__modbus_id)
            powers = [
                val * -1 for val in self.__tcp_client.read_holding_registers(
                    36005, [ModbusDataType.INT_16] * 3, unit=self.__modbus_id)
            ]
            power = self.__tcp_client.read_holding_registers(
                36008, ModbusDataType.INT_16, unit=self.__modbus_id) * -1

            frequency = self.__tcp_client.read_holding_registers(
                36014, ModbusDataType.UINT_16, unit=self.__modbus_id) / 100

        counter_state = CounterState(powers=powers,
                                     imported=imported,
                                     exported=exported,
                                     power=power,
                                     power_factors=power_factors,
                                     frequency=frequency)
        self.__store.set(counter_state)
Beispiel #12
0
    def update(self):
        log.MainLogger().debug("Komponente " + self.component_config["name"] +
                               " auslesen.")
        with self.__tcp_client:
            power = self.__tcp_client.read_input_registers(
                70, ModbusDataType.INT_32, wordorder=Endian.Little) * -1
            frequency = self.__tcp_client.read_input_registers(
                7, ModbusDataType.UINT_16) / 100
            try:
                powers = [
                    -value for value in self.__tcp_client.read_input_registers(
                        130, [ModbusDataType.INT_32] * 3,
                        wordorder=Endian.Little)
                ]
            except Exception:
                powers = None
            exported, imported = [
                value * 10 for value in self.__tcp_client.read_input_registers(
                    72, [ModbusDataType.UINT_32] * 2, wordorder=Endian.Little)
            ]

        counter_state = CounterState(imported=imported,
                                     exported=exported,
                                     power=power,
                                     powers=powers,
                                     frequency=frequency)
        log.MainLogger().debug("Solax Leistung[W]: " +
                               str(counter_state.power))
        self.__store.set(counter_state)
Beispiel #13
0
    def update(self):
        log.MainLogger().debug("Komponente "+self.component_config["name"]+" auslesen.")
        unit = self.component_config["configuration"]["modbus_id"]
        power = sum(self.__tcp_client.read_holding_registers(2600, [ModbusDataType.INT_16]*3, unit=unit))
        currents = [
            self.__tcp_client.read_holding_registers(reg, ModbusDataType.INT_16, unit=unit) / 10
            for reg in [2617, 2619, 2621]]
        voltages = [
            self.__tcp_client.read_holding_registers(reg, ModbusDataType.UINT_16, unit=unit) / 10
            for reg in [2616, 2618, 2610]]

        topic_str = "openWB/set/system/device/{}/component/{}/".format(
            self.__device_id, self.component_config["id"]
        )
        imported, exported = self.__sim_count.sim_count(
            power,
            topic=topic_str,
            data=self.simulation,
            prefix="bezug"
        )

        counter_state = CounterState(
            voltages=voltages,
            currents=currents,
            imported=imported,
            exported=exported,
            power=power
        )
        log.MainLogger().debug("Victron Leistung[W]: " + str(counter_state.power))
        self.__store.set(counter_state)
Beispiel #14
0
    def update(self, response):
        log.MainLogger().debug("Komponente "+self.component_config["name"]+" auslesen.")
        config = self.component_config["configuration"]

        power = jq.compile(config["jq_power"]).input(response).first()
        if config["jq_imported"] == "" or config["jq_exported"] == "":
            topic_str = "openWB/set/system/device/{}/component/{}/".format(
                self.__device_id, self.component_config["id"]
            )
            imported, exported = self.__sim_count.sim_count(
                power,
                topic=topic_str,
                data=self.simulation,
                prefix="bezug"
            )
        else:
            imported = jq.compile(config["jq_imported"]).input(response).first()
            exported = jq.compile(config["jq_exported"]).input(response).first()

        counter_state = CounterState(
            imported=imported,
            exported=exported,
            power=power
        )
        self.__store.set(counter_state)
Beispiel #15
0
    def __update_variant_0_1(
            self, session: Session) -> Tuple[CounterState, MeterLocation]:
        variant = self.component_config["configuration"]["variant"]
        meter_id = self.device_config["meter_id"]
        if variant == 0:
            params = (
                ('Scope', 'Device'),
                ('DeviceId', meter_id),
            )
        elif variant == 1:
            params = (
                ('Scope', 'Device'),
                ('DeviceId', meter_id),
                ('DataCollection', 'MeterRealtimeData'),
            )
        else:
            raise FaultState.error("Unbekannte Generation: " + str(variant))
        response = session.get('http://' + self.device_config["ip_address"] +
                               '/solar_api/v1/GetMeterRealtimeData.cgi',
                               params=params,
                               timeout=5)
        response_json_id = response.json()["Body"]["Data"]
        # old request for variant == 1
        # params = (
        #     ('Scope', 'System'),
        # )
        # response = req.get_http_session().get(
        #     'http://'+self.device_config["ip_address"]+'/solar_api/v1/GetMeterRealtimeData.cgi',
        #  params=params, timeout=5)
        # response_json_id = response["Body"]["Data"][meter_id]
        meter_location = MeterLocation(
            response_json_id["Meter_Location_Current"])
        log.MainLogger().debug("Einbauort: " + str(meter_location))

        power = response_json_id["PowerReal_P_Sum"]
        voltages = [
            response_json_id["Voltage_AC_Phase_" + str(num)]
            for num in range(1, 4)
        ]
        powers = [
            response_json_id["PowerReal_P_Phase_" + str(num)]
            for num in range(1, 4)
        ]
        currents = [powers[i] / voltages[i] for i in range(0, 3)]
        power_factors = [
            response_json_id["PowerFactor_Phase_" + str(num)]
            for num in range(1, 4)
        ]
        frequency = response_json_id["Frequency_Phase_Average"]
        imported = response_json_id["EnergyReal_WAC_Sum_Consumed"]
        exported = response_json_id["EnergyReal_WAC_Sum_Produced"]

        return CounterState(voltages=voltages,
                            currents=currents,
                            powers=powers,
                            imported=imported,
                            exported=exported,
                            power=power,
                            frequency=frequency,
                            power_factors=power_factors), meter_location
Beispiel #16
0
    def update(self):
        # TCP-Verbindung schließen möglichst bevor etwas anderes gemacht wird, um im Fehlerfall zu verhindern,
        # dass offene Verbindungen den Modbus-Adapter blockieren.
        with self.__tcp_client:
            voltages = self.__client.get_voltages()
            powers, power = self.__client.get_power()
            frequency = self.__client.get_frequency()
            power_factors = self.__client.get_power_factors()

            if isinstance(self.__client, Mpm3pm):
                imported = self.__client.get_imported()
                exported = self.__client.get_exported()
            else:
                currents = self.__client.get_currents()

        if isinstance(self.__client, Mpm3pm):
            currents = [powers[i] / voltages[i] for i in range(3)]
        else:
            if isinstance(self.__client, Lovato):
                power = sum(powers)
            topic_str = "openWB/set/system/device/{}/component/{}/".format(
                self.__device_id, self.component_config.id)
            imported, exported = self.__sim_count.sim_count(
                power, topic=topic_str, data=self.simulation, prefix="bezug")
        counter_state = CounterState(voltages=voltages,
                                     currents=currents,
                                     powers=powers,
                                     power_factors=power_factors,
                                     imported=imported,
                                     exported=exported,
                                     power=power,
                                     frequency=frequency)
        self.__store.set(counter_state)
Beispiel #17
0
    def __update_variant_0_1(self, session: Session) -> CounterState:
        variant = self.component_config.configuration.variant
        meter_id = self.component_config.configuration.meter_id
        if variant == 0:
            params = (
                ('Scope', 'Device'),
                ('DeviceId', meter_id),
            )
        elif variant == 1:
            params = (
                ('Scope', 'Device'),
                ('DeviceId', meter_id),
                ('DataCollection', 'MeterRealtimeData'),
            )
        else:
            raise FaultState.error("Unbekannte Generation: " + str(variant))
        response = session.get('http://' + self.device_config.ip_address +
                               '/solar_api/v1/GetMeterRealtimeData.cgi',
                               params=params,
                               timeout=5)
        response_json_id = response.json()["Body"]["Data"]

        meter_location = MeterLocation.get(
            response_json_id["Meter_Location_Current"])
        log.debug("Einbauort: " + str(meter_location))

        powers = [
            response_json_id["PowerReal_P_Phase_" + str(num)]
            for num in range(1, 4)
        ]
        if meter_location == MeterLocation.load:
            power, power_inverter = self.__get_flow_power(session)
            # wenn SmartMeter im Verbrauchszweig sitzt sind folgende Annahmen getroffen:
            # PV Leistung wird gleichmäßig auf alle Phasen verteilt
            # Spannungen und Leistungsfaktoren sind am Verbrauchszweig == Einspeisepunkt
            # Hier gehen wir mal davon aus, dass der Wechselrichter seine PV-Leistung gleichmäßig
            # auf alle Phasen aufteilt.
            powers = [-1 * power - power_inverter / 3 for power in powers]
        else:
            power = response_json_id["PowerReal_P_Sum"]
        voltages = [
            response_json_id["Voltage_AC_Phase_" + str(num)]
            for num in range(1, 4)
        ]
        currents = [powers[i] / voltages[i] for i in range(0, 3)]
        power_factors = [
            response_json_id["PowerFactor_Phase_" + str(num)]
            for num in range(1, 4)
        ]
        frequency = response_json_id["Frequency_Phase_Average"]

        return CounterState(voltages=voltages,
                            currents=currents,
                            powers=powers,
                            power=power,
                            frequency=frequency,
                            power_factors=power_factors)
Beispiel #18
0
    def update(self):
        def read_scaled_int16(address: int, count: int):
            return scale_registers(
                self.__tcp_client.read_holding_registers(
                    address, [ModbusDataType.INT_16] * (count + 1),
                    unit=self.component_config.configuration.modbus_id))

        def read_scaled_uint32(address: int, count: int):
            return scale_registers(
                self.__tcp_client.read_holding_registers(
                    address, [ModbusDataType.UINT_32] * (count) +
                    [ModbusDataType.INT_16],
                    unit=self.component_config.configuration.modbus_id))

        # 40206: Total Real Power (sum of active phases)
        # 40207/40208/40209: Real Power by phase
        # 40210: AC Real Power Scale Factor
        powers = [-power for power in read_scaled_int16(40206, 4)]

        # 40191/40192/40193: AC Current by phase
        # 40194: AC Current Scale Factor
        currents = read_scaled_int16(40191, 3)

        # 40196/40197/40198: Voltage per phase
        # 40203: AC Voltage Scale Factor
        voltages = read_scaled_int16(40196, 7)[:3]

        # 40204: AC Frequency
        # 40205: AC Frequency Scale Factor
        frequency = read_scaled_int16(40204, 1)[0]

        # 40222/40223/40224: Power factor by phase (unit=%)
        # 40225: AC Power Factor Scale Factor
        power_factors = [
            power_factor / 100 for power_factor in read_scaled_int16(40222, 3)
        ]

        # 40226: Total Exported Real Energy
        # 40228/40230/40232: Total Exported Real Energy Phase (not used)
        # 40234: Total Imported Real Energy
        # 40236/40238/40240: Total Imported Real Energy Phase (not used)
        # 40242: Real Energy Scale Factor
        counter_values = read_scaled_uint32(40226, 8)
        counter_exported, counter_imported = [
            counter_values[i] for i in [0, 4]
        ]

        counter_state = CounterState(imported=counter_imported,
                                     exported=counter_exported,
                                     power=powers[0],
                                     powers=powers[1:],
                                     voltages=voltages,
                                     currents=currents,
                                     power_factors=power_factors,
                                     frequency=frequency)
        self.__store.set(counter_state)
Beispiel #19
0
    def update(self):
        unit = self.component_config.configuration.modbus_id
        energy_meter = self.component_config.configuration.energy_meter
        with self.__tcp_client:
            if energy_meter:
                powers = self.__tcp_client.read_holding_registers(
                    2600, [ModbusDataType.INT_16] * 3, unit=unit)
                currents = [
                    self.__tcp_client.read_holding_registers(
                        reg, ModbusDataType.INT_16, unit=unit) / 10
                    for reg in [2617, 2619, 2621]
                ]
                voltages = [
                    self.__tcp_client.read_holding_registers(
                        reg, ModbusDataType.UINT_16, unit=unit) / 10
                    for reg in [2616, 2618, 2620]
                ]
                power = sum(powers)
            else:
                powers = self.__tcp_client.read_holding_registers(
                    820, [ModbusDataType.INT_16] * 3, unit=unit)
                power = sum(powers)

        topic_str = "openWB/set/system/device/{}/component/{}/".format(
            self.__device_id, self.component_config.id)
        imported, exported = self.__sim_count.sim_count(power,
                                                        topic=topic_str,
                                                        data=self.simulation,
                                                        prefix="bezug")

        if energy_meter:
            counter_state = CounterState(voltages=voltages,
                                         currents=currents,
                                         powers=powers,
                                         imported=imported,
                                         exported=exported,
                                         power=power)
        else:
            counter_state = CounterState(powers=powers,
                                         imported=imported,
                                         exported=exported,
                                         power=power)
        self.__store.set(counter_state)
Beispiel #20
0
    def update(self):
        log.MainLogger().debug("Komponente " + self.component_config["name"] +
                               " auslesen.")

        counter_state = CounterState(
            powers=[getter() for getter in self.__get_powers],
            imported=self.__get_imported(),
            exported=self.__get_exported(),
            power=self.__get_power())
        self.__store.set(counter_state)
Beispiel #21
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)
Beispiel #22
0
def update(ipaddress: str, modbusport: int, slaveid: int):
    log.debug("Beginning update")
    client = ModbusClient(ipaddress, port=modbusport)

    def read_scaled_int16(address: int, count: int):
        return scale_registers(
            client.read_holding_registers(address, [ModbusDataType.INT_16] *
                                          (count + 1),
                                          unit=slaveid))

    # 40206: Total Real Power (sum of active phases)
    # 40206/40207/40208: Real Power by phase
    # 40210: AC Real Power Scale Factor
    powers = [-power for power in read_scaled_int16(40206, 4)]

    # 40191/40192/40193: AC Current by phase
    # 40194: AC Current Scale Factor
    currents = read_scaled_int16(40191, 3)

    # 40196/40197/40198: Voltage per phase
    # 40203: AC Voltage Scale Factor
    voltages = read_scaled_int16(40196, 7)[:3]

    # 40204: AC Frequency
    # 40205: AC Frequency Scale Factor
    frequency, = read_scaled_int16(40204, 1)

    # 40222/40223/40224: Power factor by phase (unit=%)
    # 40225: AC Power Factor Scale Factor
    power_factors = [
        power_factor / 100 for power_factor in read_scaled_int16(40222, 3)
    ]

    # 40234: Total Imported Real Energy
    counter_imported = client.read_holding_registers(40234,
                                                     ModbusDataType.UINT_32,
                                                     unit=slaveid)

    # 40226: Total Exported Real Energy
    counter_exported = client.read_holding_registers(40226,
                                                     ModbusDataType.UINT_32,
                                                     unit=slaveid)

    get_counter_value_store(1).set(
        CounterState(imported=counter_imported,
                     exported=counter_exported,
                     power=powers[0],
                     powers=powers[1:],
                     voltages=voltages,
                     currents=currents,
                     power_factors=power_factors,
                     frequency=frequency))
    log.debug("Update completed successfully")
Beispiel #23
0
 def update(self):
     power, powers = self.get_values()
     topic_str = "openWB/set/system/device/{}/component/{}/".format(
         self.__device_id, self.component_config.id)
     imported, exported = self.__sim_count.sim_count(power,
                                                     topic=topic_str,
                                                     data=self.simulation,
                                                     prefix="bezug")
     counter_state = CounterState(imported=imported,
                                  exported=exported,
                                  power=power,
                                  powers=powers)
     self.__store.set(counter_state)
Beispiel #24
0
 def __update_variant_2(self) -> CounterState:
     # Auslesen einer Sonnenbatterie Eco 6 über die integrierte REST-API des Batteriesystems
     grid_import_power = int(self.__read_variant_2_element("M39"))
     grid_export_power = int(self.__read_variant_2_element("M38"))
     grid_power = grid_import_power - grid_export_power
     topic_str = "openWB/set/system/device/" + str(
         self.__device_id)+"/component/"+str(self.component_config["id"])+"/"
     imported, exported = self.__sim_count.sim_count(
         grid_power, topic=topic_str, data=self.__simulation, prefix="bezug"
     )
     return CounterState(
         power=grid_power,
         imported=imported,
         exported=exported,
     )
Beispiel #25
0
    def update(self, response) -> None:
        power = float(response["statistics"]["grid_power"])
        if response["direction"]["is_grid_selling_"] == "1":
            power = power * -1

        topic_str = "openWB/set/system/device/{}/component/{}/".format(
            self.__device_id, self.component_config.id)
        imported, exported = self.__sim_count.sim_count(power,
                                                        topic=topic_str,
                                                        data=self.simulation,
                                                        prefix="bezug")
        counter_state = CounterState(imported=imported,
                                     exported=exported,
                                     power=power)
        self.__store.set(counter_state)
Beispiel #26
0
def update_using_cookie(address: str, cookie):
    # read firmware version
    status = read_status(address, cookie)
    # since 21.44.1 tesla adds the commit hash '21.44.1 c58c2df3'
    # so we split by whitespace and take the first element for comparison
    log.debug('Firmware: ' + status["version"])
    firmwareversion = int(''.join(status["version"].split()[0].split(".")))
    # read aggregate
    aggregate = read_aggregate(address, cookie)
    # read additional info if firmware supports
    if firmwareversion >= 20490:
        meters_site = read_site(address, cookie)
        get_counter_value_store(1).set(
            CounterState(
                imported=aggregate["site"]["energy_imported"],
                exported=aggregate["site"]["energy_exported"],
                power=aggregate["site"]["instant_power"],
                voltages=[
                    meters_site["0"]["Cached_readings"]["v_l" + str(phase) +
                                                        "n"]
                    for phase in range(1, 4)
                ],
                currents=[
                    meters_site["0"]["Cached_readings"]["i_" + phase +
                                                        "_current"]
                    for phase in ["a", "b", "c"]
                ],
                powers=[
                    meters_site["0"]["Cached_readings"]["real_power_" + phase]
                    for phase in ["a", "b", "c"]
                ]))
    else:
        get_counter_value_store(1).set(
            CounterState(imported=aggregate["site"]["energy_imported"],
                         exported=aggregate["site"]["energy_exported"],
                         power=aggregate["site"]["instant_power"]))
Beispiel #27
0
    def update(self):
        imported = self.__get_imported()
        exported = self.__get_exported()
        power = self.__get_power()
        if imported is None or exported is None:
            topic_str = "openWB/set/system/device/{}/component/{}/".format(
                self.__device_id, self.component_config.id)
            imported, exported = self.__sim_count.sim_count(
                power, topic=topic_str, data=self.simulation, prefix="bezug")

        counter_state = CounterState(
            currents=[getter() for getter in self.__get_currents],
            imported=imported,
            exported=exported,
            power=power)
        self.__store.set(counter_state)
Beispiel #28
0
    def __get_values_before_v123(self, unit: int) -> CounterState:
        with self.__tcp_client:
            power, exported, imported = self.__tcp_client.read_holding_registers(
                0x6, [modbus.ModbusDataType.INT_32] * 3, unit=unit)
            exported *= 10
            imported *= 10
            currents = [
                val / 230 for val in self.__tcp_client.read_holding_registers(
                    0x0000, [ModbusDataType.INT_32] * 3, unit=unit)
            ]

        counter_state = CounterState(currents=currents,
                                     imported=imported,
                                     exported=exported,
                                     power=power)
        return counter_state
Beispiel #29
0
    def update(self):
        unit = 1
        log.MainLogger().debug("Komponente " + self.component_config["name"] +
                               " auslesen.")
        with self.__tcp_client:
            voltages = [
                val / 10 for val in self.__tcp_client.read_input_registers(
                    0x00, [ModbusDataType.INT_32] * 3,
                    wordorder=Endian.Little,
                    unit=unit)
            ]
            powers = [
                val / 10 for val in self.__tcp_client.read_input_registers(
                    0x12, [ModbusDataType.INT_32] * 3,
                    wordorder=Endian.Little,
                    unit=unit)
            ]
            power = sum(powers)
            currents = [
                abs(val / 1000)
                for val in self.__tcp_client.read_input_registers(
                    0x0C, [ModbusDataType.INT_32] * 3,
                    wordorder=Endian.Little,
                    unit=unit)
            ]
            frequency = self.__tcp_client.read_input_registers(
                0x33, ModbusDataType.INT_16, unit=unit) / 10
            if frequency > 100:
                frequency = frequency / 10

        topic_str = "openWB/set/system/device/{}/component/{}/".format(
            self.__device_id, self.component_config["id"])
        imported, exported = self.__sim_count.sim_count(power,
                                                        topic=topic_str,
                                                        data=self.__simulation,
                                                        prefix="bezug")

        counter_state = CounterState(voltages=voltages,
                                     currents=currents,
                                     powers=powers,
                                     imported=imported,
                                     exported=exported,
                                     power=power,
                                     frequency=frequency)
        log.MainLogger().debug("Carlo Gavazzi Leistung[W]: " +
                               str(counter_state.power))
        self.__store.set(counter_state)
Beispiel #30
0
 def set_counter_state(self, power: float) -> None:
     topic_str = "openWB/set/system/device/{}/component/{}/".format(
         self.__device_id, self.component_config["id"]
     )
     imported, exported = self.__sim_count.sim_count(
         power,
         topic=topic_str,
         data=self.simulation,
         prefix="bezug"
     )
     counter_state = CounterState(
         imported=imported,
         exported=exported,
         power=power
     )
     log.MainLogger().debug("Powerdog Leistung[W]: " + str(counter_state.power))
     self.__store.set(counter_state)