Hallo zusammen,
nachdem ich nun das Forum und andere Internetquellen auf den Kopf gestellt habe, ich finde keine Lösung:
FHEM empfängt Informationen eines ESP (NodeMCU). Der ESP liefert mir per Analog-Eingang die Bodenfeuchte. Die kommt als Reading auch super an
define ESPEasy_NodeMCU_3_BodenfeuchteSensor ESPEasy 192.168.100.233 80 ESPBridge NodeMCU_3_BodenfeuchteSensor
attr ESPEasy_NodeMCU_3_BodenfeuchteSensor IODev ESPBridge
attr ESPEasy_NodeMCU_3_BodenfeuchteSensor Interval 300
attr ESPEasy_NodeMCU_3_BodenfeuchteSensor group ESPEasy Device
attr ESPEasy_NodeMCU_3_BodenfeuchteSensor presenceCheck 1
attr ESPEasy_NodeMCU_3_BodenfeuchteSensor readingSwitchText 1
attr ESPEasy_NodeMCU_3_BodenfeuchteSensor room ESPEasy
attr ESPEasy_NodeMCU_3_BodenfeuchteSensor setState 3
hier das EventLog:
2020-04-22 11:57:19 ESPEasy ESPEasy_NodeMCU_3_BodenfeuchteSensor Analog: 260
2020-04-22 11:57:19 ESPEasy ESPEasy_NodeMCU_3_BodenfeuchteSensor presence: present
2020-04-22 11:57:19 ESPEasy ESPEasy_NodeMCU_3_BodenfeuchteSensor Ana: 260
Nun benötige ich den Bodenfeuchtewert für ein Powershell-Script, welches mein Sprinkleranlage steuert. Ich muss hier also den Wert 260 an das Script übergeben. Sollte eigentlich einfach sein. Habe dieses Device angelegt:
define Feuchte dummy
attr room ESPEasy
set Feuchte ReadingsVal("ESPEasy_NodeMCU_3_BodenfeuchteSensor","Analog",0)
ReadingsVal liefert aber nicht 260 sondern Datum / Zeit der letzten Abfrage. Also habe ich mit $EVENT / EVTPART experimentiert. Ich bekomme immer nur Datum / Zeit zurück.
Was mache ich falsch?
Also was Du über ReadingsVal erzählst kann ich nicht nachvollziehen. Den Zusammenhang mit $EVENT und $EVTPARTx kann ich auch noch nicht sehen, aber Dein code ist falsch!
Entweder
set Feuchte [ESPEasy_NodeMCU_3_BodenfeuchteSensor:Analog]
Oder
set Feuchte {(ReadingsVal("ESPEasy_NodeMCU_3_BodenfeuchteSensor","Analog",0))}
Besser
set Feuchte {(ReadingsNum("ESPEasy_NodeMCU_3_BodenfeuchteSensor","Analog",0))}
bzw
set Feuchte [ESPEasy_NodeMCU_3_BodenfeuchteSensor:Analog:d]
Siehe set magic in der Doku https://fhem.de/commandref_DE.html#set
Und falls Du von Powershell auf FHEM zugreifen willst, da hab ich was (https://github.com/heinz-otto/fhemcl). ;)
Gruß Otto
Hallo Otto,
DANKE für die rasend schnelle Antwort. :) Habe [ESPEasy_NodeMCU_3_BodenfeuchteSensor:Analog] jetzt über die GUI erstellt. Damit wird mir tatsächlich der gewünschte Wert in FeuchteState geschrieben. Jetzt hakt es nur noch mit der Aktualisierung. Und es stellt sich die Frage, warum ich den SET Befehl nicht in der fhem.cfg wiederfinden kann.
Zitat von: Qualle am 23 April 2020, 15:03:59
Hallo Otto,
DANKE für die rasend schnelle Antwort. :) Habe [ESPEasy_NodeMCU_3_BodenfeuchteSensor:Analog] jetzt über die GUI erstellt. Damit wird mir tatsächlich der gewünschte Wert in FeuchteState geschrieben. Jetzt hakt es nur noch mit der Aktualisierung. Und es stellt sich die Frage, warum ich den SET Befehl nicht in der fhem.cfg wiederfinden kann.
Weil du den einfach "nackt" in FHEMWeb eingegeben hast, er wird ausgeführt und fertig... ;)
Wozu soll da was in der fhem.cfg stehen!?
Frage: wie hast du das herausgefunden!? ;)
Gar nicht erst anfangen/angewöhnen in der cfg rumzuschreiben...
...außer über die fhem-Oberfläche klicken, max. "raw-Definition" Fenster...
EDIT: wenn du eine Aktualisierung möchtest, dann musst du dir überlegen "wann"/"wodurch" soll sie passieren!? Immer wenn sich der "Originalwert" ändert -> notify / immer alle 5min etc. -> at
https://wiki.fhem.de/wiki/Notify
https://wiki.fhem.de/wiki/Event_monitor
https://wiki.fhem.de/wiki/At
(und wie so oft in fhem: viele, viele weitere Möglichkeiten ;) )
EDIT2: und du wirst es nicht glauben, dann steht dazu auch was in der fhem.cfg ;)
Gruß, Joachim
Zitat von: Qualle am 23 April 2020, 15:03:59
Jetzt hakt es nur noch mit der Aktualisierung.
Wie willst DU denn aktualisieren? Immer dann wenn ein solcher Wert kommt?
Dann bau Dir ein notify hier steht wie https://wiki.fhem.de/wiki/Notify#Event_Monitor
Also einfach den Event mit Analog markieren, notify erzeugen, den Befehl reinschreiben fertig. Du kannst auch von dem notify dein Powershell Script aufrufen! ich zeig Dir gern wie :)
Und lass die Finger von der cfg.
Gruß Otto
Hallo Otto,
ich würde gern Dein Angebot annehmen. Ich kriege die richtige Syntax nicht hin. Ziel ist, das Powershellscript morgens per AT zu starten und ihm den Feuchtewert zu übergeben. Auf der Shell funktioniert dieser Befehl unter User fhem:
sudo pwsh /opt/_me/PwSh/SprinklerController-V2.ps1 -SensorValue 305
Nachdem ich auch Deinen Beitrag zum Thema Start externer Programme aus FHEM gelesen habe und dem neuen Wissen über die Syntax von ReadingsVal, habe ich diese Zeile erstellt:
{ qx "sudo pwsh -File /opt/_me/PwSh/SprinklerController_V2.ps1 -SensorValue (ReadingsVal("ESPEasy_NodeMCU_3_BodenfeuchteSensor","Analog",0))" }
In der FHEM Kommandozeile liefert das keinen Fehler, aber das Script wird nicht ausgeführt.
Vielen Dank
Frank
Hallo Frank,
Du nutzt powershell für Linux? Cool ;) Hab ich noch nicht probiert. Ist mir ein scheinbar komplexes Setup, ich arbeite gern mit ssh für Windows ;)
Nachfrage:
Funktioniert denn das in der FHEM Kommandozeile?
{qx(sudo pwsh /opt/_me/PwSh/SprinklerController-V2.ps1 -SensorValue 305)}
Den ReadingsVal kannst Du so nicht in die Zeile packen. Da wird einfach der Ausdruck an das Powershellscript als Parameter übergeben, nicht das Ergebnis. Außerdem beissen sich die " innerhalb von " ".
Eine Variante, extra Variable:
{ my $val=ReadingsVal("ESPEasy_NodeMCU_3_BodenfeuchteSensor","Analog",0);;qx "sudo pwsh -File /opt/_me/PwSh/SprinklerController_V2.ps1 -SensorValue $val" }
Andere Variante (String concatenation)
{ qx "sudo pwsh -File /opt/_me/PwSh/SprinklerController_V2.ps1 -SensorValue " . ReadingsVal("ESPEasy_NodeMCU_3_BodenfeuchteSensor","Analog",0)}
Ich bin nicht sicher ob er überhaupt pwsh findet: Was gibt Dir das zurück?
{qx(which pwsh)}
Gruß Otto
Hallo Otto,
Zeile 1 scheint nicht zu funktionieren. Kein Fehler. Ich habe das Pwsh Script darauf reduziert, dass es mir den SensorValue in eine Log Datei schreibt. Da kommt aber kein neuer Wert rein, wenn ich es aus FHEM versuche. Letzte Zeile gibt mir den Pfad zurück: /usr/bin/pwsh
Dann probier mal so
{qx(sudo /usr/bin/pwsh /opt/_me/PwSh/SprinklerController-V2.ps1 -SensorValue 305)}
Was hast Du getan damit fhem sudo darf?
Warum muss das ps1 Script überhaupt mit sudo laufen?
Wo braucht das erhöhte Rechte?
Wie hast Du fhem sudo gegeben?
Braucht pwsh höhere Rechte?
Also, ich habe gestern Abend lange an dem Thema gesessen. (Ja, ich bin kein Linux Experte, habe lediglich Grundkenntnisse) Um alle anderen Fehler auszuschließen, habe ich den Scriptaufruf auf der Shell getestet. Funktioniert mit root, mit sudo PI aber nicht mit FHEM. Mein Script meldete ständig Access denied auf das LogFile. Ich kann mit fhem direkt in das Log schreiben. Mindestberechtigung 666. Keine Ahnung, wo das Problem ist. Daher habe ich mit visudo in letzter Instanz FHEM zum Sudoer gemacht. Dann ging es. Verstehen kann ich das nicht.
Aber nein, es werden keine besonderen Rechte für pwsh benötigt. Standardmäßig geht die Installation ins Home. Ich habe den Ordner nach opt verschoben und einen symbolic link erstellt.
Kannst Du mal das Script posten?
Warum machst Du es eigentlich mit Powershell? Weil Du das von Windows her kannst? Ich sehe ja bisher gar keine Verbindung zu Windows? Ich frage rein aus Interesse :)
Ich würde gern verstehen was passiert ;)
Hallo Otto,
klar kann ich das Script posten. Warum ich das Mit PoSh mache? Weil ich seit 25 Jahren Windows administriere und PoSH einfach genial ist. Und seit ich eben die Möglichkeit habe PoSh auch auf dem Raspi zu programmieren, freue ich mich, nicht mehr mit Perl oder noch schlimmer (für mich) mit Python arbeiten zu müssen. Und ich habe natürlich auf meinem Noti eine perfekte Entwicklungsumgebung für PoSh und kann meine Bewässerungssteuerung einfach auch von dort starten bis Du ;) die Lösung für den Raspi gefunden hast.
Zum Script: Auf dem Raspi ist der Linux LogFilePath aktiv
$LogFilePath = "/opt/fhem/log/SprinklerLog-$myToday.log"
# $LogFilePath = "C:\Test\SprinklerLog-$myToday.log"
Und ich sende lediglich den $SensorValue einmal an WriteLog um zu prüfen, ob dieser übergeben wird und das Script auch tatsächlich läuft.
#Input: Bodenfeuchte
#
param(
[int][parameter(Mandatory=$true)]$SensorValue
)
$DebugPreference = "Continue"
$SprinklerSet = @{VornNord=0; VornSued=2; HintenSued=14; HintenNord=12; Hochbeet=13} # GPIO-Nummernzuordnung Verteiler
$SprinklerProzent = @{VornNord=100; VornSued=100; HintenSued=100; HintenNord=100; Hochbeet=20} # prozentualer Anteil der berechneten Laufzeit
$SprinklerGet = @{GetAllOff=16} # GPIO, die 1 ist, wenn alle Relais AUS sind
$MainWaterSet = @{SetMain1=12; SetMain2=14} # GPIO-Nummernzuordnung; beide GPIOs müssen AN sein, damit das Hauptwasser-Relais zieht
$MainWaterGet = @{GetMain1=13; GetMain2=15} # GPIO-Nummernzuordnung; über diese beiden GPIOs wird der Zustand der MainWaterSet GPIOs überwacht; 12=1 --> 13=0; 14=1 --> 15=1
$EspMainAddress = '192.168.100.232' # IP des NodeMCU2 (Hauptanschluss)
$EspSprinklerAddress = '192.168.100.231' # IP des NodeMCU1 (Verteiler)
$myToday = $(Get-Date -Format('yyyyMMdd'))
#$LogFilePath = "/opt/fhem/log/SprinklerLog-$myToday.log"
$LogFilePath = "C:\Test\SprinklerLog-$myToday.log"
# Unbedingt die Settings in Calculate-Timer beachten!!!
function Set-Gpio{
param(
[string][parameter(Mandatory=$true,Position=0)]$IpAddress,
[string][parameter(Mandatory=$true,Position=1)] [ValidateSet('set','longpulse')]$ToDo,
[int][parameter(Mandatory=$true,Position=2)] [ValidateRange(0,16)]$GpioNo,
[int][parameter(Mandatory=$true,Position=3)] [ValidateSet(0,1)]$Value,
[int][parameter(Position=4)] [ValidateRange(0,18000)]$TimerSec
)
if($ToDo -eq 'set'){$Htmlcode = "http://$IpAddress/control?cmd=gpio,$GpioNo,$Value"}
else{$Htmlcode = "http://$IpAddress/control?cmd=longpulse,$GpioNo,$Value,$TimerSec"}
Write-Debug "Set-GPIO: Sende: $htmlcode"
$Message = Invoke-WebRequest -Uri $Htmlcode
Write-Debug "Set-GPIO: Empfange: $Message"
Return $Message
}
function Get-Gpio{
param(
[string][parameter(Mandatory=$true,Position=0)]$IpAddress,
[int][parameter(Mandatory=$true,Position=1)] [ValidateRange(0,16)]$GpioNo
)
$Htmlcode = "http://$IpAddress/control?cmd=Status,GPIO,$GpioNo"
$Message = Invoke-WebRequest -Uri $Htmlcode
Write-Debug "Get-GPIO: Sende: $htmlcode"
Write-Debug "Get-GPIO: Empfange: $Message"
Return $Message
}
function Parse-EspMessage{
# parsed die Nachricht, die der ESP liefert (Kontrolle der GPIO Zustände)
param(
[string][parameter(Mandatory=$true)][parameter(Position=0)]$IpAddress
)
}
function Calculate-Timer{
# Berechnet aus dem Wert der Bodenfeuchte die Sekunden für longpulse
param(
[int][parameter(Mandatory=$true)]$mySensorValue
)
$Trocken = 450
$Nass = 300
$MaxTime = 30 #Minuten
$MinTime = 10 #Minuten
Write-Debug "Calculate-Timer: SensorValue: $mySensorValue"
# gt Trocken = Fehler; lt Nass = keine Bewässerung nötig
if(($mySensorValue -gt $Trocken) -or ($mySensorValue -lt $Nass)){$SprinklerTime = 0}
else{
$myFeuchteProzent = ($mySensorValue - $Nass)*100 / ($Trocken - $Nass)
$mySprinklerTime = (($MaxTime - $MinTime)*$myFeuchteProzent / 100) + $MinTime
}
Write-Debug "Calculate-Timer: FeuchteProzent: $myFeuchteProzent"
Write-Debug "Calculate-Timer: SprinklerZeit: $mySprinklerTime"
return $mySprinklerTime
}
function Get-AllGpioOff {
# Sicherstellen, dass alles AUS ist
$myReturnVal = 0
$StateString = "*`"state`": 1*"
$StateString15 = "*`"state`": 0*"
# für das Hauptventil gilt: GPIO 13 = 1, GPIO 15 = 0 in $MainWaterGet, dann sind die Relais sicher geschlossen, daher werden diese GPIOs explizit abgefragt
foreach ($GPIO in $MainWaterGet.GetEnumerator()){
$ReturnMsg = Get-Gpio -IpAddress $EspMainAddress -GpioNo $GPIO.Value
$PinString = "*`"pin`": $($GPIO.Value)*"
If($GPIO.Value -eq 13){
Write-Debug "Reset-GPIO Main: Empfange: $ReturnMsg"
If($ReturnMsg.Content -like $PinString -and $ReturnMsg.Content -like $StateString ){
Write-Debug "Reset-GPIO Main: Auswertung: OK"
} else {
$myReturnVal =+1
Write-Debug "Reset-GPIO Main: Auswertung: Fehler"
}
} else {
If($ReturnMsg.Content -like $PinString -and $ReturnMsg.Content -like $StateString15 ){
Write-Debug "Reset-GPIO Main: Auswertung: OK"
} else {
$myReturnVal =+2
Write-Debug "Reset-GPIO Main: Auswertung: Fehler"
}
}
}
# jetzt den Wasserverteiler abfragen
# hier gilt: Wenn alle Relais geschlossen sind ist GPIO "GetAllOff" = 1
foreach ($GPIO in $SprinklerGet.GetEnumerator()){
$PinString = "*`"pin`": $($GPIO.Value)*"
$ReturnMsg = Get-Gpio -IpAddress $EspSprinklerAddress -GpioNo $GPIO.Value
Write-Debug "Reset-GPIO Verteiler: Empfange: $ReturnMsg"
If($ReturnMsg.Content -like $PinString -and $ReturnMsg.Content -like $StateString ){
Write-Debug "Reset-GPIO Verteiler: Auswertung: OK"
} else {
$myReturnVal =+4
Write-Debug "Reset-GPIO Verteiler: Auswertung: Fehler"
}
Return $myReturnVal
}
}
Function Write-Log{
param
(
[String]
[Parameter(Mandatory=$true)]
$File,
[Parameter(Mandatory=$True)]
$Line
)
If(!(Test-Path -Path $File)){
New-Item -ItemType File -Force -Path $File
}
$LogLine = [string]::concat($(Get-Date -Format('yyyy-MM-dd_HH:mm:ss')),' - ',$Line)
Add-Content $File $LogLine
Write-Host $LogLine
}
# Hauptschleife
# Setze alle Relais auf 0
# Hauptventil
foreach ($GPIO in $MainWaterSet.GetEnumerator()){
Set-Gpio -IpAddress $EspMainAddress -ToDo set -GpioNo $GPIO.Value -Value 0
Write-Debug "Reset-GPIO Main: Rufe Set-GPIO"
}
# Verteilerventile
foreach ($GPIO in $SprinklerSet.GetEnumerator()){
Set-Gpio -IpAddress $EspSprinklerAddress -ToDo set -GpioNo $GPIO.Value -Value 0
Write-Debug "Reset-GPIO Main: Rufe Set-GPIO"
}
# Prüfe Startzustand (alles AUS)
$GPIOerror = Get-AllGpioOff
# $GPIOError muss 0 sein, dann sind alle Relais AUS
If($GPIOerror -eq 0){
Write-Log -File $LogFilePath -Line 'Alle Ventile geschlossen, starte Sprinklerlauf'
# Berechne die Laufzeit
$SprinklerTime = Calculate-Timer -mySensorValue $SensorValue
Write-Log -File $LogFilePath -Line "Bodenfeuchtewert: $SensorValue --> sprenge $SprinklerTime min pro Strang"
if ($SprinklerTime -gt 0){
# Starte Sprinklerlauf
foreach ($SprinklerGPIO in $SprinklerSet.GetEnumerator()){
# Ordne die passenden Prozente zu
$TimePercent = $SprinklerProzent.GetEnumerator() | Where-Object {$_.Key -eq $SprinklerGPIO.Key}
# Öffne Hauptventil für die ermittelte Zeit
foreach ($MainGPIO in $MainWaterSet.GetEnumerator()){
Set-Gpio -IpAddress $EspMainAddress -ToDo longpulse -GpioNo $MainGPIO.Value -Value 1 -TimerSec $($SprinklerTime * 60 * $TimePercent.Value / 100)
}
# Öffne Verteilerventil für die ermittelte Zeit
$ReturnMsg = Set-Gpio -IpAddress $EspSprinklerAddress -ToDo longpulse -GpioNo $SprinklerGPIO.Value -Value 1 -TimerSec $($SprinklerTime * 60 * $TimePercent.Value / 100)
# Warte Timer ab (plus 10 Sekunden)
Write-Debug "Main: Warte $($SprinklerTime * 60 + 10) Sekunden"
Start-Sleep -Seconds $($SprinklerTime * 60 + 10)
# Prüfe, ob alle Ventile geschlossen sind; warte 5 Minuten, damit Das Hauptventil abkühlen kann oder Abbruch
$GPIOerror = Get-AllGpioOff
If($GPIOerror -eq 0){
Write-Debug "Main: Warte 5 Minuten (Abkühlung Hauptventil)"
Start-Sleep -Seconds 300
} else {
if($GPIOerror -lt 4){
Write-Debug "Main: Fehler: $GPIOerror"
Write-Log -File $LogFilePath -Line "Fehler in Hauptventilsteuerung"
} else {
Write-Debug "Verteiler: Fehler: $GPIOerror"
Write-Log -File $LogFilePath -Line "Fehler in Verteilerventilsteuerung"
}
Write-Log -File $LogFilePath -Line "Zyklus beendet"
break
}
}
Write-Log -File $LogFilePath -Line "Zyklus beendet"
} else {
if($GPIOerror -lt 4){
Write-Debug "Main: Fehler: $GPIOerror"
Write-Log -File $LogFilePath -Line "Fehler in Hauptventilsteuerung"
} else {
Write-Debug "Verteiler: Fehler: $GPIOerror"
Write-Log -File $LogFilePath -Line "Fehler in Verteilerventilsteuerung"
}
Write-Log -File $LogFilePath -Line "Zyklus beendet"
break
}
}
Du willst, dass ich Powershell für Linux installiere 8)
Ich kann es zumindest empfehlen. Obwohl mein Raspi 2 schon ein paar Sekunden braucht, bis die PoSh Umgebung ansprechbar ist. Aber: Ich kann auch ein kleines Perl Script bauen, das mir den SensorValue in ein Log schreibt. Meine Heizungssteuerung habe ich mit Perl gemacht. Ich hatte nur noch nie die Anforderung, eine FHEM Variable an ein Script zu übergeben. Das ist ja das eigentliche Problem.
Theoretisch könnte ich auch den Bodenfeuchtesensor direkt abfragen, aber ich will, dass der schläft und nur einmal pro Stunde wach wird und den aktuellen Wert sendet. Ich hab da draußen keinen Strom. Und genau das kann nur FHEM übernehmen.
Naja ich versuche das mal, interessiert mich.
Dein Problem wird ein reines Berechtigungsthema sein, man müsste an mehren Stellen schauen.
Und ich bin immer misstrauisch mit den Fehlermeldungen, nur allzu oft in meinem Leben bedeutete der Fehler: "Kann im Ziel nicht schrieben" in Wahrheit: "kann die Quelle nicht lesen" :o
Die Befehle {qx(...)} sind alle für die FHEM Kommandozeile im Browser!
Das Logfile wird ja jeden Tag erzeugt. Wie sind die Rechte?
{qx(ls -lha /opt/fhem/log/SprinklerLog-20200428.log)}
Darf fhem pwsh ausführen und findet er es? Dazu fällt mir kein test ein, aber mach ein Script mit write-output "Hello World" und für es aus:
{qx(pwsh /opt/_me/PwSh/test.ps1)}
da sollte ja die Ausgabe im Browser landen?
Findet fhem das Script?
{qx(ls -lha /opt/_me/PwSh/SprinklerController-V2.ps1}
Hallo Otto,
ich fang nochmal von vorn an...
Ich habe das Script jetzt reduziert auf eine Ausgabe auf dem Schirm und eine Log-Eintrag:
#Input: Bodenfeuchte
#
param(
[int][parameter(Mandatory=$false)]$SensorValue
)
$myToday = $(Get-Date -Format('yyyyMMdd'))
$LogFilePath = "/opt/_me/log/SprinklerLog-$myToday.log"
$DebugPreference = "Continue"
Function Write-Log{
param
(
[String]
[Parameter(Mandatory=$true)]
$File,
[Parameter(Mandatory=$True)]
$Line
)
If(!(Test-Path -Path $File)){
New-Item -ItemType File -Force -Path $File
}
$LogLine = [string]::concat($(Get-Date -Format('yyyy-MM-dd_HH:mm:ss')),' - ',$Line)
Add-Content $File $LogLine
Write-Host $LogLine
}
# Hauptschleife
write-Host 'Hallo'
Write-Log -File $LogFilePath -Line "Script gestartet"
Write-Log -File $LogFilePath -Line "Bodenfeuchtewert: $SensorValue"
Ich führe jetzt das Script auf der Shell als root aus...
root@raspberrypi:~# pwsh -File /opt/_me/PwSh/SprinklerController-Test.ps1 -SensorValue 200
Hallo
Directory: /opt/_me/log
Mode LastWriteTime Length Name
---- ------------- ------ ----
------ 28.04.20 16:32 0 SprinklerLog-20200428.log
2020-04-28_16:32:55 - Script gestartet
2020-04-28_16:32:56 - Bodenfeuchtewert: 200
root@raspberrypi:~#
8)
Jetzt passen natürlich die Rechte nicht für FHEM, also setze ich RW für alle (666) auf das Logfile. Aber selbst auf de rShell kriege ich diese Fehler:
Test-Path : Access to the path '/opt/_me/log/SprinklerLog-20200428.log' is denied.
At /opt/_me/PwSh/SprinklerController-Test.ps1:19 char:8
+ If(!(Test-Path -Path $File)){
+ ~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : PermissionDenied: (/opt/_me/log/SprinklerLog-20200428.log:String) [Test-Path], UnauthorizedAccessException
+ FullyQualifiedErrorId : ItemExistsUnauthorizedAccessError,Microsoft.PowerShell.Commands.TestPathCommand
##########
New-Item : Access to the path '/opt/_me/log/SprinklerLog-20200428.log' is denied.
At /opt/_me/PwSh/SprinklerController-Test.ps1:20 char:5
###########
Add-Content : Access to the path '/opt/_me/log/SprinklerLog-20200428.log' is denied.
At /opt/_me/PwSh/SprinklerController-Test.ps1:23 char:3
###########
nix geht, "Hallo" wird gedruckt.
In der Kommandozeile:
{ qx "sudo pwsh -File /opt/_me/PwSh/SprinklerController-Test.ps1 -SensorValue 200)" }
keine Ausgabe
{qx(ls -lha /opt/_me/log/SprinklerLog-20200428.log)}
keine Ausgabe
Bedeutet für mich: für fhem ist das Logfile gar nicht vorhanden
Und mal den Befehl auf Systemebene:
ls -lha /opt/_me/log
Bei dem Pfad (der ist mir suspect :) ) spielt ja noch der symlink eine Rolle? Wenn von vorn dann doch lieber einfach ... ;)
Mein erster Ausflug zu pwsh :) ich weiß hat jetzt noch nichts mit deinem Problem zu tun, gibt aber erstmal gute Grundlagen in Sachen Sicherheit. Kurz mein Setup
Pi3 mit Ubuntu 18.04 LTS 64 bit - Ich dachte ja super wird direkt unterstützt (https://docs.microsoft.com/de-de/powershell/scripting/install/installing-powershell-core-on-linux?view=powershell-7) - aber ich hatte die Rechnung ohne Arm gemacht ;)
Egal, Archive heruntergeladen und Setup wie hier gemacht (https://docs.microsoft.com/de-de/powershell/scripting/install/installing-powershell-core-on-linux?view=powershell-7#raspbian).
Mein User ist ubuntu der ist normaler user. Das homedir ist /home/ubuntu
Deshalb ist powershell jetzt so aufrufbar /home/ubuntu/powershell/pwsh
Es gibt bei diesem setup keinen Pfad Eintrag, ich muss also immer den kompletten Pfad angeben!
Ein kurzer Test:
/home/ubuntu/test.ps1 mit Inhalt write-output "Hello world"
Funktioniert.
Der gleiche Test in FHEM
{qx(/home/ubuntu/powershell/pwsh /home/ubuntu/test.ps1)}
Funktioniert :) Ausgabe im Browser - dauert allerdings "ewig" bzw 11 sec :)
Ergo: bisher kein sudo nötig! Aufruf aus fhem ohne Probleme.
Jetzt: LogFile schreiben ;)
Gruß Otto
Also... ich habe nicht das ganze in Details gelesen, aber ein Paar Anmerkungen.
- 666 auf einer Datei reicht nicht immer. Ggf muss man noch x für alle auf dem Verzeichnis setzen, damit man den Folder "browsen" kann.
- sudo Befehle brauchen entspr. Einträge in sudoers. Und bitte NICHT ALL ALL ALL!
- ls ohne sudo braucht entspr. Berechtigungen auf der Datei UND auf dem Verzeichnis (siehe 1. Punkt)
Nächster Schritt: Dein Script als /home/ubuntu/test1.ps1
Einzige Änderung $LogFilePath = "/opt/fhem/log/SprinklerLog-$myToday.log"
Dazu ein Device in FHEM damit ich die Logdatei anzeigen kann:
define Testlog FileLog ./log/SprinklerLog-%Y%m%d.log fakelog
Die Ausgabe im Browser wie bei Dir. bei dem Aufruf (blockiert FHEM!)
{qx(/home/ubuntu/powershell/pwsh /home/ubuntu/test.ps1 -SensorValue 200)}
Aufruf so in der FHEM Kommandozeile (komplett mit " ") erzeugt die Ausgabe im FHEM Log blockiert aber nicht!
"/home/ubuntu/powershell/pwsh /home/ubuntu/test.ps1 -SensorValue 200"
Die Ausgabe im Testlog
2020-04-28_18:48:48 - Script gestartet
2020-04-28_18:48:48 - Bodenfeuchtewert: 200
Alles wie es soll :)
Ausgabe von
{qx(ls -lha ./log/SprinklerLog-20200428.log)}
-rw-r--r-- 1 fhem dialout 83 Apr 28 18:48 ./log/SprinklerLog-20200428.log
So habe ich es erwartet.
Also das mit deinem Test auf Systemebene erzeugt falsche Berechtigungen, der Aufruf des Powershell Scripts muss mit kompletten Pfad Angaben erfolgen, wo das Script liegt ist relativ egal, fhem muss es nur lesen können.
Ich habe das mit deinem ominösen Pfad /opt/_me noch nicht verstanden, dort liegt eventuell das Schlüsselproblem.
{qx(ls -lha /opt/_me)}
Hab ich das plausibel dargestellt? Frag einfach ;)
Gruß Otto
Jetzt habe ich das ursprüngliche Problem noch nicht ganz verstanden.
Du willst den Wert auslesen und an das Script übergeben?
Das könnte man so machen:
{my $SensorValue = ReadingsVal("ESPEasy_NodeMCU_3_BodenfeuchteSensor","Analog",0);;fhem("\"kompletterPfad/pwsh kompletterPfad Script -SensorValue $SensorValue \"")}
Der Teil fhem("\" Aufruf \"") erzeugt eine Blockingfreien Aufruf. Allerdings sollten dann Ausgaben auf der Konsole (write-host) unterbleiben, die landen im Log. Die \" erzeugen geschützte " für den Aufruf. ;)
Wie wolltest Du das Script aufrufen? Wenn sich der SensorValue ändert?
Dann erzeugst Du ein notify :)
Gruß Otto
:) :) :) :)
Jetzt funktioniert es bei mir auch. Raspi neu gestartet. FHEM wollte nicht mehr starten. Ich habe einfach mal alle Berechtigungen neu gesetzt. Bekomme jetzt die Scriptausgaben im Browser. Werde jetzt mal deine ganzen Ideen bzgl. der Wertübergabe testen.
:) :) :) :)
Hallo Otto,
Dein letzter Tipp für den gesamten Aufruf sieht jetzt so aus:
{my $SensorValue = ReadingsVal("ESPEasy_NodeMCU_3_BodenfeuchteSensor","Analog",0);;fhem("\"/opt/powershell/pwsh /opt/_me/PwSh/SprinklerController-Test.ps1 -SensorValue $SensorValue \"")}
Leider passiert dabei wieder nichts mehr im Browser. Zuletzt hatte ich ja Erfolg beim Aufruf des Scripts. Dabei erscheint ja der Donat auf der Browserlasche. da arbeitet also was. Das ist jetzt nicht mehr der Fall.
Das Escapen der Gänsefüßchen verstehe ich. Aber den Aufbau "\" nicht. Und warum geht der Aufruf jetzt nicht mehr mit qx?
Schon mal ganz vielen Dank für Deine unermüdliche Hilfe!!!!
Du kannst das auch mit qx machen - aber das blockiert (Dabei erscheint ja der Donat auf der Browserlasche. da arbeitet also was.) den gesamten Aufruf FHEM. (Varianten zum lesen (https://heinz-otto.blogspot.com/2018/02/in-fhem-externe-programme-aufrufen.html))
{my $SensorValue = ReadingsVal("ESPEasy_NodeMCU_3_BodenfeuchteSensor","Analog",0);;qx(/opt/powershell/pwsh /opt/_me/PwSh/SprinklerController-Test.ps1 -SensorValue $SensorValue )}
Du kannst auch system() nehmen. Das & am Ende wird verhindern das FHEM blockiert . Aber du bekommst nichts im Browser sondern die Ausgabe geht ins Log
{my $SensorValue = ReadingsVal("ESPEasy_NodeMCU_3_BodenfeuchteSensor","Analog",0);;system("/opt/powershell/pwsh /opt/_me/PwSh/SprinklerController-Test.ps1 -SensorValue $SensorValue &")}
Die Gänsefüsschen Variante ist die einfache Version von FHEM zum Aufruf https://fhem.de/commandref_DE.html#command
Eigentlich willst Du ja nichts im Browser zurück, Du willst ja was im Logfile. Aber zum Testen musst Du immer qx() nehmen, sonst "siehst" Du nichts ;)
OK, wieder einen Schritt weiter...
Dieser Test:
{my $SensorValue = ReadingsVal("ESPEasy_NodeMCU_3_BodenfeuchteSensor","Analog",0);;fhem("\"/opt/powershell/pwsh /opt/_me/PwSh/SprinklerController-Test.ps1 -SensorValue $SensorValue \"")}
liefert im Log einen Scriptfehler:
/opt/_me/PwSh/SprinklerController-Test.ps1 : A positional parameter cannot be found that accepts argument ''.
+ CategoryInfo : InvalidArgument: (:) [SprinklerController-Test.ps1], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : PositionalParameterNotFound,SprinklerController-Test.ps1
Da kommt offensichtlich ein neuer Parameter um die Ecker, der vom Script nicht erwartet wird.
Dein letzter Vorschlag lässt das Script laufen:
{my $SensorValue = ReadingsVal("ESPEasy_NodeMCU_3_BodenfeuchteSensor","Analog",0);;system("/opt/powershell/pwsh /opt/_me/PwSh/SprinklerController-Test.ps1 -SensorValue $SensorValue &")}
Jetzt steht im Log:
Hallo
2020-04-28_22:45:51 - Script gestartet
Da die zweite Logzeile fehlt, schließe ich daraus, dass jetzt kein SensorValue übergeben wird. Ich hoffe hier mal, dass das ReadingsVal auch dann funktioniert, wenn der Bodenfeuchtesensor ABSENT meldet. Der letzte Wert steht ja noch im Reading.
Aber Du wolltest noch wissen, wie das Script später starten soll. Das geht einfach per AT. Ich will ja nicht gerade im Garten stehen, wenn die Sprinkleranlage losgeht. deshalb soll das ganze morgens um 3:00Uhr aufgerufen werden. Die Auswertung, ob und wie lange gesprengt wird, findet im Script selbst statt. Dafür brauche ich den SensorValue.
Was liefert Dir das in der FHEM Kommandozeile?
{ReadingsVal("ESPEasy_NodeMCU_3_BodenfeuchteSensor","Analog",0)}
Du redest vom FHEM Logfile oder von deinem LogFile?
Wie gesagt, die write-host Ausgaben kommen bei der "" und der system() Variante ins FHEM Log, bei der qx() Variante ins Browserfenster (wenn von dort aufgerufen).
Dein Logfile vom Script wird unabhängig gefüllt.
Auch wenn der Parameter leer ist wird doch die Zeile geschrieben?
Write-Log -File $LogFilePath -Line "Bodenfeuchtewert: $SensorValue"
Versteh ich nicht ...
:) :) :)
Hallo Otto, es funktioniert! Dein Lösungsvorschlag
{my $SensorValue = ReadingsVal("ESPEasy_NodeMCU_3_BodenfeuchteSensor","Analog",0);;fhem("\"/opt/powershell/pwsh /opt/_me/PwSh/SprinklerController-Test.ps1 -SensorValue $SensorValue \"")}
ist genau richtig (wäre ich nie draufgekommen). Das hattest Du ja schon recht früh so vorgeschlagen. Aber da waren wohl noch ein paar andere Probleme, die ich gestern beim Troubleshooting gelöst habe. Nebenbei hast Du mir auch noch gezeigt, wie ich mein Logfile in FHEM anzeigen kann. Ich werde es aber auch aus dem Posh Script noch per Mail versenden. Den aktuellen Wetterbericht werde ich jetzt auch noch einbauen, damit ich nicht sprenge, wenn es drei Stunden später sowieso regnet.
VIELEN VIELEN DANK! Jetzt kann ich loslegen. 8) 8) 8)
Zitat von: Qualle am 29 April 2020, 21:10:34
Nebenbei hast Du mir auch noch gezeigt, wie ich mein Logfile in FHEM anzeigen kann.
Dacht ich mir :)
Und ich muss mal noch testen was mit pwsh so geht. ;)
Edit: hätt ich nicht gedacht, mein fhemcl.ps1 Script (https://github.com/heinz-otto/fhemcl) funktioniert :)
Also wenn Du aus deinem powershell Script über HTTP in Dein FHEM schreiben willst, oder Abfragen machen willst :)
Probier es aus, so in etwa (in der Systemkonsole):
./powershell/pwsh ./fhemcl.ps1 http://deinFehmServer:8083 "{ReadingsVal("ESPEasy_NodeMCU_3_BodenfeuchteSensor","Analog",0)}"
Mit PwSh geht alles. Alle Urentwickler kommen aus der Linux Ecke und haben die Vorteile beider Welten zu Powershell verarbeitet. Zuerst ja nur für Windows. Dort geht ohne PoSh heute nichts mehr. Und jetzt eben auch wieder für Linux. So komme ich besser damit klar.
PS: Gab es nicht irgendwo einen GELÖST Button? Ich finde den nicht.
Im ersten Post einfach den Betreff editieren :) [gelöst]
hatte meinen letzten Post noch editiert :)