Rule does not recognize active call

Hello,

the following rules show me the last 7 incoming and outgoing calls. The process works so far, but has a blemish. The “Gesprächsdauer messen” rule returns the duration for all phone calls. However, if a call is being made, another (incoming) phone call destroys the measurement - although the remote station hears a busy signal.
I’ve been looking for a solution for a while now. Before activating the “Gesprächsdauer messen” rule, a check should be carried out to determine whether a call is currently being made. The rule can only be executed if this is not the case.
Unfortunately, I have no idea how the process can be carried out successfully. Can someone help me?

Thanks in advance.

var Long lPhoneStart = 0
var Integer iSeconds = 0
var strFax = "030123456789" // Fax-Nummern

rule "Gesprächsdauer messen"
when
    Item fritzCallRinging changed
then
    val strNew  = newState.toString
    val strPrev = previousState.toString

    if(strNew == "ACTIVE") {
        if(strPrev == "RINGING")
            logInfo("call", "Eingehender Anruf: Verbindung hergestellt")
        else if(strPrev == "DIALING")
            logInfo("call", "Ausgehender Anruf: Verbindung hergestellt")
        lPhoneStart = now.toInstant.toEpochMilli
    } else if(strPrev == "ACTIVE" && strNew == "IDLE") {
        logInfo("call", "Aktiver Anruf: Verbindung beendet")
        iSeconds = ((now.toInstant.toEpochMilli - lPhoneStart)/1000).intValue
        var strTime = ""
        if(iSeconds !== null)
            strTime = transform("JS","secinhms.js",iSeconds.toString)
        logInfo("call", "Beendigung des {}gangsgespräches nach {}",if(Flag_1_ADauer.state.toString=="...")"Aus" else "Ein",strTime)
        if(Flag_1_EDauer.state == "...")
            Flag_1_EDauer.postUpdate(strTime)
        else if(Flag_1_ADauer.state == "...")
            Flag_1_ADauer.postUpdate(strTime)

    }
end

rule "Eingehender Anruf"
when
    Item fritzCallRinging changed to RINGING
then
    Thread.sleep(500)                                    // Wert eventuell auch noch erhöhen
    if(!(fritzIncomingCall.state instanceof StringListType)) return;
    val incCall      = fritzIncomingCall.state as StringListType   
    gEFlags.members.sortBy[ name ].reverseView.forEach[ i |
        val num = Integer::parseInt(i.name.split("_").get(1))
        val art = i.name.split("_").get(2)
        if(num > 1) {
            val myItem = gEFlags.members.filter[ j | j.name.split("_").get(1) == (num-1).toString && j.name.endsWith(art)].head
            i.postUpdate(myItem.state)
        }
    ]

 // val incCall      = fritzIncomingCall.state as StringListType
 // val ourNumber    = incCall.getValue(0)
    val callerNumber = incCall.getValue(1)

    val tr064Actions = getActions("tr064","tr064:fritzbox:1")
    var callerName   = tr064Actions.phonebookLookup(callerNumber)
    if(strFax.contains(callerNumber.toString))
        callerName = "Faxgerät"
    if(callerName==callerNumber)
        callerName = "unbekannt"
    val callDate     = String.format("%1$td.%1$tm.%1$tY", now)
    val callTime     = String.format("%1$tH:%1$tM", now)

    Flag_1_EName.postUpdate(callerName)
    Flag_1_ETel.postUpdate(callerNumber)
    Flag_1_EDat.postUpdate(callDate)
    Flag_1_ETime.postUpdate(callTime)
    Flag_1_EDauer.postUpdate("...") // signalisiert, dass gerade telefoniert wird

    logInfo("call", "Eingang {} | {} | {} | {}",callerName,callerNumber,callDate,callTime)
end

rule "Ausgehender Anruf"
when
    Item fritzCallRinging changed to DIALING
then
    Thread.sleep(500)                                    // Wert eventuell auch noch erhöhen
    if(!(fritzOutgoingCall.state instanceof StringListType)) return;
    val outCall = fritzOutgoingCall.state as StringListType
    gAFlags.members.sortBy[ name ].reverseView.forEach[ i |
        val num = Integer::parseInt(i.name.split("_").get(1))
        val art = i.name.split("_").get(2)
        //logInfo("call","Move - zu Item {} Nummer ist {} Name endet mit {}",i.name,num,art)
        if(num > 1) {
            val myItem = gAFlags.members.filter[ j | j.name.split("_").get(1) == (num-1).toString && j.name.endsWith(art)].head
            i.postUpdate(myItem.state)
        }
    ]

    //val outCall = fritzOutgoingCall.state as StringListType
    var String calledNumber = outCall.getValue(0)
    // var String ourNumber = outCall.getValue(1)

    val tr064Actions = getActions("tr064","tr064:fritzbox:1")
    var calledName = tr064Actions.phonebookLookup(calledNumber)
    if(strFax.contains(calledNumber.toString))
        calledName = "Faxgerät"
    if(calledName==calledNumber)
        calledName = "unbekannt"
    val callDate = String.format("%1$td.%1$tm.%1$tY", now)
    val callTime = String.format("%1$tH:%1$tM", now)

    Flag_1_AName.postUpdate(calledName)
    Flag_1_ATel.postUpdate(calledNumber)
    Flag_1_ADat.postUpdate(callDate)
    Flag_1_ATime.postUpdate(callTime)
    Flag_1_ADauer.postUpdate("...") // signalisiert, dass gerade telefoniert wird

    logInfo("call", "Ausgang {} | {} | {} | {}",calledName,calledNumber,callDate,callTime)
end


rule "Anruf abgebrochen"
when
    Item fritzCallRinging changed from DIALING to IDLE
then
    logInfo("FRITZ!Box", "Anruf: Teilnehmer nicht erreichbar")
    if(Flag_1_ADauer.state == "...")
            Flag_1_ADauer.postUpdate("abgebr.")
end

I did not understand all the code but to achieve what you want to do I would create an item “ongoing_call” and if a call is coming in or out → ongoing_call.sendCommand(ON).
Before Gesprächsdauer messen is excuted you can test

if (ongoing_call.state != ON) {
...
}

Sorry if I misunderstood your question.

You mean create a dummy item? I’ve already tried something like this. However, this item must also be switched from ON to OFF. Then, however, the processing of the rules is crucial. So far I haven’t found a solution this way. Or am I going the wrong way?

@schossel,

I have now made many attempts to find a solution with your suggestion. Unfortunately without success, I need another way. With this method I only produced errors. Thanks anyway, maybe I can get some other tips.

### ongoing_call.items ###
Switch ongoing_call

Somethinglike that. Not tested.

var Long lPhoneStart = 0
var Integer iSeconds = 0
var strFax = "030123456789" // Fax-Nummern

rule "Gesprächsdauer messen ON"
when
    Item ongoing_call changed to ON
then
    val strNew  = newState.toString
    val strPrev = previousState.toString

    if(strNew == "ACTIVE") {
        if(strPrev == "RINGING")
            logInfo("call", "Eingehender Anruf: Verbindung hergestellt")
        else if(strPrev == "DIALING") {
            logInfo("call", "Ausgehender Anruf: Verbindung hergestellt")
            lPhoneStart = now.toInstant.toEpochMilli
end

rule "Gesprächsdauer messen OFF"
when
    Item ongoing_call changed to OFF
then
    if(strPrev == "ACTIVE" && strNew == "IDLE") {
        logInfo("call", "Aktiver Anruf: Verbindung beendet")
        iSeconds = ((now.toInstant.toEpochMilli - lPhoneStart)/1000).intValue
        var strTime = ""
        if(iSeconds !== null)
            strTime = transform("JS","secinhms.js",iSeconds.toString)
        logInfo("call", "Beendigung des {}gangsgespräches nach {}",if(Flag_1_ADauer.state.toString=="...")"Aus" else "Ein",strTime)
        if(Flag_1_EDauer.state == "...")
            Flag_1_EDauer.postUpdate(strTime)
    else if(Flag_1_ADauer.state == "...")
            Flag_1_ADauer.postUpdate(strTime)
end


rule "Eingehender Anruf"
when
    Item fritzCallRinging changed to RINGING
then
    Thread.sleep(500)                                    // Wert eventuell auch noch erhöhen
    if(!(fritzIncomingCall.state instanceof StringListType)) return;
    val incCall      = fritzIncomingCall.state as StringListType
    ongoing_call.sendCommand(ON)   
    gEFlags.members.sortBy[ name ].reverseView.forEach[ i |
        val num = Integer::parseInt(i.name.split("_").get(1))
        val art = i.name.split("_").get(2)
        if(num > 1) {
            val myItem = gEFlags.members.filter[ j | j.name.split("_").get(1) == (num-1).toString && j.name.endsWith(art)].head
            i.postUpdate(myItem.state)
        }
    ]

 // val incCall      = fritzIncomingCall.state as StringListType
 // val ourNumber    = incCall.getValue(0)
    val callerNumber = incCall.getValue(1)

    val tr064Actions = getActions("tr064","tr064:fritzbox:1")
    var callerName   = tr064Actions.phonebookLookup(callerNumber)
    if(strFax.contains(callerNumber.toString))
        callerName = "Faxgerät"
    if(callerName==callerNumber)
        callerName = "unbekannt"
    val callDate     = String.format("%1$td.%1$tm.%1$tY", now)
    val callTime     = String.format("%1$tH:%1$tM", now)

    Flag_1_EName.postUpdate(callerName)
    Flag_1_ETel.postUpdate(callerNumber)
    Flag_1_EDat.postUpdate(callDate)
    Flag_1_ETime.postUpdate(callTime)
    Flag_1_EDauer.postUpdate("...") // signalisiert, dass gerade telefoniert wird

    logInfo("call", "Eingang {} | {} | {} | {}",callerName,callerNumber,callDate,callTime)
end

rule "Ausgehender Anruf"
when
    Item fritzCallRinging changed to DIALING
then
    Thread.sleep(500)                                    // Wert eventuell auch noch erhöhen
    if(!(fritzOutgoingCall.state instanceof StringListType)) return;
    ongoing_call.sendCommand(ON)
    val outCall = fritzOutgoingCall.state as StringListType
    gAFlags.members.sortBy[ name ].reverseView.forEach[ i |
        val num = Integer::parseInt(i.name.split("_").get(1))
        val art = i.name.split("_").get(2)
        //logInfo("call","Move - zu Item {} Nummer ist {} Name endet mit {}",i.name,num,art)
        if(num > 1) {
            val myItem = gAFlags.members.filter[ j | j.name.split("_").get(1) == (num-1).toString && j.name.endsWith(art)].head
            i.postUpdate(myItem.state)
        }
    ]

    //val outCall = fritzOutgoingCall.state as StringListType
    var String calledNumber = outCall.getValue(0)
    // var String ourNumber = outCall.getValue(1)

    val tr064Actions = getActions("tr064","tr064:fritzbox:1")
    var calledName = tr064Actions.phonebookLookup(calledNumber)
    if(strFax.contains(calledNumber.toString))
        calledName = "Faxgerät"
    if(calledName==calledNumber)
        calledName = "unbekannt"
    val callDate = String.format("%1$td.%1$tm.%1$tY", now)
    val callTime = String.format("%1$tH:%1$tM", now)

    Flag_1_AName.postUpdate(calledName)
    Flag_1_ATel.postUpdate(calledNumber)
    Flag_1_ADat.postUpdate(callDate)
    Flag_1_ATime.postUpdate(callTime)
    Flag_1_ADauer.postUpdate("...") // signalisiert, dass gerade telefoniert wird

    logInfo("call", "Ausgang {} | {} | {} | {}",calledName,calledNumber,callDate,callTime)
end


rule "Anruf abgebrochen"
when
    Item fritzCallRinging changed from DIALING to IDLE
then
    logInfo("FRITZ!Box", "Anruf: Teilnehmer nicht erreichbar")
    ongoing_call.sendCommand(OFF)
    if(Flag_1_ADauer.state == "...")
            Flag_1_ADauer.postUpdate("abgebr.")
end

Minor corrections had to be made, but in this constellation no result is transferred to the item Flag_1_ADauer for the duration of a telephone call.

var Long lPhoneStart = 0
var Integer iSeconds = 0
var strFax = "030123456789" // Fax-Nummern

rule "Gesprächsdauer messen ON"
when
    Item Flag_Messen changed to ON
then
    val strNew  = newState.toString
    val strPrev = previousState.toString

    if(strNew == "ACTIVE") {
        if(strPrev == "RINGING")
            logInfo("call", "Eingehender Anruf: Verbindung hergestellt")
    }       else if(strPrev == "DIALING") {
            logInfo("call", "Ausgehender Anruf: Verbindung hergestellt")
            lPhoneStart = now.toInstant.toEpochMilli
    }
end

rule "Gesprächsdauer messen OFF"
when
    Item Flag_Messen changed to OFF
then
    if(strPrev == "ACTIVE" && strNew == "IDLE") {
        logInfo("call", "Aktiver Anruf: Verbindung beendet")
        iSeconds = ((now.toInstant.toEpochMilli - lPhoneStart)/1000).intValue
        var strTime = ""
        if(iSeconds !== null)
            strTime = transform("JS","secinhms.js",iSeconds.toString)
        logInfo("call", "Beendigung des {}gangsgespräches nach {}",if(Flag_1_ADauer.state.toString=="...")"Aus" else "Ein",strTime)
        if(Flag_1_EDauer.state == "...")
            Flag_1_EDauer.postUpdate(strTime)
    else if(Flag_1_ADauer.state == "...")
            Flag_1_ADauer.postUpdate(strTime)
    }
end


rule "Eingehender Anruf"
when
    Item fritzCallRinging changed to RINGING
then
    Thread.sleep(500)                                    // Wert eventuell auch noch erhöhen
    if(!(fritzIncomingCall.state instanceof StringListType)) return;
    val incCall      = fritzIncomingCall.state as StringListType
    Flag_Messen.sendCommand(ON)   
    gEFlags.members.sortBy[ name ].reverseView.forEach[ i |
        val num = Integer::parseInt(i.name.split("_").get(1))
        val art = i.name.split("_").get(2)
        if(num > 1) {
            val myItem = gEFlags.members.filter[ j | j.name.split("_").get(1) == (num-1).toString && j.name.endsWith(art)].head
            i.postUpdate(myItem.state)
        }
    ]

 // val incCall      = fritzIncomingCall.state as StringListType
 // val ourNumber    = incCall.getValue(0)
    val callerNumber = incCall.getValue(1)

    val tr064Actions = getActions("tr064","tr064:fritzbox:1")
    var callerName   = tr064Actions.phonebookLookup(callerNumber)
    if(strFax.contains(callerNumber.toString))
        callerName = "Faxgerät"
    if(callerName==callerNumber)
        callerName = "unbekannt"
    val callDate     = String.format("%1$td.%1$tm.%1$tY", now)
    val callTime     = String.format("%1$tH:%1$tM", now)

    Flag_1_EName.postUpdate(callerName)
    Flag_1_ETel.postUpdate(callerNumber)
    Flag_1_EDat.postUpdate(callDate)
    Flag_1_ETime.postUpdate(callTime)
    Flag_1_EDauer.postUpdate("...") // signalisiert, dass gerade telefoniert wird

    logInfo("call", "Eingang {} | {} | {} | {}",callerName,callerNumber,callDate,callTime)
end

rule "Ausgehender Anruf"
when
    Item fritzCallRinging changed to DIALING
then
    Thread.sleep(500)                                    // Wert eventuell auch noch erhöhen
    if(!(fritzOutgoingCall.state instanceof StringListType)) return;
    Flag_Messen.sendCommand(ON)
    val outCall = fritzOutgoingCall.state as StringListType
    gAFlags.members.sortBy[ name ].reverseView.forEach[ i |
        val num = Integer::parseInt(i.name.split("_").get(1))
        val art = i.name.split("_").get(2)
        //logInfo("call","Move - zu Item {} Nummer ist {} Name endet mit {}",i.name,num,art)
        if(num > 1) {
            val myItem = gAFlags.members.filter[ j | j.name.split("_").get(1) == (num-1).toString && j.name.endsWith(art)].head
            i.postUpdate(myItem.state)
        }
    ]

    //val outCall = fritzOutgoingCall.state as StringListType
    var String calledNumber = outCall.getValue(0)
    // var String ourNumber = outCall.getValue(1)

    val tr064Actions = getActions("tr064","tr064:fritzbox:1")
    var calledName = tr064Actions.phonebookLookup(calledNumber)
    if(strFax.contains(calledNumber.toString))
        calledName = "Faxgerät"
    if(calledName==calledNumber)
        calledName = "unbekannt"
    val callDate = String.format("%1$td.%1$tm.%1$tY", now)
    val callTime = String.format("%1$tH:%1$tM", now)

    Flag_1_AName.postUpdate(calledName)
    Flag_1_ATel.postUpdate(calledNumber)
    Flag_1_ADat.postUpdate(callDate)
    Flag_1_ATime.postUpdate(callTime)
    Flag_1_ADauer.postUpdate("...") // signalisiert, dass gerade telefoniert wird

    logInfo("call", "Ausgang {} | {} | {} | {}",calledName,calledNumber,callDate,callTime)
end


rule "Anruf abgebrochen"
when
    Item fritzCallRinging changed from DIALING to IDLE
then
    logInfo("FRITZ!Box", "Anruf: Teilnehmer nicht erreichbar")
    Flag_Messen.sendCommand(OFF)
    if(Flag_1_ADauer.state == "...")
            Flag_1_ADauer.postUpdate("abgebr.")
end

ADauer seems to be an item and does the same as Flag_messen?!
Just use Flag messen and set it on or off?

Flag_Messen is a dummy item (switch ON/OFF) and should only provide a status. It has the same function as the ongoing_call element you mentioned.
For each phone call (outgoing and incoming) I have provided 5 items: name, number, date, time and duration. The item Flag_1_ADauer adopts the value from the variable strTime after the end of an outgoing call and a correct execution of the rule “Gesprächsdauer messen”.
Unfortunately, this value is not passed in your example.

The item Flag_1_ADauer adopts the value from the variable strTime after the end of an outgoing call and a correct execution of the rule “Gesprächsdauer messen”.
Unfortunately, this value is not passed in your example.

I can’t see what types your items are but I would decide for one. I would choose “number” and stop to update it with “…”. Thats a string and does no good. Make an ongoing call 555555555 or whatever you like. Not …

if(strNew == "ACTIVE") {
        if(strPrev == "RINGING")
            logInfo("call", "Eingehender Anruf: Verbindung hergestellt")
    }       else if(strPrev == "DIALING") {
            logInfo("call", "Ausgehender Anruf: Verbindung hergestellt")
            lPhoneStart = now.toInstant.toEpochMilli
            logInfo("call", "lPhone: " + lPhoneStart)
    }

Log the things you think are not correct so that you see what happens. I can’t see from here.

ADauer is of the type String And “…” is only intended to indicate that a call is in progress. The variable ‘lPhoneStar’ is declared globally with ‘var Long lPhoneStart = 0’ at the beginning of the code.