FHEM Forum

FHEM => Automatisierung => Thema gestartet von: betateilchen am 17 Februar 2014, 01:12:07

Titel: [Wunsch] 93_DbLog - einfache Funktion um Readings auszulesen
Beitrag von: betateilchen am 17 Februar 2014, 01:12:07
Ich bin auf der Suche nach Funktionen analog zu ReadingsVal und ReadingsTimestamp, mit denen sich jedes beliebige aktuelle Reading eines beliebigen Devices aus der Datenbank abfragen lassen.

Hierzu habe ich mir folgendes für die 93_DbLog ausgedacht:



sub
DbLog_Get($@)
{
  my ($hash, @a) = @_;

return dbReadings($hash,@a) if $a[1] =~ m/^Readings/;

  return "Usage: get $a[0] <in> <out> <from> <to> <column_spec>...\n".

...

sub dbReadings($@) {
my($hash,@a) = @_;
my $dbhf= $hash->{DBHF};
return 'Wrong Syntax for ReadingsVal!' unless defined($a[4]);
my $query = "select VALUE,TIMESTAMP from history where DEVICE= '$a[2]' and READING= '$a[3]' order by TIMESTAMP desc limit 1";
my ($reading,$timestamp) = $dbhf->selectrow_array($query);
$reading = ($reading) ? $reading : $a[4];
$timestamp = ($timestamp) ? $timestamp : $a[4];
return $reading if $a[1] eq 'ReadingsVal';
return $timestamp if $a[1] eq 'ReadingsTimestamp';
return "Syntax error: $a[1]";
}



Damit kann ich nun mittels


get MySqlLog ReadingsVal       BMP180 pressure-nn 77
get MySqlLog ReadingsTimestamp BMP180 pressure-nn 77


jedes beliebige Reading abfragen. Der Aufruf ist identisch zu ReadingsVal() und ReadingsTimestamp, nur dass die Klammern fehlen.

BMP180 = deviceName
pressure-nn = readingName
77 = default
Titel: Antw:[Wunsch] 93_DbLog - einfache Funktion um Readings auszulesen
Beitrag von: rudolfkoenig am 17 Februar 2014, 09:28:01
Die Funktionalitaet mit deutlich komplexeren Syntax gibt es schon fuer FileLog und DbLog, und wird von SVG.pm verwendet.
Siehe http://fhem.de/commandref.html#FileLogget bzw. http://fhem.de/commandref.html#DbLogget

Titel: Antw:[Wunsch] 93_DbLog - einfache Funktion um Readings auszulesen
Beitrag von: betateilchen am 17 Februar 2014, 10:37:09
Hallo Rudi,

kenn ich, und damit habe ich gestern bereits mehrere Stunden (!) verbracht, ohne das gewünschte Ergebnis zu bekommen.
Genau die Komplexität ist das Problem. Fürs Plotten mag das wunderbar funktionieren - aber vermutlich auch NUR fürs Plotten.

Hast Du eigentlich verstanden, WAS ich haben will?
EINEN einzigen bestimmten - nämlich den letzten (ich weiss also weder ein FROM noch ein TO!) - geloggten Wert eines Readings. Mehr nicht. Und dafür eine EINFACHE Lösung.

Viele Grüße
Udo
Titel: Antw:[Wunsch] 93_DbLog - einfache Funktion um Readings auszulesen
Beitrag von: betateilchen am 17 Februar 2014, 10:48:12
achja, wo wir grade beim Wünschen sind, ich hätte gerne in der DbLog Struktur noch ein Feld, in dem der Host geloggt wird, der die Daten in die Datenbank schickt  8)
Titel: Antw:[Wunsch] 93_DbLog - einfache Funktion um Readings auszulesen
Beitrag von: Wuppi68 am 17 Februar 2014, 13:13:55
Hallo betateilchen,

wäre nicht allen geholfen, wenn man direkt einen SQL String abschicken kann?
Titel: Antw:[Wunsch] 93_DbLog - einfache Funktion um Readings auszulesen
Beitrag von: rudolfkoenig am 17 Februar 2014, 13:38:57
ZitatHast Du eigentlich verstanden, WAS ich haben will?

Erst nach dieser Erklaerung.
So aehnlich wie OldValue(), aber auch fuer Readings.
Titel: Antw:[Wunsch] 93_DbLog - einfache Funktion um Readings auszulesen
Beitrag von: betateilchen am 17 Februar 2014, 14:05:04
nein, so ähnlich wie ReadingsVal(), nur nicht aus dem Device, sondern den geloggten Wert aus der Datenbank.

Hintergrund:

Bei mir loggen drei fhem Installation gemeinsam in eine Datenbank (auf einer zentralen 4. Hardware) und ich möchte das Plotten und die RSS-Generierung auf diese vierte Hardware verlegen.

Auf dieser Hardware sind keinerlei devices vorhanden (ausser den SVG und RSS) aber die Datenbank mit den zu verwendenden Werten. Für das Plotten funktioniert das auch jetzt schon problemlos. Aber in den RSS-layouts muss ich aktuelle einzelne ReadingsVal() ermitteln, was bisher in dieser Konstellation nicht funktioniert.
Titel: Antw:[Wunsch] 93_DbLog - einfache Funktion um Readings auszulesen
Beitrag von: betateilchen am 17 Februar 2014, 20:40:37
Aus Performancegründen macht es viel mehr Sinn, auf die Tabelle "current" zuzugreifen, dann kann man das "Limit 1" und das "order by" komplett weglassen.


sub dbReadings($@) {
my($hash,@a) = @_;
my $dbhf= $hash->{DBHF};
return 'Wrong Syntax for ReadingsVal!' unless defined($a[4]);
my $query = "select VALUE,TIMESTAMP from current where DEVICE= '$a[2]' and READING= '$a[3]'";
my ($reading,$timestamp) = $dbhf->selectrow_array($query);
$reading = ($reading) ? $reading : $a[4];
$timestamp = ($timestamp) ? $timestamp : $a[4];
return $reading if $a[1] eq 'ReadingsVal';
return $timestamp if $a[1] eq 'ReadingsTimestamp';
return "Syntax error: $a[1]";
}


Endlich hab ich den Sinn der Tabelle current verstanden - auch wenn die scheinbar nur bei MySQL Logging existiert, bei SQlite ist die bei mir immer leer.
Titel: Antw:[Wunsch] 93_DbLog - einfache Funktion um Readings auszulesen
Beitrag von: justme1968 am 17 Februar 2014, 22:03:36
wie in dem anderen thread schon gesagt :) die ist nicht leer sondern pro prozess in memory gecached.

wenn du das cachen abschaltest wie es ganz ursprünglich mal war wird es genau so wie history auf platte geschrieben und ist zu sehen.

leider leider die dann performance  erheblich.

gruss
  andre
Titel: Antw:[Wunsch] 93_DbLog - einfache Funktion um Readings auszulesen
Beitrag von: betateilchen am 17 Februar 2014, 22:09:34
Warum ist das Verhalten bei sqlite und bei mysql derartig unterschiedlich?

Das select * from current funktioniert in mysql, aber nicht in sqlite.
Titel: Antw:[Wunsch] 93_DbLog - einfache Funktion um Readings auszulesen
Beitrag von: JoeALLb am 06 März 2014, 10:42:52
sqlite speichert die Werte nicht ind er Tabelle, sondern in einer Memory-Tabelle.
Meines Wissens ist diese nur für die aktuelle Verbindung verfügbar.
Titel: Antw:[Wunsch] 93_DbLog - einfache Funktion um Readings auszulesen
Beitrag von: betateilchen am 06 März 2014, 10:52:19
Danke für den 27. Versuch, mir das erklären zu wollen, dadurch wird Dein Hinweis aber auch nicht zielführend. Denn ich nutze ja für die Abfrage die bestehende Verbindung.

Und warum man für SQLITE diese Extrawurst brät, ist mir nach wie vor unklar, die immer wieder angebrachten Performancegründe können definitiv nicht der wirkliche Grund sein. (Das hab ich inzwischen mit 100.000 Datensätzen getestet!) Ich arbeite gerade (aufgrund einer ohnehin bestehenden Socket-Problematik in diesem Modul) an einer tiefen Analyse der Verbindungsabläufe und bin auf der Suche nach einer wirklichen Optimierung und Fehlerbehebung. Da im Modul beim Loggen transaktional gearbeitet wird, macht es z.B. keinen Sinn, das auto-commit aktiviert zu lassen, das alleine schon für erhebliche Performance-Problem sorgt. Der technische Ablauf des Loggens innerhalb des Moduls muss m.E. grundlegend optimiert werden. Sobald ich da konkrete Vorschläge habe, werde ich die natürlich kundtun.

Titel: Antw:[Wunsch] 93_DbLog - einfache Funktion um Readings auszulesen
Beitrag von: justme1968 am 06 März 2014, 10:53:59
ja. ich glaube das hab ich schon ein paar mal versucht zu erklären.

bei sqlite wird für current explizit eine temporäre in memory tabelle verwendet und die ist nur für die connection zu sehen die sie auch angelegt hat.

wenn du statt dessen eine normale tabelle verwendest ist current auch für andere connections zu sehen. das war füher mal so ist aber sehr viel langsamer. da konnte man current glaube ich aber noch nicht abschalten. d.h. eigentlich könnte man die optimierung auch wieder raus bauen und statt dessen current nicht verwenden wenn man man es nicht braucht.

gruss
  andre
Titel: Antw:[Wunsch] 93_DbLog - einfache Funktion um Readings auszulesen
Beitrag von: betateilchen am 06 März 2014, 10:55:19
siehe meinen letzten Beitrag - ich verwende die aktuelle Verbindung...

Laßt mich doch einfach mal schrauben ;) Diese ganzen workarounds sind doch alles keine Lösungen.

Heute haben wir die SET-Funktionen bekommen, das finde ich schonmal klasse.
Und hier im Thread gehts um eine neue Funktion, um Readings auslesen, und eigentlich nicht um die technischen Hintergründe des Moduls selbst.