Hallo,
ich möchte das u.a. folgende Userreading in die myUtilys auslagern.
batterie {my $val=ReadingsVal("test", "sauger", 0);;$val=~s/battery:.([-\d.]+)/$1/eg;;return $1},
Wie muss ich den Code anpassen, damit ich ein Reading zurück bekomme?
Hallo,
ins Tiefblaue,
glaube auf mehrere Fragen die du mglw. hast kann dir ein Thread (https://forum.fhem.de/index.php/topic,112785.msg1071245.html#msg1071245) von mir weiterhelfen zu optimieren ?
Zu deiner Frage, mein ich, du suchst einfach nach setreading ?
Gruß
Thomas
Dort habe ich nicht das passende gefunden, bzw sehe es nicht.
So funktioniert der Code in der Eingabezeile, aber nicht in der myUtilys.
{my $val=ReadingsVal("robo_status", "sauger", 0);;$val=~s/battery:.([-\d.]+)/$1/eg;;fhem("setreading Robovac batterie $1");
my $val1=ReadingsVal("robo_status", "sauger", 0);;$val1=~s/play:.([\w]+)/$2/eg;;fhem("setreading Robovac play $2")}
Was stimmt da noch nicht?
Der Code ist mir etwas merkwürdig, wollte ich gerade schreiben.
Aber wenn Du sagst funktioniert - aber nicht in der myUtilys dann zeig doch mal bitte deine myUtilys - meinst Du eigentlich die 99_myUtils.pm ? Vielleicht ist diese Datei ja grundlegend verkehrt?
Gruß Otto
package main;
use strict;
use warnings;
use POSIX;
use Time::Local;
sub
robovacUtils_Initialize($$)
{
my ($hash) = @_;
}
sub robovac() {
{my $val=ReadingsVal("robo_status", "sauger", 0);;$val=~s/battery:.([-\d.]+)/$1/eg;;fhem("setreading Robovac batterie $1");
my $val1=ReadingsVal("robo_status", "sauger", 0);;$val1=~s/play:.([\w]+)/$2/eg;;fhem("setreading Robovac play $2")}
}
1;
dacht ichs mir :o
https://wiki.fhem.de/wiki/99_myUtils_anlegen
Machs bitte nochmal richtig :)- Du hast ja gesagt die Datei heisst myUtilys - bei deinem Inhalt müsste sie 99_robovacUtils.pm heissen?!
ZitatDer Name der Programmdatei muss mit dem Namen der Initialize-Routine übereinstimmen. Wenn Sie Ihr Programm also 99_Werkzeugkasten.pm nennen, muss die im code dargestellte initialize-Routine sub Werkzeugkasten_Initialize heißen.
Zusätzlich: In der Eingabezeile müssen die ; verdoppelt werden. In der 99_myUtils.pm genügen einfache. Doppelte sind nicht immer aber manchmal falsch.
Doppelte {{ Code .. }} braucht es auch nicht.
Der zweite Codeteil dürfte nicht funktionieren:
my $val1=ReadingsVal("robo_status", "sauger", 0);;$val1=~s/play:.([\w]+)/$2/eg;;fhem("setreading Robovac play $2")
$1 ist der erste match, $2 wäre der zweite Groupmatch - klingt jetzt für Dich eventuell wie böhmische Dörfer - soll es auch :)
Eigentlich geht es so: $val1=~ /play:.([\w]+)/ in $1 steht dann der Inhalt der Treffer von ([\w]+) Du brauchst an der Stelle kein search/replace ein match reicht. ;)
Hier kannst Du gut testen und findest weitere Erklärungen: https://regex101.com/r/K7iXLA/1
Deine Abfragen sehen so nach Reading Events aus. Ich bin mir nicht sicher ob der Inhalt der Readings wirklich so ist wie Du suchst.
Danke, es klingt für mich wirklich nach böhmische Dörfer. Die Benennung und Ansteuerung des ausgelagerten Codes habe ich richtig, nur hier nicht richtig benannt.
Nochmal Schritt für Schritt...
Reading lesen: wird in Variable $val geschrieben
my $val=ReadingsVal("robo_status", "sauger",0);
Reading filtern: $val wird gefiltert und soll in $2 geschrieben werden
$val=~s/play:.([\w]+)/$2/eg;
Reading zurück schreiben: $2 soll in ein reading geschrieben werden
fhem("setreading Robovac batterie $2");
Den Code hatte ich auf der angegebenen Seite zuvor auch getestet, funktioniert auch als userreading.
In der dargestellten Variante erhalte ich die folgende Fehlermeldung in der Fhem Konsole, weis aber nicht woran es liegt?
Usage: setreading <name> [YYYY-MM-DD HH:MM:SS] <reading> <value>
where <name> is a single device name, a list separated by comma (,) or a regexp. See the devspec section in the commandref.html for details.
Wo ist der, oder die Fehler?
Zeigst Du mal bitte ein list robo_status
Und probiere bitte diese beiden Varianten (meine und Deine) in deiner Eingabezeile:
{my $val1='play: willi';;$val1=~ /play:.([\w]+)/;;return $1}
{my $val='play: willi';;$val=~s/play:.([\w]+)/$2/eg;;return $2}
Wenn meine falsch ist und Deine das liefert was Du willst, dann hast Du Recht :)
MOBIL
Arbeitszimmer
Kinderzimmer
Fabian
Schlafzimmer
Wohnzimmer
Küche
Bad/WC
Flur
Garten
Beschattung
Heizung/Klima
Wetter
Tür/Tor
Kamera
TV/Radio
Home
Homekit
Unsorted
icoEverything Everything
Logfile
Commandref
Edit files
Event monitor
Update
UpdateCheck
Internals:
FUUID 6022efd8-f33f-804b-0ed7-957e1ef3adaf58e8
NAME robo_status
NR 1519
STATE Batterie: 100
TYPE dummy
READINGS:
2021-02-13 11:07:05 batterie 100
2021-02-13 11:07:05 error 0
2021-02-13 11:07:05 gohome true
2021-02-13 11:07:05 play true
2021-02-13 11:07:05 sauger / > eufy-robovac@1.4.3 start /opt/fhem/robovac / > node start.js "bf60a803b02612aab9nf4r" "ddc7a3f8c3528fb4" "status" / / / play: true / direction: undefined / workmode: auto / gohome: true / speed: Standard / find: undefined / battery: 100 / error: 0 /
2021-02-13 10:39:18 setting 101
2021-02-13 11:07:05 speed Standard
2021-02-13 11:07:05 state start
Attributes:
group RoboVac
stateFormat Batterie: batterie
userReadings sauger { my ($error, @content) = FileRead({FileName => "/opt/fhem/robovac/log.txt", ForceType => "file"});; return join(" / ", @content)},
play {my $val=ReadingsVal("$name", "sauger", 0);;$val=~s/play:.([\w]+)/$1/eg;;return $1},
gohome {my $val=ReadingsVal("$name", "sauger", 0);;$val=~s/gohome:.([\w]+)/$1/eg;;return $1},
batterie {my $val=ReadingsVal("$name", "sauger", 0);;$val=~s/battery:.([-\d.]+)/$1/eg;;return $1},
error {my $val=ReadingsVal("$name", "sauger", 0);;$val=~s/error:.([-\d.]+)/$1/eg;;return $1},
speed {my $val=ReadingsVal("$name", "sauger", 0);;$val=~s/speed:.([\w]+)/$1/eg;;return $1},
setting {my $val=ReadingsVal("$name", "sauger", 0);;$val=~s/"*"([\d]+)/$1/eg;;return $1}
Siehe mein Beispiel (hatte gerade editiert) Du hast die Bedeutung von $1 und $2 nicht verstanden!
Also nimm doch deinen Code erstmal so wie er ist und schreibe als letztes einfach immer $1 in Dein Reading.
my $name ='robo_status';
my $val=ReadingsVal("$name", "sauger", 0);$val=~s/speed:.([\w]+)/$1/eg;setreading $name speed $1
Optimieren und schön machen kommt später.
Wo willst Du Deine Sub denn dann aufrufen? In deinem userReadings sauger? Das wird nicht funktionieren.
Hallo,
für ein Reading funktioniert dies.
Bei 2 bekomme ich eine Fehlermeldung.
Can't locate object method "batterie" via package "100" (perhaps you forgot to load "100"?) at ./FHEM/99_robovacUtils.pm line 18.
my $name ='Robovac';
my $val=ReadingsVal("robo_status", "sauger", 0);
$val=~s/battery:.([\w]+)/$1/eg;setreading $name batterie $1;
$val=~s/gohome:.([\w]+)/$2/eg;setreading $name gohome $2;
Die sub rufe ich testweise mit {robovac()}
auf, was auch funktioniert.
Zitat von: Otto123 am 13 Februar 2021, 11:23:50
Also nimm doch deinen Code erstmal so wie er ist und schreibe als letztes einfach immer $1 in Dein Reading.
Wenn das userReading
gohome {my $val=ReadingsVal("$name", "sauger", 0);;$val=~s/gohome:.([\w]+)/$1/eg;;return $1},
funktioniert, wieso kommst Du überhaupt auf $2?
Zitat von: Otto123 am 13 Februar 2021, 11:17:21
Siehe mein Beispiel (hatte gerade editiert) Du hast die Bedeutung von $1 und $2 nicht verstanden!
ACK.
Außerdem verstehe ich nicht, warum du plötzlich in einem Device "Robovac" readings setzen möchtest - oder war Sinn und Zweck der Übung der Auslagerung, die Readings in einem anderen Gerät zu erzeugen?
my $name ='Robovac';
...
... ;setreading $name batterie $1;
Mal ein Beispiel basierend auf dem Wissen das mir in dem oben verlinkten Thread vermittelt worden ist und den Matches aus dem List.
Du müsstest eigentlich nur noch das sauger-userReading mit FileRead ergänzen (das hab ich im Dummy mit setreading gesetzt gehabt) definieren, mein ich:
defmod du_testy dummy
attr du_testy room Test
attr du_testy setList on off
attr du_testy userReadings play {robovac1($name,ReadingsVal($name,"sauger",0))},\
gohome {robovac2($name,ReadingsVal($name,"sauger",0))},\
batterie {robovac3($name,ReadingsVal($name,"sauger",0))},\
error {robovac4($name,ReadingsVal($name,"sauger",0))},\
speed {robovac5($name,ReadingsVal($name,"sauger",0))},\
setting {robovac6($name,ReadingsVal($name,"sauger",0))}
setstate du_testy on
setstate du_testy 2021-02-13 12:52:08 batterie 100
setstate du_testy 2021-02-13 12:52:08 error 0
setstate du_testy 2021-02-13 12:52:08 gohome true
setstate du_testy 2021-02-13 12:52:08 play true
setstate du_testy 2021-02-13 12:20:58 sauger / > eufy-robovac@1.4.3 start /opt/fhem/robovac / > node start.js "bf60a803b02612aab9nf4r" "ddc7a3f8c3528fb4" "status" / / / play: true / direction: undefined / workmode: auto / gohome: true / speed: Standard / find: undefined / battery: 100 / error: 0 /
setstate du_testy 2021-02-13 12:45:09 setting Standard
setstate du_testy 2021-02-13 12:52:08 speed Standard
setstate du_testy 2021-02-13 12:52:08 state on
##############################################
# $Id: myUtilsTemplate.pm 21509 2020-03-25 11:20:51Z rudolfkoenig $
#
# Save this file as 99_myUtils.pm, and create your own functions in the new
# file. They are then available in every Perl expression.
package main;
use strict;
use warnings;
sub robovacUtils_Initialize {
my $hash = shift//return;
return;
}
# Enter you functions below _this_ line.
sub robovac1 {
my $name = shift;
my $val = shift;
$val=~/play:.([\w]+)/;
return $1;}
sub robovac2 {
my $name = shift;
my $val = shift;
$val=~/gohome:.([\w]+)/;
return $1;}
sub robovac3 {
my $name = shift;
my $val = shift;
$val=~/battery:.([-\d.]+)/;
return $1;}
sub robovac4 {
my $name = shift;
my $val = shift;
$val=~/error:.([-\d.]+)/;
return $1;}
sub robovac5 {
my $name = shift;
my $val = shift;
$val=~/speed:.([\w]+)/;
return $1;}
sub robovac6 {
my $name = shift;
my $val = shift;
$val=~/"*"([\d]+)/;
return $1;}
1;
Wenns auch nur mit einer Sub geht bin ich gespannt auf diesen Weg, erstmal komm ich nicht drauf.
@stefan-dd Du hast jetzt ziemlich viele meiner Hinweise ignoriert oder einfach nicht darüber gesprochen. Solange Du nicht klar kommunizierst was Du gemacht und verstanden hast, sehe ich diese Baustellen:
Deine Datei 99_myUtils.pm ist eventuell mehrfach falsch.
Du hast das Prinzip des Groupmatch mit regExp nicht verstanden. (Die Sache mit $2)
Du bist nicht klar, welches Device Du jetzt wie mit Readings beschicken willst.
Arbeite bitte alle Hinweise (Und Links!) von Thomas und mir nochmal durch und frage wieder wenn noch was unklar ist. Aber liefere dann bitte einen kompletten Satz Informationen. Und frage gezielt was Du nicht verstanden hast. Ansonsten wird das nix.
ZitatWenns auch nur mit einer Sub geht bin ich gespannt auf diesen Weg, erstmal komm ich nicht drauf.
Mag keinen neuen Thread dazu aufmachen, missbrauche mal diesen, passt doch auch und es fuchst mich.
Mir kam kurze Zeit später eine Möglichkeit das mit einer Funktion umzusetzen, klappt auch.
Indem man der Funktion den Namen des userReadings übergibt und mit if in der myUtils prüft welcher Zweig zuständig sein soll.
Meine Frage an die Erfahrenen : Richtiges Vorgehen oder gehts noch anders ?
Anhand diese Beispiels erschließt sich mir immer noch nicht was es bringt. Das gesamte Konstrukt wird doch deutlich komplizierter?
Ein Vorteil wäre doch wenn der Punkt wo die Daten in die Datei geschrieben werden, eine einzige Sub gestartet wird die auf einen Rutsch alle Readings setzt. Ich bekomme doch hier im Beispiel die userReadings in eine kürzere Form wenn ich den unnützen Code entferne, anstatt 5 x die Übergabe von 2 Parametern.
Wer triggert eigentlich den Dummy? Eigentlich wird doch dieser Dummy offenbar mit einem 'Hops Hops' Konstrukt wie ein notify verwendet?
Aber gut darum ging es stefan vielleicht nicht.
Ja, du hast in allen aufgeführten Punkten recht. Vmtl. braucht man meine Aufgabenstellung nie.
ZitatEin Vorteil wäre doch wenn der Punkt wo die Daten in die Datei geschrieben werden, eine einzige Sub gestartet wird die auf einen Rutsch alle Readings setzt.
Dann gehts aber auch nur noch mit setreading
und rotem ? ... ?Zitat
Wer triggert eigentlich den Dummy?
Na ein on/off in meinem Beispiel. Ich hab halt einen Dummy genommen zum nachvollziehen, hätt auch ne Datei erstellen können und dann mit FileRead auslesen, mir gings aber doch nur um ein Beispiel zum nachvollziehen.