예제 #1
0
 public void exileSandwich(Sandwich refSandwich)
 {
     sandwiches.Remove(refSandwich);
 }
예제 #2
0
        public void scanSandwichIDs()
        {
            List <COMPort> legitPorts = new List <COMPort>();

            /////////////////////////////////////////////////////////////
            // Get the ports where the sandwich Arduinos are connected //
            /////////////////////////////////////////////////////////////
            // Combination of https://stackoverflow.com/a/46683622 and https://stackoverflow.com/a/6017027
            // Selecting from Win32_PnPEntity returns ALL of plug n play devices (as opposed to Win32_SerialPort);
            // Adding restriction for Name such as '(COM' narrows down to serial devices
            ManagementObjectSearcher   arduinoSearch = new ManagementObjectSearcher("SELECT * FROM Win32_PnPEntity WHERE Name like '%" + COMDeviceNameFragment_ + "%'");
            ManagementObjectCollection arduinoList   = arduinoSearch.Get();


            if (arduinoList.Count > 0)
            {// Only proceed if there were any ports to which sandwich Arduinos are connected
                // Extract the names of the ports where sandwich Arduinos are connected
                foreach (ManagementObject arduino in arduinoList)
                {
                    string caption  = arduino["Caption"].ToString();
                    int    COMStart = caption.IndexOf("(COM") + 1; // +1 to go past the opening bracket
                    int    COMEnd   = caption.IndexOf(")", COMStart);
                    string portName = caption.Substring(COMStart, COMEnd - COMStart);

                    // Add this port to the list of legit ports
                    legitPorts.Add(new COMPort(0, portName));
                }

                // Out of all the identified legit ports, identify the ones that are already assigned to any sandwiches
                for (int i = 0; i < sandwiches.Count; i++)
                {
                    // Identify which sandwiches are already running (implying that they have a working port) and exclude them from the search
                    if (sandwiches[i].getDAQStatus())
                    {
                        legitPorts.RemoveAll(x => x.portName == sandwiches[i].getCOMPort());
                    }
                }
            }


            // Assign the remaining legit ports to the appropriate sandwich class instances
            // Go in reverse direction because we will be removing ports as we assign them
            // Remaining ports will be assumed as unassigned
            for (int i = 0; i < legitPorts.Count; i++)
            {// Get IDs of the sandwiches and associate them with the COM ports. If an invalid or no response is received, remove that port from the list
                SerialPort port = new SerialPort(legitPorts[i].portName, Communication.serialBaudRate, Communication.serialParity, Communication.serialDataBits, Communication.serialStopBits);
                port.Handshake   = Communication.serialHandshake;
                port.Encoding    = Communication.serialEncoding;
                port.ReadTimeout = 100; // Increase this if the sandwiches are not responding quick enough
                bool commandSent = false;

                try
                {
                    port.Open();

                    // Send a check for connection (SERIAL_CMD_CONNECTION command), which the Arduino would respond
                    // with SERIAL_REPLY_CONNECTION and the sandwich ID.
                    port.Write(string.Format("{0}{1}{2}{3}",
                                             Communication.SERIAL_CMD_START,
                                             Communication.SERIAL_CMD_CONNECTION,
                                             Communication.SERIAL_CMD_END,
                                             Communication.SERIAL_CMD_EOL));

                    // Give time for Arduino to respond
                    System.Threading.Thread.Sleep(20);

                    // Sometimes, the first command may not receive a response. So we send a second time
                    // Clear all serial port buffers (to prepare for the second try)
                    port.DiscardInBuffer();
                    port.DiscardOutBuffer();
                    port.Write(string.Format("{0}{1}{2}{3}",
                                             Communication.SERIAL_CMD_START,
                                             Communication.SERIAL_CMD_CONNECTION,
                                             Communication.SERIAL_CMD_END,
                                             Communication.SERIAL_CMD_EOL));

                    // Give time for Arduino to respond
                    System.Threading.Thread.Sleep(50);

                    commandSent = true;
                }
                catch (Exception err)
                {
                    errorLogger_.logUnknownError(err);
                }

                if (commandSent)
                {// If the command was successfully sent, start scraping for the response from Arduino
                    try
                    {
                        // Since we set ReadTimeout to a finite number, ReadTo will return a TimeoutException if no response is received within
                        // that time limit. This is done on purpose because the thread would be blocked forever by ReadLine if ReadTimeout is not a
                        // finite number. If no response is received after the timeout or the response is an invalid format, then we assume
                        // that this port is not occupied by the Arduino controlling a sandwich.
                        string readBuffer = port.ReadTo(Communication.SERIAL_REPLY_EOL);

                        // Check if the start and end of the response have the correct flags
                        if (readBuffer.Substring(0, 1) == Communication.SERIAL_REPLY_START && readBuffer.Substring(readBuffer.Length - 1, 1) == Communication.SERIAL_REPLY_END)
                        {
                            // Now extract the sandwich ID that was sent out by this Arduino
                            int startPos = readBuffer.IndexOf(Communication.SERIAL_REPLY_START);
                            int endPos   = readBuffer.LastIndexOf(Communication.SERIAL_REPLY_END);

                            string[] replyFragments = Communication.extractReplyFragments(readBuffer, startPos, endPos);

                            if (replyFragments.Length == 2)
                            {// Sanity check; should have two fragments. One for SERIAL_REPLY_CONNECTION and the other for the sandwich ID
                                try
                                {
                                    int sandwichID = Convert.ToInt16(replyFragments[1]);

                                    // Assign the port to the sandwich class instance with the same ID that we got from the physical sandwich Arduino
                                    Sandwich matchingSandwich = sandwiches.Find(x => x.getSandwichID() == sandwichID);
                                    matchingSandwich.setCOMPort(legitPorts[i].portName);
                                }
                                catch (Exception err)
                                {// There was a problem in the conversion process; corrupted message maybe?
                                    errorLogger_.logUnknownError(err);
                                }
                            }
                            else
                            {// Somehow, number of parameters is wrong.
                                errorLogger_.logCProgError(ErrorLogger.ERR_PROG_REPLY_CORRUPT, "scanSandwichIDs, SERIAL_REPLY_CONNECTION", readBuffer);
                            }

                            // Finally, clear all serial port buffers and close the port
                            port.DiscardInBuffer();
                            port.DiscardOutBuffer();
                            port.Close();
                        }
                        else
                        {// The response doesn't follow the communication standards; either the message is corrupted or the Arduino is not programmed as a TDT Sandwich controller
                            port.Close();
                        }
                    }
                    catch (TimeoutException)
                    {// No response from this device; it's probably an Arduino which isn't programmed as a TDT Sandwich controller
                        port.Close();
                    }
                }
                else
                {// If the command was unsuccessfully sent, close the port
                    // Note that since this could also happen if the port failed to open, we ignore any errors from closing the (unopened) port
                    try { port.Close(); }
                    catch (Exception) { }
                }
            }
        }