private static void TransmitTask(Win32Serial.Device device) { // Create write overlapped structure for async operation var overlapped = Win32Serial.Device.CreateOverlapped(); uint numbytes; int i = 1; const uint size = MessageBody.SerialSize; int limit = 15; if (Options.TestCount.HasValue) { limit = Options.TestCount.Value; } while (!Options.Test || i <= limit) { // Come up with a new message var tempData = new MessageBody { Machine = new Machine { Temperature = Rnd.NextDouble() * 100.0, Pressure = Rnd.NextDouble() * 100.0, }, Ambient = new Ambient { Temperature = Rnd.NextDouble() * 100.0, Humidity = Rnd.Next(24, 27) }, Number = i }; // Async write, using overlapped structure var message = tempData.SerialEncode; device.Write(Encoding.ASCII.GetBytes(message), size, out numbytes, ref overlapped); Log.WriteLineVerbose($"Write {i} Started"); // Block until write completes device.GetOverlappedResult(ref overlapped, out numbytes, true); Log.WriteLine($"Write {i} Completed. Wrote {numbytes} bytes: \"{message}\""); i++; Thread.Sleep(1000); } Environment.Exit(0); }
private static async void ReaderTask(SerialPort device) { try { // // Continuously read from serial device // and send those values to edge hub. // int i = 1; while (true) { try { string message = device.ReadLine(); Log.WriteLine($"Read {i} Completed. Received {message.Length} bytes: \"{message}\""); // Translate it into a messagebody if (Options.UseEdge) { var tempData = new MessageBody(); tempData.SerialEncode = message; tempData.TimeCreated = DateTime.Now; if (tempData.isValid) { string dataBuffer = JsonConvert.SerializeObject(tempData); var eventMessage = new Message(Encoding.UTF8.GetBytes(dataBuffer)); Log.WriteLine($"SendEvent: [{dataBuffer}]"); await ioTHubModuleClient.SendEventAsync("temperatureOutput", eventMessage); } } } catch (Exception ex) { Log.WriteLineException(ex); } i++; } } catch (Exception ex) { Log.WriteLineException(ex); } }
private static MessageBody ResultsToMessage(ScoringOutput outcome) { var resultVector = outcome.softmaxout_1.GetAsVectorView(); // Find the top 3 probabilities List <float> topProbabilities = new List <float>() { 0.0f, 0.0f, 0.0f }; List <int> topProbabilityLabelIndexes = new List <int>() { 0, 0, 0 }; // SqueezeNet returns a list of 1000 options, with probabilities for each, loop through all for (int i = 0; i < resultVector.Count(); i++) { // is it one of the top 3? for (int j = 0; j < 3; j++) { if (resultVector[i] > topProbabilities[j]) { topProbabilityLabelIndexes[j] = i; topProbabilities[j] = resultVector[i]; break; } } } var message = new MessageBody(); message.results = new LabelResult[3]; for (int i = 0; i < 3; i++) { message.results[i] = new LabelResult() { label = labels[topProbabilityLabelIndexes[i]], confidence = topProbabilities[i] }; } return(message); }
private static void TransmitTask(Win32Serial.Device device) { // Create write overlapped structure for async operation var overlapped = Win32Serial.Device.CreateOverlapped(); uint numbytes; int i = 1; const uint size = MessageBody.SerialSize; while (true) { Thread.Sleep(1000); // Come up with a new message var tempData = new MessageBody { Machine = new Machine { Temperature = Rnd.NextDouble() * 100.0, Pressure = Rnd.NextDouble() * 100.0, }, Ambient = new Ambient { Temperature = Rnd.NextDouble() * 100.0, Humidity = Rnd.Next(24, 27) }, Number = i }; // Async write, using overlapped structure var message = tempData.SerialEncode; device.Write(Encoding.ASCII.GetBytes(message), size, out numbytes, ref overlapped); Console.WriteLine($"{DateTime.Now.ToLocalTime()} Write {i} Started"); // Block until write completes device.GetOverlappedResult(ref overlapped, out numbytes, true); Console.WriteLine($"{DateTime.Now.ToLocalTime()} Write {i} Completed. Wrote {numbytes} bytes: \"{message}\""); i++; } }
private static void TransmitTask(SerialPort device) { int i = 1; int limit = 5; if (Options.TestCount.HasValue) { limit = Options.TestCount.Value; } while (!Options.Test || i <= limit) { // Come up with a new message var tempData = new MessageBody { Machine = new Machine { Temperature = Rnd.NextDouble() * 100.0, Pressure = Rnd.NextDouble() * 100.0, }, Ambient = new Ambient { Temperature = Rnd.NextDouble() * 100.0, Humidity = Rnd.Next(24, 27) }, Number = i }; // Async write, using overlapped structure var message = tempData.SerialEncode; device.WriteLine(message); Log.WriteLine($"Write {i} Completed. Wrote {message.Length} bytes: \"{message}\""); Thread.Sleep(1000); i++; } Environment.Exit(0); }
static async Task <int> Main(string[] args) { try { // // Parse options // Options = new AppOptions(); Options.Parse(args); if (Options.ShowList) { } if (Options.Exit) { return(-1); } if (string.IsNullOrEmpty(Options.FileName)) { throw new ApplicationException("Please use --file to specify which file to use"); } // // Init module client // if (Options.UseEdge) { Log.WriteLine($"{AppOptions.AppName} module starting."); await BlockTimer("Initializing Azure IoT Edge", async() => await InitEdge()); } cts = new CancellationTokenSource(); AssemblyLoadContext.Default.Unloading += (ctx) => cts.Cancel(); Console.CancelKeyPress += (sender, cpe) => cts.Cancel(); // // Load model // MLModel model = null; Console.WriteLine($"Loading model from: '{Options.ModelPath}', Exists: '{File.Exists(Options.ModelPath)}'"); await BlockTimer($"Loading modelfile '{Options.ModelPath}' on the {(Options.UseGpu ? "GPU" : "CPU")}", async() => { var d = Directory.GetCurrentDirectory(); var path = d + "\\" + Options.ModelPath; StorageFile modelFile = await AsAsync(StorageFile.GetFileFromPathAsync(path)); model = await MLModel.CreateFromStreamAsync(modelFile); }); do { // // Open file // var rows = new List <DataRow>(); try { using (var fs = new StreamReader(Options.FileName)) { // I just need this one line to load the records from the file in my List<CsvLine> rows = new CsvHelper.CsvReader(fs).GetRecords <DataRow>().ToList(); Console.WriteLine($"Loaded {rows.Count} row(s)"); } } catch (Exception e) { Console.WriteLine(e); } Console.WriteLine(rows); // // Main loop // foreach (var row in rows) { // // Evaluate model // var inputShape = new long[2] { 1, 4 }; var inputFeatures = new float[4] { row.Temperature, row.Pressure, row.Humidity, row.ExternalTemperature }; MLModelVariable result = null; var evalticks = await BlockTimer("Running the model", async() => { result = await model.EvaluateAsync(new MLModelVariable() { Variable = TensorFloat.CreateFromArray(inputShape, inputFeatures) }); }); // // Print results // var message = new MessageBody { result = result.Variable.GetAsVectorView().First() }; message.metrics.evaltimeinms = evalticks; var json = JsonConvert.SerializeObject(message); Log.WriteLineRaw($"Recognized {json}"); // // Send results to Edge // if (Options.UseEdge) { var eventMessage = new Message(Encoding.UTF8.GetBytes(json)); await ioTHubModuleClient.SendEventAsync("resultsOutput", eventMessage); // Let's not totally spam Edge :) await Task.Delay(500); } Console.WriteLine("Waiting 1 second..."); Thread.Sleep(1000); } }while (Options.RunForever && !cts.Token.IsCancellationRequested); } catch (Exception ex) { Console.WriteLine(ex); return(-1); } return(0); }
static async Task Main(string[] args) { try { // // Parse options // Options = new AppOptions(); Options.Parse(args); if (Options.Exit) { return; } // // Open Device // using (var device = await Si7021.Open()) { if (null == device) { throw new ApplicationException($"Unable to open sensor. Please ensure that no other applications are using this device."); } // // Dump device info // Log.WriteLineRaw($"Model: {device.Model}"); Log.WriteLineRaw($"Serial Number: {device.SerialNumber}"); Log.WriteLineRaw($"Firmware Rev: {device.FirmwareRevision}"); // // Init module client // if (Options.UseEdge) { Init().Wait(); } // // Launch background thread to obtain readings // var background = Task.Run(async() => { while (true) { device.Update(); var message = new MessageBody(); message.Ambient.Temperature = device.Temperature; message.Ambient.Humidity = device.Humidity; message.TimeCreated = DateTime.Now; string dataBuffer = JsonConvert.SerializeObject(message); var eventMessage = new Message(Encoding.UTF8.GetBytes(dataBuffer)); Log.WriteLineRaw($"SendEvent: [{dataBuffer}]"); if (Options.UseEdge) { await ioTHubModuleClient.SendEventAsync("temperatureOutput", eventMessage); } await Task.Delay(1000); } }); // // Wait until the app unloads or is cancelled // var cts = new CancellationTokenSource(); AssemblyLoadContext.Default.Unloading += (ctx) => cts.Cancel(); Console.CancelKeyPress += (sender, cpe) => cts.Cancel(); WhenCancelled(cts.Token).Wait(); } } catch (Exception ex) { Log.WriteLineException(ex); } }
/// <summary> /// Module behavior: /// Sends data periodically (with default frequency of 5 seconds). /// Data trend: /// - Machine Temperature regularly rises from 21C to 100C in regularly with jitter /// - Machine Pressure correlates with Temperature 1 to 10psi /// - Ambient temperature stable around 21C /// - Humidity is stable with tiny jitter around 25% /// Method for resetting the data stream /// </summary> static async Task SendEvents( ModuleClient moduleClient, int messageCount, SimulatorParameters sim, CancellationTokenSource cts) { int count = 1; double currentTemp = sim.TempMin; double normal = (sim.PressureMax - sim.PressureMin) / (sim.TempMax - sim.TempMin); while (!cts.Token.IsCancellationRequested && (SendUnlimitedMessages(messageCount) || messageCount >= count)) { if (Reset) { currentTemp = sim.TempMin; Reset.Set(false); } if (currentTemp > sim.TempMax) { currentTemp += Rnd.NextDouble() - 0.5; // add value between [-0.5..0.5] } else { currentTemp += -0.25 + (Rnd.NextDouble() * 1.5); // add value between [-0.25..1.25] - average +0.5 } if (sendData) { var events = new List <MessageEvent> (); // Add Desired Number of Events into the Message for (int i = 0; i < eventCount; i++) { events.Add(new MessageEvent { DeviceId = Environment.GetEnvironmentVariable("DEVICE") ?? Environment.MachineName, TimeStamp = DateTime.UtcNow, Temperature = new SensorReading { Value = currentTemp, Units = "degC", Status = 200 }, Pressure = new SensorReading { Value = sim.PressureMin + ((currentTemp - sim.TempMin) * normal), Units = "psig", Status = 200 }, SuctionPressure = new SensorReading { Value = sim.PressureMin + 4 + ((currentTemp - sim.TempMin) * normal), Units = "psig", Status = 200 }, DischargePressure = new SensorReading { Value = sim.PressureMin + 1 + ((currentTemp - sim.TempMin) * normal), Units = "psig", Status = 200 }, Flow = new SensorReading { Value = Rnd.Next(78, 82), Units = "perc", Status = 200 } }); currentTemp += -0.25 + (Rnd.NextDouble() * 1.5); } var msgBody = new MessageBody { Asset = Environment.GetEnvironmentVariable("ASSET") ?? "whidbey", Source = Environment.MachineName, Events = events }; string dataBuffer = JsonConvert.SerializeObject(msgBody); var eventMessage = new Message(Encoding.UTF8.GetBytes(dataBuffer)); eventMessage.Properties.Add("sequenceNumber", count.ToString()); eventMessage.Properties.Add("batchId", BatchId.ToString()); Console.WriteLine($"\t{DateTime.Now.ToLocalTime()}> Sending message: {count}, Body: [{dataBuffer}]"); await moduleClient.SendEventAsync("temperatureOutput", eventMessage); count++; } await Task.Delay(messageDelay, cts.Token); } if (messageCount < count) { Console.WriteLine($"Done sending {messageCount} messages"); } }
private static void UpdateWebServerPayloads(MessageBody message, byte[] data, byte[] annotatedData) { try { ResultPayload payload = new ResultPayload() { Result = message }; string summaryText = "-"; if ((message.results != null) && (message.metrics != null)) { long totalEvaluations = _stats.TotalEvaluationSuccessCount; double confidence = 0.0; string lastLabel = ""; _stats.TotalEvaluationSuccessCount = _stats.TotalEvaluationSuccessCount + 1; if (message.results.Length > 0) { summaryText = $"Matched : {message.results[0].label} - Confidence ={message.results[0].confidence.ToString("P")} - Eval Time {message.metrics.evaltimeinms} ms"; confidence = message.results[0].confidence; lastLabel = message.results[0].label; } else { summaryText = $"No Match - Eval Time {message.metrics.evaltimeinms} ms"; } //update eval ms stats try { if (totalEvaluations > 0) { _stats.AverageEvaluationMs = ((_stats.AverageEvaluationMs * ((double)totalEvaluations) + ((double)message.metrics.evaltimeinms)) / ((double)totalEvaluations + 1)); } else { _stats.AverageEvaluationMs = (double)message.metrics.evaltimeinms; } } catch (Exception) { } //update match totals try { if (lastLabel != "") { if (totalEvaluations > 0) { _stats.AverageConfidence = ((_stats.AverageConfidence * ((double)totalEvaluations) + ((double)confidence)) / ((double)totalEvaluations + 1)); } else { _stats.AverageConfidence = (double)confidence; } lock (_objLock) { LabelSummary ls = _stats.MatchSummary.FirstOrDefault(o => o.Label == lastLabel); if (ls == null) { ls = new LabelSummary() { Label = lastLabel, TotalMatches = 1 }; _stats.MatchSummary.Add(ls); } else { ls.TotalMatches = ls.TotalMatches + 1; } } } } catch (Exception) { } } else if (message.metrics == null) { _stats.TotalEvaluationFailCount = _stats.TotalEvaluationFailCount + 1; summaryText = $"Evaluation Failed"; } else { _stats.TotalEvaluationSuccessCount = _stats.TotalEvaluationSuccessCount + 1; summaryText = $"No Match - Eval Time {message.metrics.evaltimeinms} ms"; } payload.Statistics = _stats; if ((data != null) && (annotatedData != null)) { payload.ImageSnapshot = Convert.ToBase64String(data); SetLatestFrameData(JsonConvert.SerializeObject(payload), JsonConvert.SerializeObject(_stats), annotatedData); } } catch (Exception e) { Log.WriteLineRaw($"Failed to create Result Payload : {e.Message}"); } }
static async Task <int> Main(string[] args) { try { // // Parse options // Options = new AppOptions(); Options.Parse(args); if (Options.ShowList) { var devices = await FrameSource.GetSourceNamesAsync(); Log.WriteLine("Available cameras:"); foreach (var device in devices) { Log.WriteLine(device); } } if (Options.Exit) { return(-1); } if (!Options.UseImages) { if (string.IsNullOrEmpty(Options.DeviceId)) { throw new ApplicationException("Please use --device to specify which camera to use"); } } try { string sv = AnalyticsInfo.VersionInfo.DeviceFamilyVersion; ulong v = ulong.Parse(sv); ulong v1 = (v & 0xFFFF000000000000L) >> 48; ulong v2 = (v & 0x0000FFFF00000000L) >> 32; ulong v3 = (v & 0x00000000FFFF0000L) >> 16; ulong v4 = (v & 0x000000000000FFFFL); var systemVersion = $"{v1}.{v2}.{v3}.{v4}"; _stats.CurrentVideoDeviceId = Options.DeviceId; _stats.Platform = $"{AnalyticsInfo.VersionInfo.DeviceFamily} - {System.Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE") ?? "Unknown"} - {systemVersion}"; } catch (Exception) { } // // Init module client // if (Options.UseEdge) { Log.WriteLine($"{AppOptions.AppName} module starting."); await BlockTimer("Initializing Azure IoT Edge", async() => await InitEdge()); } cts = new CancellationTokenSource(); AssemblyLoadContext.Default.Unloading += (ctx) => cts.Cancel(); Console.CancelKeyPress += (sender, cpe) => cts.Cancel(); // // Load model // ScoringModel model = null; await BlockTimer($"Loading modelfile '{Options.ModelPath}' on the {(Options.UseGpu ? "GPU" : "CPU")}", async() => { var d = Directory.GetCurrentDirectory(); var path = d + "\\" + Options.ModelPath; StorageFile modelFile = await AsAsync(StorageFile.GetFileFromPathAsync(path)); model = await ScoringModel.CreateFromStreamAsync(modelFile, Options.UseGpu); }); _stats.OnnxModelLoaded = true; _stats.CurrentOnnxModel = Options.ModelPath; _stats.IsGpu = Options.UseGpu; // WebServer Code HttpServer httpsv = null; bool HttpServerStarted = false; if (Options.RunForever) { try { Log.WriteLine($"Start HTTP Server on port : " + Options.WebServerPort.ToString()); httpsv = new HttpServer(Options.WebServerPort); httpsv.Start(); httpsv.OnGet += HttpsvOnOnGet; HttpServerStarted = true; Log.WriteLine($"- HTTP Server Started."); Log.WriteLine($""); } catch (Exception e) { HttpServerStarted = false; Log.WriteLine($"Exiting - Websockets Server Failed to start : " + e.Message); } } // // Open camera // FrameSource frameSource = null; ImageFileSource imageFileSource = null; if (Options.UseImages) { imageFileSource = new ImageFileSource(); imageFileSource.ScanUpdateQueue(Options.ImagePath); } else { frameSource = new FrameSource(); await frameSource.StartAsync(Options.DeviceId, Options.UseGpu); } _stats.DeviceInitialized = true; SetLatestStatsPayload(JsonConvert.SerializeObject(_stats)); // // Main loop // do { ScoringOutput outcome = null; int evalticks = 0; Log.WriteLineVerbose("Getting frame..."); byte[] data = new byte[] { }; byte[] annotatedData = new byte[] { }; MessageBody message = null; // // Use Image File Source or fall back to Webcam Source if not specified // if (Options.UseImages) { var(fileName, sbmp) = await imageFileSource.GetNextImageAsync(Options.ImagePath, cts.Token); using (var vf = VideoFrame.CreateWithSoftwareBitmap(sbmp)) { ImageFeatureValue imageTensor = ImageFeatureValue.CreateFromVideoFrame(vf); _stats.TotalFrames = _stats.TotalFrames + 1; // // Evaluate model // var ticksTaken = await BlockTimer($"Running the model", async() => { var input = new ScoringInput() { data = imageTensor }; outcome = await model.EvaluateAsync(input); }); evalticks = ticksTaken; message = ResultsToMessage(outcome); message.metrics.evaltimeinms = evalticks; _stats.TotalEvaluations = _stats.TotalEvaluations + 1; message.imgSrc = fileName; string summaryText = ""; if (message.results.Length > 0) { summaryText = $"Matched : {message.results[0].label} - Confidence ={message.results[0].confidence.ToString("P")} - Eval Time {message.metrics.evaltimeinms} ms"; } data = await ImageUtils.GetConvertedImage(sbmp); annotatedData = await ImageUtils.AnnotateImage(sbmp, $"Current Image : {fileName ?? "-"}", summaryText); } } else { using (var frame = await frameSource.GetFrameAsync()) { var inputImage = frame.VideoMediaFrame.GetVideoFrame(); ImageFeatureValue imageTensor = ImageFeatureValue.CreateFromVideoFrame(inputImage); _stats.TotalFrames = _stats.TotalFrames + 1; // // Evaluate model // var ticksTaken = await BlockTimer("Running the model", async() => { var input = new ScoringInput() { data = imageTensor }; outcome = await model.EvaluateAsync(input); }); evalticks = ticksTaken; message = ResultsToMessage(outcome); message.metrics.evaltimeinms = evalticks; _stats.TotalEvaluations = _stats.TotalEvaluations + 1; string summaryText = ""; if (message.results.Length > 0) { summaryText = $"Matched : {message.results[0].label} - Confidence ={message.results[0].confidence.ToString("P")} - Eval Time {message.metrics.evaltimeinms} ms"; } data = await ImageUtils.GetConvertedImage(inputImage.SoftwareBitmap); annotatedData = await ImageUtils.AnnotateImage(inputImage.SoftwareBitmap, $"Current Webcam : {Options.DeviceId ?? "-"}", summaryText); } } if (message != null) { // // Print results // message.metrics.evaltimeinms = evalticks; var json = JsonConvert.SerializeObject(message, new JsonSerializerSettings { //won't print null imgSrc if null NullValueHandling = NullValueHandling.Ignore }); Log.WriteLineRaw($"Inferenced: {json}"); if (Options.UseWebServer) { // // Update the latest webserver payload snapshots with data from inferencing // UpdateWebServerPayloads(message, data, annotatedData); } // // Send results to Edge // if (Options.UseEdge) { var eventMessage = new Message(Encoding.UTF8.GetBytes(json)); await ioTHubModuleClient.SendEventAsync("resultsOutput", eventMessage); // Let's not totally spam Edge :) await Task.Delay(500); } else if (Options.UseImages) { //slow it down a little.. await Task.Delay(TimeSpan.FromSeconds(5)); } } }while (Options.RunForever && !cts.Token.IsCancellationRequested); if (frameSource != null) { await frameSource.StopAsync(); } if (HttpServerStarted) { try { Log.WriteLine($"- Stopping Web Server."); httpsv.OnGet -= HttpsvOnOnGet; httpsv.Stop(); httpsv = null; Log.WriteLine($"- Web Server Stopped."); } catch (Exception) { } } return(0); } catch (Exception ex) { Log.WriteLineException(ex); return(-1); } }