I'm developing an application that needs to receive motion events from AXIS cameras.
I've downloaded version 1.8.5495 from the Synesis website, and was able to compile and use the provided ui applications; my cameras show up, and I do see motion events in the ui.
Actually using the library in my own source is another story entirely. I'm having a devil of a time figuring out what part of the code is from the library itself, and what part is ui-specific.
Here's my first problem. I'm trying to setup a session subscription like this (strongly inspired from your own "DeviceViewModel.cs"), but neither of my lambdas ever gets invoked. Can you provide me with any hints?
Dan.
NvtSessionFactory _sessionFactory = new NvtSessionFactory(null);
First of all, thanks for your help. I wish I could skype you, but it's not allowed here at work.
I looked at the synchronous version of Subscribe, and it does seem to work, but I am then unable to setup a subscription, since I don't understand the parameters Subscribe() takes, and can't find a sample for
Dan.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
maybe it suitable for You to use e-mail andrey.vrana@gmail.com.
But anyway, we can continue here.
var Account = new System.Net.NetworkCredential(devconf.accountName, devconf.accountPassword);
NvtSessionFactory factory = new NvtSessionFactory(Account);
var ProfileTokens = invtSession .GetProfiles().RunSynchronously();
var profile = invtSession .GetProfile(ProfileTokens).RunSynchronously(); //ProfileTokens == token of one of device profiles.
StreamSetup strSetup = new StreamSetup();
strSetup.Stream = StreamType.RTPUnicast;
strSetup.Transport = new Transport();
strSetup.Transport.Protocol = TransportProtocol.UDP; //as an example of using UDP
strSetup.Transport.Tunnel = null;
var strUri = invtSession.GetStreamUri(strSetup, profile ).RunSynchronously();
at the end You will have th rtsp uri for video stream.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I used the code to get the stream from an onvif-compliant IP camera but I could not. When I try to build, I get the error:
"Microsoft.FSharp.Control.FSharpAsync<onvif.services.Profile[]>' does not contain a definition for 'RunSynchronously' and no extension method 'RunSynchronously' accepting a first argument of type Microsoft.FSharp.Control.FSharpAsync<onvif.services.Profile[]>' could be found (are you missing a using directive or an assembly reference?)"
var ProfileTokens = invtSession .GetProfiles().RunSynchronously();
Could you please help me in this? More specifically, how can I get the stream from an IP camera and show in a screen?
Thanks in advance.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi, there are the following methods for receiving events:
/// <summary>Returns observable which can be used to retrieve events via PullPoint mechanism.</summary>
member this.GetPullPointEvents():IObservable<OnvifEvent>
/// <summary>Returns observable which can be used to retrieve events via PullPoint mechanism.</summary>
/// <param name="topicExpressionFilters">Describe subset of filters, which notification producer should use to filter events.</param>
/// <param name="messageContentFilters">Describe subset of filters, which notification producer should use to filter events.</param>
member this.GetPullPointEvents(topicExpressionFilters:seq<TopicExpressionFilter>, messageContentFilters:seq<MessageContentFilter>):IObservable<OnvifEvent>
/// <summary>Returns observable which can be used to retrieve events via PullPoint mechanism.</summary>
/// <param name="filters">Describe set of filters, which notification producer should use to filter events.</param>
member this.GetPullPointEvents(filters:seq<XElement>):IObservable<OnvifEvent>
/// <summary>Returns observable which can be used to retrieve events via PullPoint mechanism.</summary>
/// <param name="filter">
/// Describe set of filters, which notification producer should use to filter events.
/// If null the pullpoint should notify all occurring events to the client.
/// </param>
member this.GetPullPointEvents(filter:FilterType):IObservable<OnvifEvent>
/// <summary>Returns observable which can be used to retrieve events via BaseNotification mechanism.</summary>
/// <param name="port">Number of tcp port, that will be used to listen for events from subscribtion manager</param>
member this.GetBaseEvents(port:int):IObservable<OnvifEvent>
/// <summary>Returns observable which can be used to retrieve events via BaseNotification mechanism.</summary>
/// <param name="port">Number of tcp port, that will be used to listen for events from subscribtion manager</param>
/// <param name="topicExpressionFilters">Describe subset of filters, which notification producer should use to filter events. </param>
/// <param name="messageContentFilters">Describe subset of filters, which notification producer should use to filter events. </param>
member this.GetBaseEvents(port:int, topicExpressionFilters:seq<TopicExpressionFilter>, messageContentFilters:seq<MessageContentFilter>):IObservable<OnvifEvent>
/// <summary>Returns observable which can be used to retrieve events via BaseNotification mechanism.</summary>
/// <param name="port">Number of tcp port, that will be used to listen for events from subscribtion manager</param>
/// <param name="filters">Describe set of filters, which notification producer should use to filter events. </param>
member this.GetBaseEvents(port:int, filters:seq<XElement>):IObservable<OnvifEvent>
/// <summary>Returns observable which can be used to retrieve events via BaseNotification mechanism.</summary>
/// <param name="port">Number of tcp port, that will be used to listen for events from subscribtion manager</param>
/// <param name="filter">
/// Describe set of filters, which notification producer should use to filter events.
/// If null the notification producer should notify all occurring events to the client.
/// </param>
member this.GetBaseEvents(port:int, filter:FilterType):IObservable<OnvifEvent>
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I thought I had solved all my problems, but now that I'm moving the code to the production environment, motion events are not detected. Both computers are on the same network, running the same code; the firewall is disabled on both.
Any thoughts?
Dan.
Here's my code:
public void Scan()
{
Status = CameraStatus.Ok;
int listenPort = 8085;
int.TryParse(EventListeningPort, out listenPort);
OdmSession facade = new OdmSession(_sessionFactory.CreateSession(CamUri));
Console.WriteLine(string.Format("Camera {0} Subscribing on port {1}…", Name, listenPort));
Here's the output when testing on my test computer:
Starting scan for camera "camera1 (Opened)"
Camera camera1 (Opened) Subscribing on port 8085…
Subscription done…
Received ONVIF event
Name is state value is 0
Received ONVIF event
Name is motion value is 1
Motion detected on camera camera1 (Opened) (IP 192.168.192.90)
Received ONVIF event
Name is motion value is 1
Motion detected on camera camera1 (Opened) (IP 192.168.192.90)
Received ONVIF event
Name is motion value is 0
Received ONVIF event
Name is motion value is 0
And the same output on my production machine
Starting scan for camera "camera1 (Opened)"
Camera camera1 (Opened) Subscribing on port 8085…
Subscription done…
Received ONVIF event
Name is state value is 0
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Here some my suggestions how to find what went wrong. First we need to ensure that all libraries is compatible, they all have to be same version, except System.Reactive, behaviour can be unstable if it is not. After we need to be convinced that subscription is not disposed before we expected, if it is hard to do that by analysing your code, wireshark can help us, we will see unsubscribe request when subscription is disposed. Also we need to check that subscription is rooted, and will not be collected by GC, wireshark can help us here too, in case if subscription working well we should see periodically renew requests from client to nvt's subsription manager, with interval about 60sec. In case if it's not or incoming requests from nvt to client (port 8085) are refused or aborted we can assert that subscription was closed. Hope this will be helpful for you. If not, so kindly provide us additional details to investigate this issue more precisely (wireshark logs or simplified but integral example that reproduce this issue, so we can run it and debug by ourself).
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Also here is some aspects, that you should take into account when using onvif libraries.
Add following settings into your app.config file:
<system.net><settings><!-- follow reccomendation RFC 2616, section 19.3 "Tolerant Applications". allow to work with devices that separate headers only with LF. --><httpWebRequestuseUnsafeHeaderParsing="true"/></settings><connectionManagement><!-- set maximum number of simultaneous http connections per uri, default is 3. for normal work of onvif session it should be at least 10 --><addaddress ="*"maxconnection ="100"/></connectionManagement><authenticationModules><!-- add support for utf encoded username and password contained non-ASCII chars for http basic authentication --><removetype="System.Net.BasicClient"/><addtype="utils.UtfBasicAuthenticationModule, utils.common"/></authenticationModules></system.net>
I'm developing an application that needs to receive motion events from AXIS cameras.
I've downloaded version 1.8.5495 from the Synesis website, and was able to compile and use the provided ui applications; my cameras show up, and I do see motion events in the ui.
Actually using the library in my own source is another story entirely. I'm having a devil of a time figuring out what part of the code is from the library itself, and what part is ui-specific.
Here's my first problem. I'm trying to setup a session subscription like this (strongly inspired from your own "DeviceViewModel.cs"), but neither of my lambdas ever gets invoked. Can you provide me with any hints?
Dan.
NvtSessionFactory _sessionFactory = new NvtSessionFactory(null);
Uri camUri = new Uri { CamUri };
_sessionFactory.CreateSession(camUri)
.ObserveOnCurrentDispatcher()
.Subscribe(isession =>
{
System.Diagnostics.Trace.WriteLine(isession.deviceUri.ToString());
}, err =>
{
dbg.Error(err);
});
Hi.
First of all - please update your sources from the sourceforge - the latest available version is "1.8.5726"
There are two possible ways to create session
One-assync (if you are using several Uris.) And sincronouse - if you are using the only one uri.
the syncronuse way is:
NvtSessionFactory factory = new NvtSessionFactory (Account); / / Is you want to use anonynous you need to call NvtSessionFactory (null);
invtSession = factory.CreateSession (uri);
this will create session in any case if it is possible to connect to device.
By the way, You can connect to me by skype, to improve the speed of communication (skype: andreyvrana)
Regards,
Andrey Vrana
Hello Andrey.
First of all, thanks for your help. I wish I could skype you, but it's not allowed here at work.
I looked at the synchronous version of Subscribe, and it does seem to work, but I am then unable to setup a subscription, since I don't understand the parameters Subscribe() takes, and can't find a sample for
Dan.
Ok, I think I 've got it.
This is what I ended up with. Does it make sense to you?
INvtSession session = _sessionFactory.CreateSession(CamUri);
_facade = new OdmSession(session);
if (EventSubscriptions != null && !EventSubscriptions.IsDisposed)
{
EventSubscriptions.Dispose();
EventSubscriptions = new CompositeDisposable();
}
List<MessageContentFilter> contArray = new List<MessageContentFilter>();
List<TopicExpressionFilter> topArray = new List<TopicExpressionFilter>();
EventSubscriptions.Add(
_facade.GetBaseEvents(8085, topArray, contArray).Subscribe(
onvifEvent =>
{
foreach (var item in onvifEvent.message.Data.SimpleItem)
{
OnEvent(item.Name, item.Value);
}
}, err =>
{
}
));
Dan.
Ok, Dan.
maybe it suitable for You to use e-mail andrey.vrana@gmail.com.
But anyway, we can continue here.
var Account = new System.Net.NetworkCredential(devconf.accountName, devconf.accountPassword);
NvtSessionFactory factory = new NvtSessionFactory(Account);
Uri uri = new Uri(devUriString); //devUriString == "http://192.168.0.1/onvif/device_service" as an example
invtSession = factory.CreateSession(uri);
here an example how to get stream uri:
var ProfileTokens = invtSession .GetProfiles().RunSynchronously();
var profile = invtSession .GetProfile(ProfileTokens).RunSynchronously(); //ProfileTokens == token of one of device profiles.
StreamSetup strSetup = new StreamSetup();
strSetup.Stream = StreamType.RTPUnicast;
strSetup.Transport = new Transport();
strSetup.Transport.Protocol = TransportProtocol.UDP; //as an example of using UDP
strSetup.Transport.Tunnel = null;
var strUri = invtSession.GetStreamUri(strSetup, profile ).RunSynchronously();
at the end You will have th rtsp uri for video stream.
Dear Mr. Andrey
I used the code to get the stream from an onvif-compliant IP camera but I could not. When I try to build, I get the error:
"Microsoft.FSharp.Control.FSharpAsync<onvif.services.Profile[]>' does not contain a definition for 'RunSynchronously' and no extension method 'RunSynchronously' accepting a first argument of type Microsoft.FSharp.Control.FSharpAsync<onvif.services.Profile[]>' could be found (are you missing a using directive or an assembly reference?)"
var ProfileTokens = invtSession .GetProfiles().RunSynchronously();
Could you please help me in this? More specifically, how can I get the stream from an IP camera and show in a screen?
Thanks in advance.
It would be convenient if you have determined what specific scenario you are interested in.
Then I could give an example how to use our library.
Hi, there are the following methods for receiving events:
/// <summary>Returns observable which can be used to retrieve events via PullPoint mechanism.</summary>
member this.GetPullPointEvents():IObservable<OnvifEvent>
/// <summary>Returns observable which can be used to retrieve events via PullPoint mechanism.</summary>
/// <param name="topicExpressionFilters">Describe subset of filters, which notification producer should use to filter events.</param>
/// <param name="messageContentFilters">Describe subset of filters, which notification producer should use to filter events.</param>
member this.GetPullPointEvents(topicExpressionFilters:seq<TopicExpressionFilter>, messageContentFilters:seq<MessageContentFilter>):IObservable<OnvifEvent>
/// <summary>Returns observable which can be used to retrieve events via PullPoint mechanism.</summary>
/// <param name="filters">Describe set of filters, which notification producer should use to filter events.</param>
member this.GetPullPointEvents(filters:seq<XElement>):IObservable<OnvifEvent>
/// <summary>Returns observable which can be used to retrieve events via PullPoint mechanism.</summary>
/// <param name="filter">
/// Describe set of filters, which notification producer should use to filter events.
/// If null the pullpoint should notify all occurring events to the client.
/// </param>
member this.GetPullPointEvents(filter:FilterType):IObservable<OnvifEvent>
/// <summary>Returns observable which can be used to retrieve events via BaseNotification mechanism.</summary>
/// <param name="port">Number of tcp port, that will be used to listen for events from subscribtion manager</param>
member this.GetBaseEvents(port:int):IObservable<OnvifEvent>
/// <summary>Returns observable which can be used to retrieve events via BaseNotification mechanism.</summary>
/// <param name="port">Number of tcp port, that will be used to listen for events from subscribtion manager</param>
/// <param name="topicExpressionFilters">Describe subset of filters, which notification producer should use to filter events. </param>
/// <param name="messageContentFilters">Describe subset of filters, which notification producer should use to filter events. </param>
member this.GetBaseEvents(port:int, topicExpressionFilters:seq<TopicExpressionFilter>, messageContentFilters:seq<MessageContentFilter>):IObservable<OnvifEvent>
/// <summary>Returns observable which can be used to retrieve events via BaseNotification mechanism.</summary>
/// <param name="port">Number of tcp port, that will be used to listen for events from subscribtion manager</param>
/// <param name="filters">Describe set of filters, which notification producer should use to filter events. </param>
member this.GetBaseEvents(port:int, filters:seq<XElement>):IObservable<OnvifEvent>
/// <summary>Returns observable which can be used to retrieve events via BaseNotification mechanism.</summary>
/// <param name="port">Number of tcp port, that will be used to listen for events from subscribtion manager</param>
/// <param name="filter">
/// Describe set of filters, which notification producer should use to filter events.
/// If null the notification producer should notify all occurring events to the client.
/// </param>
member this.GetBaseEvents(port:int, filter:FilterType):IObservable<OnvifEvent>
Hi.
Thanks to both of you, I managed to get my subscription code working.
As a final question, is there any way to unsubscribe from notifications?
Dan.
to unsubscribe you just need to call Dispose from IDisposable returned by Subscribe
It's me again.
I thought I had solved all my problems, but now that I'm moving the code to the production environment, motion events are not detected. Both computers are on the same network, running the same code; the firewall is disabled on both.
Any thoughts?
Dan.
Here's my code:
public void Scan()
{
Status = CameraStatus.Ok;
int listenPort = 8085;
int.TryParse(EventListeningPort, out listenPort);
OdmSession facade = new OdmSession(_sessionFactory.CreateSession(CamUri));
Console.WriteLine(string.Format("Camera {0} Subscribing on port {1}…", Name, listenPort));
_subscription = facade.GetBaseEvents(listenPort).Subscribe(
onvifEvent =>
{
Console.WriteLine(string.Format("Received ONVIF event"));
foreach (var item in onvifEvent.message.Data.SimpleItem)
{
Console.WriteLine(string.Format("Name is {0} value is {1}", item.Name, item.Value));
if (item.Name.ToLower() == "motion" && item.Value == "1")
{
Console.WriteLine(string.Format("Motion detected on camera {0} (IP {1})", Name, IPAddress));
Status = CameraStatus.MotionDetected;
DoneEvent.Set();
}
}
}, err =>
{
Console.WriteLine(err);
Status = CameraStatus.NotResponding;
DoneEvent.Set();
}
);
Console.WriteLine(string.Format("Subscription done…"));
}
Here's the output when testing on my test computer:
Starting scan for camera "camera1 (Opened)"
Camera camera1 (Opened) Subscribing on port 8085…
Subscription done…
Received ONVIF event
Name is state value is 0
Received ONVIF event
Name is motion value is 1
Motion detected on camera camera1 (Opened) (IP 192.168.192.90)
Received ONVIF event
Name is motion value is 1
Motion detected on camera camera1 (Opened) (IP 192.168.192.90)
Received ONVIF event
Name is motion value is 0
Received ONVIF event
Name is motion value is 0
And the same output on my production machine
Starting scan for camera "camera1 (Opened)"
Camera camera1 (Opened) Subscribing on port 8085…
Subscription done…
Received ONVIF event
Name is state value is 0
I thinking I might be missing a dependency. Here's what I deploy, on top of my own library:
onvif.services.dll
onvif.session.dll
onvif.utils.dll
System.Reactive.dll
utils.bindings.dll
utils.common.dll
utils.diagnostics.dll
utils.fsharp.dll
utils.linq.dll
utils.wpf.dll
utils.xml.dll
Dan.
Here some my suggestions how to find what went wrong. First we need to ensure that all libraries is compatible, they all have to be same version, except System.Reactive, behaviour can be unstable if it is not. After we need to be convinced that subscription is not disposed before we expected, if it is hard to do that by analysing your code, wireshark can help us, we will see unsubscribe request when subscription is disposed. Also we need to check that subscription is rooted, and will not be collected by GC, wireshark can help us here too, in case if subscription working well we should see periodically renew requests from client to nvt's subsription manager, with interval about 60sec. In case if it's not or incoming requests from nvt to client (port 8085) are refused or aborted we can assert that subscription was closed. Hope this will be helpful for you. If not, so kindly provide us additional details to investigate this issue more precisely (wireshark logs or simplified but integral example that reproduce this issue, so we can run it and debug by ourself).
Also here is some aspects, that you should take into account when using onvif libraries.
Add following settings into your app.config file:
somewhere in bootsrapper code, add following: