Example #1
0
        public void Run(IBackgroundTaskInstance taskInstance)
        {
            StorageFolder localFolder = ApplicationData.Current.LocalFolder;

            this.logging.LogEvent("Application starting");

            // Log the Application build, OS version information etc.
            LoggingFields startupInformation = new LoggingFields();

            startupInformation.AddString("Timezone", TimeZoneSettings.CurrentTimeZoneDisplayName);
            startupInformation.AddString("OSVersion", Environment.OSVersion.VersionString);
            startupInformation.AddString("MachineName", Environment.MachineName);

            // This is from the application manifest
            Package        package   = Package.Current;
            PackageId      packageId = package.Id;
            PackageVersion version   = packageId.Version;

            startupInformation.AddString("ApplicationVersion", string.Format($"{version.Major}.{version.Minor}.{version.Build}.{version.Revision}"));

            try
            {
                // see if the configuration file is present if not copy minimal sample one from application directory
                if (localFolder.TryGetItemAsync(ConfigurationFilename).AsTask().Result == null)
                {
                    StorageFile templateConfigurationfile = Package.Current.InstalledLocation.GetFileAsync(ConfigurationFilename).AsTask().Result;
                    templateConfigurationfile.CopyAsync(localFolder, ConfigurationFilename).AsTask();
                }

                IConfiguration configuration = new ConfigurationBuilder().AddJsonFile(Path.Combine(localFolder.Path, ConfigurationFilename), false, true).Build();

                this.azureCognitiveServicesEndpoint = configuration.GetSection("AzureCognitiveServicesEndpoint").Value;
                startupInformation.AddString("AzureCognitiveServicesEndpoint", this.azureCognitiveServicesEndpoint);

                this.azureCognitiveServicesSubscriptionKey = configuration.GetSection("AzureCognitiveServicesSubscriptionKey").Value;
                startupInformation.AddString("AzureCognitiveServicesSubscriptionKey", this.azureCognitiveServicesSubscriptionKey);

                this.projectId = Guid.Parse(configuration.GetSection("ProjectID").Value);
                startupInformation.AddGuid("ProjectID", this.projectId);

                this.publishedName = configuration.GetSection("PublishedName").Value;
                startupInformation.AddString("PublishedName", this.publishedName);

                this.interruptPinNumber = int.Parse(configuration.GetSection("InterruptPinNumber").Value);
                startupInformation.AddInt32("Interrupt pin", this.interruptPinNumber);

                this.interruptTriggerOn = (GpioPinEdge)Enum.Parse(typeof(GpioPinEdge), configuration.GetSection("interruptTriggerOn").Value);
                startupInformation.AddString("Interrupt Trigger on", this.interruptTriggerOn.ToString());

                this.displayPinNumber = int.Parse(configuration.GetSection("DisplayPinNumber").Value);
                startupInformation.AddInt32("Display pin", this.interruptPinNumber);

                this.debounceTimeout = TimeSpan.Parse(configuration.GetSection("debounceTimeout").Value);
                startupInformation.AddTimeSpan("Debounce timeout", this.debounceTimeout);
            }
            catch (Exception ex)
            {
                this.logging.LogMessage("JSON configuration file load or settings retrieval failed " + ex.Message, LoggingLevel.Error);
                return;
            }

            try
            {
                this.customVisionClient = new CustomVisionPredictionClient(new System.Net.Http.DelegatingHandler[] { })
                {
                    ApiKey   = this.azureCognitiveServicesSubscriptionKey,
                    Endpoint = this.azureCognitiveServicesEndpoint,
                };
            }
            catch (Exception ex)
            {
                this.logging.LogMessage("Azure Cognitive Services Custom Vision Client configuration failed " + ex.Message, LoggingLevel.Error);
                return;
            }

            try
            {
                this.mediaCapture = new MediaCapture();
                this.mediaCapture.InitializeAsync().AsTask().Wait();
            }
            catch (Exception ex)
            {
                this.logging.LogMessage("Camera configuration failed " + ex.Message, LoggingLevel.Error);
                return;
            }

            this.displayOffTimer = new Timer(this.TimerCallback, null, Timeout.Infinite, Timeout.Infinite);

            try
            {
                GpioController gpioController = GpioController.GetDefault();
                this.interruptGpioPin = gpioController.OpenPin(this.interruptPinNumber);
                this.interruptGpioPin.SetDriveMode(GpioPinDriveMode.InputPullUp);
                this.interruptGpioPin.ValueChanged += this.InterruptGpioPin_ValueChanged;

                this.displayGpioPin = gpioController.OpenPin(this.displayPinNumber);
                this.displayGpioPin.SetDriveMode(GpioPinDriveMode.Output);
                this.displayGpioPin.Write(GpioPinValue.Low);
            }
            catch (Exception ex)
            {
                this.logging.LogMessage("Digital input configuration failed " + ex.Message, LoggingLevel.Error);
                return;
            }

            this.logging.LogEvent("Application started", startupInformation);

            // enable task to continue running in background
            this.backgroundTaskDeferral = taskInstance.GetDeferral();
        }
Example #2
0
        private async void InterruptGpioPin_ValueChanged(GpioPin sender, GpioPinValueChangedEventArgs args)
        {
            DateTime currentTime = DateTime.UtcNow;

            Debug.WriteLine($"Digital Input Interrupt {sender.PinNumber} triggered {args.Edge}");

            if (args.Edge != this.interruptTriggerOn)
            {
                return;
            }

            // Check that enough time has passed for picture to be taken
            if ((currentTime - this.imageLastCapturedAtUtc) < this.debounceTimeout)
            {
                this.displayGpioPin.Write(GpioPinValue.High);
                this.displayOffTimer.Change(this.timerPeriodDetectIlluminated, this.timerPeriodInfinite);
                return;
            }

            this.imageLastCapturedAtUtc = currentTime;

            // Just incase - stop code being called while photo already in progress
            if (this.cameraBusy)
            {
                this.displayGpioPin.Write(GpioPinValue.High);
                this.displayOffTimer.Change(this.timerPeriodDetectIlluminated, this.timerPeriodInfinite);
                return;
            }

            this.cameraBusy = true;

            try
            {
                using (Windows.Storage.Streams.InMemoryRandomAccessStream captureStream = new Windows.Storage.Streams.InMemoryRandomAccessStream())
                {
                    this.mediaCapture.CapturePhotoToStreamAsync(ImageEncodingProperties.CreateJpeg(), captureStream).AsTask().Wait();
                    captureStream.FlushAsync().AsTask().Wait();
                    captureStream.Seek(0);

                    IStorageFile photoFile = await KnownFolders.PicturesLibrary.CreateFileAsync(ImageFilename, CreationCollisionOption.ReplaceExisting);

                    ImageEncodingProperties imageProperties = ImageEncodingProperties.CreateJpeg();
                    await this.mediaCapture.CapturePhotoToStorageFileAsync(imageProperties, photoFile);

                    IList <FaceAttributeType> returnfaceAttributes = new List <FaceAttributeType>();

                    returnfaceAttributes.Add(FaceAttributeType.Gender);
                    returnfaceAttributes.Add(FaceAttributeType.Age);

                    IList <DetectedFace> detectedFaces = await this.faceClient.Face.DetectWithStreamAsync(captureStream.AsStreamForRead(), returnFaceAttributes : returnfaceAttributes);

                    Debug.WriteLine($"Count {detectedFaces.Count}");

                    if (detectedFaces.Count > 0)
                    {
                        this.displayGpioPin.Write(GpioPinValue.High);

                        // Start the timer to turn the LED off
                        this.displayOffTimer.Change(this.timerPeriodFaceIlluminated, this.timerPeriodInfinite);
                    }

                    LoggingFields imageInformation = new LoggingFields();

                    imageInformation.AddDateTime("TakenAtUTC", currentTime);
                    imageInformation.AddInt32("Pin", sender.PinNumber);
                    imageInformation.AddInt32("Faces", detectedFaces.Count);
                    foreach (DetectedFace detectedFace in detectedFaces)
                    {
                        Debug.WriteLine("Face");
                        if (detectedFace.FaceId.HasValue)
                        {
                            imageInformation.AddGuid("FaceId", detectedFace.FaceId.Value);
                            Debug.WriteLine($" Id:{detectedFace.FaceId.Value}");
                        }

                        imageInformation.AddInt32("Left", detectedFace.FaceRectangle.Left);
                        imageInformation.AddInt32("Width", detectedFace.FaceRectangle.Width);
                        imageInformation.AddInt32("Top", detectedFace.FaceRectangle.Top);
                        imageInformation.AddInt32("Height", detectedFace.FaceRectangle.Height);
                        Debug.WriteLine($" L:{detectedFace.FaceRectangle.Left} W:{detectedFace.FaceRectangle.Width} T:{detectedFace.FaceRectangle.Top} H:{detectedFace.FaceRectangle.Height}");
                        if (detectedFace.FaceAttributes != null)
                        {
                            if (detectedFace.FaceAttributes.Gender.HasValue)
                            {
                                imageInformation.AddString("Gender", detectedFace.FaceAttributes.Gender.Value.ToString());
                                Debug.WriteLine($" Gender:{detectedFace.FaceAttributes.Gender.ToString()}");
                            }

                            if (detectedFace.FaceAttributes.Age.HasValue)
                            {
                                imageInformation.AddDouble("Age", detectedFace.FaceAttributes.Age.Value);
                                Debug.WriteLine($" Age:{detectedFace.FaceAttributes.Age.Value.ToString("F1")}");
                            }
                        }
                    }

                    this.logging.LogEvent("Captured image processed by Cognitive Services", imageInformation);
                }
            }
            catch (Exception ex)
            {
                this.logging.LogMessage("Camera photo or save failed " + ex.Message, LoggingLevel.Error);
            }
            finally
            {
                this.cameraBusy = false;
            }
        }
        public void Run(IBackgroundTaskInstance taskInstance)
        {
            StorageFolder localFolder = ApplicationData.Current.LocalFolder;
            TimeSpan      imageUpdateDue;
            TimeSpan      imageUpdatePeriod;

            this.logging.LogEvent("Application starting");

            // Log the Application build, OS version information etc.
            LoggingFields startupInformation = new LoggingFields();

            startupInformation.AddString("Timezone", TimeZoneSettings.CurrentTimeZoneDisplayName);
            startupInformation.AddString("OSVersion", Environment.OSVersion.VersionString);
            startupInformation.AddString("MachineName", Environment.MachineName);

            // This is from the application manifest
            Package        package   = Package.Current;
            PackageId      packageId = package.Id;
            PackageVersion version   = packageId.Version;

            startupInformation.AddString("ApplicationVersion", string.Format($"{version.Major}.{version.Minor}.{version.Build}.{version.Revision}"));

            try
            {
                // see if the configuration file is present if not copy minimal sample one from application directory
                if (localFolder.TryGetItemAsync(ConfigurationFilename).AsTask().Result == null)
                {
                    StorageFile templateConfigurationfile = Package.Current.InstalledLocation.GetFileAsync(ConfigurationFilename).AsTask().Result;
                    templateConfigurationfile.CopyAsync(localFolder, ConfigurationFilename).AsTask();
                }

                IConfiguration configuration = new ConfigurationBuilder().AddJsonFile(Path.Combine(localFolder.Path, ConfigurationFilename), false, true).Build();

                this.interruptPinNumber = int.Parse(configuration.GetSection("InterruptPinNumber").Value);
                startupInformation.AddInt32("Interrupt pin", this.interruptPinNumber);

                this.interruptTriggerOn = (GpioPinEdge)Enum.Parse(typeof(GpioPinEdge), configuration.GetSection("interruptTriggerOn").Value);
                startupInformation.AddString("Interrupt Trigger on", this.interruptTriggerOn.ToString());

                this.displayPinNumber = int.Parse(configuration.GetSection("DisplayPinNumber").Value);
                startupInformation.AddInt32("Display pin", this.interruptPinNumber);

                this.azureIoTHubConnectionString = configuration.GetSection("AzureIoTHubConnectionString").Value;
                startupInformation.AddString("AzureIoTHubConnectionString", this.azureIoTHubConnectionString);

                this.transportType = (TransportType)Enum.Parse(typeof(TransportType), configuration.GetSection("TransportType").Value);
                startupInformation.AddString("TransportType", this.transportType.ToString());
            }
            catch (Exception ex)
            {
                this.logging.LogMessage("JSON configuration file load or settings retrieval failed " + ex.Message, LoggingLevel.Error);
                return;
            }

            #region AzureIoT Hub connection string creation
            try
            {
                this.azureIoTHubClient = DeviceClient.CreateFromConnectionString(this.azureIoTHubConnectionString, this.transportType);
            }
            catch (Exception ex)
            {
                this.logging.LogMessage("AzureIOT Hub DeviceClient.CreateFromConnectionString failed " + ex.Message, LoggingLevel.Error);
                return;
            }
            #endregion

            #region Report device and application properties to AzureIoT Hub
            try
            {
                TwinCollection reportedProperties = new TwinCollection();

                // This is from the OS
                reportedProperties["Timezone"]    = TimeZoneSettings.CurrentTimeZoneDisplayName;
                reportedProperties["OSVersion"]   = Environment.OSVersion.VersionString;
                reportedProperties["MachineName"] = Environment.MachineName;

                reportedProperties["ApplicationDisplayName"] = package.DisplayName;
                reportedProperties["ApplicationName"]        = packageId.Name;
                reportedProperties["ApplicationVersion"]     = string.Format($"{version.Major}.{version.Minor}.{version.Build}.{version.Revision}");

                // Unique identifier from the hardware
                SystemIdentificationInfo systemIdentificationInfo = SystemIdentification.GetSystemIdForPublisher();
                using (DataReader reader = DataReader.FromBuffer(systemIdentificationInfo.Id))
                {
                    byte[] bytes = new byte[systemIdentificationInfo.Id.Length];
                    reader.ReadBytes(bytes);
                    reportedProperties["SystemId"] = BitConverter.ToString(bytes);
                }

                this.azureIoTHubClient.UpdateReportedPropertiesAsync(reportedProperties).Wait();
            }
            catch (Exception ex)
            {
                this.logging.LogMessage("Azure IoT Hub client UpdateReportedPropertiesAsync failed " + ex.Message, LoggingLevel.Error);
                return;
            }
            #endregion

            #region Retrieve device twin settings
            try
            {
                LoggingFields configurationInformation = new LoggingFields();

                Twin deviceTwin = this.azureIoTHubClient.GetTwinAsync().GetAwaiter().GetResult();

                if (!deviceTwin.Properties.Desired.Contains("ImageUpdateDue") || !TimeSpan.TryParse(deviceTwin.Properties.Desired["ImageUpdateDue"].value.ToString(), out imageUpdateDue))
                {
                    this.logging.LogMessage("DeviceTwin.Properties ImageUpdateDue setting missing or invalid format", LoggingLevel.Warning);
                    return;
                }
                configurationInformation.AddTimeSpan("ImageUpdateDue", imageUpdateDue);

                if (!deviceTwin.Properties.Desired.Contains("ImageUpdatePeriod") || !TimeSpan.TryParse(deviceTwin.Properties.Desired["ImageUpdatePeriod"].value.ToString(), out imageUpdatePeriod))
                {
                    this.logging.LogMessage("DeviceTwin.Properties ImageUpdatePeriod setting missing or invalid format", LoggingLevel.Warning);
                    return;
                }
                configurationInformation.AddTimeSpan("ImageUpdatePeriod", imageUpdatePeriod);

                if (!deviceTwin.Properties.Desired.Contains("ModelType") || (!Enum.TryParse(deviceTwin.Properties.Desired["ModelType"].value.ToString(), out modelType)))
                {
                    this.logging.LogMessage("DeviceTwin.Properties ModelType setting missing or invalid format", LoggingLevel.Warning);
                    return;
                }
                configurationInformation.AddString("ModelType", modelType.ToString());

                if (!deviceTwin.Properties.Desired.Contains("ModelPublishedName") || (string.IsNullOrWhiteSpace(deviceTwin.Properties.Desired["ModelPublishedName"].value.ToString())))
                {
                    this.logging.LogMessage("DeviceTwin.Properties ModelPublishedName setting missing or invalid format", LoggingLevel.Warning);
                    return;
                }
                modelPublishedName = deviceTwin.Properties.Desired["ModelPublishedName"].value.ToString();
                configurationInformation.AddString("ModelPublishedName", modelPublishedName);

                if (!deviceTwin.Properties.Desired.Contains("ProjectID") || (!Guid.TryParse(deviceTwin.Properties.Desired["ProjectID"].value.ToString(), out projectId)))
                {
                    this.logging.LogMessage("DeviceTwin.Properties ProjectId setting missing or invalid format", LoggingLevel.Warning);
                    return;
                }
                configurationInformation.AddGuid("ProjectID", projectId);

                if (!deviceTwin.Properties.Desired.Contains("ProbabilityThreshold") || (!Double.TryParse(deviceTwin.Properties.Desired["ProbabilityThreshold"].value.ToString(), out probabilityThreshold)))
                {
                    this.logging.LogMessage("DeviceTwin.Properties ProbabilityThreshold setting missing or invalid format", LoggingLevel.Warning);
                    return;
                }
                configurationInformation.AddDouble("ProbabilityThreshold", probabilityThreshold);

                if (!deviceTwin.Properties.Desired.Contains("AzureCognitiveServicesEndpoint") || (string.IsNullOrWhiteSpace(deviceTwin.Properties.Desired["AzureCognitiveServicesEndpoint"].value.ToString())))
                {
                    this.logging.LogMessage("DeviceTwin.Properties AzureCognitiveServicesEndpoint setting missing or invalid format", LoggingLevel.Warning);
                    return;
                }
                azureCognitiveServicesEndpoint = deviceTwin.Properties.Desired["AzureCognitiveServicesEndpoint"].value.ToString();
                configurationInformation.AddString("AzureCognitiveServicesEndpoint", modelPublishedName);

                if (!deviceTwin.Properties.Desired.Contains("AzureCognitiveServicesSubscriptionKey") || (string.IsNullOrWhiteSpace(deviceTwin.Properties.Desired["AzureCognitiveServicesSubscriptionKey"].value.ToString())))
                {
                    this.logging.LogMessage("DeviceTwin.Properties AzureCognitiveServicesSubscriptionKey setting missing or invalid format", LoggingLevel.Warning);
                    return;
                }
                azureCognitiveServicesSubscriptionKey = deviceTwin.Properties.Desired["AzureCognitiveServicesSubscriptionKey"].value.ToString();
                configurationInformation.AddString("AzureCognitiveServicesSubscriptionKey", azureCognitiveServicesSubscriptionKey);

                if (!deviceTwin.Properties.Desired.Contains("DebounceTimeout") || !TimeSpan.TryParse(deviceTwin.Properties.Desired["DebounceTimeout"].value.ToString(), out debounceTimeout))
                {
                    this.logging.LogMessage("DeviceTwin.Properties DebounceTimeout setting missing or invalid format", LoggingLevel.Warning);
                    return;
                }
                configurationInformation.AddTimeSpan("DebounceTimeout", debounceTimeout);

                this.logging.LogEvent("Configuration settings", configurationInformation);
            }
            catch (Exception ex)
            {
                this.logging.LogMessage("Azure IoT Hub client GetTwinAsync failed or property missing/invalid" + ex.Message, LoggingLevel.Error);
                return;
            }
            #endregion

            try
            {
                this.customVisionClient = new CustomVisionPredictionClient(new System.Net.Http.DelegatingHandler[] { })
                {
                    ApiKey   = this.azureCognitiveServicesSubscriptionKey,
                    Endpoint = this.azureCognitiveServicesEndpoint,
                };
            }
            catch (Exception ex)
            {
                this.logging.LogMessage("Azure Cognitive Services Custom Vision Client configuration failed " + ex.Message, LoggingLevel.Error);
                return;
            }

            try
            {
                this.mediaCapture = new MediaCapture();
                this.mediaCapture.InitializeAsync().AsTask().Wait();
            }
            catch (Exception ex)
            {
                this.logging.LogMessage("Camera configuration failed " + ex.Message, LoggingLevel.Error);
                return;
            }

            this.displayOffTimer = new Timer(this.TimerCallback, null, Timeout.Infinite, Timeout.Infinite);

            #region Wire up interupt handler for image capture request
            if (this.interruptPinNumber != 0)
            {
                try
                {
                    GpioController gpioController = GpioController.GetDefault();
                    this.interruptGpioPin = gpioController.OpenPin(this.interruptPinNumber);
                    this.interruptGpioPin.SetDriveMode(GpioPinDriveMode.InputPullUp);
                    this.interruptGpioPin.ValueChanged += this.InterruptGpioPin_ValueChanged;

                    this.displayGpioPin = gpioController.OpenPin(this.displayPinNumber);
                    this.displayGpioPin.SetDriveMode(GpioPinDriveMode.Output);
                    this.displayGpioPin.Write(GpioPinValue.Low);
                }
                catch (Exception ex)
                {
                    this.logging.LogMessage("Digital input configuration failed " + ex.Message, LoggingLevel.Error);
                    return;
                }
            }
            #endregion

            #region Wire up command handler for image capture request
            try
            {
                this.azureIoTHubClient.SetMethodHandlerAsync("ImageCapture", this.ImageUpdateHandler, null);
            }
            catch (Exception ex)
            {
                this.logging.LogMessage("Azure IoT Hub client ImageCapture SetMethodHandlerAsync failed " + ex.Message, LoggingLevel.Error);
                return;
            }
            #endregion

            #region Wire up command handler for device reboot request
            try
            {
                this.azureIoTHubClient.SetMethodHandlerAsync("DeviceReboot", this.DeviceRebootAsync, null);
            }
            catch (Exception ex)
            {
                this.logging.LogMessage("Azure IoT Hub client DeviceReboot SetMethodHandlerAsync failed " + ex.Message, LoggingLevel.Error);
                return;
            }
            #endregion

            if ((imageUpdateDue != TimeSpan.MinValue) || (imageUpdatePeriod != TimeSpan.MinValue))
            {
                this.imageUpdatetimer = new Timer(this.ImageUpdateTimerCallback, null, imageUpdateDue, imageUpdatePeriod);
            }

            this.logging.LogEvent("Application started", startupInformation);

            // enable task to continue running in background
            this.backgroundTaskDeferral = taskInstance.GetDeferral();
        }