//-----------------------------------------------------------------------
//
// 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 ObdSimulator.Protocol
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using global::SharedObjects;
using global::SharedObjects.Protocol;
///
/// Implements the ISO9141 protocol.
///
public class SerialSessionLayer : AbstractSessionLayer
{
///
/// Data buffer.
///
private string buf = string.Empty;
///
/// Received data without header (payload part).
///
private List rxData = new List();
///
/// Event logging instance.
///
private IDataLogging iDataLogging;
///
/// 'true' if checksum shall be expected.
///
private bool expectChecksum;
///
/// List of received data bytes.
///
private List dataRecord = new List();
///
/// Array of transmitted data.
///
private byte[] txDataArray = null;
///
/// Lock object to avoid race conditions.
///
private object lockObject = new object();
///
/// List of data receivers.
///
private IList iPresentationLayerList = new List();
///
/// Communicator instance.
///
private IObdCommunicator iObdCommunicator;
///
/// Simulation engine instance.
///
private ISimEngine iSimEngine;
///
/// Initializes a new instance of the class.
///
/// Event logging instance.
/// 'true' if checksum shall be expected.
/// Data transmitter instance.
public SerialSessionLayer(IDataLogging iDataLogging, bool expectChecksum)
{
this.iDataLogging = iDataLogging;
this.expectChecksum = expectChecksum;
}
///
/// Set the simulation engine.
///
/// Simulation engine instance.
public override void setSimEngine(ISimEngine iSimEngine)
{
this.iSimEngine = iSimEngine;
}
///
/// Handle dispose of object.
///
public override void Dispose()
{
this.Dispose(true);
}
///
/// Handle dispose of object.
///
///
public void Dispose(bool disposing)
{
if (this.iPresentationLayerList != null)
{
this.iPresentationLayerList.Clear();
}
}
///
/// Send data.
///
/// Target address.
/// Data to send.
public override void sendData(uint outAddress, IList response, uint dataLen)
{
if (response != null)
{
if (this.iSimEngine != null)
{
this.iSimEngine.addRow(rowMode.session_out, outAddress, 0, 0, 0, Utils.listToHexString(response));
}
byte[] payload = ((List)response).ToArray();
this.iObdCommunicator.send(outAddress, payload);
}
}
///
/// Set CAN bus communicator instance.
///
/// CAN bus communicator instance.
public override void setObdCommunicator(IObdCommunicator iObdCommunicator)
{
if (iObdCommunicator == null && this.iObdCommunicator != null)
{
this.iObdCommunicator.removeDataReceiver(this);
}
this.iObdCommunicator = iObdCommunicator;
if (iObdCommunicator != null)
{
this.iObdCommunicator.addDataReceiver(this);
}
}
///
/// Receive one data packet.
///
/// Address value.
/// Payload data.
/// Flags value.
/// RES1 Value.
/// RES2 Value.
public override void receiveData(uint id, byte[] data0, ushort flags, ulong res1, ulong res2)
{
if (this.iSimEngine != null)
{
this.iSimEngine.addRow(rowMode.transport_in, id, 0x00, 0, 0, Utils.arrayToString(data0, 0) + ", flags=0x" + flags.ToString("X2") + ", res1=0x" + res1.ToString("X2") + ", res2=0x" + res2.ToString("X2"));
}
foreach (IPresentationLayerToSession dataRx in this.iPresentationLayerList)
{
dataRx.processPayload(id, 0x00, (uint)data0.Length, data0);
}
}
///
/// Unregister as a data receiver instance
///
/// Data receiver instance.
public override void removePresentationLayer(IPresentationLayerToSession iDataReceiver)
{
if (this.iPresentationLayerList.Contains(iDataReceiver))
{
this.iPresentationLayerList.Remove(iDataReceiver);
}
}
///
/// Register as a data receiver instance
///
/// Data receiver instance.
public override void addPresentationLayer(IPresentationLayerToSession iDataReceiver)
{
if (!this.iPresentationLayerList.Contains(iDataReceiver))
{
this.iPresentationLayerList.Add(iDataReceiver);
}
}
///
/// Activate service parser and parse payload data.
///
private void activateServiceParser()
{
byte[] ba = this.dataRecord.ToArray();
this.dataRecord.Clear();
lock (this.lockObject)
{
if (this.txDataArray != null)
{
int n = ba.Length - this.txDataArray.Length;
if (n > 0)
{
byte[] ba2 = new byte[n];
Array.Copy(ba, this.txDataArray.Length, ba2, 0, n);
ba = ba2;
}
}
this.iDataLogging.appendRow("In", ba);
}
if (this.rxData.Count > 0)
{
byte[] payload = this.rxData.ToArray();
byte[] ba2 = new byte[payload.Length + 1];
Array.Copy(payload, 0, ba2, 1, payload.Length);
ba2[0] = (byte)payload.Length;
this.receiveData(0x00, ba2, 0x00, 0x00, 0x00);
}
this.buf = string.Empty;
this.rxData.Clear();
}
}
}