protected override bool BlockCompleted() { try { //CNXLog.InfoFormat("Testing block {0}", mBlockId); //if (mMemStream.Length == mSize && mBytesWritten >= mSize) //{ // mMemStream.Seek(0, SeekOrigin.Begin); // ushort crc = CRC16.CRCStream(mMemStream); // CNXLog.InfoFormat("CRC check calculated {0} should be {1}.", crc, mCRC); // mCRCOk = (crc == mCRC); if (base.BlockCompleted() && mSize > 0) { //CNXLog.InfoFormat("Block {0} complete.", mBlockId); // transfere to permanat storage CreateBlockFile(); mMemStream.WriteTo(mFileStream); mFileStream.Flush(); mFileStream.Close(); } //} } catch (Exception e) { CNXLog.ErrorFormat("BlockComplete {0} {1}.", (Block)mBlockId, e.Message); } return(mCRCOk); }
/// <summary> /// What to do when a complete block has arrived. /// Provided by derived class. /// </summary> /// <returns></returns> protected virtual bool BlockCompleted() { try { CNXLog.InfoFormat("Testing {0} length {1}", (Block)mBlockId, mMemStream.Length); if (mSize == 0) { mCRCOk = true; } else if (mMemStream.Length >= mSize && mBytesWritten >= mSize) { mMemStream.Seek(0, SeekOrigin.Begin); ushort crc = CRC16.CRCStream(mMemStream, (int)mSize); CNXLog.InfoFormat("CRC check calculated {0:X4} should be {1:X4}.", crc, mCRC); mCRCOk = (crc == mCRC); } if (mCRCOk) { CNXLog.InfoFormat("{0} complete.", (Block)mBlockId); } SendBlockQueryResponce(); } catch (Exception e) { CNXLog.ErrorFormat("BlockComplete {0} {1}.", (Block)mBlockId, e.Message); } return(mCRCOk); }
protected override bool BlockCompleted() { bool result = false; try { if (base.BlockCompleted()) { mBlockData = new byte[mSize]; if (mSize > 0) { Array.Copy(mMemStream.ToArray(), mBlockData, mSize); } else { OnRaiseBlockStatusEvent(new BlockStatusEventArgs(mBlockId, BlockState.COMPLETE)); } CNXLog.InfoFormat("TransientBlockReciever {0} Completed:\n\r{1}", (Block)mBlockId, HexDump.Dump(mBlockData)); result = true; } } catch (Exception e) { CNXLog.Error("TransientBlockReciever.BlockCompleted:", e); } return(result); }
/// <summary> /// Creates a CAN client ready for sending and recieving CAN frames. /// </summary> /// <param name="ifaceName">The CAN interfave name to bind to.</param> /// <param name="bufferSize">recieve buffer size to set.</param> /// <remarks>This is a Linux only implementation and requires a native library.</remarks> public CANNativeClient(string ifaceName, uint bufferSize) { if (bufferSize == 0) { mCanFd = can_open(ifaceName); } else { mCanFd = can_buffer_open(ifaceName, bufferSize); } if (mCanFd < 0) { CNXLog.FatalFormat("CANNativeClient can_buffer_open({0}, 0x1000) returned {1}", ifaceName, mCanFd); throw new SocketException(mCanFd); } // organise a decent buffersize for the frames int buffersize = can_getbuffersize(mCanFd); CNXLog.InfoFormat("CAN buffer size {0}.", buffersize); mRxThread = new Thread(new ThreadStart(ReceiveFrame)) { Priority = ThreadPriority.AboveNormal, IsBackground = true }; mRxThread.Start(); }
///// <summary> ///// Event firing method. ///// </summary> ///// <param name="frame">The CAN frame just received.</param> //protected virtual void OnRaiseFrameReceivedEvent(FrameReceivedEventArgs frameEvent) //{ // // copy the event handler to avoid mid process subscribe/un-subscribe // EventHandler<FrameReceivedEventArgs> handler = RaiseFrameReceivedEvent; // // Check if there are any Subscribers // if (handler != null) // { // // Call the Event // handler(this, frameEvent); // } //} private void ReceiveFrame() { byte[] buffer = new byte[8]; CANFrame frame = new CANFrame(); int rxLen = 0; byte length = 0; uint canId = 0; while (mKeepReceiving) { try { rxLen = can_recieve(mCanFd, ref canId, ref length, buffer); if (rxLen > 0) { // populate a CAN frame frame.MailboxId = canId; frame.DataFromArray(buffer, 0, length); base.OnRaiseFrameReceivedEvent(new FrameReceivedEventArgs(frame)); } } catch (Exception e) { // stuffed. mKeepReceiving = false; CNXLog.Error("CANNative.ReceiveFrame", e); break; } } Console.WriteLine("CAN native end recieve loop"); }
private void ReceiveFrames() { const int length = 16; byte[] buffer = new byte[length]; CANFrame frame = new CANFrame(); int rxLen = 0; while (mKeepReceiving) { try { rxLen = can_read(mCanFd, buffer, length); if (rxLen > 0) { frame.WireFormatArray = buffer; base.OnRaiseFrameReceivedEvent(new FrameReceivedEventArgs(frame)); } } catch (Exception e) { // stuffed. mKeepReceiving = false; CNXLog.Error("CANNative.ReceiveFrames", e); break; } } Console.WriteLine("CAN native end recieve loop"); }
/// <summary> /// Sends a CAN frame across the bridge /// </summary> /// <param name="frame">The CAN frame to send.</param> public override int Send(CANFrame frame) { try { return(mRxSocket.SendTo(frame.WireFormatArray, mTxEndPoint)); } catch { CNXLog.Debug(frame.MailboxId.ToString("X")); return(0); } }
private void CreateBlockFile() { try { mPath = String.Format("{0}blk{1}", ((Environment.OSVersion.Platform == System.PlatformID.Unix) ? LinuxBlockFilePath : MSBlockFilePath), mBlockId); //string path = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData // delete any old file from a previous instance and overwrite with a new one. //mFileStream = new FileStream(mPath, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite | FileShare.Delete, 8, FileOptions.RandomAccess); mFileStream = new FileStream(mPath, FileMode.Create, FileAccess.ReadWrite, FileShare.Read, 8192, FileOptions.RandomAccess); } catch (Exception e) { CNXLog.ErrorFormat("Block Reciever failed for path {0}. {1}", mPath, e.Message); } }
/// <summary> /// Provides validation that the sentence is a complete and valid NMEA sentence /// </summary> /// <param name="sentence">The sentence to be validated.</param> /// <returns>True if the sentence is a valid NMEA formated sentence.</returns> /// <remarks> /// NMEA sentences are of the form $GPRMC,11,22,33,44,55*CC /// A valid sentence starts with a $. /// Has comma seperated data values. /// Has a * indicating the end of the data and position of the checksum. /// The two checksum characters are correct. /// </remarks> public bool ValidateNMEASentence(string sentence) { // Does it begin with a dollar sign? if (!sentence.StartsWith("$", StringComparison.Ordinal)) { CNXLog.WarnFormat("NMEAClient Validation failed, no $."); return(false); } // make sure there are data fields if (sentence.IndexOf(",", StringComparison.Ordinal) == -1) { CNXLog.WarnFormat("NMEAClient Validation failed, no data fields."); return(false); } // Next, get the index of the asterisk int asteriskIndex = sentence.IndexOf("*", StringComparison.Ordinal); // Is an asterisk present? if (asteriskIndex == -1) { CNXLog.WarnFormat("NMEAClient Validation failed, no *."); return(false); } // The checksum is calculated over the command and data portion of the sentence byte checksum = (byte)sentence[1]; for (int index = 2; index < asteriskIndex; ++index) { checksum ^= (byte)sentence[index]; } // The checksum is the two-character hexadecimal value string calculatedChecksum = checksum.ToString("X2", NMEACultureInfo); string sentenceChecksum = sentence.Substring(asteriskIndex + 1, 2); if (!calculatedChecksum.Equals(sentenceChecksum, StringComparison.Ordinal)) { ++mChecksumErrors; CNXLog.WarnFormat("NMEAClient checksum errors {0}, sentence ratio {1}/{2}.", mChecksumErrors, mValidSentences, mSentencesRecieved); return(false); } return(true); }
/// <summary> /// Creates a client connection to the CAN bridge which passes CAN frames across an IP socket as datagrams. /// </summary> /// <param name="address">Server address.</param> /// <param name="inPort">Port to receive frames on.</param> /// <param name="outPort">Port to transmit frames on.</param> public CANBridgeClient(string address, int inPort, int outPort) { mInPort = inPort; mOutPort = outPort; mAddress = address; // associate with the CAN Bridge mTxEndPoint = new IPEndPoint(IPAddress.Parse(address), outPort); mRxEndPoint = new IPEndPoint(IPAddress.Any, inPort); mRxSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); mRxSocket.Bind(mRxEndPoint); mTxSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); // set a decent number of threads in the thread pool int worker, completion; ThreadPool.GetMinThreads(out worker, out completion); CNXLog.InfoFormat("Workers {0} + 16, Completion {1}", worker, completion); ThreadPool.SetMinThreads(worker + 16, completion); mRxThread = new Thread(new ThreadStart(ReceiveFrames)); //mRxThread.IsBackground = true; mRxThread.Start(); }
/// <summary> /// Sends the frame on the CAN bus. /// </summary> /// <param name="frame">The frame to send.</param> /// <returns>Total number of bytes put onto the CAN bus.</returns> public override int Send(CANFrame frame) { // synchronise sends //int sent = 0; //lock (sendLock) //{ // int retries = 3; // for (sent = can_send(mCanFd, frame.MailboxId, (byte)frame.DataLength, frame.Data); sent < 4 && --retries > 0; sent = can_send(mCanFd, frame.MailboxId, (byte)frame.DataLength, frame.Data)) // Thread.Sleep(1); //} //return sent; // synchronise sends int sent = -1; uint canId = frame.MailboxId; // test 11 or 29 bit addressing if (canId > 0x7ff) { canId |= (uint)CANFrame.IDFlags.CAN_EFF_FLAG; } lock (sendLock) { try { sent = can_send(mCanFd, canId, (byte)frame.DataLength, frame.Data); } catch (Exception e) { CNXLog.Error("CANNative.Send", e); } } return(sent); }
/// <summary> /// Event firing method. /// </summary> /// <param name="frame">The CAN frame just received.</param> //protected virtual void OnRaiseFrameReceivedEvent(FrameReceivedEventArgs frameEvent) //{ // // copy the event handler to avoid mid process subscribe/un-subscribe // EventHandler<FrameReceivedEventArgs> handler = RaiseFrameReceivedEvent; // // Check if there are any Subscribers // if (handler != null) // // Call the Event // handler(this, frameEvent); //} private void ReceiveFrames() { byte[] buffer = new byte[13]; EndPoint ep = mRxEndPoint; CANFrame frame = new CANFrame(); while (mKeepReceiving) { try { if (mRxSocket.ReceiveFrom(buffer, ref ep) > 0) { CNXLog.Debug(BitConverter.ToString(buffer)); // populate a CAN frame frame.WireFormatArray = buffer; CNXLog.Debug(BitConverter.ToString(frame.Data)); CNXLog.Debug(frame.MailboxId.ToString("X")); OnRaiseFrameReceivedEvent(new FrameReceivedEventArgs(frame)); } } catch (SocketException se) { // may be OK to continue. CNXLog.WarnFormat("ReceiveFrames {0}.", se.Message); } catch (Exception e) { // stuffed. mKeepReceiving = false; CNXLog.ErrorFormat("ReceiveFrames {0}.", e.Message); break; } } mRxSocket.Close(); }
private void ProcessNewSentence(string sentence) { if (sentence.Length < 6) { OnRaiseGPSStatusChangedEvent(new GPSStatusEvent(GPS_STATUS.OFFLINE)); CNXLog.ErrorFormat("NMEAClient short sentence {0}", sentence); return; } try { //CNXLog.InfoFormat("NMEAClient ProcessNewSentence {0}", sentence); bool updateAvailable = false; string sentenceType = ""; if (sentence.Contains("RMC")) { sentenceType = "RMC"; } else if (sentence.Contains("GGA")) { sentenceType = "GGA"; } else if (sentence.Contains("GSA")) { sentenceType = "GSA"; } // Determine the type of sentence. // The NMEA specification states that the first two letters of a sentence may change. // For example, for "$GPGSV" there may be variations such as "$__GSV" where the first two letters change. // As a result, we need only test the last three characters. // Is this a GPRMC sentence? if (sentenceType.Equals("RMC", StringComparison.Ordinal)) { updateAvailable = mGPSPosition.ParseRMC(sentence); if (!updateAvailable) { OnRaiseGPSPositionChangedEvent(new GPSPositionEvent(mGPSPosition)); } } else if (sentenceType.Equals("GGA", StringComparison.Ordinal)) { // dont update on GGA, only augment error estimates. updateAvailable = mGPSPosition.ParseGGA(sentence); } else if (sentenceType.Equals("GSA", StringComparison.Ordinal)) { updateAvailable = mGPSPosition.ParseGSA(sentence); } if (updateAvailable) { mLastNMEASentenceType = sentenceType; // report any status changes GPS_STATUS status = GPS_STATUS.OFFLINE; switch (mGPSPosition.NMEAMode) { case GPSPosition.NMEAMODE.NO_FIX: status = GPS_STATUS.Connected; mTravellingState = MovingState.Unknown; break; case GPSPosition.NMEAMODE.NO_MODE: status = GPS_STATUS.Connected | GPS_STATUS.GPSResponding; mTravellingState = MovingState.Unknown; break; case GPSPosition.NMEAMODE.TWO_DIMENSION: case GPSPosition.NMEAMODE.THREE_DIMENSION: status = GPS_STATUS.Connected | GPS_STATUS.GPSResponding | GPS_STATUS.Fix; // set the travelling state mAverageVelocity.Value = mGPSPosition.SpeedOverGround; //lat = mG mTravellingState = (mAverageVelocity.Value > mMovingThreshold) ? MovingState.Moving : MovingState.Stationary; break; } if (status != mStatus) { mStatus = status; OnRaiseGPSStatusChangedEvent(new GPSStatusEvent(mStatus)); //Console.WriteLine("Fired Status Changed."); } // only update from RMC sentences as other sentences dont have date & time. if (sentenceType.Equals("RMC", StringComparison.Ordinal)) { //Console.WriteLine("Firing Position Changed."); //CNXLog.InfoFormat("GPS State {0}, {1}", mStatus, mGPSPosition.CurrentPosition.ToString()); //if (mGPSPosition.Tag.EndsWith("RMC", StringComparison.Ordinal)) if ((mStatus & GPS_STATUS.Fix) == GPS_STATUS.Fix) { //CNXLog.InfoFormat(mGPSPosition.CurrentPosition.ToString()); OnRaiseGPSPositionChangedEvent(new GPSPositionEvent(mGPSPosition)); //CNXLog.InfoFormat("OnRaiseGPSPositionChangedEvent completed."); //CNXLog.InfoFormat(mGPSPosition.CurrentPosition.ToString()); //Console.WriteLine("Fired Position Changed."); } } } //CNXLog.InfoFormat("GPS State {0}, {1}", mStatus, mGPSPosition.CurrentPosition.ToString()); } catch (Exception e) { CNXLog.Error(String.Format("NMEAClient ProcessNewSentence {0}", sentence), e); } }