Exemple #1
0
        static public ArduinoDeviceManager Connect(String nodeID, String port, SerialBaudRate bps, int timeOut, Action <ADMMessage, ArduinoDeviceManager> listener)
        {
            if (String.IsNullOrEmpty(nodeID))
            {
                throw new Exception("ArduinoDeviceManager::Connect ... nodeID cannot be empty or null");
            }
            ISerialConnection connection = new XBeeFirmataSerialConnection(nodeID, port, bps);

            if (connection != null)
            {
                var session = new ArduinoSession(connection, timeOut);
                try
                {
                    var mgr = new ArduinoDeviceManager(session, listener, port, nodeID);
                    mgr.Connection = connection;
                    return(mgr);
                }
                catch (Exception e)
                {
                    if (connection.IsOpen)
                    {
                        connection.Close();
                    }
                    throw e;
                }
            }

            return(null);
        }
        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);
        }
 public ADMRequest(ArduinoDeviceManager adm, byte tag, String target, int ttl = 60 * 1000)
 {
     ADM       = adm;
     Tag       = tag;
     Target    = target;
     Requested = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
     _ttl      = ttl;
 }
 protected void AddADMRequest(ArduinoDeviceManager adm, byte tag, String replyTo)
 {
     if (tag == 0)
     {
         throw new ArgumentException("AddADMRequest: Tag cannot be 0");
     }
     //we intentionally allow for the possibility of this being overwritten by a future request
     _admRequests.Add(new ADMRequest(adm, tag, replyTo));
 }
        virtual protected bool HandleADMDeviceCommand(ArduinoDeviceManager adm, String deviceID, String command, List <Object> args, Message response)
        {
            if (adm == null)
            {
                throw new Exception("No ADM provided");
            }

            if (!adm.HasDevice(deviceID))
            {
                throw new Exception(String.Format("Device {0} has not been added to ADM", deviceID));
            }

            bool          respond = true;
            ArduinoDevice device  = null;
            MessageSchema schema  = new ADMService.MessageSchema(response);

            switch (command)
            {
            case "list-commands":
                device = adm.GetDevice(deviceID);
                schema.AddDeviceCommands(device);
                break;

            case "status":
                device = adm.GetDevice(deviceID);
                if (device.BoardID == 0)
                {
                    throw new Exception(String.Format("Device {0} does not have a board ID", deviceID));
                }
                AddADMRequest(adm, adm.RequestStatus(device.BoardID), response.Target);
                respond = false;
                break;

            default:
                var commands = command.Split(',');
                foreach (var cmd in commands)
                {
                    var tcmd = cmd.Trim();
                    if (tcmd.ToLower().IndexOf("wait") == 0)
                    {
                        int delay = tcmd.Length > 4 ? System.Convert.ToInt16(tcmd.Substring(4, tcmd.Length - 4)) : 200;
                        System.Threading.Thread.Sleep(delay);
                    }
                    else
                    {
                        byte tag = adm.IssueCommand(deviceID, tcmd, args);
                        if (tag > 0)
                        {
                            AddADMRequest(adm, tag, response.Target);
                            respond = false;
                        }
                    }
                }
                break;
            }
            return(respond);
        }
 private void TryHandleADMMessage(ADMMessage message, ArduinoDeviceManager adm)
 {
     try
     {
         HandleADMMessage(message, adm);
     } catch (Exception e)
     {
         Tracing?.TraceEvent(TraceEventType.Error, 100, "HandleADMMessage Error handling {0}: {1}", message.Type, e.Message);
     }
 }
 protected virtual bool OnADMInactivityTimeout(ArduinoDeviceManager adm, long msQuiet)
 {
     Tracing?.TraceEvent(TraceEventType.Warning, 100, "ADMService::MonitorADM: Last activity of ADM (BoardID={0}) on {1} was {2} ms ago ... so attempting a clear", adm.BoardID, adm.PortAndNodeID, msQuiet);
     try
     {
         adm.Clear();
         Tracing?.TraceEvent(TraceEventType.Information, 100, "ADMService::MonitorADM: Clearing ADM (BoardID={0}) on {1} was successful so attempting to Ping", adm.BoardID, adm.PortAndNodeID);
         adm.RequestStatus();
         return(true);
     }
     catch (Exception e)
     {
         Tracing?.TraceEvent(TraceEventType.Error, 100, "ADMService::MonitorADM: Error clearing ADM (BoardID={0}) on {1}: {2} {3}", adm.BoardID, adm.PortAndNodeID, e.GetType(), e.Message);
         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));
            }
        }
            public void PrepareForBroadcast(ArduinoDeviceManager adm)
            {
                ADMMessage message = (ADMMessage)Message;

                message.AddValue("BoardID", adm.BoardID);
                ArduinoDevice dev = null;

                if (message.TargetID > 0)
                {
                    dev = adm.GetDeviceByBoardID(message.TargetID);
                }
                else if (message.Sender != null && message.Sender != String.Empty)
                {
                    dev = adm.GetDevice(message.Sender);
                }
                message.AddValue(DEVICE_ID, dev != null ? dev.ID : "");
                message.AddValue(DEVICE_NAME, dev != null ? dev.Name : "");
            }
        protected ADMRequest GetADMRequest(ArduinoDeviceManager adm, byte tag, bool remove = true)
        {
            ADMRequest req2return = null;

            foreach (ADMRequest req in _admRequests)
            {
                if (req.ADM == adm && req.Tag == tag)
                {
                    req2return = req;
                    break;
                }
            }

            if (req2return != null)
            {
                _admRequests.Remove(req2return);
            }

            return(req2return);
        }
Exemple #11
0
        static public ArduinoDeviceManager Connect(String port, SerialBaudRate bps, int timeOut, Action <ADMMessage, ArduinoDeviceManager> listener)
        {
            ISerialConnection connection = new EnhancedSerialConnection(port, bps);

            if (connection != null)
            {
                var session = new ArduinoSession(connection, timeOut);
                try
                {
                    var mgr = new ArduinoDeviceManager(session, listener, port);
                    return(mgr);
                } catch (Exception e)
                {
                    if (connection.IsOpen)
                    {
                        connection.Close();
                    }
                    throw e;
                }
            }

            return(null);
        }
 abstract protected void AddADMDevices(ArduinoDeviceManager adm, ADMMessage message);
        /// <summary>
        /// Called by a timer
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="eventArgs"></param>
        protected virtual void MonitorADM(Object sender, ElapsedEventArgs eventArgs)
        {
            _admtimer.Stop();

            try
            {
                lock (_lockMonitorADM)
                {
                    //get all current ports that have boards connected
                    List <String> ports = ArduinoDeviceManager.GetBoardPorts(SupportedBoards, AllowedPorts, DeniedPorts);

                    //build a list of any ADMs that are no longer connected to one of these ports (e.g. USB has been yanked out)
                    List <ArduinoDeviceManager> adms = ADMS.Values.ToList();
                    foreach (ArduinoDeviceManager adm in adms)
                    {
                        if (adm == null)
                        {
                            continue;
                        }

                        if (!ports.Contains(adm.Port))
                        {
                            //if for some reason (config change?) the port for the ADM is not a possible board port
                            DisconnectADM(adm.Port);
                        }
                    }

                    //now we try and connect all the boards that we have not just disconnected but have not yet been connected
                    if (ports.Count > 0 && ADMS.Count < RequiredBoardsCount)
                    {
                        _noPortsFoundWarning = false;
                        foreach (String port in ports)
                        {
                            try
                            {
                                ConnectADM(port);
                            }
                            catch (System.IO.IOException e)
                            {
                                switch (e.HResult)
                                {
                                case Win32.ERROR_ATTACHED_DEVICE_NOT_FUNCTIONING:
                                    ResetPort(port, e);
                                    break;
                                }
                                Tracing?.TraceEvent(TraceEventType.Error, 100, "ADMService::MonitorADM: Connecting ADM to port {0} produced IOException {1} ({2}): {3}", port, e.GetType().ToString(), e.HResult, e.Message);
                            }
                            catch (Exception e)
                            {
                                Tracing?.TraceEvent(TraceEventType.Error, 100, "ADMService::MonitorADM: Connecting ADM to port {0} produced Exception {1} ({2}): {3}", port, e.GetType().ToString(), e.HResult, e.Message);
                            }
                        }
                    }
                    else if (ADMS.Count < RequiredBoardsCount)
                    {
                        if (!_noPortsFoundWarning)
                        {
                            Tracing?.TraceEvent(TraceEventType.Warning, 100, "ADMService::MonitorADM: No boards connected to any port");
                            _noPortsFoundWarning = true;
                        }
                    }


                    //Finally we check on the state of the ADM
                    foreach (ArduinoDeviceManager adm in adms)
                    {
                        if (adm == null)
                        {
                            continue;
                        }

                        if (!adm.IsConnected)
                        {
                            //TODO: how do we handle this?
                            Tracing?.TraceEvent(TraceEventType.Warning, 100, "ADM (BDID={0}) @ {1} is of state", adm.State);
                        }
                        else if (ADMInactivityTimeout > 0)
                        {
                            //if there has been a suspicioius lack of activity...
                            long msQuiet = (DateTime.Now.Ticks - adm.LastMessageReceivedOn.Ticks) / TimeSpan.TicksPerMillisecond;
                            if (msQuiet > ADMInactivityTimeout)
                            {
                                OnADMInactivityTimeout(adm, msQuiet);
                            }
                        }
                    }
                } //end of monitor lock
            } catch (Exception e)
            {
                Tracing?.TraceEvent(TraceEventType.Error, 100, "Unknown exception in MonitorADM: {0}, {1}", e.GetType().ToString(), e.Message);
            }

            _admtimer.Start();
        }
 virtual protected void ReconnectADM(ArduinoDeviceManager adm)
 {
     DisconnectADM(adm.Port, adm.NodeID);
     System.Threading.Thread.Sleep(1000);
     ConnectADM(adm.Port, adm.NodeID);
 }
        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);
                }
            }
        }
        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);
        }
        virtual protected void HandleADMMessage(ADMMessage message, ArduinoDeviceManager adm)
        {
            switch (message.Type)
            {
            case MessageType.ERROR:
                ErrorCode errCode = message.HasValue("ErrorCode") ? message.GetEnum <ErrorCode>("ErrorCode") : ErrorCode.ERROR_UNKNOWN;
                Tracing?.TraceEvent(TraceEventType.Error, 100, "ADM {0} produced error: {1}", adm.BoardID, errCode);
                switch (errCode)
                {
                case ErrorCode.ERROR_ADM_NOT_INITIALISED:
                    ReconnectADM(adm);
                    break;

                default:
                    //currently do nothing
                    break;
                }
                break;

            case MessageType.WARNING:
                Tracing?.TraceEvent(TraceEventType.Warning, 100, "ADM {0} produced warning: {1}", adm.BoardID, message.Value);
                break;

            case MessageType.STATUS_RESPONSE:
                if (!PortSharing && !IsRequiredBoard(adm.BoardID))
                {
                    Tracing?.TraceEvent(TraceEventType.Warning, 100, "ADM {0} is not one of the required boards ({1}).  Disconnecting from port {2}...", adm.BoardID, RequiredBoards, adm.Port);
                    DisconnectADM(adm.Port);
                    break;
                }

                if (adm.State == ADMState.DEVICE_READY)
                {
                    Tracing?.TraceEvent(TraceEventType.Verbose, 100, "ADM: Ready to add devices to {0} on port {1} ...", adm.BoardID, adm.PortAndNodeID);
                    AddADMDevices(adm, message);
                    Tracing?.TraceEvent(TraceEventType.Verbose, 100, "ADM: {0} devices added to {1} on port {2}. Now configure board", adm.DeviceCount, adm.BoardID, adm.PortAndNodeID);
                    adm.Configure();
                }
                else if (adm.State == ADMState.DEVICE_CONNECTED)
                {
                    if (message.HasValue("Initialised") && !message.GetBool("Initialised"))
                    {
                        //Console.WriteLine("Whoa ... {0} has reset without us knowing", adm.PortAndNodeID);
                    }
                }
                break;

            case MessageType.CONFIGURE_RESPONSE:
                String key = adm.PortAndNodeID;
                if (adm.State == ADMState.DEVICE_CONNECTED && !_devicesConnected[key])
                {
                    Tracing?.TraceEvent(TraceEventType.Verbose, 100, "ADM: All {0} devices now configured and connected to board {1} on port {2}", adm.DeviceCount, adm.BoardID, adm.PortAndNodeID);
                    OnADMDevicesConnected(adm, message);
                }
                break;

            case MessageType.PING_RESPONSE:
                break;
            }

            if (message.Tag > 0)
            {
                ADMRequest req = GetADMRequest(adm, message.Tag);
                if (req != null)
                {
                    if (req.HasExpired())
                    {
                        Tracing?.TraceEvent(TraceEventType.Warning, 0, "ADM request for tag {0} and target {1} has expired so not returning message of type {2}", message.Tag, req.Target, message.Type);
                        return;
                    }
                    else
                    {
                        message.Target = req.Target;
                    }
                }
            }

            var schema = new ADMService.MessageSchema(message);

            schema.PrepareForBroadcast(adm);

            //notify other clients listening to this client
            Broadcast(ADMEvent.MESSAGE, message);
        }