Hauptmenü

readingsBulkUpdate

Begonnen von CoolTux, 21 Juli 2015, 16:59:51

Vorheriges Thema - Nächstes Thema

CoolTux


sub AMAD_Parse($$) {
   my($name,$valuestring) = @_;

   my @array=split('@@',$valuestring);
   foreach (@array){fhem("setreading $name $_\n");}
}


Wie kann ich hier ein readingsupdate mit dem empfohlenen readingsBeginUpdate, readingsBulkUpdate, readingsEndUpdate machen.
Leider weiß ich nicht wie viele Readings in der Tat reinkommen, daher die foreach Schleife.


Grüße
Leon
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

jensb

Hallo Leon,

wenn du in einem Modul bist, das seine eigenen Readings ändert, solltest du generell statt

{fhem("setreading $name $_\n");}

besser

readingsSingleUpdate($hash, $readingName, $readingValue, 1);

verwenden.

Dann ist auch der Umbau nicht mehr schwer. Zunächst solltest du den split so machen, dass du readingName und readingValue getrennt bekommst, indem du sie in einer Hash-Variablen pufferst. Anschließend kannst du folgendes machen:


readingsBeginUpdate($hash);
while (($t, $v) = each %buffer) {
  readingsBulkUpdate($hash, $t, $v) if (defined($v));
}
readingsEndUpdate($hash, 1);


Hast du den Modul-Hash nicht, aber bist zumindest in FHEM, kannst du ihn dir im Normalfall so holen:

my $hash = $defs{$name};


wobei $name der Modul-Instanzname ist.

LG, Jens

FHEM 6.1 - RPi 4 Raspbian 12 + PiTFT - OPi Zero Armbian 5.35
EnOcean - (W)LAN/Firmata: BMP180, TSL2561, SHT21, Heatronic 3, OBIS - WLAN/ESP8266: Gardena 1251, Zirkulationspumpe - RTL433: Oregon - Bluetooth - MQTT
Contributions: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/jensb

CoolTux

Hallo Jens,

Vielen Dank für Deine Antwort.
Ja ich bin in einem Modul welches seine eigenen Readings ändert. Es ist ein Modul was ich selber schreibe. Eigentlich habe ich keine Ahnung von FHEM Development und nur bedingt von Perl. Aber pah hat mal zu mir gesagt "keine Ahnung hatten wir alle mal, das ist keine Ausrede". Tja und nun sitze ich hier und pauke. Das besondere an dem Modul ist, so denke ich, das es seine Readings nicht holt sonder ungefragt zugesendet bekommt. Per http request mittels ?cmd=.

Das mit dem buffer hatte ich auch schon gelesen und auch probiert. Leider hatte ich Fehler bekommen. ein readingsSingleUpdate wäre nicht gut, da ja die Menge der zu aktualisierenden Readings unbekannt ist. Auf jeden Fall immer mehr wie eines, min 2.

Hier mal mein Modul, bitte nicht so genau auf die Funktionen achten, einige liegen nur brach da für später.

##############################################
# $Id: 98_AMAD.pm 8809 2015-07-21 11:09:00Z leongaultier $
package main;

use strict;
use warnings;

sub
AMAD_Initialize($)
{
  my ($hash) = @_;

  $hash->{DefFn}     = "AMAD_Define";
  $hash->{UndefFn}   = "AMAD_Undef";
  $hash->{AttrFn}    = "AMAD_Attr";
  $hash->{ParseFn}    = "AMAD_Parse";
  $hash->{AttrList}  = "readingList setList interval ". $readingFnAttributes;
}

###############################################################################

sub
AMAD_Define($$)
{
  my ($hash, $def) = @_;
  my $name = $hash->{NAME};
  my @a = split("[ \t][ \t]*", $def);

  return "Wrong syntax: use define <name> AMAD <IP>" if(int(@a) < 3);
  $hash->{".host"}  = $a[2];

  return undef;
}

################################################################################

sub AMAD_Undef($$)
{
    my ($hash, $arg) = @_;
    RemoveInternalTimer($hash);
    if(defined($hash->{helper}{RUNNING_PID}))
    {
     BlockingKill($hash->{helper}{RUNNING_PID});
    }
    return undef;
}

################################################################################

sub AMAD_Attr($$)
{
    my ($cmd,$name, $attrName,$attrVal) = @_;
my $hash = $defs{$name};

if ($cmd eq "set") {

   if ($attrName eq "interval")
   {
     if (int($attrVal) < 2) {$attrVal="5";}
     $hash->{".interval"}  = $attrVal;
     $attr{$name}{interval} = $attrVal;
   }
  }

   return undef;
}

###############################################################################

sub AMAD_Parse($$) {
   my($name,$valuestring) = @_;

   my @array=split('@@',$valuestring);
   foreach (@array){fhem("setreading $name $_\n");}
}

################################################################################

# Funktion welche von Automagic über http request aufgerufen wird und Infos überträgt

sub pushAutomagicInfo($$) {
   my($name,$valuestring) = @_;

   AMAD_Parse($name,$valuestring);
}

################################################################################

1;


Also das eigentliche Programm auf dem Handy oder Tablet heißt Automagic. Diverse Trigger stoßen unterschiedliche Flows an, welche Daten einsammeln und diese dann in Form von


http://fhem.local/fhem?cmd={pushAutomagicInfo('Device,readingName1 $reading1@@readingName2 $reading2....')}


sendet.

Die Funktion pushAutomagicInfo nimmt nur entgegen und gibt die Werte sofort weiter an die Funktion AMAD_Parse, welche dann entsprechend die Readings setzen soll.

So nun werde ich mal versuchen Deine Tips zu verinnerlichen und meine Funktion entsprechend an zu passen.
Kann ich mich wieder melden wenn ich nicht weiter komme? Also falls Du Lust und Zeit hast und ich tausend Fragen. Ich will das wirklich lernen.


Grüße
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

jensb

Hallo Leon,

du kannst gerne weiter Fragen stellen, ich werde Antworten, so gut ich kann. Habe mich selbst mit Trial and Error an die Sache heran getastet und inzwischen schon einen kleinen Überblick über die Möglichkeiten.

Die _Parse-Funktion ist normalerweise eine spezielle Funktion mit vordefinierter Parameterliste, da sie von anderen Modulen aufgerufen werden kann (z.B. vom Telnet-Server, wenn er Daten empfängt). Da du sie nur intern mit eigener Parameterliste verwendest, solltest du sie nicht in der _Initialize-Funktion als ParseFn registrieren. Funktionieren wird das aber auch ohne die Änderung.

LG, Jens
FHEM 6.1 - RPi 4 Raspbian 12 + PiTFT - OPi Zero Armbian 5.35
EnOcean - (W)LAN/Firmata: BMP180, TSL2561, SHT21, Heatronic 3, OBIS - WLAN/ESP8266: Gardena 1251, Zirkulationspumpe - RTL433: Oregon - Bluetooth - MQTT
Contributions: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/jensb

CoolTux

#4
Hallo,

Ich hatte das ganze vorher ohne Pars. Wusste nicht was das genau soll. Klang nur gut für mich als ich das gelesen hatte. Bleiben wir beim kleinsten gemeinsamen.
Och habe ein Modul was ich definieren und un-definieren kann. Ausserdem kann ich Attribute vergeben. Das mache ich mit den entsprechenden dafür vorgesehenen FHEM eigenen Funktionen.

Ich habe eine eigene Funktion, welche so aus schaut


sub pushAutomagicInfo($$) {
   
   my ($name, $pushstring) = @_;
   my $hash = $defs($name);
   my ($t,$v) = split('@@','@@'$pushstring);

   readingsBeginUpdate($hash);
   while (($t, $v) = each %buffer) {
      readingsBulkUpdate($hash, $t, $v) if (defined($v));
   }
   readingsEndUpdate($hash, 1);
}


Diese wird von extern aufgerufen. Mehr will ich erstmal nicht. Die Feinheiten kommen später. Die Funktion wird aufgerufen und Werte werden übergeben. Die Funktion verarbeitet die Werte und soll dann entsprechend der Werte die Readings setzen. Das alles soll erstmal die eine Funktion machen.

Ich habe noch Probleme mit dem Code. Ein Reload bringt folgende Fehlermeldung

Global symbol "$defs" requires explicit package name at ./FHEM/98_AMAD.pm line 74.
syntax error at ./FHEM/98_AMAD.pm line 74, near "$defs("
syntax error at ./FHEM/98_AMAD.pm line 75, near "'@@'$pushstring"
Global symbol "$hash" requires explicit package name at ./FHEM/98_AMAD.pm line 77.
Global symbol "%buffer" requires explicit package name at ./FHEM/98_AMAD.pm line 78.


Wo und wie definiere ich $defs ?
Sind bestimmt voll die Basics   :-[
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

jensb

#5
Hallo Leon,

da sieht für mich aus wie 2 Tippfehler:

Z74: my $hash = $defs{$name};

Z75: my ($t,$v) = split('@@',  $pushstring);

$defs wird von FHEM global definiert, deshalb kannst du einfach darauf zugreifen.

LG, Jens
FHEM 6.1 - RPi 4 Raspbian 12 + PiTFT - OPi Zero Armbian 5.35
EnOcean - (W)LAN/Firmata: BMP180, TSL2561, SHT21, Heatronic 3, OBIS - WLAN/ESP8266: Gardena 1251, Zirkulationspumpe - RTL433: Oregon - Bluetooth - MQTT
Contributions: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/jensb

CoolTux

#6
Ah ok das habe ich verstanden. Ich danke Dir

Aber wieso eigentlich nur

split('@@',  $pushstring);


@@ soll mein Trenner sein und keine Variable. das sieht so aus

('$device',readingname1 reading1@@readingname2 reading2@@...')


Wie kann ich jetzt mein $t und mein $v da rausbekommen?

Und ich habe noch ein


Global symbol "%buffer" requires explicit package name at ./FHEM/98_AMAD.pm line 78.
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

jensb

Hi Leon,

mein letzter Vorschlag behebt nur den Syntax-Error, aber er löst noch nicht die Aufgabe. Wollte dir noch etwas Arbeit lassen.  :D

Das ganze wird so nicht gehen, aber vielleicht etwa so:


  my @pairs = split('@@',  $pushstring);
  my %buffer;
  foreach (@pairs ) {
    my @pair = split(' ',  $_);
    $buffer{$pair[0]} = $pair[1];
  }


Damit hast du die Readings im %buffer und kannst weitermachen.

LG, Jens
FHEM 6.1 - RPi 4 Raspbian 12 + PiTFT - OPi Zero Armbian 5.35
EnOcean - (W)LAN/Firmata: BMP180, TSL2561, SHT21, Heatronic 3, OBIS - WLAN/ESP8266: Gardena 1251, Zirkulationspumpe - RTL433: Oregon - Bluetooth - MQTT
Contributions: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/jensb

CoolTux

supi damit komme ich weiter. aber ich denke ich werde statt einem leerzeichen einen selbst definierten 2. Trenner nehmen. Denn es kann auch mal vor kommen das ein Readingwert ein Leerzeichen hat. Da würde er ja dann falsch splitten oder?

PS: Mega DANK für Deine Geduld     ;D
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

jensb

Kein Thema, freut mich dass es geholfen hat.

Wenn du ein Leerzeichen in den Nutzdaten haben kannst, dann nimm einen anderen Trenner (z.B. "=").

Willst du aber beliebige Nutzdaten transportieren, muss du schon beim Eintüten ein zusätzliches Escapezeichen wählen (z.B. "\") und es in den Nutzdaten vor jeden Trenner schreiben. Dann kannst du den Trenner "=" und einen Trenner in den Nutzdaten "\=" unterscheiden. Hast du ein Escapezeichen in den Nutzdaten, muss auch das gedoppelt werden. Das macht das Parsen hinterher natürlich nicht leichter, aber zumindest eindeutig.

LG, Jens
FHEM 6.1 - RPi 4 Raspbian 12 + PiTFT - OPi Zero Armbian 5.35
EnOcean - (W)LAN/Firmata: BMP180, TSL2561, SHT21, Heatronic 3, OBIS - WLAN/ESP8266: Gardena 1251, Zirkulationspumpe - RTL433: Oregon - Bluetooth - MQTT
Contributions: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/jensb

CoolTux

Guten Morgen,

Ich musste gestern abbrechen, Kopfaua   ;D
Ich habe jetzt mal versucht unsere Ausarbeitungen zusammen zu bringen. Und zwar eins zu eins so wie Du es geschrieben hast. Ich denk mal beim verstehen und zusammen setzten habe ich bestimmt murx gemacht.


Das ist jetzt meine Funktion


sub pushAutomagicInfo($$) {

   my ($name, $pushstring) = @_;
   my $hash = $defs{$name};

   my @pairs = split('@@',  $pushstring);
   my %buffer;
   foreach (@pairs) {
      my @pair = split(' ', $_);
      $buffer{$pair[0]} = $pair[1];
   }
   readingsBeginUpdate($hash);
   my $t;
   my $v;
   while (($t, $v) = each %buffer) {
      readingsBulkUpdate($hash, $t, $v) if (defined($v));
   }
   readingsEndUpdate($hash, 1);

}


Und das kommt als Fehler


Not enough arguments for main::pushAutomagicInfo at (eval 67330) line 1, near "'automagicNexus5Marko,powerLevel 65@@powerPlugged 1')"


Es fehlt der Zusammenhang von

$buffer{$pair[0]} = $pair[1];

und $t $v, sehe ich das Richtig.
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

jensb

#11
Hi Leon,

ZitatNot enough arguments for main::pushAutomagicInfo
bedeutet, dass du diese Funktion mit keinem oder nur einem Argument aufgerufen hast, aber sie erwartet ja nun mal zwei, wegen des ($$).

LG, jensb
FHEM 6.1 - RPi 4 Raspbian 12 + PiTFT - OPi Zero Armbian 5.35
EnOcean - (W)LAN/Firmata: BMP180, TSL2561, SHT21, Heatronic 3, OBIS - WLAN/ESP8266: Gardena 1251, Zirkulationspumpe - RTL433: Oregon - Bluetooth - MQTT
Contributions: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/jensb

CoolTux

Juhu,

Ich werde irre das funktioniert. Hammer es geht. Frreuuuuuuu. Luftsprung

Melde mich wenn ich verstanden habe wieso das geht. lach

LG
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

CoolTux

Ok soweit blicke ich da durch. Muss unbedingt viel mehr Perl lesen.

Aber eines verstehe ich noch nicht


$buffer{$readings[0]} = $readings[1];


dem Skalar buffer wird das erste Element von readings zugewiesen aber was bedeutet  = $readings[1] und wieso die geschweiften klammern {$readings[0]}
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

jensb

%buffer ist eine Hash-Variable

mit $buffer{key} kann man auf einen gehashten Wert zugreifen (mit key = String), die {} sind die Zufgriffsoperatoren für Hashes

@readings ist eine Array-Variable

mit $readings[n] kann man auf die Werte zugreifen (mit n ab 0), die [] sind die Zugriffsoperatoren für Arrayelemente

LG, Jens
FHEM 6.1 - RPi 4 Raspbian 12 + PiTFT - OPi Zero Armbian 5.35
EnOcean - (W)LAN/Firmata: BMP180, TSL2561, SHT21, Heatronic 3, OBIS - WLAN/ESP8266: Gardena 1251, Zirkulationspumpe - RTL433: Oregon - Bluetooth - MQTT
Contributions: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/jensb