//----------------------------------------------------------------------- // // Copyright © 2012 Nils Hammar. All rights reserved. // //----------------------------------------------------------------------- /* * Software to access vehicle information via the OBD-II connector. * * Copyright © 2012 Nils Hammar * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Alternative licensing is possible, see the licensing document. * * The above text may not be removed or modified. */ namespace SimProtocol.SimData { using System.Collections.Concurrent; using System.Collections.Generic; using SharedObjects; using SharedObjects.GUI; using SharedObjects.SimData; /// /// Data dictionary replaying logged data. /// /// Abstract class that shall be extended from in order to get a new data presentation. /// /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix", Justification = "Reviewed, intentional")] public abstract class DataDictionary : IDataDictionary { /// /// Gets or sets Record number counter. /// public int counter { get; protected set; } /// /// Gets or sets Record number counter. /// public uint scope { get; protected set; } /// /// Gets or sets last encountered timestamp. /// public double timestamp { get; protected set; } /// /// Gets Dictionary of all loaded modes from file. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "Reviewed, intentional")] public IDictionary> modeDictionary { get { return this.modeDict; } } /// /// Gets Event logging appender. /// protected ILogging iAppender { get; private set; } /// /// Gets Counter of added PIDs. /// protected uint pidCount { get; private set; } /// /// Dictionary of all loaded modes from file. /// private IDictionary> modeDict = new ConcurrentDictionary>(); /// /// Initializes a new instance of the class. /// /// Event logging instance. protected DataDictionary(ILogging iAppender) { this.iAppender = iAppender; this.pidCount = 0; this.scope = 0; this.timestamp = 0; } /// /// Dispose object. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Justification = "Reviewed.")] public abstract void Dispose(); /// /// Called when start of data replay shall occur. /// /// Callback interface to call when end of replay occurs. /// Replay speed scale factor. /// Time for start of replay. public abstract void playData(ISimEndPlay iSimEndPlay, double replaySpeed, uint startTime); /// /// Called when stop of data replay shall occur. /// public abstract void stopData(); /// /// Add one item to the dictionary. /// /// Current Mode byte value. /// Flag indicating if PID shall be echoed to caller or not. /// PID value. /// Payload data. protected void addDictionaryItem(uint mode, uint echoPid, uint pid, byte[] ba) { IDictionary pidDictionary; if (!this.modeDict.ContainsKey(mode)) { pidDictionary = new ConcurrentDictionary(); this.modeDict.Add(mode, pidDictionary); } else { pidDictionary = this.modeDict[mode]; } if (!pidDictionary.ContainsKey(pid)) { pidDictionary.Add(pid, new DictionaryItem(pid, echoPid, ba)); this.pidCount++; } else { pidDictionary[pid] = new DictionaryItem(pid, echoPid, ba); } } /// /// Build index entries for the given mode. /// /// Mode byte value. protected void indexMode(uint mode) { if (this.modeDict.ContainsKey(mode)) { IDictionary pidDictionary = this.modeDict[mode]; uint[] indexPids = { 0x00, 0x20, 0x40, 0x60, 0x80, 0xA0, 0xC0, 0xE0 }; for (int i = indexPids.Length - 1; i >= 0; i--) { uint bitmap = 0; for (int j = 1; j <= 0x20; j++) { bitmap = bitmap << 1; if ((j + indexPids[i]) < 0x100) { if (pidDictionary.ContainsKey((uint)(j + indexPids[i]))) { bitmap |= 1; } } } byte[] ba = new byte[4]; ba[0] = (byte)((bitmap >> 24) & 0xff); ba[1] = (byte)((bitmap >> 16) & 0xff); ba[2] = (byte)((bitmap >> 8) & 0xff); ba[3] = (byte)(bitmap & 0xff); pidDictionary.Add(indexPids[i], new DictionaryItem(indexPids[i], 1, ba)); #if TRACE_INDEX this.iAppender.appendTextLn("Indexed: mode=0x" + mode.ToString("X2") + ", PID=0x" + indexPids[i].ToString("X2") + ", mask=" + bitmap.ToString("X4") + " [" + Convert.ToString(bitmap, 2) + "]"); #endif } } else { this.iAppender.appendTextLn("No data to index for mode 0x" + mode.ToString("X2")); } } } }