virtual protected void ResetPort(String port, Exception e)
        {
            //ensure that if an ADM is connected then we disconnect it first
            DisconnectADM(port);
            System.Threading.Thread.Sleep(500);
            if (SerialPorts.IsOpen(port))
            {
                throw new Exception("Serial port is open on " + port);
            }

            //now we disable-enable the device connected to the port
            DeviceManager devMgr = DeviceManager.GetInstance();
            List <DeviceManager.DeviceInfo> ar = devMgr.GetDevices("(" + port + ")");

            if (ar.Count == 1)
            {
                DeviceManager.DeviceInfo di = ar[0];
                Tracing?.TraceEvent(TraceEventType.Information, 0, "Attempting reset of device {0} of status {1} on port {2}", di.Description, di.Status, port);;
                Process proc   = devMgr.ResetDevice(di.InstanceID);
                String  output = proc.StandardOutput.ReadToEnd();
                Tracing?.TraceEvent(TraceEventType.Information, 0, output);
            }
            else
            {
                Tracing?.TraceEvent(TraceEventType.Warning, 0, "ADMService::ResetPort Could not find a unique device for port {0}", port);
            }
        }
        override public bool HandleCommand(Connection cnn, Message message, String cmd, List <Object> args, Message response)
        {
            bool                 respond = true;
            MessageSchema        schema  = new ADMService.MessageSchema(response);
            DeviceManager        devMgr;
            ArduinoDeviceManager adm;

            switch (cmd)
            {
            case "status":
                schema.AddADMS(ADMS);
                List <String> ports = ArduinoDeviceManager.GetBoardPorts(SupportedBoards, AllowedPorts, DeniedPorts);
                schema.AddPorts(ports);
                schema.AddRequiredBoards(RequiredBoards);

                devMgr = DeviceManager.GetInstance();
                List <String> portDevices = new List <String>();
                foreach (String port in ports)
                {
                    List <DeviceManager.DeviceInfo> devs = devMgr.GetDevices("(" + port + ")");
                    foreach (DeviceManager.DeviceInfo devInfo in devs)
                    {
                        String s = String.Format("{0} ({1}): {2}", devInfo.Description, devInfo.InstanceID, devInfo.Status);
                        portDevices.Add(s);
                    }
                }
                response.AddValue("PortDevices", portDevices);
                break;

            case "disable-port":
            case "enable-port":
            case "reset-port":
                if (args.Count != 1 || args[0] == null || args[0].ToString() == String.Empty)
                {
                    throw new Exception("No port specified");
                }
                String devicePort = args[0].ToString().ToUpper();
                devMgr = DeviceManager.GetInstance();
                List <DeviceManager.DeviceInfo> ar = devMgr.GetDevices("(" + devicePort + ")");
                if (ar.Count != 1)
                {
                    throw new Exception("Cannot find device on port " + devicePort);
                }
                DeviceManager.DeviceInfo di = ar[0];

                //first we check if there is an ADM on this port
                String output = "";
                lock (_lockMonitorADM)
                {
                    if (ADMS.ContainsKey(devicePort))
                    {
                        output += String.Format("Found ADM on port {0} so disconnecting first", devicePort) + Environment.NewLine;
                        DisconnectADM(devicePort);
                        System.Threading.Thread.Sleep(500);
                        if (SerialPorts.IsOpen(devicePort))
                        {
                            throw new Exception("Serial port is open on " + devicePort);
                        }
                    }

                    Process proc = null;
                    if (cmd == "disable-port")
                    {
                        proc = devMgr.DisableDevice(di.InstanceID);
                    }
                    else if (cmd == "enable-port")
                    {
                        proc = devMgr.EnableDevice(di.InstanceID);
                    }
                    else
                    {
                        proc = devMgr.ResetDevice(di.InstanceID);
                    }
                    output += proc.StandardOutput.ReadToEnd();
                }
                response.Value = output;
                break;

            default:
                var tgtcmd = cmd.Split(':');
                if (tgtcmd.Length < 2)
                {
                    throw new Exception(String.Format("ADM: Unrecognised command {0}", cmd));
                }

                //Check that there are any boards connected
                if (ADMS.Count == 0)
                {
                    throw new Exception("ADM: No boards connected");
                }

                //so this is an ADM command, find the board first
                adm = GetADM(tgtcmd[0]);

                if (adm == null)
                {
                    throw new Exception(String.Format("ADM: Cannot find ADM {0}", tgtcmd[0]));
                }

                if (!adm.IsConnected)
                {
                    throw new Exception(String.Format("ADM: {0} is not conntected", adm.BoardID));
                }

                //handle commands related to the board (i.e. not to a specific added device)
                if (tgtcmd.Length == 2)
                {
                    int repeat;    //frequently used var name
                    int delay;     //frequently used var name
                    switch (tgtcmd[1].ToLower())
                    {
                    case "status":
                        AddADMRequest(adm, adm.RequestStatus(), response.Target);
                        respond = false;
                        break;

                    case "ping":
                        AddADMRequest(adm, adm.Ping(), response.Target);
                        respond = false;
                        break;

                    case "pingloadtest":
                        repeat = args != null && args.Count > 0 ? System.Convert.ToInt16(args[0]) : 10;
                        delay  = args != null && args.Count > 1 ? System.Convert.ToInt16(args[1]) : 500;
                        Task.Run(() =>
                        {
                            for (int i = 0; i < repeat; i++)
                            {
                                adm.Ping();
                                System.Threading.Thread.Sleep(delay);
                            }
                        });
                        respond = false;
                        break;

                    case "capability":
                        var lbc = adm.ListBoardCapability();
                        response.AddValue("PinCount: ", lbc.Count);
                        response.AddValue("Pins", lbc);
                        break;

                    case "disconnect":
                        DisconnectADM(adm.Port);
                        break;

                    case "setdigitalpin":
                        if (args.Count < 2)
                        {
                            throw new Exception("Insufficient arguments ... must supply a pin number and value");
                        }
                        int  pin = System.Convert.ToInt16(args[0]);
                        bool val = Chetch.Utilities.Convert.ToBoolean(args[1]);
                        if (!adm.IsPinCapable(pin, Solid.Arduino.Firmata.PinMode.DigitalOutput))
                        {
                            throw new Exception(String.Format("Pin {0} is not capabale of digital output", pin));
                        }
                        if (adm.GetDevicesByPin(pin) != null)
                        {
                            throw new Exception(String.Format("Pin {0} is being used by a device", pin));
                        }
                        adm.SetDigitalPinMode(pin, Solid.Arduino.Firmata.PinMode.DigitalOutput);
                        adm.SetDigitalPin(pin, val);
                        break;

                    case "setdigitalport":
                        if (args.Count < 2)
                        {
                            throw new Exception("Insufficient arguments ... must supply a port number and value");
                        }
                        int  port   = System.Convert.ToInt16(args[0]);
                        bool enable = Chetch.Utilities.Convert.ToBoolean(args[1]);
                        adm.SetDigitalReportMode(port, enable);
                        //adm.G
                        break;

                    case "list-devices":
                        schema.AddDevices(adm.GetDevices());
                        break;

                    case "list-pins":

                        break;

                    default:
                        throw new Exception(String.Format("No ADM direct command {0}", tgtcmd[1]));
                    }
                }
                else
                {
                    //handle command specific to device
                    try
                    {
                        respond = HandleADMDeviceCommand(adm, tgtcmd[1], tgtcmd[2], args, response);
                    } catch (Exception e)
                    {
                        Tracing?.TraceEvent(TraceEventType.Error, 0, "Exception: {0}", e.Message);
                        throw e;
                    }
                }

                if (response.Value == null || response.Value == String.Empty)
                {
                    response.Value = "Handled " + cmd;
                }

                break;
            }

            return(respond);
        }