Esempio n. 1
0
        public ScriptTriggersPage(ScriptProbe probe)
        {
            Title = "Script Triggers";

            ScriptProbe scriptProbe = probe as ScriptProbe;

            ListView triggerList = new ListView();

            triggerList.ItemTemplate = new DataTemplate(typeof(TextCell));
            triggerList.ItemTemplate.SetBinding(TextCell.TextProperty, new Binding(".", stringFormat: "{0}"));
            triggerList.ItemsSource = scriptProbe.Triggers;

            Content = triggerList;

            ToolbarItems.Add(new ToolbarItem("+", null, async() =>
            {
                if (scriptProbe.Protocol.Probes.Where(p => p != scriptProbe && p.Enabled).Count() > 0)
                {
                    await Navigation.PushAsync(new AddScriptProbeTriggerPage(scriptProbe));
                }
                else
                {
                    UiBoundSensusServiceHelper.Get(true).FlashNotificationAsync("You must enable probes before adding triggers.");
                }
            }));

            ToolbarItems.Add(new ToolbarItem("-", null, async() =>
            {
                if (triggerList.SelectedItem != null && await DisplayAlert("Confirm Delete", "Are you sure you want to delete the selected trigger?", "Yes", "Cancel"))
                {
                    scriptProbe.Triggers.Remove(triggerList.SelectedItem as SensusService.Probes.User.Trigger);
                    triggerList.SelectedItem = null;
                }
            }));
        }
Esempio n. 2
0
        public ScriptRunnersPage(ScriptProbe probe)
        {
            Title = "Scripts";

            ListView scriptRunnersList = new ListView(ListViewCachingStrategy.RecycleElement);

            scriptRunnersList.ItemTemplate = new DataTemplate(typeof(TextCell));
            scriptRunnersList.ItemTemplate.SetBinding(TextCell.TextProperty, nameof(ScriptRunner.Caption));
            scriptRunnersList.ItemsSource = probe.ScriptRunners;
            scriptRunnersList.ItemTapped += async(o, e) =>
            {
                if (scriptRunnersList.SelectedItem == null)
                {
                    return;
                }

                ScriptRunner selectedScriptRunner = scriptRunnersList.SelectedItem as ScriptRunner;

                string selectedAction = await DisplayActionSheet(selectedScriptRunner.Name, "Cancel", null, "Edit", "Copy", "Delete");

                if (selectedAction == "Edit")
                {
                    await Navigation.PushAsync(new ScriptRunnerPage(selectedScriptRunner));
                }
                else if (selectedAction == "Copy")
                {
                    ScriptRunner copy = selectedScriptRunner.Copy();

                    //MakeNameUnique(copy, probe);

                    probe.ScriptRunners.Add(copy);
                }
                else if (selectedAction == "Delete")
                {
                    if (await DisplayAlert("Delete " + selectedScriptRunner.Name + "?", "This action cannot be undone.", "Delete", "Cancel"))
                    {
                        await selectedScriptRunner.StopAsync();

                        selectedScriptRunner.Enabled = false;
                        selectedScriptRunner.Triggers.Clear();

                        probe.ScriptRunners.Remove(selectedScriptRunner);

                        scriptRunnersList.SelectedItem = null;  // reset manually since it's not done automatically
                    }
                }
            };

            ToolbarItems.Add(new ToolbarItem(null, "plus.png", () =>
            {
                probe.ScriptRunners.Add(new ScriptRunner("New Script", probe));
            }));

            Content = scriptRunnersList;
        }
Esempio n. 3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ScriptRunnersPage"/> class.
        /// </summary>
        /// <param name="probe">Probe to display.</param>
        public ScriptRunnersPage(ScriptProbe probe)
        {
            _probe = probe;

            Title = "Scripts";

            _scriptRunnersList = new ListView();
            _scriptRunnersList.ItemTemplate = new DataTemplate(typeof(TextCell));
            _scriptRunnersList.ItemTemplate.SetBinding(TextCell.TextProperty, "Name");
            _scriptRunnersList.ItemTapped += async(o, e) =>
            {
                if (_scriptRunnersList.SelectedItem == null)
                {
                    return;
                }

                ScriptRunner selectedScriptRunner = _scriptRunnersList.SelectedItem as ScriptRunner;

                string selectedAction = await DisplayActionSheet(selectedScriptRunner.Name, "Cancel", null, "Edit", "Delete");

                if (selectedAction == "Edit")
                {
                    ScriptRunnerPage scriptRunnerPage = new ScriptRunnerPage(selectedScriptRunner);
                    scriptRunnerPage.Disappearing += (oo, ee) =>
                    {
                        Bind();
                    };

                    await Navigation.PushAsync(scriptRunnerPage);
                }
                else if (selectedAction == "Delete")
                {
                    if (await DisplayAlert("Delete " + selectedScriptRunner.Name + "?", "This action cannot be undone.", "Delete", "Cancel"))
                    {
                        selectedScriptRunner.Stop();
                        selectedScriptRunner.Enabled = false;
                        selectedScriptRunner.Triggers.Clear();

                        _probe.ScriptRunners.Remove(selectedScriptRunner);
                        _scriptRunnersList.SelectedItem = null;  // reset manually since it's not done automatically
                    }
                }
            };

            ToolbarItems.Add(new ToolbarItem(null, "plus.png", () =>
            {
                _probe.ScriptRunners.Add(new ScriptRunner("New Script", _probe));
            }));

            Bind();
            Content = _scriptRunnersList;
        }
Esempio n. 4
0
        public void MakeNameUnique(ScriptRunner runner, ScriptProbe probe)
        {
            try
            {
                string pattern = @"\s*-\s*Copy\s*(?<number>\d*)$";

                runner.Name = Regex.Replace(runner.Name, pattern, "");

                string countString = probe.ScriptRunners.Max(x => Regex.Match(x.Name, $@"(?<={runner.Name}){pattern}").Groups["number"].Value);

                int.TryParse(countString, out int count);

                count = Math.Max(count, probe.ScriptRunners.Count(x => Regex.IsMatch(x.Name, $@"(?<={runner.Name})({pattern})?$")) - 1);

                runner.Name += $" - Copy {count + 1}";
            }
            catch
            {
                SensusServiceHelper.Get().Logger.Log("Error creating unique script runner name", LoggingLevel.Normal, GetType());
            }
        }
Esempio n. 5
0
        public void ScriptCopyNewIdTest()
        {
            ScriptProbe  probe  = new ScriptProbe();
            ScriptRunner runner = new ScriptRunner("test", probe);
            Script       script = new Script(runner);
            InputGroup   group  = new InputGroup();
            Input        input1 = new SliderInput();
            Input        input2 = new SliderInput();

            group.Inputs.Add(input1);
            group.Inputs.Add(input2);
            script.InputGroups.Add(group);

            Script copy = script.Copy(true);

            Assert.AreSame(script.Runner, copy.Runner);
            Assert.AreNotEqual(script.Id, copy.Id);
            Assert.AreEqual(script.InputGroups.Single().Id, copy.InputGroups.Single().Id);
            Assert.AreEqual(script.InputGroups.Single().Inputs.First().Id, copy.InputGroups.Single().Inputs.First().Id);
            Assert.AreEqual(script.InputGroups.Count, copy.InputGroups.Count);
            Assert.AreEqual(script.InputGroups.Single().Inputs.Count, copy.InputGroups.Single().Inputs.Count);
        }
Esempio n. 6
0
        public ProbePage(Probe probe)
        {
            Title = "Probe";

            StackLayout contentLayout = new StackLayout
            {
                Orientation     = StackOrientation.Vertical,
                VerticalOptions = LayoutOptions.FillAndExpand
            };

            foreach (StackLayout stack in UiProperty.GetPropertyStacks(probe))
            {
                contentLayout.Children.Add(stack);
            }

            #region script probes
            if (probe is ScriptProbe)
            {
                ScriptProbe scriptProbe = probe as ScriptProbe;

                Button editScriptButton = new Button
                {
                    Text              = "Edit Script",
                    FontSize          = 20,
                    HorizontalOptions = LayoutOptions.FillAndExpand
                };

                contentLayout.Children.Add(editScriptButton);

                editScriptButton.Clicked += async(oo, e) =>
                {
                    await Navigation.PushAsync(new ScriptPage(scriptProbe.Script));
                };

                Button viewScriptTriggersButton = new Button
                {
                    Text              = "Edit Triggers",
                    FontSize          = 20,
                    HorizontalOptions = LayoutOptions.FillAndExpand
                };

                contentLayout.Children.Add(viewScriptTriggersButton);

                viewScriptTriggersButton.Clicked += async(o, e) =>
                {
                    await Navigation.PushAsync(new ScriptTriggersPage(scriptProbe));
                };
            }
            #endregion

            #region anonymization
            List <PropertyInfo> anonymizableProperties = probe.DatumType.GetProperties().Where(property => property.GetCustomAttribute <Anonymizable>() != null).ToList();

            if (anonymizableProperties.Count > 0)
            {
                contentLayout.Children.Add(new Label
                {
                    Text              = "Anonymization",
                    FontSize          = 20,
                    FontAttributes    = FontAttributes.Italic,
                    TextColor         = Color.Accent,
                    HorizontalOptions = LayoutOptions.Center
                });

                foreach (PropertyInfo anonymizableProperty in anonymizableProperties)
                {
                    Anonymizable anonymizableAttribute = anonymizableProperty.GetCustomAttribute <Anonymizable>(true);

                    Label propertyLabel = new Label
                    {
                        Text              = (anonymizableAttribute.PropertyDisplayName ?? anonymizableProperty.Name) + ":",
                        FontSize          = 20,
                        HorizontalOptions = LayoutOptions.Start
                    };

                    // populate a picker of anonymizers for the current property
                    Picker anonymizerPicker = new Picker
                    {
                        HorizontalOptions = LayoutOptions.FillAndExpand
                    };

                    anonymizerPicker.Items.Add("None");
                    foreach (Anonymizer anonymizer in anonymizableAttribute.AvailableAnonymizers)
                    {
                        anonymizerPicker.Items.Add(anonymizer.DisplayText);
                    }

                    anonymizerPicker.SelectedIndexChanged += (o, e) =>
                    {
                        Anonymizer selectedAnonymizer = null;
                        if (anonymizerPicker.SelectedIndex > 0)
                        {
                            selectedAnonymizer = anonymizableAttribute.AvailableAnonymizers[anonymizerPicker.SelectedIndex - 1];      // subtract one from the selected index since the JsonAnonymizer's collection of anonymizers start after the "None" option within the picker.
                        }
                        probe.Protocol.JsonAnonymizer.SetAnonymizer(anonymizableProperty, selectedAnonymizer);
                    };

                    // set the picker's index to the current anonymizer (or "None" if there is no current)
                    Anonymizer currentAnonymizer = probe.Protocol.JsonAnonymizer.GetAnonymizer(anonymizableProperty);
                    int        currentIndex      = 0;
                    if (currentAnonymizer != null)
                    {
                        currentIndex = anonymizableAttribute.AvailableAnonymizers.IndexOf(currentAnonymizer) + 1;
                    }

                    anonymizerPicker.SelectedIndex = currentIndex;

                    StackLayout anonymizablePropertyStack = new StackLayout
                    {
                        Orientation       = StackOrientation.Horizontal,
                        HorizontalOptions = LayoutOptions.FillAndExpand,
                        Children          = { propertyLabel, anonymizerPicker }
                    };

                    contentLayout.Children.Add(anonymizablePropertyStack);
                }
            }
            #endregion

            Content = new ScrollView
            {
                Content = contentLayout
            };
        }
Esempio n. 7
0
 public ScriptRunner(string name, ScriptProbe probe) : this()
 {
     Name  = name;
     Probe = probe;
 }
Esempio n. 8
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ProbePage"/> class.
        /// </summary>
        /// <param name="probe">Probe to display.</param>
        public ProbePage(Probe probe)
        {
            Title = "Probe";

            StackLayout contentLayout = new StackLayout
            {
                Orientation     = StackOrientation.Vertical,
                VerticalOptions = LayoutOptions.FillAndExpand
            };

            string type = "";

            if (probe is ListeningProbe)
            {
                type = "Listening";
            }
            else if (probe is PollingProbe)
            {
                type = "Polling";
            }

            contentLayout.Children.Add(new ContentView
            {
                Content = new Label
                {
                    Text              = probe.DisplayName + (type == "" ? "" : " (" + type + ")"),
                    FontSize          = 20,
                    FontAttributes    = FontAttributes.Italic,
                    TextColor         = Color.Accent,
                    HorizontalOptions = LayoutOptions.Center
                },
                Padding = new Thickness(0, 10, 0, 10)
            });

            foreach (StackLayout stack in UiProperty.GetPropertyStacks(probe))
            {
                contentLayout.Children.Add(stack);
            }

            #region script probes
            if (probe is ScriptProbe)
            {
                ScriptProbe scriptProbe = probe as ScriptProbe;

                Button editScriptsButton = new Button
                {
                    Text     = "Edit Scripts",
                    FontSize = 20
                };

                contentLayout.Children.Add(editScriptsButton);

                editScriptsButton.Clicked += async(o, e) =>
                {
                    await Navigation.PushAsync(new ScriptRunnersPage(scriptProbe));
                };

                Button shareScriptButton = new Button
                {
                    Text     = "Share Definition",
                    FontSize = 20
                };

                contentLayout.Children.Add(shareScriptButton);

                shareScriptButton.Clicked += (o, e) =>
                {
                    string sharePath = SensusServiceHelper.Get().GetSharePath(".json");

                    using (StreamWriter shareFile = new StreamWriter(sharePath))
                    {
                        shareFile.WriteLine(JsonConvert.SerializeObject(probe, SensusServiceHelper.JSON_SERIALIZER_SETTINGS));
                    }

                    SensusServiceHelper.Get().ShareFileAsync(sharePath, "Probe Definition", "application/json");
                };
            }
            #endregion

            #region proximity probe
            if (probe is IPointsOfInterestProximityProbe)
            {
                Button editTriggersButton = new Button
                {
                    Text              = "Edit Triggers",
                    FontSize          = 20,
                    HorizontalOptions = LayoutOptions.FillAndExpand
                };

                contentLayout.Children.Add(editTriggersButton);

                editTriggersButton.Clicked += async(o, e) =>
                {
                    await Navigation.PushAsync(new ProximityTriggersPage(probe as IPointsOfInterestProximityProbe));
                };
            }
            #endregion

            #region anonymization
            List <PropertyInfo> anonymizableProperties = probe.DatumType.GetProperties().Where(property => property.GetCustomAttribute <Anonymizable>() != null).ToList();

            if (anonymizableProperties.Count > 0)
            {
                contentLayout.Children.Add(new Label
                {
                    Text              = "Anonymization",
                    FontSize          = 20,
                    FontAttributes    = FontAttributes.Italic,
                    TextColor         = Color.Accent,
                    HorizontalOptions = LayoutOptions.Center
                });

                List <StackLayout> anonymizablePropertyStacks = new List <StackLayout>();

                foreach (PropertyInfo anonymizableProperty in anonymizableProperties)
                {
                    Anonymizable anonymizableAttribute = anonymizableProperty.GetCustomAttribute <Anonymizable>(true);

                    Label propertyLabel = new Label
                    {
                        Text              = anonymizableAttribute.PropertyDisplayName ?? anonymizableProperty.Name + ":",
                        FontSize          = 20,
                        HorizontalOptions = LayoutOptions.Start
                    };

                    // populate a picker of anonymizers for the current property
                    Picker anonymizerPicker = new Picker
                    {
                        Title             = "Select Anonymizer",
                        HorizontalOptions = LayoutOptions.FillAndExpand
                    };

                    anonymizerPicker.Items.Add("Do Not Anonymize");
                    foreach (Anonymizer anonymizer in anonymizableAttribute.AvailableAnonymizers)
                    {
                        anonymizerPicker.Items.Add(anonymizer.DisplayText);
                    }

                    anonymizerPicker.SelectedIndexChanged += (o, e) =>
                    {
                        Anonymizer selectedAnonymizer = null;
                        if (anonymizerPicker.SelectedIndex > 0)
                        {
                            selectedAnonymizer = anonymizableAttribute.AvailableAnonymizers[anonymizerPicker.SelectedIndex - 1];  // subtract one from the selected index since the JsonAnonymizer's collection of anonymizers start after the "None" option within the picker.
                        }
                        probe.Protocol.JsonAnonymizer.SetAnonymizer(anonymizableProperty, selectedAnonymizer);
                    };

                    // set the picker's index to the current anonymizer (or "Do Not Anonymize" if there is no current)
                    Anonymizer currentAnonymizer = probe.Protocol.JsonAnonymizer.GetAnonymizer(anonymizableProperty);
                    int        currentIndex      = 0;
                    if (currentAnonymizer != null)
                    {
                        currentIndex = anonymizableAttribute.AvailableAnonymizers.IndexOf(currentAnonymizer) + 1;
                    }

                    anonymizerPicker.SelectedIndex = currentIndex;

                    StackLayout anonymizablePropertyStack = new StackLayout
                    {
                        Orientation       = StackOrientation.Horizontal,
                        HorizontalOptions = LayoutOptions.FillAndExpand,
                        Children          = { propertyLabel, anonymizerPicker }
                    };

                    anonymizablePropertyStacks.Add(anonymizablePropertyStack);
                }

                foreach (StackLayout anonymizablePropertyStack in anonymizablePropertyStacks.OrderBy(s => (s.Children[0] as Label).Text))
                {
                    contentLayout.Children.Add(anonymizablePropertyStack);
                }
            }
            #endregion

            Content = new ScrollView
            {
                Content = contentLayout
            };
        }
Esempio n. 9
0
        public AddScriptProbeTriggerPage(ScriptProbe scriptProbe)
        {
            _scriptProbe = scriptProbe;

            Title = "Add Trigger";

            List <Probe> enabledProbes = scriptProbe.Protocol.Probes.Where(p => p != _scriptProbe && p.Enabled).ToList();

            if (enabledProbes.Count == 0)
            {
                Content = new Label
                {
                    Text     = "No enabled probes. Please enable them before creating triggers.",
                    FontSize = 20
                };

                return;
            }

            StackLayout contentLayout = new StackLayout
            {
                Orientation     = StackOrientation.Vertical,
                VerticalOptions = LayoutOptions.FillAndExpand
            };

            Label probeLabel = new Label
            {
                Text     = "Probe:",
                FontSize = 20
            };

            Picker probePicker = new Picker {
                Title = "Select Probe", HorizontalOptions = LayoutOptions.FillAndExpand
            };

            foreach (Probe enabledProbe in enabledProbes)
            {
                probePicker.Items.Add(enabledProbe.DisplayName);
            }

            contentLayout.Children.Add(new StackLayout
            {
                Orientation       = StackOrientation.Horizontal,
                HorizontalOptions = LayoutOptions.FillAndExpand,
                Children          = { probeLabel, probePicker }
            });

            StackLayout triggerDefinitionLayout = new StackLayout
            {
                Orientation     = StackOrientation.Vertical,
                VerticalOptions = LayoutOptions.FillAndExpand
            };

            contentLayout.Children.Add(triggerDefinitionLayout);

            Switch     changeSwitch           = new Switch();
            Switch     regexSwitch            = new Switch();
            Switch     fireRepeatedlySwitch   = new Switch();
            Switch     ignoreFirstDatumSwitch = new Switch();
            TimePicker startTimePicker        = new TimePicker {
                HorizontalOptions = LayoutOptions.FillAndExpand
            };
            TimePicker endTimePicker = new TimePicker {
                HorizontalOptions = LayoutOptions.FillAndExpand
            };

            probePicker.SelectedIndexChanged += (o, e) =>
            {
                if (probePicker.SelectedIndex < 0)
                {
                    return;
                }

                _selectedProbe = enabledProbes[probePicker.SelectedIndex];

                triggerDefinitionLayout.Children.Clear();

                #region datum property picker
                Label datumPropertyLabel = new Label
                {
                    Text     = "Property:",
                    FontSize = 20
                };

                Picker datumPropertyPicker = new Picker {
                    Title = "Select Datum Property", HorizontalOptions = LayoutOptions.FillAndExpand
                };
                PropertyInfo[] datumProperties = _selectedProbe.DatumType.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(p => p.GetCustomAttributes <ProbeTriggerProperty>().Count() > 0).ToArray();
                foreach (PropertyInfo triggerProperty in datumProperties)
                {
                    datumPropertyPicker.Items.Add(triggerProperty.Name);
                }

                triggerDefinitionLayout.Children.Add(new StackLayout
                {
                    Orientation       = StackOrientation.Horizontal,
                    HorizontalOptions = LayoutOptions.FillAndExpand,
                    Children          = { datumPropertyLabel, datumPropertyPicker }
                });
                #endregion

                #region condition picker (same for all datum types)
                Label conditionLabel = new Label
                {
                    Text     = "Condition:",
                    FontSize = 20
                };

                Picker conditionPicker = new Picker {
                    Title = "Select Condition", HorizontalOptions = LayoutOptions.FillAndExpand
                };
                TriggerValueCondition[] conditions = Enum.GetValues(typeof(TriggerValueCondition)) as TriggerValueCondition[];
                foreach (TriggerValueCondition condition in conditions)
                {
                    conditionPicker.Items.Add(condition.ToString());
                }

                conditionPicker.SelectedIndexChanged += (oo, ee) =>
                {
                    if (conditionPicker.SelectedIndex < 0)
                    {
                        return;
                    }

                    _selectedCondition = conditions[conditionPicker.SelectedIndex];
                };

                triggerDefinitionLayout.Children.Add(new StackLayout
                {
                    Orientation       = StackOrientation.Horizontal,
                    HorizontalOptions = LayoutOptions.FillAndExpand,
                    Children          = { conditionLabel, conditionPicker }
                });
                #endregion

                #region condition value for comparison, based on selected datum property -- includes change calculation (for double datum) and regex (for string datum)
                StackLayout conditionValueStack = new StackLayout
                {
                    Orientation       = StackOrientation.Vertical,
                    HorizontalOptions = LayoutOptions.FillAndExpand
                };

                triggerDefinitionLayout.Children.Add(conditionValueStack);

                datumPropertyPicker.SelectedIndexChanged += (oo, ee) =>
                {
                    if (datumPropertyPicker.SelectedIndex < 0)
                    {
                        return;
                    }

                    _selectedDatumProperty = datumProperties[datumPropertyPicker.SelectedIndex];

                    conditionValueStack.Children.Clear();

                    ProbeTriggerProperty datumTriggerAttribute = _selectedDatumProperty.GetCustomAttribute <ProbeTriggerProperty>();

                    View conditionValueStackView = null;
                    bool allowChangeCalculation  = false;
                    bool allowRegularExpression  = false;

                    if (datumTriggerAttribute is ListProbeTriggerProperty)
                    {
                        Picker conditionValuePicker = new Picker {
                            Title = "Select Condition Value", HorizontalOptions = LayoutOptions.FillAndExpand
                        };
                        object[] items = (datumTriggerAttribute as ListProbeTriggerProperty).Items;
                        foreach (object item in items)
                        {
                            conditionValuePicker.Items.Add(item.ToString());
                        }

                        conditionValuePicker.SelectedIndexChanged += (ooo, eee) =>
                        {
                            if (conditionValuePicker.SelectedIndex < 0)
                            {
                                return;
                            }

                            _conditionValue = items[conditionValuePicker.SelectedIndex];
                        };

                        conditionValueStackView = conditionValuePicker;
                    }
                    else if (datumTriggerAttribute is NumberProbeTriggerProperty)
                    {
                        Entry entry = new Entry
                        {
                            Keyboard          = Keyboard.Numeric,
                            HorizontalOptions = LayoutOptions.FillAndExpand
                        };

                        entry.TextChanged += (ooo, eee) =>
                        {
                            double value;
                            if (double.TryParse(eee.NewTextValue, out value))
                            {
                                _conditionValue = value;
                            }
                        };

                        conditionValueStackView = entry;
                        allowChangeCalculation  = true;
                    }
                    else if (datumTriggerAttribute is TextProbeTriggerProperty)
                    {
                        Entry entry = new Entry
                        {
                            Keyboard          = Keyboard.Default,
                            HorizontalOptions = LayoutOptions.FillAndExpand
                        };

                        entry.TextChanged += (ooo, eee) => _conditionValue = eee.NewTextValue;

                        conditionValueStackView = entry;
                        allowRegularExpression  = true;
                    }
                    else if (datumTriggerAttribute is BooleanProbeTriggerProperty)
                    {
                        Switch booleanSwitch = new Switch();

                        booleanSwitch.Toggled += (ooo, eee) => _conditionValue = eee.Value;

                        conditionValueStackView = booleanSwitch;
                    }

                    Label conditionValueStackLabel = new Label
                    {
                        Text     = "Value:",
                        FontSize = 20
                    };

                    conditionValueStack.Children.Add(new StackLayout
                    {
                        Orientation       = StackOrientation.Horizontal,
                        HorizontalOptions = LayoutOptions.FillAndExpand,
                        Children          = { conditionValueStackLabel, conditionValueStackView }
                    });

                    #region change calculation
                    if (allowChangeCalculation)
                    {
                        Label changeLabel = new Label
                        {
                            Text     = "Change:",
                            FontSize = 20
                        };

                        changeSwitch.IsToggled = false;

                        conditionValueStack.Children.Add(new StackLayout
                        {
                            Orientation       = StackOrientation.Horizontal,
                            HorizontalOptions = LayoutOptions.FillAndExpand,
                            Children          = { changeLabel, changeSwitch }
                        });
                    }
                    #endregion

                    #region regular expression
                    if (allowRegularExpression)
                    {
                        Label regexLabel = new Label
                        {
                            Text     = "Regular Expression:",
                            FontSize = 20
                        };

                        regexSwitch.IsToggled = false;

                        conditionValueStack.Children.Add(new StackLayout
                        {
                            Orientation       = StackOrientation.Horizontal,
                            HorizontalOptions = LayoutOptions.FillAndExpand,
                            Children          = { regexLabel, regexSwitch }
                        });
                    }
                    #endregion

                    #region fire repeatedly
                    Label fireRepeatedlyLabel = new Label
                    {
                        Text     = "Fire Repeatedly:",
                        FontSize = 20
                    };

                    fireRepeatedlySwitch.IsToggled = false;

                    conditionValueStack.Children.Add(new StackLayout
                    {
                        Orientation       = StackOrientation.Horizontal,
                        HorizontalOptions = LayoutOptions.FillAndExpand,
                        Children          = { fireRepeatedlyLabel, fireRepeatedlySwitch }
                    });
                    #endregion
                };

                datumPropertyPicker.SelectedIndex = 0;
                #endregion

                #region ignore first datum
                Label ignoreFirstDatumLabel = new Label
                {
                    Text     = "Ignore First Datum:",
                    FontSize = 20
                };

                ignoreFirstDatumSwitch.IsToggled = false;

                triggerDefinitionLayout.Children.Add(new StackLayout
                {
                    Orientation       = StackOrientation.Horizontal,
                    HorizontalOptions = LayoutOptions.FillAndExpand,
                    Children          = { ignoreFirstDatumLabel, ignoreFirstDatumSwitch }
                });
                #endregion

                #region start/end times
                Label startTimeLabel = new Label
                {
                    Text     = "Start Time:",
                    FontSize = 20
                };

                startTimePicker.Time = new TimeSpan(8, 0, 0);

                triggerDefinitionLayout.Children.Add(new StackLayout
                {
                    Orientation       = StackOrientation.Horizontal,
                    HorizontalOptions = LayoutOptions.FillAndExpand,
                    Children          = { startTimeLabel, startTimePicker }
                });

                Label endTimeLabel = new Label
                {
                    Text     = "End Time:",
                    FontSize = 20
                };

                endTimePicker.Time = new TimeSpan(21, 0, 0);

                triggerDefinitionLayout.Children.Add(new StackLayout
                {
                    Orientation       = StackOrientation.Horizontal,
                    HorizontalOptions = LayoutOptions.FillAndExpand,
                    Children          = { endTimeLabel, endTimePicker }
                });
                #endregion
            };

            probePicker.SelectedIndex = 0;

            Button okButton = new Button
            {
                Text     = "OK",
                FontSize = 20
            };

            okButton.Clicked += async(o, e) =>
            {
                try
                {
                    _scriptProbe.Triggers.Add(new SensusService.Probes.User.Trigger(_selectedProbe, _selectedDatumProperty.Name, _selectedCondition, _conditionValue, changeSwitch.IsToggled, fireRepeatedlySwitch.IsToggled, regexSwitch.IsToggled, ignoreFirstDatumSwitch.IsToggled, startTimePicker.Time, endTimePicker.Time));
                    await Navigation.PopAsync();
                }
                catch (Exception ex)
                {
                    string message = "Failed to add trigger:  " + ex.Message;
                    UiBoundSensusServiceHelper.Get(true).FlashNotificationAsync(message);
                    UiBoundSensusServiceHelper.Get(true).Logger.Log(message, LoggingLevel.Normal, GetType());
                }
            };

            contentLayout.Children.Add(okButton);

            Content = new ScrollView
            {
                Content = contentLayout
            };
        }
Esempio n. 10
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ProbePage"/> class.
        /// </summary>
        /// <param name="probe">Probe to display.</param>
        public ProbePage(Probe probe)
        {
            Title = "Probe";

            StackLayout contentLayout = new StackLayout
            {
                Orientation     = StackOrientation.Vertical,
                VerticalOptions = LayoutOptions.FillAndExpand
            };

            string type = "";

            if (probe is ListeningProbe)
            {
                type = "Listening";
            }
            else if (probe is PollingProbe)
            {
                type = "Polling";
            }

            contentLayout.Children.Add(new ContentView
            {
                Content = new Label
                {
                    Text              = probe.DisplayName + (type == "" ? "" : " (" + type + ")"),
                    FontSize          = 20,
                    FontAttributes    = FontAttributes.Italic,
                    TextColor         = Color.Accent,
                    HorizontalOptions = LayoutOptions.Center
                },
                Padding = new Thickness(0, 10, 0, 10)
            });

            foreach (StackLayout stack in UiProperty.GetPropertyStacks(probe))
            {
                contentLayout.Children.Add(stack);
            }

            #region script probes
            if (probe is ScriptProbe)
            {
                ScriptProbe scriptProbe = probe as ScriptProbe;

                Button editScriptsButton = new Button
                {
                    Text     = "Edit Scripts",
                    FontSize = 20
                };

                contentLayout.Children.Add(editScriptsButton);

                editScriptsButton.Clicked += async(o, e) =>
                {
                    await Navigation.PushAsync(new ScriptRunnersPage(scriptProbe));
                };

                Button shareScriptButton = new Button
                {
                    Text     = "Share Definition",
                    FontSize = 20
                };

                contentLayout.Children.Add(shareScriptButton);

                shareScriptButton.Clicked += async(o, e) =>
                {
                    string sharePath = SensusServiceHelper.Get().GetSharePath(".json");

                    using (StreamWriter shareFile = new StreamWriter(sharePath))
                    {
                        shareFile.WriteLine(JsonConvert.SerializeObject(probe, SensusServiceHelper.JSON_SERIALIZER_SETTINGS));
                    }

                    await SensusServiceHelper.Get().ShareFileAsync(sharePath, "Probe Definition", "application/json");
                };

                Button setAgentButton = new Button
                {
                    Text              = "Set Agent" + (scriptProbe.Agent == null ? "" : ":  " + scriptProbe.Agent.Id),
                    FontSize          = 20,
                    HorizontalOptions = LayoutOptions.FillAndExpand
                };

                setAgentButton.Clicked += async(sender, e) =>
                {
                    await SetAgentButton_Clicked(setAgentButton, scriptProbe);
                };

                contentLayout.Children.Add(setAgentButton);

                Button clearAgentButton = new Button
                {
                    Text              = "Clear Agent",
                    FontSize          = 20,
                    HorizontalOptions = LayoutOptions.FillAndExpand
                };

                clearAgentButton.Clicked += async(sender, e) =>
                {
                    if (scriptProbe.Agent != null)
                    {
                        if (await DisplayAlert("Confirm", "Are you sure you wish to clear the survey agent?", "Yes", "No"))
                        {
                            scriptProbe.Agent   = null;
                            setAgentButton.Text = "Set Agent";
                        }
                    }

                    await SensusServiceHelper.Get().FlashNotificationAsync("Survey agent cleared.");
                };

                contentLayout.Children.Add(clearAgentButton);
            }
            #endregion

            #region proximity probe
            if (probe is IPointsOfInterestProximityProbe)
            {
                Button editTriggersButton = new Button
                {
                    Text              = "Edit Triggers",
                    FontSize          = 20,
                    HorizontalOptions = LayoutOptions.FillAndExpand
                };

                contentLayout.Children.Add(editTriggersButton);

                editTriggersButton.Clicked += async(o, e) =>
                {
                    await Navigation.PushAsync(new ProximityTriggersPage(probe as IPointsOfInterestProximityProbe));
                };
            }
            #endregion

            #region estimote probe
            if (probe is EstimoteBeaconProbe)
            {
                EstimoteBeaconProbe estimoteBeaconProbe = probe as EstimoteBeaconProbe;

                Button editBeaconsButton = new Button
                {
                    Text              = "Edit Beacons",
                    FontSize          = 20,
                    HorizontalOptions = LayoutOptions.FillAndExpand
                };

                contentLayout.Children.Add(editBeaconsButton);

                editBeaconsButton.Clicked += async(sender, e) =>
                {
                    await Navigation.PushAsync(new EstimoteBeaconProbeBeaconsPage(estimoteBeaconProbe));
                };

                Button setLocationButton = new Button
                {
                    Text              = estimoteBeaconProbe.Location == null ? "Set Location" : "Location:  " + estimoteBeaconProbe.Location,
                    FontSize          = 20,
                    HorizontalOptions = LayoutOptions.FillAndExpand
                };

                contentLayout.Children.Add(setLocationButton);

                setLocationButton.Clicked += async(sender, e) =>
                {
                    List <EstimoteLocation> locations;
                    try
                    {
                        locations = await estimoteBeaconProbe.GetLocationsFromCloudAsync(TimeSpan.FromSeconds(10));

                        if (locations.Count == 0)
                        {
                            throw new Exception("No locations present within Estimote Cloud.");
                        }
                    }
                    catch (Exception ex)
                    {
                        await SensusServiceHelper.Get().FlashNotificationAsync("Failed to set location:  " + ex.Message);

                        return;
                    }

                    List <Input> inputs = await SensusServiceHelper.Get().PromptForInputsAsync("Set Location", new Input[]
                    {
                        new ItemPickerDialogInput("Location:", null, locations.Select(location => location.Name + " (" + location.Identifier + ")").ToList())
                        {
                            AllowClearSelection = true
                        }
                    }, null, true, null, null, null, null, false);

                    if (inputs == null || inputs[0]?.Value == null)
                    {
                        estimoteBeaconProbe.Location = null;
                        await SensusServiceHelper.Get().FlashNotificationAsync("Location cleared.");

                        setLocationButton.Text = "Set Location";
                    }
                    else
                    {
                        try
                        {
                            string locationIdentifier = inputs[0].Value.ToString().Split(new char[] { '(', ')' }, StringSplitOptions.RemoveEmptyEntries)[1];
                            estimoteBeaconProbe.Location = locations.Single(location => location.Identifier == locationIdentifier);
                            setLocationButton.Text       = "Location:  " + estimoteBeaconProbe.Location;
                        }
                        catch (Exception)
                        {
                            await SensusServiceHelper.Get().FlashNotificationAsync("Failed to set location.");
                        }
                    }
                };
            }
            #endregion

            #region anonymization
            List <PropertyInfo> anonymizableProperties = probe.DatumType.GetProperties().Where(property => property.GetCustomAttribute <Anonymizable>() != null).ToList();

            if (anonymizableProperties.Count > 0)
            {
                contentLayout.Children.Add(new Label
                {
                    Text              = "Anonymization",
                    FontSize          = 20,
                    FontAttributes    = FontAttributes.Italic,
                    TextColor         = Color.Accent,
                    HorizontalOptions = LayoutOptions.Center
                });

                List <StackLayout> anonymizablePropertyStacks = new List <StackLayout>();

                foreach (PropertyInfo anonymizableProperty in anonymizableProperties)
                {
                    Anonymizable anonymizableAttribute = anonymizableProperty.GetCustomAttribute <Anonymizable>(true);

                    Label propertyLabel = new Label
                    {
                        Text                  = anonymizableAttribute.PropertyDisplayName ?? anonymizableProperty.Name + ":",
                        FontSize              = 20,
                        HorizontalOptions     = LayoutOptions.Start,
                        VerticalTextAlignment = TextAlignment.Center
                    };

                    // populate a picker of anonymizers for the current property
                    Picker anonymizerPicker = new Picker
                    {
                        Title             = "Select Anonymizer",
                        HorizontalOptions = LayoutOptions.FillAndExpand
                    };

                    Button configureButton = new Button
                    {
                        Text     = "Settings",
                        FontSize = 20
                    };

                    // get the current anonymizer for this property
                    Anonymizer currentAnonymizer = probe.Protocol.JsonAnonymizer.GetAnonymizer(anonymizableProperty);

                    for (int index = 0; index < anonymizableAttribute.AvailableAnonymizers.Count; index++)
                    {
                        if (currentAnonymizer != null && anonymizableAttribute.AvailableAnonymizers[index].GetType() == currentAnonymizer.GetType())
                        {
                            anonymizableAttribute.AvailableAnonymizers[index] = currentAnonymizer;
                        }
                    }

                    anonymizerPicker.Items.Add("Do Not Anonymize");
                    foreach (Anonymizer anonymizer in anonymizableAttribute.AvailableAnonymizers)
                    {
                        anonymizerPicker.Items.Add(anonymizer.DisplayText);
                    }

                    anonymizerPicker.SelectedIndexChanged += (o, e) =>
                    {
                        Anonymizer selectedAnonymizer = null;
                        if (anonymizerPicker.SelectedIndex > 0)
                        {
                            selectedAnonymizer = anonymizableAttribute.AvailableAnonymizers[anonymizerPicker.SelectedIndex - 1];  // subtract one from the selected index since the JsonAnonymizer's collection of anonymizers start after the "None" option within the picker.

                            configureButton.IsVisible = UiProperty.HasUiProperties(selectedAnonymizer);
                        }
                        else
                        {
                            configureButton.IsVisible = false;
                        }

                        probe.Protocol.JsonAnonymizer.SetAnonymizer(anonymizableProperty, selectedAnonymizer);
                    };

                    configureButton.Clicked += async(o, e) =>
                    {
                        Anonymizer selectedAnonymizer = anonymizableAttribute.AvailableAnonymizers[anonymizerPicker.SelectedIndex - 1];

                        await ShowAnonymizerSettings(selectedAnonymizer, anonymizerPicker);
                    };

                    // set the picker's index to the current anonymizer (or "Do Not Anonymize" if there is no current)
                    //Anonymizer currentAnonymizer = probe.Protocol.JsonAnonymizer.GetAnonymizer(anonymizableProperty);
                    int currentIndex = 0;
                    if (currentAnonymizer != null)
                    {
                        currentIndex = anonymizableAttribute.AvailableAnonymizers.IndexOf(currentAnonymizer) + 1;
                    }

                    anonymizerPicker.SelectedIndex = currentIndex;

                    StackLayout anonymizablePropertyStack = new StackLayout
                    {
                        Orientation       = StackOrientation.Horizontal,
                        HorizontalOptions = LayoutOptions.FillAndExpand,
                        Children          = { propertyLabel, anonymizerPicker, configureButton }
                    };

                    anonymizablePropertyStacks.Add(anonymizablePropertyStack);
                }

                foreach (StackLayout anonymizablePropertyStack in anonymizablePropertyStacks.OrderBy(s => (s.Children[0] as Label).Text))
                {
                    contentLayout.Children.Add(anonymizablePropertyStack);
                }
            }
            #endregion

            Content = new ScrollView
            {
                Content = contentLayout
            };
        }
Esempio n. 11
0
        private async Task SetAgentButton_Clicked(Button setAgentButton, ScriptProbe scriptProbe)
        {
            List <Input> agentSelectionInputs = new List <Input>();

            // show any existing agents
            List <IScriptProbeAgent> currentAgents = null;

            // android allows us to dynamically load code assemblies, but iOS does not. so, the current approach
            // is to only support dynamic loading on android and force compile-time assembly inclusion on ios.
#if __ANDROID__
            // try to extract agents from a previously loaded assembly
            try
            {
                currentAgents = ScriptProbe.GetAgents(scriptProbe.AgentAssemblyBytes);
            }
            catch (Exception)
            { }
#elif __IOS__
            currentAgents = ScriptProbe.GetAgents();

            // display warning message, as there is no other option to load agents.
            if (currentAgents.Count == 0)
            {
                await SensusServiceHelper.Get().FlashNotificationAsync("No agents available.");

                return;
            }
#endif

            // let the user pick from currently available agents
            ItemPickerPageInput currentAgentsPicker = null;
            if (currentAgents != null && currentAgents.Count > 0)
            {
                currentAgentsPicker = new ItemPickerPageInput("Available agent" + (currentAgents.Count > 1 ? "s" : "") + ":", currentAgents.Cast <object>().ToList())
                {
                    Required = false
                };

                agentSelectionInputs.Add(currentAgentsPicker);
            }

#if __ANDROID__
            // add option to scan qr code to import a new assembly
            QrCodeInput agentAssemblyUrlQrCodeInput = new QrCodeInput(QrCodePrefix.SURVEY_AGENT, "URL:", false, "Agent URL:")
            {
                Required = false
            };

            agentSelectionInputs.Add(agentAssemblyUrlQrCodeInput);
#endif

            List <Input> completedInputs = await SensusServiceHelper.Get().PromptForInputsAsync("Survey Agent", agentSelectionInputs, null, true, "Set", null, null, null, false);

            if (completedInputs == null)
            {
                return;
            }

            // check for QR code on android. this doesn't exist on ios.
            string agentURL = null;

#if __ANDROID__
            agentURL = agentAssemblyUrlQrCodeInput.Value?.ToString();
#endif

            // if there is no URL, check if the user has selected an agent.
            if (string.IsNullOrWhiteSpace(agentURL))
            {
                if (currentAgentsPicker != null)
                {
                    IScriptProbeAgent selectedAgent = (currentAgentsPicker.Value as List <object>).FirstOrDefault() as IScriptProbeAgent;

                    // set the selected agent, watching out for a null (clearing) selection that needs to be confirmed
                    if (selectedAgent != null || await DisplayAlert("Confirm", "Are you sure you wish to clear the survey agent?", "Yes", "No"))
                    {
                        scriptProbe.Agent = selectedAgent;

                        setAgentButton.Text = "Set Agent" + (scriptProbe.Agent == null ? "" : ":  " + scriptProbe.Agent.Id);

                        if (scriptProbe.Agent == null)
                        {
                            await SensusServiceHelper.Get().FlashNotificationAsync("Survey agent cleared.");
                        }
                    }
                }
            }
#if __ANDROID__
            else
            {
                // download agent assembly from scanned QR code
                byte[] downloadedBytes      = null;
                string downloadErrorMessage = null;
                try
                {
                    // download the assembly and extract agents
                    downloadedBytes = scriptProbe.AgentAssemblyBytes = await new WebClient().DownloadDataTaskAsync(new Uri(agentURL));
                    List <IScriptProbeAgent> qrCodeAgents = ScriptProbe.GetAgents(downloadedBytes);

                    if (qrCodeAgents.Count == 0)
                    {
                        throw new Exception("No agents were present in the specified file.");
                    }
                }
                catch (Exception ex)
                {
                    downloadErrorMessage = ex.Message;
                }

                // if error message is null, then we have 1 or more agents in the downloaded assembly.
                if (downloadErrorMessage == null)
                {
                    // redisplay the current input prompt including the agents we just downloaded
                    scriptProbe.AgentAssemblyBytes = downloadedBytes;
                    await SetAgentButton_Clicked(setAgentButton, scriptProbe);
                }
                else
                {
                    SensusServiceHelper.Get().Logger.Log(downloadErrorMessage, LoggingLevel.Normal, typeof(Protocol));
                    await SensusServiceHelper.Get().FlashNotificationAsync(downloadErrorMessage);
                }
            }
#endif
        }