/// <summary> /// This function sends out a FDXDatagram /// </summary> /// <param name="datagram">the datagram that is to be send</param> /// <returns></returns> public int Send(ref FDXDatagram datagram) { //Set the current valid sequence number datagram.SetSequenceNumber(this.mNextTransmitSequenceNumber); // convert the datagram object to a byte array var outData = datagram.GenerateBuffer(); var res = this.mSocket.Send(outData, outData.Length); // Increment the sequence number for the next datagram this.mNextTransmitSequenceNumber = FDXDatagram.IncrementSequenceNumber(this.mNextTransmitSequenceNumber); return(res); }
/// <summary> /// This function receives a datagram on the socket /// </summary> /// <param name="datagram">Reference to a datagram to store the information</param> /// <returns>size of the received datagram, -1 if no data is received</returns> public int Receive(ref FDXDatagram datagram) { // Get the IPEndpoint var ep = new System.Net.IPEndPoint(this.mCanoeAddr, this.mPort); try { if (this.mSocket.Available > 0) { datagram.Buffer = this.mSocket.Receive(ref ep); } } catch (System.Net.Sockets.SocketException) { Console.Out.WriteLine("No answer from CANoe Client"); return(-1); } return(datagram.Buffer.Length); }
public void DispatchDatagram(ref FDXDatagram datagram) { var lCopy = datagram.Buffer; //if the received bytes are too short, skip if (lCopy.Length < 16) { this.OnFormatError("Datagram too short"); return; } // extract datagram header information var header = DatagramHeader.DeSerialize(lCopy); //if the signature doesn't match, skip if (header.FDXSignature != FDXHelper.kFDXSignature) { this.OnFormatError("Signature mismatch"); return; } //if the major version doesn't match, skip if (header.FDXMajorVersion != FDXHelper.kFDXMajorVersion) { this.OnFormatError("Incorrect Major version"); return; } //if the minor version doesn't match, skip if (header.FDXMinorVersion != FDXHelper.kFDXMinorVersion) { this.OnFormatError("Incorrect Minor Version"); return; } //checking the sequence number if (header.SequenceNumber == FDXHelperSequenceNumber.kSequenceNumberUnused) { //we don't use sequence numbering } else { // check if the received sequence number is the expected if ((header.SequenceNumber & 0x7FFF) != this.mNextExpectedSequenceNumber) { this.OnSequenceError(this.mNextExpectedSequenceNumber, header.SequenceNumber); } // if the session end sequence number arrives, reset the expected sequence number else if ((header.SequenceNumber & FDXHelperSequenceNumber.kSequenceNumberSessionEndFlag) != 0) { this.mNextExpectedSequenceNumber = FDXHelperSequenceNumber.kSequenceNumberStart; } else { // if expected sequence number matches the received sequence number this.mNextExpectedSequenceNumber = FDXDatagram.IncrementSequenceNumber(header.SequenceNumber); } } //extract the number of commands and set the position var numOfCommands = header.NumberOfCommands; var commandPosAndLength = DatagramHeader.Size(); //create a buffer for the single commands var data = new byte[lCopy.Length - commandPosAndLength]; for (var i = 0; i < numOfCommands; ++i) { //copy command number i into the buffer Array.Copy(lCopy, commandPosAndLength, data, 0, lCopy.Length - commandPosAndLength); //extract the header information and copy the data from the buffer into the concrete command // buffer var cmdHead = CommandHeader.DeSerialize(data); var concreteCommand = new byte[cmdHead.CommandSize]; Array.Copy(data, 0, concreteCommand, 0, concreteCommand.Length); commandPosAndLength += concreteCommand.Length; // with the command code we can decide what to do with the received command switch (cmdHead.CommandCode) { case FDXHelperCommandCode.kCommandCodeDataExchange: { var cmd = DataExchangeCommand.DeSerialize(concreteCommand); this.OnDataExchange(cmd); break; } case FDXHelperCommandCode.kCommandCodeStatus: { var cmd = StatusCommand.DeSerialize(concreteCommand); this.OnStatus(cmd); break; } case FDXHelperCommandCode.kCommandCodeSequenceNumberError: { var com = SequenceNumberErrorCommand.DeSerialize(concreteCommand); this.OnSequenceError(com.ExpectedSeqNr, com.ReceivedSeqNr); break; } } } }
static void Main(string[] args) { //Register delegate to catch CTRL-C on the console Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { e.Cancel = true; sKeepRunning = false; }; Console.Out.WriteLine("The FDX-Client can be terminated with CTRL-C"); var addr = String.Empty; ushort port = 0; sbyte cProbCapModifier = 1; var isFuelConsumingActive = false; //setup connection parameters when specified if (args.Length == 2) { addr = args[0]; port = ushort.Parse(args[1]); } //Create socket, diagram and Dispatcher var fdxSocket = new FDXSocket(); var fdxDatagram = new FDXDatagram(); var disp = new A429DataDispatcher(); //Create data packet and initialize with data var data = new A429InputData { FuelTempAndAdvisoryWarning = -2048, ProbeCapacitance = 0 }; var ovhdData = new A429OvhdData(); //Set the new connection settings only when specified if (addr != string.Empty) { fdxSocket.SetCANoeAddr(addr, port); } fdxSocket.Open(); //Initialize datagram and set start command fdxDatagram.InitWithHeader(); fdxDatagram.AddStartCommand(); //Send start command to CANoe fdxSocket.Send(ref fdxDatagram); // wait one second for initializing CANoe Thread.Sleep(1000); while (sKeepRunning) { fdxDatagram.InitWithHeader(); //Update values only when measurement is running if (FDXHelperMeasurementState.CurrentMeasurementState == FDXHelperMeasurementState.kMeasurementStateRunning) { if (data.FuelTempAndAdvisoryWarning < 2048) { data.FuelTempAndAdvisoryWarning += 4; } else { data.FuelTempAndAdvisoryWarning = -2048; } if (cProbCapModifier == 1 && data.ProbeCapacitance > 399) { cProbCapModifier = -1; } else if (cProbCapModifier == -1 && data.ProbeCapacitance < 1) { cProbCapModifier = 1; } else { // activate fuel consumption when probe capacitance is over 100 if (isFuelConsumingActive == false && data.ProbeCapacitance > 10) { ovhdData.SysMainEng1 = 1; ovhdData.SysMainEng2 = 1; ovhdData.SysMainEng3 = 1; ovhdData.SysMainEng4 = 1; ovhdData.SysTTankL = 1; ovhdData.SysTTankR = 1; fdxDatagram.AddDataExchange(A429OvhdData.sGroupId, ovhdData.Serialize()); isFuelConsumingActive = true; } // deactivate fuel consumption when probe capacitance is under 100 else if (isFuelConsumingActive && data.ProbeCapacitance <= 10) { ovhdData.SysMainEng1 = 0; ovhdData.SysMainEng2 = 0; ovhdData.SysMainEng3 = 0; ovhdData.SysMainEng4 = 0; ovhdData.SysTTankL = 0; ovhdData.SysTTankR = 0; fdxDatagram.AddDataExchange(A429OvhdData.sGroupId, ovhdData.Serialize()); isFuelConsumingActive = false; } data.ProbeCapacitance += (0.4f * cProbCapModifier); } fdxDatagram.AddDataExchange(A429InputData.sGroupId, data.Serialize()); fdxDatagram.AddDataRequest(A429OutputData.sGroupId); } //poll status whether measurement is not running fdxDatagram.AddStatusRequest(); fdxSocket.Send(ref fdxDatagram); //receive and dispatch datagram if (fdxSocket.Receive(ref fdxDatagram) > -1) { disp.DispatchDatagram(ref fdxDatagram); } // sleep 250ms for next interval Thread.Sleep(250); } //Wait one second before shutting down CANoe Thread.Sleep(1000); //Init and send stop command fdxDatagram.InitWithHeader(); fdxDatagram.AddStopCommand(); fdxSocket.Send(ref fdxDatagram); }