//----------------------------------------------------------------------- // // 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 SharedObjects.UdpServer { using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using SharedObjects.Protocol; /// /// CAN bus simulation using UDP socket communication. /// /// This is intended to be useful when no CAN hardware is present. /// /// public class UdpCanSimulation : IObdCommunicator { /// /// Gets or sets time in milliseconds between sent frames. /// public long frameSpacing { get; set; } /// /// IP endpoint address. /// private IPEndPoint ipep; /// /// UDP Socket. /// private UdpClient newsock; /// /// Thread for receiving of data. /// private Thread rxDataThread; /// /// Flag for thread. /// private bool doRun = false; /// /// Port number to communicate on. /// private int port; /// /// List of data receivers. /// private IList iDataReceiverList = new List(); /// /// Initializes a new instance of the class. /// /// Port number to communicate on. public UdpCanSimulation(int port) { this.port = port; this.ipep = new IPEndPoint(IPAddress.Any, port); this.newsock = new UdpClient(); this.newsock.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); this.newsock.Client.Bind(this.ipep); } /// /// Clean up. /// public void Dispose() { this.Dispose(true); GC.SuppressFinalize(this); } /// /// Unregister as a data receiver instance /// /// Data receiver instance. public void removeDataReceiver(ISessionLayer iDataReceiver) { if (this.iDataReceiverList.Contains(iDataReceiver)) { this.iDataReceiverList.Remove(iDataReceiver); } } /// /// Register as a data receiver instance /// /// Data receiver instance. public void addDataReceiver(ISessionLayer iDataReceiver) { if (!this.iDataReceiverList.Contains(iDataReceiver)) { this.iDataReceiverList.Add(iDataReceiver); } } /// /// Send data. /// /// Target address. /// Data to send. public void send(uint id, byte[] payload) { if (payload != null) { byte[] data = new byte[payload.Length + 4]; data[0] = (byte)((id >> 24) & 0xff); data[1] = (byte)((id >> 16) & 0xff); data[2] = (byte)((id >> 8) & 0xff); data[3] = (byte)(id & 0xff); Array.Copy(payload, 0, data, 4, payload.Length); IPEndPoint sender = new IPEndPoint(IPAddress.Broadcast, this.port); this.newsock.Send(data, data.Length, sender); } } /// /// Start CAN communication. /// public void startConnection() { this.doRun = true; this.rxDataThread = new Thread(this.rxDataThreadImpl); this.rxDataThread.Start(); } /// /// Stop CAN communication. /// public void stopConnection() { this.doRun = false; this.newsock.Close(); this.rxDataThread.Abort(); } /// /// Clean up. /// /// 'true' if disposing. protected virtual void Dispose(bool disposing) { this.doRun = false; this.stopConnection(); } /// /// Implementation of thread to receive data. /// private void rxDataThreadImpl() { byte[] data = new byte[4096]; IPEndPoint sender = new IPEndPoint(IPAddress.Any, this.port); while (this.doRun) { data = this.newsock.Receive(ref sender); if (data.Length > 4) { uint addr = 0; for (int i = 0; i < 4; i++) { addr = addr << 8; addr |= data[i]; } byte[] ba = new byte[data.Length - 4]; Array.Copy(data, 4, ba, 0, ba.Length); foreach (ISessionLayer iDataReceiver in this.iDataReceiverList) { iDataReceiver.receiveData(addr, ba, 0x00, 0x00, 0x00); } } } } } }