Hallo,
ich hab da mal ne grundsätzliche Frage zum effizienten Umgang mit einem dbRep-device.
Meines sieht grade so aus:
Internals:
DATABASE fhem
DEF mySQLDB
FUUID 5ede1d78-f33f-a625-537a-d2eb574f94488ba8
FVERSION 93_DbRep.pm:v8.40.1-s21965/2020-05-18
LASTCMD maxValue writeToDB
MODEL Client
NAME mySQLDBReport
NOTIFYDEV global,mySQLDBReport
NR 226
NTFY_ORDER 50-mySQLDBReport
ROLE Client
STATE done
TYPE DbRep
UTF8 0
HELPER:
DBLOGDEVICE mySQLDB
GRANTS SELECT,UPDATE,INSERT,ALL PRIVILEGES,DELETE
IDRETRIES 3
MINTS 2020-01-01 00:00:00
PACKAGE main
SQLHIST
VERSION 8.40.1
CV:
aggregation day
aggsec 86400
destr 2020-10-06
dsstr 2019-01-01
epoch_seconds_end 1601987505
mestr 10
msstr 01
testr 14:31:45
tsstr 00:00:00
wdadd 518400
yestr 2020
ysstr 2019
DBREPCOL:
COLSET 1
DEVICE 64
EVENT 512
READING 64
TYPE 64
UNIT 32
VALUE 128
OLDREADINGS:
READINGS:
2020-10-06 14:32:21 2019-01-01__HzgHC_Wohnzimmer__pulseTimePerDay__MAX__2019-01-01 0.0000
...
Attributes:
aggregation day
allowDeletion 1
devStateIcon connected:10px-kreis-gelb .*disconnect:10px-kreis-rot .*done:10px-kreis-gruen
device HzgHC_Wohnzimmer
event-on-update-reading state
reading pulseTimePerDay
room DbLog,LogFiles,System
timestamp_begin 2019-01-01 00:00:00
verbose 1
die DB dazu:
defmod mySQLDB DbLog ./mySQLDB.conf Rolladen.*:pct|HzgThermostat.*:batteryLevel|HzgThermostat.*:desired-temp|HzgThermostat.*:measured-temp|HzgStatus.*:humidity|HzgAktor.*:level|HzgAktor.*:pct|HzgAktor.*:state|HzgHC.*:*.perDay\
attr mySQLDB .* 1
attr mySQLDB DbLogType Current/History
attr mySQLDB asyncMode 1
attr mySQLDB bulkInsert 1
attr mySQLDB cacheLimit 500
attr mySQLDB event-on-change-reading CacheUsage
attr mySQLDB room DbLog,LogFiles,System
attr mySQLDB showNotifyTime 0
attr mySQLDB showproctime 1
attr mySQLDB syncInterval 120
attr mySQLDB verbose 5
ich habe die Anzahl der Readings in der DB bereits eingeschränkt, wie man oben sehen kann.
So, jetzt möchte ich meine ganzen Devices und Readings, die ich in der DB habe, nach bestimmten Kriterien optimieren:
Z.B. soll das Reading "measured-temp" nicht mehr jeden Wert beinhalten, sondern nur noch pro Stunde den Min- und Max-, sowie den Mittelwert.
Dann habe ich noch Readings wie z.B. "pulseTimePerDay", da möchte ich dann das Maximum eines Tages haben.
Die diskreten Werte behalte ich noch ein paar Wochen, bevor ich diese dann lösche, und nur noch die berechneten Werte habe...
Ich habe 4 Räume, und pro Raum dann die beiden Readings (den entsprechenden Devices vom Typ "HM-TC-IT-WM-W-EU" und "HourCounter" zugeordnet).
Muss ich jetzt dann für die 4 (Räume) * 4 (Readings) = 16 neue Readings in der DB dann auch 16 mal ein DbRep-Device erstellen und diese dann mit einem at-Befehl zu gegebener Zeit dann die DB aktualisieren lassen?
Oder geht das eleganter? Meine Devices heißen immer gleich:
- HzgStatusBad
- HzgStatusBuero
- HzgStatusSchlafzimmer
- HzgStatusWohnzimmer
- HzgStatusFlur *
- HzgStatusHWR *
- HzgStatusToilette *
- HzgThermostatBad
- HzgThermostatBuero
- HzgThermostatSchlafzimmer
- HzgThermostatWohnzimmer
- HzgThermostatFlur *
- HzgThermostatHWR *
- HzgThermostatToilette *
und dann der Hourcounter:
- HzgHC_Bad
- HzgHC_Buero
- HzgHC_Schlafzimmer
- HzgHC_Wohnzimmer
Die Devices mit * sind nur zum Messen da, da wird keine Raumtemperatur mit gesteuert, wie bei den anderen.
Kann mir da jemand einen Tipp geben?
Danke
Wolfgang
Hallo Wolfgang,
folgenden Weg könntest du gehen.
Es ist ja so, dass letzten Endes das DbRep Device aus jedem Befehl entsprechend seiner Parametrisierung über Attribute zur Erledigung seiner Aufgabe ein oder mehrere (Ketten) von SQL-Kommandos ausführt.
Sofern die jeweilige Aufgabe nur ein SQL-Statement ausführt, kannst du dieses SQL nehmen und direkt in einem at und dem DbRep sqlCmd-Kommando ausführen, z.B:
set <> sqlCmd <SQL-Statement>
In dieser Form kannst du verschiedene / verschiedene SQL's über nur ein DbRep-Device gegen die Datenbank fahren.
Welche SQL's verwendet werden, siehst du wenn du verbose 4 im DbRep Device einstellst und deinen Min, Max, Mittelwert ausführst. Ggf. musst du noch Anpassungen vornehmen um Datumsgrenzen zu verschieben, was ich normalerweise mit Perl-Mitteln im Modul mache.
Auf diese Weise könntest du ggf. deine benötigten DbRep's reduzieren. (Andererseits stört es auch nicht viele definiert zu haben)
Wenn SQL-Ketten verwendet werden, ist diese Methode eher nicht einsetzbar und es bieten sich in diesem Fall tatsächlich separate Devices an.
Allerdings hat die Verwendung von dedizierten DbReps generell den Vorteil, dass man seine erstellten Auswertungen direkt in den "Probably associated with" Angaben im jeweiligen Device gleich sieht und dahin springen kann usw.
Grüße,
Heiko
Zitat von: DS_Starter am 06 Oktober 2020, 17:57:22
Hallo Wolfgang,
folgenden Weg könntest du gehen.
Es ist ja so, dass letzten Endes das DbRep Device aus jedem Befehl entsprechend seiner Parametrisierung über Attribute zur Erledigung seiner Aufgabe ein oder mehrere (Ketten) von SQL-Kommandos ausführt.
Sofern die jeweilige Aufgabe nur ein SQL-Statement ausführt, kannst du dieses SQL nehmen und direkt in einem at und dem DbRep sqlCmd-Kommando ausführen, z.B:
set <> sqlCmd <SQL-Statement
In dieser Form kannst du verschiedene / verschiedene SQL's über nur ein DbRep-Device gegen die Datenbank fahren.
Welche SQL's verwendet werden, siehst du wenn du verbose 4 im DbRep Device einstellst und deinen Min, Max, Mittelwert ausführst. Ggf. musst du noch Anpassungen vornehmen um Datumsgrenzen zu verschieben, was ich normalerweise mit Perl-Mitteln im Modul mache.
Auf diese Weise könntest du ggf. deine benötigten DbRep's reduzieren. (Andererseits stört es auch nicht viele definiert zu haben)
Wenn SQL-Ketten verwendet werden, ist diese Methode eher nicht einsetzbar und es bieten sich in diesem Fall tatsächlich separate Devices an.
Allerdings hat die Verwendung von dedizierten DbReps generell den Vorteil, dass man seine erstellten Auswertungen direkt in den "Probably associated with" Angaben im jeweiligen Device gleich sieht und dahin springen kann usw.
Grüße,
Heiko
Hallo Heiko,
ich hab jetz tatsächlich für jede Aggregation die ich machen will, ein eigenes dbRep- und ein eigenes at-Device erzeugt. Einfach die raw-Definiton eines ersten Device rausgenommen, und die jeweiligen Raumnamen dann in einem Editor ersetzt... ging auch ganz fix.
Nur sehe ich jetzt, wenn ich alle at-Kommandos sofort ausführe, dass manche davon mit Fehler stecken bleiben. Sollte ich wohl dann um 00:00, 00:05 und 00:10 usw. ausführen...
Viele Grüße
und Danke
Sollte ich wohl dann um 00:00, 00:05 und 00:10 usw. ausführen...
Das ist keine schlechte Idee nicht alles zur gleichen Zeit loslaufen zu lassen, auch wegen dem Ressourcen-Verbrauch der verwendeten nicht blockierenden Arbeitsweise (Stichwort BlockingCall).
Zeig mal ein Beispiel eines Fehlers.
Zitat von: DS_Starter am 06 Oktober 2020, 18:15:24
Zeig mal ein Beispiel eines Fehlers.
Hier:
errortext: DBD::mysql::db do failed: Deadlock found when trying to get lock; try restarting transaction at ./FHEM/93_DbRep.pm line 11087. 2020-10-06 19:24:36
Ja das ist ein Datenbank Fehler (Tabellensperre) den du durch zeitlichen Versatz deiner Aktionen vermeiden kannst.
Noch ein Hinweis zur (Start)Effizienz.
Insbesondere wenn man viele DbReps definiert hat, setzt man fastStart = 1.
Damit startet FHEM schneller.
Vllt. setze ich diesen Parameter generell als default in einem der nächsten Releases.
Hallo DS_Starter,
soweit funktioniert das Ganze jetzt.
Ein Problem bleibt aber:
In der DB habe ich jetzt einen Wert drinstehen von gestern:
2020-10-06 15:58:06 HzgHC_Bad HourCounter calculated max_day_pulseTimePerDay 15326.0000
Das entspricht auch dem Reading aus dem dbRep-Device:
2020-10-06_15-58-06__HzgHC_Bad__pulseTimePerDay__MAX__2020-10-06 15326.0000 2020-10-07 00:00:28
Aber im SVG wird mir dieser Wert nicht korrekt angezeigt.
Wenn ich den Wertebereich für die Y-Achse auf 24h habe, also von 0..86400 Sekunden, sind es ungefähr 15380 Ticks.
Setze ich die Y-Achse aber auf 15300..15400, so sind es die 15326 Ticks.
Kann man da noch was machen?
Und wie könnte ich die Ticks beim Eintragen in die Datenbank gleich korrekt als hh:mm eintragen und so dann als Basis für die Grafik nehmen?
Viele Grüße
Wolfgang
PS.: Wo muss fastStart = 1 gesetzt werden?
Hallo Wolfgang,
ZitatPS.: Wo muss fastStart = 1 gesetzt werden?
Das setzt du in allen DbRep-Devices, z.B. mit einem Befehl:
attr TYPE=DbRep fastStart 1
Zitat
Wenn ich den Wertebereich für die Y-Achse auf 24h habe, also von 0..86400 Sekunden, sind es ungefähr 15380 Ticks.
Setze ich die Y-Achse aber auf 15300..15400, so sind es die 15326 Ticks.
Kann man da noch was machen?
Ich fürchte ich habe nicht verstanden was du meinst. ;) Aber vermutlich ist das sowieso eher eine Frage für die SVG-Spezialisten im entsprechenden Forum. Hat mit DbRep nichts zu tun, SVG zieht die Daten direkt aus der DB über das DbLog-Device.
Zitat
Und wie könnte ich die Ticks beim Eintragen in die Datenbank gleich korrekt als hh:mm eintragen und so dann als Basis für die Grafik nehmen?
Da gibt es meiner Meinung nach einmal den Weg über ein Userreading im HourCounter Device oder eine Umrechnung beim Abspeichern in der DB über DbLog valueFn.
Wichtig wäre aber vornweg die mathematische Definition des Zielwertes aus den Ticks, damit man eine beschreibende Funktion dafür erstellen kann. D.h. wie wäre die mathematische Ableitung von hh:mm aus x Ticks.
Wenn das noch nicht klar ist, müsstest du das erst einmal herausbekommen.
Grüße,
Heiko
Hallo,
die mathematische Funktion ist ganz einfach
86400 Ticks oder Sekunden sind 1 Tag, d.h. 1h entspricht 3600 Ticks, und 1 Minute sind 60 Ticks.
Warum da das PWM bzw. PWMR-Modul mit Ticks rechnet weiss ich auch nicht (oder bilde ich mir das nur ein und es sind tatsächlich Sekunden gemeint...)
Viele Grüße
Wolfgang
Zitat von: DS_Starter am 06 Oktober 2020, 18:15:24
Sollte ich wohl dann um 00:00, 00:05 und 00:10 usw. ausführen...
Das ist keine schlechte Idee nicht alles zur gleichen Zeit loslaufen zu lassen, auch wegen dem Ressourcen-Verbrauch der verwendeten nicht blockierenden Arbeitsweise (Stichwort BlockingCall).
Ich bin auch gerade auf der Suche nach einem Best Practise um mehrere DbRep Set-Befehle zum Schreiben von Min, Max und Average täglich effizient abzuarbeiten. Ein Versuch mit einem At, welches hintereinander mehrere Set Befehle abarbeitet scheitert folgendermaßen.
defmod a_midnight1 at *22:43 \
set Rep.MinMax minValue writeToDB;;\
set Rep.MinMax maxValue writeToDB
2023-01-04 22:43:00 DbRep Rep.MinMax running
2023-01-04 22:43:00 DbRep Rep.MinMax Timeout: process terminated
2023-01-04 22:43:00 DbRep Rep.MinMax running
2023-01-04 22:43:00 DbRep Rep.MinMax 2023-01-04_21-49-46__WP__Aussentemperatur_R1T__MAX__no_aggregation: 7.5000
2023-01-04 22:43:00 DbRep Rep.MinMax db_lines_processed: 1
2023-01-04 22:43:00 DbRep Rep.MinMax done
2023-01-04 22:43:00 DbLog myDbLog CacheOverflowLastNum: 0
Muss ich wirklich haufenweise At-Devices im 5 Sekunden Rhythmus anlegen oder hat da jemand eine effizientere Methode gefunden?
Gibt es eine effiziente Methode , um z.B. das "Done" des aktiven DbRep Befehls abzuwarten bevor der nächste Befehl gestartet wird?
ZitatMuss ich wirklich haufenweise At-Devices im 5 Sekunden Rhythmus anlegen oder hat da jemand eine effizientere Methode gefunden?
Nein.
ZitatGibt es eine effiziente Methode , um z.B. das "Done" des aktiven DbRep Befehls abzuwarten bevor der nächste Befehl gestartet wird?
Es es gibt neben sicherlich vielen anderen Methoden zwei wesentliche Möglichkeiten.
Vorab die Info, dass die Philosophie bei DbRep ist, regelmäßig wiederkehrende Aufgaben in je einem Device abzubilden.
Ich z.B. habe über 100 DbRep definiert und entsprechend ihrer Aufgaben attributiert.
Man macht das einfach per FHEM copy Befehl und passt das kopierte Device dann etwas an und definiert nicht immer neu ... einfach halten.
1. Du erstellst dir je ein DbRep für minValue, maxValue, averageValue und die Befehle alle in ein at-Device wie du es schon
gemacht hast, nur eben mit verschiedenen DbRep's.
Wichtig: Du brauchst in dem Fall genügend RAM-Speicher. Es gibt auch das globale Attribut blockingCallMax welches
eingesetzt werden kann um den HS-Verbrauch zu begrenzen.
2. Die Chain-Methode die ich einsetze und ich dir auch empfehle. Hier nutzt du das Attr executeAfterProc im DbRep.
Im 1. von den 3 DbReps setzt du
executeAfterProc = set <2> maxValue writeToDB
und im 2. DbRep setzt du
executeAfterProc = set <3> averageValue writeToDB
Die ganze Chain startest du in einem at mit:
set <1> minValue writeToDB
Wenn das 1. DbRep mit seiner Aufgabe fertig ist, startet es automatisch über executeAfterProc das 2. DbRep und das wiederum nach Abschluß startet das 3. DbRep.
So läuft immer nur ein Vorgang der Reihe nach durch.
LG,
Heiko
WOW Super ;D
Ich setzte nun auch die Chain Methode ein.
Danke für den Tipp.
Könnte evt. auch im Wiki als Best Practice hilfreich sein.
Aber für DbRep ist das irgendwie das falsche Unterforum, oder?
Ja. Ist schon ein alter Thread. Kann wohl nur wowogiengen oder ein Admin nach "Sonstiges" verschieben ?
Ich habe mich hier angehängt weil ich meist mit der Forumsuche eher zu passenden Diskussionen komme als auf der Suche nach geeigneten Unterforen.
Was wäre denn das richtige Forum? "Sonstiges" ?
Bei "Frontends" sind schöne untergeordnete Boards angelegt. Sowas würde ich mir eigentlich für alle Devices wünschen. Da wäre dann alles beisammen.
Zitat von: Ajuba am 05 Januar 2023, 22:30:58
Was wäre denn das richtige Forum? "Sonstiges" ?
https://forum.fhem.de/index.php/topic,13092.0.html