Hallo,
ich habe ein eigenes Python-Skript geschrieben, dass Messwerte als Ausgabe zurückliefert:
pi@raspberrypi ~ $ sudo /home/pi/ultrasonic2.py
2015-08-02_09:14:58 Abstand_zum_Sensor: 250.9 cm, Füllhöhe: -0.9 cm, Füllstand: 0%
p@raspberrypi ~ $
Wie kann ich dieses Skript regelmäßig (ca. alle 15 Minuten) aufrufen und die 3 Messwerte in fhem einlesen (Logfile und auch Graph erzeugen)?
Mein derzeitiger Lösungsansatz war mit "at" das Kommando regelmäßig aufrufen und dann in ein Dummy Device einlesen.
Mit einem einfachem Skript, dass nur einen Messwert zurückliefert funktioniert das auch schon.
Wie kann ich mehrere Messwerte zuweisen, also nur die 3 Zahlenwerte?
Meine derzeitigen Definition mit "at":
define Zisterne_Pct dummy
define Zisterne_Skript at +*00:01:00 {fhem "set Zisterne_Pct ".`sudo /home/pi/ultrasonic2.py`}
liefert folgende Fehlermeldung:
/home/pi/ultrasonic2.py:80: Traceback (most recent call last):
File "/home/pi/ultrasonic2.py", line 88, in <module>
main()
File "/home/pi/ultrasonic2.py", line 72, in main
print("%s Abstand_zum_Sensor: %.1f cm, F\xfcllh\xf6he: %.1f cm, F\xfcllstand: %.0f%%" % (date, distlistavg, fuellhoehe, fuellstand))
UnicodeEncodeError: 'ascii' codec can't encode character '\xfc' in position 51: ordinal not in range(128)
2015.08.02 09:38:16 3: set Zisterne_Pct : no set value specified
2015.08.02 09:38:16 3: Zisterne_Skript: no set value specified
Ich darf wohl nur einen Wert an das Dummy Device zuweisen und müsste dann für jeden Messwert ein DummyDevice erzeugen.
Eigentlich hätte ich gerne den Skript-Output in einem Logdevice und könnte dann mit SVG den Graphen erzeugen.
Wie bekomme ich das hin?
Gruß
mayerflash
Hallo,
define Zisterne_Skript at +*00:01:00 {`sudo /home/pi/ultrasonic2.py >> /opt/fhem/log/Zisterne.log`}
sollte dein Logfile liefern (ungetestet). Könnte auch per cron-Job erledigt werden.
Die Fehlermeldung betrifft die Umlaute in deinem py-Script:Pragmatischerweise einfach weglassen (oder nach UTF8 kodieren).
Gruß
Hans
Bin unterwegs, drum kann ich keinen Code anbieten (aber nachreichen).
Warum läßt du dein py Skript nicht einfach die Werte direkt an fhem senden, statt sie nur auf der Kommandozeile auszugeben und das zu catchen?
Wenn du willst, poste ich dir heute Abend ein einfaches Codeschnippselchen :)
du kannst in einem dummy mehr als ein reading unterbringen. entweder in dem du readingList verwendest oder setreading statt set verwendest.
von aussen einen wert in den dummy zu bekommen geht auf unterschiedliche arten. z.b. per wget und passender url, per telnet und kommandos oder per fhem.pl:fhem.pl $SERVER "setreading $VARNAME $VARVALUE"
gruss
andre
Zitat von: Rince am 02 August 2015, 12:11:13
Bin unterwegs, drum kann ich keinen Code anbieten (aber nachreichen).
Warum läßt du dein py Skript nicht einfach die Werte direkt an fhem senden, statt sie nur auf der Kommandozeile auszugeben und das zu catchen?
Wenn du willst, poste ich dir heute Abend ein einfaches Codeschnippselchen :)
Das hört sich genau nach dem an, was ich will. Ich bin mal gespannt. :)
Ok,
soweit mal meine Codeschnippsel dazu:
Vorbemerkung:
Ich lese die Dinger aus ner Config Datei aus, das muss man nicht so machen ;)
(Das eigentlich spannende ist die letzte Zeile ;) )
import argparse #um den Namen vom Config File anzugeben
import urllib #das macht den eigentlichen Zauber
import json #in dem Format ist meine Config gespeichert
# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-c", "--conf", required=True,
help="path to the JSON configuration file; eg try: >Webcam_Face_2_fhem.py --conf conf.json")
args = vars(ap.parse_args())
#ConfigFile laden
conf = json.load(open(args["conf"]))
client = None
# fhem Kommando erzeugen
url = (conf["fhem_host_port"])
request = (conf["fhem_request"])
command = (conf["fhem_command"])
fhem = url + request + command
# so wird dann ein Befehl an fhem abgesetzt
urllib.urlopen(fhem)
Die Teile aus dem Config File (conf.json)
{
"fhem_host_port": "http://192.168.5.31:8083",
"fhem_request": "/fhem?cmd=",
"fhem_command": "set%20az_Andi_vor_PC%20true"
}
Ein Besipielaufruf wäre dann:
test.py --conf "conf.json"
Diese Lösung funktioniert, bis auf zwei Dinge:
Zum einen kennt sie keinen Usernamen/Passwort (wobei man das sicherlich nachrüsten kann)
Zum anderen kennt sie bis jetzt keine automatische Codierung der Befehlszeile, du musst also so Dinge wie Leerzeichen = %20 selber hinterlegen
Wie gesagt, du musst kein Config File basteln, du kannst es auch hart verdrahten in deinem Skript
Apropo:
Kann man in einer json Datei Bemerkungen reinschreiben?
Sowas wie # in anderen Sprachen???
(# funktioniert nicht...)
Jein:-) Schau mal hier: http://stackoverflow.com/questions/244777/can-i-comment-a-json-file
Ich habs befürchtet;)
Aber die Idee, eine neue zusätzliche Variable mit den Kommentaren zu füllen ist nicht so abwegig. Jedenfalls wenn Speicher keine wirklich wesentliche Rolle spielt ;)
Sagen wir so:
Auf einem Amiga würde ich das nicht machen....
Zitat von: Rince am 02 August 2015, 21:31:51
Ok,
soweit mal meine Codeschnippsel dazu:
<schnipp>
Diese Lösung funktioniert, bis auf zwei Dinge:
Zum einen kennt sie keinen Usernamen/Passwort (wobei man das sicherlich nachrüsten kann)
Zum anderen kennt sie bis jetzt keine automatische Codierung der Befehlszeile, du musst also so Dinge wie Leerzeichen = %20 selber hinterlegen
Wie gesagt, du musst kein Config File basteln, du kannst es auch hart verdrahten in deinem Skript
OK, Danke für deine Rückmeldung. Interessante Idee, die Werte an den Webserver zu schicken (vor allem übers Netzwerk).
Das würde jetzt für mein Skript möglich sein, aber ich suche noch etwas universelleres, dass ich auch lokalen Skript/Programm-Output direkt in fhem auswerten kann.
Ich habe jetzt im Dummy-Device mit "setreading" schon mal den ganzen Output-String als ein Reading drinstehen:
Readings
ultrasonic2_output 2015-08-02_23:32:37 Abstand_zum_Sensor: 250.2 cm, Füllhöhe: -0.2 cm, Füllstand: 0% Das Logdevice funktioniert auch schon.
Wie kann ich jetzt über RegularExpressions mir die 3 Werte herauspicken und diese als separate Readings im Dummy-Device darstellen?
Hier nochmal meine derzeitige Definition:
define dummy_Zisterne dummy
define Zisterne_Skript at +*00:01:00 {fhem "setreading dummy_Zisterne ultrasonic2_output ".`sudo /home/pi/ultrasonic2.py`}
define Zisterne_log FileLog ./log/zisterne-%Y-%m.log dummy_Zisterne.*
Hallo,
ich habe es jetzt mit einer Änderung in meinem Skript-Output geschafft alle Readings zur Verfügung zu stellen. 8)
So sieht der Output von meinem Python-Skript jetzt aus:
pi@raspberrypi ~ $ sudo ./ultrasonic3.py
250.1
0.2
0
pi@raspberrypi ~ $
Hier meine Definition:
define zisterne_readings CustomReadings
attr zisterne_readings interval 300
attr zisterne_readings readingDefinitions COMBINED:qx(sudo /home/pi/ultrasonic3.py),zisterne_abstand:,zisterne_fuellhoehe:,zisterne_fuellstand:
define zisterne_log FileLog ./log/zisterne-%Y-%m.log zisterne_readings.*
define SVG_zisterne_log_1 SVG zisterne_log:SVG_zisterne_log_1:CURRENT
So sehen jetzt die Readings aus:
| state | OK | 2015-08-03 07:36:37 |
| zisterne_abstand | 250.1 | 2015-08-03 07:36:37 |
| zisterne_fuellhoehe | 0.2 | 2015-08-03 07:36:37 |
| zisterne_fuellstand | 0 | 2015-08-03 07:36:37 |
Perfekt! :D
Fällt jemandem noch etwas ein, wie man 2 oder mehr Werte aus einer Zeile Skriptoutput als Reading einlesen kann (am besten per RegularExpression gefiltert)?
Geht so etwas auch mit "CustomReading" und "COMBINED"?
Oder muss ich mir hier jedesmal ein Wrapper-Skript basteln, das den Output entsprechend aufbereitet?