Get Ring Time, billable Time, then the transfer times both ring and billable in CDR

I am having so much trouble with this, and it should be so simple.

So I am looking to originate a call get the ring time, billable time, then transfer to an external number and get the ring and billable time in the cdr.

I get the ring and billable time (Even though the ring time is off, it’s just the time from start to answer)
But I do not get the correct transfertimes?

I am using this originate AMI:

Action: originate
Channel: Local/s@outbound-dialer-custom;
Exten: 0
Context: speech-rec
Variable: toNum=6305559999
Priority: 1


[outbound-dialer-custom]
exten => s,1,Dial(IAX2/voipMSTEST/${toNum},30) 

[speech-rec]
   exten => 0,1,Answer()
   exten => 0,n,Wait(5)
   exten => 0,n,Dial(IAX2/voipMSTEST/6305551234,30,g)
   exten => 0,n,Hangup()

Please see my answers to the person asking about answer times for the called party.

Also note that the Answer in your dialplan serves no useful purpose, and, in simpler cases can cause a less useful answer time to appear in the CDR, and the caller to get billed for listening to ringback tone.

David,

First thanks a lot for helping.

The mock dialplan above is just so I could have the following variables the originate context would dial, I would show 5 seconds before it tried to transfer then I’d have a ring and anwer. I changed the code to simplify it, but they speech-rec is an actual ivr that requires user interaction. That’s why the answer() was left there

I’m getting closer, so here is what I have

exten => 0,1,NoOp(“HELLO”)
;exten => 0,n,AGI(tts_custom.agi,Operator we are connection,flitevoice,/usr/local/bin/flite,slt)
exten => 0,n,Wait(5)
same=>n,NoOp(STATUS ${CDR(start)}) ;start of record
;exten => 0,n,ForkCDR(aA)
;exten => 0,n,ResetCDR(wav)
same=>n,NoOp(STATUS ${DIALSTATUS})
same=>n,NoOp(AnsweredTime ${ANSWEREDTIME})
same=>n,NoOp(DialedTime ${DIALEDTIME})
same=>n,NoOp(TransferTime ${CDR(billsec)})
same=>n,NoOp(RINGTIME ${CDR(duration)})
same=>n,NoOp(Start of transfer ${STRFTIME(${EPOCH},%Y-%m-%d %H:%M:%S)})
exten => 0,n,Dial(IAX2/voipMSTEST/6302063244,30,Fg)
same=>n,NoOp(End of transfer ${STRFTIME(${EPOCH},%Y-%m-%d %H:%M:%S)})
same=>n,NoOp(STATUS ${DIALSTATUS})
same=>n,NoOp(AnsweredTime ${ANSWEREDTIME})
same=> n,NoOp(DialedTime ${DIALEDTIME})
exten => 0,n,Verbose(2,### HANGUPGO next#######)
exten => 0,n,Hangup()

The AnsweredTime gives me the entire call answer time, the dialedtime - answertime seems to be the ring time on the transfer, so transferend - transferstart - (dialedtime-answertime) give me my total answer time.

Here is the only thing left that is bothering me. Why in my cdr is my billedsec 26 seconds instead of 27 seconds when the start and end is 27 seconds. Is this a milisecond rounding issue, and if so how do I match it?

  • Executing [0@speech-rec:1] NoOp(“IAX2/voipMSTEST-13760”, ““HELLO””) in new stack
    – Executing [0@speech-rec:2] Wait(“IAX2/voipMSTEST-13760”, “5”) in new stack
    – Executing [0@speech-rec:3] NoOp(“IAX2/voipMSTEST-13760”, “STATUS 2017-05-03 18:23:56”) in new stack
    – Executing [0@speech-rec:4] NoOp(“IAX2/voipMSTEST-13760”, "STATUS ") in new stack
    – Executing [0@speech-rec:5] NoOp(“IAX2/voipMSTEST-13760”, "AnsweredTime ") in new stack
    – Executing [0@speech-rec:6] NoOp(“IAX2/voipMSTEST-13760”, "DialedTime ") in new stack
    – Executing [0@speech-rec:7] NoOp(“IAX2/voipMSTEST-13760”, “TransferTime 5”) in new stack
    – Executing [0@speech-rec:8] NoOp(“IAX2/voipMSTEST-13760”, “RINGTIME 5”) in new stack
    – Executing [0@speech-rec:9] NoOp(“IAX2/voipMSTEST-13760”, “Start of transfer 2017-05-03 18:24:01”) in new stack
    – Executing [0@speech-rec:10] Dial(“IAX2/voipMSTEST-13760”, “IAX2/voipMSTEST/6302063244,30,Fg”) in new stack
    – Called IAX2/voipMSTEST/6302063244
    – Call accepted by 208.100.39.53:4569 (format ulaw)
    – Format for call is (ulaw)
    – IAX2/voipMSTEST-9604 is making progress passing it to IAX2/voipMSTEST-13760
    – IAX2/voipMSTEST-9604 is making progress passing it to IAX2/voipMSTEST-13760
    – IAX2/voipMSTEST-9604 answered IAX2/voipMSTEST-13760
    – Channel IAX2/voipMSTEST-9604 joined ‘simple_bridge’ basic-bridge <6840bbe0-2b77-410a-9a7a-bd2060dd04c7>
    – Channel IAX2/voipMSTEST-13760 joined ‘simple_bridge’ basic-bridge <6840bbe0-2b77-410a-9a7a-bd2060dd04c7>
    – Channel IAX2/voipMSTEST-9604 left ‘simple_bridge’ basic-bridge <6840bbe0-2b77-410a-9a7a-bd2060dd04c7>
    – Channel IAX2/voipMSTEST-13760 left ‘simple_bridge’ basic-bridge <6840bbe0-2b77-410a-9a7a-bd2060dd04c7>
    – Executing [0@speech-rec:11] NoOp(“IAX2/voipMSTEST-13760”, “End of transfer 2017-05-03 18:24:23”) in new stack
    – Executing [0@speech-rec:12] NoOp(“IAX2/voipMSTEST-13760”, “STATUS ANSWER”) in new stack
    – Executing [0@speech-rec:13] NoOp(“IAX2/voipMSTEST-13760”, “AnsweredTime 26”) in new stack
    – Hungup ‘IAX2/voipMSTEST-9604’
    – Executing [0@speech-rec:14] NoOp(“IAX2/voipMSTEST-13760”, “DialedTime 32”) in new stack
    – Executing [0@speech-rec:15] Verbose(“IAX2/voipMSTEST-13760”, “2,### HANGUPGO next#######”) in new stack
    == ### HANGUPGO next#######
    – Executing [0@speech-rec:16] Hangup(“IAX2/voipMSTEST-13760”, “”) in new stack
    == Spawn extension (speech-rec, 0, 16) exited non-zero on ‘IAX2/voipMSTEST-13760’
    – Executing [h@speech-rec:1] NoOp(“IAX2/voipMSTEST-13760”, “STATUS ANSWER”) in new stack
    – Executing [h@speech-rec:2] NoOp(“IAX2/voipMSTEST-13760”, “END OF CALL/Transfer 2017-05-03 18:24:23”) in new stack
    – Executing [h@speech-rec:3] NoOp(“IAX2/voipMSTEST-13760”, “AnsweredTime 26”) in new stack
    – Executing [h@speech-rec:4] NoOp(“IAX2/voipMSTEST-13760”, “DialedTime 32”) in new stack
    – Executing [h@speech-rec:5] NoOp(“IAX2/voipMSTEST-13760”, “TransferTime 0”) in new stack
    – Executing [h@speech-rec:6] NoOp(“IAX2/voipMSTEST-13760”, “RINGTIME 0”) in new stack

Please use the log files, rather than scraping the screen, as you will then get time stamps.

I’m not familiar with the ANSWERTIME variable. It’s either new or I overlooked it.

Personally, I never got ForkCDR to do anything obviously useful, so when I do this sort of thing I use ResetCDR with the w option.

I’m also only familiar with versions before the big CDR rewrite.

Thanks again for your assistance David.

The RestetCDR does not provide useful data for this scenerio. THe end of the day I need

RINGTIME FOR CALL
TALK TIME FOR TOTAL CALL (Filtering out ringTime for the Bridge and initial ring time)
BILLABLE TIME FOR CALL 1
BILLABLE TIME FOR CALL 2

The only way I was successfully able to get this was:

  1. RIngtime for call is simply dialedtime - answeredtime
  2. Talk Time for call is answeredtime - ((transferEnd - TransferStart) - TransferRingTime)
  3. Billable Time for Call 1 is simply AnsweredTime
  4. Billable Time for Call 2 is tricky since we only pay once Answered, so that required me to look in the CEL database for Bridge EnteredTime/ANSWER

Def way harder than I anticipated, but if I want to ensure our providers are charging us what we’d expect those are the variables I need.

Thanks again for your assistance!

Incase anyone else has an issue, here is the final code

Action: originate
Channel: Local/s@outbound-dialer-custom;
Exten: 0
Context: speech-rec
Variable: toNum=6305559999
Priority: 1

The below items show how you can add multiple trunks or do lcr routing, if it’s a NO ANSWER or Answer it stops trying, otherwise it will go to the next one as many wholesale sip providers will return a 503 error and that does not necessarly mean another provider cannot connect.

[outbound-dialer-custom]
exten => s,1,NoOp(${toNum})
;exten => s,n,Dial(IAX2/voipMSTEST/6305551212,5) ;try 1
;exten => s,n,NoOp(${DIALSTATUS})
;exten => s,n,GotoIf($[${DIALSTATUS}=NOANSWER | ${DIALSTATUS}=BUSY]?noanswer)
;exten => s,n,GotoIf($[${DIALSTATUS}=NOANSWER | ${DIALSTATUS}=BUSY]?noanswer)
same=>n,NoOp(Start of CALL ${STRFTIME(${EPOCH},,%Y-%m-%d %H:%M:%S)}) ;try 2
exten => s,n,Dial(IAX2/voipMSTEST/${toNum},30) ;try 2
exten => s,n,GotoIf($[${DIALSTATUS}=NOANSWER | ${DIALSTATUS}=BUSY]?noanswer)
exten => s,n(noanswer),Hangup()



 exten => 0,1,NoOp(Start of Answer ${STRFTIME(${EPOCH},,%Y-%m-%d %H:%M:%S)})

exten => 0,n,Wait(3)
same=>n,NoOp(Start of transfer ${STRFTIME(${EPOCH},%Y-%m-%d %H:%M:%S)})
same=>n,Set(transfer=1)
same=>n,Set(transferhangup=0)
same=>n,Dial(IAX2/voipMSTEST/6302063333,30,e)

exten => h,1,NoOp(STATUS ${DIALSTATUS})
exten => h,n,GotoIf($[${transfer}=1 & ${transferhangup}=0]?transferanswer:transferhangup)
same=>n(transferanswer),Set(transferhangup=1)
same=>n,NoOp(Transfer Was Answered at : ${STRFTIME(${EPOCH},,%Y-%m-%d %H:%M:%S)})
same=>n,NoOp(STATUS ${CDR(start)}) ;start of record
same=>n,NoOp(STATUS ${DIALSTATUS})
same=>n,NoOp(AnsweredTime ${ANSWEREDTIME})
same=>n,NoOp(DialedTime ${DIALEDTIME})
same=>n,NoOp(TransferTime ${CDR(billsec)})
same=>n,NoOp(RINGTIME ${CDR(duration)})
same=>n,Hangup()
same=>n(transferhangup),NoOp(HANGUP TRANSFER)
same=>n,NoOp(Transfer Terminated  ${STRFTIME(${EPOCH},,%Y-%m-%d %H:%M:%S)}) ;start of record
same=>n,NoOp(STATUS ${CDR(start)}) ;start of record
same=>n,NoOp(STATUS ${DIALSTATUS})
same=>n,NoOp(AnsweredTime ${ANSWEREDTIME})
same=>n,NoOp(DialedTime ${DIALEDTIME})
same=>n,NoOp(TransferTime ${CDR(billsec)})
same=>n,NoOp(RINGTIME ${CDR(duration)})
same=>n,Hangup()

So the start of call ringing gives us the start time
The start of Answer shows the time the call actually picked up
The start of transfer is when it starts ringing
The Transfer Was answered is when the call was answered
The transfer Ended is the call/transfer end time.

With those variables you can figure out everything else you need.

1 Like