Script für gleitenden Mittelwert

Homematic-, TCL- und Shell-Script, Toolchain, C, etc.

Moderator: Co-Administratoren

MichaelN
Beiträge: 9534
Registriert: 27.04.2020, 10:34
System: CCU
Hat sich bedankt: 692 Mal
Danksagung erhalten: 1604 Mal

Re: Script für gleitenden Mittelwert

Beitrag von MichaelN » 08.05.2020, 12:27

Ich habe nich tviel Ahnung, aber das sieht irgendwie doppelt gemoppelt aus. Keine Ahnung was dabei raus kommt:
GetObject("BidCos-RF.MEQ1600666:1.TEMPERATURE").DPByHssDP("TEMPERATURE")

Da ich auch gerade eine solche Aufgabe habe und mir das etwas zu durcheinandern war, habe ich das Skript einmal etwas aufgehübscht. In den Kommentaren ist eigentlich alles erklärt. Wichtig: in der ursprünglichen Version wurde der Sensorname genutzt und der auch noch mit Suffix erweitert. Habe ich alles rausgeworfen. Jetzt wird nur noch ein ordentlicher Gerätename mit allem drum und dran benötigt.

Oder hier: Link mein komplett selbst-konfigurierendes Skript

Die Variable für die Messwertliste muss auch nicht mehr vorher befüllt werden (angelegt aber schon), das wird dann beim ersten Durchlauf automatisch erledigt.

Code: Alles auswählen

! gleitender Mittelwert über n Werte
! Programm muß zyklisch per Zeitmodul oder bei Aktualisierung des Gerätes ausgelöst werden
! Die benötigten Systemvariablen müssen vorher angelegt werden

! Name der Systemvariable, Datentyp Zahl, fuer den gleitenden Mittelwert
string VarName = "Temp_Licht_Mittelwert";
! Gerät angeben von dem der Messwert kommen soll inkl. kompletter Schnittstelle, Kanal, DP z.B. "BidCos-RF.ABC1234567:1.TEMPERATURE" ODER Systemvariable die gemittelt werden soll "SV_Test"
string Geraet = "BidCos-RF.ABC1234567:1.TEMPERATURE";
! Name der Systemvariablen als Werteliste, die als Speicher fuer die interne Berechnung dient
string Liste = "Mittelwertbildung";

! Konstante: Anzahl Werte in der Liste
integer n = 5;

! Lokale Variablen
string  list;    ! Meßwertliste
integer len;     ! Element-Länge
real    s = 0.0; ! Summe

! Werte einlesen und verschieben
list = dom.GetObject(Liste).Value();
! prüfen ob die Variable schon korrekt befüllt wurde
if (list.Find(",") == -1)
{
	! NEIN, Liste befüllen
	string x = dom.GetObject(Geraet).Value().ToString(1);
	string list = x;
	integer i = 1;
	while(i < n)
	{list = list#","#x;
	 i = i + 1;
	}
}
! aeltesten Wert rauswerfen
len = list.StrValueByIndex(",",0).Length() + 1;
list = list.Substr(len, list.Length() - len);

! Will man statt einem Gerät eine Variable auswerten, dann: dom.GetObject(Geraet).State() hier einsetzen
list = list#","#dom.GetObject(Geraet).Value().ToString(1);
dom.GetObject(Liste).State(list);

string summand;
foreach(summand, list.Split(","))
{s = s + summand.ToFloat();
}

! Mittelwert in Systemvariable schreiben
dom.GetObject(VarName).State(s / n);
Zuletzt geändert von MichaelN am 07.01.2023, 17:54, insgesamt 4-mal geändert.
LG, Michael.

Wenn du eine App zur Bedienung brauchst, dann hast du kein Smarthome.

Wettervorhersage über AccuWeather oder OpenWeatherMap+++ Rollladensteuerung 2.0 +++ JSON-API-Ausgaben auswerten +++ undokumentierte Skript-Befehle und Debugging-Tipps +++

Stefan0815
Beiträge: 169
Registriert: 16.04.2019, 15:15
Hat sich bedankt: 9 Mal
Danksagung erhalten: 10 Mal

Re: Script für gleitenden Mittelwert

Beitrag von Stefan0815 » 08.05.2020, 22:27

Sieh Dir mal das: viewtopic.php?f=43&t=58591 an. Dort findest Du ein Script zur Berechnung eines zeitlich beliebig definierbaren Mittelwertes (also gleitend), des reverse oder regulär gewichteten Mittelwertes, der Varianz und der Standardabweichung der Messwerte inkl. der nötigen Datensammlung in genau einer System-Variable. Funktioniert mit beliebigen Umweltdaten und auch noch mit einigen hundert Werten.

Viele Grüße,
bytelander
Viele Grüße
Stefan

MichaelN
Beiträge: 9534
Registriert: 27.04.2020, 10:34
System: CCU
Hat sich bedankt: 692 Mal
Danksagung erhalten: 1604 Mal

Re: Script für gleitenden Mittelwert

Beitrag von MichaelN » 09.05.2020, 23:07

Holla die Waldfee - aber nicht jeder braucht so ein Universal-Skript. Ich habe es jetzt noch einfacher gelöst: mit CuxD

In CuxD ein Universal Wrapper Device anlegen mit der Funktion Transform
In der WebUI bei der Gerätekonfiguration unter HMSERIAL die Seriennummer:Kanal des Sensors einstellen, unter HMDATAPT den Datenpunkt z.B. TEMPERATURE, in den Kanalparametern kann man den DATAPT noch einen Namen geben - soweit ich das sehe wird da der ursprüngliche Wert durchgereicht und unter HISTORY BUFFER stellt man ein wieviele Messwerte gemittelt werden sollen.

Anschließend kann man statt auf den Kanal des echten Sensors auf die Kanäle dieses Wrapper Device zugreifen und Mittelwert, Median, Min, Max abfragen...
Unbenannt2.JPG
Unbenannt.jpg
LG, Michael.

Wenn du eine App zur Bedienung brauchst, dann hast du kein Smarthome.

Wettervorhersage über AccuWeather oder OpenWeatherMap+++ Rollladensteuerung 2.0 +++ JSON-API-Ausgaben auswerten +++ undokumentierte Skript-Befehle und Debugging-Tipps +++

Stefan0815
Beiträge: 169
Registriert: 16.04.2019, 15:15
Hat sich bedankt: 9 Mal
Danksagung erhalten: 10 Mal

Re: Script für gleitenden Mittelwert

Beitrag von Stefan0815 » 10.05.2020, 05:12

MichaelN hat geschrieben:
09.05.2020, 23:07
Holla die Waldfee - aber nicht jeder braucht so ein Universal-Skript. Ich habe es jetzt noch einfacher gelöst: mit CuxD

In CuxD ein Universal Wrapper Device anlegen mit der Funktion Transform
In der WebUI bei der Gerätekonfiguration unter HMSERIAL die Seriennummer:Kanal des Sensors einstellen, unter HMDATAPT den Datenpunkt z.B. TEMPERATURE, in den Kanalparametern kann man den DATAPT noch einen Namen geben - soweit ich das sehe wird da der ursprüngliche Wert durchgereicht und unter HISTORY BUFFER stellt man ein wieviele Messwerte gemittelt werden sollen.

Anschließend kann man statt auf den Kanal des echten Sensors auf die Kanäle dieses Wrapper Device zugreifen und Mittelwert, Median, Min, Max abfragen...

Unbenannt2.JPG

Unbenannt.jpg
....wenn man keinen zeitlichen Bezug der Daten benötigt, eine echt coole und simple Lösung. Kannte ich noch nicht. Und zum Thema "braucht so ein Universal-Skript": Dachte ich auch immer. Dann kam die Herausforderung einer halbwegs brauchbaren Steuerung der Markisen nach Wind. Zwischenzeitlich laufen bei mir alle einfachen Hysteresen (Helligkeit - Sonne ja/nein, Temperaturen innen/außen - Wärme/Hitze) über gewichtete Mittelwerte mit unterschiedlichen Zeitabschnitten. Damit kann man die Kurven beliebig glätten. Z.B. Temperatur MIN/MAX-gleitender Durchschnitt der letzten 10 Tage um zentral die Profile der Heizungsgruppen zwischen Sommer- und Winterbetrieb nach Temperatur zu schalten. Wenn man diese Mittelwerte dann als Systemvariable (Zahlenwert) ablegt, kann man sich das graphisch dann wunderbar in CCU-Historian im Jahresverlauf ansehen.
Viele Grüße
Stefan

Belly
Beiträge: 22
Registriert: 24.06.2020, 08:07
System: CCU
Hat sich bedankt: 1 Mal

Re: Script für gleitenden Mittelwert

Beitrag von Belly » 01.07.2020, 18:04

Hallo zusammen,

ich wollte hier kurz meine Lösungen posten, weil ich alle Posts in diesem Thread durchlesen musste, um die richtigen zu finden :)

Gleitender Mittelwert

Voraussetzungen:
  • Systemvariable: Zahl "Helligkeit.Durchschnitt" von 0 bis 1.000.000 (Lux)
  • "xxxxxxxxxxxxxx" durch Seriennummer des abzufragenden Geräts ersetzen
  • ggf. "ILLUMINATION" durch abzufragenden Parameter ersetzen (z. B. TEMPERATURE)

Code: Alles auswählen

object averageObject = dom.GetObject("Helligkeit.Durchschnitt");
real current = dom.GetObject("HmIP-RF.xxxxxxxxxxxxxx:1.ILLUMINATION").Value();
real n = 5.0;
real average = (averageObject.Value() * (n - 1) / n) + (current / n);
averageObject.State(average);

WriteLine(average); ! Hier könnte eine Meldung via Messenger stehen
Vorteil: Code ist schön übersichtlich und es wird nur eine Systemvariable benötigt. Die Zahlenreihen werden aber nur geglättet, es ist kein "echter" Mittelwert.

Mittelwert via Werteliste

Voraussetzungen:
  • Systemvariable: Zahl "Helligkeit.Durchschnitt" von 0 bis 1.000.000 (Lux)
  • Systemvariable: Zeichenkette "Helligkeit.Werte"
  • "xxxxxxxxxxxxxx" durch Seriennummer des abzufragenden Geräts ersetzen
  • ggf. "ILLUMINATION" durch abzufragenden Parameter ersetzen (z. B. TEMPERATURE)

Code: Alles auswählen

object averageObject = dom.GetObject("Helligkeit.Durchschnitt");
object valueList = dom.GetObject("Helligkeit.Werte");
real currentValue = dom.GetObject("HmIP-RF.xxxxxxxxxxxxxx:1.ILLUMINATION").Value();

string delimiter = "|"; ! Trennzeichen der Werteliste
integer digits = 0; ! Anzahl Nachkommastellen in der Werteliste

string list = valueList.Value();
if (list == "???") {
  string initValue = currentValue.ToString(digits);
  list = initValue # delimiter # initValue # delimiter # initValue # delimiter # initValue # delimiter # initValue;
}

real sum = currentValue;
integer count = 1;
string each;
foreach(each, list.Split(delimiter)) {
  sum = sum + each.ToFloat();
  count = count + 1;
}

real average = sum / count;
averageObject.State(average);
valueList.State(list.Substr(list.Find(delimiter) + 1) # delimiter # currentValue.ToString(digits));

var message = "Aktuelle Helligkeit: " # currentValue.ToString(0) # " Lux. Neuer Durchschnitt: " # average.ToString(0) # " Lux.";
WriteLine(message); ! Hier könnte eine Meldung via Messenger stehen
Vorteil: Echter Mittelwert über n Werte. Das n bestimmt sich dabei automatisch aus der Anzahl der Werte in der Werteliste + 1 für den aktuellen Wert. Die Werteliste wird beim ersten Mal mit 5 Werten initialisiert, das kann natürlich angepasst werden.

MichaelN
Beiträge: 9534
Registriert: 27.04.2020, 10:34
System: CCU
Hat sich bedankt: 692 Mal
Danksagung erhalten: 1604 Mal

Re: Script für gleitenden Mittelwert

Beitrag von MichaelN » 01.07.2020, 18:45

Oder Mittelwert per CUxD_Device:

viewtopic.php?f=19&t=59404#p588548

Vorteil:
  • echter Mittelwert ohne komplexen Code
  • wahlweise Mittelwert oder Median (oder MIN oder MAX)
  • wenn man den Mittelwert eines Datenpunktes auswerten will, geht es sogar ganz ohne (periodische aufzurufendes) Skript
  • als Auslöser in WebUI Programmen verwendbar
Nachteil:
  • man muss CUxD installieren (wobei das ja eher ein Vorteil ist :lol: )
Zuletzt geändert von MichaelN am 19.07.2020, 13:23, insgesamt 2-mal geändert.
LG, Michael.

Wenn du eine App zur Bedienung brauchst, dann hast du kein Smarthome.

Wettervorhersage über AccuWeather oder OpenWeatherMap+++ Rollladensteuerung 2.0 +++ JSON-API-Ausgaben auswerten +++ undokumentierte Skript-Befehle und Debugging-Tipps +++

mading
Beiträge: 31
Registriert: 13.03.2020, 08:45
System: CCU
Hat sich bedankt: 4 Mal
Danksagung erhalten: 1 Mal

Re: Script für gleitenden Mittelwert

Beitrag von mading » 18.07.2020, 10:12

@ Belly würdest du dann in Homematic ein Programm alle 5 min laufen lassen, damit die Werte geschrieben werden - verstehe ich das richtig?

mading
Beiträge: 31
Registriert: 13.03.2020, 08:45
System: CCU
Hat sich bedankt: 4 Mal
Danksagung erhalten: 1 Mal

Re: Script für gleitenden Mittelwert

Beitrag von mading » 18.07.2020, 10:16

MichaelN hat geschrieben:
09.05.2020, 23:07
Holla die Waldfee - aber nicht jeder braucht so ein Universal-Skript. Ich habe es jetzt noch einfacher gelöst: mit CuxD

In CuxD ein Universal Wrapper Device anlegen mit der Funktion Transform
In der WebUI bei der Gerätekonfiguration unter HMSERIAL die Seriennummer:Kanal des Sensors einstellen, unter HMDATAPT den Datenpunkt z.B. TEMPERATURE, in den Kanalparametern kann man den DATAPT noch einen Namen geben - soweit ich das sehe wird da der ursprüngliche Wert durchgereicht und unter HISTORY BUFFER stellt man ein wieviele Messwerte gemittelt werden sollen.

Anschließend kann man statt auf den Kanal des echten Sensors auf die Kanäle dieses Wrapper Device zugreifen und Mittelwert, Median, Min, Max abfragen...
Hallo Michael,

Ich habe das cuxd device angelegt und konfiguriert. Leider bekomme ich über

var a = dom.GetObject("DEVICE.CUX9000001:1.ILLUMINATION").Value();

Keine Werte.

Muss im Cuxd Device oben der gerätetyp, bei mir für die wetterstation hmip-rf davor stehen oder nur serial:kanal?

Welche Variable kann ich ansprechen? Die obere aus dem cuxd device HMDATAPT oder die untere WRAPPER|DATAPT? Beide liefern bei mir leider keine Werte mit dem Skriptschnipsel oben.

Wäre über einen „Schubser“ dankbar.

MichaelN
Beiträge: 9534
Registriert: 27.04.2020, 10:34
System: CCU
Hat sich bedankt: 692 Mal
Danksagung erhalten: 1604 Mal

Re: Script für gleitenden Mittelwert

Beitrag von MichaelN » 18.07.2020, 10:21

MEAN, MEDIAN, MIN oder MAX wäre sinnvoll. Um den ursprünglichen Wert abzufragen braucht man ja kein cuxd device. Übrigens habe ich nur einen Beitrag über deinem einen link zu einer bebilderten Anleitung verlinkt
Zuletzt geändert von MichaelN am 19.07.2020, 13:11, insgesamt 1-mal geändert.
LG, Michael.

Wenn du eine App zur Bedienung brauchst, dann hast du kein Smarthome.

Wettervorhersage über AccuWeather oder OpenWeatherMap+++ Rollladensteuerung 2.0 +++ JSON-API-Ausgaben auswerten +++ undokumentierte Skript-Befehle und Debugging-Tipps +++

dtp
Beiträge: 10655
Registriert: 21.09.2012, 08:09
System: CCU
Wohnort: Stuttgart
Hat sich bedankt: 320 Mal
Danksagung erhalten: 501 Mal

Re: Script für gleitenden Mittelwert

Beitrag von dtp » 19.07.2020, 13:10

Ihr könnt ja mal dieses Skript testen. Dazu eine Systemvariable vom Typ Zeichenkette für die Liste aller zu berücksichtigenden Werte und eine vom Typ Zahl für den daraus berechneten Mittelwert anlegen.

Mit der lokalen Variablen "numOfValues" legt man fest, über wieviele Werte gemittelt werden soll.

Code: Alles auswählen

! Name von Kanal 1 des Helligkeitssensors
string channel = "xxx";

! Namen der Systemvariablen
string svValuesList = "Liste der Helligkeitswerte";
string svMean = "Helligkeitsmittelwert";

! Anzahl der zu berücksichtigenden Werte für die Mittelwertbildung
integer numOfValues = 10;

string valuesList = "";
integer value; integer mean; integer sum; integer cnt = 0;

foreach(value, (dom.GetObject(ID_CHANNELS).Get(channel)).DPByHssDP("ILLUMINATION").Value()#"\t"#(dom.GetObject(ID_SYSTEM_VARIABLES).Get(svValuesList)).Value()){
  sum = sum + value.ToInteger();
  valuesList = valuesList#"\t"#value;
  cnt = cnt + 1;
  if(cnt == numOfValues){break;}
}
mean = sum / cnt;

(dom.GetObject(ID_SYSTEM_VARIABLES).Get(svValuesList)).State(valuesList);
(dom.GetObject(ID_SYSTEM_VARIABLES).Get(svMean)).State(mean);
Zuletzt geändert von dtp am 20.07.2020, 07:27, insgesamt 1-mal geändert.
CCU3 mit stets aktueller FW und den Addons "CUxD" und "Programmedrucken", ioBroker auf Synology DiskStation DS718+ im Docker-Container;
einige Projekte: zentrales Push-Nachrichten-Programm zPNP, DoorPi-Videotürsprechanlage, An- und Abwesenheitsdetektion per Haustürschloss, zentrales Programm zur Steuerung von Beschattungsgeräten zBSP.

Antworten

Zurück zu „Softwareentwicklung für die HomeMatic CCU“