65.9K
CodeProject 正在变化。 阅读更多。
Home

如何通过 VoIP 将 Contact ID 警报从 C# 应用程序发送到中央站

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.92/5 (7投票s)

2014年6月18日

CPOL

10分钟阅读

viewsIcon

57440

downloadIcon

913

在本文中,我描述了一种解决方案,该解决方案可以通过您自己的 C#.NET 应用程序,利用 VoIP 网络将火灾、盗窃或任何其他紧急事件的警报发送到中央站。

目录

VoIP 与报警系统关系的介绍

网络电话(VoIP)包括通过互联网协议(IP)网络(如互联网)传输语音通信和多媒体会话的技术组。由于 VoIP 技术可以提供带宽效率和低成本,企业正在从传统的铜线电话系统迁移到 VoIP 系统以降低月通信成本。考虑到 VoIP 不仅可用于语音和视频传输,还可以用于任何数据传输,我认为分析如何使用 VoIP 将警报和通知从 C# 应用程序发送到中央站会很有用。这将在紧急情况下使您的安全系统更加有效。

问题背景

在描述我的解决方案的实现之前,我将解释您需要了解的最重要的术语,以便更好地理解。

首先,让我们简要了解一下传统报警系统的运行方式。您需要在办公室或家中安装和配置报警系统。该报警系统连接到中央站。在紧急情况下(例如火灾、盗窃、偷窃或任何其他入侵),报警系统会向中央站发送警报,中央站将采取适当措施来避免紧急情况。

但是,使用我的解决方案,您可以(更具体地说:您的 C# 应用程序)充当报警系统。也就是说,您可以在紧急情况下向中央站发送任何警报。让我们看一个极端的例子来说明我的应用程序如何改进您的安全系统:由于长时间工作,您深夜仍在办公室。由于您身处大楼内,报警系统尚未激活。但与此同时,您遇到了一些不寻常的情况,并怀疑发生了紧急情况。在这种情况下,您可以使用此 C# 应用程序向中央站发送 Contact ID 警报。**下图**说明了这一过程。

图 1:如何在 C# 中将 Contact ID 警报发送到中央站

迷你词汇表

  • 报警系统:一种用于检测入侵(未经授权的进入)、火灾、燃气泄漏、一氧化碳泄漏、高温或低温、系统故障、通信故障或任何其他紧急事件的系统。
  • 中央站:指一家提供监控盗窃、火灾和住宅报警系统的服务公司。
  • Contact ID 协议:这是最流行的用于建立报警系统和中央站之间通信的协议。

C# 中报警发送应用程序的实现

入门

在开始开发之前,让我们看看这个项目需要什么。考虑到我的应用程序是用 C# 编写的,您需要一个支持 C# 的开发环境(例如 Microsoft Visual Studio)。请不要忘记在您的 PC 上安装 .NET Framework。还需要一些 VoIP 组件添加到您的引用中,以便能够实现 VoIP 功能(例如 Ozeki VoIP SIP SDK)。由于我在此项目中使用 Ozeki SDK,因此您也需要将此 SDK 安装在您的 PC 上。

  1. 要创建新的控制台应用程序,请打开您的 Visual Studio,然后单击“文件”>“新建项目”。现在选择“Visual C# 控制台应用程序”菜单项并为您的项目命名。最后单击“确定”。
  2. 要添加 SDK 提供的 VoIP 组件,请右键单击“引用”并选择“添加引用”菜单项。浏览并选择 VoIPSDK.dll 文件,然后单击“确定”。

代码解释

为了使报警系统和中央站之间的通信成为可能,我使用了 Contact ID 协议。Contact ID 协议的本质是接收方首先发送握手。当发送方收到握手后,它将开始发送消息。因此,双方都需要扮演发送方和接收方的角色。因此,除了发送方之外,还需要稍微谈谈接收方。这就是为什么双方都构建在一个项目中的原因。

图 2 说明了使用 Contact ID 协议的通信过程。

图 2:使用 Contact ID 协议的通信过程

如上所示,报警信号是 DTMF 信号。但是,如果使用不应用无损压缩的编解码器,DTMF 频率在与 Contact ID 协议通信过程中可能会失真。因此,您需要使用 PCMA 或 PCMU 编解码器。

在我的项目中使用了 2 个类:Softphone.csProgram.cs。现在是时候研究这两个类的实现了!

Softphone.cs 类的实现

首先,您需要创建一个软电话(一种具有普通电话相同功能的软件电话)。这是必需的,因为警报的传输将通过 VoIP 呼叫进行。因此,报警发送将通过此软电话进行管理。Softphone.cs 类用于声明、定义和初始化软电话、如何处理必要的事件以及如何使用其函数。Softphone.cs 将在 Program.cs 类中用于创建新的软电话。

代码 1 显示第一步是添加一些 using 语句。

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

代码 1:添加一些 using 语句

正如您在下面看到的,您需要从 ISoftphoneIPhoneLineIPhoneCall 接口创建 3 个对象(软电话、电话线和呼叫)。

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

代码 2:创建软电话、电话线和呼叫对象

您还需要在构造函数中使用默认参数初始化软电话。您需要设置由第一个参数(minPortRange)和第二个参数(maxPortRange)指示的端口范围。这称为端口间隔。在代码 3 中可以看到,它还包含第三个参数:这是监听端口。如您所见,这是 SIP 的端口 5060。

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

代码 3:在构造函数中初始化软电话

通过订阅 IncomingCall 事件,将持续监控来电(代码 4)。

softphone.IncomingCall += softphone_IncomingCall;

代码 4:订阅 IncomingCall 事件

为了能够通信,您需要使用 Register() 方法将您的软电话注册到 PBX(代码 5)。此方法将构造函数的 SIPAccount 类的构造函数所需的、用于创建 SIP 帐户的所有值作为参数。

  • RegistrationRequired:是否需要注册?要接收来电,需要将此字段设置为“true”。
  • DisplayName:要在呼叫的客户端上显示的名字。
  • UserName:如果其他客户端拨打此姓名(号码),则呼叫此用户。
  • AuthenticationId:PBX 的标识符(如登录名)。
  • RegisterPassword:注册 PBX 的密码。它与身份验证 ID 配对。
  • DomainHost:域名,例如 IP 地址。
  • DomainPort:端口号。

之后,系统将能够使用该帐户创建电话线(CreatePhoneLine() 方法)。通过订阅 PhoneLineStateChanged,您可以跟踪电话线状态的变化。创建电话线后,您需要通过调用 RegisterPhoneLine() 方法来注册此电话线。

// 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());
            }
        }

代码 5:订阅 IncomingCall 事件

您已经订阅了以在电话线状态更改时收到通知。通过 phoneLine_PhoneLineStateChanged() 方法,您可以设置每种状态要执行的操作。如果电话线状态为 RegistrationSucceeded,系统将检查呼叫是否已开始。您需要设置 numberToDial (要拨打的电话号码)以及呼叫对象。如下所示,您需要通过调用 call_CallStateChanged() 方法来订阅 CallStateChanged 代码 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);
        }

代码 6:管理电话线状态

如果发生 CallStateChanged 事件(即呼叫状态发生变化),则会显示呼叫状态。

  • 如果呼叫状态为 Answered,您需要创建 PhoneCallAudioSender PhoneCallAudioReceiver 以便在呼叫期间能够发送和接收音频。为确保发送和接收都能正常工作,在建立呼叫时,应将 contactIdHandler 对象连接到 phoneCallAudioSender phoneCallAudioReceiver 对象。这可以通过使用 mediaConnector 来完成。它确保入站和出站通信都通过 contactIdHandler 进行。之后,您需要通过调用 Start() 方法来运行 contactIdHandler
  • 如果呼叫状态为 Completed,您需要断开已建立的连接,并调用 Stop() 方法停止 contactIdHandler 代码 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();
            }
        }

代码 7:管理呼叫状态

以下方法(代码 8)检查是否有来电。通过调用 call_CallStateChanged() 方法,您可以订阅有关来电的 CallStateChanged 事件。呼叫将等于当前呼叫,并且呼叫将自动接通。要挂断现有呼叫,请使用 HangUpCall() 方法。

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

代码 8:接听来电

要挂断现有呼叫,请使用 HangUpCall() 方法(代码 9)。

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

代码 9:HangUpCall() 方法

Program.cs 类的实现

首先,您需要添加一些行在“using 部分”(代码 10)。

using System;
using Ozeki.Media.MediaHandlers;

代码 10:添加一些额外的 using 语句

代码 11 展示了控制整个程序的 Main() 方法。如上所述,没有接收方,警报发送是不可能实现的。(注意:如果您想尝试此 Contact ID 项目,需要运行两个副本。首先需要启动接收方,然后启动发送方。但是,如果您有已连接到中央站的现有系统,则只需要启动发送方应用程序。)

当您通过启动 exe 文件启动控制台应用程序,并且在 'example.exe' 之后没有在命令行中输入任何内容时,它将是接收方。如果您在那里输入了一个参数,它将是发送方。

您需要创建一个 ContactIdHandler 类型的对象,该对象需要订阅 ContactIdSendFailedContactIdSendSuccessful ReceivedNotification 事件。前两个事件是发送警报所必需的,最后一个事件是接收警报所必需的。

  • ContactIdSendFailed 事件表示警报(即 Contact ID)的发送失败。
  • ContactIdSendSuccessful 事件表示警报的发送已成功。
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();
        }

代码 11:Main 方法

如下所示,在每个事件发生时,呼叫将结束,并打印当前的事件状态(代码 12)。(在收到消息的情况下,将打印消息本身。)

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!");
        }

代码 12:结束呼叫并打印事件状态

摘要

在本文中,我展示了一种独特的解决方案,该解决方案可以通过您自己的 C#.NET 应用程序,利用 VoIP 网络将火灾、盗窃或任何其他紧急事件的警报发送到中央站。为了使我的文章更容易理解,我在项目开始时描述了报警系统的主要概念,并介绍了使报警系统和中央站之间通信成为可能的 Contact ID 协议。在理论背景之后,我描述了 Contact ID 警报发送器的实现,同时逐步解释了如何使用您之前在 Microsoft Visual Studio 中添加到引用的必要 VoIP 组件。

我的解决方案可用于安全系统领域的多种用途。我希望我能为您改进任何系统提供一些有用的想法。干得好!

参考文献

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

[2] 安全报警系统:http://en.wikipedia.org/wiki/Security_alarm

[3] 网络电话(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

© . All rights reserved.