博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Windows Mobile下GPS管理软件NavsGo之GPS侦测功能的开发
阅读量:5749 次
发布时间:2019-06-18

本文共 9804 字,大约阅读时间需要 32 分钟。

简述

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

关于

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

实现

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

发现/检测功能(Detection)

  

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

/* 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
(Devices_DeviceDetected); Devices.DeviceDetectionAttempted += new EventHandler
(Devices_DeviceDetectionAttempted); Devices.DeviceDetectionAttemptFailed += new EventHandler
(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)。支持的设备类图如下:

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

GPS Intermediate Driver设备的发现

发现过程首先检查的是GPS Intermediate Driver设备。在Windows Mobile 5+和Wince 6+的系统下一般都内嵌GPS Intermediate Driver,关于GPS Intermediate Driver的开发可以参考 。我计划增加 GPS Intermediate Driver管理功能到NavsGo里面,后续会把GPS Intermediate Driver管理的开发写下来。

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

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

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

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

新蓝牙设备的发现

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

GPS Intermediate Driver设备配置

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

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

 

建议功能

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

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

日志功能

 

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

源码请看 

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

你可能感兴趣的文章
开始第一个Python程序!
查看>>
Google 或强制 OEM 预装 20 款应用,给你一个不Root的理由
查看>>
我的友情链接
查看>>
双边过滤器(Bilateral filter)
查看>>
Android图形显示系统——下层显示4:图层合成上(合成原理与3D合成)
查看>>
Windows 10 技术预览
查看>>
Tomcat http跳转https
查看>>
一个自动布署.net网站的bat批处理实例
查看>>
tomcat 安装
查看>>
AIX:物理卷及有关概念
查看>>
我的友情链接
查看>>
Centos6.6安装选包及基础场景说明
查看>>
《从零开始学Swift》学习笔记(Day 61)——Core Foundation框架之内存管理
查看>>
java基础面试题-1
查看>>
深克隆与序列化效率的比较
查看>>
C++入门篇01
查看>>
3.python开发语言的特点
查看>>
Nginx使用Proxy_cache实现服务器端静态文件缓存
查看>>
lamp+nginx代理+discuz+wordpress+phpmyadmin搭建一
查看>>
nagios监控使用139邮箱报警
查看>>