public static bool UnpackIdentifiers(CANFrame frame, out ushort commsAddress, out byte companyTag) { commsAddress = 0; companyTag = 0; if ((CNXMsgIds)frame.MailboxId != CNXMsgIds.Identifiers || frame.DataLength < 3) { return(false); } byte[] data = frame.Data; byte[] shortArray = new byte[2]; shortArray[0] = data[0]; shortArray[1] = data[1]; if (!BitConverter.IsLittleEndian) { Array.Reverse(shortArray); } commsAddress = BitConverter.ToUInt16(shortArray, 0); if (frame.DataLength > 2) { companyTag = data[2]; } return(true); }
/// <summary> /// Initialises a ProductCatalogue from a file. /// </summary> /// <param name="path">Path to product file.</param> /// <remarks> /// The file should be a text file with seperate lines containing the product Id and the version. /// The lines should be space seperated key value pairs as below. /// PRODUCT_ID 2 /// VERSION 4 /// </remarks> public ProductCatalogue(CANClient can, string path, DeviceCatalogueInfo.EquipmentFlages mask, DeviceCatalogueInfo.EquipmentFlages state) { mMask = mask; mStatus = state; mCatalogueFrame = PopulateProductFrameFromFile(path, mask, state); _ProductCatalogue(can); }
/// <summary> /// Initialises a ProductCatalogue /// </summary> /// <param name="prodId">The ID of the product.</param> /// <param name="prodVersion">The current version of the product.</param> public ProductCatalogue(CANClient can, byte prodId, byte prodVersion, DeviceCatalogueInfo.EquipmentFlages mask, DeviceCatalogueInfo.EquipmentFlages state) { mMask = mask; mStatus = state; mCatalogueFrame = CNXCANMsgHelper.PackProductId(prodId, prodVersion, (uint)mask, (uint)state); _ProductCatalogue(can); }
///// <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"); }
public static CANFrame PackDateTime(DateTime dt) { CANFrame frame = new CANFrame() { MailboxId = (uint)CNXMsgIds.DateTime }; byte[] data = new byte[6]; // Day of month data[0] = (byte)dt.Day; // Month data[1] = (byte)dt.Month; // Year // I know, time bomb data[2] = (byte)(dt.Year - 2000); // Time 0-86400 Seconds since midnight int time = (dt.Hour * 3600) + (dt.Minute * 60) + dt.Second; byte[] intArray = BitConverter.GetBytes(time); // make sure byte 0 is lsb. if (!BitConverter.IsLittleEndian) { Array.Reverse(intArray); } Array.Copy(intArray, 0, data, 3, 3); frame.Data = data; //CNXLog.InfoFormat("PackDateTime DateTime {0} frame {1}", dt.ToString(), frame.DefaultToString()); return(frame); }
public static DateTime UnpackDateTimeFrame(CANFrame frame) { if (frame.MailboxId != (uint)CNXMsgIds.DateTime) { return(new DateTime(0, DateTimeKind.Unspecified)); } //DateTime dt = new DateTime(0, DateTimeKind.Utc); //dt.AddDays((double)frame.Data[0]); //dt.AddMonths((int)frame.Data[1]); //// I know, time bomb //dt.AddYears((int)frame.Data[2] + 1999); //// sort the time bit out byte[] intArray = new byte[4]; Array.Copy(frame.Data, 3, intArray, 0, 3); // check endianess if (!BitConverter.IsLittleEndian) { Array.Reverse(intArray); } //dt.AddSeconds((double)BitConverter.ToInt32(intArray, 0)); int seconds = BitConverter.ToInt32(intArray, 0); int utcHours = seconds / 3600; seconds -= (utcHours * 3600); int utcMinutes = seconds / 60; seconds -= (utcMinutes * 60); DateTime dt = new DateTime((int)frame.Data[2] + 2000, frame.Data[1], frame.Data[0], utcHours, utcMinutes, seconds, 0, DateTimeKind.Utc); //CNXLog.InfoFormat("UnpackDateTime DateTime {0} frame {1}", dt.ToString(), frame.DefaultToString()); return(dt); }
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> /// Extracts trip progress information from the frame. /// </summary> /// <param name="frame">Trip progress frame.</param> /// <param name="pathId">Id of the current path.</param> /// <param name="position">Position along the path.</param> /// <param name="tripNo">Trip number</param> /// <param name="serviceStart">Service start</param> /// <param name="runningState">Running state</param> /// <returns>True on success, false if the frame isnt a TripProgress frame or the data payload is the wrong size.</returns> public static bool UnpackTripOnRoute(CANFrame frame, out short pathId, out int position, out int?tripNo, out ushort?serviceStart, out RunningStateType runningState) { pathId = 0; position = 0; tripNo = null; serviceStart = null; runningState = RunningStateType.Normal; // validate message type and size if ((CNXMsgIds)frame.MailboxId != CNXMsgIds.TripOnRoute || frame.DataLength < 8) { return(false); } byte[] data = frame.Data; byte[] intArray = new byte[4]; byte[] shortArray = new byte[2]; shortArray[0] = data[0]; shortArray[1] = (byte)(data[1] & 0x07); if (!BitConverter.IsLittleEndian) { Array.Reverse(shortArray); } pathId = BitConverter.ToInt16(shortArray, 0); intArray[0] = (byte)(data[1] >> 3); intArray[0] |= (byte)(data[2] << 5); intArray[1] = (byte)(data[2] >> 3); intArray[2] = 0; intArray[3] = 0; if (!BitConverter.IsLittleEndian) { Array.Reverse(intArray); } position = BitConverter.ToInt32(intArray, 0); intArray[0] = data[3]; intArray[1] = data[4]; intArray[2] = data[5]; intArray[3] = 0; if (!BitConverter.IsLittleEndian) { Array.Reverse(intArray); } tripNo = BitConverter.ToInt32(intArray, 0); shortArray[0] = data[6]; shortArray[1] = (byte)(data[7] & 0x3f); if (!BitConverter.IsLittleEndian) { Array.Reverse(shortArray); } serviceStart = BitConverter.ToUInt16(shortArray, 0); runningState = (RunningStateType)(data[7] >> 6); return(true); }
public static string UnpackDestinationFrame(CANFrame frame) { if (frame.MailboxId == (uint)CNXMsgIds.Destination) { return(UnpackDestinationFrameData(frame.Data)); } return(null); }
/// <summary> /// Unpacks a duress frame /// </summary> /// <param name="frame">The frame to unpack.</param> /// <returns>The duress state.</returns> /// <remarks>An inactive state is returened for invalid or badly formatted frames.</remarks> public static bool DuressFrame(CANFrame frame) { if (frame.MailboxId != (uint)CNXMsgIds.DuressState || frame.DataLength == 0) { return(false); } return((frame.Data[0] & 0x01) == 0x01); }
static CANFrame makeCANFrame(dynamic x) { var cf = new CANFrame() { MailboxId = (uint)x.MailboxId }; cf.Data = (byte[])x.Data; return(cf); }
public static CANGPSState UnpackGPSState(CANFrame frame) { // check we have been given a GPS frame with some data. if (frame.MailboxId != (uint)CNXMsgIds.GPS || frame.DataLength == 0) { return(CANGPSState.Invalid); } return((CANGPSState)(frame.Data[0] & 0x03)); }
/// <summary> /// Reads product information from a file. /// </summary> /// <param name="path">Path to product file.</param> /// <param name="mask">The device mask to set.</param> /// <param name="state">The device states for the masked devices.</param> /// <remarks> /// The file should be a text file with seperate lines containing the product Id and the version. /// The lines should be space seperated key value pairs as below. /// PRODUCT_ID 2 /// VERSION 4 /// </remarks> public static CANFrame PopulateProductFrameFromFile(string path, DeviceCatalogueInfo.EquipmentFlages mask, DeviceCatalogueInfo.EquipmentFlages state) { byte prodId; byte ver; ProductInfoFromFile(path, out prodId, out ver); CANFrame frame = CNXCANMsgHelper.PackProductId(prodId, ver, (uint)mask, (uint)state); CNXLog.WarnFormat("Product Frame {0}", frame.ToString()); return(frame); }
public static void UnpackFarebox(CANFrame frame, out string routeCode, out int?tripNo) { if (frame.MailboxId == (uint)CNXMsgIds.RouteTrip) { UnpackFareboxData(frame.Data, out routeCode, out tripNo); } else { routeCode = null; tripNo = null; } }
/// <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); } }
/// <summary> /// Builds a Duress frame. /// </summary> /// <param name="duress">Whether the duress is active.</param> /// <returns>Frame ready to be be put on the CAN bus.</returns> public static CANFrame DuressFrame(bool duress) { CANFrame frame = new CANFrame() { MailboxId = (uint)CNXMsgIds.DuressState }; byte[] data = new byte[1]; data[0] = duress ? (byte)0x01 : (byte)0x00; frame.Data = data; return(frame); }
public static CANFrame PackDestinationFrame(string dest) { CANFrame frame = new CANFrame() { MailboxId = (uint)CNXMsgIds.Destination }; ASCIIEncoding ascii = new ASCIIEncoding(); frame.Data = ascii.GetBytes(dest); return(frame); }
public static CANFrame PackProductId(byte prodId, byte buildNo, uint mask, uint status) { CANFrame frame = new CANFrame() { MailboxId = (uint)CNXMsgIds.ProductId }; byte[] data; // allocate the data payload if (mask > 0x0000ffff) { data = new byte[8]; } else if (mask > 0x000000ff) { data = new byte[6]; } else if (mask > 0) { data = new byte[4]; } else { data = new byte[2]; } data[0] = prodId; data[1] = buildNo; if (data.Length > 3) { data[2] = (byte)mask; data[3] = (byte)status; } if (data.Length > 5) { data[4] = (byte)(((uint)mask >> 8) & 0xff); data[5] = (byte)(((uint)status >> 8) & 0xff); } if (data.Length > 7) { data[6] = (byte)(((uint)mask >> 16) & 0xff); data[7] = (byte)(((uint)status >> 16) & 0xff); } frame.Data = data; return(frame); }
public static CANFrame PackFareSetFrame(byte fareSet) { CANFrame frame = new CANFrame() { MailboxId = (uint)CNXMsgIds.Fareset }; byte[] data = new byte[1]; data[0] = fareSet; frame.Data = data; return(frame); }
private CANFrame BuildQueryResponce() { byte[] data; CANFrame frame = new CANFrame(); try { frame.MailboxId = 0x500 + (uint)mBlockId; // decide what the offset value should be uint offset = mLastIndexWritten; ushort crc = 0; // no active or downloading block if (mLastIndexWritten == 0 && mCRC == 0) { offset = 0; } else if (BlockStatus == BlockState.COMPLETE) { offset = 0xffffffff; crc = mCRC; } data = new byte[7]; // populate the offset BitConverter.GetBytes(offset).CopyTo(data, 0); if (!BitConverter.IsLittleEndian) { Array.Reverse(data, 0, 4); } // populate the crc BitConverter.GetBytes(crc).CopyTo(data, 4); if (!BitConverter.IsLittleEndian) { Array.Reverse(data, 4, 2); } // populate the current version data[6] = mProdVersion; frame.Data = data; CNXLog.InfoFormat("BuildQueryResponce {0} {1}", BlockStatus, frame.ToString()); } catch (Exception e) { CNXLog.ErrorFormat("BuildQueryResponce {0} {1}", (Block)mBlockId, e.ToString()); } return(frame); }
public static CANFrame PackIdentifiers(ushort commsAddress, byte companyTag) { CANFrame frame = new CANFrame() { MailboxId = (uint)CNXMsgIds.Identifiers }; byte[] data = new byte[3]; byte[] shortArray = BitConverter.GetBytes(commsAddress); // make sure byte 0 is lsb. if (!BitConverter.IsLittleEndian) { Array.Reverse(shortArray); } Array.Copy(shortArray, 0, data, 0, 2); data[2] = companyTag; frame.Data = data; return(frame); }
public static bool UnpackBlockQueryResponce(CANFrame frame, out Block blockType, out uint offset, out ushort crc, out byte version) { blockType = (Block)0; offset = 0; crc = 0; version = 255; if ((frame.MailboxId & 0xffffff00) != (uint)CNXMsgIds.BlockQueryResponse) { return(false); } blockType = (Block)(frame.MailboxId & 0x0ff); byte[] data = frame.Data; if (data.Length > 3) { if (!BitConverter.IsLittleEndian) { Array.Reverse(data, 0, 4); } offset = BitConverter.ToUInt32(data, 0); } // crc supplied if (data.Length > 5) { if (!BitConverter.IsLittleEndian) { Array.Reverse(data, 4, 2); } crc = BitConverter.ToUInt16(data, 4); } // do we have some version information if (data.Length > 6) { version = data[6]; } return(true); }
/// <summary> /// Makes a TripRoute frame. /// </summary> /// <param name="routeCode">Up to 4 characters for the route number/code. May be null if no route code is required</param> /// <param name="tripNo">The trip number (limited to 24 bits).</param> /// <returns>The packed frame.</returns> public static CANFrame PackFarebox(string routeCode, int?tripNo) { CANFrame frame = new CANFrame() { MailboxId = (uint)CNXMsgIds.RouteTrip }; // calculate the payload size byte[] data = new byte[(tripNo.HasValue ? 7 : 4)]; // fill the mandetory route code for (int i = 0; i < 4; ++i) { data[i] = 0; } // add the route code if (routeCode != null) { ASCIIEncoding ascii = new ASCIIEncoding(); byte[] rc = ascii.GetBytes(routeCode); Array.Copy(rc, data, (rc.Length > 4 ? 4 : rc.Length)); } // add the tripNo if (tripNo.HasValue) { byte[] intArray = BitConverter.GetBytes(tripNo.Value); // make sure byte 0 is lsb. if (!BitConverter.IsLittleEndian) { Array.Reverse(intArray); } Array.Copy(intArray, 0, data, 4, 3); } frame.Data = data; return(frame); }
/// <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(); }
/// <summary> /// Extracts trip progress information from the frame. /// </summary> /// <param name="frame">Trip progress frame.</param> /// <param name="msgType">Trip progress message type.</param> /// <param name="pathId">Id of the current path.</param> /// <param name="position">Position along the path.</param> /// <returns>True on success, false if the frame isnt a TripProgress frame or the data payload is the wrong size.</returns> public static bool UnpackTripProgress(CANFrame frame, out TripProgressType msgType, out int pathId, out int position, out int?tripNo) { pathId = 0; position = 0; tripNo = null; // validate message type and size if ((CNXMsgIds)frame.MailboxId != CNXMsgIds.TripProgress) { msgType = TripProgressType.Unknown; return(false); } byte[] data = frame.Data; msgType = (TripProgressType)data[0]; if (msgType != TripProgressType.ActiveOnRoute) { return(true); } byte[] intArray = new byte[4]; if (data.Length > 2) { intArray[0] = data[1]; intArray[1] = (byte)(data[2] & 0x07); intArray[2] = 0; intArray[3] = 0; if (!BitConverter.IsLittleEndian) { Array.Reverse(intArray); } pathId = BitConverter.ToInt32(intArray, 0); } if (data.Length > 3) { intArray[0] = (byte)(data[2] >> 3); intArray[0] |= (byte)(data[3] << 5); intArray[1] = (byte)(data[3] >> 3); intArray[2] = 0; intArray[3] = 0; if (!BitConverter.IsLittleEndian) { Array.Reverse(intArray); } position = BitConverter.ToInt32(intArray, 0); } if (data.Length > 6) { intArray[0] = data[4]; intArray[1] = data[5]; intArray[2] = data[6]; intArray[3] = 0; if (!BitConverter.IsLittleEndian) { Array.Reverse(intArray); } tripNo = BitConverter.ToInt32(intArray, 0); } return(true); }
/// <summary> /// Puts a BlockQueryResponce frame onto the CAN bus. /// </summary> public void SendBlockQueryResponce() { CANFrame resp = BuildQueryResponce(); mClient.Send(resp); }
/// <summary> /// Processes the CAN frame and writes any valid data to the block. /// </summary> /// <param name="frame"> /// Block frame. /// If the frame was a block query the responce is provided. /// Where no responce is required the frame mailbox will be set to 0. /// </param> /// <returns>The lowest complete data offset.</returns> public uint ProcessChunk(CANFrame frame) { if (mBlockId != (byte)(frame.MailboxId & 0xff)) { return(0); } try { // make sure we have a file if (mMemStream == null) { CreateMemoryStream(); } if (mMemStream == null) { return(0); } // save the current state BlockState state = BlockStatus; // process block type switch (frame.MailboxId & 0xf00) { // Chunk 1 case 0x600: lock (mBlockLock) { ProcessChunk1(frame.Data); } break; // Chunk N case 0x700: BlockState newState = state; lock (mBlockLock) { ProcessChunkN(frame.Data); newState = BlockStatus; } if (newState != state) { OnRaiseBlockStatusEvent(new BlockStatusEventArgs(mBlockId, newState)); } break; // Block Query case 0x400: SendBlockQueryResponce(); break; default: break; } //BlockState newState = BlockStatus; //if (newState != state) // OnRaiseBlockStatusEvent(new BlockStatusEventArgs(newState)); } catch (Exception e) { CNXLog.ErrorFormat("ProcessChunk frame {0} failed {1}.", frame.ToString(), e.ToString()); } return(mLastIndexWritten); }
/// <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 abstract int Send(CANFrame frame);
public FrameReceivedEventArgs(CANFrame frame) { mFrame = frame; }