private void QueueMessage(MessageBase message)
        {
            lock (this.keyedMessageQueues)
            {
                if (!this.keyedMessageQueues.ContainsKey(message.Service))
                {
                    this.keyedMessageQueues.Add(message.Service, new Queue<MessageBase>());
                }

                this.keyedMessageQueues[message.Service].Enqueue(message);
            }

            lock (this.keys)
            {
                this.keys.Enqueue(message.Service);
            }
        }
        private async Task HandleMessageUnprotected(MessageBase message)
        {
            this.Log("R: " + message._Source + "\r\n");

            try
            {
                if (message.Service != "SYSTEM")
                {
                    var dictionary = new Dictionary<string, string> { { "Type", message.Service } };
                    App.Telemetry.TrackEvent("MessageInfo", dictionary);
                }
            }
            catch (Exception)
            {
                // ignore telemetry errors if any
            }

            switch (message.Service)
            {
                case "SYSTEM":
                    {
                        if (message.Action.Equals("PONG"))
                        {
                            var totalRoundTrip = this.recentStringReceivedTick - this.sentPingTick;
                            App.Telemetry.TrackMetric(
                                "VirtualShieldPingPongTimeDifferenceMillisec", 
                                totalRoundTrip / TimeSpan.TicksPerMillisecond);
                        }
                        else if (message.Action.Equals("START"))
                        {
                            // reset orientation
                            DisplayInformation.AutoRotationPreferences = DisplayOrientations.None;

                            // turn off all sensors, accept buffer length
                            var switches = new SensorSwitches { A = 0, G = 0, L = 0, M = 0, P = 0, Q = 0 };
                            var sensors = new List<SensorSwitches>();
                            sensors.Add(switches);

                            this.ToggleSensors(new SensorMessage { Sensors = sensors, Id = 0 });
                        }

                        break;
                    }

                case "SMS":
                    {
                        var smsService = new Sms();
                        var sms = message as SmsMessage;

                        StorageFile attachment = null;
                        if (!string.IsNullOrWhiteSpace(sms.Attachment))
                        {
                            attachment = await StorageFile.GetFileFromPathAsync(sms.Attachment);
                        }

                        smsService.Send(sms.To, sms.Message, attachment, null);
                        break;
                    }

                case "EMAIL":
                    {
                        var email = new EmailMessage();
                        var emailMessage = message as Core.Models.EmailMessage;
                        email.Body = emailMessage.Message;
                        email.Subject = emailMessage.Subject;
                        email.To.Add(new EmailRecipient(emailMessage.To));
                        if (!string.IsNullOrWhiteSpace(emailMessage.Cc))
                        {
                            email.CC.Add(new EmailRecipient(emailMessage.To));
                        }

                        if (!string.IsNullOrWhiteSpace(emailMessage.Attachment))
                        {
                            var storageFile = await StorageFile.GetFileFromPathAsync(emailMessage.Attachment);
                            var stream = RandomAccessStreamReference.CreateFromFile(storageFile);

                            var attachment = new EmailAttachment(storageFile.Name, stream);

                            email.Attachments.Add(attachment);
                        }

                        await EmailManager.ShowComposeNewEmailAsync(email);

                        break;
                    }

                case "NOTIFY":
                    {
                        var notify = message as NotifyMessage;
                        if (string.IsNullOrWhiteSpace(notify.Action))
                        {
                            return;
                        }

                        if (notify.Action.ToUpperInvariant().Equals("TOAST"))
                        {
                            await this.SendToastNotification(notify);
                        }
                        else if (notify.Action.ToUpperInvariant().Equals("TILE"))
                        {
                            await this.SendTileNotification(notify);
                        }

                        break;
                    }

                case "LCDG":
                case "LCDT":
                    {
                        await
                            this.dispatcher.RunAsync(
                                CoreDispatcherPriority.Normal, 
                                () => { this.screen.LcdPrint(message as ScreenMessage); });
                        break;
                    }

                case "LOG":
                    {
                        await this.screen.LogPrint(message as ScreenMessage);
                        break;
                    }

                case "SPEECH":
                    {
                        this.Speak(message as SpeechMessage);
                        break;
                    }

                case "RECOGNIZE":
                    {
                        this.Recognize(message as SpeechRecognitionMessage);
                        break;
                    }

                case "SENSORS":
                    {
                        this.ToggleSensors(message as SensorMessage);
                        break;
                    }

                case "WEB":
                    {
                        await this.web.RequestUrl(message as WebMessage);
                        break;
                    }

                case "CAMERA":
                    {
                        var camMsg = message as CameraMessage;
                        if (camMsg.Action != null && camMsg.Message != null && camMsg.Message.Equals("PREVIEW"))
                        {
                            if (camMsg.Action.Equals("ENABLE") && !this.isCameraInitialized)
                            {
                                await this.InitializeCamera();
                                this.camera.isPreviewing = true;
                            }
                            else if (camMsg.Action.Equals("DISABLE"))
                            {
                                this.camera.isPreviewing = false;
                            }
                        }
                        else
                        {
                            await this.TakePicture(message as CameraMessage);
                        }

                        break;
                    }

                case "VIBRATE":
                    {
                        this.Vibrate(message as TimingMessage);
                        break;
                    }

                case "MICROPHONE":
                    {
                        await this.Record(message as TimingMessage);
                        break;
                    }

                case "PLAY":
                    {
                        await this.Play(message as TimingMessage);
                        break;
                    }

                case "DEVICE":
                    {
                        await this.DeviceInfo(message as DeviceMessage);
                        break;
                    }
            }
        }
        internal async Task SendEvent(
            object sender, 
            RoutedEventArgs e, 
            string action, 
            MessageBase message = null, 
            string messageText = null)
        {
            if (sender is Grid && this.sensors.ContainsKey("LCDG:TOUCH"))
            {
                if (e is PointerRoutedEventArgs)
                {
                    var pe = (PointerRoutedEventArgs)e;
                    var pt = pe.GetCurrentPoint(sender as FrameworkElement);
                    await
                        this.SendResult(
                            new ScreenResultMessage(message)
                                {
                                    Area = "TOUCH", 
                                    Action = action, 
                                    X = pt.Position.X, 
                                    Y = pt.Position.Y
                                });
                }
            }
            else if (!(sender is Grid))
            {
                var source = (e.OriginalSource ?? sender) as FrameworkElement;

                var id = (int)source.GetValue(Screen.RemoteIdProperty);

                if (message == null)
                {
                    message = new ScreenMessage { Type = 'S', Service = "LCDG", Id = id };
                }

                var newid = (message.Id == 0) ? id : message.Id;

                await
                    this.SendResult(
                        new ScreenResultMessage(message)
                            {
                                Area = source.GetType().Name.ToUpperInvariant(), 
                                Action = action, 
                                Tag = source.Tag?.ToString(), 
                                Type = message.Type ?? 'S', 
                                Id = newid, 
                                Result = messageText
                            }, 
                        newid + action);
            }
        }
 private async Task ProcessMessage(MessageBase message)
 {
     try
     {
         await this.HandleMessageUnprotected(message);
     }
     catch (UnsupportedSensorException e)
     {
         await this.SendResult(new ResultMessage(message) { ResultId = -2, Result = e.Message });
     }
     catch (Exception e)
     {
         await this.SendResult(new ResultMessage(message) { ResultId = -1, Result = e.Message });
     }
 }
 protected void OnMessageReceived(MessageBase message)
 {
     // If the message was valid, invoke MessageReceived
     if (message != null)
     {
         this.MessageReceived?.Invoke(message);
     }
 }