FollowMe with multiple devices

Hello,

This is a follow up on the FollowMe Issues post which brought up some issues with the way follow me was designed,
Most of the issues there were resolved in version 3.1.4 and hence the post has been marked as solved, however, there is one issue that wasn’t solved yet, see below.

The Issue: When follow me calls a few extensions / external numbers and one of the callees answers the call, the call to all other devices will terminate immediately (before they press 1), the cause to the issue is that the U dial option is applied when the follow me application dials the group of follow me destinations.

The Fix: To fix this issue, we must apply only the the U option when dialing the endpoint(s)/trunk, looking at the dialplan there we see that it already applies the U option to process call recording, so I edited the dialplan to execute the call confirm there as well.

See current and modified dialplans below.

Current Dialplans

[ext-followme]
exten => FW101,1,NoOp(Follow Me: FW101)
 same => n,ExecIf($["${LEN(${INBOUND_LANGUAGE})}"!="0"]?Set(CHANNEL(language)=${INBOUND_LANGUAGE}):Set(CHANNEL(language)=${DB(${TENANT}/extensions/101/language)}))
 same => n,Set(__RETURN_ON_EXTERNAL=yes)
 same => n,Set(__SKIP_PLAYBACK=${IF($["${QUEUE_CALL}"="TRUE"]?TRUE:${SKIP_PLAYBACK})})
 same => n,Set(CALLER_RECORDING=${ASTSPOOLDIR}/tmp/followme-${UNIQUEID}.wav)
 same => n,Set(__O_RING_TIME=30)
 same => n,Set(__SKIP_CONTACT_SERVICES=TRUE)
 same => n,Set(__SRC_APP=${IF($["${LEN(${SRC_APP})}"="0"]?FW101:${SRC_APP})})
 same => n(start-dialing),NoOp(Start Dialing)
 same => n,Gosub(sub-set-moh,s,1(default,YES))
 same => n,Dial(Local/1234567890@cos-all/n&Local/101@cos-all/n,30,rU(FW101-confirm^${RECORDED_FILE}))
 same => n,System(rm -f ${CALLER_RECORDING})
 same => n,Set(__SKIP_CONTACT_SERVICES=FALSE)
 same => n,Return()

 [sub-call-recording]
 exten => s,1,NoOp(Check if call will be recorded on tenant ${TENANT})
  same => n,NoOp(Call Type: ${CALL_TYPE} )
  same => n,Set(TENANT=${ARG1})
  same => n,Set(CALLER=${ARG2})
  same => n,Set(CALLEE=${ARG3})
  same => n,Set(APP_FORCE=${ARG4})
  same => n,GotoIf($["${DB(${TENANT}/allow_recordings)}"="yes"]?:rec_no_available)
  same => n,GotoIf($["${APP_FORCE}"="yes"]?perform-recording)
  same => n,GotoIf($[$["${CALL_TYPE}"="1"]&$["${DB(${TENANT}/extensions/${CALLEE}/internal_rec)}"="yes"]]?perform-recording)
  same => n,GotoIf($[$["${CALL_TYPE}"="1"]&$["${DB(${TENANT}/extensions/${CALLER}/internal_rec)}"="yes"]]?perform-recording)
  same => n,GotoIf($[$[$["${CALL_TYPE}"="2"]|$["${CALL_TYPE}"="4"]]&$["${DB(${TENANT}/extensions/${CALLEE}/incoming_rec)}"="yes"]]?perform-recording)
  same => n,GotoIf($[$[$["${CALL_TYPE}"="3"]|$["${CALL_TYPE}"="4"]]&$["${DB(${TENANT}/extensions/${CALLER}/outgoing_rec)}"="yes"]]?perform-recording)
  same => n,Goto(return)
  same => n(perform-recording),Gosub(sub-perform-recording,s,1)
  same => n,Goto(return)
  same => n(rec_no_available),NoOP(Recordins are not available for tenant ${DB(${TENANT}/name)})
  same => n(return),Return()

[FW101-confirm]
exten => s,1,NoOp(Confirm Call)
 same => n,ExecIf($["${LEN(${INBOUND_LANGUAGE})}"!="0"]?Set(CHANNEL(language)=${INBOUND_LANGUAGE}):Set(CHANNEL(language)=${DB(${TENANT}/extensions/101/language)}))
 same => n,Set(DIALED_NUMBER=${CUT(DIALEDPEERNUMBER,@,1)})
 same => n,Set(RECFILE=${ARG1})
 same => n,Set(SOUND=${IF($["${LEN(${RECFILE})}"="0"]?followme/no-recording:followme/call-from&${RECFILE})})
 same => n,GotoIf(${DB_EXISTS(${TENANT}/extensions/${DIALED_NUMBER}/name)}?accept)
 same => n,Set(GOSUB_RESULT=CONTINUE)
 same => n,Read(CONFIRM,${SOUND}&followme/options,1,,1,5)
 same => n(accept),Set(_GOSUB_RESULT=${IF($["${CONFIRM}" = "1"]?:${GOSUB_RESULT})})
 same => n,Return()

Modified Dialplans

[ext-followme]
exten => FW101,1,NoOp(Follow Me: FW101)
 same => n,ExecIf($["${LEN(${INBOUND_LANGUAGE})}"!="0"]?Set(CHANNEL(language)=${INBOUND_LANGUAGE}):Set(CHANNEL(language)=${DB(${TENANT}/extensions/101/language)}))
 same => n,Set(__RETURN_ON_EXTERNAL=yes)
 same => n,Set(__SKIP_PLAYBACK=${IF($["${QUEUE_CALL}"="TRUE"]?TRUE:${SKIP_PLAYBACK})})
 same => n,Set(CALLER_RECORDING=${ASTSPOOLDIR}/tmp/followme-${UNIQUEID}.wav)
 same => n,Set(__O_RING_TIME=30)
 same => n,Set(__SKIP_CONTACT_SERVICES=TRUE)
 same => n,Set(__SRC_APP=${IF($["${LEN(${SRC_APP})}"="0"]?FW101:${SRC_APP})})
 same => n(start-dialing),NoOp(Start Dialing)
 same => n,Gosub(sub-set-moh,s,1(default,YES))
 same => n,Set(__FWM_CONFIRM_CONTEXT=FW101-confirm,s,1(${RECORDED_FILE}))
 same => n,Dial(Local/1234567890@cos-all/n&Local/101@cos-all/n,30,r)
 same => n,System(rm -f ${CALLER_RECORDING})
 same => n,Set(__SKIP_CONTACT_SERVICES=FALSE)
 same => n,Return()

 [sub-call-recording] ;Can perhaps be changed to [before-bridging-call]
 exten => s,1,Noop(Executing routines in the newly created channel before bridging the call)
  same => n,GotoIf($["${FWM_CONFIRM_CONTEXT}"=""]?recording)
  same => n,Set(DIALED_NUMBER=${ARG3})
  same => n,Gosub(${FWM_CONFIRM_CONTEXT})
  same => n(recording),NoOp(Check if call will be recorded on tenant ${TENANT})
  same => n,NoOp(Call Type: ${CALL_TYPE} )
  same => n,Set(TENANT=${ARG1})
  same => n,Set(CALLER=${ARG2})
  same => n,Set(CALLEE=${ARG3})
  same => n,Set(APP_FORCE=${ARG4})
  same => n,GotoIf($["${DB(${TENANT}/allow_recordings)}"="yes"]?:rec_no_available)
  same => n,GotoIf($["${APP_FORCE}"="yes"]?perform-recording)
  same => n,GotoIf($[$["${CALL_TYPE}"="1"]&$["${DB(${TENANT}/extensions/${CALLEE}/internal_rec)}"="yes"]]?perform-recording)
  same => n,GotoIf($[$["${CALL_TYPE}"="1"]&$["${DB(${TENANT}/extensions/${CALLER}/internal_rec)}"="yes"]]?perform-recording)
  same => n,GotoIf($[$[$["${CALL_TYPE}"="2"]|$["${CALL_TYPE}"="4"]]&$["${DB(${TENANT}/extensions/${CALLEE}/incoming_rec)}"="yes"]]?perform-recording)
  same => n,GotoIf($[$[$["${CALL_TYPE}"="3"]|$["${CALL_TYPE}"="4"]]&$["${DB(${TENANT}/extensions/${CALLER}/outgoing_rec)}"="yes"]]?perform-recording)
  same => n,Goto(return)
  same => n(perform-recording),Gosub(sub-perform-recording,s,1)
  same => n,Goto(return)
  same => n(rec_no_available),NoOP(Recordins are not available for tenant ${DB(${TENANT}/name)})
  same => n(return),Set(_GOSUB_RESULT=${GOSUB_RESULT})
  same => n,Return()

[FW101-confirm]
exten => s,1,NoOp(Confirm Call)
 same => n,ExecIf($["${LEN(${INBOUND_LANGUAGE})}"!="0"]?Set(CHANNEL(language)=${INBOUND_LANGUAGE}):Set(CHANNEL(language)=${DB(${TENANT}/extensions/101/language)}))
 same => n,Set(RECFILE=${ARG1})
 same => n,Set(SOUND=${IF($["${LEN(${RECFILE})}"="0"]?followme/no-recording:followme/call-from&${RECFILE})})
 same => n,GotoIf(${DB_EXISTS(${TENANT}/extensions/${DIALED_NUMBER}/name)}?accept)
 same => n,Set(GOSUB_RESULT=CONTINUE)
 same => n,Read(CONFIRM,${SOUND}&followme/options,1,,1,5)
 same => n(accept),Set(_GOSUB_RESULT=${IF($["${CONFIRM}" = "1"]?:${GOSUB_RESULT})})
 same => n,Return()

I tested this dialplan with internal and external follow me destinations, as well as on single and multi tenant systems, and all was working as expected.

Please consider taking a look at this, and if possible include the fix in future updates.

Thank you.

2 Likes

Can anyone at Vital please look in to this? this is not a final solution but rather a proof of concept on how and where to execute the follow-me confirmation.

Thank you.

We will verify this and see how to implement it.

3 Likes

Hi @miguel,

Just curious if you had a chance to test this, and if there’s an update on if and when it will be implemented.

Thank you.

We will run some tests soon. I’ll keep you posted.

2 Likes

This is fixed in 3.2.1, thank you @miguel.

BTW, there’s a closing parentheses missing in the new sub-before-bridging-call context at priority 10

  same => n,Gosub(sub-call-recording,s,1(${TENANT},${CALLER},${CALLEE},${FORCE_CALL_RECORDING})
2 Likes