Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reliably identifying and tracking Asterisk calls using C# and Aster.NET

I have been building a WinForms desktop application using C# that interfaces with Asterisk using Aster.NET (formerly/forked from Asterisk.NET). We're having real trouble reliably identifying and tracking calls that are related to an individual extension/user.

The problem we're having is due to the unpredictable/fuzzy nature of the events fired/triggered by Asterisk, with them being massively variable depending on how the call is routed before it hits an extension.

For example, the event sequence/format is different when: a call hits an IVR before getting blind transferred; if a call hits an IVR before it is attended transferred; if a call goes direct to the user's extension.

This is further hampered by the way that Asterisk tracks each side of the call using a different Unique ID (e.g. the incoming side of the call has a different UID than the received side of the call). Whilst we've managed to account for that in the (subsequently ugly!) code, we're still hitting issues with accounting for the different routing paths the call can take.

As such, I'm looking for any advice on how we can do the following:

  1. Reliably identify an incoming call to a user's extension
    • We need to be able to identify the extension being called and the originating caller ID (after either a blind or attended transfer and direct call from external)
    • Reliably track the Unique ID for that incoming call as it's used to link to the call recording
  2. Reliably identify an outgoing call from a user's extension
    • With the same caveats as above in mind

As it stands at the minute we have an extremely complex chain of event handlers that operate differently dependent on the 'current state' of the app.

To give one example: if we detect a NewStateEvent with a ChannelState of 6 ('Up'), we check if there is an ongoing call in process and that the UIDs match, and if so then the current call has been answered. If the UIDs don't match, but other factors do (e.g. channel, connectedlinenum, etc), then we pick this up as being the 'other side' of the call (i.e. the receiving or incoming side).

I'm not sure if the problem lies with the API or with AMI - but whichever it is it's causing us some real headaches.

Any advice greatly appreciated.

like image 297
iam Avatar asked Jan 30 '14 14:01

iam


2 Answers

Is it possible for you to update to Asterisk 12? The channel names in AMI are now stable in Asterisk 12.

https://wiki.asterisk.org/wiki/display/AST/AMI+v2+Specification

like image 65
sruffell Avatar answered Nov 09 '22 15:11

sruffell


i'm using package Aster.NET in c# . firstly install latest package of aster.net
than check that code .this code work perfect for me .

        manager = new ManagerConnection(address, port, user, password);
        manager.UnhandledEvent += new ManagerEventHandler(manager_Events);
        manager.NewState += new NewStateEventHandler(Monitoring_NewState);
        try
        {
            // Uncomment next 2 line comments to Disable timeout (debug mode)
            // manager.DefaultResponseTimeout = 0;
            // manager.DefaultEventTimeout = 0;


            manager.Login();

            if (manager.IsConnected())
            {



                Console.WriteLine("user name  : " + manager.Username);






                Console.ReadLine();

            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error connect\n" + ex.Message);
            manager.Logoff();
            Console.ReadLine();

        }
        void manager_Events(object sender, ManagerEvent e)
        {
            Console.WriteLine("Event : " + e.GetType().Name);

        }

           void Monitoring_NewState(object sender, NewStateEvent e)
              {
            string state = e.State;
            string callerID = e.CallerId;

            Console.WriteLine("caller  num ...", e.CallerIdNum);

            //Console.WriteLine("state =", state);

            //Console.WriteLine("callerID =", callerID);



            if ((state == "Ringing") | (e.ChannelState == "5"))
            {

                Console.WriteLine("hello rining your phone now ...");

                String connectedLineNum;
                String connectedLineName;

                Dictionary<String, String> attributes = e.Attributes;

                attributes.TryGetValue("connectedlinenum", out connectedLineNum);
                attributes.TryGetValue("connectedlinename", out connectedLineName);
                // "callerID" - called phone number
                // "connectedLineNum" - calling phone number



                // CallIn. Incoming call
            }
            else if ((state == "Ring") | (e.ChannelState == "4"))
            {

                Console.WriteLine("hello out going your call ...");
                // CallOut. Outcoming call
            }
            else if ((state == "Up") | (e.ChannelState == "6"))
            {
                String connectedLineNum;
                String connectedLineName;


                Dictionary<String, String> attributes = e.Attributes;

                attributes.TryGetValue("connectedlinenum", out connectedLineNum);
                attributes.TryGetValue("connectedlinename", out connectedLineName);
                // "callerID" - called phone number
                // "connectedLineNum" - calling phone number

                // human lifted up the phone right no

                Console.WriteLine("human lifted up the phone...");



            }

        }
like image 22
Aamir Hussain Avatar answered Nov 09 '22 15:11

Aamir Hussain