Accessing AMI using Python/Flask to calculate call duration and limit

Hello Asterisk world,

Currently I am using Python to connect to AMI and everything is working fine. I can see live calls, hangup calls as well

But I have a task to accomplish, with every calls made I can see the duration of these calls. Now I have to deduct the duration from the balance added in the MySQL table column for the user.

So when (balance - current_duration) < 60seconds then an IVR should tell the user that he or she has 1 minute left.

Do you think this can be achieved using the Python script. Also the script will have to run asynchronously not needing to go to a page before the function can be activated.

Yes, you can achieve this WITHOUT AMI

  • compute the “max_allowed_time”
  • use the Dial() app with option “L” to limit the call duration and play announcement as required

please refer to Asterisk Dial Command

pasting relevant section here:

L(x[:y][:z]): Limit the call to ‘x’ ms, warning when ‘y’ ms are left, repeated every ‘z’ ms) Only ‘x’ is required, ‘y’ and ‘z’ are optional. Numbers must be integers- beware of AGI scripts that may return long integers in scientific notation (esp PHP 5.2.5&6) The following special variables are optional for limit calls: (pasted from app_dial.c)

LIMIT_PLAYAUDIO_CALLER - yes|no (default yes) - Play sounds to the caller.
LIMIT_PLAYAUDIO_CALLEE - yes|no - Play sounds to the callee.
LIMIT_TIMEOUT_FILE - File to play when time is up.
LIMIT_CONNECT_FILE - File to play when call begins.
LIMIT_WARNING_FILE - File to play as warning if 'y' is defined. If LIMIT_WARNING_FILE is not defined, then the default behaviour is to announce ("You have [XX minutes] YY seconds").

@usmanbaiga Will I have to convert the balance to miliseconds

I have it like this

The balance here is 100 seconds
same => n, Set(balance= 100)

same => n, Set(calcbal = $[1000 * ${balance}])

same => n,Dial(SIP/1200,50, L(${calcbal}:60000))

I want to achieve an IVR saying balance is low if the ${calc} is 60s

So I converted to miliseconds by multiplying by 1000 to give 60000

But it is not working

Which version of asterisk you are using ?

please check if L switch in Dial() app is supported by that asterisk version.

I am using Asterisk 13

does asterisk 13 supports the L switch in Dia() app ?

it should.

WIll I have to convert the seconds to miliseconds by multiplying by 1000?

The L in DIal didnt work. Will I have to convert to miliseconds cos that is what I did but didnt work

  • Asterisk 13 does supports L switch in Dial() app, please check below

  • YES, you have to do seconds*1000 to get milliseconds

I am trying to test it now. Also I have this channel to update balance for ${CDR(billsec)} is just an empty string. I want to get the duration of the call at the point of answer

exten => h,1,NoOp(Now call is hangup for user ${user_id} now update balance ${balance} from ${CDR(billsec)})
same => n,Set(billmin = $[${CDR(billsec)} / 60 ])
same => n,NoOp(The billsec in minute is ${billmin})
same => n,Set(new_balance = $[${balance} - ${billmin}])
same => n,Set(BALANCE_UPDATE(${new_balance}, ${user_id}))

Now I monitored the CLI and I got to find out it is omitting the first argument which is the limit. So it just put a space instead of the variable followed by the colon.


But when I hard coded it this way


Maybe I have to see what is happening with the variable


${CDR(billsec)} will never contain a value unless the call is dropped (I may be wrong here)

You need to get the max allowed minutes from DB, that has the user details (use AGI)
and compute values to be used in L switch with Dial() app

Yes I am doing that in the hangup event (h) extension

Now I have figured a way to fix that.

Can func_odbc.conf do update.

prefix = BALANCE
dsn = project
writesql = UPDATE customers SET balance=’${ARG1}’ WHERE custid = ‘${ARG2}’

This query is not working. I think the problem is the argument ${ARG1} but I do not know how to fix it

I am passing 2 values in the dialplan BALANCE_STATUS(2,150) but it is not working.

share CLI logs with verbose 3, atleast

– Executing [h@forward:1] NoOp(“SIP/”, “Now call is hangup for user 174 now update balance 10 from 52”) in new stack
– Executing [h@forward:2] Set(“SIP/”, “billmin = 0.866666666666666667”) in new stack
– Executing [h@forward:3] NoOp(“SIP/”, "The billsec in minute is ") in new stack
– Executing [h@forward:4] Set(“SIP/”, “BALANCE_STATUS(9.13333333333333333, 174)”) in new stack

Also the column in the MySQL storing the value is an INT(30) so I would be expecting 9 to be saved in this scenario.

do you have anything relevant to this in /var/log/asterisk/messages ?