//-----------------------------------------------------------------------
//
// 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"));
}
}
}
}