Hallo Community,
ich denke das ist eine sehr spezielle Frage, aber ist es Möglich über DBRep bestimmte Einträge eines Devices X herauszufinden und dann die Zeit und datum zu verändern.
Spezielles Beispiel:
01.06.2020 12:00:00 Device X mit seinen Werten
ändern nach:
31.05.2020 00:00:00 Device X mit seinen Werten
ich möchte also die Zeit des Eintrages um 36 Stunden verschieben.
Gruß Knallkopp_02
Das geht natürlich.
Besipiel:
set <DbRep> sqlCmd UPDATE history SET TIMESTAMP='2020-05-31 13:30:23', TYPE=TYPE, EVENT=EVENT, VALUE=VALUE, UNIT=UNIT WHERE DEVICE='psize' AND TIMESTAMP='2020-05-31 13:30:13';
Ändert den Timestamp des Datensatzes mit Device "psize" und Timestamp "2020-05-31 13:30:13" auf den Timestamp "2020-05-31 13:30:23".
Kannst natürlich Variablen verwenden für automatische Änderungen.
Ein Datenbank-Backup ist natürlich Pflicht wenn die Daten in der DB wichtig sind.
Grüße,
Heiko
Nach einigem Testen bekomme ich schonmal Werte, die auch dem Entsprechen, was ich gern haben will.
SELECT * FROM history WHERE (TYPE='ECMDDEVICE') AND (DEVICE='Mastervolt_Wechselrichter') AND (READING IN ('WR_1a_Gestern_Laufzeit','WR_1a_Gestern_kWh','WR_1b_Gestern_Laufzeit','WR_1b_Gestern_kWh','WR_2_Gestern_Laufzeit','WR_2_Gestern_kWh','WR_3_Gestern_Laufzeit','WR_3_Gestern_kWh')) AND TIMESTAMP >= DATE(NOW()) - INTERVAL 0 DAY;
damit holt er mir alle Werte von heute vom gewünschten Device (absicht das es erstmal nur SELECT ist)
Jetzt stehe ich aber auf dem Schlauch, wie ich das dynamisch mache, denn er soll das ja jeden Tag aufs neue machen und die geholten Daten um ca 36h in die Vergangenheit schieben. Also eine Art "DATE(YESTERDAY())" Zeit 00:00:00
ich habe soetwas gefunden
SELECT DATEADD(month, -2, '2017/08/25') AS DateAdd;
aber irgendwie komme ich damit nicht weiter.
Evtl hast du da auch noch einen Tip für mich.
Gruß Knallkopp_02
Versuchs mal damit:
SELECT * FROM history WHERE (TYPE='ECMDDEVICE') AND (DEVICE='Mastervolt_Wechselrichter') AND (READING IN ('WR_1a_Gestern_Laufzeit','WR_1a_Gestern_kWh','WR_1b_Gestern_Laufzeit','WR_1b_Gestern_kWh','WR_2_Gestern_Laufzeit','WR_2_Gestern_kWh','WR_3_Gestern_Laufzeit','WR_3_Gestern_kWh')) AND TIMESTAMP >= DATE(NOW()) - INTERVAL 1 DAY;
oder
SELECT * FROM history WHERE (TYPE='ECMDDEVICE') AND (DEVICE='Mastervolt_Wechselrichter') AND (READING IN ('WR_1a_Gestern_Laufzeit','WR_1a_Gestern_kWh','WR_1b_Gestern_Laufzeit','WR_1b_Gestern_kWh','WR_2_Gestern_Laufzeit','WR_2_Gestern_kWh','WR_3_Gestern_Laufzeit','WR_3_Gestern_kWh')) AND TIMESTAMP >= DATE_SUB(DATE(NOW()), INTERVAL 1 DAY);
Damit kannst du heute immer die Daten von gestern bearbeiten.
Grüße,
Heiko
Beim SELECT stimmt soweit alles mit DAY 0, weil das die Daten vom heutigen Tag ausgibt,
Jetzt bin ich am UPDATE dran und versuche das Dynamisch hin zu bekommen. Folgendes funktioniert, ist aber nicht Dynamisch:
UPDATE history SET TIMESTAMP='2020-06-01 12:00:00' WHERE (TYPE='ECMDDEVICE') AND (DEVICE='Mastervolt_Wechselrichter') AND (READING IN ('WR_1a_Gestern_Laufzeit')) AND TIMESTAMP >= DATE(NOW()) - INTERVAL 0 DAY LIMIT 1;
(aktuell für 1 Reading, damit ich nicht zu viel kaputt mache wenn was schief geht)
das
SET TIMESTAMP='2020-06-01 12:00:00'
versuche ich aktuell Dynamisch zu bekommen, häge aber fest.
SET TIMESTAMP(day, -1, DATE(NOW()))
funktioniert nicht
Hast du evlt noch eine Idee?
Gruß Knallkopp_02
So sollte es klappen:
UPDATE history SET TIMESTAMP=DATE_SUB(DATE(NOW()), INTERVAL 1 DAY) WHERE (TYPE='ECMDDEVICE') AND (DEVICE='Mastervolt_Wechselrichter') AND (READING IN ('WR_1a_Gestern_Laufzeit')) AND TIMESTAMP >= DATE(NOW()) - INTERVAL 0 DAY LIMIT 1;
Ich persönlich würde aber etwas Perl verwenden in einer kleinen Routine ähnlich:
{
my $seltime = FmtDateTime($time); # jetzt im Format yyyy-mm-dd hh:mm:ss
my $uptime = FmtDateTime($time-129600); # jetzt minus 36 Stunden
fhem (qq{set <DbRep> sqlCmd UPDATE history SET TIMESTAMP="$uptime" WHERE (TYPE='ECMDDEVICE') AND (DEVICE='Mastervolt_Wechselrichter') AND (READING IN ('WR_1a_Gestern_Laufzeit')) AND TIMESTAMP >= "$uptime";});
}
Das könnte man dann in einem notify, at usw. einbauen. Die Variablen mit den Zeiten könnte man ganz beliebig anpassen und auch DEVICE, READING etc. noch als Variable ausführen um total flexibel zu sein.
DbRep-Device musst du natürlich einsetzen.
Habs nicht getestet, aber so in der Art würde ich es machen.
Das sieht soweit schon sehr gut aus, würde auch gern bei der ersten Variante bleiben, weobei ich nicht mal sagen kann warum.
Eine kleine Ändereung brauche ich aber noch, welche ich nicht hin bekomme.
UPDATE history SET TIMESTAMP=DATE_SUB(DATE(NOW()), INTERVAL 1 DAY), ...
gibt mir ja das Datum von gestern mit der Uhrzeit 00:00:00 aus, wie bekomme ich die Zeit auf 23:59:59,
habe es mit
UPDATE history SET TIMESTAMP=DATE_SUB(DATE(NOW()), INTERVAL 1 DAY) '23:59:59', ...
getestet, aber da gibt es eine Fehlermeldung
Gruß Knallkopp_02
Schau mal z.B. auf dioeser Seite -> https://www.w3schools.com/sql/func_mysql_date_sub.asp
MySQL DATE_SUB hat verschiedene Optionen. Damit kannst du probieren und das richtige für dich finden.
Kannst auch mal auf der offiziellen MySQL Doku schauen -> https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html.
Grüße,
Heiko
Zitat von: Knallkopp_02 am 02 Juni 2020, 09:38:42
gibt mir ja das Datum von gestern mit der Uhrzeit 00:00:00 aus, wie bekomme ich die Zeit auf 23:59:59,
viele Wege führen nach Rom:
SELECT DATE_SUB(DATE(NOW()), INTERVAL 1 SECOND)
SELECT DATE_ADD(DATE(DATE_SUB(NOW(), INTERVAL 1 DAY)), INTERVAL 86399 SECOND);
SELECT TIME_FORMAT(DATE_SUB(DATE(NOW()), INTERVAL 1 DAY), "%Y-%m-%d 23:59:59")
wofür brauchst du das überhaupt? Verstehe nicht so ganz den Sinn dahinter bei festgestellten Werten die Timestamps zu ändern?
Das hat geholfen, ist für einen Anfänger echt viel und vorallem doch sehr verschachtelt was so dabei rauskommt.
sqlCmd UPDATE history SET TIMESTAMP=ADDTIME((DATE_SUB(DATE(NOW()), INTERVAL 1 DAY)), '23:59:59') WHERE (TYPE='ECMDDEVICE') AND (DEVICE='Mastervolt_Wechselrichter') AND (READING IN ('WR_1a_Gestern_Laufzeit','WR_1a_Gestern_kWh','WR_1b_Gestern_Laufzeit','WR_1b_Gestern_kWh','WR_2_Gestern_Laufzeit','WR_2_Gestern_kWh','WR_3_Gestern_Laufzeit','WR_3_Gestern_kWh')) AND TIMESTAMP >= DATE(NOW()) - INTERVAL 0 DAY;
Das ist jetzt das was dabei rausgekommen ist und auch zu funktionieren scheint.
Wie sieht das aus, wenn ich das per Perl in einem DOIF machen wollen würde, brauche ich dann dafür seperates <DbRep> oder kann ich das auch über ein vorhandenes machen oder brauche ich überhaupt eins? und was bedeutet das qq am Anfang.
fhem (qq{set <DbRep> sqlCmd UPDATE history SET TIMESTAMP=ADDTIME((DATE_SUB(DATE(NOW()), INTERVAL 1 DAY)), '23:59:59') WHERE (TYPE='ECMDDEVICE') AND (DEVICE='Mastervolt_Wechselrichter') AND (READING IN ('WR_1a_Gestern_Laufzeit','WR_1a_Gestern_kWh','WR_1b_Gestern_Laufzeit','WR_1b_Gestern_kWh','WR_2_Gestern_Laufzeit','WR_2_Gestern_kWh','WR_3_Gestern_Laufzeit','WR_3_Gestern_kWh')) AND TIMESTAMP >= DATE(NOW()) - INTERVAL 0 DAY;;});
@Guybrush
Problem ist, dass ich Daten der Wechselrichter erst 1 Tag später abrufen kann, damit sie komplett sind. Sind die gesamt Laufzeit und produzierten kW. Das bedeutet im SVG Graph, dass die Anzeige nicht stimmt / verschoben ist, die könnte man zwar verschieben, aber das hat am Monatsenden nicht geklappt, da feht in der Anzeige der letzte Tage im Monat.
Gruß Knallkopp_02
Zitat von: Knallkopp_02 am 02 Juni 2020, 11:30:04
Problem ist, dass ich Daten der Wechselrichter erst 1 Tag später abrufen kann, damit sie komplett sind. Sind die gesamt Laufzeit und produzierten kW. Das bedeutet im SVG Graph, dass die Anzeige nicht stimmt / verschoben ist, die könnte man zwar verschieben, aber das hat am Monatsenden nicht geklappt, da feht in der Anzeige der letzte Tage im Monat.
was für Wechselrichter hast du? Sma? Die kannst du direkt über Modbus in Echtzeit auslesen...
Das ist außerdem viel zu kompliziert was du vor hast. Leg dir dafür einen Mysql Trigger an. Dann kannst du dir alles andere sparen und hast vor allem niemals falsche werte in deiner db.
DELIMITER //
CREATE TRIGGER Wechselrichter
BEFORE INSERT
ON history
FOR EACH ROW BEGIN
IF OLD.DEVICE = '<DEVICE>' THEN
SET NEW.TIMESTAMP = DATE_SUB(DATE(OLD.TIMESTAMP), INTERVAL 1 SECOND);
END IF;
END//
DELIMITER ;
ist nicht getestet, müsste aber so funktionieren. <DEVICE> durch deinen Devicename austauschen.
Zitat
.... brauche ich dann dafür seperates <DbRep> oder kann ich das auch über ein vorhandenes machen oder brauche ich überhaupt eins? und was bedeutet das qq am Anfang.
Du brauchst nicht unbedingt ein separates DbRep und kannst ein vorhandenes nutzen wenn es für dich passt. Du brauchst eines wenn du keine eigene Routine schreiben willst.
qq ist eine Vereinfachung um besser mit " umgehen zu können.
DB Trigger kannst du natürlich auch verwenden (bei MySQL). Viele Möglichkeiten gibt es.
@Guybrush
Es sind Wechselrichter von der Firma Mastervolt, ich dachte auch erst, das diese Modbus verwenden würden, dies ist aber nicht der Fall. Habe hier im Forum viel Hilfe in Anspruch nehmen müssen, damit ich zumindest die ersten Daten bekommen konnte, da ich von Grund auf alles selber Programmieren musste. Funktionieren tut es über SerialtoUSB und ECMD. Als Programmiere würde man wohl sagen DOKUMENTATION DER SCHNITTSTELLE = " ".
Da ich mich erst in solche Sachen einarbeiten muss fällt mir das noch recht schwer zu verstehen, was da alles passiert.
@DS_Starter
Danke für die Info
@all
Danke für die Hilfe, ich werde mich jetzt erstmal damit näher beschäftigen und etwas rumtesten. Grundlegend mach es das jetzt was es soll.
Danke und Gruß Knallkopp_02