private void OnMessageReceived(ActisenseMessage msg) { if (!msg.CRCisOK) { if (BadCRCMessageReceived != null) { BadCRCMessageReceived(msg); } return; } if (ValidMessageReceived != null) { ValidMessageReceived(msg); } switch (msg.MessageType) { case N2kDataReceived: var e = N2kMessageReceived; if (e != null) { e(msg); } break; default: // TODO: This is some other Actisense message, eg a status message. Process it somehow... break; } }
// 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 override int ProcessBytes(byte[] bytes, int offset, int size) { // Loop through data int numRead = 0; for (int i = 0; i < size; i++) { byte nextByte = bytes[offset + i]; if (_escapeRead) { switch (nextByte) { case Escape: _buffer[_bufferIdx++] = Escape; break; case StartOfText: _bufferIdx = 0; _headerRead = true; break; case EndOfText: if (!_headerRead) { // End of text, but no header read => Came in half way through frame _escapeRead = false; return(numRead); } else { _headerRead = false; _escapeRead = false; // Message complete ActisenseMessage actiMsg = new ActisenseMessage(_buffer, 0); OnMessageReceived(actiMsg); // Continue reading. numRead = i + 1; break; } default: // Unexpected character ! _headerRead = false; _escapeRead = false; return(numRead); } _escapeRead = false; } else { if (nextByte == Escape) { _escapeRead = true; } else if (_headerRead) { _buffer[_bufferIdx++] = nextByte; } else { // Unknown character. Not escaped, but not part of the message return(numRead); } } } // Read entire byte[] given return(size); }