private async void InterruptGpioPin_ValueChanged(GpioPin sender, GpioPinValueChangedEventArgs args)
        {
            DateTime currentTime = DateTime.UtcNow;

            Debug.WriteLine($"{DateTime.UtcNow.ToLongTimeString()} 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)
            {
                return;
            }

            this.imageLastCapturedAtUtc = currentTime;

            // Just incase - stop code being called while photo already in progress
            if (this.cameraBusy)
            {
                return;
            }

            this.cameraBusy = true;

            try
            {
                string localFilenameLatest  = string.Format(this.localStorageimageFilenameLatestFormat, Environment.MachineName.ToLower(), currentTime);
                string localFilenameHistory = string.Format(this.localStorageImageFilenameHistoryFormat, Environment.MachineName.ToLower(), currentTime);

                StorageFile photoFile = await KnownFolders.PicturesLibrary.CreateFileAsync(localFilenameLatest, CreationCollisionOption.ReplaceExisting);

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

                LoggingFields imageInformation = new LoggingFields();
                imageInformation.AddDateTime("TakenAtUTC", currentTime);
                imageInformation.AddString("LocalFilename", photoFile.Path);
                imageInformation.AddString("LocalFilenameHistory", localFilenameHistory);
                this.logging.LogEvent("Saving image(s) to local storage", imageInformation);

                // copy the historic image to storage
                if (!string.IsNullOrWhiteSpace(localFilenameHistory))
                {
                    await photoFile.CopyAsync(KnownFolders.PicturesLibrary, localFilenameHistory);

                    this.logging.LogEvent("Image history saved to local storage");
                }
            }
            catch (Exception ex)
            {
                this.logging.LogMessage("Camera photo save or upload failed " + ex.Message, LoggingLevel.Error);
            }
            finally
            {
                this.cameraBusy = false;
            }
        }
        private async void ImageUpdateTimerCallback(object state)
        {
            DateTime currentTime = DateTime.UtcNow;

            Debug.WriteLine($"{DateTime.UtcNow.ToLongTimeString()} Timer triggered");

            // Just incase - stop code being called while photo already in progress
            if (cameraBusy)
            {
                return;
            }
            cameraBusy = true;

            try
            {
                string localFilename     = string.Format(localImageFilenameLatestFormat, currentTime);
                string folderNameHistory = string.Format(localFolderNameHistoryFormat, currentTime);
                string filenameHistory   = string.Format(localImageFilenameHistoryFormat, currentTime);

                StorageFile photoFile = await KnownFolders.PicturesLibrary.CreateFileAsync(localFilename, CreationCollisionOption.ReplaceExisting);

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

                LoggingFields imageInformation = new LoggingFields();
                imageInformation.AddDateTime("TakenAtUTC", currentTime);
                imageInformation.AddString("LocalFilename", photoFile.Path);
                imageInformation.AddString("FolderNameHistory", folderNameHistory);
                imageInformation.AddString("FilenameHistory", filenameHistory);
                this.logging.LogEvent("Image saved to local storage", imageInformation);

                // Upload the historic image to storage
                if (!string.IsNullOrWhiteSpace(folderNameHistory) && !string.IsNullOrWhiteSpace(filenameHistory))
                {
                    // Check to see if historic images folder exists and if it doesn't create it
                    IStorageFolder storageFolder = (IStorageFolder)await KnownFolders.PicturesLibrary.TryGetItemAsync(folderNameHistory);

                    if (storageFolder == null)
                    {
                        storageFolder = await KnownFolders.PicturesLibrary.CreateFolderAsync(folderNameHistory);
                    }
                    await photoFile.CopyAsync(storageFolder, filenameHistory, NameCollisionOption.ReplaceExisting);

                    this.logging.LogEvent("Image historic saved to local storage", imageInformation);
                }
            }
            catch (Exception ex)
            {
                this.logging.LogMessage("Image capture or save failed " + ex.Message, LoggingLevel.Error);
            }
            finally
            {
                cameraBusy = false;
            }
        }
Esempio n. 3
0
        private async void InterruptGpioPin_ValueChanged(GpioPin sender, GpioPinValueChangedEventArgs args)
        {
            DateTime currentTime = DateTime.UtcNow;

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

            if (args.Edge == GpioPinEdge.RisingEdge)
            {
                return;
            }

            // Just incase - stop code being called while photo already in progress
            if (this.cameraBusy)
            {
                return;
            }

            this.cameraBusy = true;

            try
            {
                string filename = string.Format(ImageFilenameFormat, currentTime);

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

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

                LoggingFields imageInformation = new LoggingFields();

                imageInformation.AddDateTime("TakenAtUTC", currentTime);
                imageInformation.AddString("Filename", filename);
                imageInformation.AddString("Path", photoFile.Path);

                this.logging.LogEvent("Captured image saved to storage", imageInformation);
            }
            catch (Exception ex)
            {
                this.logging.LogMessage("Image capture or save failed " + ex.Message, LoggingLevel.Error);
            }

            this.cameraBusy = false;
        }
Esempio n. 4
0
        private void ImageUpdateTimerCallback(object state)
        {
            DateTime currentTime = DateTime.UtcNow;

            try
            {
                string filename = string.Format(ImageFilenameFormat, currentTime);

                IStorageFile            photoFile       = KnownFolders.PicturesLibrary.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting).AsTask().Result;
                ImageEncodingProperties imageProperties = ImageEncodingProperties.CreateJpeg();
                this.mediaCapture.CapturePhotoToStorageFileAsync(imageProperties, photoFile).AsTask().Wait();

                LoggingFields imageInformation = new LoggingFields();
                imageInformation.AddDateTime("TakenAtUTC", currentTime);
                imageInformation.AddString("Filename", filename);
                imageInformation.AddString("Path", photoFile.Path);
                this.logging.LogEvent("Image saved to storage", imageInformation);
            }
            catch (Exception ex)
            {
                this.logging.LogMessage("Image capture or save to local storage failed " + ex.Message, LoggingLevel.Error);
            }
        }
        private async void InterruptGpioPin_ValueChanged(GpioPin sender, GpioPinValueChangedEventArgs args)
        {
            DateTime currentTime = DateTime.UtcNow;

            Debug.WriteLine($"{DateTime.UtcNow.ToLongTimeString()} 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)
            {
                return;
            }

            this.imageLastCapturedAtUtc = currentTime;

            // Just incase - stop code being called while photo already in progress
            if (this.cameraBusy)
            {
                return;
            }

            this.cameraBusy = true;

            try
            {
                StorageFile photoFile = await KnownFolders.PicturesLibrary.CreateFileAsync(ImageFilenameLocal, CreationCollisionOption.ReplaceExisting);

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

                string azureContainernameLatest  = string.Format(this.azureStorageContainerNameLatestFormat, Environment.MachineName, this.deviceMacAddress, currentTime).ToLower();
                string azureFilenameLatest       = string.Format(this.azureStorageimageFilenameLatestFormat, Environment.MachineName, this.deviceMacAddress, currentTime);
                string azureContainerNameHistory = string.Format(this.azureStorageContainerNameHistoryFormat, Environment.MachineName, this.deviceMacAddress, currentTime).ToLower();
                string azureFilenameHistory      = string.Format(this.azureStorageImageFilenameHistoryFormat, Environment.MachineName.ToLower(), this.deviceMacAddress, currentTime);

                LoggingFields imageInformation = new LoggingFields();
                imageInformation.AddDateTime("TakenAtUTC", currentTime);
                imageInformation.AddString("LocalFilename", photoFile.Path);
                imageInformation.AddString("AzureContainerNameLatest", azureContainernameLatest);
                imageInformation.AddString("AzureFilenameLatest", azureFilenameLatest);
                imageInformation.AddString("AzureContainerNameHistory", azureContainerNameHistory);
                imageInformation.AddString("AzureFilenameHistory", azureFilenameHistory);
                this.logging.LogEvent("Saving image(s) to Azure storage", imageInformation);

                CloudStorageAccount storageAccount = CloudStorageAccount.Parse(this.azureStorageConnectionString);
                CloudBlobClient     blobClient     = storageAccount.CreateCloudBlobClient();

                // Update the latest image in storage
                if (!string.IsNullOrWhiteSpace(azureContainernameLatest) && !string.IsNullOrWhiteSpace(azureFilenameLatest))
                {
                    CloudBlobContainer containerLatest = blobClient.GetContainerReference(azureContainernameLatest);
                    await containerLatest.CreateIfNotExistsAsync();

                    CloudBlockBlob blockBlobLatest = containerLatest.GetBlockBlobReference(azureFilenameLatest);
                    await blockBlobLatest.UploadFromFileAsync(photoFile);

                    this.logging.LogEvent("Image latest saved to Azure storage");
                }

                // Upload the historic image to storage
                if (!string.IsNullOrWhiteSpace(azureContainerNameHistory) && !string.IsNullOrWhiteSpace(azureFilenameHistory))
                {
                    CloudBlobContainer containerHistory = blobClient.GetContainerReference(azureContainerNameHistory);
                    await containerHistory.CreateIfNotExistsAsync();

                    CloudBlockBlob blockBlob = containerHistory.GetBlockBlobReference(azureFilenameHistory);
                    await blockBlob.UploadFromFileAsync(photoFile);

                    this.logging.LogEvent("Image historic saved to Azure storage");
                }
            }
            catch (Exception ex)
            {
                this.logging.LogMessage("Camera photo save or upload failed " + ex.Message, LoggingLevel.Error);
            }
            finally
            {
                this.cameraBusy = false;
            }
        }
Esempio n. 6
0
        /// <summary>
        /// This method demonstrates the LoggingChannel and LoggingActivity APIs.
        /// </summary>
        /// <param name="channel">
        /// The channel to use for the demonstration. This channel may have been
        /// constructed using a Windows 8.1 constructor or a Windows 10 constructor.
        /// The same APIs are supported in both cases, but the ETL events will be
        /// formatted a bit differently depending on how the channel was constructed.
        /// </param>
        private void DemonstrateLogging(LoggingChannel channel)
        {
            // Whenever any ETW session changes the way it is listening to this
            // channel, the LoggingEnable event is fired. For example, this might
            // be called when a session begins listening, changes the level at
            // which it is listening, or stops listening.
            channel.LoggingEnabled += this.OnLoggingEnabled;

            // Log simple string events
            channel.LogMessage("Simple message"); // default level is Verbose
            channel.LogMessage("Simple error", LoggingLevel.Error);

            // Log simple string + integer events.
            channel.LogValuePair("Simple message", 123); // default level is Verbose
            channel.LogValuePair("Simple error", 456, LoggingLevel.Error);

            // The channel.Name property returns the name that was used when the
            // channel was constructed. When running in Windows 10 mode, the name
            // is already set as the provider name, so no LoggingChannelName is
            // automatically added to the event.
            channel.LogMessage(channel.Name);

            // The channel.Id property is new to Windows 10.
            channel.LogMessage(channel.Id.ToString());

            // If you want to avoid the overhead of collecting data when nobody is
            // listening to your channel, check the Enabled property before logging.
            if (channel.Enabled)
            {
                channel.LogMessage(this.CollectExpensiveData());
            }

            // The IsEnabled() method is exactly the same as the Enabled property,
            // except that it is a new Windows 10 API.
            if (channel.IsEnabled())
            {
                channel.LogMessage(this.CollectExpensiveData());
            }

            // If you want to only collect data if somebody is listening at a specific
            // level, you need to check both Enabled and Level. Note that the value of
            // the Level is unspecified when Enabled is false.
            if (channel.Enabled && channel.Level <= LoggingLevel.Warning)
            {
                channel.LogMessage(this.CollectExpensiveData(), LoggingLevel.Warning);
            }

            // The IsEnabled(LoggingLevel) method is a bit nicer than checking both
            // Enabled and Level, but it is only available on Windows 10 or later.
            if (channel.IsEnabled(LoggingLevel.Warning))
            {
                channel.LogMessage(this.CollectExpensiveData(), LoggingLevel.Warning);
            }

            // You can also use IsEnabled to check for keywords.
            if (channel.IsEnabled(LoggingLevel.Information, 0x10))
            {
                channel.LogMessage(this.CollectExpensiveData(), LoggingLevel.Information);
            }

            // Use LoggingFields with the LogEvent method to write complex events.
            var fields = new LoggingFields();

            fields.AddDouble("pi", 3.14159);
            channel.LogEvent(
                "ComplexEvent",
                fields,
                LoggingLevel.Verbose,
                new LoggingOptions(0x10)); // Keywords = 0x10

            // You can add any number of name-value pairs to a fields object, though
            // you may encounter ETW limitations if you add too many. For example,
            // ETW is limited to a maximum event size of 64KB, and the current
            // TraceLogging decoder can handle no more than 128 fields.

            // Performance optimization: You can reuse a LoggingFields object to
            // avoid unnecessary allocations. Don't forget to call Clear()
            // between uses, and don't try to share a LoggingFields object between
            // threads.
            fields.Clear();
            fields.AddDateTime("Date", DateTimeOffset.Now);
            channel.LogEvent("Now", fields);

            fields.Clear();

            // You can add a formatting hint to affect the way a value is decoded.
            // Not all combinations are useful, and the hint may be ignored.
            // For example, you can encode an MBCS string by writing a byte array
            // with a String hint.
            fields.AddUInt8Array(
                "AnsiString",
                new byte[] { 65, 66, 67, 49, 50, 51 }, // "ABC123"
                LoggingFieldFormat.String);

            // You can add "tag" bits to a field. These are user-defined bits that
            // can be used to communicate with an event processing tool. For example,
            // you might define a tag bit to indicate that a field contains private
            // data that should not be displayed on-screen.
            fields.AddString("Password", "12345", LoggingFieldFormat.Default, 0x10);

            // You can add a "structure" to an event. A structure is a name for a
            // group of fields. Structures can nest. Call BeginStruct to add a level
            // of nesting, and call EndStruct after the last field of the structure.
            fields.BeginStruct("Nested");
            fields.AddInt16("Nested-1", 1);
            fields.AddInt16("Nested-2", 2);
            fields.BeginStruct("Nested-Nested");
            fields.AddInt16("Nested-Nested-3", 3);
            fields.EndStruct();
            fields.AddInt16("Nested-4", 4);
            fields.EndStruct();

            // Advanced scenarios: you can use a LoggingOptions object to control
            // detailed event settings such as keywords, opcodes, and activity Ids.
            // These have their normal ETW semantics. You can also set event tags,
            // which are bit values that can be used to communicate with the event
            // processor.
            channel.LogEvent(
                "VeryComplexEvent",
                fields,
                LoggingLevel.Information,
                new LoggingOptions {
                Keywords = 0x123, Tags = 0x10
            });

            // Windows 10 introduces the ILoggingTarget interface. LoggingChannel
            // implements this interface. This interface allows components to accept
            // a logger as an parameter.
            this.DoSomething(channel);

            /*
             * If a LoggingActivity is created using a LoggingActivity constructor,
             * it will use Windows 8.1 semantics:
             *
             * - If an activity is destroyed (garbage-collected) without being closed
             * and the associated LoggingChannel is still open, the activity will
             * write a default Stop event.
             * - The default Stop event (written by the destructor or by the Close()
             * method) is encoded as a "simple" event.
             *
             * The 8.1 semantics are deprecated because the automatic generation of
             * a Stop event at garbage-collection can be misleading. The Stop event
             * is intended to mark the a precise point at which an activity is
             * completed, while the garbage-collection of an abandoned activity is
             * inherently imprecise and unpredictable.
             *
             * If a LoggingActivity is created using a StartActivity method, it will
             * use Windows 10 semantics:
             *
             * - If an activity is destroyed (garbage-collected) without being closed,
             * there will be no Stop event for the activity.
             * - The default Stop event (written by the Close() method) is encoded as
             * a TraceLogging event with name "ActivityClosed".
             */

            // This activity is created with Windows 8.1 semantics.
            using (var a1 = new LoggingActivity("Activity1", channel))
            {
                // The activity Start event is written by the LoggingActivity constructor.
                // You would do your activity's work here.
                // The activity Stop event is written when the activity is closed (disposed).

                // The Windows 10 LoggingActivity adds new methods for writing events
                // that are marked as associated with the activity.
                a1.LogEvent("Activity event");

                // LoggingActivity also implements the ILoggingTarget interface, so you can
                // use either a channel or an activity as a logging target.
                this.DoSomething(a1);

                // The Windows 10 LoggingActivity adds new methods for creating nested activities.
                // Note that nested activities are always created with Windows 10 semantics,
                // even when nested under an activity that is using Windows 8.1 semantics.
                using (var a2 = a1.StartActivity("Activity2"))
                {
                    // Nested task occurs here.

                    // The Windows 10 LoggingActivity allows you to customize the Stop event.
                    a2.StopActivity("Activity 2 stop");
                }

                // Because a1 is using Windows 8.1 semantics, if we did not call Dispose(),
                // it would attempt to write a Stop event when it is garbage collected.
                // Writing Stop events during garbage collection is not useful, so be sure
                // to properly stop, close, or dispose activities.
            }

            // The Windows 10 StartActivity method creates a new activity, optionally with
            // specified fields and characteristics.
            // This activity is created with Windows 10 semantics.
            using (var a3 = channel.StartActivity("Activity3"))
            {
                // Because a3 is using Windows 10 semantics, if we did not call Dispose(),
                // there would be no Stop event (not even when the activity is garbage
                // collected). To get a Stop event, be sure to stop, close, or dispose the
                // activity.
            }
        }
        /// <summary>
        /// This method demonstrates the LoggingChannel and LoggingActivity APIs.
        /// </summary>
        /// <param name="channel">
        /// The channel to use for the demonstration. This channel may have been
        /// constructed using a Windows 8.1 constructor or a Windows 10 constructor.
        /// The same APIs are supported in both cases, but the ETL events will be
        /// formatted a bit differently depending on how the channel was constructed.
        /// </param>
        private void DemonstrateLogging(LoggingChannel channel)
        {
            // Whenever any ETW session changes the way it is listening to this
            // channel, the LoggingEnable event is fired. For example, this might
            // be called when a session begins listening, changes the level at
            // which it is listening, or stops listening.
            channel.LoggingEnabled += this.OnLoggingEnabled;

            // Log simple string events
            channel.LogMessage("Simple message"); // default level is Verbose
            channel.LogMessage("Simple error", LoggingLevel.Error);

            // Log simple string + integer events.
            channel.LogValuePair("Simple message", 123); // default level is Verbose
            channel.LogValuePair("Simple error", 456, LoggingLevel.Error);

            // The channel.Name property returns the name that was used when the
            // channel was constructed. When running in Windows 10 mode, the name
            // is already set as the provider name, so no LoggingChannelName is
            // automatically added to the event.
            channel.LogMessage(channel.Name);

            // The channel.Id property is new to Windows 10.
            channel.LogMessage(channel.Id.ToString());

            // If you want to avoid the overhead of collecting data when nobody is
            // listening to your channel, check the Enabled property before logging.
            if (channel.Enabled)
            {
                channel.LogMessage(this.CollectExpensiveData());
            }

            // The IsEnabled() method is exactly the same as the Enabled property,
            // except that it is a new Windows 10 API.
            if (channel.IsEnabled())
            {
                channel.LogMessage(this.CollectExpensiveData());
            }

            // If you want to only collect data if somebody is listening at a specific
            // level, you need to check both Enabled and Level. Note that the value of
            // the Level is unspecified when Enabled is false.
            if (channel.Enabled && channel.Level <= LoggingLevel.Warning)
            {
                channel.LogMessage(this.CollectExpensiveData(), LoggingLevel.Warning);
            }

            // The IsEnabled(LoggingLevel) method is a bit nicer than checking both
            // Enabled and Level, but it is only available on Windows 10 or later.
            if (channel.IsEnabled(LoggingLevel.Warning))
            {
                channel.LogMessage(this.CollectExpensiveData(), LoggingLevel.Warning);
            }

            // You can also use IsEnabled to check for keywords.
            if (channel.IsEnabled(LoggingLevel.Information, 0x10))
            {
                channel.LogMessage(this.CollectExpensiveData(), LoggingLevel.Information);
            }

            // Use LoggingFields with the LogEvent method to write complex events.
            var fields = new LoggingFields();
            fields.AddDouble("pi", 3.14159);
            channel.LogEvent(
                "ComplexEvent",
                fields,
                LoggingLevel.Verbose,
                new LoggingOptions(0x10)); // Keywords = 0x10

            // You can add any number of name-value pairs to a fields object, though
            // you may encounter ETW limitations if you add too many. For example,
            // ETW is limited to a maximum event size of 64KB, and the current
            // TraceLogging decoder can handle no more than 128 fields.

            // Performance optimization: You can reuse a LoggingFields object to
            // avoid unnecessary allocations. Don't forget to call Clear()
            // between uses, and don't try to share a LoggingFields object between
            // threads.
            fields.Clear();
            fields.AddDateTime("Date", DateTimeOffset.Now);
            channel.LogEvent("Now", fields);

            fields.Clear();

            // You can add a formatting hint to affect the way a value is decoded.
            // Not all combinations are useful, and the hint may be ignored.
            // For example, you can encode an MBCS string by writing a byte array
            // with a String hint.
            fields.AddUInt8Array(
                "AnsiString",
                new byte[] { 65, 66, 67, 49, 50, 51 }, // "ABC123"
                LoggingFieldFormat.String);

            // You can add "tag" bits to a field. These are user-defined bits that
            // can be used to communicate with an event processing tool. For example,
            // you might define a tag bit to indicate that a field contains private
            // data that should not be displayed on-screen.
            fields.AddString("Password", "12345", LoggingFieldFormat.Default, 0x10);

            // You can add a "structure" to an event. A structure is a name for a
            // group of fields. Structures can nest. Call BeginStruct to add a level
            // of nesting, and call EndStruct after the last field of the structure.
            fields.BeginStruct("Nested");
                fields.AddInt16("Nested-1", 1);
                fields.AddInt16("Nested-2", 2);
                fields.BeginStruct("Nested-Nested");
                    fields.AddInt16("Nested-Nested-3", 3);
                fields.EndStruct();
                fields.AddInt16("Nested-4", 4);
            fields.EndStruct();

            // Advanced scenarios: you can use a LoggingOptions object to control
            // detailed event settings such as keywords, opcodes, and activity Ids.
            // These have their normal ETW semantics. You can also set event tags,
            // which are bit values that can be used to communicate with the event
            // processor.
            channel.LogEvent(
                "VeryComplexEvent",
                fields,
                LoggingLevel.Information,
                new LoggingOptions { Keywords = 0x123, Tags = 0x10 });

            // Windows 10 introduces the ILoggingTarget interface. LoggingChannel
            // implements this interface. This interface allows components to accept
            // a logger as an parameter.
            this.DoSomething(channel);

            /*
            If a LoggingActivity is created using a LoggingActivity constructor,
            it will use Windows 8.1 semantics:

            - If an activity is destroyed (garbage-collected) without being closed
              and the associated LoggingChannel is still open, the activity will
              write a default Stop event.
            - The default Stop event (written by the destructor or by the Close()
              method) is encoded as a "simple" event.

            The 8.1 semantics are deprecated because the automatic generation of
            a Stop event at garbage-collection can be misleading. The Stop event
            is intended to mark the a precise point at which an activity is
            completed, while the garbage-collection of an abandoned activity is
            inherently imprecise and unpredictable.

            If a LoggingActivity is created using a StartActivity method, it will
            use Windows 10 semantics:

            - If an activity is destroyed (garbage-collected) without being closed,
              there will be no Stop event for the activity.
            - The default Stop event (written by the Close() method) is encoded as
              a TraceLogging event with name "ActivityClosed".
            */

            // This activity is created with Windows 8.1 semantics.
            using (var a1 = new LoggingActivity("Activity1", channel))
            {
                // The activity Start event is written by the LoggingActivity constructor.
                // You would do your activity's work here.
                // The activity Stop event is written when the activity is closed (disposed).

                // The Windows 10 LoggingActivity adds new methods for writing events
                // that are marked as associated with the activity.
                a1.LogEvent("Activity event");

                // LoggingActivity also implements the ILoggingTarget interface, so you can
                // use either a channel or an activity as a logging target.
                this.DoSomething(a1);

                // The Windows 10 LoggingActivity adds new methods for creating nested activities.
                // Note that nested activities are always created with Windows 10 semantics,
                // even when nested under an activity that is using Windows 8.1 semantics.
                using (var a2 = a1.StartActivity("Activity2"))
                {
                    // Nested task occurs here.

                    // The Windows 10 LoggingActivity allows you to customize the Stop event.
                    a2.StopActivity("Activity 2 stop");
                }

                // Because a1 is using Windows 8.1 semantics, if we did not call Dispose(),
                // it would attempt to write a Stop event when it is garbage collected.
                // Writing Stop events during garbage collection is not useful, so be sure
                // to properly stop, close, or dispose activities.
            }

            // The Windows 10 StartActivity method creates a new activity, optionally with
            // specified fields and characteristics.
            // This activity is created with Windows 10 semantics.
            using (var a3 = channel.StartActivity("Activity3"))
            {
                // Because a3 is using Windows 10 semantics, if we did not call Dispose(),
                // there would be no Stop event (not even when the activity is garbage
                // collected). To get a Stop event, be sure to stop, close, or dispose the
                // activity.
            }
        }
Esempio n. 8
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;
            }
        }
Esempio n. 9
0
        private async void ImageUpdateTimerCallback(object state)
        {
            DateTime currentTime = DateTime.UtcNow;

            Debug.WriteLine($"{DateTime.UtcNow.ToLongTimeString()} Timer triggered");

            // Just incase - stop code being called while photo already in progress
            if (this.cameraBusy)
            {
                return;
            }

            this.cameraBusy = true;

            try
            {
                StorageFile photoFile = await KnownFolders.PicturesLibrary.CreateFileAsync(ImageFilenameLocal, CreationCollisionOption.ReplaceExisting);

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

                string azureContainernameLatest  = string.Format(this.azureStorageContainerNameLatestFormat, Environment.MachineName, this.deviceMacAddress, currentTime).ToLower();
                string azureFilenameLatest       = string.Format(this.azureStorageimageFilenameLatestFormat, Environment.MachineName, this.deviceMacAddress, currentTime);
                string azureContainerNameHistory = string.Format(this.azureStorageContainerNameHistoryFormat, Environment.MachineName, this.deviceMacAddress, currentTime).ToLower();
                string azureFilenameHistory      = string.Format(this.azureStorageImageFilenameHistoryFormat, Environment.MachineName.ToLower(), this.deviceMacAddress, currentTime);

                LoggingFields imageInformation = new LoggingFields();
                imageInformation.AddDateTime("TakenAtUTC", currentTime);
                imageInformation.AddString("LocalFilename", photoFile.Path);
                imageInformation.AddString("AzureContainerNameLatest", azureContainernameLatest);
                imageInformation.AddString("AzureFilenameLatest", azureFilenameLatest);
                imageInformation.AddString("AzureContainerNameHistory", azureContainerNameHistory);
                imageInformation.AddString("AzureFilenameHistory", azureFilenameHistory);
                this.logging.LogEvent("Saving image(s) to Azure storage", imageInformation);

                CloudStorageAccount storageAccount = CloudStorageAccount.Parse(this.azureStorageConnectionString);
                CloudBlobClient     blobClient     = storageAccount.CreateCloudBlobClient();

                // Update the latest image in storage
                if (!string.IsNullOrWhiteSpace(azureContainernameLatest) && !string.IsNullOrWhiteSpace(azureFilenameLatest))
                {
                    CloudBlobContainer containerLatest = blobClient.GetContainerReference(azureContainernameLatest);
                    await containerLatest.CreateIfNotExistsAsync();

                    CloudBlockBlob blockBlobLatest = containerLatest.GetBlockBlobReference(azureFilenameLatest);
                    await blockBlobLatest.UploadFromFileAsync(photoFile);

                    this.logging.LogEvent("Image latest saved to Azure storage");
                }

                // Upload the historic image to storage
                if (!string.IsNullOrWhiteSpace(azureContainerNameHistory) && !string.IsNullOrWhiteSpace(azureFilenameHistory))
                {
                    CloudBlobContainer containerHistory = blobClient.GetContainerReference(azureContainerNameHistory);
                    await containerHistory.CreateIfNotExistsAsync();

                    CloudBlockBlob blockBlob = containerHistory.GetBlockBlobReference(azureFilenameHistory);
                    await blockBlob.UploadFromFileAsync(photoFile);

                    this.logging.LogEvent("Image historic saved to Azure storage");
                }
            }
            catch (Exception ex)
            {
                this.logging.LogMessage("Image capture or upload failed " + ex.Message, LoggingLevel.Error);
            }
            finally
            {
                this.cameraBusy = false;
            }
        }
Esempio n. 10
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);

                    ImagePrediction imagePrediction = await this.customVisionClient.ClassifyImageAsync(this.projectId, this.publishedName, captureStream.AsStreamForRead());

                    Debug.WriteLine($"Prediction count {imagePrediction.Predictions.Count}");

                    LoggingFields imageInformation = new LoggingFields();

                    imageInformation.AddDateTime("TakenAtUTC", currentTime);
                    imageInformation.AddInt32("Pin", sender.PinNumber);
                    imageInformation.AddInt32("Predictions", imagePrediction.Predictions.Count);

                    foreach (var prediction in imagePrediction.Predictions)
                    {
                        Debug.WriteLine($" Tag:{prediction.TagName} {prediction.Probability}");
                        imageInformation.AddDouble($"Tag:{prediction.TagName}", prediction.Probability);
                    }

                    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;
            }
        }
        private async Task ImageUpdate(bool isCommand)
        {
            DateTime currentTime = DateTime.UtcNow;

            // Just incase - stop code being called while photo already in progress
            if (this.cameraBusy)
            {
                return;
            }
            this.cameraBusy = true;
            this.displayGpioPin.Write(GpioPinValue.High);

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

            this.imageLastCapturedAtUtc = currentTime;

            try
            {
                ImagePrediction imagePrediction;

                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);

                    switch (modelType)
                    {
                    case ModelType.Classification:
                        imagePrediction = await this.customVisionClient.ClassifyImageAsync(this.projectId, this.modelPublishedName, captureStream.AsStreamForRead());

                        break;

                    case ModelType.Detection:
                        imagePrediction = await this.customVisionClient.DetectImageAsync(this.projectId, this.modelPublishedName, captureStream.AsStreamForRead());

                        break;

                    default:
                        throw new ArgumentException("ModelType Invalid");
                    }
                    Debug.WriteLine($"Prediction count {imagePrediction.Predictions.Count}");
                }

                JObject       telemetryDataPoint = new JObject();
                LoggingFields imageInformation   = new LoggingFields();

                imageInformation.AddDateTime("TakenAtUTC", currentTime);
                imageInformation.AddBoolean("IsCommand", isCommand);
                imageInformation.AddDouble("Probability threshold", probabilityThreshold);
                imageInformation.AddInt32("Predictions", imagePrediction.Predictions.Count);

                // Display and log the results of the prediction
                foreach (var prediction in imagePrediction.Predictions)
                {
                    Debug.WriteLine($" Tag:{prediction.TagName} {prediction.Probability}");
                    imageInformation.AddDouble($"Tag:{prediction.TagName}", prediction.Probability);
                }

                // Post process the predictions based on the type of model
                switch (modelType)
                {
                case ModelType.Classification:
                    // Use only the tags above the specified minimum probability
                    foreach (var prediction in imagePrediction.Predictions)
                    {
                        if (prediction.Probability >= probabilityThreshold)
                        {
                            // Display and log the individual tag probabilities
                            Debug.WriteLine($" Tag valid:{prediction.TagName} {prediction.Probability:0.00}");
                            imageInformation.AddDouble($"Tag valid:{prediction.TagName}", prediction.Probability);

                            telemetryDataPoint.Add(prediction.TagName, prediction.Probability);
                        }
                    }
                    break;

                case ModelType.Detection:
                    // Group the tags to get the count, include only the predictions above the specified minimum probability
                    var groupedPredictions = from prediction in imagePrediction.Predictions
                                             where prediction.Probability >= probabilityThreshold
                                             group prediction by new { prediction.TagName }
                    into newGroup
                        select new
                    {
                        TagName = newGroup.Key.TagName,
                        Count   = newGroup.Count(),
                    };

                    // Display and log the agregated predictions
                    foreach (var prediction in groupedPredictions)
                    {
                        Debug.WriteLine($" Tag valid:{prediction.TagName} {prediction.Count}");
                        imageInformation.AddInt32($"Tag valid:{prediction.TagName}", prediction.Count);
                        telemetryDataPoint.Add(prediction.TagName, prediction.Count);
                    }
                    break;

                default:
                    throw new ArgumentException("ModelType Invalid");
                }

                this.logging.LogEvent("Captured image processed by Cognitive Services", imageInformation);

                try
                {
                    using (Message message = new Message(Encoding.ASCII.GetBytes(JsonConvert.SerializeObject(telemetryDataPoint))))
                    {
                        Debug.WriteLine(" {0:HH:mm:ss} AzureIoTHubClient SendEventAsync start", DateTime.UtcNow);
                        await this.azureIoTHubClient.SendEventAsync(message);

                        Debug.WriteLine(" {0:HH:mm:ss} AzureIoTHubClient SendEventAsync finish", DateTime.UtcNow);
                    }
                    this.logging.LogEvent("SendEventAsync payload", imageInformation, LoggingLevel.Information);
                }
                catch (Exception ex)
                {
                    imageInformation.AddString("Exception", ex.ToString());
                    this.logging.LogEvent("SendEventAsync payload", imageInformation, LoggingLevel.Error);
                }
            }
            catch (Exception ex)
            {
                this.logging.LogMessage("Camera photo or save failed " + ex.Message, LoggingLevel.Error);
            }
            finally
            {
                this.displayGpioPin.Write(GpioPinValue.Low);
                this.cameraBusy = false;
            }
        }
        private async Task ImageUpdate(bool isCommand)
        {
            DateTime currentTime = DateTime.UtcNow;

            // Just incase - stop code being called while photo already in progress
            if (this.cameraBusy)
            {
                return;
            }
            this.cameraBusy = true;

            try
            {
                using (Windows.Storage.Streams.InMemoryRandomAccessStream captureStream = new Windows.Storage.Streams.InMemoryRandomAccessStream())
                {
                    await this.mediaCapture.CapturePhotoToStreamAsync(ImageEncodingProperties.CreateJpeg(), captureStream);

                    await captureStream.FlushAsync();

#if DEBUG
                    IStorageFile photoFile = await KnownFolders.PicturesLibrary.CreateFileAsync(ImageFilenameLocal, CreationCollisionOption.ReplaceExisting);

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

                    string azureFilenameLatest  = string.Format(this.azureStorageimageFilenameLatestFormat, currentTime);
                    string azureFilenameHistory = string.Format(this.azureStorageImageFilenameHistoryFormat, currentTime);

                    LoggingFields imageInformation = new LoggingFields();
                    imageInformation.AddDateTime("TakenAtUTC", currentTime);
                    imageInformation.AddBoolean("IsCommand", isCommand);
#if DEBUG
                    imageInformation.AddString("LocalFilename", photoFile.Path);
#endif
                    imageInformation.AddString("AzureFilenameLatest", azureFilenameLatest);
                    imageInformation.AddString("AzureFilenameHistory", azureFilenameHistory);
                    this.logging.LogEvent("Saving image(s) to Azure storage", imageInformation);

                    // Update the latest image in storage
                    if (!string.IsNullOrWhiteSpace(azureFilenameLatest))
                    {
                        captureStream.Seek(0);
                        Debug.WriteLine("AzureIoT Hub latest image upload start");
                        await this.azureIoTHubClient.UploadToBlobAsync(azureFilenameLatest, captureStream.AsStreamForRead());

                        Debug.WriteLine("AzureIoT Hub latest image upload done");
                    }

                    // Upload the historic image to storage
                    if (!string.IsNullOrWhiteSpace(azureFilenameHistory))
                    {
                        captureStream.Seek(0);
                        Debug.WriteLine("AzureIoT Hub historic image upload start");
                        await this.azureIoTHubClient.UploadToBlobAsync(azureFilenameHistory, captureStream.AsStreamForRead());

                        Debug.WriteLine("AzureIoT Hub historic image upload done");
                    }
                }
            }
            catch (Exception ex)
            {
                this.logging.LogMessage("Image capture or AzureIoTHub storage upload failed " + ex.Message, LoggingLevel.Error);
            }
            finally
            {
                this.cameraBusy = false;
            }
        }