はじめに
みなさんこんにちは!
この記事では、WindowsCEに基づくデバイスでのGPSデータへのアクセスの実装を検討します。 SCOUT-Navigator製品を作成するとき、WinCEバージョン5.0とWinCEバージョン6.0の両方で動作するアプリケーションを開発する必要がありました。これは、ナビゲーションレシーバーからNMEAデータを受信してログに書き込むことができます。
解決策
バージョン5.0とバージョン6.0の両方でWinCEでGPSを使用するには、COMポートを使用するのが最も簡単です。 DeviceManagerというプログラムを使用して、COMポートがGPSデータを提供するデバイスを見つけることができます。
多くの場合、ファームウェアの製造元は、2つのGPS COMポートがあることを既に確認しています。 これにより、GPSとナビゲーションを必要とするソフトウェアを繁殖させ、COMポートへのアクセスに苦労しないようにすることができます。 排他的アクセスでCOMポートを使用するとします。
NMEAデータ(http://ru.wikipedia.org/wiki/NMEA_0183)を取得するには、COMポートを開いてデータを読み取り、COMポートを閉じるだけです。 C#の内容は次のようになります。
///<summary> /// COM ///</summary> ///<param name="comPortName"> COM-</param> ///<param name="baudRate"></param> private void ReadData(string comPortName,int baudRate) { var serialPort = newSerialPort(comPortName) { BaudRate = baudRate, DataBits = 8, Parity = Parity.None, StopBits = StopBits.One, RtsEnable = true }; serialPort.Open(); // COM- //..... var line=serialPort.ReadLine(); //..... serialPort.Close(); }
すべてが非常に簡単に見えるという事実にもかかわらず、上記のコードはしばしばCOMポートへのアクセスエラーのために機能しません。 (たとえば、「UnauthorizedAccessException:Portへのアクセスが拒否されました」というエラーが頻繁に発生します)。
動揺することはありません;動作する別のアプローチがあります。
OpenNetCfプロジェクトの優秀な人々は、自分のSerialPortのソースコードを慎重に提供します。
http://serial.codeplex.com/SourceControl/changeset/view/25883#435389
アセンブリOpenNetCf.IO.Serialをプロジェクトに追加します
GPS COMポートクラスは次のようになります。
///<summary> /// GPS COM- ///</summary> public class GpsPort: IDisposable { private Port _serialPort; private bool _disposed; private readonly object _syncObject = new object(); public bool IsOpen { get; private set; } ///<summary> /// GPS ///</summary> ///<param name="serialPortName"></param> ///<param name="baudRate"></param> public GpsPort(string serialPortName, int baudRate) { _serialPort = newPort(serialPortName, newDetailedPortSettings { BasicSettings = newBasicPortSettings { BaudRate = (BaudRates)baudRate }, EOFChar = '\n' }); _disposed = false; } public void Dispose() { if (!_disposed) { Close(); _serialPort = null; _disposed = true; } GC.SuppressFinalize(this); } ///<summary> ///Destructor ///</summary> ~GpsPort() { Dispose(); } ///<summary> /// ///</summary> public void Open() { try { _serialPort.Open(); _serialPort.DataReceived += SerialPortDataReceived; IsOpen = true; } catch (Exception ex) { throw new ApplicationException("Could not open com port", ex); } } ///<summary> /// ///</summary> private void SerialPortDataReceived() { lock (_syncObject) { if (_serialPort == null || !_serialPort.IsOpen) return; var realPortData = _serialPort.Input; if (realPortData.Length == 0) return; Debug.Write(Encoding.GetEncoding("ASCII").GetString(realPortData, 0, realPortData.Length)); } } ///<summary> /// ///</summary> public void Close() { IsOpen = false; if (_serialPort != null) if (_serialPort.IsOpen) { _serialPort.DataReceived -= SerialPortDataReceived; _serialPort.Close(); } } }
SerialPortDataReceivedメソッドでは、実際に、NMEA文字列の解析を記述します。
これを行うには、次のことができます。
- NMEAパーサーを作成します。
- SharpGpsを使用します 。
- NMEA-0183-2-0-Sentense-parser-builderを使用します (ここではHabréの開発者の記事)。
- その他のパーサー。
Sentenseparserbuilderを使用したことはありませんが、SharpGpsについて説明することがあります。
トピックから少し脱線します。 私の同僚の多くは、これは間違いではなく論理的な振る舞いであると考えていますが、ライブラリにはチェックサムの計算に面白い間違いがあります。 しかし、まず最初に:
NMEA 0183プロトコル( http://www.tronico.fi/OH6NT/docs/NMEA0183.pdf )では、チェックサムは2桁の16進数として記述されます-「$」と「*の間の文字列のすべてのバイトのXORチェックサム「。
SharpGpsには、パッケージ内のチェックサムの正確性をチェックする機能があります。
private bool CheckSentence(string strSentence) { int iStart = strSentence.IndexOf('$'); int iEnd = strSentence.IndexOf('*'); //If start/stop isn't found it probably doesn't contain a checksum, //or there is no checksum after *. In such cases just return true. if (iStart >= iEnd || iEnd + 3 > strSentence.Length) return true; byte result = 0; for (int i = iStart + 1; i < iEnd; i++) { result ^= (byte)strSentence[i]; } return (result.ToString("X") == strSentence.Substring(iEnd + 1, 2)); }
この機能は、プロトコルに記載されているように、ナビゲーションレシーバーが2つの数字(0x01、0x02など)の形式でチェックサムを送信する場合に最適です。 しかし、理想的なコードは、ナビゲーションレシーバーが先行ゼロ(0x1,0x2)を追加せずにチェックサム付きでパケットを送信するという現実に分割されます。
実行中のアプリケーションでは、パケットの一部が削除されていることがわかります。 この場合、すべてが機能しているように見えるという感覚。 しかし、トラックはそうではありますが、非常に品質が悪いです。
動作させるために、少なくとも次のように最後の行を書き換えることができます。
var packCrc = byte.Parse(strSentence.Substring(iEnd + 1, 2), System.Globalization.NumberStyles.AllowHexSpecifier); return (result == packCrc);
リトリートすべてで。
ナビゲーションデータを格納するために、SqlServer Compact Editionを使用することが決定されました。 アプリケーションに統合し、開発で使用するのは非常に簡単です。 この記事ではSqlServer Compactの使用については説明しませんでしたが、WinCeアプリケーションでのSqlServer Compactの使用に関する記事を参照したい場合は、コメントでマークできます。
おわりに
この記事では、WinCeデバイスのGPSデータにアクセスする問題の解決策を示しました。このソリューションは、WinCEの異なるバージョンを使用して、さまざまなメーカー(Prestigio、Texet、Shturmann、Mio)のナビゲーターでテストされました。 WinCEでの開発の途中であなたを待っているレーキの一部を救うことを願っています。
ご清聴ありがとうございました。 コメントで質問やコメントを待っています。