Fix satellite exceptions
[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 = 120;
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         public int Interval
38         {
39             get
40             {
41                 Log.Info(Globals.LogTag, "Getting the Callback Interval");
42                 return _interval;
43             }
44             set
45             {
46                 Log.Info(Globals.LogTag, "Setting the Callback Interval");
47                 if (value >= 0 && value <= 120)
48                 {
49                     _interval = value;
50                     if (_satelliteStatusChanged != null)
51                     {
52                         SetSatelliteStatusChangeCallback();
53                     }
54                     else
55                     {
56                         Log.Error(Globals.LogTag, "Error Setting the Callback Interval");
57                         throw LocationErrorFactory.ThrowLocationException((int)LocationError.InvalidParameter);
58                     }
59                 }
60             }
61         }
62
63         /// <summary>
64         /// The NMEAData from the Satellite.
65         /// </summary>
66         public string Nmea
67         {
68             get
69             {
70                 Log.Info(Globals.LogTag, "Getting NMEAData");
71                 return GetNmea();
72             }
73         }
74
75         private string GetNmea()
76         {
77             string value = null;
78             int ret = Interop.GpsSatellite.GetNMEAData(_handle, out value);
79             if (((LocationError)ret != LocationError.None))
80             {
81                 Log.Error(Globals.LogTag, "Error getting the NMEAData," + (LocationError)ret);
82                 throw LocationErrorFactory.ThrowLocationException(ret);
83             }
84
85             return value;
86         }
87
88
89         /// <summary>
90         /// The Count of Active satellites.
91         /// </summary>
92         public int ActiveCount
93         {
94             get
95             {
96                 return (int)GetActiveCount();
97             }
98         }
99
100         private uint GetActiveCount()
101         {
102             Log.Info(Globals.LogTag, "Getting the ActiveCount of satellites");
103             uint numActive = 0;
104             uint numInView;
105             int timestamp;
106             int ret = Interop.GpsSatellite.GetSatelliteStatus(_handle, out numActive, out numInView, out timestamp);
107             if (((LocationError)ret != LocationError.None))
108             {
109                 Log.Error(Globals.LogTag, "Error getting the satellite" + (LocationError)ret);
110                 throw LocationErrorFactory.ThrowLocationException(ret);
111             }
112             return numActive;
113         }
114
115         /// <summary>
116         /// The Count of satellites in view.
117         /// </summary>
118         public int InViewCount
119         {
120             get
121             {
122                 return (int)GetInViewCount();
123             }
124         }
125
126         private uint GetInViewCount()
127         {
128             Log.Info(Globals.LogTag, "Getting the In view count of satellites");
129             uint numActive;
130             uint numInView = 0;
131             int timestamp;
132             int ret = Interop.GpsSatellite.GetSatelliteStatus(_handle, out numActive, out numInView, out timestamp);
133             if (((LocationError)ret != LocationError.None))
134             {
135                 Log.Error(Globals.LogTag, "Error getting the satellite" + (LocationError)ret);
136                 throw LocationErrorFactory.ThrowLocationException(ret);
137             }
138             return numInView;
139         }
140
141         /// <summary>
142         /// The list of satellites/last recorded satellites in view.
143         /// </summary>
144         public IList<SatelliteInformation> Satellites
145         {
146             get
147             {
148                 return GetSatellites();
149             }
150         }
151
152         private IList<SatelliteInformation> GetSatellites()
153         {
154             List<SatelliteInformation> satelliteList = new List<SatelliteInformation>();
155             Log.Info(Globals.LogTag, "Getting the list of satellites");
156             Interop.GpsSatellite.SatelliteStatusinfomationCallback callback = (uint azimuth, uint elevation, uint prn, uint snr, bool isActive, IntPtr userData) =>
157             {
158                 SatelliteInformation satellite = new SatelliteInformation(azimuth, elevation, prn, snr, isActive);
159                 satelliteList.Add(satellite);
160                 return true;
161             };
162             int ret = Interop.GpsSatellite.GetForEachSatelliteInView(_handle, callback, IntPtr.Zero);
163             if (((LocationError)ret != LocationError.None))
164             {
165                 Log.Error(Globals.LogTag, "Error getting the satellite" + (LocationError)ret);
166                 throw LocationErrorFactory.ThrowLocationException(ret);
167             }
168             return satelliteList;
169         }
170
171         /// <summary>
172         /// The constructor of GpsSatellite class.
173         /// <param name="locator"> Locator object initilized using Gps.</param>
174         /// </summary>
175         public GpsSatellite(Locator locator)
176         {
177             Log.Info(Globals.LogTag, "Calling GpsSatellite constructor");
178             LocationType method = locator.LocationType;
179             if (method.Equals(LocationType.Gps) || method.Equals(LocationType.Hybrid))
180             {
181                 _locator = locator;
182                 _handle = _locator.GetHandle();
183             }
184             else
185             {
186                 Log.Error(Globals.LogTag, "Error constructing GpsSatellite class");
187                 throw LocationErrorFactory.ThrowLocationException((int)LocationError.InvalidParameter);
188             }
189         }
190
191         /// <summary>
192         /// (event) SatelliteStatusUpdated is raised whenever satellite information is updated.
193         /// The callback will be invoked periodically (every Interval seconds).
194         /// </summary>
195         public event EventHandler<SatelliteStatusChangedEventArgs> SatelliteStatusUpdated
196         {
197             add
198             {
199                 Log.Info(Globals.LogTag, "SatelliteStatusUpdated Add called");
200                 if (_satelliteStatusChanged == null)
201                 {
202                     Log.Info(Globals.LogTag, "SetSatelliteStatusChangeCallback called");
203                     SetSatelliteStatusChangeCallback();
204                 }
205                 _satelliteStatusChanged += value;
206             }
207             remove
208             {
209                 Log.Info(Globals.LogTag, "SatelliteStatusUpdated remoove called");
210                 _satelliteStatusChanged -= value;
211                 if (_satelliteStatusChanged == null)
212                 {
213                     Log.Info(Globals.LogTag, "UnSetSatelliteStatusChangeCallback called");
214                     UnSetSatelliteStatusChangeCallback();
215                 }
216             }
217         }
218
219         private void SetSatelliteStatusChangeCallback()
220         {
221             Log.Info(Globals.LogTag, "SetSatelliteStatusChangeCallback");
222             GCHandle handle = GCHandle.Alloc(this);
223             int ret = Interop.GpsSatellite.SetSatelliteStatusChangedCallback(_handle, SatelliteStatusChangedCallback, _interval, GCHandle.ToIntPtr(handle));
224             if (((LocationError)ret != LocationError.None))
225             {
226                 Log.Error(Globals.LogTag, "Error in setting satellite status changed callback," + (LocationError)ret);
227                 throw LocationErrorFactory.ThrowLocationException(ret);
228             }
229         }
230
231         private void UnSetSatelliteStatusChangeCallback()
232         {
233             Log.Info(Globals.LogTag, "UnSetSatelliteStatusChangeCallback");
234             int ret = Interop.GpsSatellite.UnSetSatelliteStatusChangedCallback(_handle);
235             if (((LocationError)ret != LocationError.None))
236             {
237                 Log.Error(Globals.LogTag, "Error in Getting Unsetting satellite status changed callback," + (LocationError)ret);
238                 throw LocationErrorFactory.ThrowLocationException(ret);
239             }
240         }
241
242         private void SatelliteStatusChangedCallback(uint numActive, uint numInView, int timestamp, IntPtr userData)
243         {
244             Log.Info(Globals.LogTag, "Inside SatelliteStatusChangedCallback");
245             DateTime timeStamp = DateTime.Now;
246
247             if (timestamp != 0)
248             {
249                 DateTime start = DateTime.SpecifyKind(new DateTime(1970, 1, 1).AddSeconds(timestamp), DateTimeKind.Utc);
250                 timeStamp = start.ToLocalTime();
251             }
252
253             _satelliteStatusChanged?.Invoke(_handle, new SatelliteStatusChangedEventArgs(numActive, numInView, timeStamp));
254         }
255     }
256
257     /// <summary>
258     /// A class which contains the information of the Satellite under consideration.
259     /// </summary>
260     public class SatelliteInformation
261     {
262         /// <summary>
263         /// Class Constructor for SatelliteInformation class.
264         /// </summary>
265         /// <param name="azimuth"> The azimuth value of the satellite in degrees.</param>
266         /// <param name="elevation"> The elevation of the satellite in meters.</param>
267         /// <param name="prn"> The Prn value of the satellite.</param>
268         /// <param name="snr"> The SNR value of the satellite in dB.</param>
269         /// <param name="isActive"> The flag signaling if satellite is in use.</param>
270         public SatelliteInformation(uint azimuth, uint elevation, uint prn, uint snr, bool isActive)
271         {
272             Azimuth = azimuth;
273             Elevation = elevation;
274             Prn = prn;
275             Snr = snr;
276             Active = isActive;
277         }
278
279         /// <summary>
280         /// The Azimuth information of the Satellite.
281         /// </summary>
282         public uint Azimuth { get; private set; }
283
284         /// <summary>
285         /// The Elevation information of the Satellite.
286         /// </summary>
287         public uint Elevation { get; private set; }
288
289         /// <summary>
290         /// The PRN of the Satellite.
291         /// </summary>
292         public uint Prn { get; private set; }
293
294         /// <summary>
295         /// The SNR of the Satellite.
296         /// </summary>
297         public uint Snr { get; private set; }
298
299         /// <summary>
300         /// The operational status of the Satellite.
301         /// </summary>
302         public bool Active { get; private set; }
303     }
304 }