Page 1 of 1

Monitoring Agent Screens

PostPosted: Tue May 04, 2010 11:13 am
by iratik
For the latest version of vicidial 2.2.0-53. We needed the ability to monitor agent screens . All our phones are SIP and we have vnc servers (UltraVNC) installed on all stations. We have them set to watch only with minimal disruption to agents. We have the web interfaces for these stations setup listening on port 5800. When you connect to that port a java applet is launched and the agent's screen in displayed.

We modified ASTtimeon_VDADall.php to include this ability alongside listen/barge.

We had to give the user "wwwrun" access to /var/run/asterisk.ctl with chmod a+rw /var/run/asterisk.ctl

In the script on the current line for the main table, we strip the channel info from the extension. Query asterisk for the IP of that phone registration and pass the IP to be used in a link to port 5800 on the IP.

Code: Select all
                if ($non_latin < 1)
                        {
                        $extension = eregi_replace('Local/',"",$Aextension[$i]);
                        $extension =            sprintf("%-14s", $extension);
                        while(strlen($extension)>14) {$extension = substr("$extension", 0, -1);}
                        }
                else   
                        {
                        $extension = eregi_replace('Local/',"",$Aextension[$i]);
                        $extension =            sprintf("%-48s", $extension);
                        while(mb_strlen($extension, 'utf-8')>14) {$extension = mb_substr("$extension", 0, -1,'utf8');}
                        }

                //screen monitoring patch for sip extensions {
                $exten=preg_replace("/[^0-9]/","",$extension);
                $ip=shell_exec("asterisk -rx 'sip show peer $exten' | grep 'Addr->IP' | awk '{print $3}'");
                $extension="<a target='_blank' href='http://$ip:5800'>$extension</a>";
                //}

                $phone =                        sprintf("%-12s", $phone_split[0]);
                $custphone =            sprintf("%-11s", $custphone);



It would be great to include some functionality like this in the default installation along with the existing LISTEN/BARGE abilities.

PostPosted: Tue May 04, 2010 1:45 pm
by gardo
This is great. Can you document everything on how to set this up? Something like a HOWTO based on the existing Vicidial documents. We'll try to have this integrated on the next major release of VicidialNOW. It will also be great if you can post this on the Vicidial tracker. Matt might be able to have this available for everyone. 8)

PostPosted: Tue May 04, 2010 3:41 pm
by mflorell
Isn't the default standard VNC port 5900? I guess we would have to make that configurable if this is added.

For all contributed code additions you will need to post to the Issue Tracker with your patch file against current SVN code.

Monitoring Agent Screens

PostPosted: Tue May 04, 2010 5:43 pm
by iratik
Mantis seems to only let me attach one file at a time. I have 2 files at this point. The modifications to the code above increase the rendering time of that page by n*(time it takes to make the shell_exec call to asterisk) where n is the number of agents being rendered. Also, it would be nice to have screen view capability from the user status and user stats screen as well. Because of this , I created a file "user_vnc_gateway.php" to which is passed the phone extension. The new user_vnc_gateway.php + the patch file for AST_timeonVDADall.php make 2 files.

Here is the code for user_vnc_gateway.php
Code: Select all
if (!isset($_GET["exten"])) die ("No extension provided");
/**
*  resolve_registration_ip
*       @param  string  $extension      A valid SIP phone identifier e.g. SIP/6203
*       @return string                  Returns an IP address for the registration of the phone
*       
*/
function resolve_registration_ip($extension) {
        $extension=preg_replace("/[^0-9]/","",$extension); //Just need the #s / Protects against command injection
        $ip=trim(shell_exec("asterisk -rx 'sip show peer $extension' | grep 'Addr->IP' | awk '{print $3}'"));
        if ($ip=="")
                throw new Exception("Could not find registration info for $extension");
        return $ip;
}
function resolve_registration_ip_test() { //throws no exceptions if test passes
        $ip="";
        $ip=resolve_registration_ip("SIP/512"); //the test extension will vary from system to system
        if (!preg_match("/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/",$ip))
                throw new Exception("Resolve registration result did not match ip");
}       

$ip=resolve_registration_ip($_GET["exten"]);
header("Location: http://$ip:5800");
?>


The code providing functionality in AST_timeonVDADall.php now reads
Code: Select all
       if (preg_match("/^SIP/",$extension)) {
          $extension="<a target='_blank' href='user_vnc_link.php?exten=".$extension."'>$extension</a>";
       }


Since the page no longer makes system call for every user, the rendering time is returned to normal. Links are only displayed for SIP extensions, and the functionality can be ported easily to other parts of the system simply by passing the phone extension to user_vnc_link.php?exten= .

PostPosted: Thu May 06, 2010 5:20 am
by Trying
This will be an excellent feature.

Chmod would need to be run for asterisk.ctl daily

PostPosted: Thu May 06, 2010 9:13 am
by iratik
Everytime asterisk starts, we would need to change the permissions for asterisk.ctl. Though, I have a php / asterisk AMI lib that I use which I could add in that would prevent the need to mess with permissions on asterisk.ctl. We could also use the lib in other areas to streamline communication with asterisk with PHP. Thoughts?

PostPosted: Thu May 06, 2010 6:15 pm
by mflorell
We already do communication with AMI through perl on Asterisk startup. I would rather avoid requiring PHP on the dialers if it is not necessary.

PostPosted: Fri May 07, 2010 10:11 am
by iratik
Agree. I'm definitely a proponent of not adding in any extra libs unless they are absolutely necessary. Can you point me to a script in the existing source that uses AMI so I can use the same functionality?

PostPosted: Fri May 07, 2010 10:42 am
by mflorell
There are several scripts that use AMI, AST_update.pl would be a good place to start.

PostPosted: Fri May 07, 2010 4:25 pm
by iratik
It appears there is no AMI library being used in the system. AST_update contains code to use the AMI protocol to interface with asterisk's manager interface using perl's telnet library. I'm at odds with this, to not introduce any extra source files into the system I would have to use the same approach. Directly interface with AMI using telnet. There are many setup / tear down and message formatting routines for ami usage through telnet scripted into AST_update. If I simply used the same code, we would have code in two places that does the exact same thing. If code in one area updates, we would have to update it in the other area. The right thing to do seems to be to abstract the AMI functionality into a lib and use it anywhere astguiclient needs to access AMI functionality. I'm guessing this hasn't been done because there is only one place AMI functionality has been used, so DRY principles would not have needed to have been enforced. Then again, you use originate commands through AMI in the timeonVDADall screen. Looking into the source, the script triggers the agent api via ajax call which inserts a record into some sort of mysql based AMI command queue. Seems that AST_manager_send.pl reads this queue and reformats the request to be passed to AST_send_action_child. AST_send_action_child then reimplements the same setup/teardown code in AST_update to send commands to AMI.

Code: Select all
    $telnet_port = '5038' if (!$telnet_port);

        ### connect to asterisk manager through telnet
        my $tn = new Net::Telnet (Port => $telnet_port,
                Prompt => '/.*[\$%#>] $/',
                Output_record_separator => '',
                Errmode    => "return");
        #$fh = $tn->dump_log("$PATHlogs/SAC_telnet_log.txt");  # uncomment for telnet log
        my $telnet_login;
        if ($ASTmgrUSERNAMEsend) {
                $telnet_login = $ASTmgrUSERNAMEsend;
        } else {
                $telnet_login = $ASTmgrUSERNAME;
        }
        $tn->open($telnet_host);
        $tn->waitfor('/[01]\n$/'); # print login
        $tn->print("Action: Login\nUsername: $telnet_login\nSecret: $ASTmgrSECRET\n\n");
        $tn->waitfor('/Authentication accepted/'); # waitfor auth accepted

        $tn->buffer_empty;


Its not that much setup / teardown. Its just odd that so many scripts are talking to each other with no capability to return results the opposite direction. I do understand how systems grow, and I can see how that might have happened as vicidial developed.

The lib I use for AMI actually uses asterisk's http interface, though it may not provide some of the level of queueing and dispatch logging control that the existing system provides, it does provide 2 way communication with AMI. This will allow the IP for the extension/phone/station to be retrieved in just 3-4 lines.

Code: Select all
<?php
                require 'asterisk_ajam.php';
                $a=new AsteriskAJAM();
                $response=$a->SendCommand(array(
                        'action'=>'sipshowpeer',
                        'peer'=>"512"
                ));

?>


I'm fine with either approach or one you suggest. Direct Telnet, AJAM lib, or cron job to change permissions on asterisk.ctl ? (Remember the whole reason we need one of these options is to fetch the IP of a station based on its sip registration data). Maybe we could just implement a cron job to dump sip registration data into the database and run it on cron. Another possibility outside of the box is to just log the IP the user logged in from. The sip registration method would fail if the agent were not using a softphone. If we use the IP they logged into the web interface with, we can bypass all the asterisk sip show peer stuff and just add a routine to log the IP then grab it from the DB when we need it. Thoughts?

PostPosted: Fri May 07, 2010 4:52 pm
by mflorell
http://astguiclient.sourceforge.net/acqs.html

And we actually already have the IP of the computer the agent is coming from in the phones table when the agent logs in. This is the computer_ip field.

PostPosted: Fri May 07, 2010 5:15 pm
by iratik
That being said. As long as the agent is not using a desk-based phone and the ip of the sip registration is the ip of the screen to be monitored. This would be the code for user_vnc_link.php
Code: Select all
<?php
if (!isset($_GET["exten"])) die ("No extension provided");
/**
* user_vnc_link
* Redirects the user to Ultravnc's HTTP server running on the extension's ip
* Throws an unhandled exception if the extension ip cannot be found
* $_GET["exten"]  the sip extension of the user
*/
/**
*  resolve_registration_ip.
*       @param  string  $extension      A valid SIP phone identifier e.g. SIP/6203
*       @return string                  Returns an IP address for the registration of the phone
*
*/
function resolve_registration_ip($extension) {
        require 'dbconnect.php';
        $extension=preg_replace("/[^0-9]/","",$extension); //Just need the #s / Protects against command injection
        $stmt="SELECT computer_ip ";
        $stmt.=" FROM phones ";
        $stmt.=" WHERE extension='$extension' ";

        $rslt=mysql_query($stmt,$link);

        if (mysql_num_rows($rslt)) {
                $row=mysql_fetch_row($rslt);
                $ip=$row[0];
                if (!empty($ip)) return $ip;
        }
        throw new Exception("Could not find registration info for $extension");
}
function resolve_registration_ip_test() { //throws no exceptions if test passes
        $ip="";
        $ip=resolve_registration_ip("SIP/512"); //the test extension will vary from system to system
        if (!preg_match("/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/",$ip))
                throw new Exception("Resolve registration result did not match ip");
}
$ip=resolve_registration_ip($_GET["exten"]);
header("Location: http://$ip:5800");
?>


PostPosted: Fri May 07, 2010 5:27 pm
by mflorell
The computer_ip comes from the IP address of the computer that is on the web interface, so even if they are using a desk phone it is not a problem.

PostPosted: Tue May 25, 2010 7:46 am
by omarrodriguezt
Nice feature :)

PostPosted: Wed May 26, 2010 1:32 pm
by omarrodriguezt
Could be great also if we can have the recordings of the agent's screens too, like the voice recordings.
There are some clients that required this feature.
NICE JOB!!!!

PostPosted: Wed May 26, 2010 7:35 pm
by mflorell
There is a lot more that needs to go into screen recordings than there is voice. For voice you can do it without loading anything on the agent workstation, not so for screen recording. Then there is all of the space that screen recording takes up on the archive server. The only people that are doing it that we work with are using Oreka, which works great for this task we have heard.

PostPosted: Thu May 27, 2010 8:36 am
by omarrodriguezt
Thnak you Matt.
So Eureka support video recording too?

I was reading, but I was not able to find the video recording feature.

http://oreka.sourceforge.net/

Thank you again.

PostPosted: Thu May 27, 2010 11:15 am
by mflorell
I believe the screen recording feature might be part of their proprietary featureset.

PostPosted: Thu May 27, 2010 12:53 pm
by Trying

PostPosted: Thu May 27, 2010 2:22 pm
by omarrodriguezt
Indeed.
Thank you

PostPosted: Thu May 27, 2010 2:29 pm
by Trying
This will still be an awesome feature.