PageRenderTime 44ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/windows-phone-7/templates/standalone/Plugins/Compass.cs

https://bitbucket.org/leispire/phonegap
C# | 362 lines | 224 code | 51 blank | 87 comment | 20 complexity | 78ae1b0eaf9e6802213f3ae37ced0145 MD5 | raw file
  1. /*
  2. Licensed under the Apache License, Version 2.0 (the "License");
  3. you may not use this file except in compliance with the License.
  4. You may obtain a copy of the License at
  5. http://www.apache.org/licenses/LICENSE-2.0
  6. Unless required by applicable law or agreed to in writing, software
  7. distributed under the License is distributed on an "AS IS" BASIS,
  8. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  9. See the License for the specific language governing permissions and
  10. limitations under the License.
  11. */
  12. using System;
  13. using System.Net;
  14. using System.Windows;
  15. using System.Windows.Controls;
  16. using System.Windows.Documents;
  17. using System.Windows.Ink;
  18. using System.Windows.Input;
  19. using System.Windows.Media;
  20. using System.Windows.Media.Animation;
  21. using System.Windows.Shapes;
  22. using DeviceCompass = Microsoft.Devices.Sensors.Compass;
  23. using System.Windows.Threading;
  24. using System.Runtime.Serialization;
  25. using System.Collections.Generic;
  26. using System.Diagnostics;
  27. using System.Globalization;
  28. using System.Threading;
  29. using Microsoft.Devices.Sensors;
  30. namespace WPCordovaClassLib.Cordova.Commands
  31. {
  32. public class Compass : BaseCommand
  33. {
  34. #region Static members
  35. /// <summary>
  36. /// Status of listener
  37. /// </summary>
  38. private static int currentStatus;
  39. /// <summary>
  40. /// Id for get getCompass method
  41. /// </summary>
  42. private static string getCompassId = "getCompassId";
  43. /// <summary>
  44. /// Compass
  45. /// </summary>
  46. private static DeviceCompass compass = new DeviceCompass();
  47. /// <summary>
  48. /// Listeners for callbacks
  49. /// </summary>
  50. private static Dictionary<string, Compass> watchers = new Dictionary<string, Compass>();
  51. #endregion
  52. #region Status codes
  53. public const int Stopped = 0;
  54. public const int Starting = 1;
  55. public const int Running = 2;
  56. public const int ErrorFailedToStart = 4;
  57. public const int Not_Supported = 20;
  58. /*
  59. * // Capture error codes
  60. CompassError.COMPASS_INTERNAL_ERR = 0;
  61. CompassError.COMPASS_NOT_SUPPORTED = 20;
  62. * */
  63. #endregion
  64. #region CompassOptions class
  65. /// <summary>
  66. /// Represents Accelerometer options.
  67. /// </summary>
  68. [DataContract]
  69. public class CompassOptions
  70. {
  71. /// <summary>
  72. /// How often to retrieve the Acceleration in milliseconds
  73. /// </summary>
  74. [DataMember(IsRequired = false, Name = "frequency")]
  75. public int Frequency { get; set; }
  76. /// <summary>
  77. /// The change in degrees required to initiate a watchHeadingFilter success callback.
  78. /// </summary>
  79. [DataMember(IsRequired = false, Name = "filter")]
  80. public int Filter { get; set; }
  81. /// <summary>
  82. /// Watcher id
  83. /// </summary>
  84. [DataMember(IsRequired = false, Name = "id")]
  85. public string Id { get; set; }
  86. }
  87. #endregion
  88. /// <summary>
  89. /// Time the value was last changed
  90. /// </summary>
  91. //private DateTime lastValueChangedTime;
  92. /// <summary>
  93. /// Accelerometer options
  94. /// </summary>
  95. private CompassOptions compassOptions;
  96. //bool isDataValid;
  97. //bool calibrating = false;
  98. public Compass()
  99. {
  100. }
  101. /// <summary>
  102. /// Formats current coordinates into JSON format
  103. /// </summary>
  104. /// <returns>Coordinates in JSON format</returns>
  105. private string GetHeadingFormatted(CompassReading reading)
  106. {
  107. // NOTE: timestamp is generated on the JS side, to avoid issues with format conversions
  108. string result = String.Format("\"magneticHeading\":{0},\"headingAccuracy\":{1},\"trueHeading\":{2}",
  109. reading.MagneticHeading.ToString("0.0", CultureInfo.InvariantCulture),
  110. reading.HeadingAccuracy.ToString("0.0", CultureInfo.InvariantCulture),
  111. reading.TrueHeading.ToString("0.0", CultureInfo.InvariantCulture));
  112. return "{" + result + "}";
  113. }
  114. public void getHeading(string options)
  115. {
  116. if (!DeviceCompass.IsSupported)
  117. {
  118. DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, "{code:" + Not_Supported + "}"));
  119. }
  120. else
  121. {
  122. //if (compass == null)
  123. //{
  124. // // Instantiate the compass.
  125. // compass = new DeviceCompass();
  126. // compass.TimeBetweenUpdates = TimeSpan.FromMilliseconds(40);
  127. // compass.CurrentValueChanged += new EventHandler<Microsoft.Devices.Sensors.SensorReadingEventArgs<Microsoft.Devices.Sensors.CompassReading>>(compass_CurrentValueChanged);
  128. // compass.Calibrate += new EventHandler<Microsoft.Devices.Sensors.CalibrationEventArgs>(compass_Calibrate);
  129. //}
  130. //compass.Start();
  131. }
  132. try
  133. {
  134. if (currentStatus != Running)
  135. {
  136. lock (compass)
  137. {
  138. compass.CurrentValueChanged += compass_SingleHeadingValueChanged;
  139. compass.Start();
  140. this.SetStatus(Starting);
  141. }
  142. long timeout = 2000;
  143. while ((currentStatus == Starting) && (timeout > 0))
  144. {
  145. timeout = timeout - 100;
  146. Thread.Sleep(100);
  147. }
  148. if (currentStatus != Running)
  149. {
  150. DispatchCommandResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, ErrorFailedToStart));
  151. return;
  152. }
  153. }
  154. lock (compass)
  155. {
  156. compass.CurrentValueChanged -= compass_SingleHeadingValueChanged;
  157. if (watchers.Count < 1)
  158. {
  159. compass.Stop();
  160. this.SetStatus(Stopped);
  161. }
  162. }
  163. }
  164. catch (UnauthorizedAccessException)
  165. {
  166. DispatchCommandResult(new PluginResult(PluginResult.Status.ILLEGAL_ACCESS_EXCEPTION, ErrorFailedToStart));
  167. }
  168. catch (Exception)
  169. {
  170. DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, ErrorFailedToStart));
  171. }
  172. }
  173. void compass_SingleHeadingValueChanged(object sender, Microsoft.Devices.Sensors.SensorReadingEventArgs<CompassReading> e)
  174. {
  175. this.SetStatus(Running);
  176. if (compass.IsDataValid)
  177. {
  178. // trueHeading :: The heading in degrees from 0 - 359.99 at a single moment in time.
  179. // magneticHeading:: The heading relative to the geographic North Pole in degrees 0 - 359.99 at a single moment in time.
  180. // A negative value indicates that the true heading could not be determined.
  181. // headingAccuracy :: The deviation in degrees between the reported heading and the true heading.
  182. //rawMagnetometerReading = e.SensorReading.MagnetometerReading;
  183. //Debug.WriteLine("Compass Result :: " + GetHeadingFormatted(e.SensorReading));
  184. PluginResult result = new PluginResult(PluginResult.Status.OK, GetHeadingFormatted(e.SensorReading));
  185. DispatchCommandResult(result);
  186. }
  187. }
  188. /// <summary>
  189. /// Starts listening for compass sensor
  190. /// </summary>
  191. /// <returns>status of listener</returns>
  192. private int start()
  193. {
  194. if ((currentStatus == Running) || (currentStatus == Starting))
  195. {
  196. return currentStatus;
  197. }
  198. try
  199. {
  200. lock (compass)
  201. {
  202. watchers.Add(getCompassId, this);
  203. compass.CurrentValueChanged += watchers[getCompassId].compass_CurrentValueChanged;
  204. compass.Start();
  205. this.SetStatus(Starting);
  206. }
  207. }
  208. catch (Exception)
  209. {
  210. this.SetStatus(ErrorFailedToStart);
  211. }
  212. return currentStatus;
  213. }
  214. public void startWatch(string options)
  215. {
  216. if (!DeviceCompass.IsSupported)
  217. {
  218. DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, Not_Supported));
  219. }
  220. try
  221. {
  222. compassOptions = JSON.JsonHelper.Deserialize<CompassOptions>(options);
  223. }
  224. catch (Exception ex)
  225. {
  226. this.DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION, ex.Message));
  227. return;
  228. }
  229. if (string.IsNullOrEmpty(compassOptions.Id))
  230. {
  231. this.DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
  232. return;
  233. }
  234. try
  235. {
  236. lock (compass)
  237. {
  238. watchers.Add(compassOptions.Id, this);
  239. compass.CurrentValueChanged += watchers[compassOptions.Id].compass_CurrentValueChanged;
  240. compass.Start();
  241. this.SetStatus(Starting);
  242. }
  243. }
  244. catch (Exception)
  245. {
  246. this.DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, ErrorFailedToStart));
  247. return;
  248. }
  249. }
  250. public void stopWatch(string options)
  251. {
  252. try
  253. {
  254. compassOptions = JSON.JsonHelper.Deserialize<CompassOptions>(options);
  255. }
  256. catch (Exception ex)
  257. {
  258. this.DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION, ex.Message));
  259. return;
  260. }
  261. if (string.IsNullOrEmpty(compassOptions.Id))
  262. {
  263. this.DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
  264. return;
  265. }
  266. if (currentStatus != Stopped)
  267. {
  268. lock (compass)
  269. {
  270. Compass watcher = watchers[compassOptions.Id];
  271. compass.CurrentValueChanged -= watcher.compass_CurrentValueChanged;
  272. watchers.Remove(compassOptions.Id);
  273. watcher.Dispose();
  274. }
  275. }
  276. this.SetStatus(Stopped);
  277. this.DispatchCommandResult();
  278. }
  279. void compass_Calibrate(object sender, Microsoft.Devices.Sensors.CalibrationEventArgs e)
  280. {
  281. //throw new NotImplementedException();
  282. // TODO: pass calibration error to JS
  283. }
  284. void compass_CurrentValueChanged(object sender, Microsoft.Devices.Sensors.SensorReadingEventArgs<CompassReading> e)
  285. {
  286. this.SetStatus(Running);
  287. if (compass.IsDataValid)
  288. {
  289. // trueHeading :: The heading in degrees from 0 - 359.99 at a single moment in time.
  290. // magneticHeading:: The heading relative to the geographic North Pole in degrees 0 - 359.99 at a single moment in time.
  291. // A negative value indicates that the true heading could not be determined.
  292. // headingAccuracy :: The deviation in degrees between the reported heading and the true heading.
  293. //rawMagnetometerReading = e.SensorReading.MagnetometerReading;
  294. //Debug.WriteLine("Compass Result :: " + GetHeadingFormatted(e.SensorReading));
  295. PluginResult result = new PluginResult(PluginResult.Status.OK, GetHeadingFormatted(e.SensorReading));
  296. result.KeepCallback = true;
  297. DispatchCommandResult(result);
  298. }
  299. }
  300. /// <summary>
  301. /// Sets current status
  302. /// </summary>
  303. /// <param name="status">current status</param>
  304. private void SetStatus(int status)
  305. {
  306. currentStatus = status;
  307. }
  308. }
  309. }