I am trying to receive events from an ONVIF device using the Basic Notification Interface (section 9.3 of ONVIF-Core-Specification). In other words, I want to use the Notify API and not the PullPoint.
I am programming in C# with Visual Studio 2022 and have used the Add->Service Reference to generate a C# class for the various ONVIF services, including device.wsdl and event.wsdl (e.g. https://www.onvif.org/ver10/events/wsdl/event.wsdl).
The following code works and subscribes to events with my camera, which then sends the events to <localIP>:8080/subscription-1
as expected.
notificationProducerClient = new onvif10_event.NotificationProducerClient(binding, remoteAddress);
notificationProducerClient.Endpoint.Address = onvifEvent.Endpoint.Address;
var subscribe = new onvif10_event.Subscribe();
string consumerDestAddress = string.Format("http://{0}:8080/subscription-1", localIP);
var clientEndpoint = new onvif10_event.EndpointReferenceType() { Address = new onvif10_event.AttributedURIType() { Value = consumerDestAddress } };
subscribe.ConsumerReference = clientEndpoint;
subscribe.InitialTerminationTime = GetTerminationTime();
var subscribveResponse = notificationProducerClient.Subscribe(subscribe);
// Store the subscription URI for use in Renew
subsribeRenewUri = subscribveResponse.SubscriptionReference.Address.Value;
System.TimeSpan? actualTerminationDuration = subscribveResponse.TerminationTime - subscribveResponse.CurrentTime;
subscriptionTerminationTime = (System.TimeSpan)actualTerminationDuration; // update our original termination time with what the server actually does
renewIntervalMs = (int)(subscriptionTerminationTime.TotalMilliseconds / 2);
subscriptionManagerClient = new onvif10_event.SubscriptionManagerClient(binding, new EndpointAddress(new Uri(subsribeRenewUri)));
subscriptionManagerClient.Open();
However I cannot find which class to use in the auto-generated code from the event.wsdl to receive to receive the events. I have implemented my own HTTP server and I am able to receive the events from my camere.
According to the spec I think it should a NotificationConsumer
class which should receive the events. Such class was auto-generated, but I do not understand from its API how to use it.
Below the code that was auto-generated for this class.
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace="http://docs.oasis-open.org/wsn/bw-2", ConfigurationName="onvif10_event.NotificationConsumer")]
public interface NotificationConsumer {
// CODEGEN: Generating message contract since the operation Notify is neither RPC nor document wrapped.
[System.ServiceModel.OperationContractAttribute(IsOneWay=true, Action="http://docs.oasis-open.org/wsn/bw-2/NotificationConsumer/Notify")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
void Notify(Onvif.Services.onvif10_event.Notify1 request);
[System.ServiceModel.OperationContractAttribute(IsOneWay=true, Action="http://docs.oasis-open.org/wsn/bw-2/NotificationConsumer/Notify")]
System.Threading.Tasks.Task NotifyAsync(Onvif.Services.onvif10_event.Notify1 request);
}
As you can see, it has a Notify() function that returns nothing. So looks to me more like the API a server would use to notify a client.
What am I missing? Is it possible to use the auto-generated code to receive event? Or do I need to implement my own HTTP server to receive the events?