示例#1
0
        private void HandleReceivedADMMessage(ADMMessage message)
        {
            try
            {
                //do some general checking
                //TODO: check BoardID matches to SenderID
                lock (MessageStatsLock)
                {
                    LastMessageReceived    = message;
                    LastMessageReceivedOn  = DateTime.Now;
                    MessageReceivedSuccess = message.Tag == LastMessageSent.Tag;
                    MessagesReceived++;
                }
                //Console.WriteLine("<--------- {0}: Received message {1} tag {2} target {3} from sender {4}", PortAndNodeID, message.Type, message.Tag, message.TargetID, message.SenderID);

                switch (message.Type)
                {
                case Messaging.MessageType.INITIALISE_RESPONSE:
                    message.AddValue("LittleEndian", message.ArgumentAsBool(0));
                    LittleEndian = message.GetBool("LittleEndian");
                    message.AddValue("FreeMemory", message.ArgumentAsInt(1));
                    BoardID = message.SenderID;
                    message.AddValue("MaxDevices", message.ArgumentAsInt(2));
                    MaxDevices = message.GetInt("MaxDevices");
                    message.AddValue("LEDBI", message.ArgumentAsInt(3));
                    LEDBIPin = message.GetInt("LEDBI");
                    break;

                case Messaging.MessageType.STATUS_RESPONSE:
                    try
                    {
                        if (message.TargetID == 0)
                        {
                            message.AddValue("FreeMemory", message.ArgumentAsInt(0));
                            message.AddValue("BoardType", message.ArgumentAsString(1));
                            message.AddValue("Initialised", message.ArgumentAsBool(2));
                            message.AddValue("DeviceCount", message.ArgumentAsInt(3));
                        }
                        if (State == ADMState.CONNECTED)
                        {
                            State = ADMState.DEVICE_READY;
                        }
                    }
                    catch (Exception e)
                    {
                        Tracing?.TraceEvent(TraceEventType.Error, 4000, "STATUS_RESPONSE error: {0}, {1}", e.GetType(), e.Message);
                        throw new ArduinoException(PortAndNodeID, e.Message, e);
                    }

                    //record this
                    LastStatusResponseMessage = message;
                    LastStatusResponseOn      = DateTime.Now;
                    break;

                case Messaging.MessageType.PING_RESPONSE:
                    //record this
                    LastPingResponseMessage = message;
                    LastPingResponseOn      = DateTime.Now;
                    break;

                case Messaging.MessageType.CONFIGURE_RESPONSE:
                    break;

                case Messaging.MessageType.ERROR:
                    //record last error message
                    if (message.Arguments.Count > 0)
                    {
                        message.AddValue("ErrorCode", (ErrorCode)message.ArgumentAsByte(0));
                    }
                    else
                    {
                        message.AddValue("ErrorCode", ErrorCode.ERROR_HOST_GENERATED);
                    }
                    LastErrorMessage = message;
                    LastErrorOn      = DateTime.Now;
                    break;
                }

                if (State == ADMState.DEVICE_READY || State == ADMState.DEVICE_CONNECTED)
                {
                    //direct messages to devices
                    var dev = GetTargetedDevice(message);
                    if (dev != null)
                    {
#if DEBUG
                        Debug.Print(String.Format("Handling message {0} for device {1} ... connected: {2}, memory: {3}", message.Type, dev.ID, dev.IsConnected, message.HasValue("FM") ? message.GetValue("FM") : "N/A"));
#endif
                        try
                        {
                            dev.HandleMessage(message);
                        }
                        catch (Exception e)
                        {
                            Tracing?.TraceEvent(TraceEventType.Error, 4000, "Handling message for device {0} produced exception {1}: {2}", dev.ID, e.GetType(), e.Message);
                            throw new ArduinoException(dev.ID, e.Message, e);
                        }
                    }

                    //we do this test after handling message because the message maybe a CONFIGURE_RESPONSE message which will then set the 'connected' status of the device
                    if (message.Type == Messaging.MessageType.CONFIGURE_RESPONSE && DevicesConnected)
                    {
                        State = ADMState.DEVICE_CONNECTED;
                    }
                }
            } catch (Exception e)
            {
                byte tag = message != null ? message.Tag : (byte)0;
                message       = new ADMMessage();
                message.Type  = Messaging.MessageType.ERROR;
                message.Value = e.Message;
                message.AddValue("ErrorCode", ErrorCode.ERROR_HOST_GENERATED);
                if (e is ArduinoException)
                {
                    ArduinoException ae = (ArduinoException)e;
                    message.AddValue("ErrorSource", ae.Source);
                }

                message.Tag = tag;
            }

            Broadcast(message);
        }
        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);
        }