//public OnvifPtz(string ip, int port, string user, string password) //{ // System.Net.IPAddress.TryParse(ip, out IP); // Port = port; // User = user; // Password = password; // PtzClient = OnvifServices.GetOnvifPTZClient(IP.ToString(), Port, User, Password); // MediaClient = OnvifServices.GetOnvifMediaClient(IP.ToString(), Port, User, Password); //} public OnvifPtz(string mediaUri, string ptzUri, double deviceTimeOffset, string user, string password) { User = user; Password = password; if (string.IsNullOrEmpty(mediaUri) | string.IsNullOrEmpty(ptzUri)) { throw new Exception("Media and/or PTZ URI is empty or null. PTZ object cannot be created"); } PtzClient = OnvifServices.GetOnvifPTZClient(ptzUri, deviceTimeOffset, User, Password); MediaClient = OnvifServices.GetOnvifMediaClient(mediaUri, deviceTimeOffset, User, Password); }
/// <summary> /// Subscribes to all events provided by the device and directs to :8080/subscription-1 Http listener /// </summary> /// <param name="uri">XAddr URI for Onvif events</param> /// <param name="username">User</param> /// <param name="password">Password</param> public void Subscribe(string uri, double deviceTimeOffset, string username, string password) { EventPortTypeClient eptc = OnvifServices.GetEventClient(uri, deviceTimeOffset, username, password); string localIP = GetLocalIp(); // Producer client NotificationProducerClient npc = OnvifServices.GetNotificationProducerClient(uri, deviceTimeOffset, username, password); // ip, port, username, password); npc.Endpoint.Address = eptc.Endpoint.Address; Subscribe s = new Subscribe(); // Consumer reference tells the device where to Post messages back to (the client) EndpointReferenceType clientEndpoint = new EndpointReferenceType() { Address = new AttributedURIType() { Value = string.Format("http://{0}:8080/subscription-1", localIP) } }; s.ConsumerReference = clientEndpoint; s.InitialTerminationTime = "PT60S"; try { SubscribeResponse sr = npc.Subscribe(s); // Store the subscription URI for use in Renew SubRenewUri = sr.SubscriptionReference.Address.Value; // Start timer to periodically check if a Renew request needs to be issued // Use PC time for timer in case camera time doesn't match PC time // This works fine because the renew command issues a relative time (i.e. PT60S) so PC/Camera mismatch doesn't matter SubTermTime = System.DateTime.UtcNow.AddSeconds(50); // sr.TerminationTime; SubRenewTimer.Start(); SubRenewTimer.Interval = 1000; SubRenewTimer.Elapsed += SubRenewTimer_Elapsed; OnNotification(string.Format("Initial Termination Time: {0} (Current Time: {1})", SubTermTime, System.DateTime.UtcNow)); SubscriptionManagerClient = OnvifServices.GetSubscriptionManagerClient(SubRenewUri, deviceTimeOffset, username, password); } catch (Exception e) { OnNotification(string.Format("{0} Unable to subscribe to events on device [{1}]", System.DateTime.UtcNow, uri)); // ip)); } }
/// <summary> /// Instantiates PTZ object with known media profile /// </summary> /// <param name="mediaUri">Camera's Media URI (from device client GetServices())</param> /// <param name="ptzUri">Camera's PTZ URI (from device client GetServices())</param> /// <param name="deviceTimeOffset">Difference between device time and client time (seconds)</param> /// <param name="mediaProfile">Media Profile to use</param> /// <param name="user">Username</param> /// <param name="password">Password</param> public OnvifPtz(string mediaUri, string ptzUri, double deviceTimeOffset, RTSP_Viewer.OnvifMediaServiceReference.Profile mediaProfile, string user, string password) { User = user; Password = password; if (string.IsNullOrEmpty(mediaUri) | string.IsNullOrEmpty(ptzUri)) { throw new Exception("Media and/or PTZ URI is empty or null. PTZ object cannot be created"); } PtzClient = OnvifServices.GetOnvifPTZClient(ptzUri, deviceTimeOffset, User, Password); MediaProfile = mediaProfile; // Should be able to remove this once all instantiates go through this constructor (only used by GetMediaProfile - which is only necessary if a mediaProfile is not provided) MediaClient = OnvifServices.GetOnvifMediaClient(mediaUri, deviceTimeOffset, User, Password); }
/// <summary> /// Retrieves Onvif service URIs from the device and stores them in the ServiceUris dictionary /// </summary> /// <param name="ip">IP Address</param> /// <param name="onvifPort">Port to connect on (normally HTTP - 80)</param> /// <param name="user">User name</param> /// <param name="password">User's Password</param> private void GetOnvifUris(Camera cam, int onvifPort) { ServiceUris.Clear(); DeviceClient client = OnvifServices.GetOnvifDeviceClient(cam.IP, onvifPort, DeviceTimeOffset, cam.User, cam.Password); Service[] svc = client.GetServices(IncludeCapability: false); // Bosch Autodome 800 response can't be deserialized if IncludeCapability enabled foreach (Service s in svc) { ServiceUris.Add(s.Namespace, s.XAddr); } // Check if this is an Onvif enabled PTZ if (ServiceUris.ContainsKey(OnvifNamespace.PTZ)) { IsPtz = true; } else { IsPtz = false; } }
/// <summary> /// Get the device time. Per spec, the time in the Onvif header must be within 5 seconds of the device time /// Some devices will fail to authenticate or accept commands if the timestamp difference is too great /// </summary> /// <param name="ip">IP Address</param> /// <param name="onvifPort">Port to connect on (normally HTTP - 80)</param> public void GetDeviceTime(Camera cam, int onvifPort) { DeviceClient client = OnvifServices.GetOnvifDeviceClient(cam.IP, onvifPort, deviceTimeOffset: 0); SystemDateTime deviceTime = client.GetSystemDateAndTime(); DeviceTime = new System.DateTime( deviceTime.UTCDateTime.Date.Year, deviceTime.UTCDateTime.Date.Month, deviceTime.UTCDateTime.Date.Day, deviceTime.UTCDateTime.Time.Hour, deviceTime.UTCDateTime.Time.Minute, deviceTime.UTCDateTime.Time.Second ); LastTimeCheck = System.DateTime.UtcNow; DeviceTimeOffset = (DeviceTime - LastTimeCheck).TotalSeconds; if (Math.Abs(DeviceTimeOffset) > MaxTimeOffset) { log.Warn(string.Format("Camera #{0} [{1}] Time difference between PC and client [{2:0.0} seconds] exceeds MaxTimeOffset [{3:0.0} seconds]. ", cam.Number, cam.IP, DeviceTimeOffset, MaxTimeOffset)); } }
/// <summary> /// Retrieves Onvif video stream URIs from the device and stores them in the StreamUris list /// </summary> /// <param name="onvifPort">Port to connect on (normally HTTP - 80)</param> private void GetStreamUris(Camera cam, int onvifPort, StreamType sType, TransportProtocol tProtocol, int StreamIndex) { //StreamUris.Clear(); MediaClient mc = OnvifServices.GetOnvifMediaClient(ServiceUris[OnvifNamespace.MEDIA], DeviceTimeOffset, cam.User, cam.Password); Profile[] mediaProfiles = mc.GetProfiles(); StreamSetup ss = new StreamSetup(); Transport transport = new Transport() { Protocol = tProtocol }; string uri = string.Empty; // Only store the Profile related to the StreamIndex from the XML file MediaProfile = mediaProfiles[StreamIndex - 1]; // Get stream URI for the requested transport/protocol and insert the User/Password if present ss.Stream = sType; ss.Transport = transport; Uri mu = new Uri(mc.GetStreamUri(ss, MediaProfile.token).Uri); StreamUri = RTSP_Viewer.Classes.Utilities.InsertUriCredentials(mu, cam.User, cam.Password); // Get multicast uri (if available) along with requested protocol/stream type MulticastUri = GetMulticastUri(cam, mc, MediaProfile); // Not being used currently MulticastUri = RTSP_Viewer.Classes.Utilities.InsertUriCredentials(MulticastUri, cam.User, cam.Password); // A PTZ may not have a PTZ configuration for a particular media profile // Disable PTZ access in that case IsPtzEnabled = IsPtz; if (MediaProfile.PTZConfiguration == null && IsPtz) { log.Warn(string.Format("Camera #{0} [{1}] Disabling PTZ control based on the PTZConfiguration being null for stream profile {0}", cam.Number, cam.IP, StreamUri)); IsPtzEnabled = false; } }