/// <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 }; }