virtual protected void OnADMDevicesConnected(ArduinoDeviceManager adm, ADMMessage message)
        {
            _devicesConnected[adm.PortAndNodeID] = true;
            bool startSampler = false;

            if (String.IsNullOrEmpty(RequiredBoards))
            {
                startSampler = true;
            }
            else
            {
                String[] ar = RequiredBoards.Split(',');
                startSampler = true;
                for (int i = 0; i < ar.Length; i++)
                {
                    ArduinoDeviceManager amg = GetADM(ar[i]);
                    if (amg == null || amg.State != ADMState.DEVICE_CONNECTED)
                    {
                        startSampler = false;
                        break;
                    }
                }
            }
            if (startSampler)
            {
                Sampler.Start();
                Tracing?.TraceEvent(TraceEventType.Information, 0, "Started sampler with {0} subjects and tick time of {1}", Sampler.SubjectCount, Sampler.TimerInterval);
            }

            String msg = String.Format("All {0} added devices connected for {1} ", adm.DeviceCount, adm.BoardID);

            Broadcast(ADMEvent.DEVICES_CONNECTED, msg);
        }
 protected bool IsRequiredBoard(byte boardID)
 {
     if (RequiredBoards == null || RequiredBoards == String.Empty)
     {
         return(true);
     }
     String[] ar = RequiredBoards.Split(',');
     for (int i = 0; i < ar.Length; i++)
     {
         if (ar[i] == boardID.ToString())
         {
             return(true);
         }
     }
     return(false);
 }
        virtual protected void DisconnectADM(String port, String nodeID = null)
        {
            if (PortSharing)
            {
                //when using a shared port we connect all the boards in one go
                var ar = nodeID == null?RequiredBoards.Split(',') : new String[]
                {
                    nodeID
                };
                foreach (String nid in ar)
                {
                    String key = port + ":" + nid;
                    if (!ADMS.ContainsKey(key))
                    {
                        continue;
                    }

                    Tracing?.TraceEvent(TraceEventType.Information, 100, "ADMService::DisconnectADM: Attempting to disconnect board @ {0}", key);
                    ArduinoDeviceManager adm = ADMS[key];
                    if (adm != null)
                    {
                        adm.Disconnect();
                    }
                    ADMS.Remove(key);
                    _devicesConnected.Remove(key);
                    Tracing?.TraceEvent(TraceEventType.Information, 100, "ADMService::DisconnectADM: Disconnected board @ {0}", key);
                }
            }
            else
            {
                if (!ADMS.ContainsKey(port))
                {
                    return;
                }

                ArduinoDeviceManager adm = ADMS[port];
                if (adm != null)
                {
                    adm.Disconnect();
                }
                ADMS.Remove(port);
                _devicesConnected.Remove(port);

                Tracing?.TraceEvent(TraceEventType.Information, 100, "ADMService::DisconnectADM: Board {0} on port {1} disconnected", adm.BoardID, port);
                Broadcast(ADMEvent.DISCONNECTED, String.Format("{0} disconnected from port {1}", adm.BoardID, port));
            }
        }
        virtual protected void ConnectADM(String port, String nodeID = null)
        {
            //turn off the sampler ... it will start again when all boards have been connected
            Sampler.Stop();

            if (PortSharing)
            {
                if (RequiredBoards == null)
                {
                    throw new Exception("If using a shared port, 'Nodes' on the port must be specified as the 'RequiredBoards' property");
                }

                //when using a shared port we connect all the boards in one go
                var boards = nodeID == null?RequiredBoards.Split(',') : new String[]
                {
                    nodeID
                };
                List <Exception> exs = new List <Exception>();

                foreach (String nid in boards)
                {
                    String key = port + ":" + nid;
                    if (ADMS.ContainsKey(key))
                    {
                        continue;
                    }

                    try
                    {
                        //now proceed to connect
                        ADMS[key] = null; //reserve a place (cos the connection process takes a while)
                        Tracing?.TraceEvent(TraceEventType.Information, 100, "ADMService::ConnectADM: Attempting to connect board @ {0}", key);
                        ArduinoDeviceManager adm = ArduinoDeviceManager.Connect(nid, port, BaudRate, TryHandleADMMessage);
                        adm.Sampler            = Sampler;
                        adm.Tracing            = Tracing;
                        ADMS[key]              = adm;
                        _devicesConnected[key] = false;
                        Tracing?.TraceEvent(TraceEventType.Information, 100, "ADMService::ConnectADM: Connected to board @ {0}", key);
                        Broadcast(ADMEvent.CONNECTED, String.Format("ADM now Connected @ {0}", key));

                        //Wait here (i.e. before connecting to another board) until the adm is of status device connected
                        while (!adm.DevicesConnected)
                        {
                            System.Threading.Thread.Sleep(1000);
                        }
                    } catch (Exception e)
                    {
                        ADMS.Remove(key);

                        //TODO: remove the trace and create a single 'aggregate' exception and throw that after th eloop
                        Tracing?.TraceEvent(TraceEventType.Error, 100, "ADMService::ConnectADM: Error connection to board @ {0}: {1}", key, e.Message);
                        exs.Add(e);
                    }
                } //end loop of all required boards
            }
            else
            {
                String key = port;
                if (ADMS.ContainsKey(key))
                {
                    throw new Exception("ADMService::ConnectADM: port " + port + " already has an assigned ADM");
                }

                Tracing?.TraceEvent(TraceEventType.Information, 100, "ADMService::ConnectADM: Attempting to connect board on {0} port {0}", port);
                try
                {
                    ADMS[key] = null; //reserve a place (cos the connection process takes a while)

                    //now connct
                    ArduinoDeviceManager adm = ArduinoDeviceManager.Connect(port, BaudRate, TryHandleADMMessage);
                    adm.Sampler            = Sampler;
                    adm.Tracing            = Tracing;
                    ADMS[key]              = adm;
                    _devicesConnected[key] = false;
                    Tracing?.TraceEvent(TraceEventType.Information, 100, "ADMService::ConnectADM: Connected to board on port {0}", port);
                    Broadcast(ADMEvent.CONNECTED, String.Format("Connected ADM to port {0}", port));
                } catch (Exception e) {
                    ADMS.Remove(key);

                    //TODO: remove the trace and create a single 'aggregate' exception and throw that after th eloop
                    Tracing?.TraceEvent(TraceEventType.Error, 100, "ADMService::ConnectADM: Error connection to board @ {0}: {1}", key, e.Message);
                }
            }
        }