Coder Social home page Coder Social logo

marinmitev / smarthome Goto Github PK

View Code? Open in Web Editor NEW

This project forked from eclipse-archived/smarthome

2.0 2.0 1.0 19.08 MB

Eclipse SmartHome project

License: Eclipse Public License 1.0

Shell 0.10% Groovy 10.22% Java 77.50% XSLT 0.01% Xtend 1.21% JavaScript 3.34% CSS 1.08% HTML 6.52% Batchfile 0.03%

smarthome's People

Contributors

alex-kostadinov avatar aounhaider1 avatar cdjackson avatar chriskn avatar clinique avatar dnobel avatar dominicdesu avatar dvanherbergen avatar gerrieg avatar gradyd avatar hmerk avatar iilievdev avatar kaikreuzer avatar kgoderis avatar maggu2810 avatar marcelrv avatar mariniss avatar marinmitev avatar olibutzki avatar paulianttila avatar pre-martin avatar sbussweiler avatar sja avatar sjsf avatar teichsta avatar tilmankamp avatar tomhoefer avatar vlad-ivanov-name avatar watou avatar yordandzhelev avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Forkers

szoubev

smarthome's Issues

Parser API should be refactored

The current API of the Parser imho does not make sense, especially the Status class.

My suggestion is to:

  • change the Parser.importData() method to return a Set of RuleDTOs or throw a ParsingException with a list of errors (like Status.errorMap)
  • remove the Status class completely (and introduce the ParsingException instead)

Add rule events

Events are currently completely missing.
Similar to the Thing infrastructure, we should have events for Rules like at least RULE_ADDED, RULE_UPDATED, RULE_REMOVED, RULE_STATUS_INFO.

Analyse and fix Startup/Timing problems

The IntegrationTest "assert that a rule added by json is executed correctly" only sometimes gets green when executed in eclipse, but never when executed in maven. There seems to be a timing problem on startup. This has to be analyzed

Fail in composite trigger

I've defined a rule which contains composite trigger and composite condition (See below). It seems to fail on the trigger when it checks:

public void receive(Event event) {

 if (!event.getTopic().contains(source)) {

}

The source that I see is $itemName. It seems that the reference wasn't replaced with the item name: demo_switch_1_switch. Currently I cannot find in the source were the replacement is being done for composite trigger.

BTW, is it valid to define a rule without action (although I know that it doesn't make any sense).

The rule:

[
{
"uid": "smart.rule.composite",
"name": "SmartRule",
"tags": [
"smart",
"rule"
],
"description": "Smart Rule definition composite.",
"on": [
{
"id": "SmartTriggerID",
"type": "ItemStateChangeTrigger",
"config": {
"itemName": "demo_switch_1_switch"
}
}
],
"if": [
{
"id": "SmartConditionID",
"type": "ItemStateEvent_ON_Condition",
"config": {
"itemName": "demo_switch_1_switch"
}
}
],
"then": [
]
}
]

BasicModuleHandlerFactory

Move the BasicModuleHandlerFactory to the api Bundle and provide methods for common useCases here. According to Issue #48 the setter and unsetter could probably be removed as the ModuleTypeRegistry is resolved in the Handlers themselves.
Additionally the BasicModuleHandlerFactory should be able to control the lifecycle of the created ModuleHandlers.

Add integration tests

As for other components, we should have Groovy integration tests that test functionality on a running OSGi framework.

Java7 code

The automation module sources should not rely on Java7 classes and code constructs in order to be compatible with other JVMs

Provide documentation

The new rule engine contribution must come with documentation

  • explaining the overall concepts/ideas
  • listing the ways for interaction (bundle resources, console, Java API, etc.)
  • showing the JSON syntax (incl. reference to the JSON schema)
  • providing examples for JSON as well as code

Fail composite condition

Hi,

See rule below. It seems that it fails "to satisfy" the condition. As far as I can see, it fails in ""EventCondition" because $event gets null in the inputs (which means event is null).

 @Override
    public boolean isSatisfied(Map<String, ?> inputs) {
        Event event = inputs.get("event") != null ? (Event) inputs.get("event") : null;
        if (event != null) {
            return isConfiguredAndMatches(TOPIC, event.getTopic()) && isConfiguredAndMatches(SOURCE, event.getSource())
                    && isConfiguredAndMatches(PAYLOAD, event.getPayload())
                    && isConfiguredAndMatches(EVENTTYPE, event.getType());
        }
        return false;
    }

The rule:

[
{
"uid": "smart.rule.composite",
"name": "SmartRule",
"tags": [
"smart",
"rule"
],
"description": "Smart Rule definition composite.",
"on": [
{
"id": "SmartTriggerID",
"type": "ItemStateChangeTrigger",
"config": {
"itemName": "demo_switch_1_switch"
}
}
],
"if": [
{
"id": "SmartConditionID",
"type": "ItemStateEvent_ON_Condition",
"config": {
"itemName": "demo_switch_1_switch"
}
}
],
"then": [
]
}
]

Rule context should be cleared on every re-execution of a rule

Currently, the rule context map is kept filled across the executions of the rule.

This can cause problems, because modules cannot know whether information is from the current execution or from previous ones.

Imagine two triggers T1 and T2, which trigger if Item A updates to ON, resp. Item B updates to ON.

If you know have:
A updates to ON -> T1 triggers, context is filled with A->ON
A updates to OFF -> No triggers, since nobody reacts on OFF
B updates to ON -> T2 triggers, context now contains A->ON, B->ON.

There are actually two problems:

  1. A following module cannot determine which trigger has been triggered as both A and B are in the context.
  2. The module might imply that A is ON, but this is a false assumption.

Event handling order for item state change event

There are two problems (which may have one root cause):

  1. the order of delivering the event to event handlers is not the same as the order in which the handlers were registered
  2. when first event handler receives the event and queries the item state - the item state is not yet changed

The consequence of these two problems is that in some rules which are triggered on item state event and the rule condition checks the item state - this check fails because the item did not receive the event prior the rule trigger and rule condition actually checks the old item state

Here is a sample test code to check the event handling

        def eventHandler = [
            receive: { Event e ->
                logger.info("Event1: " + e.topic + " = " + e)
                logger.warn('after event1, myMotionItem.state=' + myMotionItem.getState());
            },
            getSubscribedEventTypes: {
                Sets.newHashSet(ItemStateEvent.TYPE)
            },
            getEventFilter:{ null }
        ] as EventSubscriber
        registerService(eventHandler)

///////////////////////
        def eventHandler2 = [
            receive: { Event e ->
                logger.info("Event2: " + e.topic + " = " + e)
                logger.warn('after event2, myMotionItem.state=' + myMotionItem.getState());
            },
            getSubscribedEventTypes: {
                Sets.newHashSet(ItemStateEvent.TYPE)
            },
            getEventFilter:{ null }
        ] as EventSubscriber
        registerService(eventHandler2)
///////////////////////
        def eventHandler3 = [
            receive: { Event e ->
                logger.info("Event3: " + e.topic + " = " + e)
                logger.warn('after event3, myMotionItem.state=' + myMotionItem.getState());
            },
            getSubscribedEventTypes: {
                Sets.newHashSet(ItemStateEvent.TYPE)
            },
            getEventFilter:{ null }
        ] as EventSubscriber
        registerService(eventHandler3)
///////////////////////

Then when event is posted
eventPublisher.post(ItemEventFactory.createStateEvent("myMotionItem", OnOffType.ON))
the messages printed are:

Event2: smarthome/items/myMotionItem/state = myMotionItem updated to ON
after event2, myMotionItem.state=NULL
Event1: smarthome/items/myMotionItem/state = myMotionItem updated to ON
after event1, myMotionItem.state=ON
Event3: smarthome/items/myMotionItem/state = myMotionItem updated to ON
after event3, myMotionItem.state=ON

Improve Rule UID generation in RuleResourceBundleImporter

The RuleResourceBundleImporter.setUID() method has the following problems that should be addressed:

  • it uses the bundle id (vendor id), which can potentially change if a bundle is uninstalled and re-installed. Using the bundle name would imho be a better choice.
  • rulesCount is declared static and will be incremented globally. This means that rules will get different UIDs if the startup order of bundle changes or a bundle in uninstalled. The count should instead be done individually per processed bundle.
  • The rule name could potentially contain special characters that we would not want to have within the UID (which will e.g. be used as part of a URL in the REST API). We should therefore strip out any characters that we consider illegal for the UID.

Getting all module types does not consider composite types

ModuleTypeManager can return all modules by class type (getTypes(Class moduleType, Locale locale)). The issue is that if I want to get all TriggerTypes it will not return CompositeTriggerType because of the following line:

if (moduleType.getName().equals(mt.getClass().getName()))

Is it for purpose?

Remove RuleManager and RuleManagerImpl

We currently have a very long chain:
RuleRegistry->RuleRegistryImpl->RuleManager->RuleManagerImpl->RuleEngine

Many of these simply delegate calls to the next level. We should simplify this to only have

RuleRegistry->RuleRegistryImpl->RuleEngine

Adding a rule without UID to the RuleRegistry fails with NPE

Calling ruleRegistry.add(rule) for a rule without UID results in

Caused by: java.lang.NullPointerException: null
    at org.mapdb.BTreeMap.get(BTreeMap.java:595)
    at org.mapdb.BTreeMap.get(BTreeMap.java:591)
    at org.eclipse.smarthome.storage.mapdb.MapDbStorage.get(MapDbStorage.java:76)
    at org.eclipse.smarthome.core.common.registry.AbstractManagedProvider.add(AbstractManagedProvider.java:55)
    at org.eclipse.smarthome.core.common.registry.AbstractRegistry.add(AbstractRegistry.java:112)
    at org.eclipse.smarthome.automation.core.internal.RuleRegistryImpl.add(RuleRegistryImpl.java:76)
    at org.eclipse.smarthome.automation.core.internal.RuleRegistryImpl.add(RuleRegistryImpl.java:1)

The UID only seems to be created for the RuntimeRule, but it is not set in the Rule object itself before passing it to super.add(rule).

Remove requirement for Manifest header "Automation-ResourceType"

It should be equally fast to check the existence of the ESH-INF/automation resource to check whether a bundle has automation resources or not. Requiring a manifest header is a possible reason for problems, since people might tend to forget adding it.

The parser type should not be determined by the header, but by the resouce file extension.

Solve lifecycle issues at startup

Currently, the rule importer fails at startup, if the templates are not yet read from the bundle resources.
This should be changed to be stable, independent of the bundle startup order.

Methods from java 1.7 has to be workaround

In the following method of AutomationCommandList class:

 protected String parseOptionsAndParameters(String[] parameterValues) {
        boolean getId = true;
        boolean getLocale = true;
        for (int i = 0; i < parameterValues.length; i++) {
            if (null == parameterValues[i]) {
                continue;
            }
            if (parameterValues[i].charAt(0) == '-') {
                if (parameterValues[i].equals(OPTION_ST)) {
                    st = true;
                    continue;
                }
                return String.format("[Automation Commands : Command \"%s\"] Unsupported option: %s", command,
                        parameterValues[i]);
            }
            if (getId) {
                id = parameterValues[i];
                getId = false;
                continue;
            }
            if (getLocale) {
                String l = parameterValues[i];
                if (l.contains("-"))
                    locale = Locale.forLanguageTag(l);
                else
                    locale = new Locale(l);
                getLocale = false;
            }
            if (getId && getLocale)
                return String.format("[Automation Commands : Command \"%s\"] Unsupported parameter: %s", command,
                        parameterValues[i]);
        }
        return SUCCESS;
    }

is used method: forLanguageTag(), which comes from jdk 1.7. I propose to remove support of language tag and the locale to be defined only by the language code.

moduleID is not unique

In ModuleHandlerFactory we have to add the ruleId to the methods getHandler and ungetHandler to uniquely identify moduleHandlers. Also the implementation within the factories has to be adapted then.

Handle enabling/disabling of rules

The RuleRegistry must provide methods to get and set rules to enabled/disabled.
If StorageService is available, this information should be persisted in a separate Storage, otherwise it should be kept only in memory.
The "active" property should be removed from the rule JSON format. If a rule should be deactivated, this is done through a separate call to the RuleRegistry.

Synchronize ResourceBundleProviders

The IntegrationTest "assert that a rule created from a template is executed as expected" does sometimes not work because there seems to be a problem with the ResourceBundleProviders: while parsing the templates, they are validated, but the modules referenced in the template are not yet parsed. This causes that the template never will be loaded. There has to be a mechanism which tries to import failed templates again if moduleTypes are added.

Additionally here is the stacktrace:

13:29:19.753 [Automation Provider Processing Queue] ERROR o.e.s.a.p.json.TemplateJSONParser - [Template  UID : SimpleTestTemplate] Failed to validate connections of RuleTemplate with UID "SimpleTestTemplate"! Condition Type "ItemStateConditionX" does not exist!
java.lang.IllegalArgumentException: Condition Type "ItemStateConditionX" does not exist!
    at org.eclipse.smarthome.automation.core.util.ConnectionValidator.validateConditionConnections(ConnectionValidator.java:169) ~[org.eclipse.smarthome.automation.core/:na]
    at org.eclipse.smarthome.automation.core.util.ConnectionValidator.validateConnections(ConnectionValidator.java:51) ~[org.eclipse.smarthome.automation.core/:na]
    at org.eclipse.smarthome.automation.core.provider.TemplateResourceBundleProvider.importData(TemplateResourceBundleProvider.java:244) ~[org.eclipse.smarthome.automation.providers/:na]
    at org.eclipse.smarthome.automation.core.provider.AbstractResourceBundleProvider.processAutomationProvider(AbstractResourceBundleProvider.java:317) [org.eclipse.smarthome.automation.providers/:na]
    at org.eclipse.smarthome.automation.core.provider.AutomationResourceBundlesEventQueue.processBundleChanged(AutomationResourceBundlesEventQueue.java:316) [org.eclipse.smarthome.automation.providers/:na]
    at org.eclipse.smarthome.automation.core.provider.AutomationResourceBundlesEventQueue.run(AutomationResourceBundlesEventQueue.java:144) [org.eclipse.smarthome.automation.providers/:na]
    at java.lang.Thread.run(Thread.java:745) [na:1.7.0_55]

Refactor parser to parse JSON to DTOs instead of Impls

We now have the DTOs to be more or less the Java representation of our JSON structures. These DTOs will also be created by the REST API (Jersey/JAX-RS) when receiving requests. It makes sense to move the code from ManagedRuleProvider.toElement(RuleDTO) to some public helper, so that it can be used by others (e.g. the REST API).
In consequence, the Parser can be simplified to only parse into DTOs and we leave the rule construction to the caller of the parser.
Changing the Parser that way would mean it could be also independent from AutomationFactory - it really β€žjustβ€œ parses JSON to a Java object model.

NPE when adding a rule with missing module types

I have a rule that gets imported through the bundle importer. This seems to happen before the according module types are loaded and I get:

13:07:04.479 [ESH-safeCall-3] INFO  smarthome.event.RuleAddedEvent - Rule 'javascript.rule1' has been added.
13:07:04.493 [Automation Provider Processing Queue] DEBUG o.e.s.a.core.internal.RuleEngine - Added rule 'javascript.rule1'
Exception in thread "Automation Provider Processing Queue" java.lang.NullPointerException
    at org.eclipse.smarthome.automation.core.internal.RuleEngine.setDefautlValues(RuleEngine.java:1137)
    at org.eclipse.smarthome.automation.core.internal.RuleEngine.resolveDefaultValues(RuleEngine.java:1127)
    at org.eclipse.smarthome.automation.core.internal.RuleEngine.setRule(RuleEngine.java:336)
    at org.eclipse.smarthome.automation.core.internal.RuleRegistryImpl.addIntoRuleEngine(RuleRegistryImpl.java:87)
    at org.eclipse.smarthome.automation.core.internal.RuleRegistryImpl.add(RuleRegistryImpl.java:78)
    at org.eclipse.smarthome.automation.core.internal.RuleRegistryImpl.add(RuleRegistryImpl.java:1)
    at org.eclipse.smarthome.automation.internal.core.provider.RuleResourceBundleImporter.importData(RuleResourceBundleImporter.java:213)
    at org.eclipse.smarthome.automation.internal.core.provider.RuleResourceBundleImporter.processAutomationProvider(RuleResourceBundleImporter.java:183)
    at org.eclipse.smarthome.automation.internal.core.provider.AutomationResourceBundlesEventQueue.processBundleChanged(AutomationResourceBundlesEventQueue.java:319)
    at org.eclipse.smarthome.automation.internal.core.provider.AutomationResourceBundlesEventQueue.run(AutomationResourceBundlesEventQueue.java:144)
    at java.lang.Thread.run(Thread.java:745)

Double-Check returning empty Collections instead of null

ConnectionValidator.validateConnections() makes use of condition.getConnections().iterator() but a NullPointerException is thrown because condition.getConnections returns null instead of an empty collection.
Consequently returning empty collections instead of null will avoid those errors.

Localization through I18NProvider

The current Localizer class should be replaced by using the I18NProvider interface, so that a localization implementation can be plugged in (for ESH in place already).

DTO model is not "clean"

We have DTOs for almost everything, but not for ModuleTypes (e.g. no ActionTypeDTO).
From what I see, the reason is that ActionType etc. are already pojos, which are nicely serializable.
Still, this somehow brings some strange mix as the Parsers will return an object model that consists partly of DTOs and partly of classes from the API.

I see two ways to fix this:

  1. Create ActionTypeDTO etc. classes that simply extend the ActionType and nothing more.
  2. Remove the specific DTO classes altogether and instead use in general pojos from the API bundle. Since Action etc. are currently interfaces and not pojos, this would mean to change them to be classes (this could be easily done by moving the getters and setters from the ActionImpl etc. classes).

Looking at this, I think option 2 would very much simplify the architecture and move it towards what we had initially in mind (to have the API to be a representation of the JSON and not requiring additional DTOs). This would also go very well with option 2 of #58, since the rule registry could deal with the simply pojos and the RuleEngine could wrap them into Impl classes when instantiating them, connecting them and injecting handlers into them.

Allow adding rules with externally provided UID

  • RuleRegistry should only add a UID to a newly added rule, if none was provided.
  • The BundleResourceRuleImporter should add a UID to the imported rules that is derived from bundle id, version and rule name, so that it is constructed the same way every time.
  • The JSON parser must support the UID property on rules.

Adding rule without UID results in exception

When adding two rules without UID, the second one fails with

java.lang.IllegalArgumentException: Cannot add element, because an element with same UID (rule_0) already exists.
    at org.eclipse.smarthome.core.common.registry.AbstractManagedProvider.add(AbstractManagedProvider.java:56)
    at org.eclipse.smarthome.core.common.registry.AbstractRegistry.add(AbstractRegistry.java:112)
    at org.eclipse.smarthome.automation.core.internal.RuleRegistryImpl.add(RuleRegistryImpl.java:81)
    at org.eclipse.smarthome.automation.core.internal.RuleRegistryImpl.add(RuleRegistryImpl.java:1)

Ids of CustomizedModuleTypes

I would like to have only the last part of the ID be treated as the ID of an customized moduleType. So that we can express a chain for BaseModuleType->CutomModuleType->MoreCustomModuleType as follows:

"BaseModuleType": {...}

"BaseModuleType:CustomModuleType":{...}

"CustomModuleType:MoreCustomModuleType":{...}

The Ids of the CustomModuleTypes should be only CustomModuleType and MoreCustomModuleType then. With this approach the CustomModuleType only needs to know its direct parent as it should be in the implementation as well.
In the rule where these moduleTypes will be used, we then only should specify the ID of the CustomModuleType as well.

Rule creation fails if template or module types are not present

The constructor of RuleImpl throws an IllegalArgumentException, if used templates or module types are not available in the system.
This can create a bunch of critical lifecycle problems:

  • Rules can not be restored from the database, if the ManagedRuleProvider starts before bundles holding the templates or module types
    -The RuleBundleResourceImporter will fail the import, if a rule is declared in one bundle why the types are provided by a specific provider from another bundle.

I see two solutions to this problem:

  1. Try to get the dynamic behavior under control, i.e. listen for things coming and going and retry instantiation, as soon as all dependencies are available. I think this might be quite nasty to implement.
  2. Only use the DTO model within the RuleRegistry, which would cut all those dependencies. Move the instantiation problem to the RuleEngine, where the RuleImpl instances are really only required. This would allow the RuleRegistry to offer a consistent view on the rules in the system, regardless if their underlying module types are (still) available in the system or not.

I very much prefer option 2 as I think in option 1 rules can miraculously disappear from the system when module types disappear - they should rather be in an error status in this case.

Update MANIFEST.MFs

Set the Execution Environment to OSGi minimal 1.2 for all automation bundles.
Keep compiler settings of IDE/Tycho at 1.7 as is.

SampleTriggerHandler.parse() should be moved

The method SampleTriggerHandler.parse() appears to be a generally required code to resolve references in handler implementation, thus it should be moved to the AbstractModuleHandler.

I actually assume that this even applies to getSystemOutputsValues() as well?

Ensure that providers are ready when importing rules

As I understand, module type providers are added in a thread (AutomationResourceBundlesEventQueue runnable) different than the thread setRule (RuleEngine) is being called.

setRule calls ConnectionValidator which requires the providers for the rule validation process (ConnectionValidator.validateConnections). How do you make sure that providers are ready before setRule is completed?

(Mainly I refer to the case when the system starts and the rules are added via ruleRegistry.addProvider(rp);. In this case the module type providers are still not loaded).

Add basic module types

The rule engine should come with some basic module type definitions and their handlers, like Item event triggers, thing status triggers, item command actions and item state actions.

gson dependency in events

In the package org.eclipse.smarthome.core.events;
there is a class AbstractEventFactory with dependency to com.google.gson.Gson;
this dependency should be moved outside this class

Provide all module outputs as a rule context to subsequent modules

When implementing JavascriptModuleTypes, I came across a conceptional problem:

A generic "ScriptAction" type would not have any inputs defined, but it still needs access to the outputs of modules that ran before within the same rule (so that these values can be used within the script itself). As the available outputs depend on the concrete rule and its trigger modules, there is no chance for the ScriptAction type to define suitable inputs.

My suggestion would be to provide all module outputs in general as a rule context within the Map that it passed into module handlers (i.e. in execute(Map<String, ?> inputs)).
Using "." as a key within the map should hopefully prevent any clashes with the inputs.

Refactor Rule Status

Instead of different flags, there should be an aggregated RuleStatus (similar to ThingInfoStatus), which has primary values NOT_INITIALIZED, IDLE, DISABLED, RUNNING and sub-statuses like NONE, HANDLER_MISSING_ERROR, HANDLER_INITIALIZING_ERROR, CONFIGURATION_ERROR (see also ThingStatusDetail). Additionally, there should be a string message (like ThingStatusInfo.description), which is an english text providing details, which can be used in logs or admin user interfaces.

internal packages should follow guidelines

Internal packages should have the bundle name as a prefix, i.e. within the bundle org.eclipse.smarthome.automation.core' the packages should be 'org.eclipse.smarthome.automation.core.internal and not org.eclipse.smarthome.automation.internal.core.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.