/// <summary> /// Send an acknowledgement message. /// </summary> /// <param name="a_rowNr">The row number that should be acknowledged.</param> private void sendAck(uint a_rowNr) { CANMessage msg = new CANMessage(0x266, 0, 5); msg.elmExpectedResponses = (a_rowNr == 0)?0:1; uint i = 0; ulong data = 0; data = setCanData(data, (byte)0x40, i++); data = setCanData(data, (byte)0xA1, i++); data = setCanData(data, (byte)0x3F, i++); data = setCanData(data, (byte)(0x80 | (int)(a_rowNr)), i++); msg.setData(data); if (!m_canDevice.sendMessage(msg)) { throw new Exception("Error sending ack"); } }
/// <summary> /// Start a KWP session. /// </summary> /// <remarks> /// A KWP session must be started before any requests can be sent. /// </remarks> /// <returns>True if the session was started, otherwise false.</returns> public bool startSession() { CANMessage msg = new CANMessage(0x220, 0, 8); msg.setData(0x000040021100813F); AddToCanTrace("Sending 0x000040021100813F message"); m_kwpCanListener.setupWaitMessage(0x238); if (!m_canDevice.sendMessage(msg)) { AddToCanTrace("Unable to send 0x000040021100813F message"); return(false); } Console.WriteLine("Init msg sent"); if (m_kwpCanListener.waitMessage(timeoutPeriod).getID() == 0x238) { AddToCanTrace("Successfully sent 0x000040021100813F message and received reply 0x238"); return(true); } else { AddToCanTrace("Didn't receive 0x238 message as reply on 0x000040021100813F message"); return(false); } /* if (!m_canDevice.sendMessage(msg)) * { * AddToCanTrace("Unable to send 0x000040021100813F message"); * return false; * } * Console.WriteLine("Init msg sent"); * if (m_kwpCanListener.waitForMessage(0x238, timeoutPeriod).getID() == 0x238) * { * AddToCanTrace("Successfully sent 0x000040021100813F message and received reply 0x238"); * return true; * } * else * { * AddToCanTrace("Didn't receive 0x238 message as reply on 0x000040021100813F message"); * return false; * } */ }
public void BackgroundRun(bool IsUserAbort) { Executor(IsUserAbort); CANMessage[] canMessages = new CANMessage[32]; int num = CANDevice.Receive(CANPortIndex, canMessages); for (int i = 0; i < num; i++) { if (IsShowSendRecive) { WriteLine("Receive:" + canMessages[i].ToString()); } Executor(canMessages[i]); Executor(); } Executor(); }
private void StartFirmwareUpdateProcedure(string deviceVersion) { if (ForceUpdate || deviceVersion != FirmwareFileVersion) { Console.WriteLine("Starting update to {0}", FirmwareFileVersion); var canMessage = new CANMessage(BuildCANId(CANMaerklinCommand.Reset, CS2AddressHash), new byte[] { 0x00, 0x00, 0x00, 0x00, 0x80, 0xff }); Array.Copy(CurrentDeviceId.HexStringToByteArray(), 0, canMessage.Data, 0, 4); serialCAN.SendCAN(canMessage); /* delay for boot ? */ Thread.Sleep(500); serialCAN.SendCAN(new CANMessage(BuildCANId(CANMaerklinCommand.Bootloader, CS2AddressHash), new byte[0])); } else { Console.WriteLine("Firmware already installed."); UpdateCompletedAutoResetEvent.Set(); UpdateRunning = false; } }
/// <summary> /// Send a message that starts a session. This is used to test if there is /// a connection. /// </summary> /// <returns></returns> private bool sendSessionRequest() { CANMessage msg1 = new CANMessage(0x220, 0, 8); LAWICEL.CANMsg msg = new LAWICEL.CANMsg(); msg1.setData(0x000040021100813f); if (!sendMessage(msg1)) { return(false); } if (waitForMessage(0x238, 1000, out msg) == 0x238) { //Ok, there seems to be a ECU somewhere out there. //Now, sleep for 10 seconds to get a session timeout. This is needed for //applications on higher level. Otherwise there will be no reply when the //higher level application tries to start a session. Thread.Sleep(10000); return(true); } return(false); }
//------------------------------------------------------------------------- /** * Waits for arrival of a specific CAN message or any message if ID = 0. * * @param a_canID message ID * @param timeout timeout, ms * @param canMsg message * * @return message ID */ public uint waitForMessage(uint a_canID, uint timeout, out CANMessage canMsg) { canMsg = new CANMessage(); Debug.Assert(canMsg != null); canMsg.setID(0); caCombiAdapter.caCANFrame frame = new caCombiAdapter.caCANFrame(); if (this.combi.CAN_GetMessage(ref frame, timeout) && (frame.id == a_canID || a_canID == 0)) { // message received canMsg.setID(frame.id); canMsg.setLength(frame.length); canMsg.setData(frame.data); return(frame.id); } // timed out return(0); }
/// <summary> /// readMessages is the "run" method of this class. It reads all incomming messages /// and publishes them to registered ICANListeners. /// </summary> public void readMessages() { int readResult = 0; LAWICEL.CANMsg r_canMsg = new LAWICEL.CANMsg(); CANMessage canMessage = new CANMessage(); while (true) { lock (m_synchObject) { if (m_endThread) { return; } } readResult = LAWICEL.canusb_Read(m_deviceHandle, out r_canMsg); if (readResult == LAWICEL.ERROR_CANUSB_OK) { canMessage.setID(r_canMsg.id); canMessage.setLength(r_canMsg.len); canMessage.setTimeStamp(r_canMsg.timestamp); canMessage.setFlags(r_canMsg.flags); canMessage.setData(r_canMsg.data); lock (m_listeners) { foreach (ICANListener listener in m_listeners) { listener.handleMessage(canMessage); } } } else if (readResult == LAWICEL.ERROR_CANUSB_NO_MESSAGE) { Thread.Sleep(1); } } }
public CanFrameEventArgs(CANMessage message) { _message = message; }
// ############################################################################## static public int GetCANMess(byte InterfaceNum, byte DeviceNum, ref CANMessage Msg) { byte[] USBOutBuf = new byte[30]; byte[] USBInBuf = new byte[100]; int Result; if (InterfaceNum > 9) { return(Resp_ErrImproperCallingParameter); } if (!ClassInit[InterfaceNum]) { Result = Init(InterfaceNum); if (Result == Resp_ErrNoInterfacePresent) { return(Result); } } USBOutBuf[0] = DeviceNum; USBOutBuf[1] = (byte)LLCMD.GETCANMESREQ; Result = USBRawCommand(InterfaceNum, USBOutBuf, 2, ref USBInBuf); if (Result < 0) { return(Result); // return error } if ((int)USBInBuf[0] != (int)LLCMD.GETCANMESRESP) { return(Resp_ErrImproperResponse); //improper response from node } if ((int)USBInBuf[1] == 0) { return(Resp_NAck); } Msg.DLC = (byte)(USBInBuf[4] & 0x0F); Msg.MO = ((USBInBuf[1] & 0x10) > 0) ? (byte)1 : (byte)0; // two message objects defined by 0x10 bit Msg.ID = ((long)(USBInBuf[6] & 0x3F)) << 24; // lose the top two bits Msg.ID |= ((long)USBInBuf[7] << 16); Msg.ID |= ((long)USBInBuf[8] << 8); Msg.ID |= (long)USBInBuf[9]; Msg.EID = ((USBInBuf[5] & 0x80) > 0) ? true : false; // extended ID Msg.RTR = ((USBInBuf[5] & 0x40) > 0) ? true : false; // RTR true Msg.BOF = ((USBInBuf[5] & 0x20) > 0) ? true : false; // Buffer Overflow Msg.SendOption = 0; for (int c = 0; c < Msg.DLC; c++) { Msg.Data[c] = USBInBuf[c + 10]; } if (USBInBuf[3] == (Msg.DLC + 10)) // timestamp { Msg.TimeStamp = (long)USBInBuf[Msg.DLC + 10] * .524288; Msg.TimeStamp += ((long)USBInBuf[Msg.DLC + 11] * .002048); Msg.TimeStamp += ((long)USBInBuf[Msg.DLC + 12] * .000008); } else { Msg.TimeStamp = 0; } return(Resp_Ack); }
// ############################################################################## // Error Int is returned with the two byte values from the MCP2515, the highest byte // is from the TXBnCRTL register and the lower byte is the TEC // Option variable, lower 4 bits, defines message priority (lowest 2 bits) and Txwait bit (0x04 bit) static public int SendCANMess(byte InterfaceNum, byte DeviceNum, CANMessage Msg, out int ErrorInt) { byte[] USBOutBuf = new byte[30]; byte[] USBInBuf = new byte[100]; int Result; ErrorInt = 0; if (Msg.DLC > 8) { return(Resp_ErrImproperCallingParameter); } if (Msg.MO > 2) { return(Resp_ErrImproperCallingParameter); } if (InterfaceNum > 9) { return(Resp_ErrImproperCallingParameter); } if (!ClassInit[InterfaceNum]) { Result = Init(InterfaceNum); if (Result == Resp_ErrNoInterfacePresent) { return(Result); } } USBOutBuf[0] = DeviceNum; USBOutBuf[1] = (byte)LLCMD.SENDCANREQ; USBOutBuf[2] = (byte)(Msg.ID >> 24); USBOutBuf[3] = (byte)(Msg.ID >> 16); USBOutBuf[4] = (byte)(Msg.ID >> 8); USBOutBuf[5] = (byte)Msg.ID; if (Msg.EID) { USBOutBuf[2] |= 0x80; // set highest bit high for extended ID messages } if (Msg.RTR) { USBOutBuf[2] |= 0x40; // set next highest bit high for RTR messages } USBOutBuf[6] = (byte)(Msg.SendOption & 0x07); // transmit wait and priority bits USBOutBuf[7] = (byte)((byte)(Msg.MO << 4) | Msg.DLC); // Tx buffer to send and DLC for (int c = 0; c < Msg.DLC; c++) { USBOutBuf[c + 8] = Msg.Data[c]; } Result = USBRawCommand(InterfaceNum, USBOutBuf, Msg.DLC + 8, ref USBInBuf); if (Result < 0) { return(Result); // return error } if ((int)USBInBuf[0] != (int)LLCMD.SENDCANRESP) { return(Resp_ErrImproperResponse); //improper response from node } if (((int)USBInBuf[0] == (int)LLCMD.SENDCANRESP) && ((int)USBInBuf[1] == Resp_Ack)) { return(Resp_Ack); // success } else { ErrorInt = (USBInBuf[2] << 8); // first error code ErrorInt |= USBInBuf[3]; // second error code } return(Resp_NAck); }
private CANMessageData BuildCANMessageData(string MsgIdentifier, long TimeValue) { CANMessage oMsgDef = oCanConfig.GetCANMessage(MsgIdentifier, MessageResearchOption.Identifier); //Get engeneering value for each parameter of the message foreach (CANParameter oParamDef in oMsgDef.Parameters) { DataAssociation oParamAssociation = oAssociations.GetAssociation(MsgIdentifier, oParamDef.Name); double DataValue = 0; //Retrieve formated value if (!(oParamAssociation == null)) { switch (oParamAssociation.AssociationType) { case CS_DataAssociationType.AcqData: if (!(oDataFile.GetValueAtTime(oParamAssociation.DataColumnTitle, TimeValue, out DataValue))) { return(null); } break; case CS_DataAssociationType.BuiltSignal: DataValue = oSignalLibCollection.GetSignalValueAtTime(oParamAssociation.SignalLibrary, oParamAssociation.SignalName, TimeValue); break; case CS_DataAssociationType.FixedValue: DataValue = oParamAssociation.DefaultValue; break; default: DataValue = 0; break; } } else { if (TimeValue == 0) { DialogResult Rep = MessageBox.Show("No association found for CAN parameter " + oParamDef.Name + " of message ID " + MsgIdentifier + "\nDo you want to continue cycle creation anyway ?", Application.ProductName, MessageBoxButtons.YesNo, MessageBoxIcon.Warning); if (Rep.Equals(DialogResult.No)) { MessageBox.Show("Cycle creation abort !", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information); return(null); } } } oParamDef.DecodedValue = DataValue; } //Encode the message CANMessageEncoded oMsgEncoded = new CANMessageEncoded(oMsgDef); oMsgEncoded.EncodeMessage(); return(oMsgEncoded.GetCANMessageData()); }
//Executor Process Message public void Executor(CANMessage CANMessage) { lock (this) { if (!IsRunning) { return; } if (CANMessage.ExternFlag) { return; } Job j = JobRunning; //ACK if (j.Type == Job.JobType.ACK) { if (_StepRunning == 1) { if (CheckCANMessage(CANMessage, ID_ACK, DA_ACK)) { RunningNext(); } else if (CheckCANMessage(CANMessage, ID_ACK, DA_NACK)) { RunningNext(); } else { ErrorWriteLine("Unknow Message:" + CANMessage.ToString()); } } } //READ else if (j.Type == Job.JobType.Read) { if (CheckCANMessage(CANMessage, ID_READ, DA_NACK)) { RunningNext(JobEventType.NACK, "NACK"); } int m = (int)Math.Ceiling(j.DataNum / 8f); if (_StepRunning == 1)//ACK { if (CheckCANMessage(CANMessage, ID_READ, DA_ACK)) { _StepRunning++; } else { ErrorWriteLine("Unknow Message:" + CANMessage.ToString()); } } else if (_StepRunning >= 2 && _StepRunning <= m + 1)//DATA { if (CheckCANMessage(CANMessage, ID_READ) && CANMessage.DataLen > 0) { if (_StepRunning == 2) { j.DataReceive = new byte[j.DataNum]; } Array.Copy(CANMessage.Data, 0, j.DataReceive, (_StepRunning - 2) * CANMessage.DataLenMax, CANMessage.DataLen); _StepRunning++; } else { ErrorWriteLine("Unknow Message:" + CANMessage.ToString()); } } else if (_StepRunning == m + 2)//ACK { if (CheckCANMessage(CANMessage, ID_READ, DA_ACK)) { RunningNext(); } else { ErrorWriteLine("Unknow Message:" + CANMessage.ToString()); } } else { TimeoutCheck(); } } //WRITE else if (j.Type == Job.JobType.Write) { if (CheckCANMessage(CANMessage, ID_WRITE, DA_NACK)) { RunningNext(JobEventType.NACK, "NACK"); } int m = (int)Math.Ceiling(j.DataSend.Length / 8f); if (_StepRunning == 2 * m + 2) { if (CheckCANMessage(CANMessage, ID_WRITE, DA_ACK)) { RunningNext(); } else { ErrorWriteLine("Unknow Message:" + CANMessage.ToString()); } } else if (_StepRunning % 2 == 1 && _StepRunning <= 2 * m + 1) { if (CheckCANMessage(CANMessage, ID_WRITE, DA_ACK)) { _StepRunning++; } else { ErrorWriteLine("Unknow Message:" + CANMessage.ToString()); } } } //ERASE else if (j.Type == Job.JobType.Erase) { if (CheckCANMessage(CANMessage, ID_ERASE, DA_NACK)) { RunningNext(JobEventType.NACK, "NACK"); } if (_StepRunning == 1 || _StepRunning == 3) { if (CheckCANMessage(CANMessage, ID_ERASE, DA_ACK)) { _StepRunning++; } else { ErrorWriteLine("Unknow Message:" + CANMessage.ToString()); } } else if (_StepRunning == 4) { if (CheckCANMessage(CANMessage, ID_ERASE, DA_ACK)) { RunningNext(); } else { ErrorWriteLine("Unknow Message:" + CANMessage.ToString()); } } } //GV else if (j.Type == Job.JobType.GetState) { if (CheckCANMessage(CANMessage, ID_GV, DA_NACK)) { RunningNext(JobEventType.NACK, "NACK"); } if (_StepRunning == 1) { if (CheckCANMessage(CANMessage, ID_GV, DA_ACK)) { _StepRunning++; } else { ErrorWriteLine("Unknow Message:" + CANMessage.ToString()); } } else if (_StepRunning == 2) { if (CheckCANMessage(CANMessage, ID_GV, 1)) { j.DataReceive = new byte[3]; j.DataReceive[0] = CANMessage.Data[0]; _StepRunning++; } else { ErrorWriteLine("Unknow Message:" + CANMessage.ToString()); } } else if (_StepRunning == 3) { if (CheckCANMessage(CANMessage, ID_GV, 2)) { j.DataReceive[1] = CANMessage.Data[0]; j.DataReceive[2] = CANMessage.Data[1]; _StepRunning++; } else { ErrorWriteLine("Unknow Message:" + CANMessage.ToString()); } } else if (_StepRunning == 4) { if (CheckCANMessage(CANMessage, ID_GV, DA_ACK)) { RunningNext(); } else { ErrorWriteLine("Unknow Message:" + CANMessage.ToString()); } } } //GO else if (j.Type == Job.JobType.Go) { if (CheckCANMessage(CANMessage, ID_GO, DA_NACK)) { RunningNext(JobEventType.NACK, "NACK"); } if (_StepRunning == 1) { if (CheckCANMessage(CANMessage, ID_GO, DA_ACK)) { RunningNext(); } else { ErrorWriteLine("Unknow Message:" + CANMessage.ToString()); } } } else { ErrorWriteLine("Unsupport Job:" + j.Type.ToString()); } } }
/// <summary> /// Decodes the PCAN trace file CAN messages in raw format into the engineering format according to the specified CAN Configuration /// </summary> /// <returns>Decoding result (True: OK / False: Error)</returns> private bool DecodeTrcFile() { bool bComputeVirtuals = false; long iRecord = 0; if (!(VCLibraries == null)) { VCLibraries.InitLibrariesComputation(); bComputeVirtuals = true; } foreach (TraceRecord Record in Records) { iRecord++; if (oCanConfig.IsUsedIdentifier(Record.MessageIdentifier)) { CANMessage oMessage = oCanConfig.GetCANMessage(Record.MessageIdentifier, MessageResearchOption.Identifier); if (!(oMessage == null)) { CANMessageDecoded oMsgDecoded = new CANMessageDecoded(oMessage, Record); if (oMsgDecoded.bMessageDecoded) { foreach (CANParameter oParam in oMsgDecoded.Parameters) { AddDataSample(oParam.Name, Record.TimeOffset, oParam.DecodedValue); if (bComputeVirtuals) { VCLibraries.UpDateVariableElement(oParam.Name, oParam.DecodedValue); } } if (bComputeVirtuals) { VCLibraries.ComputeLibraries(); foreach (CS_VirtualChannelsLibrary oLib in VCLibraries.Libraries) { foreach (CS_VirtualChannel oVirtual in oLib.Channels) { if (oVirtual.bComputed && (oVirtual.bNewValue | iRecord == Records.Count)) //Virtual channel computation for the last record in order to have value until the end { oVirtual.bNewValue = false; if (!oVirtual.InError) { if (!Double.IsNaN(oVirtual.Value)) { AddDataSample(oVirtual.Name, Record.TimeOffset, oVirtual.Value); } } } } } } } } } } return(true); }
/// <summary> /// waitForMessage waits for a specific CAN message give by a CAN id. /// </summary> /// <param name="a_canID">The CAN id to listen for</param> /// <param name="timeout">Listen timeout</param> /// <param name="r_canMsg">The CAN message with a_canID that we where listening for.</param> /// <returns>The CAN id for the message we where listening for, otherwise 0.</returns> public override uint waitForMessage(uint a_canID, uint timeout, out CANMessage canMsg) { /* * int readResult = 0; * int nrOfWait = 0; * while (nrOfWait < timeout) * { * LAWICEL.CANMsg r_canMsg = new LAWICEL.CANMsg(); * canMsg = new CANMessage(); * readResult = LAWICEL.canusb_Read(m_deviceHandle, out r_canMsg); * if (readResult == LAWICEL.ERROR_CANUSB_OK) * { * //Console.WriteLine("rx id: 0x" + r_canMsg.id.ToString("X4")); * if (r_canMsg.id != a_canID) * { * nrOfWait++; * continue; * } * else * { * canMsg.setID(r_canMsg.id); * canMsg.setData(r_canMsg.data); * canMsg.setFlags(r_canMsg.flags); * return (uint)r_canMsg.id; * } * } * else if (readResult == LAWICEL.ERROR_CANUSB_NO_MESSAGE) * { * Thread.Sleep(1); * nrOfWait++; * } * } * canMsg = new CANMessage(); * return 0;*/ LAWICEL.CANMsg r_canMsg; canMsg = new CANMessage(); int readResult = 0; int nrOfWait = 0; while (nrOfWait < timeout) { r_canMsg = new LAWICEL.CANMsg(); readResult = LAWICEL.canusb_Read(m_deviceHandle, out r_canMsg); if (readResult == LAWICEL.ERROR_CANUSB_OK) { Thread.Sleep(1); AddToCanTrace("rx: 0x" + r_canMsg.id.ToString("X4") + r_canMsg.data.ToString("X16")); if (r_canMsg.id == 0x00) { nrOfWait++; } else if (r_canMsg.id != a_canID) { continue; } canMsg.setData(r_canMsg.data); canMsg.setID(r_canMsg.id); canMsg.setLength(r_canMsg.len); return((uint)r_canMsg.id); } else if (readResult == LAWICEL.ERROR_CANUSB_NO_MESSAGE) { Thread.Sleep(1); nrOfWait++; } } r_canMsg = new LAWICEL.CANMsg(); return(0); }
/// <summary> /// readMessages is the "run" method of this class. It reads all incomming messages /// and publishes them to registered ICANListeners. /// </summary> public void readMessages() { int readResult = 0; LAWICEL.CANMsg r_canMsg = new LAWICEL.CANMsg(); CANMessage canMessage = new CANMessage(); Console.WriteLine("readMessages started"); while (true) { lock (m_synchObject) { if (m_endThread) { Console.WriteLine("readMessages ended"); return; } } readResult = LAWICEL.canusb_Read(m_deviceHandle, out r_canMsg); if (readResult == LAWICEL.ERROR_CANUSB_OK) { //Console.WriteLine(r_canMsg.id.ToString("X6") + " " + r_canMsg.data.ToString("X16")); //if (MessageContainsInformationForRealtime(r_canMsg.id)) { canMessage.setID(r_canMsg.id); canMessage.setLength(r_canMsg.len); canMessage.setTimeStamp(r_canMsg.timestamp); canMessage.setFlags(r_canMsg.flags); canMessage.setData(r_canMsg.data); lock (m_listeners) { bitsPerSecond += 109; AddToCanTrace("RX: " + r_canMsg.id.ToString("X6") + " " + r_canMsg.data.ToString("X16")); rxCount++; foreach (ICANListener listener in m_listeners) { //while (listener.messagePending()) ; // dirty, make this better listener.handleMessage(canMessage); } CastInformationEvent("", rxCount, txCount, errCount); // <GS-05042011> re-activated this function } //Thread.Sleep(1); } // cast event to application to process message //if (MessageContainsInformationForRealtime(r_canMsg.id)) //{ //TODO: process all other known msg id's into the realtime view // CastInformationEvent(canMessage); // <GS-05042011> re-activated this function //} } else if (readResult == LAWICEL.ERROR_CANUSB_NO_MESSAGE) { // Console.WriteLine("No message"); Thread.Sleep(1); } else { Console.WriteLine("Result: " + readResult.ToString("X8")); } /*int stat = LAWICEL.canusb_Status(m_deviceHandle); * if (stat != 0) * { * Console.WriteLine("status: " + stat.ToString("X4")); * }*/ } }
private void SerialCAN_CANMessageReceived(object sender, CANMessageReceivedEventArgs e) { int requestedBlockIndex; if (UpdateRunning) { switch ((CANMaerklinCommand)(e.CANMessage.Id & 0xFFFF0000UL)) { case (CANMaerklinCommand.Ping): Console.WriteLine("received CAN Ping {0}\n", e.CANMessage); if (CurrentDeviceHash == (e.CANMessage.Id & 0x00FFFF)) { if (!FileUpdateRunning) { //Ping received from update device so we expect the File update has been completed Console.WriteLine("UPDATE COMPLETE"); UpdateCompletedAutoResetEvent.Set(); UpdateRunning = false; } } break; case (CANMaerklinCommand.PingRsp): Console.WriteLine("received CAN Ping answer from Device {0}\n", (DeviceType)(e.CANMessage.Data[0])); if ((e.CANMessage.Data.Length == 8) && (e.CANMessage.Data[0] == (byte)DeviceType)) { string deviceVersion = string.Format("{0}.{1}", e.CANMessage.Data[4], e.CANMessage.Data[5]); switch ((DeviceType)e.CANMessage.Data[0]) { case DeviceType.GB2: Console.WriteLine("found Gleisbox with ID 0x{0} Version {1}\n", CurrentDeviceId, deviceVersion); CurrentDeviceId = GetDeviceIdFromCanMessage(e.CANMessage); CurrentDeviceHash = e.CANMessage.Id & 0x00FFFF; PingReceived = true; break; case DeviceType.MS2: Console.WriteLine("found MS2 with ID 0x{0} Version {1}\n", CurrentDeviceId, deviceVersion); CurrentDeviceId = GetDeviceIdFromCanMessage(e.CANMessage); CurrentDeviceHash = e.CANMessage.Id & 0x00FFFF; PingReceived = true; break; } if (IsFirmwareUpdate) { StartFirmwareUpdateProcedure(deviceVersion); } else { StartConfigFileSend(); } } break; case CANMaerklinCommand.BootloaderRsp: //Firmware update process if (PingReceived) { if (e.CANMessage.Data.Length == 8 && GetDeviceIdFromCanMessage(e.CANMessage) == CurrentDeviceId && ((e.CANMessage.Data[7] == 0x10) || (e.CANMessage.Data[7] == 0x32))) { Console.WriteLine("Send initial block id"); SendInitialBlockId(e.CANMessage); } else { /* first data block */ if (LastSentFrame == null || e.CANMessage.Data.ByteArrayEquals(LastSentFrame.Data) && LastBinBlock == TotalBlocksToSend) { Console.WriteLine("Send first data block"); SendFirmwareBlock(DataBytesToSendWithPadding.Skip(LastBinBlock * (int)CurrentUpdateFiles[CurrentUpdateFileIndex].blockSize).ToArray(), DataBytesToSendWithPadding.Length - TotalBlocksToSend * (int)CurrentUpdateFiles[CurrentUpdateFileIndex].blockSize); LastBinBlock--; } else { //there seems to be different NACK types : 0xF1 and 0xF2 if (CheckFrameNack != null && e.CANMessage.Data.Length >= 5 && CheckFrameNack.Data.Length >= 5 && e.CANMessage.Id == CheckFrameNack.Id && e.CANMessage.Data.Take(4).ToArray().ByteArrayEquals(CheckFrameNack.Data.Take(4).ToArray()) && (e.CANMessage.Data[4] == 0xF1 || e.CANMessage.Data[4] == 0xF2) ) { Console.WriteLine("Aiiee got NACK. Aborting"); UpdateCompletedAutoResetEvent.Set(); UpdateRunning = false; } //MS2 may use 0x0000 as hash -> compare CheckFrameBlockId full 8 bytes if (CheckFrameBlockId != null && e.CANMessage.Data.ByteArrayEquals(CheckFrameBlockId.Data)) { SendFirmwareBlock(DataBytesToSendWithPadding.Skip(LastBinBlock * (int)CurrentUpdateFiles[CurrentUpdateFileIndex].blockSize).ToArray(), (int)CurrentUpdateFiles[CurrentUpdateFileIndex].blockSize); //firmware flashing has to be sent in reversed order LastBinBlock--; } //MS2 may use 0x0000 as hash -> compare CheckFrame full 8 bytes if (CheckFrame != null && e.CANMessage.Data.Length == CheckFrame.Data.Length && e.CANMessage.Data.Take(5).ToArray().ByteArrayEquals(CheckFrame.Data.Take(5).ToArray())) { if ((LastBinBlock >= 0)) { SendNextBlockId((byte)(LastBinBlock + CurrentUpdateFiles[CurrentUpdateFileIndex].blockOffset)); } else { if (DeviceType == DeviceType.MS2) { Console.WriteLine("Reboot MS2 - be patient..."); //end of update LastSentFrame = new CANMessage(BuildCANId(CANMaerklinCommand.Bootloader, CS2AddressHash), new byte[] { 0x00, 0x00, 0x00, 0x00, 0xf5 }); Array.Copy(CurrentDeviceId.HexStringToByteArray(), 0, LastSentFrame.Data, 0, 4); serialCAN.SendCAN(LastSentFrame); Thread.Sleep(1000); //soft reset LastSentFrame = new CANMessage(BuildCANId(CANMaerklinCommand.Bootloader, CS2AddressHash), new byte[] { 0x00, 0x00, 0x00, 0x00, 0x11 }); Array.Copy(CurrentDeviceId.HexStringToByteArray(), 0, LastSentFrame.Data, 0, 4); serialCAN.SendCAN(LastSentFrame); Thread.Sleep(13000); //Start updating MS2 files StartConfigFileSend(); } else { Console.WriteLine("UPDATE COMPLETE"); UpdateCompletedAutoResetEvent.Set(); UpdateRunning = false; } } } } } } break; case CANMaerklinCommand.ConfigDataQuery: //Send/Update CONFIG DATA if (e.CANMessage.Data.ByteArrayToHexString() == "6666666666666666") { if (RequestedConfigNameData.EndsWith("ver")) { if (AckconfigFileRequestFrame != null) { serialCAN.SendCAN(AckconfigFileRequestFrame); } //Send config data LastBinBlock = 0; PrepareCS2FileVersionInfoToSend(CurrentUpdateFiles[CurrentUpdateFileIndex]); byte[] fileSizeBytes = BitConverter.GetBytes(FileLength).ToBigEndian(); Array.Copy(fileSizeBytes, LastSentFrame.Data, 4); Crc16Ccitt crc16Ccitt = new Crc16Ccitt(InitialCrcValue.NonZero1); LastSentFrame.Id = BuildCANId(CANMaerklinCommand.ConfigDataStream, e.CANMessage.Id & 0x00FFFF); var crc16 = crc16Ccitt.ComputeChecksumBytes(DataBytesToSendWithPadding).ToBigEndian(); LastSentFrame.Data[4] = crc16[0]; LastSentFrame.Data[5] = crc16[1]; Console.WriteLine("block checksum 0x{0}", crc16.ByteArrayToHexString()); serialCAN.SendCAN(LastSentFrame); //send all data for (int i = 0; i < DataBytesToSendWithPadding.Length; i += 8) { LastSentFrame.Data = new byte[8]; Array.Copy(DataBytesToSendWithPadding, i, LastSentFrame.Data, 0, 8); serialCAN.SendCAN(LastSentFrame); } Console.WriteLine("Data sent."); } } else if (e.CANMessage.Data.ByteArrayToHexString().Substring(6) == "0000000000" && int.TryParse(Encoding.ASCII.GetString(e.CANMessage.Data).Trim('\0'), out requestedBlockIndex)) { FileUpdateRunning = true; if (!string.IsNullOrEmpty(RequestedConfigNameData)) { Console.WriteLine("Request file {0} block {1}", RequestedConfigNameData, requestedBlockIndex); byte[] bytesToSend = DataBytesToSendWithPadding.Skip(requestedBlockIndex * CurrentUpdateFiles[CurrentUpdateFileIndex].blockSize).Take(CurrentUpdateFiles[CurrentUpdateFileIndex].blockSize).ToArray(); //check if requested block is last block if (DataBytesToSendWithPadding.Length / CurrentUpdateFiles[CurrentUpdateFileIndex].blockSize == requestedBlockIndex) { FileUpdateRunning = false; } byte[] fileSizeBytes = BitConverter.GetBytes(bytesToSend.Length).ToBigEndian(); //Prepare messages for later sending (FFFFFF... message) AckconfigFileRequestFrame = e.CANMessage.Clone(); AckconfigFileRequestFrame.Id = BuildCANId(CANMaerklinCommand.ConfigDataQueryRsp, CS2AddressHash); serialCAN.SendCAN(AckconfigFileRequestFrame); Array.Copy(fileSizeBytes, LastSentFrame.Data, 4); Crc16Ccitt crc16Ccitt = new Crc16Ccitt(InitialCrcValue.NonZero1); LastSentFrame.Id = BuildCANId(CANMaerklinCommand.ConfigDataStream, e.CANMessage.Id & 0x00FFFF); var crc16 = crc16Ccitt.ComputeChecksumBytes(bytesToSend).ToBigEndian(); LastSentFrame.Data[4] = crc16[0]; LastSentFrame.Data[5] = crc16[1]; Console.WriteLine("block checksum 0x{0}", crc16.ByteArrayToHexString()); Thread.Sleep(100); serialCAN.SendCAN(LastSentFrame); //send block LastSentFrame.Id = BuildCANId(CANMaerklinCommand.ConfigDataStream, e.CANMessage.Id & 0x00FFFF); for (int i = 0; i < bytesToSend.Length; i += 8) { LastSentFrame.Data = new byte[8]; Array.Copy(bytesToSend, i, LastSentFrame.Data, 0, 8); serialCAN.SendCAN(LastSentFrame); } } } else { RequestedConfigNameData = Encoding.ASCII.GetString(e.CANMessage.Data).Trim('\0'); CurrentUpdateFileIndex = Array.FindIndex(ms2_update_data, x => x.versionName == RequestedConfigNameData); if (Array.Exists(ms2_update_data, x => x.versionName == RequestedConfigNameData)) { //CS2 version string request Console.WriteLine("Request .CS2 fileinfo {0}", RequestedConfigNameData); CurrentUpdateFileIndex = Array.FindIndex(ms2_update_data, x => x.versionName == RequestedConfigNameData); LastSentFrame = new CANMessage(BuildCANId(CANMaerklinCommand.ConfigDataStream, CS2AddressHash), new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }); //Prepare messages for later sending (FFFFFF... message) AckconfigFileRequestFrame = e.CANMessage.Clone(); AckconfigFileRequestFrame.Id = BuildCANId(CANMaerklinCommand.ConfigDataQueryRsp, CS2AddressHash); } else if (Array.Exists(ms2_update_data, x => x.name == RequestedConfigNameData)) { //File data request Console.WriteLine("Request file {0}", RequestedConfigNameData); CurrentUpdateFileIndex = Array.FindIndex(ms2_update_data, x => x.name == RequestedConfigNameData); ReadFirmwareFile(CurrentUpdateFiles[CurrentUpdateFileIndex], false); LastSentFrame = new CANMessage(BuildCANId(CANMaerklinCommand.ConfigDataStream, CS2AddressHash), new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }); AckconfigFileRequestFrame = e.CANMessage.Clone(); AckconfigFileRequestFrame.Id = BuildCANId(CANMaerklinCommand.ConfigDataStreamRsp, CS2AddressHash); } else { Console.WriteLine("Couldn't find requested file {0}", RequestedConfigNameData); } } break; default: break; } } }
/// <summary> /// Send a KWP request. /// </summary> /// <param name="a_request">A KWP request.</param> /// <param name="r_reply">A KWP reply.</param> /// <returns>The status of the request.</returns> public override RequestResult sendRequest(KWPRequest a_request, out KWPReply r_reply) { uint row; uint all_rows = row = nrOfRowsToSend(a_request.getData()); m_kwpCanListener.setupWaitMessage(0x258); // Send one or several request messages. for (; row > 0; row--) { CANMessage msg = new CANMessage(0x240, 0, 8); msg.elmExpectedResponses = a_request.ElmExpectedResponses; msg.setData(createCanMessage(a_request.getData(), row - 1)); if ((msg.getData() & 0xFFFFUL) == 0xA141UL) { msg.elmExpectedResponses = 0; } if (all_rows == 22) { msg.elmExpectedResponses = row == 1 ? 1 : 0; // on last message (expect 1 reply) } if (!m_canDevice.sendMessage(msg)) { r_reply = new KWPReply(); return(RequestResult.ErrorSending); } } var response = m_kwpCanListener.waitMessage(getTimeout()); // Receive one or several replys and send an ack for each reply. if (response.getID() == 0x258) { uint nrOfRows = (uint)(response.getCanData(0) & 0x3F) + 1; row = 0; if (nrOfRows == 0) { throw new Exception("Wrong nr of rows"); } //Assume that no KWP reply contains more than 0x200 bytes byte[] reply = new byte[0x200]; reply = collectReply(reply, response.getData(), row); sendAck(nrOfRows - 1); nrOfRows--; m_kwpCanListener.setupWaitMessage(0x258); while (nrOfRows > 0) { response = m_kwpCanListener.waitMessage(getTimeout()); if (response.getID() == 0x258) { row++; reply = collectReply(reply, response.getData(), row); sendAck(nrOfRows - 1); nrOfRows--; } else { logger.Debug("1response.getID == " + response.getID()); r_reply = new KWPReply(); return(RequestResult.Timeout); } } r_reply = new KWPReply(reply, a_request.getNrOfPID()); return(RequestResult.NoError); } else { logger.Debug("2response.getID == " + response.getID()); r_reply = new KWPReply(); return(RequestResult.Timeout); } }
/// <summary> /// Send a KWP request. /// </summary> /// <param name="a_request">A KWP request.</param> /// <param name="r_reply">A KWP reply.</param> /// <returns>The status of the request.</returns> public RequestResult sendRequest(KWPRequest a_request, out KWPReply r_reply) { CANMessage msg = new CANMessage(0x240, 0, 8); uint row = nrOfRowsToSend(a_request.getData()); m_kwpCanListener.setupWaitMessage(0x258); // Send one or several request messages. for (; row > 0; row--) { msg.setData(createCanMessage(a_request.getData(), row - 1)); if (!m_canDevice.sendMessage(msg)) { r_reply = new KWPReply(); return(RequestResult.ErrorSending); } } msg = m_kwpCanListener.waitMessage(timeoutPeriod); // msg = m_kwpCanListener.waitForMessage(0x258, timeoutPeriod); // Receive one or several replys and send an ack for each reply. if (msg.getID() == 0x258) { uint nrOfRows = (uint)(msg.getCanData(0) & 0x3F) + 1; row = 0; if (nrOfRows == 0) { throw new Exception("Wrong nr of rows"); } //Assume that no KWP reply contains more than 0x200 bytes byte[] reply = new byte[0x200]; reply = collectReply(reply, msg.getData(), row); sendAck(nrOfRows - 1); nrOfRows--; m_kwpCanListener.setupWaitMessage(0x258); while (nrOfRows > 0) { // msg = m_kwpCanListener.waitForMessage(0x258, timeoutPeriod); msg = m_kwpCanListener.waitMessage(timeoutPeriod); if (msg.getID() == 0x258) { row++; reply = collectReply(reply, msg.getData(), row); sendAck(nrOfRows - 1); nrOfRows--; } else { r_reply = new KWPReply(); return(RequestResult.Timeout); } } r_reply = new KWPReply(reply, a_request.getNrOfPID()); return(RequestResult.NoError); } else { r_reply = new KWPReply(); return(RequestResult.Timeout); } }
/// <summary> /// Convert the DBC object into a CANStream CAN configuration object /// </summary> /// <param name="Rate">CAN bus Baud rate</param> /// <param name="CanNodeName">CAN device name</param> /// <returns>CANStream CAN configuration object of the DBC</returns> public CANMessagesConfiguration Convert_DBC_to_XCC(int Rate, string CanNodeName) { CANMessagesConfiguration oXCC = new CANMessagesConfiguration(); //Bus Baud rate oXCC.CanRate = Rate; //Config name oXCC.Name = "DBC:"; if (!(BusComponents == null)) { for (int i = 0; i < BusComponents.Length; i++) { oXCC.Name = oXCC.Name + " " + BusComponents[i]; } } foreach (DBCFrame oFrame in Frames) { CANMessage oCSMsg = new CANMessage(); oCSMsg.Identifier = NumberBaseConverter.Dec2Hex(oFrame.Identifier); oCSMsg.DLC = oFrame.ByteLength; oCSMsg.Name = oFrame.Name; oCSMsg.Comment = oFrame.GetNodeComments(); oCSMsg.Period = 1000; //Default value //oCSMsg.RxTx=CanMsgRxTx.Tx; //Default value if (oFrame.Transmitter.Equals(CanNodeName)) { oCSMsg.RxTx = CanMsgRxTx.Tx; } else { oCSMsg.RxTx = CanMsgRxTx.Rx; } oCSMsg.MultiplexerName = oFrame.GetMultiplexerSignalName(); foreach (DBCSignal oSignal in oFrame.Signals) { if ((oCSMsg.RxTx.Equals(CanMsgRxTx.Tx)) || (oCSMsg.RxTx.Equals(CanMsgRxTx.Rx) && oSignal.Destination.Equals(CanNodeName))) { CANParameter oCSParam = new CANParameter(); oCSParam.Name = oSignal.Name; oCSParam.Comment = oSignal.GetSignalComments(); oCSParam.Unit = oSignal.Unit; oCSParam.StartBit = oSignal.StartBit; oCSParam.Length = oSignal.Length; oCSParam.Endianess = (CanParameterEndianess)Enum.Parse(typeof(CanParameterEndianess), oSignal.Endianess.ToString()); oCSParam.Signed = oSignal.Signed; oCSParam.Gain = oSignal.Gain; oCSParam.Zero = oSignal.Zero; if (!(oSignal.Multiplexer == null)) { if (!(oSignal.Multiplexer.IsMultiplexerSignal)) { oCSParam.IsMultiplexed = true; oCSParam.MultiplexerValue = oSignal.Multiplexer.MultiplexerValue; } } oCSMsg.Parameters.Add(oCSParam); } } if (oCSMsg.Parameters.Count > 0) { oXCC.Messages.Add(oCSMsg); } } return(oXCC); }