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