private void AttachToMessageBus() { var filter = new WirehomeDictionary() .WithValue("type", "component_registry.event.status_changed"); _messageBusService.Subscribe("history_receiver", filter, OnComponentStatusChanged); }
public string Subscribe(string uid, WirehomeDictionary filter, Action <MessageBusMessage> callback) { if (filter == null) { throw new ArgumentNullException(nameof(filter)); } if (callback == null) { throw new ArgumentNullException(nameof(callback)); } if (string.IsNullOrEmpty(uid)) { uid = Guid.NewGuid().ToString("D"); } var subscriber = new MessageBusSubscriber(uid, filter, callback, _logger); lock (_subscribers) { _subscribers[uid] = subscriber; } return(uid); }
private ServiceInstance CreateServiceInstance(string id, ServiceConfiguration configuration) { var packageUid = new PackageUid(id, configuration.Version); var package = _repositoryService.LoadPackage(packageUid); var scriptHost = _pythonScriptHostFactoryService.CreateScriptHost(_logger); scriptHost.Compile(package.Script); var context = new WirehomeDictionary { ["service_id"] = id, ["service_version"] = configuration.Version, ["service_uid"] = new PackageUid(id, configuration.Version).ToString() }; scriptHost.AddToWirehomeWrapper("context", context); var serviceInstance = new ServiceInstance(id, configuration, scriptHost); if (configuration.Variables != null) { foreach (var variable in configuration.Variables) { serviceInstance.SetVariable(variable.Key, variable.Value); } } return(serviceInstance); }
public WirehomeDictionary PostProcessMessage(string uid, [FromBody] WirehomeDictionary message) { var result = _componentRegistryService.ProcessComponentMessage(uid, message); result["component"] = _componentRegistryService.GetComponent(uid); return(result); }
private CloudMessage InvokeRawRequest(CloudMessage requestMessage) { try { WirehomeDictionary responseContent; var requestContent = requestMessage.GetContent <JToken>(); // TODO: Refactor this and build converter for JSON to WirehomeDictionary and WirehomeList if (!(PythonConvert.ToPython(requestContent) is PythonDictionary parameters)) { responseContent = new WirehomeDictionary().WithType(ControlType.ParameterInvalidException); } else { if (!_messageHandlers.TryGetValue(parameters.GetValueOr("type", string.Empty), out var messageHandler)) { responseContent = new WirehomeDictionary().WithType(ControlType.NotSupportedException); } else { responseContent = messageHandler.Invoke(parameters); } } var responseMessage = new CloudMessage(); responseMessage.SetContent(responseContent); return(responseMessage); }
public WirehomeDictionary InvokeFunction(string uid, WirehomeDictionary parameters) { if (uid == null) { throw new ArgumentNullException(nameof(uid)); } Func <WirehomeDictionary, WirehomeDictionary> function; lock (_functions) { if (!_functions.TryGetValue(uid, out function)) { throw new NotSupportedException(); } } try { return(function(parameters ?? new WirehomeDictionary())); } catch (Exception exception) { return(new WirehomeDictionary() .WithType(ControlType.Exception) .WithValue("exception.type", exception.GetType().Name) .WithValue("exception.message", exception.Message) .WithValue("exception.stack_trace", exception.StackTrace)); } }
private CloudMessage InvokeRawRequest(CloudMessage requestMessage) { try { object content; // TODO: Refactor this and build converter for JSON to WirehomeDictionary and WirehomeList if (!(PythonConvert.ToPython(requestMessage.Content) is PythonDictionary parameters)) { content = new WirehomeDictionary().WithType(ControlType.ParameterInvalidException); } else { if (!_messageHandlers.TryGetValue(parameters.GetValueOr("type", string.Empty), out var messageHandler)) { content = new WirehomeDictionary().WithType(ControlType.NotSupportedException); } else { content = messageHandler.Invoke(parameters); } } return(_messageFactory.CreateResponseMessage(requestMessage, content)); }
public void InitializeComponent(Component component, ComponentConfiguration configuration) { if (component == null) { throw new ArgumentNullException(nameof(component)); } if (configuration == null) { throw new ArgumentNullException(nameof(configuration)); } var context = new WirehomeDictionary { ["component_uid"] = component.Uid }; if (!string.IsNullOrEmpty(configuration.Script)) { // Having a script in place always overrides the logic and adapter configuration. SetupComponentBasedOnScript(component, configuration, context); return; } SetupComponentBasedOnPackages(component, configuration, context); }
public WirehomeDictionary ProcessComponentMessage(string componentUid, WirehomeDictionary message) { if (componentUid == null) { throw new ArgumentNullException(nameof(componentUid)); } if (message == null) { throw new ArgumentNullException(nameof(message)); } Component component; lock (_components) { if (!_components.TryGetValue(componentUid, out component)) { return(new WirehomeDictionary() .WithValue("type", ControlType.ParameterInvalidException) .WithValue("parameter_name", nameof(componentUid)) .WithValue("parameter_value", componentUid)); } } return(component.ProcessMessage(message)); }
public static object FromJson(JToken json) { if (json == null) { return(null); } if (json is JObject jsonObject) { var dictionary = new WirehomeDictionary(); foreach (var property in jsonObject.Properties()) { dictionary[property.Name] = FromJson(property.Value); } return(dictionary); } if (json is JArray jsonArray) { var list = new List <object>(); foreach (var item in jsonArray) { list.Add(FromJson(item)); } } return(json.ToObject <object>()); }
public async Task <WirehomeDictionary> PublishRequestAsync(WirehomeDictionary message, TimeSpan timeout) { if (message == null) { throw new ArgumentNullException(nameof(message)); } var request = new MessageBusMessage { Message = message }; var responseSubscriber = new MessageBusResponseSubscriber(); try { _responseSubscribers.TryAdd(request.Uid, responseSubscriber); Publish(request); using (var timeoutCts = new CancellationTokenSource(timeout)) { await Task.Run(() => responseSubscriber.Task, timeoutCts.Token).ConfigureAwait(false); return(responseSubscriber.Task.Result.Message); } } finally { _responseSubscribers.TryRemove(request.Uid, out _); } }
public void Set_Type() { var dictionary = new WirehomeDictionary().WithValue("type", "myTestType"); Assert.AreEqual(1, dictionary.Keys.Count); Assert.AreEqual("myTestType", dictionary["type"]); }
public void SetValue(string uid, object value) { if (uid == null) { throw new ArgumentNullException(nameof(uid)); } object oldValue; lock (_variables) { if (_variables.TryGetValue(uid, out oldValue)) { if (Equals(oldValue, value)) { return; } } _variables[uid] = value; Save(); } var busMessage = new WirehomeDictionary() .WithValue("type", "global_variables.event.value_set") .WithValue("uid", uid) .WithValue("old_value", oldValue) .WithValue("new_value", value); _logger.LogInformation("Global variable '{0}' changed to '{1}'.", uid, value); _messageBusService.Publish(busMessage); }
public MessageBusSubscriber(string uid, WirehomeDictionary filter, Action <MessageBusMessage> callback, ILogger logger) { Uid = uid ?? throw new ArgumentNullException(nameof(uid)); Filter = filter ?? throw new ArgumentNullException(nameof(filter)); _callback = callback ?? throw new ArgumentNullException(nameof(callback)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); }
private AutomationInstance CreateAutomation(string uid, AutomationConfiguration configuration, WirehomeDictionary settings) { var repositoryEntitySource = _repositoryService.LoadEntity(configuration.Logic.Uid); var scriptHost = _pythonScriptHostFactoryService.CreateScriptHost(_logger, new AutomationPythonProxy(uid, this)); scriptHost.Initialize(repositoryEntitySource.Script); var context = new WirehomeDictionary { ["automation_uid"] = uid, ["logic_id"] = configuration.Logic.Uid.Id, ["logic_version"] = configuration.Logic.Uid.Version }; // TODO: Remove scope as soon as all automations are migrated. scriptHost.SetVariable("scope", context); scriptHost.SetVariable("context", context); foreach (var variable in configuration.Logic.Variables) { scriptHost.SetVariable(variable.Key, variable.Value); } var automation = new AutomationInstance(uid, scriptHost); foreach (var setting in settings) { automation.Settings[setting.Key] = setting.Value; } return(automation); }
public void InitializeComponent(string uid) { if (uid == null) { throw new ArgumentNullException(nameof(uid)); } try { if (!_storageService.TryRead(out ComponentConfiguration configuration, ComponentsDirectory, uid, DefaultFilenames.Configuration)) { throw new ComponentNotFoundException(uid); } if (!configuration.IsEnabled) { _logger.LogInformation($"Component '{uid}' not initialized because it is disabled."); return; } if (!_storageService.TryRead(out WirehomeDictionary settings, ComponentsDirectory, uid, DefaultFilenames.Settings)) { settings = new WirehomeDictionary(); } var component = new Component(uid); foreach (var setting in settings) { component.Settings[setting.Key] = setting.Value; } lock (_components) { if (_components.TryGetValue(uid, out var existingComponent)) { existingComponent.ProcessMessage(new WirehomeDictionary().WithType(ControlType.Destroy)); } _components[uid] = component; } _componentInitializerService.Create(this).InitializeComponent(component, configuration); component.ProcessMessage(new WirehomeDictionary().WithType(ControlType.Initialize)); _logger.LogInformation($"Component '{component.Uid}' initialized successfully."); } catch { lock (_components) { _components.Remove(uid, out _); } throw; } }
private void InitializeLogic(Component component, ComponentLogicConfiguration configuration) { var scope = new WirehomeDictionary { ["component_uid"] = component.Uid }; var adapterEntity = _repositoryService.LoadEntity(configuration.Adapter.Uid); var adapter = new ScriptComponentAdapter(_pythonEngineService, _componentRegistryService, _loggerFactory); adapter.Initialize(component.Uid, adapterEntity.Script); if (configuration.Adapter.Variables != null) { foreach (var parameter in configuration.Adapter.Variables) { adapter.SetVariable(parameter.Key, parameter.Value); } } scope["adapter_uid"] = adapterEntity.Uid.ToString(); scope["adapter_id"] = adapterEntity.Uid.Id; scope["adapter_version"] = adapterEntity.Uid.Version; if (string.IsNullOrEmpty(configuration.Uid?.Id)) { component.SetLogic(new EmptyLogic(adapter)); } else { var logicEntity = _repositoryService.LoadEntity(configuration.Uid); var logic = new ScriptComponentLogic(_pythonEngineService, _componentRegistryService, _loggerFactory); adapter.MessagePublishedCallback = message => logic.ProcessAdapterMessage(message); logic.AdapterMessagePublishedCallback = message => adapter.ProcessMessage(message); logic.Initialize(component.Uid, logicEntity.Script); if (configuration.Variables != null) { foreach (var parameter in configuration.Variables) { logic.SetVariable(parameter.Key, parameter.Value); } } scope["logic_uid"] = logicEntity.Uid.ToString(); scope["logic_id"] = logicEntity.Uid.Id; scope["logic_version"] = logicEntity.Uid.Version; logic.SetVariable("scope", scope); component.SetLogic(logic); } adapter.SetVariable("scope", scope); }
public static WirehomeDictionary WithType(this WirehomeDictionary wirehomeDictionary, string type) { if (wirehomeDictionary == null) { throw new ArgumentNullException(nameof(wirehomeDictionary)); } return(wirehomeDictionary.WithValue("type", type)); }
public WirehomeDictionary invoke(string uid, WirehomeDictionary parameters) { if (uid == null) { throw new ArgumentNullException(nameof(uid)); } return(_functionPoolService.InvokeFunction(uid, parameters)); }
public WirehomeDictionary Invoke(WirehomeDictionary message) { if (message == null) { throw new ArgumentNullException(nameof(message)); } return(_callback(message)); }
public void InitializeAutomation(string uid) { if (uid == null) { throw new ArgumentNullException(nameof(uid)); } try { if (!_storageService.TryRead(out AutomationConfiguration configuration, AutomationsDirectory, uid, DefaultFilenames.Configuration)) { throw new AutomationNotFoundException(uid); } if (!configuration.IsEnabled) { _logger.LogInformation($"Automation '{uid}' not initialized because it is disabled."); return; } if (!_storageService.TryRead(out WirehomeDictionary settings, AutomationsDirectory, uid, DefaultFilenames.Settings)) { settings = new WirehomeDictionary(); } _logger.LogInformation($"Initializing automation '{uid}'."); var automationInstance = CreateAutomation(uid, configuration, settings); automationInstance.Initialize(); _logger.LogInformation($"Automation '{uid}' initialized."); lock (_automations) { if (_automations.TryGetValue(uid, out var existingAutomation)) { _logger.LogInformation($"Deactivating automation '{uid}'."); existingAutomation.Deactivate(); _logger.LogInformation($"Automation '{uid}' deactivated."); } _automations[uid] = automationInstance; _logger.LogInformation($"Activating automation '{uid}'."); automationInstance.Activate(); _logger.LogInformation($"Automation '{uid}' activated."); } } catch { lock (_automations) { _automations.Remove(uid); } throw; } }
public WirehomeDictionary ProcessMessage(WirehomeDictionary message) { if (message == null) { throw new ArgumentNullException(nameof(message)); } ThrowIfLogicNotSet(); return(_logic.ProcessMessage(message)); }
public void InitializeAutomation(string uid, AutomationConfiguration configuration) { if (uid == null) { throw new ArgumentNullException(nameof(uid)); } if (configuration == null) { throw new ArgumentNullException(nameof(configuration)); } if (!configuration.IsEnabled) { _logger.Log(LogLevel.Information, $"Automation '{uid}' not initialized because it is disabled."); return; } var repositoryEntitySource = _repositoryService.LoadEntity(configuration.Logic.Uid); var scriptHost = _pythonEngineService.CreateScriptHost(_logger); scriptHost.Initialize(repositoryEntitySource.Script); var scope = new WirehomeDictionary { ["automation_uid"] = uid, ["logic_id"] = configuration.Logic.Uid.Id, ["logic_version"] = configuration.Logic.Uid.Version }; scriptHost.SetVariable("scope", scope); foreach (var variable in configuration.Logic.Variables) { scriptHost.SetVariable(variable.Key, variable.Value); } var automationInstance = new Automation(scriptHost); automationInstance.Initialize(); lock (_automations) { if (_automations.TryGetValue(uid, out var existingAutomationInstance)) { existingAutomationInstance.Deactivate(); } automationInstance.Activate(); _automations[uid] = automationInstance; } _logger.Log(LogLevel.Information, $"Automation '{uid}' initialized."); }
public static bool IsMatch(WirehomeDictionary message, WirehomeDictionary filter) { if (message == null) { throw new ArgumentNullException(nameof(message)); } if (filter == null) { throw new ArgumentNullException(nameof(filter)); } foreach (var filterEntry in filter) { if (!message.TryGetValue(filterEntry.Key, out var propertyValue)) { return(false); } var pattern = ConvertValueToString(filterEntry.Value); var wildcard = "*".AsSpan(); if (pattern.Equals(wildcard, StringComparison.Ordinal)) { continue; } var value = ConvertValueToString(propertyValue); if (pattern.EndsWith(wildcard, StringComparison.Ordinal)) { if (!value.StartsWith(pattern.Slice(0, pattern.Length - 1), StringComparison.Ordinal)) { return(false); } } else if (pattern.StartsWith(wildcard, StringComparison.Ordinal)) { if (!value.EndsWith(pattern.Slice(1), StringComparison.Ordinal)) { return(false); } } else { if (!value.Equals(pattern, StringComparison.Ordinal)) { return(false); } } } // A filter without any properties is matching always. return(true); }
public IDictionary PostProcessMessage(string uid, [FromBody] WirehomeDictionary message, bool returnUpdatedComponent = true) { var result = _componentRegistryService.ProcessComponentMessage(uid, message); if (returnUpdatedComponent) { result["component"] = CreateComponentModel(_componentRegistryService.GetComponent(uid)); } return(result); }
public void PublishDisabledEvent(string componentUid) { var message = new WirehomeDictionary { ["type"] = "component_registry.event.disabled", ["component_uid"] = componentUid, ["timestamp"] = DateTime.Now.ToString("O") }; _messageBusService.Publish(message); }
public void Match_Wildcard() { var message = new WirehomeDictionary() .WithValue("type", "myTypeX"); var filter = new WirehomeDictionary() .WithValue("type", "*"); var compareResult = MessageBusFilterComparer.IsMatch(message, filter); Assert.IsTrue(compareResult); }
public void PublishMacroExecutedBusMessage(string macroUid, WirehomeDictionary result) { var message = new WirehomeDictionary { ["type"] = "macro_registry.event.macro_executed", ["macro_uid"] = macroUid, ["result"] = result, ["timestamp"] = DateTime.Now.ToString("O") }; _messageBusService.Publish(message); }
public void PublishTagRemovedEvent(string componentUid, string tag) { var message = new WirehomeDictionary { ["type"] = "component_registry.event.tag_removed", ["component_uid"] = componentUid, ["tag"] = tag, ["timestamp"] = DateTime.Now.ToString("O") }; _messageBusService.Publish(message); }
public void TryInitializeComponentGroup(string uid) { if (uid == null) { throw new ArgumentNullException(nameof(uid)); } try { if (!_storageService.TryRead(out ComponentGroupConfiguration configuration, ComponentGroupsDirectory, uid, DefaultFilenames.Configuration)) { throw new ComponentGroupNotFoundException(uid); } if (!_storageService.TryRead(out WirehomeDictionary settings, ComponentGroupsDirectory, uid, DefaultFilenames.Settings)) { settings = new WirehomeDictionary(); } var componentGroup = new ComponentGroup(uid); foreach (var setting in settings) { componentGroup.Settings[setting.Key] = setting.Value; } var associationUids = _storageService.EnumeratureDirectories("*", ComponentGroupsDirectory, uid, "Components"); foreach (var associationUid in associationUids) { if (!_storageService.TryRead(out WirehomeDictionary associationSettings, ComponentGroupsDirectory, uid, "Components", associationUid, DefaultFilenames.Settings)) { associationSettings = new WirehomeDictionary(); } var componentAssociation = new ComponentGroupAssociation(); foreach (var associationSetting in associationSettings) { componentAssociation.Settings[associationSetting.Key] = associationSetting.Value; } componentGroup.Components.TryAdd(associationUid, componentAssociation); } lock (_componentGroups) { _componentGroups[uid] = componentGroup; } } catch (Exception exception) { _logger.LogError(exception, $"Error while initializing component group '{uid}'.'"); } }