Ejemplo n.º 1
0
        public void Broadcast(ADMMessage message)
        {
            if (message == null)
            {
                return;
            }

            MessageTags.Release(message.Tag);
            message.Target = null; //clear the target as it may have been used internally but now this is a broadcast so it's not intended for any specific target

            if (_listener != null && message.CanBroadcast)
            {
                switch (message.Type)
                {
                case Chetch.Messaging.MessageType.ERROR:
                    _listener(message, this);
                    break;

                default:
                    if (State == ADMState.DEVICE_READY || State == ADMState.DEVICE_CONNECTED)
                    {
                        _listener(message, this);
                    }
                    break;
                }
            }
        }
Ejemplo n.º 2
0
        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);
        }
Ejemplo n.º 3
0
        public byte Ping()
        {
            var message = new ADMMessage(MessageTags.CreateTag());

            message.Type     = Messaging.MessageType.PING;
            message.TargetID = 0;
            SendMessage(message);
            return(message.Tag);
        }
Ejemplo n.º 4
0
        public byte RequestStatus(byte boardID = 0)
        {
            var message = new ADMMessage(MessageTags.CreateTag());

            message.Type     = Messaging.MessageType.STATUS_REQUEST;
            message.TargetID = boardID;
            SendMessage(message);
            return(message.Tag);
        }
Ejemplo n.º 5
0
        public byte Initialise()
        {
            ADMMessage message = new ADMMessage(MessageTags.CreateTag());

            message.TargetID = 0;
            message.Type     = Messaging.MessageType.INITIALISE;
            SendMessage(message);
            return(message.Tag);
        }
Ejemplo n.º 6
0
 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);
     }
 }
Ejemplo n.º 7
0
        virtual public void HandleMessage(ADMMessage message)
        {
            switch (message.Type)
            {
            case Messaging.MessageType.CONFIGURE_RESPONSE:
                IsConnected = true;
                OnConnect(message);
                break;

            default:
                break;
            }
        }
Ejemplo n.º 8
0
            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 : "");
            }
Ejemplo n.º 9
0
 public void Configure()
 {
     if (_devices.Count == 0)
     {
         State = ADMState.DEVICE_CONNECTED;
     }
     else
     {
         //send configuration/setup data to board
         foreach (ArduinoDevice device in _devices.Values)
         {
             var message = new ADMMessage();
             message.LittleEndian = LittleEndian;
             message.Type         = Messaging.MessageType.CONFIGURE;
             device.AddConfig(message);
             SendMessage(message);
         }
     }
 }
Ejemplo n.º 10
0
        virtual public void AddConfig(ADMMessage message)
        {
            //add board ID, device category and device name
            message.TargetID = BoardID;
            message.AddArgument((byte)Category);
            message.AddArgument(Name);

#if DEBUG
            System.Diagnostics.Debug.Print(String.Format("Adding config for device {0} ... ", ID));
#endif

            if (Mgr.Sampler != null && SampleInterval > 0 && SampleSize > 0)
            {
                Mgr.Sampler.Add(this, SampleInterval, SampleSize, SamplingOptions, SampleIntervalDeviation);
#if DEBUG
                System.Diagnostics.Debug.Print(String.Format("Adding to sampler with interval {0} and sample size {1}", SampleInterval, SampleSize));
#endif
            }
        }
Ejemplo n.º 11
0
        public byte SendCommand(byte targetID, ArduinoCommand command, List <Object> extraArgs = null, byte tag = 0)
        {
            var message = new ADMMessage();

            message.LittleEndian = LittleEndian;
            message.Type         = Messaging.MessageType.COMMAND;
            message.TargetID     = targetID;
            message.Tag          = tag == 0 ? MessageTags.CreateTag() : tag;
            message.CommandID    = command.ID;

            List <Object> allArgs = command.Arguments;

            if (extraArgs != null && extraArgs.Count > 0)
            {
                allArgs.AddRange(extraArgs);
            }

            foreach (Object arg in allArgs)
            {
                byte[] b;
                if (arg is String)
                {
                    b = Chetch.Utilities.Convert.ToBytes((String)arg);
                }
                else if (arg.GetType().IsValueType)
                {
                    b = Chetch.Utilities.Convert.ToBytes((ValueType)arg, LittleEndian);
                }
                else
                {
                    throw new Exception("Unable to process type " + arg.GetType());
                }
                message.AddArgument(b);
            }

            return(SendMessage(message));
        }
Ejemplo n.º 12
0
        public byte SendMessage(ADMMessage message)
        {
            if (message == null)
            {
                return(0);
            }

            if (Monitor.TryEnter(SendMessageLock, SEND_MESSAGE_LOCK_TIMEOUT))
            {
                try
                {
                    bool ready2send;
                    long msSinceLastSent = -1;

                    //loop waiting for a message response
                    do
                    {
                        msSinceLastSent = (DateTime.Now.Ticks - LastMessageSentOn.Ticks) / TimeSpan.TicksPerMillisecond;
                        if (LastMessageSent == null || MessageReceivedSuccess)
                        {
                            ready2send = true;
                        }
                        else
                        {
                            ready2send = msSinceLastSent > MESSAGE_RECEIVED_TIMEOUT;
                            if (!ready2send)
                            {
                                _sleep(10); //crappy idea to reduce load on cpu
                            }
                            else
                            {
                                //so here we have waited long enough for the previous sent message which has failed to arrive
                                //so we proceed with sending anyway
                                Tracing?.TraceEvent(TraceEventType.Warning, 0, "SendMessage {0}: Sending {1} timed out waiting to receive message {2} tag {3}", PortAndNodeID, message.Type, LastMessageSent.Type, LastMessageSent.Tag);
                            }
                        }
                    } while (!ready2send);

                    //store old values before sending (rollback if exception thrown)
                    //This unusual approach is because it appeared like messages were being received before the SendString could exit
                    ADMMessage lastMessageSent   = LastMessageSent;
                    DateTime   lastMessageSentOn = LastMessageSentOn;
                    try
                    {
                        lock (MessageStatsLock)
                        {
                            MessagesSent++;
                            LastMessageSent        = message;
                            LastMessageSentOn      = DateTime.Now;
                            MessageReceivedSuccess = false;
                        }
                        if (message.Tag == 0)
                        {
                            message.Tag = MessageTags.CreateTag();
                        }
                        message.SenderID = BoardID;
                        //Console.WriteLine("-------------> {0}: Sending message {1} tag {2} target {3}." , PortAndNodeID, message.Type, message.Tag, message.TargetID);
                        SendString(message.Serialize());
                    }
                    catch (Exception e)
                    {
                        lock (MessageStatsLock) //rollback
                        {
                            MessagesSent--;
                            LastMessageSent   = lastMessageSent;
                            LastMessageSentOn = lastMessageSentOn;
                        }
                        String errMsg = String.Format("{0} SendMessage: sending {1} (Tag={2}) produced exception {3} {4}", PortAndNodeID, message.Type, message.Tag, e.GetType(), e.Message);
                        Tracing?.TraceEvent(TraceEventType.Error, 0, errMsg);
                        throw e;
                    }
                }
                finally
                {
                    Monitor.Exit(SendMessageLock);
                }
            } //end attempt to try get lock
            else
            {
                //we waited too long to get the lock...
                throw new SendFailedException("ArduinoDeviceManager::SendMessage ... waited to long to obtain lock");
            }
            return(message.Tag);
        }
Ejemplo n.º 13
0
 abstract protected void AddADMDevices(ArduinoDeviceManager adm, ADMMessage message);
Ejemplo n.º 14
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);
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Handle messages that harve arrived from the board and successfully processed by Firmata
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="eventArgs"></param>
        private void HandleFirmataMessageReceived(Object sender, FirmataMessageEventArgs eventArgs)
        {
            var        fmessage = eventArgs.Value;
            ADMMessage message  = null;

            try
            {
                switch (fmessage.Type)
                {
                case Solid.Arduino.Firmata.MessageType.FirmwareResponse:
                    break;

                case Solid.Arduino.Firmata.MessageType.StringData:
                    StringData sd = (StringData)fmessage.Value;
                    try
                    {
                        String serialized = sd.Text;
                        message = ADMMessage.Deserialize <ADMMessage>(serialized, MessageEncoding.BYTES_ARRAY);
                    }
                    catch (Exception e)
                    {
                        String sbytes = BitConverter.ToString(Chetch.Utilities.Convert.ToBytes(sd.Text));
                        Tracing?.TraceEvent(TraceEventType.Error, 4000, "Deserializing {0} produced exception {1}: {2}", sbytes, e.GetType(), e.Message);
                        throw e;
                    }
                    break;

                case Solid.Arduino.Firmata.MessageType.PinStateResponse:
                    break;

                case Solid.Arduino.Firmata.MessageType.DigitalPortState:
                    DigitalPortState portState = (DigitalPortState)fmessage.Value;
                    String           s         = BitConverter.ToString(BitConverter.GetBytes(portState.Pins));

                    int pinsChanged;
                    if (_portStates.ContainsKey(portState.Port))
                    {
                        pinsChanged = portState.Pins ^ _portStates[portState.Port].Pins;
                    }
                    else
                    {
                        pinsChanged = 255;
                    }
                    _portStates[portState.Port] = portState;

                    for (int i = 0; i < 8; i++)
                    {
                        int bit2check = (int)System.Math.Pow(2, i);
                        if ((bit2check & pinsChanged) == 0)
                        {
                            continue;
                        }

                        bool state     = portState.IsSet(i);
                        int  pinNumber = GetPinForPort(portState.Port, i);    //TODO: this might need to be board dependent
                        var  devs      = GetDevicesByPin(pinNumber);
                        if (devs != null)
                        {
                            foreach (var dev in devs)
                            {
                                dev.HandleDigitalPinStateChange(pinNumber, state);
                            }
                        }
                    }

                    //String s1 = System.Convert.ToString(portState.Pins, 2);
                    //String s2 = System.Convert.ToString(pinsChanged, 2);
                    //Debug.Print("Pins/2change: " + s1 + "/" + s2);
                    break;

                case Solid.Arduino.Firmata.MessageType.CapabilityResponse:
                    break;

                default:
                    break;
                }
            } catch (Exception e)
            {
                byte tag = message != null ? message.Tag : (byte)0;
                message       = new ADMMessage();
                message.Type  = Messaging.MessageType.ERROR;
                message.Value = e.Message;
                message.Tag   = tag;
            }

            if (message != null)
            {
                Task.Run(() => { HandleReceivedADMMessage(message); });
            }
        }
Ejemplo n.º 16
0
        public ArduinoDevice GetTargetedDevice(ADMMessage message)
        {
            var boardID = message.TargetID;

            return(GetDeviceByBoardID(boardID));
        }
Ejemplo n.º 17
0
 public byte AssignID(byte idx)
 {
     ID = ADMMessage.CreateCommandID((byte)Type, idx);
     return(ID);
 }
Ejemplo n.º 18
0
        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);
        }
Ejemplo n.º 19
0
 //called after the device has been configured on the board
 virtual protected void OnConnect(ADMMessage message)
 {
     //hook
 }
Ejemplo n.º 20
0
 virtual protected void Broadcast(ADMMessage message)
 {
     message.Sender = ID;
     Mgr.Broadcast(message);
 }