C# C中的Onvif事件订阅#
我正在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类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
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);