protected bool ValidGlobalsatPort(SerialPort port) { GlobalsatPacket packet = PacketFactory.GetWhoAmI(); bool res = false; //If "probe" packet fails, this is not a Globalsat port //If some distinction needed (other device?), set some flag here GhPacketBase response = null; try { response = SendPacket(packet); } catch (Exception) { } if (response != null && response.CommandId == packet.CommandId && response.PacketLength > 1) { string devId = response.ByteArr2String(0, 8); if (!string.IsNullOrEmpty(devId)) { lastDevId = devId; if (this.FitnessDevice.configInfo.AllowedIds == null || this.FitnessDevice.configInfo.AllowedIds.Count == 0) { this.devId = devId; res = true; } else { foreach (string aId in this.FitnessDevice.configInfo.AllowedIds) { if (devId.StartsWith(aId)) { this.devId = devId; res = true; break; } } } } } if (!res) { this.Close(); } return(res); }
//This routine has a lot of try-catch-rethrow to simplify debugging //Globalsat device communication is tricky... public virtual GhPacketBase SendPacket(GlobalsatPacket packet) { //Use packet factory, to make sure the packet matches the device GhPacketBase received = this.PacketFactory; //sending occasionally fails, retry int remainingAttempts = 3; while (remainingAttempts > 0) { try { if (!port.IsOpen) { //Physical port should be closed port.Open(); } if (packet.CommandId == GhPacketBase.CommandWhoAmI) { //Speed-up device detection, keep this as short as possible. //625XT seem to work with 5ms, 505 needs more than 100 port.ReadTimeout = this.FitnessDevice.ReadTimeoutDetect; } else if (packet.CommandId == GhPacketBase.CommandGetScreenshot) { port.ReadTimeout = 5000; } else { port.ReadTimeout = this.FitnessDevice.ReadTimeout; } //Override from device config? if (this.FitnessDevice.configInfo.ReadTimeout > 0 && (packet.CommandId != GhPacketBase.CommandGetScreenshot || this.FitnessDevice.configInfo.ReadTimeout > port.ReadTimeout)) { port.ReadTimeout = this.FitnessDevice.configInfo.ReadTimeout; } byte[] sendPayload = packet.ConstructPayload(this.FitnessDevice.BigEndianPacketLength); try { /* * Console.Write("Write:"); * for(int i = 0; i < sendPayload.Length;i++) * { * Console.Write(" " + sendPayload[i].ToString() ); * } * Console.WriteLine(""); */ port.Write(sendPayload, 0, sendPayload.Length); } catch (Exception e) { string s = string.Format("Error occurred, sending {0} bytes.", sendPayload.Length); ReportError(s, packet.CommandId == GhPacketBase.CommandWhoAmI, e); port.Close(); throw; } try { int data = port.ReadByte(); received.CommandId = (byte)data; if (data < 0 || data > 255) { //Special handling for first byte -1 is stream closed throw new TimeoutException(string.Format("No data received for {0},{1}", packet.CommandId, data)); } if (packet.CommandId == GhPacketBase.CommandWhoAmI) { this.DataRecieved = false; } else { this.DataRecieved = true; } int hiPacketLen = port.ReadByte(); int loPacketLen = port.ReadByte(); //Note: The endian for size (except for 561) from the device always seem to be the same (not so when sending) received.PacketLength = (Int16)((hiPacketLen << 8) + loPacketLen); } catch (Exception e) { string s = string.Format("Error occurred, receiving {0} bytes ({1},{2}).", received.PacketLength, packet.CommandId, received.CommandId); ReportError(s, packet.CommandId == GhPacketBase.CommandWhoAmI, e); port.Close(); throw; } if (packet.CommandId != GhPacketBase.CommandGetScreenshot && received.PacketLength > this.FitnessDevice.configInfo.MaxPacketPayload || received.PacketLength > 0x1000) { string s = string.Format("Error occurred, bad response receiving {0} bytes ({1},{2}).", received.PacketLength, packet.CommandId, received.CommandId); ReportError(s, packet.CommandId == GhPacketBase.CommandWhoAmI); port.Close(); throw new Exception(Properties.Resources.Device_OpenDevice_Error); } received.PacketData = new byte[received.PacketLength]; byte checksum = 0; int receivedBytes = 0; //debug timeouts try { for (Int16 b = 0; b < received.PacketLength; b++) { int data = port.ReadByte(); if (data < 0 || data > 255) { //-1 is stream closed throw new TimeoutException(string.Format("All data not received for {0}({4},{1}) bytes ({2},{3}).", received.PacketLength, receivedBytes, packet.CommandId, received.CommandId, data)); } received.PacketData[b] = (byte)data; receivedBytes++; } checksum = (byte)port.ReadByte(); receivedBytes++; /* * Console.Write("Read: id:" + received.CommandId + " length:" + received.PacketLength); * for(int i = 0; i < received.PacketLength;i++) * { * Console.Write(" " + received.PacketData[i].ToString() ); * } * Console.WriteLine(" checksum:" + checksum); */ } catch (Exception e) { string s = string.Format("Error occurred, receiving {0}({1}) bytes ({2},{3}).", received.PacketLength, receivedBytes, packet.CommandId, received.CommandId); ReportError(s, packet.CommandId == GhPacketBase.CommandWhoAmI, e); port.Close(); throw; //Debug template, if the device is corrupted //Should use resend //Ignore the exception, just to get data from the device //if (!(this is Gh505Device && // (receivedBytes == 2005 && received.PacketLength == 2068 || // receivedBytes == 913 && received.PacketLength == 976))) //{ // throw e; //} //received.PacketLength = (Int16)receivedBytes; //checksum = 0; //overrideException = true; } if (!received.ValidResponseCrc(checksum)) { string s = string.Format("Error occurred, invalid checksum receiving {0}({1}) bytes ({2},{3}).", received.PacketLength, receivedBytes, packet.CommandId, received.CommandId); ReportError(s, packet.CommandId == GhPacketBase.CommandWhoAmI); port.Close(); throw new Exception(Properties.Resources.Device_OpenDevice_Error); } else if (received.CommandId == GhPacketBase.ResponseResendTrackSection && remainingAttempts > 0) { //retry sending remainingAttempts--; } else if (received.CommandId != packet.CommandId && //TODO: Cleanup in allowed sender/response allowed (probably overload) !((received.CommandId == GhPacketBase.CommandGetTrackFileSections || received.CommandId == GhPacketBase.CommandId_FINISH || received.CommandId == GhPacketBase.ResponseSendTrackFinish) && (packet.CommandId == GhPacketBase.CommandGetNextTrackSection || packet.CommandId == GhPacketBase.CommandGetTrackFileSections || packet.CommandId == GhPacketBase.CommandSendTrackSection)) ) { string s = string.Format("Error occurred, invalid response {0}({1}) bytes ({2},{3}).", received.PacketLength, receivedBytes, packet.CommandId, received.CommandId); ReportError(s, packet.CommandId == GhPacketBase.CommandWhoAmI); if (received.CommandId == GhPacketBase.ResponseInsuficientMemory) { throw new InsufficientMemoryException(Properties.Resources.Device_InsuficientMemory_Error); } throw new Exception(Properties.Resources.Device_OpenDevice_Error); } else { //Assume OK response, no more tries remainingAttempts = 0; } } #pragma warning disable CS0168 // Variable is declared but never used catch (Exception e) #pragma warning restore CS0168 // Variable is declared but never used { remainingAttempts--; if (packet.CommandId == GhPacketBase.CommandWhoAmI || remainingAttempts <= 0) { //No need retry this.Close(); throw; } } } return(received); }
public virtual int SendRoute(IList <GlobalsatRoute> routes, IJobMonitor jobMonitor) { int res = 0; int totPackets = routes.Count; int extraPackets = 0; //Open, wpt etc bool status = true; if (this.Open()) { try { GlobalsatPacket packet; GlobalsatPacket response; if (this.RouteRequiresWaypoints) { packet = PacketFactory.GetWaypoints(); response = (GlobalsatPacket)this.SendPacket(packet); IList <GlobalsatWaypoint> wptDev = response.ResponseGetWaypoints(); extraPackets++; jobMonitor.PercentComplete = (float)(res + extraPackets) / (float)(totPackets + extraPackets); //Routes need waypoints - find those missing IList <GlobalsatWaypoint> wptSend = new List <GlobalsatWaypoint>(); foreach (GlobalsatRoute route in routes) { foreach (GlobalsatWaypoint wpt1 in route.wpts) { bool found = false; foreach (GlobalsatWaypoint wpt2 in wptDev) { if (GhPacketBase.ToGlobLatLon(wpt1.Latitude) == GhPacketBase.ToGlobLatLon(wpt2.Latitude) && GhPacketBase.ToGlobLatLon(wpt1.Longitude) == GhPacketBase.ToGlobLatLon(wpt2.Longitude)) { found = true; break; } } if (!found) { wptSend.Add(wpt1); } } } if (wptSend.Count > 0) { //Send with normal protocol, 625XT requires one by one int sent = this.SendWaypoints(wptSend, jobMonitor); if (sent < wptSend.Count) { status = false; } else { extraPackets++; jobMonitor.PercentComplete = (float)(res + extraPackets) / (float)(totPackets + extraPackets); this.Open(); //Reopen extraPackets++; jobMonitor.PercentComplete = (float)(res + extraPackets) / (float)(totPackets + extraPackets); } } } else { //Check if capacity is sufficient. Wpt checked separetly int rtePoint = 0; foreach (GlobalsatRoute route in routes) { rtePoint += route.wpts.Count; } if (rtePoint > this.FitnessDevice.MaxNoRoutePoints) { jobMonitor.ErrorText = string.Format("Need to send {0} route points, the device can only handle {1}.", rtePoint, this.FitnessDevice.MaxNoRoutePoints); status = false; } } if (status) { //Finally the routes... foreach (GlobalsatRoute route in routes) { packet = PacketFactory.SendRoute(route); response = (GlobalsatPacket)this.SendPacket(packet); //Note: No way to determine that GB-580/GH-505 do not really receive the routes? res++; jobMonitor.PercentComplete = (float)(res + extraPackets) / (float)(totPackets + extraPackets); } } } catch (Exception e) { jobMonitor.ErrorText = Properties.Resources.Device_SendRoute_Error + e; //throw new Exception(Properties.Resources.Device_SendRoute_Error + e); status = false; } finally { this.Close(); } } if (status && !this.DataRecieved) { NoCommunicationError(jobMonitor); } return(res); }