Подписка на события Onvif в C#

Я реализую систему управления ipCamera/кодировщиком на С#. Система будет управлять несколькими ip-камерами и/или кодировщиками от разных поставщиков. Использование Onvif вместо каждого ipcamera или encoders sdk будет преимуществом.

Одной из ключевых концепций системы управления является прослушивание событий, таких как события обнаружения движения, с камер. Onvif поддерживает это с помощью ws-basenotification или поддержки типа pull. Мне не нравится pull, поэтому я буду использовать поддержку ws-basenotification в Onvif (Onvif spec 9.1).

Я успешно добавил подписку на Sony SNC-RH164, Bosh VIP X1 XF IVA и Acti TCD2100.

Моя проблема: я не получаю никаких уведомлений ни от одного из устройств. Может ли кто-нибудь увидеть, что я делаю неправильно, или дать мой совет, как получать уведомления с устройств. Мой компьютер находится в той же подсети, что и устройства. И мой брандмауэр отключен для теста.

Мое тестовое консольное приложение, инициирующее класс 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; }
}

Конфиг для NotificationConsumerService

<services>
  <service name="OnvifClassLib.NotificationConsumerService">
    <endpoint address="" binding="customBinding" bindingConfiguration="CustomBasicHttpBinding"
      name="CustomHttpBinding" contract="EventService.NotificationConsumer" />
    <host>
      <baseAddresses>
        <add baseAddress="http://192.168.0.10:8080/NotificationConsumerService" />
      </baseAddresses>
    </host>
  </service>
</services>
<bindings>      
  <customBinding>
    <binding name="CustomBasicHttpBinding">
      <textMessageEncoding messageVersion="Soap12">
        <readerQuotas maxStringContentLength="80000" />
      </textMessageEncoding>
      <httpTransport maxReceivedMessageSize="800000" maxBufferSize="800000" />
    </binding>        
  </customBinding>      
</bindings>

Метод AddDevice

public void AddDevice(OnvifDevice device)
    {
        LoadCapabilities(device);
        OnvifDevices.Add(device);
    }


internal void LoadCapabilities(OnvifDevice onvifDevice)
    {
        if (onvifDevice.OnvifDeviceServiceUri == null)
            return;
        if (onvifDevice.DeviceClient == null)
            LoadDeviceClient(onvifDevice);
        try
        {

            onvifDevice.Capabilities = onvifDevice.DeviceClient.GetCapabilities(new[] { OnvifClassLib.DeviceManagement.CapabilityCategory.All });

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


    }
private void LoadDeviceClient(OnvifDevice onvifDevice)
    {

        if (onvifDevice.OnvifDeviceServiceUri == null)
            return;

        var serviceAddress = new EndpointAddress(onvifDevice.OnvifDeviceServiceUri.ToString());
        var binding = GetBindingFactory(onvifDevice);
        onvifDevice.DeviceClient = new OnvifClassLib.DeviceManagement.DeviceClient(binding, serviceAddress);
        if (!string.IsNullOrWhiteSpace(onvifDevice.UserName))
        {
            onvifDevice.DeviceClient.ClientCredentials.UserName.UserName = onvifDevice.UserName;
            onvifDevice.DeviceClient.ClientCredentials.UserName.Password = onvifDevice.Password;
        }

    }

Метод AddEventSubscription

 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;
        }
    }

Крепления для мыла12

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;

    }

person Frode    schedule 15.05.2013    source источник


Ответы (2)


Я думаю, проблема в том, что ваш потребитель уведомлений использует AddressingVersion.None, а уведомления от устройства ONVIF форматируются в соответствии с WS-Addressing 1.0. Попробуйте изменить следующую строку вашего метода GetCustomBinding:

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

to

messegeElement.MessageVersion = MessageVersion.CreateVersion(
    EnvelopeVersion.Soap12, AddressingVersion.WSAddressing10);
person dawe    schedule 19.05.2014

У меня была эта проблема с камерой GrandStream. Мне пришлось добавить к нему одну или несколько зон обнаружения с помощью веб-интерфейса камеры, чтобы заставить его обнаруживать движение.

person Frank Hagenson    schedule 22.01.2020