using System; using System.Collections; using System.Collections.Generic; /// /// Summary description for Class1 /// namespace Sensor.Gateway.DataXfer { public class Decompressor { #region variables private List _factories = new List(); private SortedList _packetIdentifiers = new SortedList(); private List _decompressedRecords = new List(); private List _flashRecords = new List(); private List _journalRecords = new List(); private ushort[] _lastSensorVals; public ushort[] LastSensorVals { get { return _lastSensorVals; } set { _lastSensorVals = value; } } private Int32 _sampleInterval; private Int32 _localTime; private Int32 _rebootCounter; public Int32 SampleInterval{ get { return _sampleInterval; } } public Int32 LocalTime { get { return _localTime; } set { _localTime = value; } } public Int32 RebootCounter { get { return _rebootCounter; } set { _rebootCounter = value; } } private int _downloadId; private ArrayList getRecordsOfType(Type t) { ArrayList ret = new ArrayList(); for (int k = 0; k < _decompressedRecords.Count; k++) { if (_decompressedRecords[k].GetType() == t) { ret.Add(_decompressedRecords[k]); } } return ret; } internal ArrayList getGPSRecords() { return getRecordsOfType(Type.GetType("Sensor.Gateway.DataXfer.DecompressedGPSRecord")); } internal ArrayList getFlashRecords() { return getRecordsOfType(Type.GetType("Sensor.Gateway.DataXfer.FlashRecord")); } internal ArrayList getJournalRecords() { return getRecordsOfType(Type.GetType("Sensor.Gateway.DataXfer.JournalRecord")); } internal ArrayList getAnchorRecords() { return getRecordsOfType(Type.GetType("Sensor.Gateway.DataXfer.DecompressedAnchorRecord")); } private FlashRecord _lastRecord; private int _nodeId; public int NodeId { get { return _nodeId; } } #endregion variables #region conversion public static UInt64 convert64(int offset, byte[] b) { UInt64 result = 0; for (int k = 0; k < 8; k++) { result |= b[offset + k]; if(k!=7) result <<= 8; // result |= ((UInt64)b[offset + k]) << 56 - (8 * k); } return result; } public static UInt32 convert32(int offset, byte[] b) { UInt32 result = 0; for (int k = 0; k < 4; k++) { result |= b[offset + k]; if(k != 3) result <<= 8; //result |= ((UInt32)b[offset + k]) << 24 - (8 * k); } return result; } public static UInt16 convert16(int offset, byte[] b) { UInt16 result = 0; for (int k = 0; k < 2; k++) { result |= b[offset + k]; if (k != 1) result <<= 8; //result |= ((UInt32)b[offset + k]) << 24 - (8 * k); } //result = (b[offset]);// << 8; return result; } #endregion conversion public Decompressor(int downloadId_, FlashRecord lastRecord_, int nodeId){ _downloadId = downloadId_; _localTime = 0; _rebootCounter = -1; _lastSensorVals = new ushort[10]; _lastRecord = lastRecord_; _sampleInterval = 30*1024; _nodeId = nodeId; //_factories.Add(new RebootRecordFactory()); _factories.Add(new CRCRecordFactory()); _factories.Add(new AnchorRecordFactory()); //TODO: read record descriptors in from config file? /* _factories.Add(new SampleRecordFactory(new SampleRecordDescriptor(0xc0, new byte[] { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 4))); _factories.Add(new SampleRecordFactory(new SampleRecordDescriptor(0xd0, new byte[] { 0x08, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 4))); _factories.Add(new SampleRecordFactory(new SampleRecordDescriptor(0xe0, new byte[] { 0x08, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 }, 4))); _factories.Add(new SampleRecordFactory(new SampleRecordDescriptor(0xf0, new byte[] { 0x0C, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 }, 4))); _factories.Add(new SampleRecordFactory(new SampleRecordDescriptor(0x00, new byte[] { 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 }, 8))); */ /* Olin _factories.Add(new SampleRecordFactory(new SampleRecordDescriptor(0x50, new byte[] { 2, 2, 3, 5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 4))); _factories.Add(new SampleRecordFactory(new SampleRecordDescriptor(0x60, new byte[] { 3, 3, 2, 4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 4))); _factories.Add(new SampleRecordFactory(new SampleRecordDescriptor(0x70, new byte[] { 2, 2, 4, 4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 4))); _factories.Add(new SampleRecordFactory(new SampleRecordDescriptor(0x80, new byte[] { 3, 3, 3, 3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 4))); _factories.Add(new SampleRecordFactory(new SampleRecordDescriptor(0x90, new byte[] { 4, 4, 2, 2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 4))); _factories.Add(new SampleRecordFactory(new SampleRecordDescriptor(0xa0, new byte[] { 5, 5, 4, 6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 4))); _factories.Add(new SampleRecordFactory(new SampleRecordDescriptor(0xb0, new byte[] { 4, 5, 6, 5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 4))); _factories.Add(new SampleRecordFactory(new SampleRecordDescriptor(0xc0, new byte[] { 3, 3, 7, 7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 4))); _factories.Add(new SampleRecordFactory(new SampleRecordDescriptor(0xd0, new byte[] { 5, 5, 5, 5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 4))); _factories.Add(new SampleRecordFactory(new SampleRecordDescriptor(0xe0, new byte[] { 11, 11, 11, 11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 4))); _factories.Add(new SampleRecordFactory(new SampleRecordDescriptor(0x00, new byte[] { 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 }, 8))); */ //Brazil _factories.Add(new SampleRecordFactory(new SampleRecordDescriptor(0x50, new byte[] { 3, 3, 3, 3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 4))); _factories.Add(new SampleRecordFactory(new SampleRecordDescriptor(0x60, new byte[] { 3, 3, 2, 4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 4))); _factories.Add(new SampleRecordFactory(new SampleRecordDescriptor(0x70, new byte[] { 5, 5, 4, 6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 4))); _factories.Add(new SampleRecordFactory(new SampleRecordDescriptor(0x80, new byte[] { 4, 4, 6, 6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 4))); _factories.Add(new SampleRecordFactory(new SampleRecordDescriptor(0x90, new byte[] { 5, 5, 5, 5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 4))); _factories.Add(new SampleRecordFactory(new SampleRecordDescriptor(0xa0, new byte[] { 4, 4, 4, 8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 4))); _factories.Add(new SampleRecordFactory(new SampleRecordDescriptor(0xb0, new byte[] { 4, 4, 5, 7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 4))); _factories.Add(new SampleRecordFactory(new SampleRecordDescriptor(0xc0, new byte[] { 6, 7, 7, 8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 4))); _factories.Add(new SampleRecordFactory(new SampleRecordDescriptor(0xd0, new byte[] { 6, 6, 7, 9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 4))); _factories.Add(new SampleRecordFactory(new SampleRecordDescriptor(0xe0, new byte[] { 6, 6, 6, 10, 0x00, 0x00, 0x00, 0x00, 0x00,0x00}, 4))); _factories.Add(new SampleRecordFactory(new SampleRecordDescriptor(0xf0, new byte[] { 9, 9, 9, 9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 4))); _factories.Add(new SampleRecordFactory(new SampleRecordDescriptor(0x00, new byte[] { 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 }, 8))); _factories.Add(new GPSRecordFactory()); _factories.Add(new JournalRecordFactory()); } internal void addLine(string line) { PacketIdentifier pi = new PacketIdentifier(_downloadId , line); _packetIdentifiers.Add(pi._leftPtr, pi); } public void setCRCs(int bytesCovered, int index, bool passed) { IEnumerator iter = _packetIdentifiers.Values.GetEnumerator(); while (iter.MoveNext() && iter.Current.ByteStart < index) { IEnumerator inner = iter.Current.CompressedRecords.GetEnumerator(); while(inner.MoveNext()){ if (inner.Current.ByteStart >= index - bytesCovered) { inner.Current.CRC = passed; } } } } internal void decompress() { List bl = new List(); foreach (PacketIdentifier pi in _packetIdentifiers.Values) { int byteStart = bl.Count; pi.ByteStart = byteStart; bl.AddRange(pi.Bytes); } int byteIndex = 0; if (_lastRecord != null) { _localTime = _lastRecord.LocalClock; _rebootCounter = _lastRecord.Reboots; //System.Buffer.BlockCopy(_lastRecord.Measurement, 0, _lastSensorVals, 0, 20);//TODO: swap endian for (int k = 0; k < 10; k++ ) { byte[] tmp = Utils.ChangeEndian(_lastRecord.Measurement, 2 * k, 2); System.Buffer.BlockCopy(tmp, 0, _lastSensorVals, 2*k, 2); } byteIndex = (int)(_lastRecord.RightPtr - _packetIdentifiers.Values[0]._leftPtr); //hack! //The problem is that when we compute leftptr/rightptr for samples, we assume that either: //a. the sample being decompressed is the first sensor sample in the packet and we let leftptr=packet.leftpr //b. the sample being decompressed is not the first, and we let leftptr = packet.leftptr + sum(lengths of the other compressed records) //however, if this decompressor is starting at a partially-processed packet, there may be some non-sample records before the last record in the db // and this means that we are going to get a different leftptr than we otherwise would (b/c it would be missing some of the "other compressed records" above) _packetIdentifiers.Values[0].CompressedRecords.Add(new DummyCompressedRecord((int)(_lastRecord.RightPtr - _lastRecord.LeftPtr))); _packetIdentifiers.Values[0].FirstLeftPtr = _lastRecord.LeftPtr; //TODO: detect rubbish duplicates here? } // throw new Exception("Last record.rp " + _lastRecord.RightPtr + " pi.lp " + _packetIdentifiers.Values[0]._leftPtr + " index " + byteIndex); byte[] byteArr = bl.ToArray(); // PacketIdentifier[] piArr = _packetIdentifiers.Values.; IEnumerator iter = _packetIdentifiers.Values.GetEnumerator(); iter.MoveNext(); PacketIdentifier curPI = iter.Current; while (byteIndex < byteArr.Length) { int startBI = byteIndex; //keep correct packet identifier for (; byteIndex > curPI.ByteStart + curPI.Bytes.Length; iter.MoveNext()) { curPI = iter.Current; curPI.FirstLeftPtr = curPI._leftPtr + (byteIndex - curPI.ByteStart); } foreach( RecordFactory rf in _factories){ if (rf.isMatch(byteIndex, byteArr)) { //parse compressed record out of raw data CompressedRecord cr = rf.build(byteIndex, byteArr, curPI); //add the decompressed records to our array of all decompressed records _decompressedRecords.AddRange(cr.decompress(this)); //add this compressed record to the packet it came from curPI.CompressedRecords.Add(cr); //move it on up byteIndex += cr.Length; break; } } if (startBI == byteIndex) { throw new Exception("Unmatched record for index " + byteIndex + " byte " + byteArr[byteIndex] + " from packet " + curPI._nodeid + " " + curPI._leftPtr); } } byteIndex = 0; } } }