Seite 1 von 1

openHAB/HABPanel /FritzBox

Verfasst: 22. Jan 2025 18:48
von Frigoblue
Hallo zusammen,

ich versuche das FritzBox in openHAB HABPanel von https://github.com/sidamos/openHAB/tree ... l/FritzBox zum funktioniere zu bringen.
Es funktioniert schon einiges. Die Regel wird aufgerufen, aber der Teil executecommand wird irgend wie nicht gestartet.

Weiß da mir jemand zu helfen wo mein Fehler ist?

Code: Alles auswählen

rule "Generate Call-Uebersicht"
when
   Item FRITZBox_6660_Cable_Anrufzustand changed from IDLE to DIALING or
   Item FRITZBox_6660_Cable_Anrufzustand changed from IDLE to RINGING
then
logInfo("FRITZBox", "Anruf: Script wird gestartet")

if ((FRITZBox_6660_Cable_Anrufzustand.state.toString == "RINGING") && (FRITZBox_6660_Cable_Anrufzustand.state.toString == "DIALING") && (previousState.toString == "IDLE"))
   {
     Thread.sleep(500)
     executeCommandLine("sudo /etc/openhab/scripts/fritzbox.sh update", 300)
     ListDate.postUpdate(now.millis);
   }
logInfo("FRITZBox", "Anruf: Script wird beendet")
end
Vielen Dank für die Unterstützung.
Gruß Uwe

openHAB 4.3.2
Release Build
RapberryPI 4 Raspbian 12

Re: openHAB/HABPanel /FritzBox

Verfasst: 22. Jan 2025 19:36
von Frigoblue
Huch, nach Stunden von Trial and Error....

ich habs geschafft: vielleicht hilft es jemand anderen auch

In openHAB eine Rule erstellen:

Die drei WHEN Bedingungen definieren und eine THEN BEdingung definieren. Dazu ein Inline Script auswählen und dann RuleDSL folgende eintragen:

Code: Alles auswählen

val command = "shellscripts/fritzbox.sh update"
var result = executeCommandLine(Duration.ofSeconds(300), "/bin/sh", "-c", command)
logInfo("FritzBox Exec Result", result)

Hierr der komplette Code nach erstellen:

Code: Alles auswählen

configuration: {}
triggers:
  - id: "1"
    configuration:
      itemName: FRITZBox_6660_Cable_Anrufzustand
      state: IDLE
      previousState: RINGING
    type: core.ItemStateChangeTrigger
  - id: "2"
    configuration:
      itemName: FRITZBox_6660_Cable_Anrufzustand
      state: IDLE
      previousState: DIALING
    type: core.ItemStateChangeTrigger
  - id: "3"
    configuration:
      itemName: FRITZBox_6660_Cable_Anrufzustand
      state: IDLE
      previousState: ACTIVE
    type: core.ItemStateChangeTrigger
conditions: []
actions:
  - inputs: {}
    id: "4"
    configuration:
      type: application/vnd.openhab.dsl.rule
      script: >
        val command = "shellscripts/fritzbox.sh update"

        var result = executeCommandLine(Duration.ofSeconds(30), "/bin/sh", "-c",
        command)

        logInfo("FritzBox Exec Result", result)
    type: script.ScriptAction
Gutes Gelingen...
Gruß Uwe

Re: openHAB/HABPanel /FritzBox

Verfasst: 22. Jan 2025 19:37
von Harka
Moin,
Gut. Ich hatte die folgenden Zeile in Verdacht.
https://community.openhab.org/t/fritzbo ... w/28430/80

Re: openHAB/HABPanel /FritzBox

Verfasst: 22. Jan 2025 21:57
von udo1toni
Es ist kein Wunder, dass executeCommandLine() nicht ausgeführt wird, denn diese Bedingung:

Code: Alles auswählen

if ((FRITZBox_6660_Cable_Anrufzustand.state.toString == "RINGING") && (FRITZBox_6660_Cable_Anrufzustand.state.toString == "DIALING") && (previousState.toString == "IDLE"))
ist niemals erfüllt. Das Problem ist hier, dass der Bandwurm nicht sonderlich übersichtlich ist.
Um es etwas lesbarer zu gestalten, führe ich mal eine lokale Konstante ein:

Code: Alles auswählen

val myState = FRITZBox_6660_Cable_Anrufzustand.state.toString
if(myState == "RINGING" && myState == "DIALING" && previousState.toString == "IDLE")
Die Bedingung lautet also, dass myState den Wert RINGING und DIALING gleichzeitig haben muss, zusätzlich zum vorherigen Status IDLE (diese Bedingung ist allerdings immer erfüllt, weil in allen Triggern angegeben)
Mutmaßlich wolltest Du eher so etwas als Bedingung:

Code: Alles auswählen

if((newState.toString == "RINGING" || newState.toString == "DIALING") && previousState.toString == "IDLE")
newState enthält den neuen Status, previousState den alten Status.
Als aktueller Status muss RINING oder (||) DIALING gesetzt sein, gleichzeitig (&&) muss der alte Status IDLE sein.
Da diese Zeile nun aber immer erfüllt ist (weil dies schon die Einschränkungen durch die Trigger sind) kannst Du die Bedingung auch einfach komplett weg lassen - oder Du änderst den Trigger ab...

Ein anderes Problem ist der eigentliche Befehl executeCommandLine(), der früher(tm) mal anders verwendet wurde als das aktuell der Fall ist. Insbesondere der Timeout (hinten als Zahl oder vorn als Duration) ist auffällig, aber auch sonst... Früher(tm) musste man Leerzeichen innerhalb einer Befehlszeile mit @@ ersetzen, jetzt werden die einzelnen Parameter als einzelne Strings übergeben.

Ein anderer Punkt ist der Speicherort für Dein Script. Der Ordner /etc/openhab/scripts/ ist ausschließlich für Dateien mit der Endung .script reserviert. Das trifft auf Dein Shell script nicht zu :) Bei *.script Dateien handelt es sich um DSL Rules ohne Rahmen, also ohne

Code: Alles auswählen

rule "..."
when
   // irgendein trigger
then
end
Stattdessen kann man aus jeder DSL Rule heraus per callScript("scriptname") das DSL Script in der Datei scriptname.script aufrufen.
Wenn Du selbst Shell Scripte definierst, solltest Du diese besser in einem Verzeichnis $OPENHAB_USERDATA/shellscripts/ ablegen ($OPENHAB_USERDATA ist gewöhnlich ein Link auf /var/lib/openhab/). Da es sich bei $OPENHAB_USERDATA um das Home-Verzeichnis des Users openhab handelt (unter dem der Service läuft), kannst Du dann auch den Pfad shellscripts/fritzbox.sh als Aufruf verwenden.
Der Name shellscripts ist auch nur beispielhaft, wichtig ist nur, dass Du keine bereits vorhandenen Ordner verwendest :)

Wenn ich es richtig verstehe, holst Du nach dem Beenden eines Telefonats den letzten Datensatz ab, mutmaßlich um die Gesprächsdauer anzuzeigen?

Code: Alles auswählen

rule "Generate Call-Übersicht"
when
   Item FRITZBox_6660_Cable_Anrufzustand changed to IDLE
then
    logInfo("FRITZBox", "Anruf: Script wird gestartet, Change von {} nach {}",previousState,newState)
    Thread.sleep(500)
    val result = executeCommandLine(Duration.ofSeconds(5), "shellscripts/fritzbox.sh", "update")
    ListDate.postUpdate(result)
    logInfo("FRITZBox", "Anruf: Script wird beendet")
end
Was den Befehl logInfo() betrifft: Dieser Befehl erwartet zwei Strings. dabei ist der erste String der letzte Teil des Loggernamens. Dieser String sollte weder Leerzeichen noch Sonderzeichen oder Umlaute enthalten. Der zweite String ist die eigentliche Logmeldung. Dieser String unterstützt Substitution.
falsch:

Code: Alles auswählen

logInfo("FritzBox Exec Result", result)
richtig:

Code: Alles auswählen

logInfo("fritzbox", "FRITZ!Box Exec Result: {}", result)
Nun wird die Meldung unter dem Logger org.openhab.core.model.script.fritzbox gelistet, mit diesem Loggernamen kann man die Meldung auch über die Karaf Konsole "abschalten".

Re: openHAB/HABPanel /FritzBox

Verfasst: 23. Jan 2025 00:22
von Frigoblue
Hallo udo1toni,

vielen Dank für die sehr aufschlussreiche und ausführliche Erklärung. Über deinen Antwort habe ich mich sehr gefreut.
Ich hab dein Script einfach mal übernommen.... einfach weil es sauber geschrieben ist und vom Fachmann. :D

Die Datei lockRoutines habe ich auch nach /var/lib/openhab/shellscripts kopiert. Aber ich bekomme da einen Fehler, der das Script nicht ausführt. Wenn ich es in /etc/openhab/scripts lasse dann gibt es keinen Fehler.

Das ist der betreffende Ausschnitt aus der fritzbox.sh

Code: Alles auswählen

### the fun starts here ###
source `dirname $0`/lockRoutines
exlock_now || exit 1

echo "lock obtained"
Ich guck mal, vielleicht finde ich die Lösung.... :shock:

Danke sehr für die Untertützung
Gruß Uwe

Re: openHAB/HABPanel /FritzBox

Verfasst: 23. Jan 2025 01:45
von udo1toni
Die Frage ist ja, was in lockRoutines drin steht.

Re: openHAB/HABPanel /FritzBox

Verfasst: 23. Jan 2025 01:52
von Frigoblue
Nur das:

Code: Alles auswählen

## This script is licensed under the terms of the MIT license.
## https://opensource.org/licenses/MIT
#
# Lockable script boilerplate

### HEADER ###

LOCKFILE="/var/lock/`basename $0`"
LOCKFD=99

# PRIVATE
_lock()             { flock -$1 $LOCKFD; }
_no_more_locking()  { _lock u; _lock xn && rm -f $LOCKFILE; }
_prepare_locking()  { eval "exec $LOCKFD>\"$LOCKFILE\""; trap _no_more_locking EXIT; }

# ON START
_prepare_locking

# PUBLIC
exlock_now()        { _lock xn; }  # obtain an exclusive lock immediately or fail
exlock()            { _lock x; }   # obtain an exclusive lock
shlock()            { _lock s; }   # obtain a shared lock
unlock()            { _lock u; }   # drop a lock

### BEGIN OF SCRIPT ###

Re: openHAB/HABPanel /FritzBox

Verfasst: 23. Jan 2025 13:50
von udo1toni
Dann schau doch mal bitte unter /var/lock/ nach, ob dort noch eine "Dateileiche" aus den "/etc/openhab/script-Zeiten" rumliegt -
mutmaßlich /var/lock/fritzbox.sh
Diese müsstest Du dann (notfalls als root) löschen.

Re: openHAB/HABPanel /FritzBox

Verfasst: 23. Jan 2025 14:00
von Frigoblue
Danke sehr udo1toni,

das wars der Grund.... es gab noch 2 lock-dateien.
Jetzt bekomme ich keinen Fehler.....und es läuft sauber durch.

Wie immer danke sehr für die Unterstüttzung

Gruß Uwe

Re: openHAB/HABPanel /FritzBox

Verfasst: 23. Jan 2025 14:41
von udo1toni
Immer gerne :)