Recently I installed for a customer an Asterisk PBX with ACD service.
This customer has the necessity to have two queues with specialized agents.
If situation requires, not specialized agent should answer the call.
In the situation in which only one specialized agent is logged in, and he/she is not at the phone, because whatever reason, it would happen that the call is not routed to other agent with lower priority.
To fix this scenario, you can use the autopause feature, which put in the pause status an agent if he/she does not answer the call.
But when the agent returns back at him/her position, he/she can not know he/she has been auto paused, and then he/she could sit and wait a call that will never arrive.
It would be nice to have a signal on the telephone stating the ACD pause status.
I do not find any built-in feature in the Asterisk I were using that let me do this, so I wrote a script to have such service.
The idea is to watch the "queue_log" where asterisk puts all events about ACD and agents.
When agent pause event appears in such log, you can set the respective devicestate using "devstate change" Asterisk cli command.
Here my script.
#!/bin/sh
# Agentwatch 0.1 2014 Alessandro Carminati
on_die()
{
rm /tmp/aw
exit 0
}
trap 'on_die' TERM INT KILL
[ -f /tmp/aw ] && echo "aw exists, exit" && exit;
touch /tmp/aw
IFS=$'\n';
for i in $(rasterisk -x "queue show queue1" | grep "SIP"); do
status="NOT_INUSE";
echo $i |grep "paused" >/dev/null && status="INUSE";
ext=$(echo $i | cut -d "(" -f1| sed -e 's/ //g'| sed -e 's/.*sip//');
rasterisk -x "devstate change custom:queue1_${ext} ${status}" >/dev/null
[ "${1}" = "-d" ] && echo "devstate change custom:queue1_${ext} ${status}"
done
for i in $(rasterisk -x "queue show queue2" | grep "SIP"); do
status="NOT_INUSE";
echo $i |grep "paused" >/dev/null && status="INUSE";
ext=$(echo $i | cut -d "(" -f1| sed -e 's/ //g'| sed -e 's/.*sip//');
rasterisk -x "devstate change custom:queue2_${ext} ${status}" >/dev/null
[ "${1}" = "-d" ] && echo "devstate change custom:queue2_${ext} ${status}"
done
tail -n0 -f /var/log/asterisk/queue_log | while read LOGLINE
do
if [[ "${LOGLINE}" == *"|PAUSE|"* ]]; then
coda=$(echo "${LOGLINE}" | cut -d"|" -f3);
agente=$(echo "${LOGLINE}" | cut -d"|" -f4|cut -d"p" -f2);
[ "${1}" = "-d" ] && echo "l'agente $agente entra in pausa per la coda $coda";
rasterisk -x "devstate change custom:${coda}_${agente} INUSE" >/dev/null
fi
if [[ "${LOGLINE}" == *"|UNPAUSE|"* ]]; then
coda=$(echo "${LOGLINE}" | cut -d"|" -f3);
agente=$(echo "${LOGLINE}" | cut -d"|" -f4|cut -d"p" -f2);
[ "${1}" = "-d" ] && echo "l'agente $agente esce dalla pausa per la coda $coda";
rasterisk -x "devstate change custom:${coda}_${agente} NOT_INUSE" >/dev/null
fi
done
Because you want to see this on the phone, you have to define some hints so them can be configured as blf on the phone. (Agent extensions goes from 511 to 519).
exten => *9*511, hint, Custom:queue1_511&Custom:queue2_511
exten => *9*512, hint, Custom:queue1_512&Custom:queue2_512
exten => *9*513, hint, Custom:queue1_513&Custom:queue2_513
exten => *9*514, hint, Custom:queue1_514&Custom:queue2_514
exten => *9*515, hint, Custom:queue1_515&Custom:queue2_515
exten => *9*516, hint, Custom:queue1_516&Custom:queue2_516
exten => *9*517, hint, Custom:queue1_517&Custom:queue2_517
exten => *9*518, hint, Custom:queue1_518&Custom:queue2_518
exten => *9*519, hint, Custom:queue1_519&Custom:queue2_519
And at last, because you want this service starts automaticaly when server goes up, here is my redhat fashon rc script.
#!/bin/sh
# $Id: rc.redhat.agentwatch 268535 2010-06-06 05:31:11Z AC$
#
# AgentWatch Starts, Stops and Reloads
#
# chkconfig: 2345 90 60
# description: Track using blf pause status
# processname: agentwatch
# pidfile: /var/run/aw.pid
#
. /etc/init.d/functions
if test -e /etc/sysconfig/mouse ; then
. /etc/sysconfig/mouse
fi
RETVAL=0
start() {
echo "Starting AgentWatch service: "
/usr/aw/agentwatch.sh >/dev/null &
echo $! > /var/run/aw.pid
}
stop() {
echo "Shutting down AgentWatch service: "
kill -9 $(cat /var/run/aw.pid);
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart|reload)
stop
start
;;
*)
echo $"Usage: $0 {start|stop|restart}"
exit 1
esac
exit $RETVAL
Any comment about this argument is very welcome.
Thursday, June 12, 2014
Sunday, May 18, 2014
Asterisk and old Pay Phones
Today I want to talk you about a matter I have with an old Pay phone.
The less young among my readers may recall the old days when there was no mobile phone.
Those days if it happened you had to call someone, you used to go to a payphone booth and call.
During the 70s and early 80s in some Europeans countries among others, there were widespread usage of some special coins, telephone tokens. Those times, if you wanted to use one of those payphone, you also needed a telephone token.
Today's topic however, is not properly the payphone, it is instead the way old Pay Phones collect tokens, or to say it better how to reproduce it in a modern Asterisk based telephone system.
For today topic I focused on the only Pay Phone I have, the Italian U+I.
U+I stands for "urbane ed interurbane" (local calls and long distance call), is the first public phone in Italy by which you could call someone outside of your city without operator's support.
At that times, the signaling between central office and telephones was quite easy, they had only a twisted pair and quite simple technology. The signaling was done just by reversing polarity of the twisted pair.
Signals from central office side was something like
Also, from terminal side, the signaling were done using polarity reversal and interrupting local loop (Pulse dialing).
From terminal side, after the receipt of central office command "collect token", terminal had to invert polarity for 50ms, failing in doing so, was interpreted as "no more tokens" and than call was ended by central office.
Our goal is therefore invert polarity when we need to say to the payphone to collect the token.
My first thought was to use polarity reversal feature, if fits, due to its widespread we can use almost any ATA on the market to have it. Not properly suited for this task, though.
Lets see.
From wikipedia: "Modern loop start trunks also have methods of answer supervision and disconnect supervision to alert a foreign exchange office (FXO) interface that the remote party has answered or hung up. Answer supervision usually takes the form of the central office reversing the polarity of the line for the duration of the call when it has been answered. This condition is called Reverse Battery or battery reversal. Disconnect supervision can take the form of the polarity reversing back. [...]"
It is quite different from what we need; the specification states: momentarily polarity reversal each time payphone needs to collect tokens, using this feature we have a unique polarity reversal from connection to the end of the call.
Projecting this feature on our device, the Italian U+I, the result is an odd behaviour that may be sufficient for someone, but which is definitely not what we want. We may observe, when call connects, the phone collecting the token and also switch its status to "out of order". Call does not drop, it continues until you hang up, and finally when you hang up, due to polarity reversion, the device tries again to collect a token while revert its status in "on line".
To have the control of the line the way we want we can not use any standard feature, we have to control the line directly.
Asterisk controls DAHDI devices directly through chan_dahdi channel driver. It means that to implement the standard feature battery reversal, the way you have on standard connection it have to "manually" invert the polarity on the line.
Reviewing code I could write a new dialplan application Polarity().
Using this new dialplan application is now possible to collect the first token, the one usually collected when the called party answers the line.
Here a dialplan to do so.
[payphone]
exten => _X., 1, Set(GLOBAL(cchan)=${CHANNEL})
exten => _X., n, Dial(dahdi/1/${EXTEN},30,G(payphone,ANSWERED,1));
exten => ANSWERED, 1, Goto(ANSWERED1,1)
exten => ANSWERED, n, Goto(ANSWERED2,1)
exten => ANSWERED1, 1, polarity2(${GLOBAL(cchan)}, 500)
exten => ANSWERED1, n, Answer()
exten => ANSWERED2, 1, wait(1)
exten => ANSWERED2, 2, Bridge(${GLOBAL(cchan)})
Though using this application is now possible to revert the polarity the way we need when call connects, because Asterisk structure, the dialplan application can not be used during a connected call, the incall token collection feature is therefore still missing.
In a not so distant future I'd like to add a flag to the Dial dialplan application to revert polarity at prefixed time intervals starting when called party answers the call.
The less young among my readers may recall the old days when there was no mobile phone.
Those days if it happened you had to call someone, you used to go to a payphone booth and call.
During the 70s and early 80s in some Europeans countries among others, there were widespread usage of some special coins, telephone tokens. Those times, if you wanted to use one of those payphone, you also needed a telephone token.
Today's topic however, is not properly the payphone, it is instead the way old Pay Phones collect tokens, or to say it better how to reproduce it in a modern Asterisk based telephone system.
For today topic I focused on the only Pay Phone I have, the Italian U+I.
U+I stands for "urbane ed interurbane" (local calls and long distance call), is the first public phone in Italy by which you could call someone outside of your city without operator's support.
At that times, the signaling between central office and telephones was quite easy, they had only a twisted pair and quite simple technology. The signaling was done just by reversing polarity of the twisted pair.
Signals from central office side was something like
Duration | meaning |
>250ms | end call |
~50ms | collect token |
Continuous | out of order |
Also, from terminal side, the signaling were done using polarity reversal and interrupting local loop (Pulse dialing).
From terminal side, after the receipt of central office command "collect token", terminal had to invert polarity for 50ms, failing in doing so, was interpreted as "no more tokens" and than call was ended by central office.
Our goal is therefore invert polarity when we need to say to the payphone to collect the token.
My first thought was to use polarity reversal feature, if fits, due to its widespread we can use almost any ATA on the market to have it. Not properly suited for this task, though.
Lets see.
From wikipedia: "Modern loop start trunks also have methods of answer supervision and disconnect supervision to alert a foreign exchange office (FXO) interface that the remote party has answered or hung up. Answer supervision usually takes the form of the central office reversing the polarity of the line for the duration of the call when it has been answered. This condition is called Reverse Battery or battery reversal. Disconnect supervision can take the form of the polarity reversing back. [...]"
It is quite different from what we need; the specification states: momentarily polarity reversal each time payphone needs to collect tokens, using this feature we have a unique polarity reversal from connection to the end of the call.
Projecting this feature on our device, the Italian U+I, the result is an odd behaviour that may be sufficient for someone, but which is definitely not what we want. We may observe, when call connects, the phone collecting the token and also switch its status to "out of order". Call does not drop, it continues until you hang up, and finally when you hang up, due to polarity reversion, the device tries again to collect a token while revert its status in "on line".
To have the control of the line the way we want we can not use any standard feature, we have to control the line directly.
Asterisk controls DAHDI devices directly through chan_dahdi channel driver. It means that to implement the standard feature battery reversal, the way you have on standard connection it have to "manually" invert the polarity on the line.
Reviewing code I could write a new dialplan application Polarity().
Using this new dialplan application is now possible to collect the first token, the one usually collected when the called party answers the line.
Here a dialplan to do so.
[payphone]
exten => _X., 1, Set(GLOBAL(cchan)=${CHANNEL})
exten => _X., n, Dial(dahdi/1/${EXTEN},30,G(payphone,ANSWERED,1));
exten => ANSWERED, 1, Goto(ANSWERED1,1)
exten => ANSWERED, n, Goto(ANSWERED2,1)
exten => ANSWERED1, 1, polarity2(${GLOBAL(cchan)}, 500)
exten => ANSWERED1, n, Answer()
exten => ANSWERED2, 1, wait(1)
exten => ANSWERED2, 2, Bridge(${GLOBAL(cchan)})
Though using this application is now possible to revert the polarity the way we need when call connects, because Asterisk structure, the dialplan application can not be used during a connected call, the incall token collection feature is therefore still missing.
In a not so distant future I'd like to add a flag to the Dial dialplan application to revert polarity at prefixed time intervals starting when called party answers the call.
Friday, May 16, 2014
I2C driver for Sharp LM167511 lcd display
Recently I got into my hand this old digital phone.
The phone is part of a proprietary system of the early 90s, not so much useful today, but the display seems to be still useful, so I took apart it from the rest, and I begun to test its behaviour.
Display is branded Sharp model LM167511 and it is controled by the OKI MSM6262 chip.
The other 2 components present on the PCB are column drivers T6A39, not particulary interesting to control it.There's not a lot of documentation about this display provided by Sharp nor anyone else, and googling for its name you can only find an old post of a spanish guy asking if someone knows how to use it.
Using a multimeter and the datasheet of the OKI chip I mapped the chip pin on the control headers.
The most hard part has been understand how to use V5.
I thought to use it, in the same way I used to use V0 on the hd44780, the OKI chip expects a negative power on that pin! I got help on that.
But after that it was a piece of cake.
To control it I used an Arduino board and the following circuit:
The display has 7 lines of 16 characters each.
It also has a quite weird memory mapping. The followings are the first character address for each row:
0x08,0x48,0x88,0xc8,0x18,0x98
and this some code I wrote to drive this display.
LM167511.cpp
LM167511.h
sharp_expi2c.ino
that's all.
Display is branded Sharp model LM167511 and it is controled by the OKI MSM6262 chip.
The other 2 components present on the PCB are column drivers T6A39, not particulary interesting to control it.There's not a lot of documentation about this display provided by Sharp nor anyone else, and googling for its name you can only find an old post of a spanish guy asking if someone knows how to use it.
Using a multimeter and the datasheet of the OKI chip I mapped the chip pin on the control headers.
The most hard part has been understand how to use V5.
I thought to use it, in the same way I used to use V0 on the hd44780, the OKI chip expects a negative power on that pin! I got help on that.
But after that it was a piece of cake.
To control it I used an Arduino board and the following circuit:
The display has 7 lines of 16 characters each.
0x08,0x48,0x88,0xc8,0x18,0x98
and this some code I wrote to drive this display.
LM167511.cpp
LM167511.h
sharp_expi2c.ino
that's all.
Sunday, January 5, 2014
SendFSK
Happy new year!
This is an early release of the new version of app_fsk , in which is finally implemented the SendFSK function. Now there should be all it's needed to send and receive messages between two asterisk using only telephone lines. As early release, I'm sure it's full of bugs, so please notify me any weird behaviour you may notice, I'll do my best to fix it.
Here an example for a test using the two apps on the same machine.
...and here a call file to be used with the previous dialplan.
Channel:local/100@default
Callerid: "FSKer" <0000>
Maxretries:3
Waittime:45
Context: default
Extension: 200
This is an early release of the new version of app_fsk , in which is finally implemented the SendFSK function. Now there should be all it's needed to send and receive messages between two asterisk using only telephone lines. As early release, I'm sure it's full of bugs, so please notify me any weird behaviour you may notice, I'll do my best to fix it.
Here an example for a test using the two apps on the same machine.
[default] |
exten => 100, 1, Noop(Incoming call is just arrived on fsk receive number) exten => 100, n, Answer() exten => 100, n, ReceiveFSK(msg) exten => 100, n, Noop(Message received ${msg}) exten => 100, n, Set(f1=${CUT(msg,#,1)}) exten => 100, n, Set(f2=${CUT(msg,#,2)}) exten => 100, n, Set(f3=${CUT(msg,#,3)}) exten => 100, n, Noop(f1: ${f1}) exten => 100, n, Noop(f2: ${f2}) exten => 100, n, Noop(f3: ${f3}) exten => 100, n, wait(5) exten => 100, n, Hangup() |
exten => 200, 1, Noop(Incoming call is just arrived on fsk send number) exten => 200, n, Progress() exten => 200, n, Wait(1) exten => 200, n, Answer() exten => 200, n, Wait(5) exten => 200, n, SendFSK(Field1#Field2#Field3) exten => 200, n, Wait(5) exten => 200, n, Hangup() |
...and here a call file to be used with the previous dialplan.
Channel:local/100@default
Callerid: "FSKer" <0000>
Maxretries:3
Waittime:45
Context: default
Extension: 200
Subscribe to:
Posts (Atom)