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里面来了。
发现/检测功能(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 += newEventHandler(Devices_DeviceDetectionStarted);Devices.DeviceDetectionCompleted += newEventHandler(Devices_DeviceDetectionCompleted);Devices.DeviceDetected += newEventHandler<DeviceEventArgs>(Devices_DeviceDetected);Devices.DeviceDetectionAttempted += newEventHandler<DeviceEventArgs>(Devices_DeviceDetectionAttempted);Devices.DeviceDetectionAttemptFailed += newEventHandler<DeviceDetectionExceptionEventArgs>(Devices_DeviceDetectionAttemptFailed);
由于GPS.net是开源的,我们这次钻到他的源代码看看Detection的实现逻辑。
启动发现功能是在 Devices.BeginDetection() 函数里面。
public static voidBeginDetection() {// Start detection on another thread.if(_IsDetectionInProgress)return; // Signal that detection is in progress_IsDetectionInProgress = true; // Start a thread for managing detection_DetectionThread = newThread(newThreadStart(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(); #ifPocketPC// Signal that the thread is alive (no Thread.IsAlive on the CF :P)_IsDetectionThreadAlive = true;#endif}
启动发现过程,系统会启动一个线程调用DetectionThreadProc()进行发现。下面是DetectionThreadProc()函数。
private static voidDetectionThreadProc() {try{// Signal that it startedOnDeviceDetectionStarted(); // Monitor this thread up to the timeout, then quitThreadPool.QueueUserWorkItem(newWaitCallback(DetectionThreadProcWatcher)); #ifPocketPC // Are we using the GPS Intermediate Driver?GpsIntermediateDrivergpsid = GpsIntermediateDriver.Current; // Is the GPSID supported?if(gpsid != null) {// Yes. Test it to be suregpsid.BeginDetection(); // Wait for one device to get detected. Was it confirmed?if(gpsid.WaitForDetection()) {// Yes. If we only need one device, exitif(_IsOnlyFirstDeviceDetected)return; } } #endif/* If we get here, the GPS Intermediate Driver is not responding! */intcount; #regionDetect Bluetooth devices // Is Bluetooth supported and turned on?if(IsBluetoothSupported && IsBluetoothEnabled) {// Start bluetooth detection for each devicecount = _BluetoothDevices.Count;for(intindex = 0; index < count; index++) _BluetoothDevices[index].BeginDetection(); } #endregion #regionDetect serial GPS devices if(AllowSerialConnections) { count = SerialDevices.Count;for(intindex = 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 numberfor(intindex = 0; index < _MaximumSerialPortNumber; index++) {// Is this port already being checked?boolalreadyBeingScanned = false;for(intexistingIndex = 0; existingIndex < _SerialDevices.Count; existingIndex++) {if(_SerialDevices[existingIndex].PortNumber.Equals(index)) {// Yes. Don't test it againalreadyBeingScanned = true;break; } // If it's already being scanned, stopif(alreadyBeingScanned)break; } // If it's already being scanned, skip to the next portif(alreadyBeingScanned)continue; // This is a new device. Scan itSerialDeviceexhaustivePort = newSerialDevice("COM"+ index.ToString() + ":"); exhaustivePort.BeginDetection(); } } } #endregion #regionDiscover 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. */#ifPocketPC// Wait for existing devices to be testedcount = _BluetoothDevices.Count;for(intindex = 0; index < count; index++) {// Complete detection for this device_BluetoothDevices[index].WaitForDetection(); }#endif// Begin searching for brand new devicesBluetoothDevice.DiscoverDevices(true); // Block until that search completesBluetoothDevice.DeviceDiscoveryThread.Join(); } #endregion #regionWait 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{ManualResetEventhandle = _CurrentlyDetectingWaitHandles[0];#if!PocketPCif (!handle.SafeWaitHandle.IsClosed)#endifhandle.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 #ifPocketPC#regionReconfigure 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 devicecount = _GpsDevices.Count;for(intindex = 0; index < count; index++) {// Is it a serial device?SerialDevicedevice = _GpsDevices[index] asSerialDevice;if(device == null)continue; // Yes. Use it!try{ gpsid.HardwarePort = device; // The GPSID is now workingAdd(gpsid); }catch(Exceptionex) {// Notify of the error gracefullyOnDeviceDetectionAttemptFailed(newDeviceDetectionException(gpsid, ex)); } // That's the best device, so quitbreak; } } #endregion#endif// Signal completionOnDeviceDetectionCompleted(); }catch(ThreadAbortException) {#regionAbort detection for all devices#ifPocketPC// Stop detection for the GPSIDif(GpsIntermediateDriver.Current != null)GpsIntermediateDriver.Current.CancelDetection();#endif// Stop detection for each Bluetooth devicefor(intindex = 0; index < _BluetoothDevices.Count; index++) _BluetoothDevices[index].CancelDetection(); // Stop detection for each serial devicefor(intindex = 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 cancellationif(DeviceDetectionCanceled != null) DeviceDetectionCanceled(null, EventArgs.Empty); }finally{// Detection is no longer in progress_DetectionCompleteWaitHandle.Set(); _CurrentlyDetectingWaitHandles.Clear(); // <-- Already empty?_IsDetectionInProgress = false; #ifPocketPC// 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相关的可以参考.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设备的配置管理功能。
最后的最后是清理所有资源,一个好的程序的习惯。
建议功能
发现功能实现了整个GPS诊断模块的核心,建议功能也就是呈现发现功能缓存的信息。建议功能实现在SummaryForm和DeviceForm两个类里面,SummaryForm提示建议,而DeviceForm现实某个设备的检查情况。
建议功能的流程是,判断GPS Intermediate Driver设备是否可用,如果不可用可能是硬件端口配置错误,建议把可用的串口端口配置为GPS Intermediate Driver的硬件端口,如果没有可用的串口端口,建议使用蓝牙设备。
日志功能
GPS.net提供日志发送功能,把设备发现和检查信息发送到服务器,方便开发者改进。这个功能很简单。
源码请看 Windows Mobile下GPS管理软件NavsGo之GPS监控功能的开发
转载于:https://www.cnblogs.com/procoder/archive/2009/08/21/1551155.html
Windows Mobile下GPS管理软件NavsGo之GPS侦测功能的开发相关推荐
- 实测Windows Mobile下卡巴斯基手机安全软件表现
实测Windows Mobile下卡巴斯基手机安全软件表现 文/ 图 鲜橙加冰(王文文) [51CTO.com 独家特稿]随着科技的不断发展和3G技术的不断成熟,我国正迅速进入一个全新的3G时代.大量 ...
- Windows Mobile下使用CppUnitLite输出测试结果
背景 TDD测试驱动开发是当前流行的开发方法及模式.遵循TDD的方法对开发程序库(Library)特别有用,因为Library就是为第三方提供一定功能接口的实现,使用TDD的方法可以预先为定义的接口提 ...
- 装机必备 Windows Mobile系统最“牛”软件
装机必备 Windows Mobile系统最"牛"软件 作者:月雯/彭刚 首先谨代表数字家庭版祝福机友们Happy "牛" Year!作为WM6.0到WM7.0 ...
- Windows Mobile下访问Sqlite的Native C++封装
背景 当前移动设备开发领域,在本地数据存储方面,Sqlite几乎成了事实标准,Andriod (android.database.sqlite),iPhone (SQLite for iPhone S ...
- 关于在Windows Mobile下今日插件使用WTL的问题
简介 本文讲述在今日插件开发中整合WTL遇到的问题,问题已经解决,看解决部分. 问题 最近一段时间都在开发今日插件(Today Plug-in).开始把代码都写的差不多了,整合了Sqlite和WTL, ...
- 关于Windows平台下安装mysql软件
关于Windows平台下安装mysql软件 mysql是数据库一个代表:本人安装踩过坑 5.7版本和5.1版本大不相同,低版本的对中文不友好,默认字符集不友好, 5.7.18-log目前是我使用比较b ...
- Windows Mobile下猜数字游戏的TDD实现
背景 早上看了TDD by example (1) -- 挑战,觉得有趣,实现一个Windows Mobile版本.很多年前我也有一台文曲星,也常常玩这个猜数字游戏,所以尝试在Windows Mobi ...
- Windows系统下基于开源软件的多物理场仿真
Windows系统下基于开源软件的多物理场仿真实践技术应用 随着计算机技术的发展,计算机仿真技术日益成为继实验和理论之后的第三种重要研究和设计手段.真实世界中遇到的问题往往是固体力学,流体力学,热,电 ...
- 修改信息显示服务器升级,无感门禁监控管理软件升级37条新功能
无感门禁监控管理软件升级37条新功能 1.修改后台数据中心支持同时获取多条事件记录. 2.添加门到地图后,事件监控中按照当前tab页中的门进行监控(过滤). 3.修正不能浏览视频记录 4.门禁权限组, ...
最新文章
- Linux磁盘管理----分区格式化挂载fdisk、mkfs、mount
- linux单次任务调度,go任务调度2(linux的cron调用)
- WPF的ComboBox 数据模板自定义
- 二叉树C++ | 链表递归实现二叉树(插入、搜索)_1
- python睡眠_Python时间睡眠()
- 兆易创新GD32系列单片机不同容量和启动文件之间的选择(GD32F10X_MD/GD32F10X_HD/GD32F10X_XD/GD32F10X_CL)
- 解决Arduino开发板管理器下载esp8266开发包失败和速度慢的方法
- 手机号检测性别原理分析 微信男女 抖音ID检测原理
- 使用邮件合并批量制作工资条并进行发送邮件
- 分享详细剪辑步骤,做自媒体一个月7852,全程复制粘贴即可
- 基于SSM的图书馆管理系统
- 星起航跨境:美国市场8月份在线价格同比上涨0.4%
- CogPDF417Tool工具
- 云服务器基本信息的公网ip在哪,如何查看云服务器的公网ip地址
- 微信公众号开发(十)模板消息
- salesforce lightning 入门(一)
- 【leetcode刷题】70.最少操作使数组递增——Java版
- 解决 remote Read-only file system 报错原因
- 数据可视化分析教学课件——FineBI实验册节选====权益分析
- 安装Seurat内置数据集ifnb.SeuratData的方法(Linux上安装)