[NUI] TCSACR-226 code change (#1032)
[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     /// This class contains the functionality for obtaining information about GPS satellites in the 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 of 1~120 seconds.
40         /// </summary>
41         /// <since_tizen> 3 </since_tizen>
42         /// <exception cref="ArgumentException">Thrown when an 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 NMEA data 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="UnauthorizedAccessException">Thrown when the application 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="UnauthorizedAccessException">Thrown when the application 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="UnauthorizedAccessException">Thrown when the application 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 or 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="UnauthorizedAccessException">Thrown when the application 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             _satelliteStatusinfomationCallback = (azimuth, elevation, prn, snr, active, userData) =>
183             {
184                 SatelliteInformation satellite = new SatelliteInformation(azimuth, elevation, prn, snr, active);
185                 satelliteList.Add(satellite);
186                 return true;
187             };
188
189             int ret = Interop.GpsSatellite.GetForEachSatelliteInView(_handle, _satelliteStatusinfomationCallback, IntPtr.Zero);
190             if (((LocationError)ret != LocationError.None))
191             {
192                 Log.Error(Globals.LogTag, "Error getting the satellite" + (LocationError)ret);
193                 throw LocationErrorFactory.ThrowLocationException(ret);
194             }
195             return satelliteList;
196         }
197
198         /// <summary>
199         /// The constructor of the GpsSatellite class.
200         /// </summary>
201         /// <since_tizen> 3 </since_tizen>
202         /// <param name="locator">The locator object initilized using GPS.</param>
203         /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
204         public GpsSatellite(Locator locator)
205         {
206             Log.Info(Globals.LogTag, "Calling GpsSatellite constructor");
207             if (locator == null)
208             {
209                 Log.Error(Globals.LogTag, "locator is null");
210                 throw LocationErrorFactory.ThrowLocationException((int)LocationError.InvalidParameter);
211             }
212
213             LocationType method = locator.LocationType;
214             if (method.Equals(LocationType.Gps) || method.Equals(LocationType.Hybrid))
215             {
216                 _locator = locator;
217                 _handle = _locator.GetHandle();
218             }
219             else
220             {
221                 Log.Error(Globals.LogTag, "Error constructing GpsSatellite class");
222                 throw LocationErrorFactory.ThrowLocationException((int)LocationError.InvalidParameter);
223             }
224         }
225
226         /// <summary>
227         /// The SatelliteStatusUpdated event is raised whenever the satellite information is updated.
228         /// The callback will be invoked periodically (every Interval seconds).
229         /// </summary>
230         /// <since_tizen> 3 </since_tizen>
231         /// <privilege>http://tizen.org/privilege/location</privilege>
232         /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
233         /// <exception cref="UnauthorizedAccessException">Thrown when the application has no privilege to use the location.</exception>
234         /// <exception cref="NotSupportedException">Thrown when the location is not supported.</exception>
235         public event EventHandler<SatelliteStatusChangedEventArgs> SatelliteStatusUpdated
236         {
237             add
238             {
239                 Log.Info(Globals.LogTag, "SatelliteStatusUpdated Add called");
240                 if (_satelliteStatusChanged == null)
241                 {
242                     Log.Info(Globals.LogTag, "SetSatelliteStatusChangeCallback called");
243                     SetSatelliteStatusChangeCallback();
244                 }
245                 _satelliteStatusChanged += value;
246             }
247             remove
248             {
249                 Log.Info(Globals.LogTag, "SatelliteStatusUpdated Remove called");
250                 _satelliteStatusChanged -= value;
251                 if (_satelliteStatusChanged == null)
252                 {
253                     Log.Info(Globals.LogTag, "UnSetSatelliteStatusChangeCallback called");
254                     UnSetSatelliteStatusChangeCallback();
255                 }
256             }
257         }
258
259         private void SetSatelliteStatusChangeCallback()
260         {
261             Log.Info(Globals.LogTag, "SetSatelliteStatusChangeCallback");
262             if (_satelliteStatuschangedCallback == null)
263             {
264                 _satelliteStatuschangedCallback = (numActive, numInView, timestamp, userData) =>
265                 {
266                     Log.Info(Globals.LogTag, "Inside SatelliteStatusChangedCallback");
267                     DateTime timeStamp = DateTime.Now;
268
269                     if (timestamp != 0)
270                     {
271                         DateTime start = DateTime.SpecifyKind(new DateTime(1970, 1, 1).AddSeconds(timestamp), DateTimeKind.Utc);
272                         timeStamp = start.ToLocalTime();
273                     }
274                     _satelliteStatusChanged?.Invoke(_handle, new SatelliteStatusChangedEventArgs(numActive, numInView, timeStamp));
275                 };
276             }
277
278             GCHandle handle = GCHandle.Alloc(this);
279             int ret = Interop.GpsSatellite.SetSatelliteStatusChangedCallback(_handle, _satelliteStatuschangedCallback, _interval, GCHandle.ToIntPtr(handle));
280             if (((LocationError)ret != LocationError.None))
281             {
282                 Log.Error(Globals.LogTag, "Error in setting satellite status changed callback," + (LocationError)ret);
283                 throw LocationErrorFactory.ThrowLocationException(ret);
284             }
285         }
286
287         private void UnSetSatelliteStatusChangeCallback()
288         {
289             Log.Info(Globals.LogTag, "UnSetSatelliteStatusChangeCallback");
290             int ret = Interop.GpsSatellite.UnSetSatelliteStatusChangedCallback(_handle);
291             if (((LocationError)ret != LocationError.None))
292             {
293                 Log.Error(Globals.LogTag, "Error in Getting Unsetting satellite status changed callback," + (LocationError)ret);
294                 throw LocationErrorFactory.ThrowLocationException(ret);
295             }
296         }
297     }
298
299     /// <summary>
300     /// This class contains the information of the satellite under consideration.
301     /// </summary>
302     /// <since_tizen> 3 </since_tizen>
303     public class SatelliteInformation
304     {
305         /// <summary>
306         /// The Class constructor for the SatelliteInformation class.
307         /// </summary>
308         /// <since_tizen> 3 </since_tizen>
309         /// <param name="azimuth">The azimuth value of the satellite in degrees.</param>
310         /// <param name="elevation">The elevation of the satellite in meters.</param>
311         /// <param name="prn">The PRN value of the satellite.</param>
312         /// <param name="snr">The SNR value of the satellite in dB.</param>
313         /// <param name="active">The flag signaling if the satellite is in use.</param>
314         public SatelliteInformation(uint azimuth, uint elevation, uint prn, uint snr, bool active)
315         {
316             Azimuth = azimuth;
317             Elevation = elevation;
318             Prn = prn;
319             Snr = snr;
320             Active = active;
321         }
322
323         /// <summary>
324         /// The azimuth information of the satellite.
325         /// </summary>
326         /// <since_tizen> 3 </since_tizen>
327         public uint Azimuth { get; private set; }
328
329         /// <summary>
330         /// The elevation information of the satellite.
331         /// </summary>
332         /// <since_tizen> 3 </since_tizen>
333         public uint Elevation { get; private set; }
334
335         /// <summary>
336         /// The PRN of the satellite.
337         /// </summary>
338         /// <since_tizen> 3 </since_tizen>
339         public uint Prn { get; private set; }
340
341         /// <summary>
342         /// The SNR of the satellite.
343         /// </summary>
344         /// <since_tizen> 3 </since_tizen>
345         public uint Snr { get; private set; }
346
347         /// <summary>
348         /// The operational status of the satellite.
349         /// </summary>
350         /// <since_tizen> 3 </since_tizen>
351         public bool Active { get; private set; }
352     }
353 }