private async static void ReceiveFeedbackAsync() { var db = new IsmIoTPortalContext(); while (true) { var feedbackBatch = await feedbackReceiver.ReceiveAsync(); if (feedbackBatch == null) { continue; } // foreach (FeedbackRecord record in feedbackBatch.Records) { // https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-devguide-messaging#cloud-to-device-messages // Message is always success, because MQTT clients can't reject C2D Messages switch (record.OriginalMessageId.Substring(0, 3)) // Substring(0, 3) is the MessageIdPrefix { // CMD case MessageIdPrefix.CMD: await Task.Factory.StartNew(() => ProcessCmdMessage(record)); break; default: break; } } await feedbackReceiver.CompleteAsync(feedbackBatch); } }
private void UpdateFirmwareUpdateStatus(UpdateState updateState) { using (IsmIoTPortalContext db = new IsmIoTPortalContext()) { // Get reference to device string deviceId = updateState.DeviceId; var device = db.IsmDevices.FirstOrDefault(d => d.DeviceId.Equals(deviceId)); if (device == null) { this.OnLogMessage(new LogMessageEventArgs(String.Format("{0} > UpdateFirmwareUpdateStatus Error: DeviceId unknown.<br>", DateTime.Now.ToString()))); return; } // Check update status for error if (updateState.FwUpdateStatus.Contains("Error")) { device.UpdateStatus = updateState.FwUpdateStatus; } else { device.UpdateStatus = IsmIoTSettings.UpdateStatus.READY; } // Get reference to release var release = db.Releases.FirstOrDefault(r => r.Name.Equals(updateState.Version)); if (release == null) { this.OnLogMessage(new LogMessageEventArgs(String.Format("{0} > UpdateFirmwareUpdateStatus Error: Release unknown.<br>", DateTime.Now.ToString()))); db.SaveChanges(); return; } device.UpdateMessage = updateState.Message; var updateLog = new UpdateLog { IsmDeviceId = device.IsmDeviceId, ReleaseId = release.SoftwareId, LogData = updateState.Log, Date = DateTime.Now }; db.UpdateLogs.Add(updateLog); device.SoftwareId = release.SoftwareId; db.SaveChanges(); this.OnLogMessage(new LogMessageEventArgs(String.Format("{0} > UpdateFirmwareUpdateStatus Info: Update Log: {1} <br>", DateTime.Now.ToString(), updateState.Log))); } }
/* * In the Changed event, RoleEnvironment.CurrentRoleInstance.Role.Instances returns the target role instances, * not the original role instances. If you need to know about the original instances, * you can save this information when the Changing event fires and access it from the Changed event * (since these events are always fired in sequence). */ private void RoleEnvironmentChanged(object sender, RoleEnvironmentChangedEventArgs e) { targetNumOfInstances = RoleEnvironment.CurrentRoleInstance.Role.Instances.Count; Logfile.Get(logfile).fTextout(Logging.Fontcolors.RED, "{0} > RoleEnvironmentChanged Eventhandler logging target instance count of {1} <br>", DateTime.Now.ToString(), targetNumOfInstances); Logfile.Get(logfile).Update(); // The change is a downscale! Delete Mcr flag entry from db if (originalNumOfInstances > targetNumOfInstances) { using (IsmIoTPortalContext db = new IsmIoTPortalContext()) { try { // The highest role instance id was determined in the changing event ImagingProcessorWorkerInstance entry = null; var queryResults = db.ImagingProcessorWorkerInstances.Where(en => en.RoleInstanceId == highestRoleInstanceId); if (queryResults.Count() > 0) { entry = queryResults.First(); } if (lowestRoleInstanceId) // The role instance with the lowest id deletes the db entry in case of downscale. { Logfile.Get(logfile).fTextout(Logging.Fontcolors.RED, "{0} > Delete database entry with key {1} <br>", DateTime.Now.ToString(), highestRoleInstanceId); Logfile.Get(logfile).Update(); // Delete entry from DB db.ImagingProcessorWorkerInstances.Remove(entry); db.SaveChanges(); } } catch (Exception ex) { Logfile.Get(logfile).fTextout(Logging.Fontcolors.RED, "{0} > Failed to delete McrInstalled flag DB entry. <br>", DateTime.Now.ToString()); Logfile.Get(logfile).fTextout(Logging.Fontcolors.RED, "{0} > Exception: {1} <br>", DateTime.Now.ToString(), ex.Message); Logfile.Get(logfile).Update(); throw; } } } }
private static async Task ProcessCmdMessage(FeedbackRecord record) { using (var db = new IsmIoTPortalContext()) { // Achtung .Substring(4), weil die ersten 3 Zeichen das Präfix "CMD" sind int CommandId = Convert.ToInt32(record.OriginalMessageId.Substring(4)); // Beim Senden des Commands wurde der Schlüssel des DB Eintrages als MessageId angegeben var entry = db.Commands.Where(c => c.CommandId == CommandId).First(); // Es gibt natürlich nur ein DB Eintrag mit dem Schlüssel CommandId if (record.StatusCode == FeedbackStatusCode.Success) { db.Entry(entry).Entity.CommandStatus = CommandStatus.SUCCESS; } else // Rejected,... { db.Entry(entry).Entity.CommandStatus = CommandStatus.FAILURE; } db.Entry(entry).State = EntityState.Modified; db.SaveChanges(); await signalRHelper.IsmDevicesIndexChangedTask(); } }
private void ProcessImage(DeviceSettings DeviceSettings) { try { // MWArray[] argsIn = new MWArray[6]; string blobname = DeviceSettings.CurrentCaptureName; argsIn[0] = GetBlobSasUri(blobname); // Path / Uri of the image (with Shared Access Signature for MATLAB) argsIn[1] = DeviceSettings.VarianceThreshold; //var_thresh = 0.0025; % variance threshold argsIn[2] = DeviceSettings.DistanceMapThreshold; //dist_thresh = 8.5; % distance - map threshold argsIn[3] = DeviceSettings.RGThreshold; //RG_thresh = 3.75; % R.R.G.threshold argsIn[4] = DeviceSettings.RestrictedFillingThreshold; //fill_area = 4; % Restricted filling threshold argsIn[5] = DeviceSettings.DilateValue; // dilate_value = 16; % Size of square SE used for dilation of dist.- map mask MWArray[] argsOut = new MWArray[3]; // [TEFL, real_length, img_colored] FilamentDetection filamentDetection = new FilamentDetection(); filamentDetection.new_detectFilaments(3, ref argsOut, argsIn); // MATLAB call // double fl = (double)((MWNumericArray)argsOut[0]); // FL (TEFL) double[] single_lengths; if (((MWNumericArray)argsOut[1]).IsEmpty) { single_lengths = new double[] { } } ; else { single_lengths = (double[])((MWNumericArray)argsOut[1]).ToVector(MWArrayComponent.Real); // TODO: NullReference checks } int h1 = 0, h2 = 0, h3 = 0, h4 = 0, h5 = 0, h6 = 0, h7 = 0, h8 = 0, h9 = 0, h10 = 0; for (int i = 0; i < single_lengths.Length; i++) { switch (GetInterval(single_lengths[i])) { case 0: h1++; break; case 1: h2++; break; case 2: h3++; break; case 3: h4++; break; case 4: h5++; break; case 5: h6++; break; case 6: h7++; break; case 7: h8++; break; case 8: h9++; break; case 9: h10++; break; default: break; } } double fc = single_lengths.Length; // FC // colored image CloudBlockBlob blob; string coloredImage = argsOut[2].ToString(); using (System.IO.FileStream fs = new System.IO.FileStream(coloredImage, System.IO.FileMode.Open)) { blob = GenerateBlobAsync().Result; fs.Position = 0; blob.UploadFromStream(fs); } File.Delete(coloredImage); // using (IsmIoTPortalContext db = new IsmIoTPortalContext()) { /* * IsmDeviceId ist Foreign-Key von FilamentData zu IsmDevice */ int id = db.IsmDevices.Where(d => d.DeviceId == DeviceSettings.DeviceId).First().IsmDeviceId; IsmIoTPortal.Models.FilamentData fildata = new IsmIoTPortal.Models.FilamentData(fc, fl, id, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, DeviceSettings.DeviceId, DeviceSettings.CurrentCaptureName, blob.Name); // 1.) Sende in Queue für DashboardBroker // FilamentData ist [DataContract], somit sind die Objekte mit DataContractSerializer serialisierbar var queueMessage = new BrokeredMessage(fildata); queueMessage.Label = IsmIoTPortal.CommandType.PRV; // BrokeredMessage.Label reicht aus um Nachrichtentyp festzulegen // CapturePeriod als Information für DashboardBroker mitsenden. queueMessage.Properties.Add(new KeyValuePair <string, object>("capturePeriod", DeviceSettings.CapturePeriod)); queueClient.SendAsync(queueMessage).Wait(); /* * // 1.) Sende Daten an Dashboards * signalRHubProxy.Invoke<string>("DataForDashboard", fildata.DeviceId, fildata.BlobUriImg, fildata.FC.ToString(), fildata.FL.ToString(), fildata.BlobUriColoredImg).ContinueWith(t => * { * //Console.WriteLine(t.Result); * this.OnLogMessage(new LogMessageEventArgs(String.Format("{0} > Send Filament Data to Dashboard <br>BlobUriimg: {1}", DateTime.Now.ToString(), fildata.BlobUriImg))); * }); */ // 2.) Bei DAT sende die Daten in EventHub, bei PRV nicht if (DeviceSettings.StateName == IsmIoTPortal.DeviceStates.RUN_STATE) { ForwaredFilamentDataToEventHub(fildata); } } } catch (Exception ex) { this.OnLogMessage(new LogMessageEventArgs(String.Format("{0} > ProcessImage Exception: {1} <br>", DateTime.Now.ToString(), ex.Message))); } }
private async Task RunAsync(CancellationToken cancellationToken) { // 1. Check if this is after restart and "MCR is installed" already // bool mcrAlreadyInstalled = false; string line = ""; try { using (IsmIoTPortalContext db = new IsmIoTPortalContext()) { ImagingProcessorWorkerInstance entry = null; var queryResults = db.ImagingProcessorWorkerInstances.Where(e => e.RoleInstanceId == RoleEnvironment.CurrentRoleInstance.Id); if (queryResults.Count() > 0) { entry = queryResults.First(); // Es gibt natürlich nur ein DB Eintrag mit dem Schlüssel RoleInstanceId } if (entry == null) // First start of this Instance -> Create and add new DB entry { // entry = new ImagingProcessorWorkerInstance(); entry.RoleInstanceId = RoleEnvironment.CurrentRoleInstance.Id; entry.McrInstalled = false; entry.Timestamp = DateTime.UtcNow; db.ImagingProcessorWorkerInstances.Add(entry); db.SaveChanges(); // mcrAlreadyInstalled is still false } else { if (entry.McrInstalled == true) { mcrAlreadyInstalled = true; } } } } catch (Exception ex) { Logfile.Get(logfile).fTextout(Logging.Fontcolors.RED, "{0} > Failed to use McrInstalled flag. <br>", DateTime.Now.ToString()); Logfile.Get(logfile).fTextout(Logging.Fontcolors.RED, "{0} > Exception: {1} <br>", DateTime.Now.ToString(), ex.Message); Logfile.Get(logfile).Update(); mcrAlreadyInstalled = false; } // *************DEBUG***************** mcrAlreadyInstalled = true; // DEBUG // 2. Poll the MCR Installation Log if mcrAlreadyInstalled == false // Stopwatch stopWatch = new Stopwatch(); bool timeout = false; stopWatch.Start(); while (!mcrAlreadyInstalled && true) { try { // Timeout if (stopWatch.Elapsed > TimeSpan.FromMinutes(30)) { timeout = true; break; } // Sleep await Task.Delay(TimeSpan.FromMinutes(5)); if (!File.Exists(mcrlog)) { continue; } line = File.ReadLines(mcrlog).Last(); if (!line.Contains("End - Successful")) { continue; } else { break; } } catch (Exception ex) { // Probably file reading errors because the MCR installer uses the file continue; } } // // MCR is installed now -->Set the flag in DB and Reboot if (!mcrAlreadyInstalled && timeout == false) { try { using (IsmIoTPortalContext db = new IsmIoTPortalContext()) { // Update DB entry and set the McrInstalled Flag to true var entry = db.ImagingProcessorWorkerInstances.Where(e => e.RoleInstanceId == RoleEnvironment.CurrentRoleInstance.Id).First(); // // Es gibt natürlich nur ein DB Eintrag mit dem Schlüssel RoleInstanceId db.Entry(entry).Entity.McrInstalled = true; db.Entry(entry).Entity.Timestamp = DateTime.UtcNow; db.Entry(entry).State = EntityState.Modified; db.SaveChanges(); // Restart Worker Role // Update: Der User nach dem Startup Task darf wohl kein shuttdown ausführen --> benutze schtasks //string stat = ExecuteCommandSync("shutdown /R /F"); // Mit schtasks DateTime executionTime = DateTime.Now.Add(new TimeSpan(0, 1, 0)); string date = string.Format("{0}/{1}/{2}", executionTime.Month.ToString("d2"), executionTime.Day.ToString("d2"), executionTime.Year); string time = string.Format("{0}:{1}", executionTime.Hour.ToString("d2"), executionTime.Minute.ToString("d2")); string cmd = string.Format("schtasks /CREATE /TN RebootRoleInstance /SC ONCE /SD {0} /ST {1} /RL HIGHEST /RU scheduser /RP Qwer123 /TR \"shutdown /R /F\" /F", date, time); string stat = ExecuteCommandSync(cmd); Logfile.Get(logfile).fTextout(Logging.Fontcolors.RED, "{0} > {1} <br>", DateTime.Now.ToString(), stat); Logfile.Get(logfile).Update(); } } catch (Exception ex) { Logfile.Get(logfile).fTextout(Logging.Fontcolors.RED, "{0} > Failed writing to update McrInstalled flag and reboot. <br>", DateTime.Now.ToString()); Logfile.Get(logfile).fTextout(Logging.Fontcolors.RED, "{0} > Exception: {1} <br>", DateTime.Now.ToString(), ex.Message); Logfile.Get(logfile).Update(); } } // Timeout --> Write to log and do Not start Event Processor if (!mcrAlreadyInstalled && timeout == true) { Logfile.Get(logfile).fTextout(Logging.Fontcolors.RED, "{0} > Timeout occured during MCR Installation Polling. <br>", DateTime.Now.ToString()); Logfile.Get(logfile).Update(); } // Reboot and MCR is already installed --> Start Event Processor if (mcrAlreadyInstalled) { // // Create EventProcessorHost /*the iotHubD2cEndpoint in the example is the name of the device-to - cloud endpoint on your IoT hub. * Technically, and IoT hub could have multiple endpoints that are compatible with Event Hubs. * At this time the only Event Hubs - compatible endpoint is called "messages/events", so it is a fixed string. */ string iotHubD2cEndpoint = "messages/events"; string eventHubName = CloudConfigurationManager.GetSetting("iotHubName"); //"IsmIoTHub"; string consumerGroupName = EventHubConsumerGroup.DefaultGroupName; // Alternativ geht auch CurrentRoleInstance.Id (ist auch unique) //string eventProcessorHostName = Guid.NewGuid().ToString(); string eventProcessorHostName = RoleEnvironment.CurrentRoleInstance.Id; // leaseContainerName-Parameter wie im scaled out event processing beispiel: // here it's using eventhub as lease name. but it can be specified as any you want. // if the host is having same lease name, it will be shared between hosts. // by default it is using eventhub name as lease name. eventProcessorHost = new EventProcessorHost(eventProcessorHostName, iotHubD2cEndpoint, // eigentlich steht hier der EventHub Name aber siehe Kommentar, bei IoTHubs ist hier der fixe string "messages/events" notwendig consumerGroupName, //iotHubConnectionString, CloudConfigurationManager.GetSetting("ismiothub"), //System.Configuration.ConfigurationSettings.AppSettings.Get("ismiothub"), //EventProcessor.StorageConnectionString, CloudConfigurationManager.GetSetting("ismiotstorage"), //System.Configuration.ConfigurationSettings.AppSettings.Get("ismiotstorage"), eventHubName.ToLowerInvariant()); factory = new EventProcessorFactory(logfile); await eventProcessorHost.RegisterEventProcessorFactoryAsync(factory); // Register EventProcessorHost Logfile.Get(logfile).fTextout("{0} > Registering EventProcessor... <br>", DateTime.Now.ToString()); Logfile.Get(logfile).Update(); // Ansatz ohne Factory. Hatte jedoch den Nachteil, dass man keine Referenz auf das EventProcessor Objekt // hat und somit z.B. keine Eventhandler registrieren konnte. Parameter an Konstruktor gigen ja auch nicht, // weil dieser niemals sichtbar aufgerufen wird bei dem Ansatz //eventProcessorHost.RegisterEventProcessorAsync<EventProcessor>().Wait(); } while (!cancellationToken.IsCancellationRequested) { await Task.Delay(TimeSpan.FromHours(1), cancellationToken); } }
/// <summary> /// Creates a new firmware update ready to be rolled out. Call asynchronously because it can take some time. Don't use await. /// </summary> /// <param name="file">File of firmware update. Must be a tar.</param> /// <param name="location">Directory of where file will be stored on server.</param> /// <param name="id">Key of software version in databse.</param> /// <returns></returns> public static async Task CreateNewFirmwareUpdateTask(string fileUrl, string location, int id) { IsmIoTPortalContext db = new IsmIoTPortalContext(); // Get reference to software var software = db.Releases.Find(id); try { // Filename is always the same var fileName = "update.tar"; // Creates all directories in path that do not exist Directory.CreateDirectory(location); // Full path of file string filePath = Path.Combine(location, fileName); // Save file to disk var retval = await DownloadFromBlobStorage(fileUrl, filePath).ConfigureAwait(false); if (retval.Equals("Error")) { // Update software status software.Status = "Error during download of file."; db.SaveChanges(); return; } // Update software status software.Status = "Saved"; db.SaveChanges(); // Calculate SHA 256 hash var checksum = await Sha256Sum(filePath).ConfigureAwait(false); // Get checksum string var checksum_string = BitConverter.ToString(checksum).Replace("-", String.Empty).ToLower(); // Add checksum string to database software.Checksum = checksum_string; db.SaveChanges(); // Get access to key vault var kv = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(GetToken)); // Sign Checksum var sig = await kv.SignAsync( // Key ID is in appsettings keyIdentifier : ConfigurationManager.AppSettings["kv:fw-signing-key"], // Sign with RS256 algorithm : Microsoft.Azure.KeyVault.WebKey.JsonWebKeySignatureAlgorithm.RS256, // We want to sign the checksum digest : checksum).ConfigureAwait(false); // Save byte data as sig string checksumPath = Path.Combine(location, "sig"); File.WriteAllBytes(checksumPath, sig.Result); software.Status = "Signed"; db.SaveChanges(); // Create tarball (.tar.gz file containing signed checksum and tarfile with update) var tarball = CreateTarBall(location); software.Status = "Compressed"; db.SaveChanges(); // Upload var uri = await UploadToBlobStorage(Path.GetFileName(tarball), tarball).ConfigureAwait(false); if (uri.Equals("Error")) { software.Status = "Error during upload."; db.SaveChanges(); return; } // Remove old file from BLOB storage var retVal = RemoveFromBlobStorage(fileUrl); if (retval.Equals("Error")) { software.Status = "Error during removal of old file from BLOB storage."; db.SaveChanges(); return; } // Everything is ok software.Status = "Ready"; software.Url = uri; db.SaveChanges(); } catch (Exception e) { software.Status = "Error"; db.SaveChanges(); } }