Я реализую систему управления 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;
}