private void Rfm9XDevice_OnReceive(object sender, Rfm9XDevice.OnDataReceivedEventArgs e) { LoggingFields messageHandlerLoggingFields = new LoggingFields(); #if DEBUG Debug.WriteLine($"{DateTime.UtcNow:HH:mm:ss}-OnReceive From:{BitConverter.ToString(e.Address)} PacketSnr:{e.PacketSnr:0.0} Packet RSSI:{e.PacketRssi}dBm RSSI:{e.Rssi}dBm Length:{e.Data.Length}"); #endif messageHandlerLoggingFields.AddString("PacketSNR", e.PacketSnr.ToString("F1")); messageHandlerLoggingFields.AddInt32("PacketRSSI", e.PacketRssi); messageHandlerLoggingFields.AddInt32("RSSI", e.Rssi); string addressBcdText = BitConverter.ToString(e.Address); messageHandlerLoggingFields.AddInt32("DeviceAddressLength", e.Address.Length); messageHandlerLoggingFields.AddString("DeviceAddressBCD", addressBcdText); if (messageHandler != null) { try { messageHandler.Rfm9XOnReceive(e); } catch (Exception ex) { messageHandlerLoggingFields.AddString("MessageHandler Exception", ex.ToString()); this.logging.LogEvent("Rfm9XDevice_OnReceive", messageHandlerLoggingFields, LoggingLevel.Error); return; } } this.logging.LogEvent("Rfm9XDevice_OnReceive", messageHandlerLoggingFields, LoggingLevel.Information); }
private async Task <MethodResponse> DeviceSendAsync(MethodRequest methodRequest, object userContext) { LoggingFields sendLoggingInfo = new LoggingFields(); this.logging.LogEvent("Send BCD initiated"); try { // Initially use a dynamic maybe use a decorated class in future dynamic json = JValue.Parse(methodRequest.DataAsJson); string deviceAddressBcd = json.DeviceAddress; sendLoggingInfo.AddString("DeviceAddressBCD", deviceAddressBcd); Debug.WriteLine($"DeviceSendAsync DeviceAddressBCD {deviceAddressBcd}"); byte[] deviceAddressBytes = deviceAddressBcd.Split('-').Select(x => byte.Parse(x, NumberStyles.HexNumber)).ToArray(); sendLoggingInfo.AddInt32("DeviceAddressBytes Length", deviceAddressBytes.Length); Debug.WriteLine($"DeviceSendAsync DeviceAddressLength {deviceAddressBytes.Length}"); if ((deviceAddressBytes.Length < Rfm9XDevice.AddressLengthMinimum) || (deviceAddressBytes.Length > Rfm9XDevice.AddressLengthMaximum)) { this.logging.LogEvent("DeviceSendAsync failed device address bytes length", sendLoggingInfo, LoggingLevel.Error); return(new MethodResponse(414)); } string messagedBcd = json.DevicePayload; sendLoggingInfo.AddString("MessageBCD", messagedBcd); byte[] messageBytes = messagedBcd.Split('-').Select(x => byte.Parse(x, NumberStyles.HexNumber)).ToArray(); // changed the '-' to ' ' sendLoggingInfo.AddInt32("MessageBytesLength", messageBytes.Length); Debug.WriteLine($"DeviceSendAsync DeviceAddress:{deviceAddressBcd} Payload:{messagedBcd}"); if ((messageBytes.Length < Rfm9XDevice.MessageLengthMinimum) || (messageBytes.Length > Rfm9XDevice.MessageLengthMaximum)) { this.logging.LogEvent("DeviceSendAsync failed payload Length", sendLoggingInfo, LoggingLevel.Error); return(new MethodResponse(413)); } if (sendMessageQueue.TryAdd(deviceAddressBytes, messageBytes)) { this.logging.LogEvent("DeviceSendAsync failed message already queued", sendLoggingInfo, LoggingLevel.Error); return(new MethodResponse(409)); } this.logging.LogEvent("DeviceSendAsync success", sendLoggingInfo, LoggingLevel.Information); } catch (Exception ex) { sendLoggingInfo.AddString("Exception", ex.ToString()); this.logging.LogEvent("DeviceSendAsync failed exception", sendLoggingInfo, LoggingLevel.Error); return(new MethodResponse(400)); } return(new MethodResponse(200)); }
async Task PayloadText(DeviceClient azureIoTHubClient, Rfm9XDevice.OnDataReceivedEventArgs e) { JObject telemetryDataPoint = new JObject(); LoggingFields processLoggingFields = new LoggingFields(); processLoggingFields.AddString("PacketSNR", e.PacketSnr.ToString("F1")); telemetryDataPoint.Add("PacketSNR", e.PacketSnr.ToString("F1")); processLoggingFields.AddInt32("PacketRSSI", e.PacketRssi); telemetryDataPoint.Add("PacketRSSI", e.PacketRssi); processLoggingFields.AddInt32("RSSI", e.Rssi); telemetryDataPoint.Add("RSSI", e.Rssi); string addressBcdText = BitConverter.ToString(e.Address); processLoggingFields.AddInt32("DeviceAddressLength", e.Address.Length); processLoggingFields.AddString("DeviceAddressBCD", addressBcdText); telemetryDataPoint.Add("DeviceAddressBCD", addressBcdText); string messageBcdText = BitConverter.ToString(e.Data); processLoggingFields.AddInt32("MessageLength", e.Data.Length); processLoggingFields.AddString("MessageBCD", messageBcdText); try { string messageText = UTF8Encoding.UTF8.GetString(e.Data); processLoggingFields.AddString("MessageText", messageText); telemetryDataPoint.Add("Payload", messageText); } catch (Exception) { this.logging.LogEvent("PayloadProcess failure converting payload to text", processLoggingFields, LoggingLevel.Warning); return; } 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 Text payload", processLoggingFields, LoggingLevel.Information); } catch (Exception ex) { processLoggingFields.AddString("Exception", ex.ToString()); this.logging.LogEvent("SendEventAsync Text payload", processLoggingFields, LoggingLevel.Error); } }
private void WriteLog(string text, LoggingLevel loggingLevel = LoggingLevel.Verbose, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) { Debug.WriteLine($"[Log::{Enum.GetName(typeof(LoggingLevel), loggingLevel)}][{memberName}] {text}"); if (_session == null || _channel == null) { Debug.WriteLine("Error: Logger is not initialized"); return; } try { string message = "Message: " + text + Environment.NewLine + Environment.NewLine + "Member name: " + memberName + Environment.NewLine + "Source file path: " + sourceFilePath + Environment.NewLine + "Source line number: " + sourceLineNumber + Environment.NewLine; var fields = new LoggingFields(); fields.AddString("MemberName", memberName); fields.AddString("SourceFilePath", sourceFilePath); fields.AddInt32("SourceLineNumber", sourceLineNumber); fields.AddString("Message", text); _channel.LogEvent("LogEvent", fields, loggingLevel); } catch (Exception ex) { Debug.WriteLine("[Log] " + ex); } }
public void Run(IBackgroundTaskInstance taskInstance) { LoggingFields startupInformation = new LoggingFields(); this.logging.LogEvent("Application starting"); try { this.mediaCapture = new MediaCapture(); this.mediaCapture.InitializeAsync().AsTask().Wait(); Debug.WriteLine("Camera configuration success"); GpioController gpioController = GpioController.GetDefault(); this.interruptGpioPin = gpioController.OpenPin(InterruptPinNumber); this.interruptGpioPin.SetDriveMode(GpioPinDriveMode.InputPullUp); this.interruptGpioPin.ValueChanged += this.InterruptGpioPin_ValueChanged; Debug.WriteLine("Digital Input Interrupt configuration success"); } catch (Exception ex) { this.logging.LogMessage("Camera or digital input configuration failed " + ex.Message, LoggingLevel.Error); return; } startupInformation.AddString("PrimaryUse", this.mediaCapture.VideoDeviceController.PrimaryUse.ToString()); startupInformation.AddInt32("Interrupt pin", InterruptPinNumber); this.logging.LogEvent("Application started", startupInformation); // enable task to continue running in background this.backgroundTaskDeferral = taskInstance.GetDeferral(); }
void IMessageHandler.Rfm9XOnReceive(Rfm9XDevice.OnDataReceivedEventArgs e) { LoggingFields processReceiveLoggingFields = new LoggingFields(); processReceiveLoggingFields.AddString("PacketSNR", e.PacketSnr.ToString("F1")); processReceiveLoggingFields.AddInt32("PacketRSSI", e.PacketRssi); processReceiveLoggingFields.AddInt32("RSSI", e.Rssi); string addressBcdText = BitConverter.ToString(e.Address); processReceiveLoggingFields.AddInt32("DeviceAddressLength", e.Address.Length); processReceiveLoggingFields.AddString("DeviceAddressBCD", addressBcdText); string payloadBcdText = BitConverter.ToString(e.Data); processReceiveLoggingFields.AddInt32("PayloadLength", e.Data.Length); processReceiveLoggingFields.AddString("DeviceAddressBCD", payloadBcdText); this.Logging.LogEvent("Rfm9XOnReceive", processReceiveLoggingFields, LoggingLevel.Information); }
public void ResizeVisibleComplete(int viewId) { if (!GetTraceLoggingProviderEnabled()) { return; } LoggingFields fields = new LoggingFields(); PopulateAppInfo(fields); fields.AddInt32("ViewId", viewId); LogAppLifecycleEvent("ModernAppResize_VisibleComplete", fields); }
/// <summary> /// Logs an exception and returns it. /// </summary> /// <param name="msg">A message associated with the exception.</param> /// <param name="exception">The exception.</param> /// <returns>The exception.</returns> public static Exception LogException(string msg, Exception exception) { Debug.WriteLine("Exception: " + msg); Debug.WriteLine("Message: " + exception.Message); LoggingFields fields = new LoggingFields(); fields.AddString("Error message", msg); fields.AddString("Exception message", exception.Message); fields.AddInt32("HResult", exception.HResult); Instance().channel.LogEvent("Exception", fields, LoggingLevel.Error); return(exception); }
private static void PushException(ref LoggingFields a, Exception m) { if (m != null) { a.BeginStruct("Exception"); a.AddString("Type", m.GetType().Name); a.AddString("Message", m.Message ?? string.Empty); a.AddString("Source", m.Source ?? string.Empty); a.AddInt32("HResult", m.HResult); a.AddString("StackTrace", m.StackTrace ?? string.Empty); PushException(ref a, m.InnerException); a.EndStruct(); } else { return; } }
private async Task <MethodResponse> RestartAsync(MethodRequest methodRequest, object userContext) { LoggingFields restartLoggingInfo = new LoggingFields(); #if CLOUD_DEVICE_SEND restartLoggingInfo.AddInt32("Send message queue count", sendMessageQueue.Count); #endif restartLoggingInfo.AddTimeSpan("Device restart period", DeviceRestartPeriod); // Disconnect the transmit and receive callbacks, once messages Send & Push need to consider what todo with queued outbound messages rfm9XDevice.OnReceive -= Rfm9XDevice_OnReceive; rfm9XDevice.OnTransmit -= Rfm9XDevice_OnTransmit; this.logging.LogEvent("Restart initiated", restartLoggingInfo, LoggingLevel.Information); ShutdownManager.BeginShutdown(ShutdownKind.Restart, DeviceRestartPeriod); return(new MethodResponse(200)); }
private async Task <MethodResponse> DeviceBondAsync(MethodRequest methodRequest, object userContext) { LoggingFields bondLoggingInfo = new LoggingFields(); try { dynamic json = JValue.Parse(methodRequest.DataAsJson); string deviceAddressBcd = json.DeviceAddressBCD; bondLoggingInfo.AddString("DeviceAddressBCD", deviceAddressBcd); Debug.WriteLine($"DeviceBondAsync DeviceAddressBCD {deviceAddressBcd}"); byte[] deviceAddressBytes = deviceAddressBcd.Split('-').Select(x => byte.Parse(x, NumberStyles.HexNumber)).ToArray(); bondLoggingInfo.AddInt32("DeviceAddressBytes Length", deviceAddressBytes.Length); Debug.WriteLine($"DeviceBondAsync DeviceAddressLength {deviceAddressBytes.Length}"); if ((deviceAddressBytes.Length < Rfm9XDevice.AddressLengthMinimum) || (deviceAddressBytes.Length > Rfm9XDevice.AddressLengthMaximum)) { this.logging.LogEvent("DeviceBondAsync failed device address bytes length", bondLoggingInfo, LoggingLevel.Error); return(new MethodResponse(414)); } // Empty payload for bond message byte[] payloadBytes = {}; rfm9XDevice.Send(deviceAddressBytes, payloadBytes); this.logging.LogEvent("DeviceBondAsync success", bondLoggingInfo, LoggingLevel.Information); } catch (Exception ex) { bondLoggingInfo.AddString("Exception", ex.ToString()); this.logging.LogEvent("DeviceBondAsync exception", bondLoggingInfo, LoggingLevel.Error); return(new MethodResponse(400)); } return(new MethodResponse(200)); }
private async void Rfm9XDevice_OnReceive(object sender, Rfm9XDevice.OnDataReceivedEventArgs e) { string addressBcdText; string messageBcdText; string messageText = ""; char[] sensorReadingSeparator = new char[] { ',' }; char[] sensorIdAndValueSeparator = new char[] { ' ' }; addressBcdText = BitConverter.ToString(e.Address); messageBcdText = BitConverter.ToString(e.Data); try { messageText = UTF8Encoding.UTF8.GetString(e.Data); } catch (Exception) { this.logging.LogMessage("Failure converting payload to text", LoggingLevel.Error); return; } #if DEBUG Debug.WriteLine(@"{0:HH:mm:ss}-RX From {1} PacketSnr {2:0.0} Packet RSSI {3}dBm RSSI {4}dBm = {5} byte message ""{6}""", DateTime.Now, addressBcdText, e.PacketSnr, e.PacketRssi, e.Rssi, e.Data.Length, messageText); #endif LoggingFields messagePayload = new LoggingFields(); messagePayload.AddInt32("AddressLength", e.Address.Length); messagePayload.AddString("Address-BCD", addressBcdText); messagePayload.AddInt32("Message-Length", e.Data.Length); messagePayload.AddString("Message-BCD", messageBcdText); messagePayload.AddString("Nessage-Unicode", messageText); messagePayload.AddDouble("Packet SNR", e.PacketSnr); messagePayload.AddInt32("Packet RSSI", e.PacketRssi); messagePayload.AddInt32("RSSI", e.Rssi); this.logging.LogEvent("Message Data", messagePayload, LoggingLevel.Verbose); // Check the address is not to short/long if (e.Address.Length < AddressLengthMinimum) { this.logging.LogMessage("From address too short", LoggingLevel.Warning); return; } if (e.Address.Length > MessageLengthMaximum) { this.logging.LogMessage("From address too long", LoggingLevel.Warning); return; } // Check the payload is not too short/long if (e.Data.Length < MessageLengthMinimum) { this.logging.LogMessage("Message too short to contain any data", LoggingLevel.Warning); return; } if (e.Data.Length > MessageLengthMaximum) { this.logging.LogMessage("Message too long to contain valid data", LoggingLevel.Warning); return; } // Adafruit IO is case sensitive & onlye does lower case ? string deviceId = addressBcdText.ToLower(); // Chop up the CSV text payload string[] sensorReadings = messageText.Split(sensorReadingSeparator, StringSplitOptions.RemoveEmptyEntries); if (sensorReadings.Length == 0) { this.logging.LogMessage("Payload contains no sensor readings", LoggingLevel.Warning); return; } Group_feed_data groupFeedData = new Group_feed_data(); LoggingFields sensorData = new LoggingFields(); sensorData.AddString("DeviceID", deviceId); // Chop up each sensor reading into an ID & value foreach (string sensorReading in sensorReadings) { string[] sensorIdAndValue = sensorReading.Split(sensorIdAndValueSeparator, StringSplitOptions.RemoveEmptyEntries); // Check that there is an id & value if (sensorIdAndValue.Length != 2) { this.logging.LogMessage("Sensor reading invalid format", LoggingLevel.Warning); return; } string sensorId = sensorIdAndValue[0].ToLower(); string value = sensorIdAndValue[1]; // Construct the sensor ID from SensordeviceID & Value ID groupFeedData.Feeds.Add(new Anonymous2() { Key = string.Format("{0}{1}", deviceId, sensorId), Value = value }); sensorData.AddString(sensorId, value); Debug.WriteLine(" Sensor {0}{1} Value {2}", deviceId, sensorId, value); } this.logging.LogEvent("Sensor readings", sensorData, LoggingLevel.Verbose); try { Debug.WriteLine(" CreateGroupDataAsync start"); await this.adaFruitIOClient.CreateGroupDataAsync(this.applicationSettings.AdaFruitIOUserName, this.applicationSettings.AdaFruitIOGroupName.ToLower(), groupFeedData); Debug.WriteLine(" CreateGroupDataAsync finish"); } catch (Exception ex) { Debug.WriteLine(" CreateGroupDataAsync failed {0}", ex.Message); this.logging.LogMessage("CreateGroupDataAsync failed " + ex.Message, LoggingLevel.Error); } }
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(); }
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; } }
public void Run(IBackgroundTaskInstance taskInstance) { StorageFolder localFolder = ApplicationData.Current.LocalFolder; int imageUpdateDueSeconds; int imageUpdatePeriodSeconds; 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(); this.logging.LogMessage("JSON configuration file missing, templated created", LoggingLevel.Warning); return; } IConfiguration configuration = new ConfigurationBuilder().AddJsonFile(Path.Combine(localFolder.Path, ConfigurationFilename), false, true).Build(); localImageFilenameLatestFormat = configuration.GetSection("ImageFilenameFormatLatest").Value; startupInformation.AddString("ImageFilenameLatestFormat", localImageFilenameLatestFormat); localFolderNameHistoryFormat = configuration.GetSection("FolderNameFormatHistory").Value; startupInformation.AddString("ContainerNameHistoryFormat", localFolderNameHistoryFormat); localImageFilenameHistoryFormat = configuration.GetSection("ImageFilenameFormatHistory").Value; startupInformation.AddString("ImageFilenameHistoryFormat", localImageFilenameHistoryFormat); imageUpdateDueSeconds = int.Parse(configuration.GetSection("ImageUpdateDueSeconds").Value); startupInformation.AddInt32("ImageUpdateDueSeconds", imageUpdateDueSeconds); imageUpdatePeriodSeconds = int.Parse(configuration.GetSection("ImageUpdatePeriodSeconds").Value); startupInformation.AddInt32("ImageUpdatePeriodSeconds", imageUpdatePeriodSeconds); } catch (Exception ex) { this.logging.LogMessage("JSON configuration file load or settings retrieval failed " + ex.Message, LoggingLevel.Error); return; } try { mediaCapture = new MediaCapture(); mediaCapture.InitializeAsync().AsTask().Wait(); } catch (Exception ex) { this.logging.LogMessage("Camera configuration failed " + ex.Message, LoggingLevel.Error); return; } ImageUpdatetimer = new Timer(ImageUpdateTimerCallback, null, new TimeSpan(0, 0, imageUpdateDueSeconds), new TimeSpan(0, 0, imageUpdatePeriodSeconds)); this.logging.LogEvent("Application started", startupInformation); //enable task to continue running in background backgroundTaskDeferral = taskInstance.GetDeferral(); }
/// <summary> /// Asynchronously attempts to unlock the document file. /// </summary> /// <remarks> /// Algorithm is as of this writing (11/5/2012): /// 0. Use UTF8 encoding with no BOM. /// 1. Read header. /// 2. Compute SHA256 hash of header. /// 3. Decrypt the rest of the viewModel using header parameters. /// Relies on: /// a. MasterSeed.Length == 32 /// Write masterseed to stream /// b. GenerateKey32(_transformSeed, KeyEncryptionRounds) /// Create raw32 (CreateRawCompositeKey32) /// Concatenate all data and Sha256 /// TransformKey(raw32, _transformSeed, numRounds) /// Init Rijndael: /// 128 bit (16 byte) blocks /// ECB mode /// k = _transformSeed /// For numRounds: /// Transform in place raw32[0:15] /// Transform in place raw32[16:31] /// c. Write 32 bytes of Key32 to stream /// d. aesKey = Sha256 the stream /// e. DecryptStream with aesKey and _encryptionIV /// 4. Verify the first 32 bytes of the decrypted viewModel match up with /// "StreamStartBytes" from the header. /// 5. Read from the decrypted viewModel as a "HashedBlockStream" /// /// File format at the time of this writing (11/5/2012): /// /// 4 bytes: SIG1 /// 4 bytes: SIG2 /// Failure to match these constants results in a parse Result. /// /// 4 bytes: File version /// /// Header fields: /// 1 byte: Field ID /// 2 bytes: Field size (n) /// n bytes: Data /// </remarks> /// <param name="stream">An IRandomAccessStream containing the document to unlock (including the header).</param> /// <param name="rawKey">The aggregate raw key to use for decrypting the database.</param> /// <param name="token">A token allowing the parse to be cancelled.</param> /// <returns>A Task representing the result of the descryiption operation.</returns> public async Task <KdbxDecryptionResult> DecryptFile(IRandomAccessStream stream, IBuffer rawKey, CancellationToken token) { if (HeaderData == null) { throw new InvalidOperationException("Cannot decrypt database before ReadHeader has been called."); } // Init a SHA256 hash buffer and append the master seed to it HashAlgorithmProvider sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256); CryptographicHash hash = sha256.CreateHash(); hash.Append(HeaderData.MasterSeed); this.rawKey = rawKey; this.logger.LogEvent("KdbxReader.GotRawKey", EventVerbosity.Verbose); // Transform the key (this can take a while) IBuffer transformedKey; try { IKdfEngine kdf = HeaderData.KdfParameters.CreateEngine(); LoggingFields fields = new LoggingFields(); fields.AddString("KdfEngine", kdf.GetType().Name); this.logger.LogEvent("KdbxReader.StartingKeyTransform", fields, EventVerbosity.Info); transformedKey = await HeaderData.KdfParameters.CreateEngine().TransformKeyAsync(rawKey, token) .ConfigureAwait(false); if (transformedKey == null) { throw new OperationCanceledException(); } this.logger.LogEvent("KdbxReader.KeyTransformSucceeded", EventVerbosity.Info); } catch (OperationCanceledException) { return(new KdbxDecryptionResult(new ReaderResult(KdbxParserCode.OperationCancelled))); } // In KDBX4, after the header is an HMAC-SHA-256 value computed over the header // allowing validation of header integrity. IBuffer hmacKey = HmacBlockHandler.DeriveHmacKey(transformedKey, HeaderData.MasterSeed); HmacBlockHandler hmacHandler = new HmacBlockHandler(hmacKey); IBuffer expectedMac = null; if (this.parameters.UseInlineHeaderAuthentication) { var algorithm = MacAlgorithmProvider.OpenAlgorithm(MacAlgorithmNames.HmacSha256); CryptographicHash hmacHash = algorithm.CreateHash(hmacHandler.GetKeyForBlock(UInt64.MaxValue)); DebugHelper.Assert(HeaderData.FullHeader != null); hmacHash.Append(HeaderData.FullHeader); expectedMac = hmacHash.GetValueAndReset(); } // Hash transformed k (with the master seed) to get final cipher k hash.Append(transformedKey); IBuffer cipherKey = hash.GetValueAndReset(); this.logger.LogEvent("KdbxReader.GotFinalCipherKey", EventVerbosity.Info); // Decrypt the document starting from the end of the header ulong headerLength = HeaderData.FullHeader.Length; if (this.parameters.UseInlineHeaderAuthentication) { // KDBX4 has a hash at the end of the header headerLength += 32; } stream.Seek(headerLength); if (expectedMac != null) { using (DataReader macReader = GetReaderForStream(stream)) { await macReader.LoadAsync(expectedMac.Length); IBuffer actualMac = macReader.ReadBuffer(expectedMac.Length); for (uint i = 0; i < expectedMac.Length; i++) { if (expectedMac.GetByte(i) != actualMac.GetByte(i)) { this.logger.LogEvent("KdbxReader.HmacFailure", EventVerbosity.Critical); return(new KdbxDecryptionResult(new ReaderResult(KdbxParserCode.CouldNotDecrypt))); } } macReader.DetachStream(); } } IBuffer cipherText; try { cipherText = await GetCipherText(stream, hmacHandler); } catch (FormatException ex) { this.logger.LogEvent("KdbxReader.DataIntegrityFailure", ex.ToLoggingFields(), EventVerbosity.Critical); return(new KdbxDecryptionResult(new ReaderResult(KdbxParserCode.DataIntegrityProblem, ex))); } IBuffer decryptedFile = DecryptDatabaseData(cipherText, cipherKey); if (decryptedFile == null) { this.logger.LogEvent("KdbxReader.DecryptionFailure", EventVerbosity.Critical); return(new KdbxDecryptionResult(new ReaderResult(KdbxParserCode.CouldNotDecrypt))); } this.logger.LogEvent("KdbxReader.DecryptionSucceeded", EventVerbosity.Info); // Verify first 32 bytes of the clear data; if StreamStartBytes wasn't set // (e.g. due to KDBX4), nothing happens here. for (uint i = 0; i < (HeaderData.StreamStartBytes?.Length ?? 0); i++) { byte actualByte = decryptedFile.GetByte(i); byte expectedByte = HeaderData.StreamStartBytes.GetByte(i); if (actualByte != expectedByte) { this.logger.LogEvent("KdbxReader.PlaintextValidationFailure", EventVerbosity.Critical); return(new KdbxDecryptionResult(new ReaderResult(KdbxParserCode.FirstBytesMismatch))); } } this.logger.LogEvent("KdbxReader.PlaintextValidationSucceeded", EventVerbosity.Verbose); IBuffer plainText = await UnhashAndInflate(decryptedFile); if (plainText == null) { return(new KdbxDecryptionResult(new ReaderResult(KdbxParserCode.CouldNotInflate))); } // Update HeaderData with info from the inner header, if relevant if (this.parameters.UseInnerHeader) { using (IRandomAccessStream plainTextStream = plainText.AsStream().AsRandomAccessStream()) { using (DataReader reader = GetReaderForStream(plainTextStream)) { ReaderResult innerHeaderResult = await ReadInnerHeader(reader, HeaderData); if (innerHeaderResult != ReaderResult.Success) { LoggingFields fields = new LoggingFields(); fields.AddInt32("Code", (int)innerHeaderResult.Code); this.logger.LogEvent("KdbxReader.InnerHeaderReadFailure", fields, EventVerbosity.Critical); return(new KdbxDecryptionResult(innerHeaderResult)); } // Update plainText to point to the remainder of the buffer uint bytesRemaining = plainText.Length - (uint)plainTextStream.Position; await reader.LoadAsync(bytesRemaining); plainText = reader.ReadBuffer(bytesRemaining); } } } XDocument finalTree = null; try { finalTree = XDocument.Load(plainText.AsStream()); } catch (XmlException) { return(null); } if (finalTree == null) { return(new KdbxDecryptionResult(new ReaderResult(KdbxParserCode.MalformedXml))); } try { KdbxDocument parsedDocument = await Task.Run(() => new KdbxDocument(finalTree.Root, HeaderData.ProtectedBinaries, HeaderData.GenerateRng(), this.parameters)); // Validate the final parsed header hash before returning if (this.parameters.UseXmlHeaderAuthentication && !String.IsNullOrEmpty(parsedDocument.Metadata.HeaderHash) && parsedDocument.Metadata.HeaderHash != HeaderData.HeaderHash) { return(new KdbxDecryptionResult(new ReaderResult(KdbxParserCode.BadHeaderHash))); } return(new KdbxDecryptionResult(this.parameters, parsedDocument, this.rawKey)); } catch (KdbxParseException e) { return(new KdbxDecryptionResult(e.Error)); } }
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; } }
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.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.faceClient = new FaceClient( new Microsoft.Azure.CognitiveServices.Vision.Face.ApiKeyServiceClientCredentials(this.azureCognitiveServicesSubscriptionKey), new System.Net.Http.DelegatingHandler[] { }) { Endpoint = this.azureCognitiveServicesEndpoint, }; } catch (Exception ex) { this.logging.LogMessage("Azure Cognitive Services Face 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(); }
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; } }
private async Task PayloadCommaSeparatedValues(DeviceClient azureIoTHubClient, Rfm9XDevice.OnDataReceivedEventArgs e) { JObject telemetryDataPoint = new JObject(); LoggingFields processLoggingFields = new LoggingFields(); char[] sensorReadingSeparators = { ',' }; char[] sensorIdAndValueSeparators = { ' ' }; processLoggingFields.AddString("PacketSNR", e.PacketSnr.ToString("F1")); telemetryDataPoint.Add("PacketSNR", e.PacketSnr.ToString("F1")); processLoggingFields.AddInt32("PacketRSSI", e.PacketRssi); telemetryDataPoint.Add("PacketRSSI", e.PacketRssi); processLoggingFields.AddInt32("RSSI", e.Rssi); telemetryDataPoint.Add("RSSI", e.Rssi); string addressBcdText = BitConverter.ToString(e.Address); processLoggingFields.AddInt32("DeviceAddressLength", e.Address.Length); processLoggingFields.AddString("DeviceAddressBCD", addressBcdText); telemetryDataPoint.Add("DeviceAddressBCD", addressBcdText); string messageText; try { messageText = UTF8Encoding.UTF8.GetString(e.Data); processLoggingFields.AddString("MessageText", messageText); } catch (Exception) { this.logging.LogEvent("PayloadProcess failure converting payload to text", processLoggingFields, LoggingLevel.Warning); return; } // Chop up the CSV text string[] sensorReadings = messageText.Split(sensorReadingSeparators, StringSplitOptions.RemoveEmptyEntries); if (sensorReadings.Length < 1) { this.logging.LogEvent("PayloadProcess payload contains no sensor readings", processLoggingFields, LoggingLevel.Warning); return; } // Chop up each sensor read into an ID & value foreach (string sensorReading in sensorReadings) { string[] sensorIdAndValue = sensorReading.Split(sensorIdAndValueSeparators, StringSplitOptions.RemoveEmptyEntries); // Check that there is an id & value if (sensorIdAndValue.Length != 2) { this.logging.LogEvent("PayloadProcess payload invalid format", processLoggingFields, LoggingLevel.Warning); return; } string sensorId = sensorIdAndValue[0].ToLower(); string value = sensorIdAndValue[1]; // Construct the sensor ID from SensordeviceID & Value, mainly intended for Azure IOT Central support if (this.applicationSettings.SensorIDIsDeviceIDSensorID) { sensorId = string.Concat(addressBcdText, sensorId); } try { telemetryDataPoint.Add(sensorId, value); processLoggingFields.AddString(sensorId, value); Debug.WriteLine($" SensorID {sensorId} Value {value}"); } catch (Exception ex) { processLoggingFields.AddString("Exception", ex.ToString()); this.logging.LogEvent("PayloadProcess sensor reading invalid JSON format", processLoggingFields, LoggingLevel.Warning); return; } } 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 JSON payload", processLoggingFields, LoggingLevel.Information); } catch (Exception ex) { processLoggingFields.AddString("Exception", ex.ToString()); this.logging.LogEvent("SendEventAsync JSON payload", processLoggingFields, LoggingLevel.Error); } }
async void IMessageHandler.Rfm9XOnReceive(Rfm9XDevice.OnDataReceivedEventArgs e) { LoggingFields processReceiveLoggingFields = new LoggingFields(); char[] sensorReadingSeparators = { ',' }; char[] sensorIdAndValueSeparators = { ' ' }; processReceiveLoggingFields.AddString("PacketSNR", e.PacketSnr.ToString("F1")); processReceiveLoggingFields.AddInt32("PacketRSSI", e.PacketRssi); processReceiveLoggingFields.AddInt32("RSSI", e.Rssi); string addressBcdText = BitConverter.ToString(e.Address); processReceiveLoggingFields.AddInt32("DeviceAddressLength", e.Address.Length); processReceiveLoggingFields.AddString("DeviceAddressBCD", addressBcdText); string messageText; try { messageText = UTF8Encoding.UTF8.GetString(e.Data); processReceiveLoggingFields.AddString("MessageText", messageText); } catch (Exception ex) { processReceiveLoggingFields.AddString("Exception", ex.ToString()); this.Logging.LogEvent("PayloadProcess failure converting payload to text", processReceiveLoggingFields, LoggingLevel.Warning); return; } // Chop up the CSV text string[] sensorReadings = messageText.Split(sensorReadingSeparators, StringSplitOptions.RemoveEmptyEntries); if (sensorReadings.Length < 1) { this.Logging.LogEvent("PayloadProcess payload contains no sensor readings", processReceiveLoggingFields, LoggingLevel.Warning); return; } JObject payloadJObject = new JObject(); JObject feeds = new JObject(); // Chop up each sensor read into an ID & value foreach (string sensorReading in sensorReadings) { string[] sensorIdAndValue = sensorReading.Split(sensorIdAndValueSeparators, StringSplitOptions.RemoveEmptyEntries); // Check that there is an id & value if (sensorIdAndValue.Length != 2) { this.Logging.LogEvent("PayloadProcess payload invalid format", processReceiveLoggingFields, LoggingLevel.Warning); return; } string sensorId = string.Concat(addressBcdText, sensorIdAndValue[0]); string value = sensorIdAndValue[1]; feeds.Add(sensorId.ToLower(), value); } payloadJObject.Add("feeds", feeds); string topic = $"{MqttClient.Options.Credentials.Username}/groups/{PlatformSpecificConfiguration}"; try { var message = new MqttApplicationMessageBuilder() .WithTopic(topic) .WithPayload(JsonConvert.SerializeObject(payloadJObject)) .WithAtLeastOnceQoS() .Build(); Debug.WriteLine(" {0:HH:mm:ss} MQTT Client PublishAsync start", DateTime.UtcNow); await MqttClient.PublishAsync(message); Debug.WriteLine(" {0:HH:mm:ss} MQTT Client PublishAsync finish", DateTime.UtcNow); this.Logging.LogEvent("PublishAsync Adafruit payload", processReceiveLoggingFields, LoggingLevel.Information); } catch (Exception ex) { processReceiveLoggingFields.AddString("Exception", ex.ToString()); this.Logging.LogEvent("PublishAsync Adafruit payload", processReceiveLoggingFields, LoggingLevel.Error); } }
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}")); // ethernet mac address this.deviceMacAddress = NetworkInterface.GetAllNetworkInterfaces() .Where(i => i.NetworkInterfaceType.ToString().ToLower().Contains("ethernet")) .FirstOrDefault() ?.GetPhysicalAddress().ToString(); // remove unsupported charachers from MacAddress this.deviceMacAddress = this.deviceMacAddress.Replace("-", string.Empty).Replace(" ", string.Empty).Replace(":", string.Empty); startupInformation.AddString("MacAddress", this.deviceMacAddress); 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(); this.logging.LogMessage("JSON configuration file missing, templated created", LoggingLevel.Warning); return; } IConfiguration configuration = new ConfigurationBuilder().AddJsonFile(Path.Combine(localFolder.Path, ConfigurationFilename), false, true).Build(); this.azureStorageConnectionString = configuration.GetSection("AzureStorageConnectionString").Value; startupInformation.AddString("AzureStorageConnectionString", this.azureStorageConnectionString); this.azureStorageContainerNameLatestFormat = configuration.GetSection("AzureContainerNameFormatLatest").Value; startupInformation.AddString("ContainerNameLatestFormat", this.azureStorageContainerNameLatestFormat); this.azureStorageimageFilenameLatestFormat = configuration.GetSection("AzureImageFilenameFormatLatest").Value; startupInformation.AddString("ImageFilenameLatestFormat", this.azureStorageimageFilenameLatestFormat); this.azureStorageContainerNameHistoryFormat = configuration.GetSection("AzureContainerNameFormatHistory").Value; startupInformation.AddString("ContainerNameHistoryFormat", this.azureStorageContainerNameHistoryFormat); this.azureStorageImageFilenameHistoryFormat = configuration.GetSection("AzureImageFilenameFormatHistory").Value; startupInformation.AddString("ImageFilenameHistoryFormat", this.azureStorageImageFilenameHistoryFormat); 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.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.mediaCapture = new MediaCapture(); this.mediaCapture.InitializeAsync().AsTask().Wait(); } catch (Exception ex) { this.logging.LogMessage("Camera configuration failed " + ex.Message, LoggingLevel.Error); return; } try { GpioController gpioController = GpioController.GetDefault(); this.interruptGpioPin = gpioController.OpenPin(this.interruptPinNumber); this.interruptGpioPin.SetDriveMode(GpioPinDriveMode.InputPullUp); this.interruptGpioPin.ValueChanged += this.InterruptGpioPin_ValueChanged; } 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(); }
private async Task <MethodResponse> DevicePushAsync(MethodRequest methodRequest, object userContext) { LoggingFields pushLoggingInfo = new LoggingFields(); this.logging.LogEvent("Push BCD initiated"); try { // Initially use a dynamac maybe use a decorated class in future +flexibility -performance dynamic json = JValue.Parse(methodRequest.DataAsJson); // Prepare the server address bytes for the message header and validate length byte[] serverAddressBytes = Encoding.UTF8.GetBytes(this.applicationSettings.RF24Address); pushLoggingInfo.AddInt32("serverAddressBytes Length", serverAddressBytes.Length); if (serverAddressBytes.Length > MessageAddressLengthMaximum) { this.logging.LogEvent("DevicePushBcdAsync failed server address bytes Length", pushLoggingInfo, LoggingLevel.Error); return(new MethodResponse(400)); } // Convert the device address from the JSON payload to bytes and validate length string deviceAddressBcd = json.DeviceAddress; pushLoggingInfo.AddString("DeviceAddressBCD", deviceAddressBcd); byte[] deviceAddressBytes = deviceAddressBcd.Split('-').Select(x => byte.Parse(x, NumberStyles.HexNumber)).ToArray(); pushLoggingInfo.AddInt32("DeviceAddressBytes Length", deviceAddressBytes.Length); if ((deviceAddressBytes.Length <) || (deviceAddressBytes.Length >)) { this.logging.LogEvent("DevicePushAsync failed device address bytes length", pushLoggingInfo, LoggingLevel.Error); return(new MethodResponse(414)); } string messagedBcd = json.DevicePayload; pushLoggingInfo.AddString("MessageBCD", messagedBcd); byte[] messageBytes = messagedBcd.Split('-').Select(x => byte.Parse(x, NumberStyles.HexNumber)).ToArray(); pushLoggingInfo.AddInt32("MessageBytesLength", messageBytes.Length); Debug.WriteLine($"BondDeviceAsync DeviceAddress:{deviceAddressBcd} Payload:{messagedBcd} ServerAddress:{serverAddressBytes}"); int payloadLength = MessageHeaderLength + deviceAddressBytes.Length + messageBytes.Length; pushLoggingInfo.AddInt32("PayloadLength", payloadLength); if (payloadLength < MessagePayloadLengthMinimum || (payloadLength > MessagePayloadLengthMaximum)) { this.logging.LogEvent("DevicePushBcdAsync failed payload Length", pushLoggingInfo, LoggingLevel.Error); return(new MethodResponse(400)); } // Assemble payload to send to device byte[] payloadBytes = new byte[payloadLength]; payloadBytes[0] = (byte)(((byte)MessagePayloadType.DeviceIdPlusBinaryPayload << 4) | deviceAddressBytes.Length); Array.Copy(serverAddressBytes, 0, payloadBytes, MessageHeaderLength, serverAddressBytes.Length); Array.Copy(messageBytes, 0, payloadBytes, MessageHeaderLength + serverAddressBytes.Length, messageBytes.Length); this.rf24.SendTo(deviceAddressBytes, payloadBytes); this.logging.LogEvent("Device Push BCD data", pushLoggingInfo, LoggingLevel.Information); } catch (Exception ex) { pushLoggingInfo.AddString("Exception", ex.ToString()); this.logging.LogEvent("DevicePushAsync failed exception", pushLoggingInfo, LoggingLevel.Error); return(new MethodResponse(400)); } return(new MethodResponse(200)); }