CCU-Historian Script Update TimeSeries

Das Langzeitarchiv für HomeMatic

Moderator: Co-Administratoren

Antworten
TomTB
Beiträge: 73
Registriert: 18.11.2018, 15:30
Danksagung erhalten: 4 Mal

CCU-Historian Script Update TimeSeries

Beitrag von TomTB » 22.01.2023, 12:47

Ich beschäftige mich mit den Script-Möglichkeiten des CCU-Historians. Ich habe das Thema, dass die Temperatursensoren von HM-IP (HmIP-STHO) nach unten auf -20 Grad beschränkt sind. Darunter wird ein Überlauf erzeugt (-3276.8 Grad). Das ist für die Darstellung in den Diagrammen nicht besonders schön. Daher möchte ich die Zeitreihe korrigieren. Das gelingt mit einem SQL-Statement kinderleicht.

Code: Alles auswählen

update D_HMIP_RF_000EDBE9992E8B_1_ACTUAL_TEMPERATURE set "VALUE" = -21.0 where "VALUE" < -21.0;
update D_HMIP_RF_000EDBE9992BBD_1_ACTUAL_TEMPERATURE set "VALUE" = -21.0 where "VALUE" < -21.0;
Resultat

Code: Alles auswählen

update D_HMIP_RF_000EDBE9992E8B_1_ACTUAL_TEMPERATURE set "VALUE" = -21.0 where "VALUE" < -21.0;
Änderungen: 23
(204 ms)

update D_HMIP_RF_000EDBE9992BBD_1_ACTUAL_TEMPERATURE set "VALUE" = -21.0 where "VALUE" < -21.0;
Änderungen: 18
(108 ms)
Alles fein. Nun möchte ich das gern periodisch ausführen. Dazu habe ich mich an den Scripten orientiert, die im Handbuch stehen. Leider ist das Objekt TimeSeries nicht erklärt und ich finde auch keinen Weg, wie ich ein TimeSeries-Objekt aktualisieren kann.
Script soweit:

Code: Alles auswählen

def end=new Date() // aktueller Zeitpunkt
def duration=720*1000 // 12 Minuten zurück in Millisekunden (Task soll alle 10 Minuten laufen)
def begin=new Date(end.time-duration) 
println "Beginn: $begin, Ende: $end"

// Datenpunkt holen
dp = database.getDataPoint(115)
// Zeitreihe holen
def ts=database.getTimeSeries(dp, begin, end)

println "Anzahl Einträge: $ts.size"

ts.each { pv -> 
print pv
if (pv.value < -21)
{
 print " zu kalt" 
 pv.value = -21.0
 println " korrigiert auf -21"
 
}
else println " ok"
}

// Hier müsste jetzt die TimeSeries ts in der Datenbank aktualisiert werden. // Aber wie?
Gibt den Output

Code: Alles auswählen

Datenpunkt: Temperatursensor Tiefkühler Hauswirtschaftsraum:1.ACTUAL_TEMPERATURE
Beginn: Sun Jan 22 12:30:56 CET 2023, Ende: Sun Jan 22 12:42:56 CET 2023
Anzahl Einträge: 3
Sun Jan 22 12:30:56 CET 2023, -21.0, 2 ok
Sun Jan 22 12:32:42 CET 2023, -21.0, 2 ok
Sun Jan 22 12:41:00 CET 2023, -3276.8, 2 zu kalt korrigiert auf -21
Wo kann ich Infos dazu finden? Es scheint eine Methode database.updateTimeSeries zu geben, aber ich kenne die Signatur nicht (welche Parameter) und habe auch noch keinen Weg gefunden, die zu ermitteln.

Danke und freundliche Grüße, Tom

TomTB
Beiträge: 73
Registriert: 18.11.2018, 15:30
Danksagung erhalten: 4 Mal

Re: CCU-Historian Script Update TimeSeries

Beitrag von TomTB » 22.01.2023, 16:56

Ich habe es allein herausgefunden.
Ich bin zwar nicht vertraut mit Groovy, dafür aber mit C# und allgemeinen Programmiertechniken. Ich habe gesehen, dass es ein ReplaceTimeSeries gibt. Dann habe ich mir überlegt, eine neue TimeSeries aufzubauen mit den geänderten Werten und dann diese TimeSeries zurückzuschreiben.
Das war dann erfolgreich. Der Rest ist Kosmetik. Ich habe das ganze - weil ich zwei Tiefkühler und zwei solche Sensoren habe - in eine Funktion gepackt, die ich jeweils für jeden der beiden Datenpunkte aufrufe. Da die Werte vom Sensor nur ungefähr alle drei Minuten kommen, habe ich sicherheitshalber das Abfrageintervall auf die letzten 20 Minuten gesetzt und führe das Script alle 10 Minuten aus.

Hier der Code:

Code: Alles auswählen

def end=new Date() // aktueller Zeitpunkt
	// 20 Minuten = 1200 Sekunden zurück in Millisekunden 
	// (Task soll alle 10 Minuten laufen)
	def duration=1200*1000 
	def begin=new Date(end.time-duration) 
	println "Beginn: $begin, Ende: $end"

	def AdjustFreezerTemperature(String name, int datapoint_id, Date begin, Date end)
	{
	  def dp = database.getDataPoint(datapoint_id)
	  def ts = database.getTimeSeries(dp, begin, end)

	  println "Anzahl Einträge $name: $ts.size"

	  // neue Zeitreihe erzeugen
	  def tsnew = []

	  ts.each { pv -> 
		print pv
		if (pv.value < -21)
		  {
			 print " zu kalt" 
			 pv.value = -21.0
			 println " korrigiert auf -21"
		  }
		else 
		  {
			 println " ok"
		  }

		// Process Value in neue Zeitreihe einfügen
		tsnew << pv
	  }
	  database.replaceTimeSeries(dp, tsnew, begin, end)
	}

	// 
	// Einmal für den Hauswirtschaftsraum
	// 

	AdjustFreezerTemperature("Hauswirtschaftsraum", 115, begin, end)

	// 
	// Einmal für die Küche
	// 

	AdjustFreezerTemperature("Küche", 226, begin, end)
Das mit der Funktion hat zwar in der Script-Umgebung funktioniert, nicht aber in der ccu-historian.config. Der ccu-historian ist einfach nicht mehr gestartet. Dort musste ich die Funktion wieder entfernen und durch duplizierten Code ersetzen. Unschön.

Code: Alles auswählen

database.tasks.adjustfreezertemps.enable=true
database.tasks.adjustfreezertemps.cron="* 0/10 0 ? * * *" 
database.tasks.adjustfreezertemps.script={
def end=new Date() // aktueller Zeitpunkt
// 20 Minuten = 1200 Sekunden zurück in Millisekunden 
// (Task soll alle 10 Minuten laufen)
def duration=1200*1000 
def begin=new Date(end.time-duration) 
println "Beginn: $begin, Ende: $end"

def dp = database.getDataPoint(115)
def ts = database.getTimeSeries(dp, begin, end)

println "Anzahl Einträge Hauswirtschaftsraumm: $ts.size"

// neue Zeitreihe erzeugen
def tsnew = []

ts.each { pv -> 
  print pv
  if (pv.value < -21)
    {
       print " zu kalt" 
       pv.value = -21.0
       println " korrigiert auf -21"
    }
  else 
    {
       println " ok"
    }

  // Process Value in neue Zeitreihe einfügen
  tsnew << pv
}
database.replaceTimeSeries(dp, tsnew, begin, end)

dp = database.getDataPoint(226)
ts = database.getTimeSeries(dp, begin, end)

println "Anzahl Einträge Küche: $ts.size"

// neue Zeitreihe erzeugen
tsnew = []

ts.each { pv -> 
  print pv
  if (pv.value < -21)
    {
       print " zu kalt" 
       pv.value = -21.0
       println " korrigiert auf -21"
    }
  else 
    {
       println " ok"
    }

  // Process Value in neue Zeitreihe einfügen
  tsnew << pv
}
database.replaceTimeSeries(dp, tsnew, begin, end)

}

TomTB
Beiträge: 73
Registriert: 18.11.2018, 15:30
Danksagung erhalten: 4 Mal

Re: CCU-Historian Script Update TimeSeries

Beitrag von TomTB » 22.01.2023, 17:21

Nochmal ich. Das habe ich im Log gefunden:

Code: Alles auswählen

Method definition not expected here. Please define the method at an appropriate place or perhaps try using a block/Closure instead.
Schade eigentlich. Ich mag keinen duplizierten Code.
Tom

Mathias
Beiträge: 1794
Registriert: 03.11.2010, 10:25
System: CCU
Wohnort: Aachen
Hat sich bedankt: 58 Mal
Danksagung erhalten: 261 Mal
Kontaktdaten:

Re: CCU-Historian Script Update TimeSeries

Beitrag von Mathias » 23.01.2023, 21:32

Ich habe es nicht getestet, aber die Funktion kann auch, wie vom Compiler vorgeschlagen, als Closure definiert werden:

Code: Alles auswählen

database.tasks.adjustfreezertemps.script={
    ....
    def AdjustFreezerTemperature = { String name, int datapoint_id, Date begin, Date end ->
       ....
    }
    ....
    AdjustFreezerTemperature("Hauswirtschaftsraum", 115, begin, end)
}

TomTB
Beiträge: 73
Registriert: 18.11.2018, 15:30
Danksagung erhalten: 4 Mal

Re: CCU-Historian Script Update TimeSeries

Beitrag von TomTB » 24.01.2023, 08:03

Muss ich mal ausprobieren.
Welcher Compiler hat das vorgeschlagen? Ich habe schlicht in der Script-Umgebung des CCU-Historians gearbeitet. Die Umgebung ist etwas karg. :D
Tom

Mathias
Beiträge: 1794
Registriert: 03.11.2010, 10:25
System: CCU
Wohnort: Aachen
Hat sich bedankt: 58 Mal
Danksagung erhalten: 261 Mal
Kontaktdaten:

Re: CCU-Historian Script Update TimeSeries

Beitrag von Mathias » 24.01.2023, 10:13

TomTB hat geschrieben:
22.01.2023, 17:21
Nochmal ich. Das habe ich im Log gefunden:

Code: Alles auswählen

Method definition not expected here. Please define the method at an appropriate place or perhaps try using a block/Closure instead.

TomTB
Beiträge: 73
Registriert: 18.11.2018, 15:30
Danksagung erhalten: 4 Mal

Re: CCU-Historian Script Update TimeSeries

Beitrag von TomTB » 28.01.2023, 11:09

Ich habe es ausprobiert. Die Closure verträgt nur ein Argument. Sobald man mehr als eins kommasepartiert angibt, startet der CCU-Historian nicht.
Schade. Klassen gehen auch nicht (dann könnte man die Parameter zusammenfassen). Wirklich schade.
Die Aussage im Handbuch "Die Skriptumgebung verwendet die Programmiersprache Groovy für die Ausführung der Skripte. Der gesamte Sprachumfang kann genutzt werden, allerdings kann absichtlich nur auf bestimmte Klassen bzw. Objekte zugegriffen werden." stimmt so wohl nicht. Jedenfalls nicht für Scripte in der Konfigurationsdatei. In der Script-Umgebung funktioniert es ja. Sehr seltsam.
Tom

Antworten

Zurück zu „CCU-Historian“