How to receive a Contact ID alert in C#


This guide explains how to receive a Contact ID alert notification using Ozeki VoIP SIP SDK. This way, you can be notified in case of any alarm that allows you to monitor your whole alarm system. After reading through the following guide, you will find out how to use your own C# application for this purpose.

To use this example, you need to have an Ozeki VoIP SIP SDK installed, and a reference to ozeki.dll should be added to your visual studio project. It is also recommended to visit the How to register to a SIP PBX and How to accept incoming call with Ozeki VoIP SIP SDK using C#? articles before studying this functionality.

What is the Contact ID? When is it needed?

The Ademco Contact ID protocol is the most popular protocol that is used for communication between the alarm systems and the Central Station. If you would like to implement any alarm functionality, you will need to use this protocol.

You can find a detailed guide about this protocol at the Contact ID protocol page. You can also check its official documentation that can be found at the Contact ID standards page. It describes how this protocol works.

The communication process is shown below:

Figure 1 - The communication process of Contact ID protocol

Figure 2 illustrates the participants of the communication. The alarm systems can be connected to some kind of ATA devices (e.g. Linksys SPA3102). By using this device the Contact ID alarm message can be sent through the VoIP network for the dialed telephone number, if the receiver side is ready to accept the Contact ID (that is, the use of the protocol). The following example program allows you to receive these alerts.

Figure 2 - The participants of receiving a Contact ID alert in C#

How to implement a Contact ID alarm receiver using C#?

During the communication with the Contact ID protocol, the DTMF frequencies may be distorted if you do not use a codec applying lossless compression. So you need to use PCMA or PCMU codecs. This setting can be seen in lines 28-32.

To implement the receiver side it is required to be able to accept a call. In connection with this task, you can find more information at the Accept incoming call page. In addition, you need a ContactIdHandler type object as well that needs to be signed up to the ReceivedNotification event. When this event occurs, it means that a Contact ID alarm is received.

This example program will print the received DTMF Contact ID sequence according to their function: account number, message type, event qualifier, event code, partition number, zone number. (The ToString() method at line 60 performs this.)

In order to ensure that the receiver works properly, the contactIdHandler object should be connected to the phoneCallAudioSender and phoneCallAudioReceiver objects when the call is established. This ensures that both of the incoming and outgoing communication will be carried out through the contactIdHandler. After that, you need to run the contactIdHandler, so you need to call the Start() method.

When the call is finished, you need to disconnect the established connections, and stop the contactIdHandler by calling the Stop() method.

A Contact ID alarm receiver example in C#

using System;
using Ozeki.Media;
using Ozeki.VoIP;

namespace ContactIdReceiver
    class Program
        static ISoftPhone softphone;  // softphone object
        static IPhoneLine phoneLine;  // phoneline object
        static IPhoneCall call;  // call object

        static PhoneCallAudioSender phoneCallAudioSender;
        static PhoneCallAudioReceiver phoneCallAudioReceiver;

        static MediaConnector mediaConnector;
        static ContactIdHandler contactIdHandler; // Contact ID Handler object

        private static void Main(string[] args)
            // Create a softphone object with RTP port range 5000-10000
            softphone = SoftPhoneFactory.CreateSoftPhone(5000, 10000);

            foreach (var s in softphone.Codecs)
            softphone.EnableCodec(8); //only PCMA codec enabled

            // SIP account registration data, (supplied by your VoIP service provider)
            var registrationRequired = true;
            var userName = "sipusername"; //1001
            var displayName = "sipdisplayname"; //1001
            var authenticationId = "authenticationid"; //1001
            var registerPassword = "Password"; //1001
            var domainHost = "";
            var domainPort = 5060;
            var account = new SIPAccount(registrationRequired, displayName, userName, authenticationId, registerPassword, domainHost, domainPort);

            // Send SIP regitration request

            mediaConnector = new MediaConnector();
            phoneCallAudioSender = new PhoneCallAudioSender();
            phoneCallAudioReceiver = new PhoneCallAudioReceiver();
            contactIdHandler = new ContactIdHandler();

            contactIdHandler.ReceivedNotification += contactIdHandler_ReceivedNotification;

            // prevents the termination of the application

        private static void contactIdHandler_ReceivedNotification(object sender, ContactIdNotificationEventArg e)

        static void RegisterAccount(SIPAccount account)
                phoneLine = softphone.CreatePhoneLine(account);
                softphone.IncomingCall += softphone_IncomingCall;   // subscribing to the event to get notified about incoming calls
                phoneLine.RegistrationStateChanged += sipAccount_RegStateChanged;
            catch (Exception ex)
                Console.WriteLine("Error during SIP registration: " + ex);

        private static void sipAccount_RegStateChanged(object sender, RegistrationStateChangedArgs e)
            if (e.State == RegState.Error || e.State == RegState.NotRegistered)
                Console.WriteLine("Registration failed!");

            if (e.State == RegState.RegistrationSucceeded)
                Console.WriteLine("Registration succeeded - Online!");

        private static void softphone_IncomingCall(object sender, VoIPEventArgs<IPhoneCall> e)
            call = e.Item;  // initializes the call
            call.CallStateChanged += call_CallStateChanged; // subscribes to the event to get notified about the call's states
            call.Answer();  // accepts the call (sends back the 200 OK SIP message)

        static void call_CallStateChanged(object sender, CallStateChangedArgs e)
            Console.WriteLine("Call state: {0}.", e.State);

            if (e.State == CallState.Answered)
                SetupDevices(); // set up the devices by calling the proper method

            if (e.State == CallState.Completed)
                StopDevices(); // detach and disconnect the devices by calling the proper method

        static void SetupDevices()
            // attach the phoneCallAudioSender and the phoneCallAudioReceiver to the call

            mediaConnector.Connect(contactIdHandler, phoneCallAudioSender); // connect the contactIdHandler to the phoneCallAudioSender object
            mediaConnector.Connect(phoneCallAudioReceiver, contactIdHandler); // connect the phoneCallAudioReceiver to the contactIdHandler object

            contactIdHandler.Start(); // start the contactIdHandler

        static void StopDevices()

            mediaConnector.Disconnect(contactIdHandler, phoneCallAudioSender);
            mediaConnector.Disconnect(phoneCallAudioReceiver, contactIdHandler);

            contactIdHandler.Stop(); // stop the contactIdHandler

Training guides, simple examples

If you would like to visit the detailed developer documentations, you can learn much more from the Ozeki VoIP SIP SDK Training chapter.

If you have any questions or need assistance, please contact us at

Related Pages