Windows Mobile下GPS管理软件NavsGo之GPS侦测功能的开发

简介:

简述

在上篇文章 Windows Mobile下GPS管理软件NavsGo之GPS监控功能的开发 概述了NavsGo项目以及讲述了GPS监控功能的开发,GPS.net控件的使用,这篇文章讲述侦测功能的开发。

关于

所谓GPS侦测功能就是扫描手机上所有可用的GPS设备(available GPS devices),把各个设备运行状态展现给用户,如果发现问题,通过友善的方式提示用户如果解决设备连通性问题。这些建议包括启动GPS设备,修改GPS Intermediate Driver的配置,启动蓝牙GPS设备等等。

实现

这个模块是GPS.net 作者jperson的一个demo程序,原程序可以到 GPS Diagnostics for .NET 下载。我做了少量修改加到NavsGo里面来了。

gpsdiagnostics2

发现/检测功能(Detection)

 gpsdiagnostics3 

发现功能在上篇文章讲过,通过注册静态事件,然后回调相应的处理函数。

/* Hook into GPS device detection events.  These events are static, allowing them to
* be easily sunk by any other class or form.
*/
Devices.DeviceDetectionStarted += new EventHandler(Devices_DeviceDetectionStarted);
Devices.DeviceDetectionCompleted += new EventHandler(Devices_DeviceDetectionCompleted);
Devices.DeviceDetected += new EventHandler<DeviceEventArgs>(Devices_DeviceDetected);
Devices.DeviceDetectionAttempted += new EventHandler<DeviceEventArgs>(Devices_DeviceDetectionAttempted);
Devices.DeviceDetectionAttemptFailed += new EventHandler<DeviceDetectionExceptionEventArgs>(Devices_DeviceDetectionAttemptFailed);

由于GPS.net是开源的,我们这次钻到他的源代码看看Detection的实现逻辑。

启动发现功能是在 Devices.BeginDetection() 函数里面。

        public static void BeginDetection()
{
// Start detection on another thread.
if (_IsDetectionInProgress)
return;

// Signal that detection is in progress
_IsDetectionInProgress = true;

// Start a thread for managing detection
_DetectionThread = new Thread(new ThreadStart(DetectionThreadProc));
_DetectionThread.Name = "GPS.NET Device Detector (http://www.geoframeworks.com)";
_DetectionThread.IsBackground = true;

#if !PocketPC
// Do detection in the background
_DetectionThread.Priority = ThreadPriority.Lowest;
#endif

_DetectionThread.Start();

#if PocketPC
// Signal that the thread is alive (no Thread.IsAlive on the CF :P)
_IsDetectionThreadAlive = true;
#endif
}

启动发现过程,系统会启动一个线程调用DetectionThreadProc()进行发现。下面是DetectionThreadProc()函数。

        private static void DetectionThreadProc()
{
try
{
// Signal that it started
OnDeviceDetectionStarted();

// Monitor this thread up to the timeout, then quit
ThreadPool.QueueUserWorkItem(new WaitCallback(DetectionThreadProcWatcher));

#if PocketPC
// Are we using the GPS Intermediate Driver?
GpsIntermediateDriver gpsid = GpsIntermediateDriver.Current;

// Is the GPSID supported?
if (gpsid != null)
{
// Yes. Test it to be sure
gpsid.BeginDetection();

// Wait for one device to get detected. Was it confirmed?
if (gpsid.WaitForDetection())
{
// Yes. If we only need one device, exit
if(_IsOnlyFirstDeviceDetected)
return;
}
}

#endif
/* If we get here, the GPS Intermediate Driver is not responding! */

int count;

#region Detect Bluetooth devices

// Is Bluetooth supported and turned on?
if (IsBluetoothSupported && IsBluetoothEnabled)
{
// Start bluetooth detection for each device
count = _BluetoothDevices.Count;
for (int index = 0; index < count; index++)
_BluetoothDevices[index].BeginDetection();
}

#endregion

#region
Detect serial GPS devices

if (AllowSerialConnections)
{
count = SerialDevices.Count;
for (int index = 0; index < count; index++)
_SerialDevices[index].BeginDetection();

/* If we're performing "exhaustive" detection, ports are scanned
* even if there's no evidence they actually exist. This can happen in rare
* cases, such as when a PCMCIA GPS device is plugged in and fails to create
* a registry entry.
*/

if (_AllowExhaustiveSerialPortScanning)
{
// Try all ports from COM0: up to the maximum port number
for (int index = 0; index < _MaximumSerialPortNumber; index++)
{
// Is this port already being checked?
bool alreadyBeingScanned = false;
for (int existingIndex = 0; existingIndex < _SerialDevices.Count; existingIndex++)
{
if (_SerialDevices[existingIndex].PortNumber.Equals(index))
{
// Yes. Don't test it again
alreadyBeingScanned = true;
break;
}

// If it's already being scanned, stop
if (alreadyBeingScanned)
break;
}

// If it's already being scanned, skip to the next port
if (alreadyBeingScanned)
continue;

// This is a new device. Scan it
SerialDevice exhaustivePort = new SerialDevice("COM" + index.ToString() + ":");
exhaustivePort.BeginDetection();
}
}
}

#endregion

#region
Discover new Bluetooth devices

// Is Bluetooth supported and turned on?
if (IsBluetoothSupported && IsBluetoothEnabled)
{
/* NOTE: For mobile devices, only one connection is allowed at a time.
* As a result, we use a static SyncRoot to ensure that connections
* and discovery happens in serial. For this reason, we will not attempt
* to discover devices until *after* trying to detect existing ones.
*/

#if PocketPC
// Wait for existing devices to be tested
count = _BluetoothDevices.Count;
for (int index = 0; index < count; index++)
{
// Complete detection for this device
_BluetoothDevices[index].WaitForDetection();
}
#endif

// Begin searching for brand new devices
BluetoothDevice.DiscoverDevices(true);

// Block until that search completes
BluetoothDevice.DeviceDiscoveryThread.Join();
}

#endregion

#region
Wait for all devices to finish detection

/* A list holds the wait handles of devices being detected. When it is empty,
* detection has finished on all threads.
*/
while (_CurrentlyDetectingWaitHandles.Count != 0)
{
try
{
ManualResetEvent handle = _CurrentlyDetectingWaitHandles[0];
#if !PocketPC
if (!handle.SafeWaitHandle.IsClosed)
#endif
handle.WaitOne();
}
catch (ObjectDisposedException)
{
/* In some rare cases a device will get disposed of and nulled out.
* So, regardless of what happens we can remove the item.
*/
}
finally
{
_CurrentlyDetectingWaitHandles.RemoveAt(0);
}
}

#endregion

#if
PocketPC
#region Reconfigure the GPS Intermediate Driver (if necessary)

/* The GPS Intermediate Driver may not have the right "Program Port" (actual GPS port/baud rate)
* settings. Now that detection has completed, let's see if the GPSID needs configuration.
* If it is flagged as NOT being a GPS device, then it could not connect. In this case, let's
* find the most reliable serial device and use it.
*/
if (
// Is the GPSID supported?
gpsid != null
// Are we allowed to configure it?
&& gpsid.IsAutomaticallyConfigured
// Is it currently NOT identified as a GPS device? (connections failed)
&& !gpsid.IsGpsDevice)
{
// Look through each confirmed GPS device
count = _GpsDevices.Count;
for (int index = 0; index < count; index++)
{
// Is it a serial device?
SerialDevice device = _GpsDevices[index] as SerialDevice;
if (device == null)
continue;

// Yes. Use it!
try
{
gpsid.HardwarePort = device;

// The GPSID is now working
Add(gpsid);
}
catch (Exception ex)
{
// Notify of the error gracefully
OnDeviceDetectionAttemptFailed(new DeviceDetectionException(gpsid, ex));
}

// That's the best device, so quit
break;
}
}

#endregion
#endif

// Signal completion
OnDeviceDetectionCompleted();
}
catch (ThreadAbortException)
{
#region Abort detection for all devices
#if PocketPC
// Stop detection for the GPSID
if(GpsIntermediateDriver.Current != null)
GpsIntermediateDriver.Current.CancelDetection();
#endif

// Stop detection for each Bluetooth device
for (int index = 0; index < _BluetoothDevices.Count; index++)
_BluetoothDevices[index].CancelDetection();

// Stop detection for each serial device
for (int index = 0; index < _SerialDevices.Count; index++)
_SerialDevices[index].CancelDetection();

#endregion

// Wait for all the threads to die. Just... sit and watch. And wait.
while (_CurrentlyDetectingWaitHandles.Count != 0)
{
try { _CurrentlyDetectingWaitHandles[0].WaitOne(); }
catch { }
finally { _CurrentlyDetectingWaitHandles.RemoveAt(0); }
}

// Signal the cancellation
if (DeviceDetectionCanceled != null)
DeviceDetectionCanceled(null, EventArgs.Empty);
}
finally
{
// Detection is no longer in progress
_DetectionCompleteWaitHandle.Set();
_CurrentlyDetectingWaitHandles.Clear(); // <-- Already empty?
_IsDetectionInProgress = false;

#if PocketPC
// Signal that the thread is alive (no Thread.IsAlive on the CF :P)
_IsDetectionThreadAlive = false;
#endif
}
}

DetectionThreadProc()负责整个发现过程,是一个很长的函数,有必要重构一下,把它分离(split)成几个小函数。他的处理逻辑是,检测超时,一旦发现发现过程超时,就好中途停止所有的处理。然后按顺序检测设备。检测的设备包括GPS Intermediate Driver设备(GpsIntermediateDriver),串口设备(SerialDevice)和蓝牙设备(BluetoothDevice)。支持的设备类图如下:

gpsdiagnostics1

所有设备都是继承于父类Device,这样可以通过容器类Devices类统一管理所有设备的对象,通过多态的方式去调用各个具体设备的处理函数来实现发现过程。对于每个独立的设备,他们统一发现流程是启动一个线程,然后试图打开该设备,如果超时,认为设备不可用,如果在超时之前读取到数据就分析输出数据,如果数据是标准的NMEA就认为这个是GPS设备。NMEA相关的可以参考.NET Compact Framework下的GPS NMEA data数据分析

GPS Intermediate Driver设备的发现

发现过程首先检查的是GPS Intermediate Driver设备。在Windows Mobile 5+和Wince 6+的系统下一般都内嵌GPS Intermediate Driver,关于GPS Intermediate Driver的开发可以参考30 Days of .NET [Windows Mobile Applications] - Day 03: GPS Compass(GPS指南针) 。我计划增加 GPS Intermediate Driver管理功能到NavsGo里面,后续会把GPS Intermediate Driver管理的开发写下来。

已经配对了的蓝牙设备的发现

检测完GPS Intermediate Driver设备,就开始检查已经配对了的蓝牙设备(Paired Bluetooth Devices),这些已经配对了的蓝牙设备保存在注册表HKEY_LOCAL_MACHINE\SOFTWARE\GeoFrameworks\GPS.NET\3.0\Devices\Bluetooth\中。关于蓝牙配对也可以参考一下 .NET Compact Framework下的Bluetooth设备的配对

软件意义上的串口设备的发现

检测完已经配对了的蓝牙设备后,就开始检查串口设备,这里的串口设备是指软件意义上的串口,不是仅仅只通过硬件串口线连接的设备。由于 NMEA 0183 的规范规定GPS设备的联通性通过波特率(Baud rate)为4800的串口设备。所以GPS设备厂商尽管使用其他联通方式,但是都可以转成软件上的串口设备。例如USB GPS设备可以通过驱动转成串口设备,蓝牙可以建立虚拟串口,关于虚拟串口可以参考 .NET Compact Framework下的Bluetooth开发 之 Bluetooth Virtual Serial Port。总的来说,这里软件意义上的串口,真实的设备可能是 真正的串口线,USB,PCMCIA,蓝牙,红外等。

新蓝牙设备的发现

做完GPS Intermediate Driver设备,已经配对了的蓝牙设备和软件意义上的串口的发现流程后,进入了对新蓝牙设备的发现过程,这些蓝牙设备是不在已经配对了的蓝牙设备的范畴里面的,是手机周边新的蓝牙设备。由于手机对蓝牙的通信只能是一对一,也就是一个时间内一台手机只能和一个蓝牙设备进行通信,所以在发现新蓝牙设备之前,需要先等待已经配对了的蓝牙设备的发现过程的结束。关于蓝牙设备的开发和发现可以参考一下 .NET Compact Framework下的Bluetooth开发 之 Windows Embedded Source Tools for Bluetooth 和 .NET Compact Framework下的Bluetooth开发 之 32feet.NET

GPS Intermediate Driver设备配置

一般来说移动设备都是通过GPS Intermediate Driver设备来对外部GPS程序提供服务的,有时候尽管GPS Intermediate Driver设备存在,并在运行,但是由于配置不正确也会导致外部GPS程序未能正确连接和使用GPS设备。所以最后一步是检查GPS Intermediate Driver设备的配置情况。我计划也在NavsGo增加GPS Intermediate Driver设备的配置管理功能。

最后的最后是清理所有资源,一个好的程序的习惯。

 

建议功能

gpsdiagnostics4

gpsdiagnostics6

发现功能实现了整个GPS诊断模块的核心,建议功能也就是呈现发现功能缓存的信息。建议功能实现在SummaryForm和DeviceForm两个类里面,SummaryForm提示建议,而DeviceForm现实某个设备的检查情况。

建议功能的流程是,判断GPS Intermediate Driver设备是否可用,如果不可用可能是硬件端口配置错误,建议把可用的串口端口配置为GPS Intermediate Driver的硬件端口,如果没有可用的串口端口,建议使用蓝牙设备。

日志功能

 

gpsdiagnostics5

GPS.net提供日志发送功能,把设备发现和检查信息发送到服务器,方便开发者改进。这个功能很简单。


源码请看 Windows Mobile下GPS管理软件NavsGo之GPS监控功能的开发




    本文转自Jake Lin博客园博客,原文链接:http://www.cnblogs.com/procoder/archive/2009/08/21/1551155.html,如需转载请自行联系原作者


相关文章
|
1月前
|
人工智能 JavaScript 网络安全
ToB项目身份认证AD集成(三完):利用ldap.js实现与windows AD对接实现用户搜索、认证、密码修改等功能 - 以及针对中文转义问题的补丁方法
本文详细介绍了如何使用 `ldapjs` 库在 Node.js 中实现与 Windows AD 的交互,包括用户搜索、身份验证、密码修改和重置等功能。通过创建 `LdapService` 类,提供了与 AD 服务器通信的完整解决方案,同时解决了中文字段在 LDAP 操作中被转义的问题。
|
1月前
|
监控 关系型数据库 MySQL
PowerShell 脚本编写 :自动化Windows 开发工作流程
PowerShell 脚本编写 :自动化Windows 开发工作流程
39 0
|
2月前
|
Linux Android开发 iOS开发
Windows平台RTSP|RTMP播放器如何实现实时录像功能
Windows平台RTSP、RTMP播放器实时录像接口设计,实际上,除了Windows平台,我们Linux、Android、iOS平台也是一样的设计,单纯的录像模块,如果做的全面,也不是一两个接口可以搞定的
|
1月前
|
Ubuntu Linux Python
如何利用wsl-Ubuntu里conda用来给Windows的PyCharm开发
如何在WSL(Windows Subsystem for Linux)的Ubuntu环境中使用conda虚拟环境来为Windows上的PyCharm开发设置Python解释器。
88 0
|
2月前
|
XML JSON C#
有哪些让你「 爽到爆炸 」的 Windows 软件?
有哪些让你「 爽到爆炸 」的 Windows 软件?
|
2月前
|
存储 安全 程序员
Windows任务管理器开发原理与实现
Windows任务管理器开发原理与实现
|
2月前
|
Linux 网络虚拟化 Windows
ccproxy windows上用的代理软件(类似linux系统上的squid)
ccproxy windows上用的代理软件(类似linux系统上的squid)
|
3月前
|
开发者 C# Windows
WPF与游戏开发:当桌面应用遇见游戏梦想——利用Windows Presentation Foundation打造属于你的2D游戏世界,从环境搭建到代码实践全面解析新兴开发路径
【8月更文挑战第31天】随着游戏开发技术的进步,WPF作为.NET Framework的一部分,凭借其图形渲染能力和灵活的UI设计,成为桌面游戏开发的新选择。本文通过技术综述和示例代码,介绍如何利用WPF进行游戏开发。首先确保安装最新版Visual Studio并创建WPF项目。接着,通过XAML设计游戏界面,并在C#中实现游戏逻辑,如玩家控制和障碍物碰撞检测。示例展示了创建基本2D游戏的过程,包括角色移动和碰撞处理。通过本文,WPF开发者可更好地理解并应用游戏开发技术,创造吸引人的桌面游戏。
187 0
|
3月前
|
存储 开发者 C#
WPF与邮件发送:教你如何在Windows Presentation Foundation应用中无缝集成电子邮件功能——从界面设计到代码实现,全面解析邮件发送的每一个细节密武器!
【8月更文挑战第31天】本文探讨了如何在Windows Presentation Foundation(WPF)应用中集成电子邮件发送功能,详细介绍了从创建WPF项目到设计用户界面的全过程,并通过具体示例代码展示了如何使用`System.Net.Mail`命名空间中的`SmtpClient`和`MailMessage`类来实现邮件发送逻辑。文章还强调了安全性和错误处理的重要性,提供了实用的异常捕获代码片段,旨在帮助WPF开发者更好地掌握邮件发送技术,提升应用程序的功能性与用户体验。
67 0
|
3月前
|
API C# Shell
WPF与Windows Shell完美融合:深入解析文件系统操作技巧——从基本文件管理到高级Shell功能调用,全面掌握WPF中的文件处理艺术
【8月更文挑战第31天】Windows Presentation Foundation (WPF) 是 .NET Framework 的关键组件,用于构建 Windows 桌面应用程序。WPF 提供了丰富的功能来创建美观且功能强大的用户界面。本文通过问题解答的形式,探讨了如何在 WPF 应用中集成 Windows Shell 功能,并通过具体示例代码展示了文件系统的操作方法,包括列出目录下的所有文件、创建和删除文件、移动和复制文件以及打开文件夹或文件等。
79 0
下一篇
无影云桌面