/// <summary> /// Enqueue a message in the current priority queue. If you have not /// set the priority of the message it is enqueued according to its /// creation status. /// </summary> /// <param name="enqueue"></param> public void commPriorityQueueEnqueue(CNCRMessage enqueue) { bool threadLocked = _commPriorityQLock.WaitOne(100); if (threadLocked) { _commPriorityQueue.Enqueue(enqueue); _commPriorityQLock.Release(); } else { throw new Exception("Failed to lock thread"); } }
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ // @@@@@ IComparable Functions @@@@@ public int CompareTo(object obj) { CNCRMessage msg = (CNCRMessage)obj; if (msg != null) { int compare = getPriority().CompareTo(msg.getPriority()); switch (compare) { case 0: return(_msgID.CompareTo(msg.getMsgID())); default: return(compare); } } else { throw new ArgumentException("Object is not a message"); } }
public void SendMsg(CNCRMessage msg) { //TODO: SendMsg: Should this function really be doing this check? Shouldnt the function errorhandler do this? if (getDiscardingData() && // If we are discarding data. msg.getMessageType() == CNCRMSG_TYPE.CMD_ACKNOWLEDGE && // and sending an acknowledge ((CNCRMsgCmdAck)msg).getError() == true) // and that acknowledge is saying we have an error. { setDiscardingData(false); // Then clear the discard data bit so we can see the response. byte[] serialStuff = msg.toSerial(); string toDisplay = "Ack Sent: " + CNCRTools.BytesToHex(msg.toSerial()); toDisplay += "\n"; DisplayData(toDisplay); } if (msg.getMessageType() != CNCRMSG_TYPE.CMD_ACKNOWLEDGE) { setWaitingOnAck(true); } setLastMessage(msg); DisplayData("Sending: " + msg.ToString() + "\n"); SendBytes(msg.toSerial()); }
private void btnSndMsg_Click(object sender, EventArgs e) { /* * int discarded = 0; * byte[] bytes = CNCRTools.GetBytes(txtHex.Text, out discarded); * lblDbgOut.Text = ""; * for (int i = 0; i < bytes.Length; i++) * { * lblDbgOut.Text += bytes[i].ToString() + " "; * }//*/ byte[] sendBytes = { 0 }; CNCRMessage sendMsg = null; switch (cmbMsgs.SelectedIndex) { case 0: int discarded = 0; sendBytes = CNCRTools.GetBytes(txtHex.Text, out discarded); break; case 1: sendMsg = new CNCRMsgPing(); sendBytes = sendMsg.toSerial(); break; case 2: sendMsg = new CNCRMsgCmdAck(false, 127); sendBytes = sendMsg.toSerial(); break; case 3: sendMsg = new CNCRMsgEStop(); sendBytes = sendMsg.toSerial(); break; case 4: sendMsg = new CNCRMsgRequestCommands(128); sendBytes = sendMsg.toSerial(); break; case 5: sendMsg = new CNCRMsgStartQueue(false); sendBytes = sendMsg.toSerial(); break; case 6: sendMsg = new CNCRMsgSetSpeed(true, true, false, 40000); sendBytes = sendMsg.toSerial(); break; case 7: sendMsg = new CNCRMsgMove(Int16.MinValue, Int16.MaxValue, 0); sendBytes = sendMsg.toSerial(); break; case 8: sendMsg = new CNCRMsgToolCmd(true); sendBytes = sendMsg.toSerial(); break; } rtbTraffic.AppendText(CNCRTools.BytesToHex(sendBytes) + "\n"); if (sendMsg == null) { commCmd.SendBytes(sendBytes); } else { commCmd.SendMsg(sendMsg); } }
private void setLastMessage(CNCRMessage lastMessage) { _lastMessageLock.WaitOne(); _lastMessage = lastMessage; _lastMessageLock.Release(); }
public void SendMsg(CNCRMessage msg) { //TODO: SendMsg: Should this function really be doing this check? Shouldnt the function errorhandler do this? if (getDiscardingData() // If we are discarding data. && msg.getMessageType() == CNCRMSG_TYPE.CMD_ACKNOWLEDGE // and sending an acknowledge && ((CNCRMsgCmdAck)msg).getError() == true) // and that acknowledge is saying we have an error. { setDiscardingData(false); // Then clear the discard data bit so we can see the response. byte[] serialStuff = msg.toSerial(); string toDisplay = "Ack Sent: " + CNCRTools.BytesToHex(msg.toSerial()); toDisplay += "\n"; DisplayData(toDisplay); } if (msg.getMessageType() != CNCRMSG_TYPE.CMD_ACKNOWLEDGE) { setWaitingOnAck(true); } setLastMessage(msg); DisplayData("Sending: " + msg.ToString() + "\n"); SendBytes(msg.toSerial()); }
/// <summary> /// Enqueue a message in the current priority queue. If you have not /// set the priority of the message it is enqueued according to its /// creation status. /// </summary> /// <param name="enqueue"></param> public void commPriorityQueueEnqueue(CNCRMessage enqueue) { bool threadLocked = _commPriorityQLock.WaitOne(100); if (threadLocked) { _commPriorityQueue.Enqueue(enqueue); _commPriorityQLock.Release(); } else throw new Exception("Failed to lock thread"); }
private void processQueues() { DateTime lastMsg = DateTime.Now; TimeSpan timeout = new TimeSpan(CNCRConstants.TIMEOUT_MS * TimeSpan.TicksPerMillisecond); while (!getEStopActive() && // While eStop is not active. ((commPriorityQueueCount() > 0) || (commCommandQueueCount() > 0 && getNumCmdsToSend() > 0)) && // And this stuff ((DateTime.Now - lastMsg) < timeout)) // TODO; Log a timeout error. { // If waiting for Ack or EStopped, exit thread, we cant send any commands. if (!getWaitingOnAck() && !getEStopActive()) { // reset the timeout lastMsg = DateTime.Now; int numCmdsToSend = getNumCmdsToSend(); // Check the priority queue first, it has priority. if (commPriorityQueueCount() > 0) { CNCRMessage commMsg = commPriorityQueueDequeue(); if (commMsg.getMessageType() == CNCRMSG_TYPE.E_STOP) { setEStopActive(true); } SendMsg(commMsg); } // Check to see if the router is requesting commands and then // Check to ensure we actually have commands to send. else if (numCmdsToSend > 0 && commCommandQueueCount() > 0) { // Grab the next router command in the queue. SendMsg(commCommandQueueDequeue()); // Check if we are out of commands, if so set the numCmdsToSend to 0 // and send StartQueue(true) if (commCommandQueueCount() == 0) { numCmdsToSend = 0; commPriorityQueueEnqueue(new CNCRMsgStartQueue(true)); } else // Decrement the command counter { numCmdsToSend--; } // Set the new numCmdsToSend safely. setNumCmdsToSend(numCmdsToSend); } } // TODO: Check to see if we timed out, what do we do in this event? // TODO: Check to see if the router is requesting more commands than we have. // if so, send them a "StartQueue(true)" message to stop them. // - Possibly do this when sending messages? what about when I receive this message? // - I should be able to check on receipt if requested is > than received. // - Or when emptying the queue, as soon as I hit 0 I can append a "stop message" // (following message saved for posterity, moved from above last } // - Well currently I do not even reach this level if there // is a discrepency between commCommandQueueCount and // getNumCmdsToSend due to the while loop. Figure this out. Thread.Sleep(10); } }
/// <summary> /// Takes the passed in message and performs the nessessary actions /// required by that message. /// </summary> /// <param name="msg">Message to act on.</param> public void actOnMessage(object msgObj) { CNCRMessage msg = (CNCRMessage)msgObj; if (msg == null) { throw new ArgumentNullException(); } switch (msg.getMessageType()) { case CNCRMSG_TYPE.CMD_ACKNOWLEDGE: if (((CNCRMsgCmdAck)msg).getError()) { // if error, resend last message CNCRMessage lastMsg = getLastMessage(); lastMsg.setPriority(CNCRMSG_PRIORITY.HIGH); commPriorityQueueEnqueue(lastMsg); } else { // if not error, clear "Waiting for Ack" setWaitingOnAck(false); } launchProcessQueues(); break; case CNCRMSG_TYPE.E_STOP: // Send Ack. CNCRMessage ack = new CNCRMsgCmdAck(false, 0); ack.setPriority(CNCRMSG_PRIORITY.MEDIUM); // TODO: what about the E-stop Ack. commPriorityQueueEnqueue(ack); // Set the "Stop Sending Messages variable" setEStopActive(true); break; case CNCRMSG_TYPE.REQUEST_COMMAND: // Send Ack. CNCRMessage ack2 = new CNCRMsgCmdAck(false, 0); ack2.setPriority(CNCRMSG_PRIORITY.MEDIUM); commPriorityQueueEnqueue(ack2); // Set the "Send Commands" variable to the # of messages. CNCRMsgRequestCommands msgRC = (CNCRMsgRequestCommands)msg; setNumCmdsToSend(msgRC.getCommandCount() + getNumCmdsToSend()); // If it is not already started, kick off the "SendMessages" method. launchProcessQueues(); break; case CNCRMSG_TYPE.MOVE: case CNCRMSG_TYPE.PING: case CNCRMSG_TYPE.SET_SPEED: case CNCRMSG_TYPE.START_QUEUE: case CNCRMSG_TYPE.TOOL_CMD: // We should not be receiving any of these messages. DisplayData("Received a valid message that should not have " + "been sent by the router. " + msg.ToString() + "\n"); break; default: throw new ArgumentException("CNCRMessage has an invalid type"); } }
public void handleData(byte[] commBuffer) { // Are we currently in the middle of a type? if (_commBufferQueue.Count == 0) { // No, so grab the type in the next byte. setCurType((CNCRMSG_TYPE)Enum.ToObject(typeof(CNCRMSG_TYPE), (commBuffer[0] & 0xF0) >> 4)); } // Get the current type, if it is not between MIN and MAX_TYPE CNCRMSG_TYPE currentType = getCurType(); if (CNCRMSG_TYPE.zMIN_TYPE < currentType && currentType < CNCRMSG_TYPE.zMAX_TYPE) { // Drop all incoming bytes into the queue for (int i = 0; i < commBuffer.Length; i++) { if (CNCRTools.validateParityBit(commBuffer[i])) { _commBufferQueue.Enqueue(commBuffer[i]); } else { // Bad Parity bit, Discard the data and log an error. handleError("Invalid Parity Bit."); return; } } // Check how long of a message we are expecting int expectedLength = CNCRTools.getMsgLenFromType(getCurType()); // Uh, Oh, what about expectedLength = 0, AKA, bad type? // - At this point, curType should be validated and curType // should not be unknown, throw an error in getMsgLenFromType. if (expectedLength > 0) { // Process the current Queue while (_commBufferQueue.Count >= expectedLength) { // We have enough bytes, lets get the message for those bytes. byte[] msgBytes = new byte[expectedLength]; for (int i = 0; i < msgBytes.Length; i++) { msgBytes[i] = _commBufferQueue.Dequeue(); } if (CNCRTools.validateParityByte(msgBytes)) { DisplayData("- Valid Parity\n"); CNCRMessage CommMsg = CNCRTools.getMsgFromBytes(msgBytes); DisplayData("- Type: " + CommMsg.ToString() + "\n"); Thread runActOnMessage = new Thread(new ParameterizedThreadStart(actOnMessage)); runActOnMessage.Start(CommMsg); } else { handleError("Invalid Parity Byte."); return; } } } else { handleError("Expected length was 0 or less."); return; } } else { // Bad type: log an error, discard bytes. handleError("Invalid message type."); return; } }