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
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)
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)
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)
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)
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)
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)
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")
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)
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, )
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)
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)
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)
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)
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
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)
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)
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)
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)
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)
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)
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")
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)
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, )
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)
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"]))
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)
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
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)
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)