/*
* 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; }
}
}