/* * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved * * Licensed under the Apache License, Version 2.0 (the License); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Collections.Generic; using System.Runtime.InteropServices; namespace Tizen.Location { /// /// A class which contains the functionality for obtaining information about Gps satellites in range and in use. /// /// 3 public class GpsSatellite { private int _interval = 1; private Locator _locator; private EventHandler _satelliteStatusChanged; private IntPtr _handle = IntPtr.Zero; private Interop.GpsSatellite.SatelliteStatuschangedCallback _satelliteStatuschangedCallback; private Interop.GpsSatellite.SatelliteStatusinfomationCallback _satelliteStatusinfomationCallback; /// /// The time interval between callback updates. /// Should be in the range [1~120] seconds. /// /// 3 /// Thrown when an invalid argument is used. public int Interval { get { Log.Info(Globals.LogTag, "Getting the Callback Interval"); return _interval; } set { Log.Info(Globals.LogTag, "Setting the Callback Interval"); if (value > 0 && value <= 120) { _interval = value; } else { Log.Error(Globals.LogTag, "Error Setting the Callback Interval"); throw LocationErrorFactory.ThrowLocationException((int)LocationError.InvalidParameter); } } } /// /// The NMEAData from the Satellite. /// /// 3 /// Thrown when the operation is invalid for the current state. /// Thrown when an invalid argument is used. /// Thrown when the app has no privilege to use the location. /// Thrown when the location is not supported. public string Nmea { get { Log.Info(Globals.LogTag, "Getting NMEAData"); return GetNmea(); } } private string GetNmea() { string value = null; int ret = Interop.GpsSatellite.GetNMEAData(_handle, out value); if (((LocationError)ret != LocationError.None)) { Log.Error(Globals.LogTag, "Error getting the NMEAData," + (LocationError)ret); throw LocationErrorFactory.ThrowLocationException(ret); } return value; } /// /// The Count of Active satellites. /// /// 3 /// http://tizen.org/privilege/location /// Thrown when the operation is invalid for the current state. /// Thrown when an invalid argument is used. /// Thrown when the app has no privilege to use the location. /// Thrown when the location is not supported. public int ActiveCount { get { return (int)GetActiveCount(); } } private uint GetActiveCount() { Log.Info(Globals.LogTag, "Getting the ActiveCount of satellites"); uint numActive = 0; uint numInView; int timestamp; int ret = Interop.GpsSatellite.GetSatelliteStatus(_handle, out numActive, out numInView, out timestamp); if (((LocationError)ret != LocationError.None)) { Log.Error(Globals.LogTag, "Error getting the satellite" + (LocationError)ret); throw LocationErrorFactory.ThrowLocationException(ret); } return numActive; } /// /// The Count of satellites in view. /// /// 3 /// http://tizen.org/privilege/location /// Thrown when the operation is invalid for the current state. /// Thrown when an invalid argument is used. /// Thrown when the app has no privilege to use the location. /// Thrown when the location is not supported. public int InViewCount { get { return (int)GetInViewCount(); } } private uint GetInViewCount() { Log.Info(Globals.LogTag, "Getting the In view count of satellites"); uint numActive; uint numInView = 0; int timestamp; int ret = Interop.GpsSatellite.GetSatelliteStatus(_handle, out numActive, out numInView, out timestamp); if (((LocationError)ret != LocationError.None)) { Log.Error(Globals.LogTag, "Error getting the satellite" + (LocationError)ret); throw LocationErrorFactory.ThrowLocationException(ret); } return numInView; } /// /// The list of satellites/last recorded satellites in view. /// /// 3 /// http://tizen.org/privilege/location /// Thrown when the operation is invalid for the current state. /// Thrown when an invalid argument is used. /// Thrown when the app has no privilege to use the location. /// Thrown when the location is not supported. public IList Satellites { get { return GetSatellites(); } } private IList GetSatellites() { List satelliteList = new List(); Log.Info(Globals.LogTag, "Getting the list of satellites"); if (_satelliteStatusinfomationCallback == null) { _satelliteStatusinfomationCallback = (azimuth, elevation, prn, snr, active, userData) => { SatelliteInformation satellite = new SatelliteInformation(azimuth, elevation, prn, snr, active); satelliteList.Add(satellite); return true; }; } int ret = Interop.GpsSatellite.GetForEachSatelliteInView(_handle, _satelliteStatusinfomationCallback, IntPtr.Zero); if (((LocationError)ret != LocationError.None)) { Log.Error(Globals.LogTag, "Error getting the satellite" + (LocationError)ret); throw LocationErrorFactory.ThrowLocationException(ret); } return satelliteList; } /// /// The constructor of GpsSatellite class. /// /// 3 /// Locator object initilized using Gps. /// Thrown when an invalid argument is used. public GpsSatellite(Locator locator) { Log.Info(Globals.LogTag, "Calling GpsSatellite constructor"); if (locator == null) { Log.Error(Globals.LogTag, "locator is null"); throw LocationErrorFactory.ThrowLocationException((int)LocationError.InvalidParameter); } LocationType method = locator.LocationType; if (method.Equals(LocationType.Gps) || method.Equals(LocationType.Hybrid)) { _locator = locator; _handle = _locator.GetHandle(); } else { Log.Error(Globals.LogTag, "Error constructing GpsSatellite class"); throw LocationErrorFactory.ThrowLocationException((int)LocationError.InvalidParameter); } } /// /// (event) SatelliteStatusUpdated is raised whenever satellite information is updated. /// The callback will be invoked periodically (every Interval seconds). /// /// 3 /// http://tizen.org/privilege/location /// Thrown when an invalid argument is used. /// Thrown when the app has no privilege to use the location. /// Thrown when the location is not supported. public event EventHandler SatelliteStatusUpdated { add { Log.Info(Globals.LogTag, "SatelliteStatusUpdated Add called"); if (_satelliteStatusChanged == null) { Log.Info(Globals.LogTag, "SetSatelliteStatusChangeCallback called"); SetSatelliteStatusChangeCallback(); } _satelliteStatusChanged += value; } remove { Log.Info(Globals.LogTag, "SatelliteStatusUpdated Remove called"); _satelliteStatusChanged -= value; if (_satelliteStatusChanged == null) { Log.Info(Globals.LogTag, "UnSetSatelliteStatusChangeCallback called"); UnSetSatelliteStatusChangeCallback(); } } } private void SetSatelliteStatusChangeCallback() { Log.Info(Globals.LogTag, "SetSatelliteStatusChangeCallback"); if (_satelliteStatuschangedCallback == null) { _satelliteStatuschangedCallback = (numActive, numInView, timestamp, userData) => { Log.Info(Globals.LogTag, "Inside SatelliteStatusChangedCallback"); DateTime timeStamp = DateTime.Now; if (timestamp != 0) { DateTime start = DateTime.SpecifyKind(new DateTime(1970, 1, 1).AddSeconds(timestamp), DateTimeKind.Utc); timeStamp = start.ToLocalTime(); } _satelliteStatusChanged?.Invoke(_handle, new SatelliteStatusChangedEventArgs(numActive, numInView, timeStamp)); }; } GCHandle handle = GCHandle.Alloc(this); int ret = Interop.GpsSatellite.SetSatelliteStatusChangedCallback(_handle, _satelliteStatuschangedCallback, _interval, GCHandle.ToIntPtr(handle)); if (((LocationError)ret != LocationError.None)) { Log.Error(Globals.LogTag, "Error in setting satellite status changed callback," + (LocationError)ret); throw LocationErrorFactory.ThrowLocationException(ret); } } private void UnSetSatelliteStatusChangeCallback() { Log.Info(Globals.LogTag, "UnSetSatelliteStatusChangeCallback"); int ret = Interop.GpsSatellite.UnSetSatelliteStatusChangedCallback(_handle); if (((LocationError)ret != LocationError.None)) { Log.Error(Globals.LogTag, "Error in Getting Unsetting satellite status changed callback," + (LocationError)ret); throw LocationErrorFactory.ThrowLocationException(ret); } } } /// /// A class which contains the information of the Satellite under consideration. /// /// 3 public class SatelliteInformation { /// /// Class Constructor for SatelliteInformation class. /// /// 3 /// The azimuth value of the satellite in degrees. /// The elevation of the satellite in meters. /// The Prn value of the satellite. /// The SNR value of the satellite in dB. /// The flag signaling if satellite is in use. public SatelliteInformation(uint azimuth, uint elevation, uint prn, uint snr, bool active) { Azimuth = azimuth; Elevation = elevation; Prn = prn; Snr = snr; Active = active; } /// /// The Azimuth information of the Satellite. /// /// 3 /// The azimuth value of the satellite in degrees. public uint Azimuth { get; private set; } /// /// The Elevation information of the Satellite. /// /// 3 /// The azimuth value of the satellite in degrees. public uint Elevation { get; private set; } /// /// The PRN of the Satellite. /// /// 3 /// The azimuth value of the satellite in degrees. public uint Prn { get; private set; } /// /// The SNR of the Satellite. /// /// 3 public uint Snr { get; private set; } /// /// The operational status of the Satellite. /// /// 3 public bool Active { get; private set; } } }