Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - moa

Pages: [1] 2
1
QueueMetrics installation / Re: Agent Priority
« on: November 28, 2011, 21:10:41 »
We use leastrecent in our asterisk environment. It handles agent priorities and rings the agent who's been idle the longest.

2
Running QueueMetrics / Re: FreePBX(AsteriskNow) transfer
« on: November 19, 2010, 20:04:57 »
This sounds a bit like Frankenstein Jr. :-) but.... chapeau!

Does this mean that my forum member status can change from "Newbie" to "Frankenstein Jr." ?

3
Running QueueMetrics / Re: FreePBX(AsteriskNow) transfer
« on: November 19, 2010, 18:16:59 »
This sounds a bit like Frankenstein Jr. :-) but.... chapeau!

It's what I do best :)

Do you mind if we add this to the Advanced Configuration manual? with proper credits, of course! :)

I don't mind at all.  I'm just glad that I got it all working  ;D ;D

4
Running QueueMetrics / Re: FreePBX(AsteriskNow) transfer
« on: November 16, 2010, 19:36:49 »
 ;D

It can be done!

Since it is close to impossible to find any decent information on this.  I'm going to explain how I solved it here.
*Warning* This may be a lengthy post, so to keep it short I've taken out anything that doesn't pertain to this issue in my dialplan. Also, all dialplan will be in AEL syntax.

First off, in order to successfully accomplish this we need a few channel variables that aren't in the new transferred channel.  We need the AgentID, the asterisk Call ID, and our Queue the call is coming from.

In my setup, when a call comes in, I'm setting two inherent channel variable:
Code: [Select]
context queues-inbound{
XXXX =>{
Set(_CALLID=${UNIQUEID});
Set(_QUEUENAME=test);
Queue(test,t);
}
}

Now my agents are logged into the queues via local channels:
Code: [Select]
queues*CLI> queue show test
test has 0 calls (max unlimited) in 'leastrecent' strategy (3s holdtime, 96s talktime), W:0, C:12, A:4, SL:100.0% within 120s
   Members:
      local/1234@agents/n with penalty 1 (realtime) (Not in use) has taken no calls yet

When the agent is dialed another inherent variable is set:
Code: [Select]
context agents {
_. => {
Set(_AGENTTHATTRANSFERED=${EXTEN});
...
// doing a mysql database lookup to get Agents SIP Extension
...
Dial(SIP/${AGENT_EXTENSION});
}
}

Hope everyone is following thus far. Just a few more steps  ;)

Here is what the queue_log looks like at this point:

Code: [Select]
+---------+------------+------------------+-----------+-------------------+---------------+------------------------------+
| id      | time       | callid           | queuename | agent             | event         | data                         |
+---------+------------+------------------+-----------+-------------------+---------------+------------------------------+
| 1194627 | 1289929044 | 1289929028.30773 | test      | NONE              | ENTERQUEUE    | |XXXXXXXXXX_1289929028.30773 |
| 1194629 | 1289929048 | 1289929028.30773 | test      | local/1234@agents/n| CONNECT       | 4|1289929045.30777|3       |


I've instructed our agents to use a specific line extension when transferring.  For this example, I'm going to use line 6.

Code: [Select]
context agents-transferred {
_6. => {
NoOp("Current UniqueID: ${UNIQUEID}");
NoOp("inherited callid: ${CALLID}");
NoOp("inherited agendid: ${AGENTTHATTRANSFERED}");
NoOp("inherited queuename: ${QUEUENAME}");
MYSQL(Connect connid localhost UN PW asterisk_database);
if(${connid} = ""){
Playback(tt-error);
Hangup();
}else{
// make the query to track it
MYSQL(Query resultid ${connid} INSERT into transferred_calls(callid,full_extension) values('${CALLID}','${EXTEN}'));
// disconnect
MYSQL(Disconnect ${connid});
// now enter in our queue log
QueueLog(${QUEUENAME},${CALLID},local/${AGENTTHATTRANSFERED}@agents/n,TRANSFER,${EXTEN:1});
// dial the transferred extesion
Dial(SIP/${EXTEN:1});
};
if(${connid}){
MYSQL(Disconnect ${connid});
};
Hangup();
};
}

Now once the call gets to here.  Here is what the queue_log looks like (agent transferred to sip extension 299):
Code: [Select]
+---------+------------+------------------+-----------+-------------------+---------------+------------------------------+
| id      | time       | callid           | queuename | agent             | event         | data                         |
+---------+------------+------------------+-----------+-------------------+---------------+------------------------------+
| 1194627 | 1289929044 | 1289929028.30773 | test      | NONE              | ENTERQUEUE    | |XXXXXXXXXX_1289929028.30773 |
| 1194629 | 1289929048 | 1289929028.30773 | test      | local/1234@agents/n| CONNECT       | 4|1289929045.30777|3       |
| 1194642 | 1289929161 | 1289929028.30773 | test      | local/1234@agents/n | TRANSFER      | 299                     |


QueueMetrics is happy at this point.  Transferred calls are calculated correctly. 

But wait
Here's what the queue_log looks like AFTER the transferred call is completed:

Code: [Select]
+---------+------------+------------------+-----------+-------------------+---------------+------------------------------+
| id      | time       | callid           | queuename | agent             | event         | data                         |
+---------+------------+------------------+-----------+-------------------+---------------+------------------------------+
| 1194627 | 1289929044 | 1289929028.30773 | test      | NONE              | ENTERQUEUE    | |XXXXXXXXXX_1289929028.30773 |
| 1194629 | 1289929048 | 1289929028.30773 | test      | local/1234@agents/n| CONNECT       | 4|1289929045.30777|3       |
| 1194642 | 1289929161 | 1289929028.30773 | test      | local/1234@agents/n | TRANSFER      | 299                     |
| 1194650 | 1289929253 | 1289929028.30773 | test      | local/1234@agents/n | COMPLETEAGENT | 5|204|1                      |

QueueMetrics doesn't like this because of the last entry(COMPLETEAGENT).  So if you see above where I created my own database table called transferred_calls and placed the transfer information into it(agents-transferred context).  I have a cronjob running every 5 minutes to check this table for anything new, if there is a new transferred call.  It grabs the callid and deletes the offending row out of the queue_log.

QueueMetrics is happy, boss is happy, customers are happy!

This is currently working in my lab and I'm about to push it all into production.

Please comment and let me know what everyone thinks.  Suggestions, bug fixes, and typo's are all welcome.

5
Running QueueMetrics / Re: FreePBX(AsteriskNow) transfer
« on: November 15, 2010, 23:21:28 »
Is there any way to force or fake a TRANSFER record?

Since QueueMetrics didn't answer me. ;)  I'm going to write up some dialplan and test this very thing.  I'll let everyone know of my findings.


6
Running QueueMetrics / Re: FreePBX(AsteriskNow) transfer
« on: November 11, 2010, 21:11:40 »
I'm using dynamic agents, so my queue member association comes out of mysql.  Here's what the table looks like (Sorry I'm not sure how to do it statically in agents.conf):

Code: [Select]

mysql> describe queue_member_table;
+-----------------+------------------+------+-----+---------+----------------+
| Field           | Type             | Null | Key | Default | Extra          |
+-----------------+------------------+------+-----+---------+----------------+
| uniqueid        | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| membername      | varchar(40)      | YES  |     | NULL    |                |
| queue_name      | varchar(128)     | YES  | MUL | NULL    |                |
| interface       | varchar(128)     | YES  |     | NULL    |                |
| penalty         | int(11)          | YES  |     | NULL    |                |
| paused          | int(11)          | YES  |     | NULL    |                |
| state_interface | varchar(128)     | YES  |     | NULL    |                |
+-----------------+------------------+------+-----+---------+----------------+
7 rows in set (0.01 sec)

When an agent logs in, I'm putting a row like this into the table:
Code: [Select]
+----------+--------------------+------------+--------------------+---------+--------+-----------------+
| uniqueid | membername         | queue_name | interface          | penalty | paused | state_interface |
+----------+--------------------+------------+--------------------+---------+--------+-----------------+
|   223008 | Agent/106         | TEST        | local/106@agents/n |       1 |   NULL | SIP/157         |
+----------+--------------------+------------+--------------------+---------+--------+-----------------+

My @agents context does a database lookup to find what sip extension agent 106 is sitting at and dials their phone.

By adding the state interface it tells asterisk to check the state of the sip extension rather than looking at the local channel for agent availability.  This solved my "In Use" issue after the agent transferred a call.

What I've found out about the TRANSFER event not showing up in the queue_log is that since I'm using local channels, asterisk doesn't complete the queue_log entry for the call until the transferred call is completed.

For example:
Caller comes into QueueA : ENTERQUEUE is put in the queue_log
QueueA rings Agent/106 : CONNECT is put in the queue_log
Agent/106 transfers to Agent/107 : Nothing is put in the queue_log, asterisk changes state of Agent/106 from "In use" to "Available"
Agent/107 completes call with Caller : COMPLETEDBYAGENT(Agent/106) is entered in queue_log.

This all seems like an asterisk bug to me (or maybe a feature??).

One solution I've come up with but not implemented is creating my own transfer dialplan.  A dialplan where I inserted the needed TRANSFER event into the queue_log. If I do this though, asterisk will still place into the database it's COMPLETEDBYAGENT row with the same callid.  
How would Queuemetrics handle that? ??? ???

I was hoping I could get some answers on this,  we are currently billing one of our customers per minute. Long untracked transferred call times is causing their bill to go through the roof.  Good for us, not so god for them..

7
Running QueueMetrics / Re: FreePBX(AsteriskNow) transfer
« on: November 10, 2010, 23:30:16 »
No, a TRANSFER record never shows up in the queue_log.  It did prior to use extension state but stopped once I enabled it.

AFAIK the extension state was created in 1.6 and they back ported it to 1.4.

I attempted a upgrade to 1.8 a few days ago and IMHO it didn't seem very stable.  I was going to wait until a few minor revisions are released to clear up some of the release bugs.

8
QueueMetrics installation / Re: QM 1.6 and realtime queue_log
« on: November 10, 2010, 18:30:54 »
I'm sure you have, but it's always good to check: After altering the database table, did you do a module reload within the asterisk CLI?  From my experience, it seems asterisk does some sort of cacheing of the database column types and layouts.

Here is the describe on my queue_log:
Code: [Select]
mysql> describe queue_log;
+-----------+------------------+------+-----+---------+----------------+
| Field     | Type             | Null | Key | Default | Extra          |
+-----------+------------------+------+-----+---------+----------------+
| id        | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| time      | char(10)         | YES  |     | NULL    |                |
| callid    | varchar(32)      | NO   |     |         |                |
| queuename | varchar(32)      | NO   |     |         |                |
| agent     | varchar(32)      | NO   |     |         |                |
| event     | varchar(32)      | NO   |     |         |                |
| data      | varchar(255)     | NO   |     |         |                |
+-----------+------------------+------+-----+---------+----------------+
7 rows in set (0.00 sec)

And here are my relevant config file entries:
Code: [Select]
res_mysql.conf:
[general]
dbhost=127.0.0.1
dbname=ast_db
dbuser=asterisk
dbpass=XXXXXX
dbport=3306
sock=/var/run/mysqld/mysqld.sock

extconfig.conf:
[settings]
queue_log => mysql,general,queue_log


The main difference I have noticed here is that my column type is "char" not "varchar".  I'm no database expert but if asterisk is picky about column types this could cause it to fail.

I hope this helps!

9
Running QueueMetrics / Re: FreePBX(AsteriskNow) transfer
« on: November 10, 2010, 17:45:14 »
How interesting, I came in here to ask a similar question. Today must be the day to work on transfer issues.  ;D

I've been running asterisk 1.6(source) for quite some time and techs haven't been able to transfer until I added the stateextension column into the database(I'm using REALTIME for queue_members) and changed a few things in the GUI our agents use to login.  This solved my issue with agents channels being "In Use" after the transfer. Now my problem is the queue stats continue to grow until the transferred call is hung up.  Has anyone ran into this issue and know how to solve it?


P.S. Sorry for hijacking this thread.  Since these issues seem very closely related, I'm hoping someone can provide us both with a little insight on asterisk 1.6 and transfers.

10
So having a removemember show up after the agentlogoff has been faked wont affect any stats?

We don't have any agents that will be logged in for the full realtime visibility window. However, there is a possibility that they will be associated with queues according to QM and the asterisk queue_log. Due to the way asterisk handles it's queue log with realtime agents.

11
I'm in the process of upgrading and completely reworking our phone network.  In the process I've ran into a small problem that I need some more input on.  I apologize for the long winded post but more information is better, right?

Here's the setup to help everyone understand:
Asterisk 1.6, logging the queue log directly to mysql.
QM 1.6.0.1 setup to watch the asterisk mysql queue_log rather than qloaderd.
In house built web front end for agents to login/logout and add/remove themselves from queues.

It is my understanding that by using asterisk realtime, you eliminate the need for agents to login and logout.  You only need to add/remove queue members via mysql.  With asterisk queue members setup to use the realtime engine the queues are parsed only when needed (i.e., call comes into queue).  If there have been any changes to the queue members since the last time it was parsed, that is when the sql queue_log is written.  I was thinking to get the correct payroll information, queue availability stats, and current agent extension, I could add a fake AGENTCALLBACKLOGIN row in asterisk mysql table.

I've got all of this up and running in my test environment and I would like some clarification on how QM would handle the following situation:

>Agent logs in (fake agentcallbacklogin row)
>Agent becomes member of 5 queues (added into queue member mysql table)
>Agent takes calls on all 5 queues (placing the queueaddmember line in asterisk queue_log)
>Agent removes himself as member of 5 queues(removed from mysql table)
>Agent logs out (fake agentcallbacklogin row)
>Queues stay dormant for several hours before receiving calls parsing the queue member table and updating the queue_log

So now there is a queue remove member after the agent has already logged out and gone home for the day.


We have roughly 50 queues, and the activity ranges from several thousand calls a day to one or two a week.  There is a high possibility that an agent will stay a member of the queue over night until he comes back the next day.  How would a situation like this affect the QM stats?


Hopes this makes sense!

12
Scripting QueueMetrics / Re: Wallboard Example script
« on: October 30, 2008, 18:39:28 »
Really man, why not contribute the script to the sourceforge project? :)


No one has contributed this yet?  I'll contribute it once I figure out this last problem.  Here's the issue:

We have queueA and queueB, splitting those up is easy.  But when you have a supervisor that is logged into both queues.  And he/she is on a call on queueA, he is showing up available on the queueB page.  I'm assuming that this has to do with QM and how it displays the users on the realtime stats page.  Any suggestions ?

13
Scripting QueueMetrics / Re: Wallboard Example script
« on: October 27, 2008, 22:40:02 »
Well, guess I should try a few things before I post.  Here's a quick and dirty way:

Code: [Select]
function getAgentLoggedIn( $blockname, $blocks ) {
    $agent = array();
    $block = $blocks[$blockname];
     for ( $r = 1; $r < sizeof( $block ) ; $r++ ) {
      //$queues = $block[$r][4];
      if($block[$r][4])
      {
       $agent[$block[$r][1]]['name'] = $block[$r][1];
       $agent[$block[$r][1]]['lastlogin'] = $block[$r][3];
       $agent[$block[$r][1]]['queues'] = $block[$r][4];
       $agent[$block[$r][1]]['extension'] = $block[$r][5];
       $agent[$block[$r][1]]['onpause'] = $block[$r][6];
       $agent[$block[$r][1]]['srv'] = $block[$r][7];
       $agent[$block[$r][1]]['lastcall'] = $block[$r][8];
       $agent[$block[$r][1]]['onqueue'] = $block[$r][9];
       $agent[$block[$r][1]]['caller'] = '----------';
       $agent[$block[$r][1]]['entered'] = null;
       $agent[$block[$r][1]]['waiting'] = null;
       $agent[$block[$r][1]]['duration'] = null;
       }
      }
    return $agent;
}


14
Scripting QueueMetrics / Re: Wallboard Example script
« on: October 27, 2008, 22:18:44 »
 ???

Quick question, has anyone figured out how to make the function getAgentLoggedIn(); only return the agents that are logged into the requested queues ?  I've got four different wallboards, one for each department.  Only problem is it shows every person that is logged into the phones, it doesn't matter if they are associated with the department queues or not.

15
Scripting QueueMetrics / Re: Wallboard Example script
« on: September 24, 2008, 17:32:06 »
RTCallsBeingProc is working just fine after the upgrade from 1.4.2 to 1.4.7 last night.  I did have to do Bevorts change with the "all selected" case.  Here's the code for RTCallsBeingProc:
Here's the call to it:
Code: [Select]
$agentStatus = getCurrentCalls( "RealtimeDO.RTCallsBeingProc", $blocks_rt, $agent );
And here is getCurrentCalls
Code: [Select]
function getCurrentCalls( $blockname, $blocks, $agent ) {
    global $agent;
    $block = $blocks[$blockname];
     for ( $r = 1; $r < sizeof( $block ) ; $r++ ) {
       $agent[$block[$r][6]]['caller'] = $block[$r][2];
       $agent[$block[$r][6]]['entered'] = $block[$r][3];
       $agent[$block[$r][6]]['waiting'] = $block[$r][4];
       $agent[$block[$r][6]]['duration'] = $block[$r][5];
       $agent[$block[$r][6]]['queue'] = $block[$r][1];
      }
      $agentStatus = '';
      $rowcount=1;
      for  ( $r = 0; $r < sizeof( $agent ) ; $r++ ) {
        $agent = array_values($agent);
        if ($rowcount == 1){
          $rowcolor = "lightgray";
          $rowcount++;
        } elseif ($rowcount == 2) {
          $rowcolor = "white";
          $rowcount = 1;
        }
        if ($agent[$r]['duration'] != '') {
          $status =  $agent[$r]['entered'] . " Call " . " (" . $agent[$r]['duration'] . ")";
          $bgcolor3 = $rowcolor;
          $fontcolor3 = "maroon";
          $blinkon = '';
          $blinkoff = '';
        }
        elseif ($agent[$r]['onpause'] != '-') {
          $pauseTime=substr_replace($agent[$r]['onpause'],"",5);
          $pauseWhat=substr_replace($agent[$r]['onpause'],"",0,6);
          $pauseDuration = time() - strtotime($pauseTime);
          if($pauseWhat == "Break" && sec2hms($pauseDuration) > "0:10:00"){
          $status = $agent[$r]['onpause'] . " (". sec2hms($pauseDuration) .")";
          $bgcolor3 = $rowcolor;
            $fontcolor3 = "red";
            $blinkon = '<blink>';
            $blinkoff = '</blink>';
          }elseif($pauseWhat == "Lunch" && sec2hms($pauseDuration) >= "0:60:00"){
          $status = $agent[$r]['onpause'] . " (". sec2hms($pauseDuration) .")";
          $bgcolor3 = $rowcolor;
            $fontcolor3 = "red";
            $blinkon = '<blink>';
            $blinkoff = '</blink>';
          }elseif($pauseWhat == "ACW" && sec2hms($pauseDuration) >= "0:01:00"){
          $status = $agent[$r]['onpause'] . " (". sec2hms($pauseDuration) .")";
          $bgcolor3 = $rowcolor;
            $fontcolor3 = "red";
            $blinkon = '<blink>';
            $blinkoff = '</blink>';
          }elseif($pauseWhat == "Meeting" && sec2hms($pauseDuration) >= "0:60:00"){
          $status = $agent[$r]['onpause'] . " (". sec2hms($pauseDuration) .")";
          $bgcolor3 = $rowcolor;
            $fontcolor3 = "blue";
            $blinkon = '';
            $blinkoff = '';
          }elseif($pauseWhat == "Extra Duties" && sec2hms($pauseDuration) >= "0:10:00"){
          $status = $agent[$r]['onpause'] . " (". sec2hms($pauseDuration) .")";
          $bgcolor3 = $rowcolor;
            $fontcolor3 = "red";
            $blinkon = '<blink>';
            $blinkoff = '</blink>';
          }
          else{
          $status = $agent[$r]['onpause'] . " (". sec2hms($pauseDuration) .")";
          $bgcolor3 = $rowcolor;
          $fontcolor3 = "blue";
          $blinkon = '';
          $blinkoff = '';
        }
        }
       
       
         else {
          $status = "Available";
          $bgcolor3 = $rowcolor;
          $fontcolor3 = "black";
          $blinkon = '';
          $blinkoff = '';
        }
            $agentStatus .="<tr bgcolor=\"" . $rowcolor . "\" style=\"color:black; font-size: 30px;\"><td>&nbsp;</td><td style=\"color:" . $fontcolor3 . ";\" bgcolor=\"" . $bgcolor3 . "\" >".$blinkon."" . $agent[$r]['name'] . "".$blinkoff."</td><td style=\"color:" . $fontcolor3 . ";\" bgcolor=\"" . $bgcolor3 . "\" >".$blinkon."" . $status .  "".$blinkoff."</td><td>" . $agent[$r]['queue'] . "</td><td>" . substr_replace($agent[$r]['caller'],"",10) . "</td></tr>";
     
      }
     
    return $agentStatus;
}



Most of it is the original code from Barry.  You might notice I added extra stuff to handle the techs on pause.  It makes the text start blinking if they take to long of a break.  I hope this helps.

Pages: [1] 2