C# C中的Onvif事件订阅#

C# C中的Onvif事件订阅#,c#,events,onvif,C#,Events,Onvif,我正在C#中实现一个ipCamera/编码器管理系统。该系统将管理来自多个供应商的多个ipCameras和/或编码器。使用Onvif而不是关闭每个ipcamera或编码器sdk将是一个好处 管理系统的关键概念之一是监听来自摄像机的事件,如运动检测事件。Onvif通过使用ws-basenotification或pull类型支持来支持这一点。我不喜欢pull,所以我将在Onvif中使用ws-basenotification支持(Onvif规范9.1) 我已成功添加了对索尼SNC-RH164、波什VI

我正在C#中实现一个ipCamera/编码器管理系统。该系统将管理来自多个供应商的多个ipCameras和/或编码器。使用Onvif而不是关闭每个ipcamera或编码器sdk将是一个好处

管理系统的关键概念之一是监听来自摄像机的事件,如运动检测事件。Onvif通过使用ws-basenotification或pull类型支持来支持这一点。我不喜欢pull,所以我将在Onvif中使用ws-basenotification支持(Onvif规范9.1)

我已成功添加了对索尼SNC-RH164、波什VIP X1 XF IVA和Acti TCD2100的订阅

我的问题是:我没有收到来自任何设备的任何通知。任何人都可以看到我做错了什么,或者给出我的som指针,告诉我如何从设备获取通知。 我的电脑与设备位于同一子网中。我的防火墙也被关闭了

我的测试控制台应用程序启动OnvifManager类

using (var manager = new OnvifManager())
        {
            //manager.ScanForDevices();
            var sonyDevice = new OnvifClassLib.OnvifDevice
            {
                OnvifDeviceServiceUri = new Uri(@"http://192.168.0.101/onvif/device_service"),

            };
            manager.AddDevice(sonyDevice);
            manager.AddEventSubscription(sonyDevice, "PT1H");

            var boshDevice = new OnvifClassLib.OnvifDevice
            {
                OnvifDeviceServiceUri = new Uri(@"http://192.168.0.102/onvif/device_service"),


            };
            manager.AddDevice(boshDevice);
            manager.AddEventSubscription(boshDevice, string.Empty);

            var actiDevice = new OnvifClassLib.OnvifDevice
            {
                OnvifDeviceServiceUri = new Uri(@"http://192.168.0.103/onvif/device_service"),
                UserName = "uid",
                Password = "pwd"

            };
            manager.AddDevice(actiDevice);
            manager.AddEventSubscription(actiDevice);

            Console.WriteLine("Waiting...");
            Console.Read();
        }
我的managerClass将在构造函数中初始化我的NotificationConsumer接口

private void InitializeNotificationConsumerService()
    {
        _notificationConsumerService = new NotificationConsumerService();
        _notificationConsumerService.NewNotification += NotificationConsumerService_OnNewNotification;
        _notificationConsumerServiceHost = new ServiceHost(_notificationConsumerService);
        _notificationConsumerServiceHost.Open();
    }
我的NotificationConsumer接口实现

 /// <summary>
/// The client reciever service for WS-BaseNotification
/// </summary>
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class NotificationConsumerService : NotificationConsumer
{

    public event EventHandler<EventArgs<Notify1>> NewNotification;

    /// <summary>
    /// Notifies the specified request.
    /// </summary>
    /// <param name="request">The request.</param>
    /// <remarks>A </remarks>
    public void Notify(Notify1 request)
    {
        var threadSafeEventHandler = NewNotification;
        if (threadSafeEventHandler != null)
            threadSafeEventHandler.Invoke(this, new EventArgs<Notify1>(request));
    }
}

public class EventArgs<T> : EventArgs
{

    public EventArgs(T data)
    {
        Data = data;
    }

    public T Data { get; set; }
}
加法积分法

 public void AddEventSubscription(OnvifDevice onvifDevice, string initialTerminationTime = "PT2H")
    {
        if (onvifDevice.Capabilities.Events == null)
            throw new ApplicationException("The streamer info does not support event");
        try
        {


            if (onvifDevice.NotificationProducerClient == null)
                LoadNotificationProducerClient(onvifDevice);

            XmlElement[] filterXml = null;


            var subScribe = new Subscribe()
            {
                ConsumerReference = new EndpointReferenceType
                {
                    Address = new AttributedURIType { Value = _notificationConsumerServiceHost.BaseAddresses.First().ToString() },

                }

            };
            if (!string.IsNullOrWhiteSpace(initialTerminationTime))
                subScribe.InitialTerminationTime = initialTerminationTime;


            onvifDevice.SubscribeResponse = onvifDevice.NotificationProducerClient.Subscribe(subScribe);

            Console.WriteLine("Listening on event from {0}", onvifDevice.NotificationProducerClient.Endpoint.Address.Uri.ToString());
        }

        catch (FaultException ex)
        {
            Console.Write(ex.ToString());
        }
        catch (Exception ex)
        {
            Console.Write(ex.ToString());
        }
    }

private void LoadNotificationProducerClient(OnvifDevice onvifDevice)
    {
        var serviceAddress = new EndpointAddress(onvifDevice.Capabilities.Events.XAddr.ToString());
        var binding = GetBindingFactory(onvifDevice);
        onvifDevice.NotificationProducerClient = new OnvifClassLib.EventService.NotificationProducerClient(binding, serviceAddress);
        if (!string.IsNullOrWhiteSpace(onvifDevice.UserName))
        {
            onvifDevice.NotificationProducerClient.ClientCredentials.UserName.UserName = onvifDevice.UserName;
            onvifDevice.NotificationProducerClient.ClientCredentials.UserName.Password = onvifDevice.Password;
        }
    }
Soap12的绑定

private Binding GetBindingFactory(OnvifDevice onvifDevice)
    {            
        return GetCustomBinding(onvifDevice);
    }
private Binding GetCustomBinding(OnvifDevice onvifDevice)
    {
        HttpTransportBindingElement transportElement = new HttpTransportBindingElement();

        if (!string.IsNullOrWhiteSpace(onvifDevice.UserName))
            transportElement.AuthenticationScheme = AuthenticationSchemes.Basic;


        var messegeElement = new TextMessageEncodingBindingElement();
        messegeElement.MessageVersion = MessageVersion.CreateVersion(EnvelopeVersion.Soap12, AddressingVersion.None);

        var binding = new CustomBinding(messegeElement, transportElement);
        binding.SendTimeout = new TimeSpan(0, 10, 0);
        return binding;

    }

我认为问题在于,您的通知使用者使用了
AddressingVersion.None
,而来自ONVIF设备的通知是根据WS-Addressing 1.0格式化的。尝试更改GetCustomBinding方法的以下行:

messegeElement.MessageVersion = MessageVersion.CreateVersion(
    EnvelopeVersion.Soap12, AddressingVersion.None);


我的GrandStream相机有这个问题。我必须使用camera web UI向其添加一个或多个检测区域,以使其检测运动

private Binding GetBindingFactory(OnvifDevice onvifDevice)
    {            
        return GetCustomBinding(onvifDevice);
    }
private Binding GetCustomBinding(OnvifDevice onvifDevice)
    {
        HttpTransportBindingElement transportElement = new HttpTransportBindingElement();

        if (!string.IsNullOrWhiteSpace(onvifDevice.UserName))
            transportElement.AuthenticationScheme = AuthenticationSchemes.Basic;


        var messegeElement = new TextMessageEncodingBindingElement();
        messegeElement.MessageVersion = MessageVersion.CreateVersion(EnvelopeVersion.Soap12, AddressingVersion.None);

        var binding = new CustomBinding(messegeElement, transportElement);
        binding.SendTimeout = new TimeSpan(0, 10, 0);
        return binding;

    }
messegeElement.MessageVersion = MessageVersion.CreateVersion(
    EnvelopeVersion.Soap12, AddressingVersion.None);
messegeElement.MessageVersion = MessageVersion.CreateVersion(
    EnvelopeVersion.Soap12, AddressingVersion.WSAddressing10);