public override int ProcessBytes(byte[] bytes, int offset, int size) { N2kHeader n2kHeader = new N2kHeader(bytes[0], bytes[1], bytes[2], bytes[3]); byte[] n2kData = new byte[size - 4]; Array.Copy(bytes, 4, n2kData, 0, size - 4); N2kFrame n2kFrame = new N2kFrame(n2kHeader, n2kData, DateTime.Now); OnFrameCreated(n2kFrame); return(size); }
// Private methods private void ProcessN2kMessage(ActisenseMessage msg) { /* This N2kDataReceived message goes: * [0] Priority * [1] PGN LSB=Least Significant Byte * [2] PGN Middle Byte * [3] PGN MSB=MostSignificant Byte * [4] Destination * [5] Source * [6,7,8,9] Time stamp, LSB...MSB * [10] N2k payload length * [11, 12, ...] N2k payload (always 8 bytes in data seen so far) */ byte[] payload = msg.MessagePayload; byte Priority = payload[0]; int PGN = payload[1] + (payload[2] << 8) + (payload[3] << 16); byte Destination = payload[4]; byte Source = payload[5]; uint ms = BitConverter.ToUInt32(payload, 6); // TODO: Work out what the Actisense is transmitting in its time-stamp field // as the number of milliseconds appears to go down as well as up (according to a user report) // Note that the Actisense clock appears to be reset when the unit is reset by software, /* as indicated by the following R(read)/W(rite) sequence of commands * Clock 4 bytes * W: 10 2 A1 1 13 4B 10 3 * R: 10 2 93 13 2 2 FD 1 FF 3A 66 9F 0 0 8 FF 3 3 69 0 FA FF FF AC 10 3 * R: 10 2 A0 0E 13 1 0E 0 FA A4 1 0 0 0 0 0 0 1 90 10 3 * W: 10 2 A1 3 13 0 0 49 10 3 * R: 10 2 A0 0E 13 1 0E 0 FA A4 1 0 0 0 0 0 0 0 91 10 3 * W: 10 2 A1 1 10 10 4E 10 3 * R: 10 2 93 13 2 12 F1 1 FF 3A 98 9F 0 0 8 FF 0 0 FF 7F FF 7F FD E4 10 3 * R: 10 2 A0 22 10 10 1 0E 0 FA A4 1 0 0 0 0 0 6D 0 3C 9C 25 93 67 8 3C 9C 2A 93 67 0 BB AF 0 0 3 0 0 0 AB 10 3 * W: 10 2 A1 2 4C 2 0F 10 3 <- some sort of reset? * R: 10 2 A0 0D 4C 1 0E 0 FA A4 1 0 0 0 0 0 2 57 10 3 * W: 10 2 A1 1 13 4B 10 3 <- some sort of reset? * R: 10 2 A0 0F F0 1 0E 0 FA A4 1 0 0 0 0 0 67 8 0 44 10 3 * R: 10 2 93 13 2 12 F1 1 FF 3A 2D 0 0 0 8 FF 0 0 FF 7F FF 7F FD EE 10 3 */ // For now, we just use the computer's clock (and so don't get millisecond accuracy) DateTime thisTime; thisTime = DateTime.Now; //if (firstArrived) //{ // // Check for rollover. // if (ms < lastMs) // baseTime = baseTime.AddMilliseconds(uint.MaxValue); // being 8.1715 years // thisTime = baseTime.AddMilliseconds(ms); //} //else //{ // firstArrived = true; // thisTime = DateTime.Now; // baseTime = thisTime.AddMilliseconds(-ms); //} //lastMs = ms; int N2kDataLength = payload[10]; byte[] N2kData = new byte[N2kDataLength]; Array.Copy(payload, 11, N2kData, 0, N2kDataLength); N2kHeader Header = new N2kHeader(Priority, PGN, Destination, Source); N2kFrame frame = new N2kFrame(Header, N2kData, thisTime); OnFrameCreated(frame); }
// Public methods public static int PackFrame(N2kFrame n2kFrame, byte[] buffer) { /* [0] Message Protocol: 0x93 = N2kDataReceived * [1] Message body length (number of bytes 2, 3, ..., up to last byte before CRC) * [2] Priority * [3] PGN LSB=Least Significant Byte * [4] PGN Middle Byte * [5] PGN MSB=MostSignificant Byte * [6] Destination * [7] Source * [8,9,10,11] Time stamp, LSB...MSB * [12] N2k payload length * [13, 14, ..., 13+[12]=20 ] N2k payload (always 8 bytes in data seen so far) * [21] CRC byte, chosen so that the sum over all bytes is 0 (mod 256). */ // TODO : Test sending // - confirm CRC is generated correctly N2kHeader n2kHeader = n2kFrame.Header; buffer[0] = Escape; buffer[1] = StartOfText; buffer[2] = N2kDataReceived; // TODO : What should this be ? int pgn = n2kHeader.PGN; byte pgnLSB = (byte)(pgn & 0xFF); pgn >>= 8; byte pgnMDB = (byte)(pgn & 0xFF); pgn >>= 8; byte pgnMSB = (byte)(pgn & 0xFF); buffer[4] = n2kHeader.PGNPriority; buffer[5] = pgnLSB; buffer[6] = pgnMDB; buffer[7] = pgnMSB; buffer[8] = n2kHeader.PGNDestination; buffer[9] = n2kHeader.PGNSource; // Set timestamp bytes [10, 11, 12, 13] Array.Copy(BitConverter.GetBytes(DateTime.Now.Millisecond), 0, buffer, 10, 4); // Byte 14 : Length of n2k data buffer[14] = (byte)n2kFrame.Data.Length; // N2k data length : Bytes [15, CRCbyte) byte msgIdx = 15; for (int i = 0; i < n2kFrame.Data.Length; i++) { if (n2kFrame.Data[i] == Escape) { buffer[msgIdx++] = Escape; buffer[msgIdx++] = Escape; } else { buffer[msgIdx++] = n2kFrame.Data[i]; } } int byteSum = 0; for (int i = 2; i < msgIdx; i++) { byteSum += buffer[i]; } byteSum %= 256; buffer[msgIdx++] = (byte)((byteSum == 0) ? 0 : (256 - byteSum)); buffer[3] = (byte)(msgIdx - 5); // Message length : Bytes [4, CRCbyte) buffer[msgIdx++] = Escape; buffer[msgIdx++] = EndOfText; return(msgIdx); }