From 6ee2ef1b7c562e27ff87997bc819d780313d9960 Mon Sep 17 00:00:00 2001 From: okaegi Date: Mon, 19 Dec 2022 10:41:13 +0100 Subject: [PATCH] =?UTF-8?q?Leistungsmessung=20=C3=BCber=20Lovato=20Z=C3=A4?= =?UTF-8?q?hler=20f=C3=BCr=20Smarthome-?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Neu wird der Lovato Zähler als separate Leistungsmessung unterstützt. Ebenso wurde auf static Types umgestellt. --- modules/smarthome/lovato/lovato.py | 24 +++++++ runs/mqttsub.py | 2 +- runs/usmarthome/smartbase.py | 68 +++++++++--------- runs/usmarthome/smartmeas.py | 107 ++++++++++++++++++----------- web/settings/smarthomeconfig.php | 9 +-- 5 files changed, 132 insertions(+), 78 deletions(-) create mode 100644 modules/smarthome/lovato/lovato.py diff --git a/modules/smarthome/lovato/lovato.py b/modules/smarthome/lovato/lovato.py new file mode 100644 index 0000000000..4d29419cbd --- /dev/null +++ b/modules/smarthome/lovato/lovato.py @@ -0,0 +1,24 @@ +#!/usr/bin/python3 +import sys +import struct +from smarthome.smartret import writeret +from pymodbus.client.sync import ModbusTcpClient +import codecs +devicenumber = int(sys.argv[1]) +seradd = str(sys.argv[2]) +sdmid = int(sys.argv[3]) +port = int(sys.argv[4]) +client = ModbusTcpClient(seradd, port=port) +# phasen watt +resp = client.read_input_registers(0x0013, 2, unit=sdmid) +all = format(resp.registers[0], '04x') + format(resp.registers[1], '04x') +finalw1 = int(struct.unpack('>i', codecs.decode(all, 'hex'))[0] / 100) +resp = client.read_input_registers(0x0015, 2, unit=sdmid) +all = format(resp.registers[0], '04x') + format(resp.registers[1], '04x') +finalw2 = int(struct.unpack('>i', codecs.decode(all, 'hex'))[0] / 100) +resp = client.read_input_registers(0x0017, 2, unit=sdmid) +all = format(resp.registers[0], '04x') + format(resp.registers[1], '04x') +finalw3 = int(struct.unpack('>i', codecs.decode(all, 'hex'))[0] / 100) +power = finalw1 + finalw2 + finalw3 +answer = '{"power":' + str(power) + ',"powerc":0}' +writeret(answer, devicenumber) diff --git a/runs/mqttsub.py b/runs/mqttsub.py index 7d9de345d5..fd223f8305 100755 --- a/runs/mqttsub.py +++ b/runs/mqttsub.py @@ -197,7 +197,7 @@ def on_message(client, userdata, msg): client.publish("openWB/config/get/SmartHome/Devices/"+str(devicenumb)+"/device_type", msg.payload.decode("utf-8"), qos=0, retain=True) if (( "openWB/config/set/SmartHome/Device" in msg.topic) and ("device_measureType" in msg.topic)): devicenumb=re.sub(r'\D', '', msg.topic) - validDeviceMeasureTypes = ['shelly','tasmota','http','mystrom','sdm630','we514','fronius','json','avm','mqtt','sdm120','smaem'] # 'pyt' is deprecated and will be removed! + validDeviceMeasureTypes = ['shelly','tasmota','http','mystrom','sdm630','lovato','we514','fronius','json','avm','mqtt','sdm120','smaem'] # 'pyt' is deprecated and will be removed! if ( 1 <= int(devicenumb) <= numberOfSupportedDevices and len(str(msg.payload.decode("utf-8"))) > 2): try: deviceMeasureTypeIndex = validDeviceMeasureTypes.index(msg.payload.decode("utf-8")) diff --git a/runs/usmarthome/smartbase.py b/runs/usmarthome/smartbase.py index 2a4709b783..51dbde3693 100644 --- a/runs/usmarthome/smartbase.py +++ b/runs/usmarthome/smartbase.py @@ -1,9 +1,10 @@ #!/usr/bin/python3 import time import os +from typing import Dict, Tuple, Any from usmarthome.global0 import log from usmarthome.smartbase0 import Sbase0 -from usmarthome.smartmeas import Slsdm630, Slsdm120, Slwe514, Slfronius +from usmarthome.smartmeas import Slsdm630, Sllovato, Slsdm120, Slwe514, Slfronius from usmarthome.smartmeas import Sljson, Slsmaem, Slshelly, Sltasmota, Slmqtt from usmarthome.smartmeas import Slhttp, Slavm, Slmystrom from usmarthome.smartbut import Sbshelly @@ -22,12 +23,12 @@ class Sbase(Sbase0): nureinschaltinsec = 0 eindevstatus = 0 - def __init__(self): + def __init__(self) -> None: # setting super().__init__() print('__init__ Sbase executed') - self.mqtt_param = {} - self.mqtt_param_del = {} + self.mqtt_param = {} # type: Dict[str, str] + self.mqtt_param_del = {} # type: Dict[str, str] self.device_name = 'none' self.devstatus = 10 # (10 = ueberschuss gesteuert oder manual, @@ -53,7 +54,7 @@ def __init__(self): self.newdevice_manual = 0 self.newdevice_manual_control = 0 self.device_type = 'none' - self._smart_param = {} + self._smart_param = {} # type: Dict[str, str] self._uberschussoffset = 0 self._uberschuss = 0 self.device_canswitch = 0 @@ -89,8 +90,8 @@ def __init__(self): self._device_pbtype = 'none' self._device_lambdaueb = 'UP' self._old_pbtype = 'none' - self._mydevicepb = 'none' - self._oldrelais = '2' + self._mydevicepb = 'none' # type: Any + self._oldrelais = 2 self._oldwatt = 0 self._device_chan = 0 self._device_updatesec = 0 @@ -123,12 +124,13 @@ def __init__(self): self.device_setauto = 0 self.gruppe = 'none' self.btchange = 0 + self._mydevicemeasure = 'none' # type: Any - def __del__(self): + def __del__(self) -> None: print('__del__ Sbase executed ') - def prewatt(self, uberschuss, uberschussoffset): + def prewatt(self, uberschuss: int, uberschussoffset: int) -> None: self._uberschuss = uberschuss self._uberschussoffset = uberschussoffset if (self._deviceconfiguredold == "9") and (self._deviceconfigured == @@ -154,7 +156,7 @@ def prewatt(self, uberschuss, uberschussoffset): # prepare end self.getueb() - def postwatt(self): + def postwatt(self) -> None: (self.newwatt, self.newwattk) = self.sepwatt(self.newwatt, self.newwattk) # bei reiner Leistungsmessung relais nur nach Watt setzten @@ -168,7 +170,7 @@ def postwatt(self): self.relais = 0 self.mqtt_param = {} pref = 'openWB/SmartHome/Devices/' + str(self.device_nummer) + '/' - self.mqtt_param[pref + 'RelayStatus'] = self.relais + self.mqtt_param[pref + 'RelayStatus'] = str(self.relais) if (self.c_mantime_f == 'Y') and (self.device_manual != 1): # nach Ausschalten manueller Modus mindestens 30 Sek + # max( ausschaltverzögerung,mindeseinschaltdauer @@ -226,7 +228,7 @@ def postwatt(self): else: self.c_oldstampeinschaltdauer = 0 self.c_oldstampeinschaltdauer_f = 'N' - self.mqtt_param[pref + 'RunningTimeToday'] = self.runningtime + self.mqtt_param[pref + 'RunningTimeToday'] = str(self.runningtime) # Einschaltzeit des Relais setzen if (self._oldrelais == 0): if (self.relais == 1): @@ -242,9 +244,9 @@ def postwatt(self): self.mqtt_param[pref + 'TemperatureSensor1'] = self.temp1 if (self.device_temperatur_configured > 2): self.mqtt_param[pref + 'TemperatureSensor2'] = self.temp2 - self.mqtt_param[pref + 'Watt'] = self._oldwatt - self.mqtt_param[pref + 'Wh'] = self._wh - self.mqtt_param[pref + 'WHImported_temp'] = self._wpos + self.mqtt_param[pref + 'Watt'] = str(self._oldwatt) + self.mqtt_param[pref + 'Wh'] = str(self._wh) + self.mqtt_param[pref + 'WHImported_temp'] = str(self._wpos) self.mqtt_param[pref + 'oncountnor'] = self.oncountnor self.mqtt_param[pref + 'OnCntStandby'] = self.oncntstandby # nur bei Status 10 on status mitnehmen @@ -252,7 +254,7 @@ def postwatt(self): sendstatus = self.relais + self.devstatus else: sendstatus = self.devstatus - self.mqtt_param[pref + 'Status'] = sendstatus + self.mqtt_param[pref + 'Status'] = str(sendstatus) if (self.gruppe == 'A'): Sbase.ausschaltwatt = Sbase.ausschaltwatt + self._oldwatt elif (self.gruppe == 'E'): @@ -260,7 +262,7 @@ def postwatt(self): Sbase.einrelais = 1 Sbase.eindevstatus = max(Sbase.eindevstatus, self.devstatus) - def updatepar(self, input_param): + def updatepar(self, input_param: Dict[str, str]) -> None: self._smart_param = input_param.copy() self.device_nummer = int(self._smart_param.get('device_nummer', '0')) for key, value in self._smart_param.items(): @@ -390,7 +392,7 @@ def updatepar(self, input_param): " " + value) else: log.info("(" + str(self.device_nummer) + ") " - + __class__.__name__ + " überlesen " + key + + + "Sbase überlesen " + key + " " + value) self._first_run = 0 pref = 'openWB/SmartHome/Devices/' + str(self.device_nummer) + '/' @@ -451,6 +453,8 @@ def updatepar(self, input_param): del self._mydevicemeasure if (self._device_measuretype == 'sdm630'): self._mydevicemeasure = Slsdm630() + elif (self._device_measuretype == 'lovato'): + self._mydevicemeasure = Sllovato() elif (self._device_measuretype == 'sdm120'): self._mydevicemeasure = Slsdm120() elif (self._device_measuretype == 'we514'): @@ -494,14 +498,14 @@ def updatepar(self, input_param): str(self.device_nummer), 'w') as f: f.write(str(self.device_homeconsumtion)) - def getueb(self): + def getueb(self) -> None: # (1 = mit Speicher, 2 = mit offset , 0 = manual eingeschaltet) if (self.ueberschussberechnung == 2): self.devuberschuss = self._uberschussoffset else: self.devuberschuss = self._uberschuss - def preturn(self, zustand, ueberschussberechnung, updatecnt): + def preturn(self, zustand: int, ueberschussberechnung: int, updatecnt: int) -> None: self.ueberschussberechnung = ueberschussberechnung with open(self._basePath+'/ramdisk/device' + str(self.device_nummer) + '_req_relais', 'w') as f: @@ -519,7 +523,7 @@ def preturn(self, zustand, ueberschussberechnung, updatecnt): self._c_eintime_f = 'Y' self._c_eintime = int(time.time()) - def sepwatt(self, newwatt, newwattk): + def sepwatt(self, newwatt: int, newwattk: int) -> Tuple[int, int]: if (self._device_differentmeasurement == 0): return newwatt, newwattk # ueberschuss übertragen @@ -529,7 +533,7 @@ def sepwatt(self, newwatt, newwattk): self.newwattk = self._mydevicemeasure.newwattk return self.newwatt, self.newwattk - def conditions(self, speichersoc): + def conditions(self, speichersoc: int) -> None: # do not do anything in case none type or can switch = no # or device manuam mode if ((self.device_canswitch == 0) or @@ -550,8 +554,8 @@ def conditions(self, speichersoc): work_ausschaltschwelle = self._device_ausschaltschwelle work_ausschaltverzoegerung = self._device_ausschaltverzoegerung local_time = datetime.now(timezone.utc).astimezone() - localhour = int(local_time.strftime(format="%H")) - localminute = int(local_time.strftime(format="%M")) + localhour = int(local_time.strftime("%H")) + localminute = int(local_time.strftime("%M")) localinsec = int((localhour * 60 * 60) + (localminute * 60)) if (localinsec < Sbase.nureinschaltinsec) and (Sbase.eindevices > 0): log.info("(" + str(self.device_nummer) + ") " + @@ -966,8 +970,8 @@ def conditions(self, speichersoc): self._c_ausverz_f = 'N' # rechne Zeit exclusive einschaltgruppe local_time = datetime.now(timezone.utc).astimezone() - localh = int(local_time.strftime(format="%H")) - localminute = int(local_time.strftime(format="%M")) + localh = int(local_time.strftime("%H")) + localminute = int(local_time.strftime("%M")) localinsec = int((localh * 60 * 60) + (localminute * 60)) Sbase.nureinschaltinsec = localinsec + Sbase.einverz return @@ -1132,7 +1136,7 @@ def conditions(self, speichersoc): self._c_einverz_f = 'N' self._c_ausverz_f = 'N' - def simcount(self, watt2, pref, importfn, exportfn, nummer, wattks): + def simcount(self, watt2: int, pref: str, importfn: str, exportfn: str, nummer: str, wattks: int) -> None: # Zaehler mitgeliefert in WH , zurueckrechnen fuer simcount if wattks > 0: wattposkh = wattks @@ -1191,8 +1195,8 @@ def simcount(self, watt2, pref, importfn, exportfn, nummer, wattks): wattnegh = wattnegh + watt1 else: wattposh = wattposh + watt1 - wattposkh = wattposh/3600 - wattnegkh = (wattnegh*-1)/3600 + wattposkh = int(wattposh/3600) + wattnegkh = int((wattnegh*-1)/3600) with open(self._basePath+'/ramdisk/'+pref+'watt0pos', 'w') as f: f.write(str(wattposh)) self._wpos = wattposh @@ -1210,17 +1214,17 @@ def simcount(self, watt2, pref, importfn, exportfn, nummer, wattks): with open(self._basePath+'/ramdisk/'+pref+'wh0', 'w') as f: f.write(str(watt2)) - def getwatt(self, uberschuss, uberschussoffset): + def getwatt(self, uberschuss: int, uberschussoffset: int) -> None: self.prewatt(uberschuss, uberschussoffset) self.newwatt = 0 self.newwattk = 0 self.relais = 0 self.postwatt() - def turndevicerelais(self, zustand, ueberschussberechnung, updatecnt): + def turndevicerelais(self, zustand: int, ueberschussberechnung: int, updatecnt: int) -> None: pass - def updatebutton(self): + def updatebutton(self) -> None: self.newdevice_manual = self.device_manual self.newdevice_manual_control = self.device_manual_control self.btchange = 0 diff --git a/runs/usmarthome/smartmeas.py b/runs/usmarthome/smartmeas.py index a2304cab5b..5302f5102f 100644 --- a/runs/usmarthome/smartmeas.py +++ b/runs/usmarthome/smartmeas.py @@ -1,10 +1,11 @@ from usmarthome.smartbase0 import Sbase0 from usmarthome.global0 import log +from typing import Dict, Tuple import subprocess class Slbase(Sbase0): - def __init__(self): + def __init__(self) -> None: # # setting super().__init__() @@ -19,7 +20,7 @@ def __init__(self): self.newwatt = 0 self.newwattk = 0 self.relais = 0 - self._smart_param = {} + self._smart_param = {} # type: Dict[str, str] self._device_differentmeasureoment = 0 self._device_configured = '0' self._device_ip = 'none' @@ -45,7 +46,7 @@ def __init__(self): self._device_measchan = 0 self._device_chan = 0 - def updatepar(self, input_param): + def updatepar(self, input_param: Dict[str, str]) -> None: self._smart_param = input_param.copy() self.device_nummer = int(self._smart_param.get('device_nummer', '0')) for key, value in self._smart_param.items(): @@ -127,27 +128,27 @@ def updatepar(self, input_param): self._device_stateurl = value else: log.info("(" + str(self.device_nummer) + ") " - + __class__.__name__ + " überlesen " + key + + + "Slbase überlesen " + key + " " + value) - def __del__(self): + def __del__(self) -> None: print('__del__ Slbase executed ') class Slmqtt(Slbase): - def __init__(self): + def __init__(self) -> None: # setting super().__init__() print('__init__ Slmqtt excuted') - def getwattread(self): + def getwattread(self) -> None: self._watt(self._device_ip) - def sepwattread(self): + def sepwattread(self) -> Tuple[int, int]: self._watt(self._device_measureip) return self.newwatt, self.newwattk - def _watt(self, ip): + def _watt(self, ip: str) -> None: argumentList = ['python3', self._prefixpy + 'mqtt/watt.py', str(self.device_nummer), str(ip), str(self.devuberschuss)] @@ -164,19 +165,19 @@ def _watt(self, ip): class Slshelly(Slbase): - def __init__(self): + def __init__(self) -> None: # setting super().__init__() print('__init__ Slshelly excuted') - def getwattread(self): + def getwattread(self) -> None: self._watt(self._device_ip, self._device_chan) - def sepwattread(self): + def sepwattread(self) -> Tuple[int, int]: self._watt(self._device_measureip, self._device_measchan) return self.newwatt, self.newwattk - def _watt(self, ip, chan): + def _watt(self, ip: str, chan: int) -> None: argumentList = ['python3', self._prefixpy + 'shelly/watt.py', str(self.device_nummer), str(ip), '0', str(chan)] @@ -214,24 +215,24 @@ def _watt(self, ip, chan): class Slavm(Slbase): - def __init__(self): + def __init__(self) -> None: # setting super().__init__() print('__init__ Slavm excuted') - def getwattread(self): + def getwattread(self) -> None: self._watt(self._device_ip, self._device_actor, self._device_username, self._device_password) - def sepwattread(self): + def sepwattread(self) -> Tuple[int, int]: self._watt(self._device_measureip, self._device_measureavmactor, self._device_measureavmusername, self._device_measureavmpassword) return self.newwatt, self.newwattk - def _watt(self, ip, act, user, pw): + def _watt(self, ip: str, act: str, user: str, pw: str) -> None: argumentList = ['python3', self._prefixpy + 'avmhomeautomation/watt.py', str(self.device_nummer), str(ip), @@ -250,19 +251,19 @@ def _watt(self, ip, act, user, pw): class Sltasmota(Slbase): - def __init__(self): + def __init__(self) -> None: # setting super().__init__() print('__init__ Sltasmota excuted') - def getwattread(self): + def getwattread(self) -> None: self._watt(self._device_ip) - def sepwattread(self): + def sepwattread(self) -> Tuple[int, int]: self._watt(self._device_measureip) return self.newwatt, self.newwattk - def _watt(self, ip): + def _watt(self, ip: str) -> None: argumentList = ['python3', self._prefixpy + 'tasmota/watt.py', str(self.device_nummer), str(ip), '0'] try: @@ -278,21 +279,21 @@ def _watt(self, ip): class Slhttp(Slbase): - def __init__(self): + def __init__(self) -> None: # setting super().__init__() print('__init__ Slhttp excuted') - def getwattread(self): + def getwattread(self) -> None: self._watt(self._device_leistungurl, 'none', self._device_stateurl) - def sepwattread(self): + def sepwattread(self) -> Tuple[int, int]: self._watt(self._device_measureurl, self._device_measureurlc, 'none') return self.newwatt, self.newwattk - def _watt(self, url, urlc, urls): + def _watt(self, url: str, urlc: str, urls: str) -> None: argumentList = ['python3', self._prefixpy + 'http/watt.py', str(self.device_nummer), '0', str(self.devuberschuss), url, urlc, @@ -312,19 +313,19 @@ def _watt(self, url, urlc, urls): class Slmystrom(Slbase): - def __init__(self): + def __init__(self) -> None: # setting super().__init__() print('__init__ Slmystrom excuted') - def getwattread(self): + def getwattread(self) -> None: self._watt(self._device_ip) - def sepwattread(self): + def sepwattread(self) -> Tuple[int, int]: self._watt(self._device_measureip) return self.newwatt, self.newwattk - def _watt(self, ip): + def _watt(self, ip: str) -> None: argumentList = ['python3', self._prefixpy + 'mystrom/watt.py', str(self.device_nummer), str(ip), '0'] try: @@ -347,12 +348,12 @@ def _watt(self, ip): class Slsmaem(Slbase): - def __init__(self): + def __init__(self) -> None: # setting super().__init__() print('__init__ Slsmaem excuted') - def sepwattread(self): + def sepwattread(self) -> Tuple[int, int]: argumentList = ['python3', self._prefixpy + 'smaem/watt.py', str(self.device_nummer), str(self._device_measureip), str(self._device_measuresmaser), @@ -371,12 +372,12 @@ def sepwattread(self): class Slwe514(Slbase): - def __init__(self): + def __init__(self) -> None: # setting super().__init__() print('__init__ Slwe514 excuted') - def sepwattread(self): + def sepwattread(self) -> Tuple[int, int]: argumentList = ['python3', self._prefixpy + 'we514/watt.py', str(self.device_nummer), str(self._device_measureip), str(self._device_measureid)] @@ -394,12 +395,12 @@ def sepwattread(self): class Sljson(Slbase): - def __init__(self): + def __init__(self) -> None: # setting super().__init__() print('__init__ Sljson excuted') - def sepwattread(self): + def sepwattread(self) -> Tuple[int, int]: argumentList = ['python3', self._prefixpy + 'json/watt.py', str(self.device_nummer), self._device_measurejsonurl, @@ -418,12 +419,12 @@ def sepwattread(self): class Slfronius(Slbase): - def __init__(self): + def __init__(self) -> None: # setting super().__init__() print('__init__ Slfronius excuted') - def sepwattread(self): + def sepwattread(self) -> Tuple[int, int]: argumentList = ['python3', self._prefixpy + 'fronius/watt.py', str(self.device_nummer), str(self._device_measureip), str(self._device_measureid)] @@ -440,13 +441,37 @@ def sepwattread(self): return self.newwatt, self.newwattk +class Sllovato(Slbase): + def __init__(self) -> None: + # setting + super().__init__() + print('__init__ Sllovato excuted') + + def sepwattread(self) -> Tuple[int, int]: + argumentList = ['python3', self._prefixpy + 'lovato/lovato.py', + str(self.device_nummer), str(self._device_measureip), + str(self._device_measureid), + str(self._device_measureportsdm)] + try: + proc = subprocess.Popen(argumentList) + proc.communicate() + answer = self.readret() + self.newwatt = int(answer['power']) + self.newwattk = int(answer['powerc']) + except Exception as e1: + log.warning("Leistungsmessung %s %d %s Fehlermeldung: %s " + % ('Lovato ', self.device_nummer, + str(self._device_measureip), str(e1))) + return self.newwatt, self.newwattk + + class Slsdm630(Slbase): - def __init__(self): + def __init__(self) -> None: # setting super().__init__() print('__init__ Slsdm630 excuted') - def sepwattread(self): + def sepwattread(self) -> Tuple[int, int]: argumentList = ['python3', self._prefixpy + 'sdm630/sdm630.py', str(self.device_nummer), str(self._device_measureip), str(self._device_measureid), @@ -465,12 +490,12 @@ def sepwattread(self): class Slsdm120(Slbase): - def __init__(self): + def __init__(self) -> None: # setting super().__init__() print('__init__ Slsdm120 excuted') - def sepwattread(self): + def sepwattread(self) -> Tuple[int, int]: argumentList = ['python3', self._prefixpy + 'sdm120/sdm120.py', str(self.device_nummer), str(self._device_measureip), str(self._device_measureid), diff --git a/web/settings/smarthomeconfig.php b/web/settings/smarthomeconfig.php index f21d4949ed..3a3f94c0ae 100644 --- a/web/settings/smarthomeconfig.php +++ b/web/settings/smarthomeconfig.php @@ -792,10 +792,11 @@ + -
+
@@ -816,19 +817,19 @@
-
+
-
+
Standardeinstellungen verschiedener Geräte:
- SDM630: 8899
+ SDM630/Lovato: 8899
Elgris: 502