Script zur Ermittlung eines gleitenden Mittelwertes

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

Moderator: Co-Administratoren

duralis
Beiträge: 29
Registriert: 31.12.2015, 15:29
Danksagung erhalten: 4 Mal

Script zur Ermittlung eines gleitenden Mittelwertes

Beitrag von duralis » 13.04.2020, 11:43

Ich möchte euch heute ein weiteres Script anbieten welches die Funktion eines gleitenden Mittelwert umsetzt.
Solch eine Funktion kann genutzt werden um schwankende Messwerte zu glätten oder um z.B. festzustellen ob sich ein Trend ergibt.
Es ist so programmiert, dass es mit nur 2 Systemvariablen auskommt und sehr variabel mit der Anzahl der Werte, über die der Mittelwert gebildet wird, umgehen kann. Weiterhin lässt sich entweder ein Kanal eines Gerätes oder eine Systemvariable als Daten Quelle nutzen.
Die Konfiguration des Script ist im Script nochmals detailliert beschrieben.

Vorbereitung:
  • erstellen einer Systemvariablen vom Typ Werteliste, Inhalt in der Voreinstellung belassen - Zwischenspeicher FiFo u.a.
  • erstellen einer Systemvariablen vom Typ Zahl im Wertebereich von -31.000 bis 31.000 - Speicher für den berechneten gleitenden Mittelwert
weiterhin benötigt:
  • genaue Adressierung eines Gerätekanal ODER Name der Systemvariable von dem die Messwerte genommen werden sollen um den gleitenden Mittelwert zu ermitteln
  • die Anzahl der Messwerte über die der gleitende Mittelwert gebildet wird, größer gleich 2
Script Aufruf:
  • Den Aufruf kann man z.B. so konfigurieren, dass mit jeder Aktualisierung eines Gerätes das Script aufgerufen wird. Manchmal macht aber auch eine zeitliche Aktivierung Sinn.
Funktion:
  • das Script liest bei jedem Aufruf einen neuen Messwert ein
  • aus dem neuen Messwert und den bisherigen vergangenen Messwerten aus dem Zwischenspeicher wird ein neuer Mittelwert gebildet, dabei wurde der älteste Messwert im Zwischenspeicher nicht beachtet, FiFo Prinzip
  • der neu berechnete Mittelwert wird an die konfigurierte Systemvariable ausgegeben
  • der Zwischenspeicher wird aktualisiert indem der neue Messwert abgelegt und der älteste Messwert entfernt wird.
Hinweise:
* das Script fragt keine Grenzen bezüglich der Menge der Messwerte im FiFo Speicher ab, bitte also nicht übertreiben
* Eine Änderung der Anzahl der Messwerte im FiFo lässt sich im Teil der Script Konfiguration einfach auch nachträglich durchführen (Anzahl der Werte im FiFo). Beim nächsten Durchlauf des Scriptes wird die neue Konfiguration übernommen.
* Alle Messwerte im FiFo werden nicht unterschiedlich gewichtet. Der älteste Wert wird also genau so bewertet wie der jüngste Wert.

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 = "v_tempor_WertelisteB";	! 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 = "BidCos-RF.OEQ7654321:1.TEMPERATURE";		!hier in "" das Geraet angeben von dem der Messwert kommen soll inkl. kompletter Schnittstelle z.B. "BidCos-RF.OEQ1234567:1.WIND_SPEED" ODER ""
string str_NameMesswertSystemvariable = "";									!hier in "" den Namen der Systemvariablen angeben von dem der Messwert kommen soll und NICHT von einem Geraet
! Name der Systemvariable in dem der jeweils berechnete gleitende Mittelwert, also das Ergebnis, abgelegt werden soll
string svMittelwertGleitend = "v_tempor_ZahlB1"; 		! Datentyp "Zahl", Wertebereich -31.000 bis +31.000; Name der Variable fuer den abzuspeichernden gleitenden Mittelwert
integer int_SollAnzahlMittelwerte = 21;				! 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);
}


froema
Beiträge: 205
Registriert: 19.12.2018, 15:20
Hat sich bedankt: 3 Mal

Re: Script zur Ermittlung eines gleitenden Mittelwertes

Beitrag von froema » 14.04.2020, 16:29

Danke,

auch dieses Skript funktioniert hervorragend. Ich habe mich letztenendes dann für dieses hier entschieden.

VG
Marc

paul53
Beiträge: 2554
Registriert: 26.04.2012, 20:42
Wohnort: Berlin
Danksagung erhalten: 15 Mal

Re: Script zur Ermittlung eines gleitenden Mittelwertes

Beitrag von paul53 » 14.04.2020, 16:43

duralis hat geschrieben:
13.04.2020, 11:43
Funktion eines gleitenden Mittelwert umsetzt.
Gab es bereits (ist wohl zu lange her ?).
Versionen: HM-CC-TC 2.1, HM-LC-Sw1 1.9, HM-CC-RT-DN 1.1, HM-MOD-RPI-PCB 1.2.1 (keine CCU)

duralis
Beiträge: 29
Registriert: 31.12.2015, 15:29
Danksagung erhalten: 4 Mal

Re: Script zur Ermittlung eines gleitenden Mittelwertes

Beitrag von duralis » 14.04.2020, 20:45

Hallo paul53,
ja, hatte nichts gefunden aber wohl auch nicht gut genug gesucht.

Duralis

MichaelN
Beiträge: 9654
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 » 08.05.2020, 10:59

duralis hat geschrieben:
13.04.2020, 11:43
  • erstellen einer Systemvariablen vom Typ Zahl im Wertebereich von -31.000 bis 31.000 - Speicher für den berechneten gleitenden Mittelwert
Dazu mal eine Frage: Ist der Punkt im Wertebreich als Dezimalkomma oder als Tausendertrennzeichen zu verstehen?
Also -31 bis +31 oder -31000 bis +31000
Und Wenn nur -31 bis +31 - gibt es dafür einen technischen Grund oder lag das an der Anwednung für die Du es nutzt und eigentlich ist der mögliche Wertebereich viel größer?
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 +++

Xel66
Beiträge: 14149
Registriert: 08.05.2013, 23:33
System: Alternative CCU (auf Basis OCCU)
Wohnort: Nordwürttemberg
Hat sich bedankt: 583 Mal
Danksagung erhalten: 1497 Mal

Re: Script zur Ermittlung eines gleitenden Mittelwertes

Beitrag von Xel66 » 08.05.2020, 12:17

Englische Notation. Entspricht somit dem hier gebräuchlichen Komma.

Gruß Xel66
-------------------------------------------------------------------------------------------
524 Kanäle in 146 Geräten und 267 CUxD-Kanäle in 34 CUxD-Geräten:
343 Programme, 334 Systemvariablen und 183 Direktverknüpfungen,
RaspberryMatic Version: 3.65.11.20221005 + Testsystem: CCU2 2.61.7
-------------------------------------------------------------------------------------------
Einsteigerthread, Programmlogik-Thread, WebUI-Handbuch

duralis
Beiträge: 29
Registriert: 31.12.2015, 15:29
Danksagung erhalten: 4 Mal

Re: Script zur Ermittlung eines gleitenden Mittelwertes

Beitrag von duralis » 08.05.2020, 22:37

Ich meinte eigentlich +-31000. Kommt aber immer darauf an welchen Werte Bereich die ermittelten Zahlen haben könnten. Die CCU begrenzt wohl die Werte auf den Wertebereich der in der Konfiguration der Systemvariable angegeben wird. Daher bin ich recht großzügig damit.

duralis

Kanumouse
Beiträge: 91
Registriert: 09.04.2018, 10:10

Re: Script zur Ermittlung eines gleitenden Mittelwertes

Beitrag von Kanumouse » 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.

alchy
Beiträge: 10754
Registriert: 24.02.2011, 01:34
System: CCU
Hat sich bedankt: 65 Mal
Danksagung erhalten: 673 Mal

Re: Script zur Ermittlung eines gleitenden Mittelwertes

Beitrag von alchy » 07.07.2020, 18:57

Kanumouse hat geschrieben:
07.07.2020, 18:34
Ich konnte keine Fehler feststellen.
Die Aussage ist nicht so wirklich wertvoll wie du dir das denkst. :roll:
Bei Problemen mit Scripten postet man unaufgefordert das >> Fehlerprotokoll << vom Zeitpunkt der Ausführung und das Script in>Codetags eingebettet< oder (zumindest wenn es unverändert ist) einen Link zum verwendeten Script.

Hat man Probleme mit Programmen postet man unaufgefordert eine Bildschirmcopy des Programms in dem man es mit der >> Forenfunktion als Bild an den Beitrag anhängt <<.

Das gibt dir wenigstens eine Chance, das sich jemand deines Problems annimmt. :wink:

Alchy

Blacklist................... almost full
Ignoranz ist die Summe aller Maßnahmen die man ergreift, um bestehende Tatsachen nicht sehen zu müssen.

© Sandra Pulsfort (*1974)

Lies bitte die Logik von WebUI Programmen und die Tipps und Tricks für Anfänger.

Wichtig auch CUxD ersetzt System.exec. Die HM Script Doku (Downloadart Skripte) hilft auch weiter.
Zum Testen von Scripten den >> HomeMatic Script Executor << von Anli benutzen.

Kanumouse
Beiträge: 91
Registriert: 09.04.2018, 10:10

Re: Script zur Ermittlung eines gleitenden Mittelwertes

Beitrag von Kanumouse » 07.07.2020, 19:22

Entschuldigung, läuft, hatte nur einen kleinen Schreibfehler!

Antworten

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