Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

How to send a Contact ID alarm to the Central Station from a C# application over VoIP

0.00/5 (No votes)
2 Jul 2014 1  
In this article I described a solution that can be used to send alarms through your VoIP network to the Central Station in case of fire, burglary or any other emergency event by using your own C#.NET application.

Table of Contents

Introduction to the relationship of VoIP and alarm systems

Voice over Internet Protocol (VoIP) consists of the group of technologies for the delivery of voice communications and multimedia sessions over Internet Protocol (IP) networks, such as the Internet. Because of the bandwidth efficiency and low costs that VoIP technology can provide, businesses are migrating from traditional copper-wire telephone systems to VoIP systems to reduce their monthly communication costs. Concerning to the fact that VoIP can not be used just for voice and video transmission but also for any data transmission, I thought it would be useful to analyze how to use VoIP for sending alarms and notifications to the Central Station from a C# application. It would make your security system more effective in case of emergency.

Background of the problem

Before describing the implementation of my solution, I am going to explain the most important terms you need to know for better understanding.

First of all, let’s take a look at the operation of the traditional alarm systems in a nutshell. You have an alarm system installed and configured in your office or home. This alarm system is connected to the Central Station. In case of emergency (e.g. fire, burglary, theft or any other intrusion) the alarm system sends an alert to the Central Station that will take the appropriate action to avert the emergency.

But using my solution, you (more specifically: your C# application) can behave as an alarm system. That is, you can send out any alarm in case of emergency to the Central Station. Let’s see a drastic example that illustrates how my application can improve your security system: Due to a protracted work, you are sitting in the office late night. Since you are in the building, the alarm system is not activated yet. But in the meantime you experience something unusual and there is a suspicion of emergency. In this case you can use this C# application in order to send out a Contact ID alarm to the Central Station. The following figure illustrates this process:

Figure 1: How to send a Contact ID alarm to the Central Station in C#

Mini glossary:

  • Alarm System: It is a system designed to detect intrusion (unauthorized entry), fire, gas leak, Carbon Monoxide leakage, high or low temperature, system trouble, communication trouble or any other emergency event.
  • Central Station: It refers to a company providing services to monitor burglar, fire and residental alarm systems.
  • Contact ID protocol: It is the most popular protocol that is used to establish communication between the alarm systems and the Central Station.

Implementation of the alarm sender application in C#

Getting started

Before starting the development, let's see what you need for this project. Considering that my application has been written in C#, you need a development environment that supports C# (such as Microsoft Visual Studio). Please do not forget to install .NET Framework on your PC as well. There is also a need for some VoIP components added to your references to be able to implement the VoIP functionality (such as Ozeki VoIP SIP SDK). Since I have used the Ozeki SDK for this project, you need to install this SDK on your PC, too.

  1. For creating a new Console Application, open your Visual Studio, click File > New project. Now select the Visual C# Console Application menu item and provide a name for your project. Finally click OK.
  2. For adding the VoIP components provided by the SDK, right-click on References and select the Add references menu item. Browse and select the VoIPSDK.dll file then click OK.

Code explanation

In order to make the communication possible between the alarm system and the Central Station I used the Contact ID protocol. The essence of the Contact ID procotol is that the receiver side sends a Handshake firstly. When the sender side receives that, it will start to send the message. That is both of the sides need to play the role of the sender and receiver as well. Therefore, in addition to the sender side, it is needed to talk a little about the receiver side as well. This is the reason why both of the sides has been built in one project.

Figure 2 illustrates the communication process using the Contact ID protocol:

Figure 2: The communication process using the Contact ID protocol

As you can see above, the alarm signal is a DTMF signal. However, the DTMF frequencies may be distorted during the communication with the Contact ID protocol, if you do not use a codec applying lossless compression. Therefore, you need to use PCMA or PCMU codecs.

In my project 2 classes have been used: Softphone.cs and Program.cs. Now it’s time to study the implementation of the two classes!

The implementation of the Softphone.cs class

First of all, you need to create a softphone (a software-based telephone that has the same features as an ordinary phone). It is required, because the transmission of the alarm will be carried out through a VoIP call. So the alarm sending will be managed with the help of this softphone. The Softphone.cs class is used to declare, define and initialize a softphone, how to handle the necessary events and how to use its functions. The Softphone.cs will be used to create a new softphone in the Program.cs class.

Code 1 shows that the first step is the addition of some using lines:

using System;
using Ozeki.Media;
using Ozeki.Media.MediaHandlers;
using Ozeki.VoIP;
using Ozeki.VoIP.SDK;

Code 1: Add some using lines

As you can see below, you need to create 3 objects (softphone, phone line and call) from the ISoftphone, IPhoneLine and IPhoneCall interfaces:

ISoftPhone softphone; // softphone object
IPhoneLine phoneLine; // phoneline object
IPhoneCall call; // call object

Code 2: Creating the softphone, phone line and call objects

You also need to initialize the softphone in the constructor using the default parameters. You need to set the port range indicated by the first parameter (minPortRange) and the second parameter (maxPortRange). This is called the port’s interval. It can be seen in Code 3 that it also contains a third parameter: this is the listening port. As you can see, this is 5060 that is the port of the SIP.

softphone = SoftPhoneFactory.CreateSoftPhone(5000, 10000, 5060);

Code 3: Initializing the softphone in the constructor

By subscribing to the IncomingCall event, incoming calls will be monitored continuously (Code 4).

softphone.IncomingCall += softphone_IncomingCall;

Code 4: Subscribing to the IncomingCall event

In order to be able to communicate, you need to register your softphone to a PBX by using the Register() method (Code 5). This method gets all of the values required for the registration as parameters that are used to create a SIP account with the constructor of the SIPAccount class:

  • RegistrationRequired: Is the registration required or not? To be able to receive incoming calls, this field needs to be set to ’true’.
  • DisplayName: A name to be displayed at the called client.
  • UserName: If an other client dials this name (number), this user is getting called.
  • AuthenticationId: An identifier (like a login name) to the PBX.
  • RegisterPassword: The password for registering to the PBX. It works in pair with the authentication ID.
  • DomainHost: A domain name, e.g. an IP address.
  • DomainPort: Port number.

After that the system will be able to create the phone line (CreatePhoneLine() method) by using the account. By subscribing to the PhoneLineStateChanged, you can track the changes of the phone line. When the phone line has been created, you need to register this phone line by calling the RegisterPhoneLine() method.

// Send SIP regitration request
        public void Register(bool registrationRequired, string displayName, string userName, string authenticationId, string registerPassword, string domainHost, int domainPort)
        {
            try
            {
                var account = new SIPAccount(registrationRequired, displayName, userName, authenticationId, registerPassword, domainHost, domainPort);
                Console.WriteLine("\n Creating SIP account {0}", account);

                phoneLine = softphone.CreatePhoneLine(account);
                Console.WriteLine("Phoneline created.");

                phoneLine.PhoneLineStateChanged += phoneLine_PhoneLineStateChanged;

                softphone.RegisterPhoneLine(phoneLine);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error during SIP registration" + ex.ToString());
            }
        }

Code 5: Subscribing to the IncomingCall event

You have already subscribed to get notified if the state of the phone line has been changed. With the phoneLine_PhoneLineStateChanged() method you can set what to do for each state. If the state of the phone line is RegistrationSucceeded, the system will examine whether the call has been started or not. You need to setup the numberToDial (a telephone number to be dialed) and the call object as well. As you can see below, you need to subscribe to the CallStateChanged by calling the call_CallStateChanged() method (Code 6).

void phoneLine_PhoneLineStateChanged(object sender, VoIPEventArgs<PhoneLineState> e)
        {
            Console.WriteLine("Phone line state changed to {0}", e.Item);

            if (e.Item == PhoneLineState.RegistrationSucceeded)
            {
                if (startCall)
                {
                    var numberToDial = "101";
                    call = softphone.CreateCallObject(phoneLine, numberToDial);

                    call.CallStateChanged += call_CallStateChanged;
                    call.Start();
                }
            }

            var handler = PhoneLineStateChanged;
            if (handler != null)
                handler(this, e.Item);
        }

Code 6: Managing the phone line states

If the CallStateChanged event occurs (that is the call state changes), the state of the call will be displayed.

  • If the call state is Answered, you need to create a PhoneCallAudioSender and a PhoneCallAudioReceiver in order to be able to send and receive audio during a call. In order to ensure that both of the sending and receiving works properly, the contactIdHandler object should be connected to the phoneCallAudioSender and phoneCallAudioReceiver objects when the call is established. It can be completed by using the mediaConnector. It ensures that both of the incoming and outgoing communication will be carried out through the contactIdHandler. After that, you need to run the contactIdHandler by calling the Start() method.
  • If the call state is Completed, you need to disconnect the established connections, and stop the contactIdHandler by calling the Stop() method (Code 7).
        void call_CallStateChanged(object sender, VoIPEventArgs<CallState> e)
        {
            Console.WriteLine("call state changed: {0}", e.Item);

            if (e.Item == CallState.Answered)
            {
                phoneCallAudioSender = new PhoneCallAudioSender();
                phoneCallAudioReceiver = new PhoneCallAudioReceiver();

                // attach the phoneCallAudioSender and the phoneCallAudioReceiver to the call
                phoneCallAudioReceiver.AttachToCall(call);
                phoneCallAudioSender.AttachToCall(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
            }
            else if (e.Item == CallState.Completed)
            {
                contactIdHandler.Stop(); // stop the contactIdHandler

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

                phoneCallAudioReceiver.Detach();
                phoneCallAudioSender.Detach();
            }
        }

Code 7: Managing the call states

The following method (Code 8) examines whether is there an incoming call or not. By calling the call_CallStateChanged() method you can subscribe to the events of the CallStateChanged concerning to the incoming calls. The call will be equal to the current call and the call will be accepted automatically. To hang up an existing call use the HangUpCall() method.

void softphone_IncomingCall(object sender, VoIPEventArgs<IPhoneCall> e)
        {
            Console.WriteLine("Incoming call...");
            e.Item.CallStateChanged += call_CallStateChanged;
            call = e.Item;
            call.Accept();
        }

Code 8: Accepting an incoming call

To hang up an existing call use the HangUpCall() method (Code 9).

public void HangUpCall()
        {
            call.HangUp();
        }

Code 9: The HangUpCall() method

The implementation of the Program.cs class

First you need to add some lines in the ’using section’ (Code 10):

using System;
using Ozeki.Media.MediaHandlers;

Code 10: Add some extra using lines

Code 11 demonstrates the Main() method that controls the whole program. As I mentioned above, the alert sending can not be possible without the receiver side. (Note: If you want to try out this Contact ID project, there is a need for launching two copies of that. First you need to start the receiver thereafter the sender one. However, if you have an existing system that has connected to the Central Station, you only need to launch the sender application.)

When you start your console application by launching the exe file and you do not write anything after the ’example.exe’ in the command line, it will be the receiver. If you write there an argument, it will be the sender.

You need to create a ContactIdHandler type object that needs to subscribe to the ContactIdSendFailed, ContactIdSendSuccessful and ReceivedNotification events. The first two events are needed to be able to send the alarm, and the last one is needed for receiving that.

  • The ContactIdSendFailed event means that the sending of the alarm (that is, the contact ID) is failed.
  • The ContactIdSendSuccessful event means that the sending of the alarm has been successful.
static void Main(string[] args)
        {
            ContactIdHandler contactIdHandler = new ContactIdHandler();

            bool send = (args.Length != 0); // sender or receiver
            softphone = new Softphone(contactIdHandler, send);

            if (send) // sender
            {
                contactIdHandler.SendNotification(1506, ContactIdEventQualifier.NewEvent, 110, 1, 22); // send the Contact ID alarm notification
                softphone.Register(registrationRequired, displayName, userName, authenticationId, registerPassword, domainHost, domainPort); // 1000
            }
            else // receiver
            {
                softphone.Register(registrationRequired, displayName, userName, authenticationId, registerPassword, domainHost, domainPort); // 1001
            }

            contactIdHandler.ContactIdSendSuccessful += contactIdHandler_ContactIdSendSuccessfull;
            contactIdHandler.ContactIdSendFailed += contactIdHandler_ContactIdSendFailed;
            contactIdHandler.ReceivedNotification += contactIdHandler_ReceivedNotification;

            Console.ReadLine();
            contactIdHandler.Stop();

            Console.ReadLine();
            softphone.HangUpCall();
        }

Code 11: The Main method

As you can see below, in case of each event the call will be finished and the current event state will be printed (Code 12). (In case of receiving the message itself will be printed.)

static void contactIdHandler_ReceivedNotification(object sender, ContactIdNotificationEventArg e)
        {
            Console.WriteLine(e.ToString());
        }

        static void contactIdHandler_ContactIdSendFailed(object sender, EventArgs e)
        {
            softphone.HangUpCall();
            Console.WriteLine("Failed!");
        }

        static void contactIdHandler_ContactIdSendSuccessfull(object sender, EventArgs e)
        {
            softphone.HangUpCall();
            Console.WriteLine("Success!");
        }

Code 12: Finishing the call and printing the event state

Summary

In this article I demonstrated a unique solution that can be used to send alarms through your VoIP network to the Central Station in case of fire, burglary or any other emergency event by using your own C#.NET application. To make my article more understandable, I started the project by describing the main concept of alarms systems and I introduced the Contact ID protocol that makes the communication possible between the alarm system and the Central Station. After the theoretical background I described the implementation of the Contact ID alarm sender while explaining step by step how to use the necessary VoIP components that you previously added to your references in Microsoft Visual Studio.

My solution can be used for several purposes in the field of security systems. I hope I could give you some useful ideas for improving any system. Good work!

References

[1] Contact ID standards: http://www.technoimport.com.co/Producto/pdfs/ADEMCO%20-%20DC05_Contact_ID.pdf

[2] Security alarm systems: http://en.wikipedia.org/wiki/Security_alarm

[3] Voice over Internet Protocol (VoIP): http://en.wikipedia.org/wiki/VoIP

[4] Microsoft Visual Studio: http://www.microsoft.com/en-us/download/details.aspx?id=40787

[5] Microsoft .NET Framework: http://www.microsoft.com/hu-hu/download/details.aspx?id=30653

[6] Ozeki VoIP SIP SDK: http://voip-sip-sdk.com/p_21-download-ozeki-voip-sip-sdk-voip.html

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here