Ejemplo n.º 1
0
 // For all sensor arrays connected to the computer that aren't in LCAArduinos, this method pings them, adds them to LCAArduinos, and reads their config information
 public async Task ActivateAllArduinos()
 {
     // This method activates (Ping + Adding to LCAArduino + ReadConfig) all Arduinos that have not been added yet
     foreach (ManagementBaseObject dev in FindArduinos())
     {
         if (!LCAArduinos.ToList().Exists(a => a.Port.PortName == GetPortName(dev)))  // Do nothing for Arduinos already added
         {
             await ActivateArduino(dev);
         }
     }
 }
Ejemplo n.º 2
0
        // Pings an Arduino (to verify it is one of our LCA Arduinos), and if it is, it adds them to LCAArduinos and reads their config information
        public async Task ActivateArduino(ManagementBaseObject device)
        {
            string port      = GetPortName(device);                                       // "COM3", "COM4", etc.
            bool   ardExists = LCAArduinos.ToList().Exists(a => a.Port.PortName == port); // Gives ArduinoBoard if one with that port exists, else null

            if (ardExists)                                                                // If an LCA arduino with the port specified doesn't exist in the LCAArduinos list, create an ArduinoBoard
            {
                return;
            }

            Console.WriteLine("Currently verifying arduino on port {0}...", port);

            try
            {
                // CancellationTokenSource source = new CancellationTokenSource();  // Can/should this be used?
                await Task.Run(async delegate
                {
                    //Console.WriteLine("Lock status before TryEnter: _ActivateArduinoLock.IsHeld = {0}, _ActivateArduinoLock.IsHeldByCurrentThread = {1} ", _ActivateArduinoLock.IsHeld, _ActivateArduinoLock.IsHeldByCurrentThread);
                    bool _GotActivateArduinoLock = false;
                    try
                    {
                        _ActivateArduinoLock.TryEnter(1, ref _GotActivateArduinoLock);  // Only want one at a time. Else more than one ArduinoBoard instance could exist and be communicating with the same arduino during the activation stage.
                    }
                    catch (Exception ex)
                    {
                        if (_GotActivateArduinoLock)
                        {
                            _ActivateArduinoLock.Exit(false);
                        }
                        Console.WriteLine("ActivateArduino TryEnter exception: " + ex.Message + " Inner exception: " + ex.InnerException);
                        return;
                    }

                    if (!_GotActivateArduinoLock)
                    {
                        Console.WriteLine("Could not enter critical section. Lock is held by another thread. "); return;
                    }                                                                                                                                  // Don't enter the critical section if the lock wasn't acquired.

                    ArduinoBoard ard = new ArduinoBoard(device);

                    //Console.WriteLine("Lock status after TryEnter: _ActivateArduinoLock.IsHeld = {0}, _ActivateArduinoLock.IsHeldByCurrentThread = {1} ", _ActivateArduinoLock.IsHeld, _ActivateArduinoLock.IsHeldByCurrentThread);

                    // Pass event from Arduino's event handler to SerialInterface's ArduinoDataChanged event handler:
                    ard.ArduinoDataChanged += delegate(object sender, ArduinoEventArgs e) { ArduinoDataChanged.Invoke(sender, e); };

                    if (!ard.Port.IsOpen)
                    {
                        ard.OpenConnection();
                    }

                    bool success = false;
                    try
                    {
                        Console.WriteLine("Now pinging arduino...");
                        await ard.Ping(5000); // The timeout is 5 seconds for this ping.
                        // Sending a ping let's us verify that the Arduino is from one of our sensor packages and that this program can communicate with it.
                        success = true;       // If there's no response to the ping or there's another error, ard.Ping() will throw and exception and success will never be set to true.
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("Back in ActivateArduino: " + ex.Message + " Inner exception: " + ex.InnerException);
                        success = false;
                    }

                    //Console.WriteLine("Lock status after ping: _ActivateArduinoLock.IsHeld = {0}, _ActivateArduinoLock.IsHeldByCurrentThread = {1} ", _ActivateArduinoLock.IsHeld, _ActivateArduinoLock.IsHeldByCurrentThread);

                    if (!success)                                                      // If there's some sort of error and a correct ping response is not received before the timeout
                    {
                        if (LCAArduinos.ToList().Exists(a => a.Port.PortName == port)) // If we've previously connected to this arduino, but now it isn't responding
                        {
                            // Note: This case should never happen to the ping that happens in this method because this method only executes fully if the arduino is not already in LCAArduinos
                            // One of the LCA arduinos is not responding!
                            // Set some kind of status variable in arduino instance? (Unresponsive, Running, Ready, etc.)
                            Console.WriteLine("Ping response not received, but the device on this port is thought to be a verified LCA arduino.");
                        }
                        else // The unresponsive arduino is not in LCAArduinos
                        {
                            // Get rid of the ArduinoBoard object ard.
                            // The arduino is not responding to the ping, so it could be either unresponsive or not an arduino from one of our sensor packages.
                            // In either case, it is not an arduino we want to add to LCAArduinos if we cannot communicate with it.
                            ard.Port.Close();
                            ard.Port = null;  // "Destroy" its serial port (unecessary?)
                            ard      = null;  // "Destroy" the arduino instance, since ping was not received
                            // ard will be destroyed when garbage collection occurs.
                            Console.WriteLine("Ping response not received. The ArduinoBoard instance was set to null.");
                        }
                    }
                    else
                    {
                        Console.WriteLine("\n\nThe ping was successful! \n\n");

                        if (Arduino == null)  // If there is no LCA arduino currently in use
                        {
                            // Adds the arduino to LCAArduinos if it is not there already, and sets the arduino as the one currently in use.
                            Arduino = ard;
                        }
                        else
                        {
                            // Adds the arduino to the list of available LCA arduino devices. It's just not the one we're currently using.
                            LCAArduinos.Add(ard);
                        }

                        success = false;
                        try
                        {
                            // It already pinged successfully, so it's a real LCA Arduino. Now we want more information about it.
                            // So ReadConfig gets more info about the Arduino in order to have something to show in the GUI
                            await ard.ReadConfig();
                            // If there's no response or there's another error, ard.ReadConfig() will throw an exception and success will never be set to true.
                            success = true;
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.Message + " Inner exception: " + ex.InnerException);
                            success = false;
                        }
                    }
                    //Console.WriteLine("About to exit lock. _ActivateArduinoLock.IsHeld = {0}, _ActivateArduinoLock.IsHeldByCurrentThread = {1} ", _ActivateArduinoLock.IsHeld, _ActivateArduinoLock.IsHeldByCurrentThread);
                    if (_GotActivateArduinoLock)
                    {
                        _ActivateArduinoLock.Exit(false);
                    }
                    Console.WriteLine("End of ActivateArduino's task.\n\n");
                    return;
                });
            }
            catch (Exception e)
            {
                Console.WriteLine("In ActivateArduino, caught: {0}", e.Message);
            }
            finally
            {
                //if (_GotActivateArduinoLock) { _ActivateArduinoLock.Exit(); }
            }
        }
Ejemplo n.º 3
0
        // Responds to USB PnP (Plug and Play) devices when they are plugged into the computer, unplugged from the computer, or modified
        private void SerialInterface_USBPnPDeviceChanged(object sender, EventArrivedEventArgs e)
        {
            Console.WriteLine("USB PnP device changed");

            //Console.WriteLine(((ManagementBaseObject)(((EventArrivedEventArgs)e).Context))["TargetInstance"].ToString());

            ManagementBaseObject device = (ManagementBaseObject)e.NewEvent["TargetInstance"];  // Is this right?
            string wclass = e.NewEvent.SystemProperties["__Class"].Value.ToString();
            string port   = GetPortName(device);

            //Console.WriteLine(wclass);
            //Console.WriteLine(port);
            //Console.WriteLine(Arduino?.Port?.PortName == port);

            string wop = string.Empty;

            switch (wclass)
            {
            case "__InstanceModificationEvent":
                wop = "modified";
                break;

            case "__InstanceCreationEvent":
                wop = "created";
                break;

            case "__InstanceDeletionEvent":
                wop = "deleted";
                break;

            default:
                wop = "error";
                break;
            }

            if (Arduino?.Port?.PortName == port)  // If the added/removed device is the LCA Arduino in use
            {
                Console.WriteLine("The LCA arduino device on port {0} that you were using was {1}.", port, wop);

                if (wop == "created")
                {
                    throw new InvalidOperationException("Cannot create an arduino device that is already created and in use. ");
                }
                else if (wop == "deleted")
                {
                    // Handle errors here. Code to stop from writing to port or start writing, or whatever?
                    // Or are there no errors to handle?
                    Arduino = null; // This also updates the LCA Arduino list and invokes the event ArduinoChanged
                }
            }
            else if (LCAArduinos.ToList().Exists(a => a?.Port?.PortName == port))  // If the added/removed device was an LCA Arduino not in use
            {
                Console.WriteLine("An LCA arduino device on port {0} that you were not using was {1}.", port, wop);

                if (wop == "deleted")
                {
                    // This part is untested
                    // Want to remove the other ArduinoBoard object from the list without disturbing the currently in-use Arduino
                    int remove_index      = LCAArduinos.ToList().FindIndex(a => a?.Port?.PortName == port);
                    int old_arduino_index = _Arduino;
                    // If this condition is true, Arduino's position in the LCAArduinos list will change after removal:
                    if (remove_index < old_arduino_index && _Arduino != -1)
                    {
                        LCAArduinos.RemoveAt(remove_index);
                        _Arduino--;
                    }
                }
            }
            else  // The added/removed device was not an LCA Arduino (an LCA Arduino device previously known by the program)
            {
                Console.WriteLine("A non-LCA-Arduino device on port {0} was {1}.", port, wop);

                if (wop == "created" && IsGenuineArduino(device))  // A new arduino device was added!
                {
                    Thread.Sleep(TimeSpan.FromMilliseconds(2000)); // Give it a little time before trying to connect. Want the Arduino to go through its setup routine first.
                    ActivateArduino(device);                       // Checks if it is an LCA arduino device in the LCAArduinos list (which it shouldn't be), and adds it to LCAArduinos if it is not
                }
            }

            Console.WriteLine("Done with USB PnP device change.");
        }