/* public CANMessage waitForMessage(uint a_canID, int a_timeout) { CANMessage retMsg; m_canMessage.setID(0); // init so we cannot receive the same frame twice <GS-10022010> lock (m_canMessage) { m_waitMsgID = a_canID; } m_resetEvent.WaitOne(a_timeout, true); lock (m_canMessage) { retMsg = m_canMessage; } return retMsg; } */ public override void handleMessage(CANMessage a_message) { lock (m_canMessage) { if (a_message.getID() == m_waitMsgID) { m_canMessage.setData(a_message.getData()); m_canMessage.setFlags(a_message.getFlags()); m_canMessage.setID(a_message.getID()); m_canMessage.setLength(a_message.getLength()); m_canMessage.setTimeStamp(a_message.getTimeStamp()); m_resetEvent.Set(); } } }
/// <summary> /// This message sends a CANMessage to the CAN device. /// The open method must have been called and returned possitive result /// before this method is called. /// </summary> /// <param name="a_message">The CANMessage</param> /// <returns>true on success, otherwise false.</returns> public abstract bool sendMessage(CANMessage a_message);
/// <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; }
/// <summary> /// sendMessage send a CANMessage. /// </summary> /// <param name="a_message">A CANMessage.</param> /// <returns>true on success, othewise false.</returns> public override bool sendMessage(CANMessage a_message) { LAWICEL.CANMsg msg = new LAWICEL.CANMsg(); msg.id = a_message.getID(); msg.len = a_message.getLength(); msg.flags = a_message.getFlags(); msg.data = a_message.getData(); int writeResult; AddToCanTrace("Sending message"); writeResult = LAWICEL.canusb_Write(m_deviceHandle, ref msg); if (writeResult == LAWICEL.ERROR_CANUSB_OK) { AddToCanTrace("Message sent successfully"); return true; } else { switch (writeResult) { case LAWICEL.ERROR_CANUSB_COMMAND_SUBSYSTEM: AddToCanTrace("Message failed to send: ERROR_CANUSB_COMMAND_SUBSYSTEM"); break; case LAWICEL.ERROR_CANUSB_INVALID_PARAM: AddToCanTrace("Message failed to send: ERROR_CANUSB_INVALID_PARAM"); break; case LAWICEL.ERROR_CANUSB_NO_MESSAGE: AddToCanTrace("Message failed to send: ERROR_CANUSB_NO_MESSAGE"); break; case LAWICEL.ERROR_CANUSB_NOT_OPEN: AddToCanTrace("Message failed to send: ERROR_CANUSB_NOT_OPEN"); break; case LAWICEL.ERROR_CANUSB_OPEN_SUBSYSTEM: AddToCanTrace("Message failed to send: ERROR_CANUSB_OPEN_SUBSYSTEM"); break; case LAWICEL.ERROR_CANUSB_TX_FIFO_FULL: AddToCanTrace("Message failed to send: ERROR_CANUSB_TX_FIFO_FULL"); break; default: AddToCanTrace("Message failed to send: " + writeResult.ToString()); break; } return false; } }
/// <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); } } }
//------------------------------------------------------------------------- /** Tries to connect to CAN bus using the specified bitrate. @param bitrate bitrate @return succ / fail */ private bool try_bitrate(uint bitrate) { try { // try connecting this.combi.CAN_SetBitrate(bitrate); this.combi.CAN_Open(true); // look for bus activity CANMessage msg = new CANMessage(); Debug.Assert(msg != null); if (this.waitForMessage(0, 1000, out msg) < 1) { throw new Exception("No traffic at given bitrate"); } return true; } catch { // failed this.combi.CAN_Open(false); 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; }
//------------------------------------------------------------------------- /** Sends a 11 bit CAN data frame. @param msg CAN message @return success (true/false) */ public override bool sendMessage(CANMessage msg) { this.AddToCanTrace("Sending message: " + msg.getID().ToString("X4") + " " + msg.getData().ToString("X16")); try { Combi.caCombiAdapter.caCANFrame frame; frame.id = msg.getID(); frame.length = msg.getLength(); frame.data = msg.getData(); frame.is_extended = 0; frame.is_remote = 0; this.combi.CAN_SendMessage(ref frame); this.AddToCanTrace("Message sent successfully"); return true; } catch (Exception e) { this.AddToCanTrace("Message failed to send: " + e.Message); return false; } }
/// <summary> /// This method is called by ICANDevices where derived objects of this class /// are registered. The method is called for each received CANMessage. /// What this method does is application dependent. /// </summary> /// <param name="a_canMessage">The CANMessage to be handled by this method.</param> public abstract void handleMessage(CANMessage a_canMessage);
/// <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,8); 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; } */ }
/// <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> /// This message sends a CANMessage to the CAN device. /// The open method must have been called and returned possitive result /// before this method is called. /// </summary> /// <param name="a_message">The CANMessage</param> /// <returns>true on success, otherwise false.</returns> abstract public bool sendMessage(CANMessage a_message);