Boundary destroy handle
[platform/core/csapi/tizenfx.git] / src / Tizen.Location / Tizen.Location / GpsSatellite.cs
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 using System;
18 using System.Collections.Generic;
19 using System.Runtime.InteropServices;
20
21 namespace Tizen.Location
22 {
23     /// <summary>
24     /// A class which contains the functionality for obtaining information about Gps satellites in range and in use.
25     /// </summary>
26     public class GpsSatellite
27     {
28         private int _interval = 1;
29         private Locator _locator;
30         private EventHandler<SatelliteStatusChangedEventArgs> _satelliteStatusChanged;
31         private IntPtr _handle = IntPtr.Zero;
32
33         /// <summary>
34         /// The time interval between callback updates.
35         /// Should be in the range [1~120] seconds.
36         /// </summary>
37         /// <exception cref="ArgumentException">Thrown when an invalid argument is used</exception>
38         /// <exception cref="NotSupportedException">Thrown when the location is not supported</exception>
39         public int Interval
40         {
41             get
42             {
43                 Log.Info(Globals.LogTag, "Getting the Callback Interval");
44                 return _interval;
45             }
46             set
47             {
48                 Log.Info(Globals.LogTag, "Setting the Callback Interval");
49                 if (value > 0 && value <= 120)
50                 {
51                     _interval = value;
52                 }
53                 else
54                 {
55                     Log.Error(Globals.LogTag, "Error Setting the Callback Interval");
56                     throw LocationErrorFactory.ThrowLocationException((int)LocationError.InvalidParameter);
57                 }
58             }
59         }
60
61         /// <summary>
62         /// The NMEAData from the Satellite.
63         /// </summary>
64         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state</exception>
65         /// <exception cref="ArgumentException">Thrown when an invalid argument is used</exception>
66         /// <exception cref="UnauthroizedAccessException">Thrown when the app has no privilege to use the location</exception>
67         /// <exception cref="NotSupportedException">Thrown when the location is not supported</exception>
68         public string Nmea
69         {
70             get
71             {
72                 Log.Info(Globals.LogTag, "Getting NMEAData");
73                 return GetNmea();
74             }
75         }
76
77         private string GetNmea()
78         {
79             string value = null;
80             int ret = Interop.GpsSatellite.GetNMEAData(_handle, out value);
81             if (((LocationError)ret != LocationError.None))
82             {
83                 Log.Error(Globals.LogTag, "Error getting the NMEAData," + (LocationError)ret);
84                 throw LocationErrorFactory.ThrowLocationException(ret);
85             }
86
87             return value;
88         }
89
90
91         /// <summary>
92         /// The Count of Active satellites.
93         /// </summary>
94         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state</exception>
95         /// <exception cref="ArgumentException">Thrown when an invalid argument is used</exception>
96         /// <exception cref="UnauthroizedAccessException">Thrown when the app has no privilege to use the location</exception>
97         /// <exception cref="NotSupportedException">Thrown when the location is not supported</exception>
98         public int ActiveCount
99         {
100             get
101             {
102                 return (int)GetActiveCount();
103             }
104         }
105
106         private uint GetActiveCount()
107         {
108             Log.Info(Globals.LogTag, "Getting the ActiveCount of satellites");
109             uint numActive = 0;
110             uint numInView;
111             int timestamp;
112             int ret = Interop.GpsSatellite.GetSatelliteStatus(_handle, out numActive, out numInView, out timestamp);
113             if (((LocationError)ret != LocationError.None))
114             {
115                 Log.Error(Globals.LogTag, "Error getting the satellite" + (LocationError)ret);
116                 throw LocationErrorFactory.ThrowLocationException(ret);
117             }
118             return numActive;
119         }
120
121         /// <summary>
122         /// The Count of satellites in view.
123         /// </summary>
124         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state</exception>
125         /// <exception cref="ArgumentException">Thrown when an invalid argument is used</exception>
126         /// <exception cref="UnauthroizedAccessException">Thrown when the app has no privilege to use the location</exception>
127         /// <exception cref="NotSupportedException">Thrown when the location is not supported</exception>
128         public int InViewCount
129         {
130             get
131             {
132                 return (int)GetInViewCount();
133             }
134         }
135
136         private uint GetInViewCount()
137         {
138             Log.Info(Globals.LogTag, "Getting the In view count of satellites");
139             uint numActive;
140             uint numInView = 0;
141             int timestamp;
142             int ret = Interop.GpsSatellite.GetSatelliteStatus(_handle, out numActive, out numInView, out timestamp);
143             if (((LocationError)ret != LocationError.None))
144             {
145                 Log.Error(Globals.LogTag, "Error getting the satellite" + (LocationError)ret);
146                 throw LocationErrorFactory.ThrowLocationException(ret);
147             }
148             return numInView;
149         }
150
151         /// <summary>
152         /// The list of satellites/last recorded satellites in view.
153         /// </summary>
154         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state</exception>
155         /// <exception cref="ArgumentException">Thrown when an invalid argument is used</exception>
156         /// <exception cref="UnauthroizedAccessException">Thrown when the app has no privilege to use the location</exception>
157         /// <exception cref="NotSupportedException">Thrown when the location is not supported</exception>
158         public IList<SatelliteInformation> Satellites
159         {
160             get
161             {
162                 return GetSatellites();
163             }
164         }
165
166         private IList<SatelliteInformation> GetSatellites()
167         {
168             List<SatelliteInformation> satelliteList = new List<SatelliteInformation>();
169             Log.Info(Globals.LogTag, "Getting the list of satellites");
170             Interop.GpsSatellite.SatelliteStatusinfomationCallback callback = (uint azimuth, uint elevation, uint prn, uint snr, bool isActive, IntPtr userData) =>
171             {
172                 SatelliteInformation satellite = new SatelliteInformation(azimuth, elevation, prn, snr, isActive);
173                 satelliteList.Add(satellite);
174                 return true;
175             };
176             int ret = Interop.GpsSatellite.GetForEachSatelliteInView(_handle, callback, IntPtr.Zero);
177             if (((LocationError)ret != LocationError.None))
178             {
179                 Log.Error(Globals.LogTag, "Error getting the satellite" + (LocationError)ret);
180                 throw LocationErrorFactory.ThrowLocationException(ret);
181             }
182             return satelliteList;
183         }
184
185         /// <summary>
186         /// The constructor of GpsSatellite class.
187         /// <param name="locator"> Locator object initilized using Gps.</param>
188         /// </summary>
189         /// <exception cref="ArgumentException">Thrown when an invalid argument is used</exception>
190         public GpsSatellite(Locator locator)
191         {
192             Log.Info(Globals.LogTag, "Calling GpsSatellite constructor");
193             LocationType method = locator.LocationType;
194             if (method.Equals(LocationType.Gps) || method.Equals(LocationType.Hybrid))
195             {
196                 _locator = locator;
197                 _handle = _locator.GetHandle();
198             }
199             else
200             {
201                 Log.Error(Globals.LogTag, "Error constructing GpsSatellite class");
202                 throw LocationErrorFactory.ThrowLocationException((int)LocationError.InvalidParameter);
203             }
204         }
205
206         /// <summary>
207         /// (event) SatelliteStatusUpdated is raised whenever satellite information is updated.
208         /// The callback will be invoked periodically (every Interval seconds).
209         /// </summary>
210         /// <exception cref="ArgumentException">Thrown when an invalid argument is used</exception>
211         /// <exception cref="UnauthroizedAccessException">Thrown when the app has no privilege to use the location</exception>
212         /// <exception cref="NotSupportedException">Thrown when the location is not supported</exception>
213         public event EventHandler<SatelliteStatusChangedEventArgs> SatelliteStatusUpdated
214         {
215             add
216             {
217                 Log.Info(Globals.LogTag, "SatelliteStatusUpdated Add called");
218                 if (_satelliteStatusChanged == null)
219                 {
220                     Log.Info(Globals.LogTag, "SetSatelliteStatusChangeCallback called");
221                     SetSatelliteStatusChangeCallback();
222                 }
223                 _satelliteStatusChanged += value;
224             }
225             remove
226             {
227                 Log.Info(Globals.LogTag, "SatelliteStatusUpdated Remove called");
228                 _satelliteStatusChanged -= value;
229                 if (_satelliteStatusChanged == null)
230                 {
231                     Log.Info(Globals.LogTag, "UnSetSatelliteStatusChangeCallback called");
232                     UnSetSatelliteStatusChangeCallback();
233                 }
234             }
235         }
236
237         private void SetSatelliteStatusChangeCallback()
238         {
239             Log.Info(Globals.LogTag, "SetSatelliteStatusChangeCallback");
240             GCHandle handle = GCHandle.Alloc(this);
241             int ret = Interop.GpsSatellite.SetSatelliteStatusChangedCallback(_handle, SatelliteStatusChangedCallback, _interval, GCHandle.ToIntPtr(handle));
242             /* int ret = Interop.GpsSatellite.SetSatelliteStatusChangedCallback(_handle, SatelliteStatusChangedCallback, _interval, IntPtr.Zero); */
243             if (((LocationError)ret != LocationError.None))
244             {
245                 Log.Error(Globals.LogTag, "Error in setting satellite status changed callback," + (LocationError)ret);
246                 throw LocationErrorFactory.ThrowLocationException(ret);
247             }
248         }
249
250         private void UnSetSatelliteStatusChangeCallback()
251         {
252             Log.Info(Globals.LogTag, "UnSetSatelliteStatusChangeCallback");
253             int ret = Interop.GpsSatellite.UnSetSatelliteStatusChangedCallback(_handle);
254             if (((LocationError)ret != LocationError.None))
255             {
256                 Log.Error(Globals.LogTag, "Error in Getting Unsetting satellite status changed callback," + (LocationError)ret);
257                 throw LocationErrorFactory.ThrowLocationException(ret);
258             }
259         }
260
261         private void SatelliteStatusChangedCallback(uint numActive, uint numInView, int timestamp, IntPtr userData)
262         {
263             Log.Info(Globals.LogTag, "Inside SatelliteStatusChangedCallback");
264             DateTime timeStamp = DateTime.Now;
265
266             if (timestamp != 0)
267             {
268                 DateTime start = DateTime.SpecifyKind(new DateTime(1970, 1, 1).AddSeconds(timestamp), DateTimeKind.Utc);
269                 timeStamp = start.ToLocalTime();
270             }
271
272             _satelliteStatusChanged?.Invoke(_handle, new SatelliteStatusChangedEventArgs(numActive, numInView, timeStamp));
273         }
274     }
275
276     /// <summary>
277     /// A class which contains the information of the Satellite under consideration.
278     /// </summary>
279     public class SatelliteInformation
280     {
281         /// <summary>
282         /// Class Constructor for SatelliteInformation class.
283         /// </summary>
284         /// <param name="azimuth"> The azimuth value of the satellite in degrees.</param>
285         /// <param name="elevation"> The elevation of the satellite in meters.</param>
286         /// <param name="prn"> The Prn value of the satellite.</param>
287         /// <param name="snr"> The SNR value of the satellite in dB.</param>
288         /// <param name="isActive"> The flag signaling if satellite is in use.</param>
289         public SatelliteInformation(uint azimuth, uint elevation, uint prn, uint snr, bool isActive)
290         {
291             Azimuth = azimuth;
292             Elevation = elevation;
293             Prn = prn;
294             Snr = snr;
295             Active = isActive;
296         }
297
298         /// <summary>
299         /// The Azimuth information of the Satellite.
300         /// </summary>
301         public uint Azimuth { get; private set; }
302
303         /// <summary>
304         /// The Elevation information of the Satellite.
305         /// </summary>
306         public uint Elevation { get; private set; }
307
308         /// <summary>
309         /// The PRN of the Satellite.
310         /// </summary>
311         public uint Prn { get; private set; }
312
313         /// <summary>
314         /// The SNR of the Satellite.
315         /// </summary>
316         public uint Snr { get; private set; }
317
318         /// <summary>
319         /// The operational status of the Satellite.
320         /// </summary>
321         public bool Active { get; private set; }
322     }
323 }