Release 4.0.0-preview1-00051
[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     /// <since_tizen>3</since_tizen>
27     public class GpsSatellite
28     {
29         private int _interval = 1;
30         private Locator _locator;
31         private EventHandler<SatelliteStatusChangedEventArgs> _satelliteStatusChanged;
32         private IntPtr _handle = IntPtr.Zero;
33
34         private Interop.GpsSatellite.SatelliteStatuschangedCallback _satelliteStatuschangedCallback;
35         private Interop.GpsSatellite.SatelliteStatusinfomationCallback _satelliteStatusinfomationCallback;
36
37         /// <summary>
38         /// The time interval between callback updates.
39         /// Should be in the range [1~120] seconds.
40         /// </summary>
41         /// <since_tizen>3</since_tizen>
42         /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
43         public int Interval
44         {
45             get
46             {
47                 Log.Info(Globals.LogTag, "Getting the Callback Interval");
48                 return _interval;
49             }
50             set
51             {
52                 Log.Info(Globals.LogTag, "Setting the Callback Interval");
53                 if (value > 0 && value <= 120)
54                 {
55                     _interval = value;
56                 }
57                 else
58                 {
59                     Log.Error(Globals.LogTag, "Error Setting the Callback Interval");
60                     throw LocationErrorFactory.ThrowLocationException((int)LocationError.InvalidParameter);
61                 }
62             }
63         }
64
65         /// <summary>
66         /// The NMEAData from the Satellite.
67         /// </summary>
68         /// <since_tizen>3</since_tizen>
69         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state.</exception>
70         /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
71         /// <exception cref="UnauthroizedAccessException">Thrown when the app has no privilege to use the location.</exception>
72         /// <exception cref="NotSupportedException">Thrown when the location is not supported.</exception>
73         public string Nmea
74         {
75             get
76             {
77                 Log.Info(Globals.LogTag, "Getting NMEAData");
78                 return GetNmea();
79             }
80         }
81
82         private string GetNmea()
83         {
84             string value = null;
85             int ret = Interop.GpsSatellite.GetNMEAData(_handle, out value);
86             if (((LocationError)ret != LocationError.None))
87             {
88                 Log.Error(Globals.LogTag, "Error getting the NMEAData," + (LocationError)ret);
89                 throw LocationErrorFactory.ThrowLocationException(ret);
90             }
91
92             return value;
93         }
94
95
96         /// <summary>
97         /// The Count of Active satellites.
98         /// </summary>
99         /// <since_tizen>3</since_tizen>
100         /// <privilege>http://tizen.org/privilege/location</privilege>
101         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state.</exception>
102         /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
103         /// <exception cref="UnauthroizedAccessException">Thrown when the app has no privilege to use the location.</exception>
104         /// <exception cref="NotSupportedException">Thrown when the location is not supported.</exception>
105         public int ActiveCount
106         {
107             get
108             {
109                 return (int)GetActiveCount();
110             }
111         }
112
113         private uint GetActiveCount()
114         {
115             Log.Info(Globals.LogTag, "Getting the ActiveCount of satellites");
116             uint numActive = 0;
117             uint numInView;
118             int timestamp;
119             int ret = Interop.GpsSatellite.GetSatelliteStatus(_handle, out numActive, out numInView, out timestamp);
120             if (((LocationError)ret != LocationError.None))
121             {
122                 Log.Error(Globals.LogTag, "Error getting the satellite" + (LocationError)ret);
123                 throw LocationErrorFactory.ThrowLocationException(ret);
124             }
125             return numActive;
126         }
127
128         /// <summary>
129         /// The Count of satellites in view.
130         /// </summary>
131         /// <since_tizen>3</since_tizen>
132         /// <privilege>http://tizen.org/privilege/location</privilege>
133         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state.</exception>
134         /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
135         /// <exception cref="UnauthroizedAccessException">Thrown when the app has no privilege to use the location.</exception>
136         /// <exception cref="NotSupportedException">Thrown when the location is not supported.</exception>
137         public int InViewCount
138         {
139             get
140             {
141                 return (int)GetInViewCount();
142             }
143         }
144
145         private uint GetInViewCount()
146         {
147             Log.Info(Globals.LogTag, "Getting the In view count of satellites");
148             uint numActive;
149             uint numInView = 0;
150             int timestamp;
151             int ret = Interop.GpsSatellite.GetSatelliteStatus(_handle, out numActive, out numInView, out timestamp);
152             if (((LocationError)ret != LocationError.None))
153             {
154                 Log.Error(Globals.LogTag, "Error getting the satellite" + (LocationError)ret);
155                 throw LocationErrorFactory.ThrowLocationException(ret);
156             }
157             return numInView;
158         }
159
160         /// <summary>
161         /// The list of satellites/last recorded satellites in view.
162         /// </summary>
163         /// <since_tizen>3</since_tizen>
164         /// <privilege>http://tizen.org/privilege/location</privilege>
165         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state.</exception>
166         /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
167         /// <exception cref="UnauthroizedAccessException">Thrown when the app has no privilege to use the location.</exception>
168         /// <exception cref="NotSupportedException">Thrown when the location is not supported.</exception>
169         public IList<SatelliteInformation> Satellites
170         {
171             get
172             {
173                 return GetSatellites();
174             }
175         }
176
177         private IList<SatelliteInformation> GetSatellites()
178         {
179             List<SatelliteInformation> satelliteList = new List<SatelliteInformation>();
180             Log.Info(Globals.LogTag, "Getting the list of satellites");
181
182             if (_satelliteStatusinfomationCallback == null)
183             {
184                 _satelliteStatusinfomationCallback = (azimuth, elevation, prn, snr, active, userData) =>
185                 {
186                     SatelliteInformation satellite = new SatelliteInformation(azimuth, elevation, prn, snr, active);
187                     satelliteList.Add(satellite);
188                     return true;
189                 };
190             }
191
192             int ret = Interop.GpsSatellite.GetForEachSatelliteInView(_handle, _satelliteStatusinfomationCallback, IntPtr.Zero);
193             if (((LocationError)ret != LocationError.None))
194             {
195                 Log.Error(Globals.LogTag, "Error getting the satellite" + (LocationError)ret);
196                 throw LocationErrorFactory.ThrowLocationException(ret);
197             }
198             return satelliteList;
199         }
200
201         /// <summary>
202         /// The constructor of GpsSatellite class.
203         /// </summary>
204         /// <since_tizen>3</since_tizen>
205         /// <param name="locator"> Locator object initilized using Gps.</param>
206         /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
207         public GpsSatellite(Locator locator)
208         {
209             Log.Info(Globals.LogTag, "Calling GpsSatellite constructor");
210             if (locator == null)
211             {
212                 Log.Error(Globals.LogTag, "locator is null");
213                 throw LocationErrorFactory.ThrowLocationException((int)LocationError.InvalidParameter);
214             }
215
216             LocationType method = locator.LocationType;
217             if (method.Equals(LocationType.Gps) || method.Equals(LocationType.Hybrid))
218             {
219                 _locator = locator;
220                 _handle = _locator.GetHandle();
221             }
222             else
223             {
224                 Log.Error(Globals.LogTag, "Error constructing GpsSatellite class");
225                 throw LocationErrorFactory.ThrowLocationException((int)LocationError.InvalidParameter);
226             }
227         }
228
229         /// <summary>
230         /// (event) SatelliteStatusUpdated is raised whenever satellite information is updated.
231         /// The callback will be invoked periodically (every Interval seconds).
232         /// </summary>
233         /// <since_tizen>3</since_tizen>
234         /// <privilege>http://tizen.org/privilege/location</privilege>
235         /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
236         /// <exception cref="UnauthroizedAccessException">Thrown when the app has no privilege to use the location.</exception>
237         /// <exception cref="NotSupportedException">Thrown when the location is not supported.</exception>
238         public event EventHandler<SatelliteStatusChangedEventArgs> SatelliteStatusUpdated
239         {
240             add
241             {
242                 Log.Info(Globals.LogTag, "SatelliteStatusUpdated Add called");
243                 if (_satelliteStatusChanged == null)
244                 {
245                     Log.Info(Globals.LogTag, "SetSatelliteStatusChangeCallback called");
246                     SetSatelliteStatusChangeCallback();
247                 }
248                 _satelliteStatusChanged += value;
249             }
250             remove
251             {
252                 Log.Info(Globals.LogTag, "SatelliteStatusUpdated Remove called");
253                 _satelliteStatusChanged -= value;
254                 if (_satelliteStatusChanged == null)
255                 {
256                     Log.Info(Globals.LogTag, "UnSetSatelliteStatusChangeCallback called");
257                     UnSetSatelliteStatusChangeCallback();
258                 }
259             }
260         }
261
262         private void SetSatelliteStatusChangeCallback()
263         {
264             Log.Info(Globals.LogTag, "SetSatelliteStatusChangeCallback");
265             if (_satelliteStatuschangedCallback == null)
266             {
267                 _satelliteStatuschangedCallback = (numActive, numInView, timestamp, userData) =>
268                 {
269                     Log.Info(Globals.LogTag, "Inside SatelliteStatusChangedCallback");
270                     DateTime timeStamp = DateTime.Now;
271
272                     if (timestamp != 0)
273                     {
274                         DateTime start = DateTime.SpecifyKind(new DateTime(1970, 1, 1).AddSeconds(timestamp), DateTimeKind.Utc);
275                         timeStamp = start.ToLocalTime();
276                     }
277                     _satelliteStatusChanged?.Invoke(_handle, new SatelliteStatusChangedEventArgs(numActive, numInView, timeStamp));
278                 };
279             }
280
281             GCHandle handle = GCHandle.Alloc(this);
282             int ret = Interop.GpsSatellite.SetSatelliteStatusChangedCallback(_handle, _satelliteStatuschangedCallback, _interval, GCHandle.ToIntPtr(handle));
283             if (((LocationError)ret != LocationError.None))
284             {
285                 Log.Error(Globals.LogTag, "Error in setting satellite status changed callback," + (LocationError)ret);
286                 throw LocationErrorFactory.ThrowLocationException(ret);
287             }
288         }
289
290         private void UnSetSatelliteStatusChangeCallback()
291         {
292             Log.Info(Globals.LogTag, "UnSetSatelliteStatusChangeCallback");
293             int ret = Interop.GpsSatellite.UnSetSatelliteStatusChangedCallback(_handle);
294             if (((LocationError)ret != LocationError.None))
295             {
296                 Log.Error(Globals.LogTag, "Error in Getting Unsetting satellite status changed callback," + (LocationError)ret);
297                 throw LocationErrorFactory.ThrowLocationException(ret);
298             }
299         }
300     }
301
302     /// <summary>
303     /// A class which contains the information of the Satellite under consideration.
304     /// </summary>
305     /// <since_tizen>3</since_tizen>
306     public class SatelliteInformation
307     {
308         /// <summary>
309         /// Class Constructor for SatelliteInformation class.
310         /// </summary>
311         /// <since_tizen>3</since_tizen>
312         /// <param name="azimuth"> The azimuth value of the satellite in degrees.</param>
313         /// <param name="elevation"> The elevation of the satellite in meters.</param>
314         /// <param name="prn"> The Prn value of the satellite.</param>
315         /// <param name="snr"> The SNR value of the satellite in dB.</param>
316         /// <param name="active"> The flag signaling if satellite is in use.</param>
317         public SatelliteInformation(uint azimuth, uint elevation, uint prn, uint snr, bool active)
318         {
319             Azimuth = azimuth;
320             Elevation = elevation;
321             Prn = prn;
322             Snr = snr;
323             Active = active;
324         }
325
326         /// <summary>
327         /// The Azimuth information of the Satellite.
328         /// </summary>
329         /// <since_tizen>3</since_tizen>
330         /// <param name="azimuth"> The azimuth value of the satellite in degrees.</param>
331         public uint Azimuth { get; private set; }
332
333         /// <summary>
334         /// The Elevation information of the Satellite.
335         /// </summary>
336         /// <since_tizen>3</since_tizen>
337         /// <param name="azimuth"> The azimuth value of the satellite in degrees.</param>
338         public uint Elevation { get; private set; }
339
340         /// <summary>
341         /// The PRN of the Satellite.
342         /// </summary>
343         /// <since_tizen>3</since_tizen>
344         /// <param name="azimuth"> The azimuth value of the satellite in degrees.</param>
345         public uint Prn { get; private set; }
346
347         /// <summary>
348         /// The SNR of the Satellite.
349         /// </summary>
350         /// <since_tizen>3</since_tizen>
351         public uint Snr { get; private set; }
352
353         /// <summary>
354         /// The operational status of the Satellite.
355         /// </summary>
356         /// <since_tizen>3</since_tizen>
357         public bool Active { get; private set; }
358     }
359 }