Script zur Ermittlung eines gleitenden Mittelwertes

Problemlösungen und Hinweise von allgemeinem Interesse zur Haussteuerung mit HomeMatic

Moderator: Co-Administratoren

MichaelN
Beiträge: 9656
Registriert: 27.04.2020, 10:34
System: CCU
Hat sich bedankt: 697 Mal
Danksagung erhalten: 1617 Mal

Re: Script zur Ermittlung eines gleitenden Mittelwertes

Beitrag von MichaelN » 07.07.2020, 19:24

:roll:
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 +++

Chemieka
Beiträge: 649
Registriert: 03.01.2017, 17:39
Hat sich bedankt: 4 Mal
Danksagung erhalten: 9 Mal

Re: Script zur Ermittlung eines gleitenden Mittelwertes

Beitrag von Chemieka » 06.01.2023, 21:16

Kanumouse hat geschrieben:
07.07.2020, 18:34
Das Script läuft bei mir leider nicht.
Ich konnte keine Fehler feststellen.
Die angelegte Variable für den Mittelwert ändert sich nicht.
Ich muss mich hier anschließen.

Code: Alles auswählen

!! MittelwertGleitend V0.1
!! Berechnung eines gleitenden Mittelwertes (einfacher gleitender Durchschnitt) ueber eine frei definierbare Anzahl von Werten
!! * ermoeglicht die Aufzeichnung und Berechnung eines gleitenden Mittelwertes fuer eines
!!     beliebigen Kanalnummes eines Geraetes oder eine Systemvariable aus denen die Werte kommen
!! * es findet keine Wichtung der einzelnen Werte statt, 
!! * das Fenster, aus denen der Mittelwert berechnet wird bleibt gleich
!!
!!(c) duralis; zur freien Verwendung
!!
!!
!! Vorbereitung:
!! * in der CCU Anlegen einer Systemvariable vom Typ "Werteliste" anlegen, - automatisch generierten Inhalt so belassen
!! * in der CCU Anlagen einer Systemvariablen vom Typ "Zahl" mit Minimum -31000 und Maximum 31000 anlegen, dies ist der berechnete gleitende Mittelwert
!! * Konfiguration dieses Scriptes (etwas weiter unten) mit dem Namen der beiden soeben angelegten Systemvariablen und den weiteren Angaben
!! * in der CCU in der grafischen Obeflaeche ein Programm fuer Aufruf dieses Scriptes zusammenklicken, dieses angepasste Script angeben, fertig
!!
!! Aufruf:
!! * dieses Script z.B. mit jeder Messwertaufnahme (bei Aktualisierung) vom Sensor starten oder zeitlich z.B. jede Stunde je nach Zweck
!!

! ******* die folgenden Zeilen muessen angepasst werden ******
string svNameWerteliste = "MittelListe";	! Name der Systemvariablen als Werteliste, der als Speicher fuer die interne Berechnung dient (FiFo, Werte, Namen usw.)
! *** Bitte nur in einer der beiden naechsten Zeilen den Inhalt zwischen die Anfuehrungszeichen "" eintragen ***
string str_NameMesswertGeraet = "HmIP-RF.001818A992BC16:1.ACTUAL_TEMPERATURE";		
! Name der Systemvariable in dem der jeweils berechnete gleitende Mittelwert, also das Ergebnis, abgelegt werden soll
string svMittelwertGleitend = "MittelZahl"; 		! Datentyp "Zahl", Wertebereich -31.000 bis +31.000; Name der Variable fuer den abzuspeichernden gleitenden Mittelwert
integer int_SollAnzahlMittelwerte = 24;				! Anzahl von Messwerten aus denen der gleitende Mittelwert berechnet wird (Beispiel 3 bedeutet, aus der aktuellen und den letzten 2 Messwerten wird der Mittelwert berechnet)
													! Mindestens eine 2 als Zahl angeben, sehr grosse Werte sind eigentlich unsinnig und sorgen fuer viel zu hohe CCU Last

!! ********************************************************************************************************************
! ******* ab hier sind keine Anpassungen im Code mehr notwendig ******

object svObjekt;
! interne Variablen
string TrennzeichenDerZeilen = ";"; !das Semikolon dient als Trennzeichen in der Systemvariable(Listvariable) zum trennen der einzelnen Abschnitte
string TrennzeichenWerte = "|";		! das "|" Pipe dient als Trennzeichen zwischen den Messwerten im FiFo Speicher

string str_WertelisteKomplett;				!nimmt die komplette Werteliste auf (FiFo + Konfiguration)
string str_FiFoKomplett;					!nimmt nur die Werte des FiFo auf
string str_FiFoNeu;							!neue Werte die in den FiFo aufgenommen werden sollen
string str_EinSpeicherwert;					!eine Zahl als String aus der Werteliste
integer int_EinSpeicherwert;				!eine Zahl als Zahl aus der Werteliste
real real_Messwert;							!nimmt Werte als Zahl auf - pruefen ob das nicht "real" sein sollte
integer int_IstAnzahlMittelwerteFiFo;		!aktuelle Anzahl der Mittelwerte im FiFo
string str_index;							!Indexvariable fuer foreach
integer int_index;							!Indexvariable als Zahl
real real_GleitenderMittelwert;				!enthaelt die Zwischenberechnung fuer den gleitenden Mittelwert
integer int_DifAnzahlZusatzWerte;			!Anzahl FiFo Plaetze Aenderung, wenn der FiFo in der Groesse veraendert werden muss

!Aufbau Werteliste Variable
! Index 0 -> FiFo Speicher der einzelnen Messwerte, Pipe trennt die einzelnen Messwerte
! Index 1 -> komplette Adresse des Geraetes von dem die Messwerte genutzt werden ODER Name der Systemvariablen dessen Inhalt als Messwerte genutzt werden
! Index 2 -> Name der Systemvariablen in dem der gleitenden Mittelwert bei jedem Durchlauf geschrieben wird
! Index 3 -> aktuelle Anzahl der Messwerte im FiFo Speicher


!++++++++++++++++ Messwert aus Geraet oder Systemvariable auslesen +++++++++++++++++++++++++
if (str_NameMesswertSystemvariable!="")
{
	real_Messwert = dom.GetObject(str_NameMesswertSystemvariable).State();	!den Messwert einlesen welcher als Mittelwert genutzt werden soll
}
else
{
	real_Messwert = dom.GetObject(str_NameMesswertGeraet).Value();		!den Messwert einlesen welcher als Mittelwert genutzt werden soll
}

!++++++++++++++++ die Werteliste analysieren +++++++++++++++++++++++++
object svObjekt = (dom.GetObject(ID_SYSTEM_VARIABLES).Get(svNameWerteliste));		!Einlesen Werteliste vorbereiten
str_FiFoKomplett = svObjekt.ValueList().StrValueByIndex(TrennzeichenDerZeilen, 0);

!!wenn Script schon gelaufen ist dann Vorbelegte Werte nutzen ansonsten neue Werte erstellen, Find liefert "-1" wenn Substring nicht gefunden wurde
if (str_FiFoKomplett.Find(TrennzeichenWerte)!=-1)
{
	str_EinSpeicherwert = svObjekt.ValueList().StrValueByIndex(TrennzeichenDerZeilen, 3);		!Index 3 in Werteliste = Anzahl Werte im FiFo
	int_IstAnzahlMittelwerteFiFo = str_EinSpeicherwert.ToFloat();								!Anzahl Werte im FiFo
	real_GleitenderMittelwert = real_Messwert;	!den aktuellen Messwert uebernehmen, dann den FiFo abklappern
	int_index = 1;								!erster Messwert wurde ja schon eingelesen
	str_FiFoNeu = real_Messwert.ToString();		!den neuen Messwert in den FiFo an den Anfang setzen
	
	int_DifAnzahlZusatzWerte = int_SollAnzahlMittelwerte - int_IstAnzahlMittelwerteFiFo;		!feststellen ob der FiFo groesser, kleiner oder gleich gross bleiben soll
	if (int_DifAnzahlZusatzWerte>=1)
	{
		while (int_DifAnzahlZusatzWerte>0)
		{
			str_FiFoNeu = str_FiFoNeu#TrennzeichenWerte#real_Messwert.ToString();
			real_GleitenderMittelwert = real_GleitenderMittelwert + real_Messwert.ToString();
			int_index = int_index +1;
			int_DifAnzahlZusatzWerte = int_DifAnzahlZusatzWerte -1;
		}
	}
	foreach(str_EinSpeicherwert, str_FiFoKomplett.Split(TrennzeichenWerte))
	{
		if (int_index < int_SollAnzahlMittelwerte)
		{
			str_FiFoNeu = str_FiFoNeu#TrennzeichenWerte;
			str_FiFoNeu = str_FiFoNeu#str_EinSpeicherwert;
			real_GleitenderMittelwert = real_GleitenderMittelwert + str_EinSpeicherwert.ToFloat();		!den naechsten Messwert aus dem FiFo mit berechnen
			int_index = int_index +1;
		}
		!weitere Werte werden ignoriert weil FiFo Soll Anzahl erreicht wurde
	}

	!Index 0 der Listvariable fertig stellen - FiFo
	str_FiFoKomplett = str_FiFoNeu#TrennzeichenDerZeilen;
	
	!Index 1 der Listvariable fertig stellen - Quell Geraet oder Quell Variable
	if (str_NameMesswertGeraet!="")
	{
		str_FiFoKomplett = str_FiFoKomplett#str_NameMesswertGeraet#TrennzeichenDerZeilen;
	}
	else
	{
		str_FiFoKomplett = str_FiFoKomplett#str_NameMesswertSystemvariable#TrennzeichenDerZeilen;
	}

	!Index 2 der Listvariable fertig stellen - Name der Systemvariable fuer die Ablage gleitender Mittelwert
	real_GleitenderMittelwert = real_GleitenderMittelwert / int_index;		!Berechnung neuer gleitender Mittelwert
	str_EinSpeicherwert = svObjekt.ValueList().StrValueByIndex(TrennzeichenDerZeilen, 2);
	str_FiFoKomplett = str_FiFoKomplett#str_EinSpeicherwert#TrennzeichenDerZeilen;
	dom.GetObject(str_EinSpeicherwert).State(real_GleitenderMittelwert);		!aktuellen berechneten gleitenden Mittelwert in die Systemvariable schreiben

	!Index 3 der Listvariable fertig stellen - Anzahl der gleitenden Mittelwerte im FiFo
	str_FiFoKomplett = str_FiFoKomplett#int_index;
	svObjekt.State(0);
	svObjekt.ValueList(str_FiFoKomplett);	!Variableninhalt schreiben
}
else
{
	!Die Systemvariable enthaelt Bloedsinn weil sie gerade angelegt wurde
	!Index 0 zusammenbauen
	int_index=0;
	str_WertelisteKomplett = "";
	str_WertelisteKomplett = str_WertelisteKomplett#real_Messwert.ToString();
	int_index = int_index + 1;
	while (int_index<int_SollAnzahlMittelwerte)
	{
		str_WertelisteKomplett = str_WertelisteKomplett#TrennzeichenWerte;
		str_WertelisteKomplett = str_WertelisteKomplett#real_Messwert.ToString();
		int_index = int_index + 1;
	}
	str_WertelisteKomplett = str_WertelisteKomplett#TrennzeichenDerZeilen;
	!Index 1 zusammenbauen
	str_WertelisteKomplett = str_WertelisteKomplett#str_NameMesswertGeraet#TrennzeichenDerZeilen;
	!Index 2 zusammenbauen
	str_WertelisteKomplett = str_WertelisteKomplett#svMittelwertGleitend#TrennzeichenDerZeilen;
	!Index 3 zusammenbauen
	str_WertelisteKomplett = str_WertelisteKomplett#int_index;
	dom.GetObject(dom.GetObject(svNameWerteliste)).ValueList(str_WertelisteKomplett);		!wieder abspeichern der korrigierten Systemvariable
	
	!in die Systemvariable den Messwert als gleitenden Mittelwert schreiben
	real_GleitenderMittelwert = real_Messwert;
	dom.GetObject(svMittelwertGleitend).State(real_Messwert);
}
1.jpg
Die Werte ändern sich auch bei mir nicht, das Programm wird aber gestartet.
Die Werte am Sensor ändern sich natürlich:
<datapoint name="HmIP-RF.001818A992BC16:1.ACTUAL_TEMPERATURE" type="ACTUAL_TEMPERATURE" ise_id="26596" value="7.300000" valuetype="4" valueunit="°C" timestamp="1673036083" operations="5"/>
PI3+ mit RaspberryMatic; PI4 mit IOBroker; Samsung Tab A mit Mediola Visualisierung; Harmony Hub; Philips Hue; Drei IP Cams; Zwei Leseköpfe an den Stromzählern; Reedkontakt (Arduino) am Wasserzähler; Drucksensor (Arduino); CUL433 für Intertechno und Somfy RTS; Nuki Bridge

Benutzeravatar
Baxxy
Beiträge: 10789
Registriert: 18.12.2018, 15:45
System: Alternative CCU (auf Basis OCCU)
Hat sich bedankt: 604 Mal
Danksagung erhalten: 2208 Mal

Re: Script zur Ermittlung eines gleitenden Mittelwertes

Beitrag von Baxxy » 06.01.2023, 23:56

Chemieka hat geschrieben:
06.01.2023, 21:16
Ich muss mich hier anschließen.
Tja, wenn man benötigte Dinge aus dem Script löscht muss man sich nicht wundern...

Code: Alles auswählen

local0.err ReGaHss: ERROR: SyntaxError: Error 1 at row 58 col 35 near ^!="")
:roll:

Code: Alles auswählen

str_NameMesswertSystemvariable
ist nicht deklariert!

MichaelN
Beiträge: 9656
Registriert: 27.04.2020, 10:34
System: CCU
Hat sich bedankt: 697 Mal
Danksagung erhalten: 1617 Mal

Re: Script zur Ermittlung eines gleitenden Mittelwertes

Beitrag von MichaelN » 07.01.2023, 00:10

Ich denke es gibt doch gute Gründe für selbst konfigurierende skripte. Ich habe auch schon eine Idee wie ich mein Skript so gestalten kann, dass es auch beim triggern über Zeitmodul arbeitet.

EDIT: Fertig - siehe viewtopic.php?f=43&t=10182&p=750572#p750572
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 +++

MarKiesCo
Beiträge: 69
Registriert: 11.04.2023, 21:07
System: CCU
Hat sich bedankt: 29 Mal
Danksagung erhalten: 3 Mal

Re: Script zur Ermittlung eines gleitenden Mittelwertes

Beitrag von MarKiesCo » 25.04.2023, 18:33

Oh man, ich liebe dieses Forum :D
Als Neueinsteiger in CCU und scripte, und ehemaliger, langjähriger Nutzer von HOMEMATIC IP, sind die Möglichkeiten hier wirklich Grenzenlos.

Auch ich möchte mich ganz herzlich bei dem Ersteller des scriptes bedanken, es funktioniert tadellos.

Ich verwende es um den Ertrag meines 600W Balkonkraftwerkes etwas zu glätten, um anschließend Verbraucher automatisiert anzuschalten, um keinen Strom zu verschenken.

cheers
MarKiesCo

Marcus1@@@
Beiträge: 219
Registriert: 02.01.2016, 14:24
Danksagung erhalten: 21 Mal

Re: Script zur Ermittlung eines gleitenden Mittelwertes

Beitrag von Marcus1@@@ » 19.05.2023, 18:25

Hallo, an welcher Stelle des Scripts kann ich denn nochmal vor dem state in die Systemvariable eine Berechnung machen.
in der letzten bzw. vorletzten Zeile des Scripts nicht.

GRüße

MichaelN
Beiträge: 9656
Registriert: 27.04.2020, 10:34
System: CCU
Hat sich bedankt: 697 Mal
Danksagung erhalten: 1617 Mal

Re: Script zur Ermittlung eines gleitenden Mittelwertes

Beitrag von MichaelN » 19.05.2023, 18:43

Doch, warum nicht?
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 +++

Marcus1@@@
Beiträge: 219
Registriert: 02.01.2016, 14:24
Danksagung erhalten: 21 Mal

Re: Script zur Ermittlung eines gleitenden Mittelwertes

Beitrag von Marcus1@@@ » 19.05.2023, 19:16

hmmm

Code: Alles auswählen

!in die Systemvariable den Messwert als gleitenden Mittelwert schreiben
	real_GleitenderMittelwert = real_Messwert;
	dom.GetObject(svMittelwertGleitend).State(real_Messwert);
ich hätte gerne das ganze /255 und *100

Code: Alles auswählen

dom.GetObject(svMittelwertGleitend).State((real_Messwert/255)*100);
ändert aber bei mir nichts

grüße

MichaelN
Beiträge: 9656
Registriert: 27.04.2020, 10:34
System: CCU
Hat sich bedankt: 697 Mal
Danksagung erhalten: 1617 Mal

Re: Script zur Ermittlung eines gleitenden Mittelwertes

Beitrag von MichaelN » 19.05.2023, 19:45

Wenn du das unbedingt in einen möglichst kurzen Befehl packen willst, dann musst du mehr Klammern setzen. HM Skript ist da sehr eigen.
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 +++


Antworten

Zurück zu „HomeMatic Tipps & Tricks - keine Fragen!“