예제 #1
0
        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;
        }
예제 #2
0
        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,
                };
            }));
        }
예제 #3
0
#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}");
            }
        }
예제 #4
0
        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);
            }
        }
예제 #5
0
        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
                };
            }));
        }