private async Task StopPlaybackAsync(string message) { MyBaseThing.StatusLevel = 6; MyBaseThing.LastMessage = "Playback stopping"; var ts = playbackCancel; playbackCancel = null; ts?.Cancel(); await TheCommonUtils.TaskWhenAll(playbackTasks); playbackTasks.Clear(); _kpiTimer?.Change(Timeout.Infinite, Timeout.Infinite); OnKpiUpdate(null); IsStarted = false; MyBaseThing.StatusLevel = 0; MyBaseThing.LastMessage = string.IsNullOrEmpty(message) ? "Playback stopped" : message; }
public static Task <MsgApplyPipelineConfigResponse> ApplyPipelineConfigAsync(MsgApplyPipelineConfig request) { var pipeLineTasks = ApplyPipelineConfigJsonInternal(request.Config, request.AnswerConfigs, null, null); if (pipeLineTasks == null) { return(TheCommonUtils.TaskFromResult(new MsgApplyPipelineConfigResponse { Error = "Error applying configuration", })); } return(TheCommonUtils.TaskWhenAll(pipeLineTasks.Select(t => (Task)t)) .ContinueWith(t => { bool bSuccess = true; int failedFileCount = 0; var thingsConfigured = new List <TheThingIdentity>(); foreach (var task in pipeLineTasks) { if (task.IsFaulted) { failedFileCount++; bSuccess = false; thingsConfigured.Add(null); } else { var thingIdentities = task.Result?.Select(thing => new TheThingIdentity(thing)); if (thingIdentities != null) { thingsConfigured.AddRange(thingIdentities); } else { thingsConfigured.Add(null); } } } return new MsgApplyPipelineConfigResponse { Error = bSuccess ? null : "Error applying configuration", ThingsConfigured = thingsConfigured, }; })); }
#pragma warning restore CS0649 private async void RunScriptsAsync(object _) { try { MyBaseThing.SetStatus(4, "Running scripts."); var variables = new TheThing(); // Using this as a property bag to hold variables that can be shared across the scripts -> Maybe use the script thing itself for this? Keeps an audit trail of the state of the script... var scriptDir = TheCommonUtils.cdeFixupFileName(@"ClientBin\scripts"); var scriptFiles = Directory.EnumerateFiles(scriptDir, "*.cdescript").ToList(); var scriptsRun = new List <string>(); var pendingScripts = new List <string>(); var scriptsToRun = new List <TheScript>(); int pendingScriptCount; pendingScriptCount = pendingScripts.Count; foreach (var scriptFile in scriptFiles) { try { TheScript script = LoadScript(scriptFile); scriptsToRun.Add(script); } catch (Exception e) { string scriptName = scriptFile; try { scriptName = Path.GetFileNameWithoutExtension(scriptFile); } catch { } UpdateStorageList(scriptFile, $"Failed to read: {e.Message}", -1, null, null, false); TheBaseAssets.MySYSLOG.WriteToLog(175000, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM(MyBaseThing.EngineName, "Error reading cde script file", eMsgLevel.l1_Error, e.ToString())); } } foreach (var dependentScript in scriptsToRun.Where(script => script.DependsOn != null && script.DependsOn.Length > 0).ToList()) { foreach (var dependencyName in dependentScript.DependsOn) { var dependencyScriptIndex = scriptsToRun.FindIndex(script => script.Name == dependencyName); if (dependencyScriptIndex < 0) { TheBaseAssets.MySYSLOG.WriteToLog(175007, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM(MyBaseThing.EngineName, "Unable to run script with dependencies", eMsgLevel.l1_Error, $"Dependent: '{dependentScript.Name}'. Dependency not found: '{dependencyName}'")); } else { var dependentScriptIndex = scriptsToRun.IndexOf(dependentScript); if (dependentScriptIndex >= 0 && dependencyScriptIndex > dependentScriptIndex) { scriptsToRun.Insert(dependencyScriptIndex + 1, dependentScript); scriptsToRun.RemoveAt(dependentScriptIndex); } } } } // This assumes RunScriptsAsync is only called from Init() (= on gate restart) foreach (var oldScript in MyScriptTableStorage.TheValues) { if (oldScript.ScriptStatus == "Not found") { MyScriptTableStorage.RemoveAnItem(oldScript, null); } else { oldScript.ScriptStatus = "Not found"; } } foreach (var script in scriptsToRun) { int stepNumber = 1; foreach (var step in script.Steps ?? new TheScriptStep[0]) { UpdateStorageList(script.Name, "Pending", stepNumber, script, null, false); stepNumber++; } } int index = 0; var scriptTasks = new List <Task>(); foreach (var script in scriptsToRun) { Task task = null; if (script.DependsOn?.Length > 0) { if (index > 1) { task = scriptTasks[index - 1].ContinueWith(t => RunScriptAsync(script, variables)); } } if (task == null) { task = RunScriptAsync(script, variables); } scriptTasks.Add(task); scriptsRun.Add(script.Name); } await TheCommonUtils.TaskWhenAll(scriptTasks); if (MyBaseThing.StatusLevel == 4) { if (scriptTasks?.Count > 0) { MyBaseThing.SetStatus(1, $"All {scriptTasks?.Count} scripts applied."); } else { MyBaseThing.SetStatus(1, "No scripts found."); } TheBaseAssets.MySYSLOG.WriteToLog(175001, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM(MyBaseThing.EngineName, "Scripts applied", eMsgLevel.l3_ImportantMessage, $"Number of scripts: {scriptTasks?.Count}")); } } catch (DirectoryNotFoundException) { TheBaseAssets.MySYSLOG.WriteToLog(175001, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM(MyBaseThing.EngineName, "Error finding or running script files", eMsgLevel.l3_ImportantMessage, "Script directory not found")); MyBaseThing.SetStatus(1, "No script directory found."); } catch (Exception e) { TheBaseAssets.MySYSLOG.WriteToLog(175001, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM(MyBaseThing.EngineName, "Error finding or running script files", eMsgLevel.l1_Error, e.ToString())); MyBaseThing.SetStatus(3, $"Error while finding or running cdescript files: {e.Message}"); } }
private async Task RunPlaybackAsync(IEnumerable <cdeP> allProperties, IEnumerable <object> thingUpdates, TimeSpan startupDelayRange, bool bFromAutoStart, double propCountBefore) { for (int j = 1; j <= ReplayCount; j++) { playbackCancel?.Cancel(); playbackCancel = new CancellationTokenSource(); var cancelCombined = CancellationTokenSource.CreateLinkedTokenSource(playbackCancel.Token, TheBaseAssets.MasterSwitchCancelationToken); IsStarted = true; MyBaseThing.StatusLevel = 1; MyBaseThing.LastMessage = $"Playback started: {ItemCount} items. {ParallelPlaybackCount} things."; for (int i = 1; i <= ParallelPlaybackCount; i++) { TheThing tThingOverride = null; if (!string.IsNullOrEmpty(PlaybackEngineName)) { if (TheThingRegistry.GetBaseEngine(PlaybackEngineName) == null) { TheCDEngines.RegisterNewMiniRelay(PlaybackEngineName); } var thingName = $"{MyBaseThing.FriendlyName}{i:D6}"; tThingOverride = TheThingRegistry.GetThingByID(PlaybackEngineName, thingName, true); if (tThingOverride == null) { tThingOverride = new TheThing { FriendlyName = thingName, ID = thingName, EngineName = PlaybackEngineName, DeviceType = PlaybackDeviceType, }; foreach (var prop in allProperties) { tThingOverride.SetProperty(prop.Name, prop.Value, prop.cdeT); } TheThingRegistry.RegisterThing(tThingOverride); } // This only works if the plug-in is actually installed, not with mini relay //var createThingInfo = new TheThingRegistry.MsgCreateThingRequestV1 //{ // EngineName = PlaybackEngineName, // DeviceType = PlaybackDeviceType, // InstanceId = thingName, // FriendlyName = thingName, // CreateIfNotExist = true, // DoNotModifyIfExists = true, // OwnerAddress = MyBaseThing, // Properties = new Dictionary<string, object> { { "ID", thingName } }, //}; //tThingOverride = await TheThingRegistry.CreateOwnedThingAsync(createThingInfo, new TimeSpan(0, 1, 0)); if (tThingOverride == null) { MyBaseThing.LastMessage = "Error creating playback thing"; break; } } var playbackTask = TheCommonUtils.cdeRunTaskChainAsync($"Playback{i}", o => PlaybackLoop(tThingOverride, cancelCombined.Token, thingUpdates, startupDelayRange, bFromAutoStart), true); playbackTasks.Add(playbackTask); } _ = await TheCommonUtils.TaskWhenAll(playbackTasks).ContinueWith(async(t) => { try { PlaybackDuration = sw.Elapsed; sw.Stop(); OnKpiUpdate(null); var propCount = Gen_Stats_PropertyCounter - propCountBefore; var message = $"Playback done. {propCount} props in {PlaybackDuration}. {propCount / PlaybackDuration.TotalSeconds} props/s. {ItemCount * ParallelPlaybackCount / PlaybackDuration.TotalSeconds} items/s."; //MyBaseThing.LastMessage = message; TheBaseAssets.MySYSLOG.WriteToLog(700, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM(MyBaseThing.EngineName, message, eMsgLevel.l6_Debug)); await StopPlaybackAsync(message); _ = new CDMyMeshManager.Contracts.MsgReportTestStatus { NodeId = TheBaseAssets.MyServiceHostInfo.MyDeviceInfo.DeviceID, PercentCompleted = (j * 1.0 / ReplayCount) * 100, SuccessRate = 100, Status = j == ReplayCount ? CDMyMeshManager.Contracts.eTestStatus.Success : CDMyMeshManager.Contracts.eTestStatus.Running, TestRunId = TheCommonUtils.CGuid(TheBaseAssets.MySettings.GetSetting("TestRunID")), Timestamp = DateTimeOffset.Now, ResultDetails = new Dictionary <string, object> { { "Message", message }, { "PropertyCount", propCount }, { "DurationInSeconds", PlaybackDuration.TotalSeconds } }, }.Publish().Result; } catch { } }, TaskContinuationOptions.OnlyOnRanToCompletion); } }
internal static Task <ApplyConfigFilesResult> ApplyConfigurationFilesAsync() { bool bSuccess = true; int fileCount = 0; int failedFileCount = 0; var pipeLineTasks = new List <Task <List <TheThing> > >(); try { var configDir = TheCommonUtils.cdeFixupFileName(Path.Combine("ClientBin", "config")); if (!Directory.Exists(configDir)) { return(TheCommonUtils.TaskFromResult(new ApplyConfigFilesResult { Success = true, })); } var configDirs = Directory.GetParent(configDir).GetDirectories("config"); if (configDirs.Length != 1 || configDirs[0].FullName != configDir) { TheBaseAssets.MySYSLOG.WriteToLog(7721, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM(eEngineName.ThingService, "ClientBin/config directory has invalid casing. Must be lower case.", eMsgLevel.l1_Error)); return(TheCommonUtils.TaskFromResult(new ApplyConfigFilesResult { Success = false, })); } var configFiles = Directory.GetFiles(configDir, "*.cdeconfig"); fileCount = configFiles.Length; foreach (var configFile in configFiles) { var pipelineJson = File.ReadAllText(configFile); pipelineJson = TheCommonUtils.GenerateFinalStr(pipelineJson); var pipelineConfig = TheCommonUtils.DeserializeJSONStringToObject <ThePipelineConfiguration>(pipelineJson); var answerFileNames = Directory.GetFiles(configDir, $"{Path.GetFileNameWithoutExtension(configFile)}*.cdeanswer"); var answerConfigs = answerFileNames.Select(af => { var answerJson = File.ReadAllText(af); answerJson = TheCommonUtils.GenerateFinalStr(answerJson); var answerConfig = TheCommonUtils.DeserializeJSONStringToObject <ThePipelineConfiguration>(answerJson); return(answerConfig); }); var tasks = ApplyPipelineConfigJsonInternal(pipelineConfig, answerConfigs, configFile, answerFileNames); if (tasks?.Count == 0) { failedFileCount++; } pipeLineTasks.AddRange(tasks); } } catch (Exception e) { TheBaseAssets.MySYSLOG.WriteToLog(7722, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM(eEngineName.ThingService, "Error processing config files", eMsgLevel.l1_Error, $"{e.Message}")); bSuccess = false; } return(TheCommonUtils.TaskWhenAll(pipeLineTasks.Select(t => (Task)t)) .ContinueWith(t => { foreach (var task in pipeLineTasks) { if (task.IsFaulted) { failedFileCount++; bSuccess = false; } } return new ApplyConfigFilesResult { Success = bSuccess, NumberOfFiles = fileCount, NumberOfFailedFiles = failedFileCount }; })); }