public Task <MsgSubscribeToThingsResponse> SubscribeToThingAsync(TheThingSubscription thingSubscriptionRequest) { return(SubscribeToThingsAsync(new List <TheThingSubscription> { thingSubscriptionRequest })); }
internal static void SpecializeThingSubscription(TheThingSubscription answerSub, TheThingSubscription generalizedSub) { if (answerSub.SubscriptionId != null) { generalizedSub.SubscriptionId = answerSub.SubscriptionId; } if (answerSub.ExtensionData != null) { foreach (var prop in answerSub.ExtensionData) { generalizedSub.ExtensionData[prop.Key] = prop.Value; } } if (answerSub.PropertiesIncluded != null) { generalizedSub.PropertiesIncluded = answerSub.PropertiesIncluded; } if (answerSub.PropertiesExcluded != null) { generalizedSub.PropertiesExcluded = answerSub.PropertiesExcluded; } if (answerSub.AddThingIdentity != null) { generalizedSub.AddThingIdentity = answerSub.AddThingIdentity; } if (answerSub.ContinueMatching != null) { generalizedSub.ContinueMatching = answerSub.ContinueMatching; } if (answerSub.CooldownPeriod != null) { generalizedSub.CooldownPeriod = answerSub.CooldownPeriod; } if (answerSub.EventFormat != null) { generalizedSub.EventFormat = answerSub.EventFormat; } if (answerSub.ForceAllProperties != null) { generalizedSub.ForceAllProperties = answerSub.ForceAllProperties; } if (answerSub.IgnoreExistingHistory != null) { generalizedSub.IgnoreExistingHistory = answerSub.IgnoreExistingHistory; } if (answerSub.IgnorePartialFailure != null) { generalizedSub.IgnorePartialFailure = answerSub.IgnorePartialFailure; } if (answerSub.KeepDurableHistory != null) { generalizedSub.KeepDurableHistory = answerSub.KeepDurableHistory; } if (answerSub.MaxHistoryCount != null) { generalizedSub.MaxHistoryCount = answerSub.MaxHistoryCount; } if (answerSub.MaxHistoryTime != null) { generalizedSub.MaxHistoryTime = answerSub.MaxHistoryTime; } if (answerSub.PartitionKey != null) { generalizedSub.PartitionKey = answerSub.PartitionKey; } if (answerSub.PreserveOrder != null) { generalizedSub.PreserveOrder = answerSub.PreserveOrder; } if (answerSub.ReplaceExistingThing != null) { generalizedSub.ReplaceExistingThing = answerSub.ReplaceExistingThing; } if (answerSub.SamplingWindow != null) { generalizedSub.SamplingWindow = answerSub.SamplingWindow; } if (answerSub.SendInitialValues != null) { generalizedSub.SendInitialValues = answerSub.SendInitialValues; } if (answerSub.SendUnchangedValue != null) { generalizedSub.SendUnchangedValue = answerSub.SendUnchangedValue; } if (answerSub.StaticProperties != null) { generalizedSub.StaticProperties = answerSub.StaticProperties; } if (answerSub.TargetName != null) { generalizedSub.TargetName = answerSub.TargetName; } if (answerSub.TargetType != null) { generalizedSub.TargetType = answerSub.TargetType; } if (answerSub.TargetUnit != null) { generalizedSub.TargetUnit = answerSub.TargetUnit; } if (answerSub.ThingReference != null) { generalizedSub.ThingReference = answerSub.ThingReference; } if (answerSub.TokenExpirationInHours != null) { generalizedSub.TokenExpirationInHours = answerSub.TokenExpirationInHours; } }
public MsgSubscribeToThings(TheThingSubscription thingSubscription) { SubscriptionRequests = new List <TheThingSubscription> { thingSubscription }; }
//internal static Task<ApplyConfigFilesResult> ApplyPipelineConfigJsonAsync(string pipelineConfigJson, IEnumerable<string> answerFilesJson, string configFileNameForLog, string[] answerFileNamesForLog) //{ // var pipeLineTasks = ApplyPipelineConfigJsonInternal(pipelineConfigJson, answerFilesJson, configFileNameForLog, answerFileNamesForLog); // if (pipeLineTasks == null) // { // return TheCommonUtils.TaskFromResult(new ApplyConfigFilesResult // { // Success = false, // }); // } // return TheCommonUtils.TaskWhenAll(pipeLineTasks.Select(t => (Task)t)) // .ContinueWith(t => // { // bool bSuccess = true; // int failedFileCount = 0; // foreach (var task in pipeLineTasks) // { // if (task.IsFaulted) // { // failedFileCount++; // bSuccess = false; // } // } // return new ApplyConfigFilesResult { Success = bSuccess, NumberOfFiles = 1, NumberOfFailedFiles = failedFileCount }; // }); //} static List <Task <List <TheThing> > > ApplyPipelineConfigJsonInternal(ThePipelineConfiguration pipelineConfig, IEnumerable <ThePipelineConfiguration> answerConfigs, string configFileNameForLog, string[] answerFileNamesForLog) { List <Task <List <TheThing> > > pipeLineTasks = new List <Task <List <TheThing> > >(); try { if (configFileNameForLog == null) { configFileNameForLog = pipelineConfig?.FriendlyName ?? "Not specified"; } if (pipelineConfig != null && pipelineConfig.ThingConfigurations != null) { var pipelines = new List <ThePipelineConfiguration>(); if (!pipelineConfig.ThingConfigurations.Any(tc => tc.ThingSpecializationParameters == null)) // If all thing instances have specializations, add the pipeline as a config { pipelines.Add(pipelineConfig); } try { if (!answerConfigs?.Any() == true && !pipelines.Contains(pipelineConfig)) { TheBaseAssets.MySYSLOG.WriteToLog(7721, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM(eEngineName.ThingService, "Found no answer file for generalized config. Attempting to install the generalized config.", eMsgLevel.l2_Warning, $"File: {configFileNameForLog}. Config {pipelineConfig}")); pipelines.Add(pipelineConfig); } int answerFileIndex = 0; foreach (var answerConfig in answerConfigs) { var answerFileNameForLog = answerFileIndex < answerFileNamesForLog?.Length ? answerFileNamesForLog[answerFileIndex] : answerConfig.FriendlyName ?? $"Answer Config {answerFileIndex}"; answerFileIndex++; try { var pipelineInstance = TheCommonUtils.DeserializeJSONStringToObject <ThePipelineConfiguration>(TheCommonUtils.SerializeObjectToJSONString(pipelineConfig)); // TODO implement Clone to avoid reparsing int thingConfigIndex = 0; foreach (var answerThingConfig in answerConfig.ThingConfigurations) { // verify that the rest matches (or doesn't exist) if (thingConfigIndex < pipelineInstance.ThingConfigurations.Count) { if (answerThingConfig.ThingSpecializationParameters != null) { pipelineInstance.ThingConfigurations[thingConfigIndex].ThingSpecializationParameters = answerThingConfig.ThingSpecializationParameters; } else { TheBaseAssets.MySYSLOG.WriteToLog(7721, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM(eEngineName.ThingService, "Error processing answer file: no specialization parameters", eMsgLevel.l1_Error, $"File: {configFileNameForLog}. Answer File: {answerFileNameForLog}. Config {pipelineInstance.ThingConfigurations[thingConfigIndex]}")); } if (answerThingConfig.ThingSubscriptions != null) { var generalizedSubscriptions = pipelineInstance.ThingConfigurations[thingConfigIndex].ThingSubscriptions; int subIndex = 0; var newSubscriptions = new List <TheThingSubscription>(); foreach (var answerSub in answerThingConfig.ThingSubscriptions) { if (answerSub != null) { if (answerSub.ExtensionData.ContainsKey("Add")) { // Add a new subscription: remember for now, add later to not confused the subIndex logic newSubscriptions.Add(answerSub); } else if (answerSub.ExtensionData.ContainsKey("Remove")) { // remove this subscription generalizedSubscriptions[subIndex] = null; // Just set to null here, so the subIndex logic doesn't get confused. Will remove the null's later. subIndex++; } else { // Update this subscription var generalizedSub = generalizedSubscriptions[subIndex]; TheThingSubscription.SpecializeThingSubscription(answerSub, generalizedSub); subIndex++; } } } generalizedSubscriptions.AddRange(newSubscriptions); generalizedSubscriptions.RemoveAll(sub => sub == null); } if (answerThingConfig.SensorSubscriptions != null) { var generalizedSubscriptions = pipelineInstance.ThingConfigurations[thingConfigIndex].SensorSubscriptions; int subIndex = 0; var newSubscriptions = new List <TheSensorSubscription>(); foreach (var answerSub in answerThingConfig.SensorSubscriptions) { if (answerSub != null) { if (answerSub.ExtensionData.ContainsKey("Add")) { // Add a new subscription: remember for now, add later to not confused the index newSubscriptions.Add(answerSub); } else if (answerSub.ExtensionData.ContainsKey("Remove")) { // remove this subscription generalizedSubscriptions[subIndex] = null; // Just set to null here, so the index doesn't get confused. Will remove the null's later. subIndex++; } else { // Update this subscription var generalizedSub = generalizedSubscriptions[subIndex]; TheSensorSubscription.SpecializeSensorSubscription(answerSub, generalizedSub); subIndex++; } } } generalizedSubscriptions.AddRange(newSubscriptions); generalizedSubscriptions.RemoveAll(sub => sub == null); } } else { TheBaseAssets.MySYSLOG.WriteToLog(7721, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM(eEngineName.ThingService, "Error processing answer file: too many specialization parameters. Ignoring.", eMsgLevel.l1_Error, $"File: {configFileNameForLog}. Answer File: {answerFileNameForLog}. Config# {thingConfigIndex}")); } thingConfigIndex++; } if (answerConfig.ThingConfigurations.Count < pipelineInstance.ThingConfigurations.Count) { TheBaseAssets.MySYSLOG.WriteToLog(7721, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM(eEngineName.ThingService, "Error processing answer file: not enough specialization parameters.", eMsgLevel.l1_Error, $"File: {configFileNameForLog}. Answer File: {answerFileNameForLog}. Params {answerConfig.ThingConfigurations.Count} Expected: {pipelineInstance.ThingConfigurations.Count}")); } pipelines.Add(pipelineInstance); } catch (Exception e) { TheBaseAssets.MySYSLOG.WriteToLog(7721, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM(eEngineName.ThingService, "Error processing answer file", eMsgLevel.l1_Error, $"File: {configFileNameForLog}. Answer File: {answerFileNameForLog}. {e.Message}")); } } } catch (Exception e) { TheBaseAssets.MySYSLOG.WriteToLog(7721, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM(eEngineName.ThingService, "Error processing answer files", eMsgLevel.l1_Error, $"File: {configFileNameForLog}. {e.Message}")); } // TODO use the application host thing or specify the host thing in the pipeline config/answer file? var owner = TheThingRegistry.GetBaseEngineAsThing(eEngineName.ThingService); if (!owner.IsInit()) { TheBaseAssets.MySYSLOG.WriteToLog(7720, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM(eEngineName.ThingService, $"ApplyConfig Files: error getting Thing engine", eMsgLevel.l1_Error, $"{pipelineConfig}")); } foreach (var pipeline in pipelines) { var thingReferenceMap = new Dictionary <string, string>(); foreach (var thingConfig in pipeline.ThingConfigurations) { var specializedThingIdentity = thingConfig.GetSpecializedThingIdentity(thingReferenceMap); // First synchronously apply the configuration properties, so the plug-in does not start up with the old values var tThing = new TheThingReference(specializedThingIdentity).GetMatchingThings().FirstOrDefault(); if (tThing != null) { if (!tThing.ApplyConfigurationPropertiesInternal(thingConfig, thingReferenceMap)) { TheBaseAssets.MySYSLOG.WriteToLog(7719, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM(eEngineName.ThingService, $"Error applying config properties", eMsgLevel.l3_ImportantMessage, $"{thingConfig}")); } } } var thingsTask = CreateThingPipelineFromConfigurationAsync(owner, pipeline); pipeLineTasks.Add(thingsTask); } } else { throw new Exception($"Error parsing config file {configFileNameForLog}"); } } catch (Exception e) { TheBaseAssets.MySYSLOG.WriteToLog(7721, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM(eEngineName.ThingService, "Error processing config file", eMsgLevel.l1_Error, $"File: {configFileNameForLog}. {e.Message}")); pipeLineTasks = null; } return(pipeLineTasks); }