Beispiel #1
0
        private void AttachToMessageBus()
        {
            var filter = new WirehomeDictionary()
                         .WithValue("type", "component_registry.event.status_changed");

            _messageBusService.Subscribe("history_receiver", filter, OnComponentStatusChanged);
        }
Beispiel #2
0
        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));
            }
        }
Beispiel #7
0
        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));
        }
Beispiel #10
0
        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"]);
        }
Beispiel #13
0
        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);
        }
Beispiel #14
0
 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);
        }
Beispiel #16
0
        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;
            }
        }
Beispiel #17
0
        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);
        }
Beispiel #18
0
        public static WirehomeDictionary WithType(this WirehomeDictionary wirehomeDictionary, string type)
        {
            if (wirehomeDictionary == null)
            {
                throw new ArgumentNullException(nameof(wirehomeDictionary));
            }

            return(wirehomeDictionary.WithValue("type", type));
        }
Beispiel #19
0
        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;
            }
        }
Beispiel #22
0
        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.");
        }
Beispiel #24
0
        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);
        }
Beispiel #26
0
        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);
        }
Beispiel #27
0
        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);
        }
Beispiel #28
0
        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);
        }
Beispiel #29
0
        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);
        }
Beispiel #30
0
        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}'.'");
            }
        }