ReadingsGroup: Fragen zu Perl-Code, longpoll und valueStyle

Begonnen von Reinerlein, 23 April 2015, 13:48:04

Vorheriges Thema - Nächstes Thema

Reinerlein

Hallo Andre,

ich bin es mal wieder :)
Ich habe ein paar readingsGroups zusammengebaut, die auch ganz gut funktionieren, mir sind da nur ein paar Sachen aufgefallen, die ich mal kurz mit dir besprechen wollte.

1) In eingebettetem Perl-Code darf kein '=' (Gleichheitszeichen) vorkommen.
Beispiel:

define heizung_Stellventile readingsGroup type=HeatingThermostat:mode,desiredTemperature,valveposition <Summe>,<>,<>,<{myCalculateReading('type=HeatingThermostat','valveposition',0,'+').' %'}>
geht nicht, wegen des Gleichheitszeichens bei der Devspec-String-Übergabe an meine eigene Prozedur. Die letzte Zeile wird dann komplett ausgelassen, und gar nicht ausgeführt, die anderen (meine Heizungsthermostate) werden normal angezeigt.

Ich habe das als Workaround in URL-Encoded umgebaut (und in meiner Prozedur entsprechend zurückkodiert):

define heizung_Stellventile readingsGroup type=HeatingThermostat:mode,desiredTemperature,valveposition <Summe>,<>,<>,<{myCalculateReading('type%3DHeatingThermostat','valveposition',0,'+').' %'}>


Das ist für mich jetzt mehr eine Unschönheit, die anderen aber vielleicht als echte Hürde begegnet...

2) In dem Beispiel werden die Werte der Heizungsthermostate per longpoll aktualisiert. Da meine Summenberechnung letztendlich auf den darüber dargestellten Zuständen basiert, wäre es super, wenn auch diese Zeile neu berechnet werden würde, wenn sich irgendeine Zeile darüber ändert (meine Prozedur zum Ausrechnen also nochmal aufgerufen werden würde).
Geht das irgendwie, oder kann man das irgendwie ermöglichen?

Eine @-Angabe dahinter habe ich schon versucht:

define heizung_Stellventile readingsGroup type=HeatingThermostat:mode,desiredTemperature,valveposition <Summe>,<>,<>,<{myCalculateReading('type=HeatingThermostat','valveposition',0,'+').' %'}@valveposition>


3) An der oben genannten ReadingsGroup habe ich das Attribut 'valueStyle' gesetzt, um die Zahlen rechtsbündig darzustellen:

attr heizung_Stellventile valueStyle { desiredTemperature => 'style="text-align:right"', valveposition => 'style="text-align:right"' }

Das funktioniert auch gut. Allerdings habe ich auf diese Art keine Möglichkeit die Darstellung der Werte meines Perl-Ergebnisses zu beeinflussen, oder doch?
Wenn ja, wie lautet der Schlüssel dafür, den ich bei valueStyle einsetzen muss?

Danke schon mal für deine Mühen...

Grüße
Reiner

justme1968


na ich hoffe doch die funktionieren mehr als nur gut :)

1. das problem mit dem = ist das die define zeile per regex 'geparsed' wird und das = zwischen internal und wert erwartet wird. für leerzeichen und kommas kann ich das problem umgehen da diese eine ebene tiefer auftauchen.

am besten ist das das = hier zu vermeiden. z.b. durch ausweichen auf ein anderes zeichen wie # oder in dem man die Argumente als hash übergibt (type=>'HeatingThermostat').

die <{}>... variante ist aber eigentlich 'veraltet' es ist besser ...,!meinDummyReading,... zu verwenden. durch das ! kannst du ein reading einbauen das auch dann angezeigt wird wenn es im device nicht vorhanden ist. da es ein normales reading ist kannst du es dann ganz normal über alle value attribute beeinflussen. in deinem fall würdest du das myCalculateReading aus valueFormat aufrufen.

2. dafür ist genau das @<reading> anhängsel gedacht. das geht aber immer nur im kontext eines devices. d.h. einer zeile die am anfang ein device spezifiziert. deine summen zeile hat aktuell keinen device kontext

ich würde den device kontext herstellen in dem ich das ergebnis der berechnung mit setreading in ein reading der readingGroup schreibe und dann dieses wie ein ganz normales reading anzeige. die berechnung würde ich vermutlich eher über ein notify triggern.

statt dem notify funktioniert eventuell auch das aufsummieren in valueFormat.

in beiden fällen triggert die ändernung von valveposition die neuberechnung und das setreading triggert dann die aktualisierung der summe.

3. die strings aus den <> ausdrücken kannst du per nameStyle formatieren. das ist aber nicht so flexibel da der eine style für alle elemente gilt. wenn du aber wie vorgeschlagen über die 'neue' ! variante gehst hast du ein normales reading das du ganz normal über valueStyle formatieren kannst.


ich bin schon eine weile am überlegen eine möglichkeit einzubauen solche summen (oder andere Verknüpfungen) über spalten oder zeilen direkt als feature in die readingsGroup einzubauen.

gruss
  andre

ps: zeig doch mal einen screenshot


gruss
  andre
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

Reinerlein

Hi Andre,

natürlich funktionieren die ReadingsGroups hervorragend :) Ich bin total begeistert, mit wie wenig Code man alle Möglichen Sammelinformationen auf den Bildschirm bekommt...
Ich verwende diese Summenbildung mittlerweile an mehreren Stellen. Wenn du da also eine Aggregationsidee hast... gerne :)

Die Idee mit einem Extra-notify würde ich ungern verfolgen. So wichtig ist eine longpoll-Aktualisierung nicht. Da habe ich lieber eine kompakte ReadingsGroup ohne weitere Anhängsel, und muss halt mal manuell aktualisieren.

Zum Aggregieren habe ich mir die kleine myCalculateReading gebaut, die eine DevSpec bekommt, welches Reading verarbeitet werden soll, einen Startwert und die Operation. Optional kann man noch einen String angeben, der die Variable $value vor der Verarbeitung konvertieren kann.

Hier mal die Prozedur:

sub myCalculateReading($$$$;$) {
  my ($devspec, $readingsName, $startValue, $operator, $valueConverter) = @_;
 
  # Workaround für readingsGroup, da dort im Perl-Code kein Gleichheitszeichen vorkommen darf
  $devspec =~ s/%3D/=/gi;
 
  foreach my $device (devspec2array($devspec)) {
    my $value = ReadingsVal($device, $readingsName, undef);
   
    if (defined($value)) {
      if (defined($valueConverter)) {
        $value = eval $valueConverter;
      }
     
      $startValue = eval $startValue.$operator.$value;
    }
  }
 
  return $startValue;
}
Ist wirklich einfach für meine Zwecke gehalten.

Mit der folgenden ReadingsGroup erhält man dann die besagte Übersicht über die Max-Stellventile:

define heizung_Sammler_Stellventile readingsGroup type=HeatingThermostat:mode,desiredTemperature,valveposition <Summe>,<>,<>,<{myCalculateReading('type%3DHeatingThermostat','valveposition',0,'+').' %'}>

Irgendwie konnte ich deine Idee mit dem Aufruf im valueFormat nicht korrekt einbauen. Das klappt bei mir noch nicht, habe aber auch noch nicht viel Zeit investiert...

Dann habe ich mir noch eine Übersicht über die Batterie-Zustände gebaut, für die ich dann auch diesen optionalen Konverter brauche, um aus OK eine Zahl zu machen.
Die ReadingsGroup:

define global_Batteries readingsGroup .*:battery <Anzahl OK>,<{myCalculateReading('.*','battery',0,'+','getBatteryValue($value)')}> <Anzahl nicht OK>,<{myCalculateReading('.*','battery',0,'+!','getBatteryValue($value)')}>


Dafür habe ich dann noch den eigentlichen Konverter angelegt:

sub getBatteryValue($) {
  my ($value) = @_;
 
  return 1 if (lc($value) eq 'ok');
  return 0;
}


Wenn du also eine Aggregation baust, brauchst du auf jeden Fall eine Möglichkeit, die Werte *vor* der eigentlichen Aggregation zu konvertieren, da man oftmals Nicht-Zahlenwerte verarbeiten muss (übrigens etwas was ich auch als direkte Möglichkeit im SVG- oder LogProxy-Modul sehr gut für die Darstellung meiner on/off Plots gebrauchen könnte :) )

Grüße
Reiner

justme1968

hallo reiner,

bitte probier noch mal das = im define.

ich habe eben noch etwas getestet und eigentlich sollte es gehen. ich vermute eher das sich irgendwo ein leerzeichen eingeschlichen hat. z.b. vor dem %. die machen definitiv probleme. die leerzeichen die in der ausgabe erscheinen sollen müssen als &nbsp; kodiert werden. (ja. manchmal geht es weil ich workarounds eingebaut habe. vermeiden ist aber besser)

zur aggregation: die idee ist beim aufbau der tabelle für alle zellen den original wert und den über valueFormat geänderten wert zu merken. darauf kann könnte man dann in einem <{}> ausdruck zugreifen. longpoll würde dann über einen künstlichen trigger gesteuert wenn in einer teile oder spalte dieser <{}> ausdruck vor kommt. mit ein paar default routinen zum summieren, mittelwert bilden oder gähnlichem würde es dann z.b. auf einen solchen aufruf am ende einer spalte hinauslaufen: ...,<{rgSum($COLUMN)}>,... oder noch besser über die ! variante weil man dann per valueStyle z.b. die summe einfärben kann wenn 'anzahl nicht ok' > 0 ist.

gruss
  andre
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

Reinerlein

Hi Andre,

ich habe das mit dem Gleichheitszeichen nochmal versucht. Kein Erfolg. Die Zeile fehlt einfach, Leider wird auch nix dazu im Log ausgegeben (obwohl ich Verbose an der ReadingsGroup auf 5 gesetzt habe), sodass ich dir keinen tieferen Einblick bieten kann.

Zu der Aggregation:
Du brauchst auch etwas um diesen Originalwert zu transferieren, oder deine Aggregat-Funktion muss mit Texten wie "on" oder "off" umgehen können...

Grüße
Reiner

justme1968

schau dir mal die test version hier: http://forum.fhem.de/index.php/topic,36893.0.html an. da gibt es eine erste version die werte aggregieren kann.

gruss
  andre
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968