Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stateengine Plugin: multiple updates and fixes #949

Merged
merged 19 commits into from
Jul 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
16e217b
stateengine plugin: add se_name to attribute parameters
onkelandy Jul 18, 2024
50b5652
stateengine plugin: fix docu
onkelandy Jul 18, 2024
f43c6f4
stateengine plugin: minor webif code fixes
onkelandy Jul 18, 2024
0f4dce3
stateengine plugin: fix web interface.. corrct handling of "force set…
onkelandy Jul 18, 2024
10a9b0b
stateengine plugin: fix condition handling, now it's working as OR, w…
onkelandy Jul 18, 2024
956ac7a
stateengine plugin: update SetForce Action
onkelandy Jul 18, 2024
35aca7d
stateengine plugin: code cleanup, fixes, improvements
onkelandy Jul 18, 2024
3612b4c
stateengine plugin: write log message when log is turned off (set to 0)
onkelandy Jul 18, 2024
168e63f
stateengine plugin: dump version to 2.0.1
onkelandy Jul 18, 2024
4a6309f
stateengine plugin: minor updates
onkelandy Jul 25, 2024
6634e68
stateengine plugin: improve and extend issue reporting when getting v…
onkelandy Jul 25, 2024
d6f96ff
stateengine plugin: attributes from items, structs, etc. referenced b…
onkelandy Jul 25, 2024
7aeb57b
stateengine plugin: don't expand item pathes at beginning so relative…
onkelandy Jul 25, 2024
5b00ffe
stateengine plugin: improve se_use handling when searching for attrib…
onkelandy Jul 25, 2024
9a358f8
stateengine plugin: minor code and logging improvements
onkelandy Jul 30, 2024
cde3630
stateengine plugin: "set" function now also returns original value, n…
onkelandy Jul 30, 2024
88b91c6
stateengine plugin: set_from_attribute function now takes an ignore l…
onkelandy Jul 30, 2024
8bc09e2
stateengine plugin: massive update of se_use handling. Now the item c…
onkelandy Jul 30, 2024
fb1ddc7
stateengine plugin: bump version to 2.1 as there were quite some edits
onkelandy Jul 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
223 changes: 122 additions & 101 deletions stateengine/StateEngineAction.py

Large diffs are not rendered by default.

193 changes: 99 additions & 94 deletions stateengine/StateEngineActions.py

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions stateengine/StateEngineCliCommands.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
# noinspection PyUnresolvedReferences
from lib.model.smartplugin import SmartPlugin
from lib.plugin import Plugins
from bin.smarthome import VERSION


class SeCliCommands:
Expand All @@ -42,7 +41,8 @@ def __init__(self, smarthome, items, logger):
self.logger.info("StateEngine: Additional CLI commands not registered because CLI plugin is too old")
else:
cli.commands.add_command("se_list", self.cli_list, "StateEngine", "se_list: list StateEngine items")
cli.commands.add_command("se_detail", self.cli_detail, "StateEngine", "se_detail [seItem]: show details on StateEngine item [seItem]")
cli.commands.add_command("se_detail", self.cli_detail, "StateEngine",
"se_detail [seItem]: show details on StateEngine item [seItem]")
self.logger.info("StateEngine: Two additional CLI commands registered")
except AttributeError as err:
self.logger.error("StateEngine: Additional CLI commands not registered because error occured.")
Expand Down
208 changes: 95 additions & 113 deletions stateengine/StateEngineCondition.py

Large diffs are not rendered by default.

23 changes: 15 additions & 8 deletions stateengine/StateEngineConditionSet.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ def name(self):
def id(self):
return self.__id

@property
def path(self):
return self.__id

# List of conditions that are part of this condition set
@property
def conditions(self):
Expand Down Expand Up @@ -111,6 +115,8 @@ def update(self, item, grandparent_item):
raise ValueError("Condition {0} error: {1}".format(name, ex))

# Update item from grandparent_item
if grandparent_item is None:
return self.__unused_attributes, self.__used_attributes
for attribute in grandparent_item.conf:
func, name = StateEngineTools.partition_strip(attribute, "_")

Expand Down Expand Up @@ -142,21 +148,22 @@ def update(self, item, grandparent_item):
return self.__unused_attributes, self.__used_attributes

# Check the condition set, optimize and complete it
# item_state: item to read from
def complete(self, item_state):
# state: state (item) to read from
def complete(self, state, use):
conditions_to_remove = []
# try to complete conditions

for name in self.conditions:
try:
if not self.__conditions[name].complete(item_state):
if not self.__conditions[name].complete(state, use):
conditions_to_remove.append(name)
continue
except ValueError as ex:
self._abitem.update_attributes(self.__unused_attributes, self.__used_attributes)
self._abitem.update_issues('state', {item_state.property.path: {'issue': ex, 'issueorigin':
[{'conditionset': self.name, 'condition': name}]}})
self._abitem.update_issues('state', {state.id: {'issue': ex, 'issueorigin':
[{'conditionset': self.name, 'condition': name}]}})
text = "State '{0}', Condition Set '{1}', Condition '{2}' Error: {3}"
raise ValueError(text.format(item_state.property.path, self.name, name, ex))
raise ValueError(text.format(state.id, self.name, name, ex))

# Remove incomplete conditions
for name in conditions_to_remove:
Expand Down Expand Up @@ -184,14 +191,14 @@ def all_conditions_matching(self, state):
try:
self._log_info("Check condition set '{0}'", self.__name)
self._log_increase_indent()
self.__previousconditionset_set(self._abitem.get_variable('current.conditionset_id'), self._abitem.get_variable('current.conditionset_name'))
self.__previousconditionset_set(self._abitem.get_variable('current.conditionset_id'),
self._abitem.get_variable('current.conditionset_name'))
self.__currentconditionset_set(self.__id.property.path, self.__name)

for name in self.__conditions:
if not self.__conditions[name].check(state):
self.__currentconditionset_set('', '')
return False
#self._abitem.previousconditionset_set(self._abitem.get_variable('previous.conditionset_id'), self._abitem.get_variable('previous.conditionset_name'))
self._abitem.lastconditionset_set(self.__id.property.path, self.__name)
return True
finally:
Expand Down
8 changes: 5 additions & 3 deletions stateengine/StateEngineConditionSets.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,12 @@ def update(self, name, item, grandparent_item):
return self.__condition_sets[name].unused_attributes, self.__condition_sets[name].used_attributes

# Check the condition sets, optimize and complete them
# item_state: item to read from
def complete(self, item_state):
# state: item (item) to read from
def complete(self, state, use=None):
if use is None:
use = state.use.get()
for name in self.__condition_sets:
self.__condition_sets[name].complete(item_state)
self.__condition_sets[name].complete(state, use)

# Write all condition sets to logger
def write_to_logger(self):
Expand Down
46 changes: 26 additions & 20 deletions stateengine/StateEngineEval.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ def remap(_value, _minoutput):
_lamella_open_value = StateEngineDefaults.lamella_open_value
_lamella_text = " (based on lamella open value of {0})".format(_lamella_open_value)
value = remap(90 - altitude, _lamella_open_value) + offset
self._log_debug("Blinds at right angle to the sun at {0}° with an offset of {1}°{2}", value, offset, _lamella_text)
self._log_debug("Blinds at right angle to the sun at {0}° with an offset of {1}°{2}",
value, offset, _lamella_text)

self._log_decrease_indent()
self._eval_lock.release()
Expand Down Expand Up @@ -94,8 +95,8 @@ def get_variable(self, varname):
self._eval_lock.acquire()
self._log_debug("Executing method 'get_variable({0})'", varname)
try:
if self._abitem._initactionname and varname == 'current.action_name':
returnvalue = self._abitem._initactionname
if self._abitem.initactionname and varname == 'current.action_name':
returnvalue = self._abitem.initactionname
self._log_debug("Return '{}' for variable {} during init", returnvalue, varname)
else:
returnvalue = self._abitem.get_variable(varname)
Expand All @@ -115,8 +116,8 @@ def get_relative_itemid(self, subitem_id):
self._eval_lock.acquire()
self._log_debug("Executing method 'get_relative_itemid({0})'", subitem_id)
try:
if self._abitem._initstate and subitem_id == '..state_name':
returnvalue = self._abitem.return_item(self._abitem._initstate.id)[0].property.path
if self._abitem.initstate and subitem_id == '..state_name':
returnvalue = self._abitem.return_item(self._abitem.initstate.id)[0].property.path
self._log_debug("Return item path '{0}' during init", returnvalue)
else:
returnvalue = self._abitem.return_item(subitem_id)[0].property.path
Expand All @@ -136,8 +137,8 @@ def get_relative_item(self, subitem_id):
self._eval_lock.acquire()
self._log_debug("Executing method 'get_relative_item({0})'", subitem_id)
try:
if self._abitem._initstate and subitem_id == '..state_name':
returnvalue, issue = self._abitem.return_item(self._abitem._initstate.id)
if self._abitem.initstate and subitem_id == '..state_name':
returnvalue, issue = self._abitem.return_item(self._abitem.initstate.id)
self._log_debug("Return item '{0}' during init", returnvalue)
else:
returnvalue, issue = self._abitem.return_item(subitem_id)
Expand All @@ -158,14 +159,16 @@ def get_relative_itemvalue(self, subitem_id):
returnvalue = []
self._log_debug("Executing method 'get_relative_itemvalue({0})'", subitem_id)
try:
if self._abitem._initstate and subitem_id == '..state_name':
returnvalue = self._abitem._initstate.text
if self._abitem.initstate and subitem_id == '..state_name':
returnvalue = self._abitem.initstate.text
self._log_debug("Return item value '{0}' during init", returnvalue)
else:
item, issue = self._abitem.return_item(subitem_id)
returnvalue = item.property.value
returnvalue = StateEngineTools.convert_str_to_list(returnvalue)
self._log_debug("Return item value '{0}' for item {1}", returnvalue, subitem_id)
issue = f" Issue: {issue}" if issue not in [[], None, [None]] else ""
self._log_debug("Return item value '{0}' for item {1}.{2}",
returnvalue, subitem_id, issue)
except Exception as ex:
self._log_warning("Problem evaluating value of '{0}': {1}", subitem_id, ex)
finally:
Expand All @@ -182,16 +185,17 @@ def get_relative_itemproperty(self, subitem_id, prop):
self._eval_lock.acquire()
self._log_debug("Executing method 'get_relative_itemproperty({0}, {1})'", subitem_id, prop)
try:
item, issue = self._abitem.return_item(subitem_id)
item, _ = self._abitem.return_item(subitem_id)
except Exception as ex:
self._log_warning("Problem evaluating property of {0} - relative item might not exist. Error: {1}", subitem_id, ex)
self._log_warning("Problem evaluating property of {0} - relative item might not exist. Error: {1}",
subitem_id, ex)
self._eval_lock.release()
return
try:
if self._abitem._initstate and subitem_id == '..state_name':
returnvalue = getattr(self._abitem.return_item(self._abitem._initstate.id)[0].property, prop)
if self._abitem.initstate and subitem_id == '..state_name':
returnvalue = getattr(self._abitem.return_item(self._abitem.initstate.id)[0].property, prop)
self._log_debug("Return item property '{0}' from {1}: {2} during init", prop,
self._abitem.return_item(self._abitem._initstate.id)[0].property.path, returnvalue)
self._abitem.return_item(self._abitem.initstate.id)[0].property.path, returnvalue)
else:
returnvalue = getattr(item.property, prop)
if prop == "value":
Expand Down Expand Up @@ -221,20 +225,22 @@ def get_attribute_value(self, item, attrib):
def get_attributevalue(self, item, attrib):
self._eval_lock.acquire()
self._log_debug("Executing method 'get_attributevalue({0}, {1})'", item, attrib)
issue = None
if ":" in item:
var_type, item = StateEngineTools.partition_strip(item, ":")
if var_type == "var":
item, issue = self._abitem.return_item(self._abitem.get_variable(item))
else:
item, issue = self._abitem.return_item(item)
try:
if self._abitem._initstate and item == '..state_name':
returnvalue = self._abitem.return_item(self._abitem._initstate.id).conf[attrib]
self._log_debug("Return item attribute '{0}' from {1}: {2} during init",
attrib, self._abitem.return_item(self._abitem._initstate.id)[0].property.path, returnvalue)
if self._abitem.initstate and item == '..state_name':
returnvalue, issue = self._abitem.return_item(self._abitem.initstate.id).conf[attrib]
self._log_debug("Return item attribute '{0}' from {1}: {2} during init. Issue {3}", attrib,
self._abitem.return_item(self._abitem.initstate.id)[0].property.path, returnvalue, issue)
else:
returnvalue = item.conf[attrib]
self._log_debug("Return item attribute {0} from {1}: {2}", attrib, item.property.path, returnvalue)
self._log_debug("Return item attribute {0} from {1}: {2}. Issue {3}",
attrib, item.property.path, returnvalue, issue)
except Exception as ex:
returnvalue = None
self._log_warning("Problem evaluating attribute {0} of {1} - attribute might not exist. "
Expand Down
8 changes: 3 additions & 5 deletions stateengine/StateEngineFunctions.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
from . import StateEngineLogger
from . import StateEngineTools
from . import StateEngineDefaults
from lib.item import Items
from ast import literal_eval


Expand All @@ -45,7 +44,6 @@ def __init__(self, smarthome=None, logger=None):
self.__locks = {}
self.__global_struct = {}
self.__ab_alive = False
self.itemsApi = Items.get_instance()

def __repr__(self):
return "SeFunctions"
Expand Down Expand Up @@ -99,7 +97,7 @@ def check_include_exclude(entry_type):
elog.decrease_indent()
return None

item = self.itemsApi.return_item(item_id)
item = self.__sh.return_item(item_id)
if item is None:
self.logger.error("manual_item_update_eval: item {0} not found!".format(item_id))

Expand All @@ -113,7 +111,7 @@ def check_include_exclude(entry_type):

if "se_manual_logitem" in item.conf:
elog_item_id = item.conf["se_manual_logitem"]
elog_item = self.itemsApi.return_item(elog_item_id)
elog_item = self.__sh.return_item(elog_item_id)
if elog_item is None:
self.logger.error("manual_item_update_item: se_manual_logitem {0} not found!".format(elog_item_id))
elog = StateEngineLogger.SeLoggerDummy()
Expand All @@ -128,7 +126,7 @@ def check_include_exclude(entry_type):
retval_trigger = not item()
elog.info("Current value of item {0} is {1}", item_id, retval_no_trigger)

original_caller, original_source = StateEngineTools.get_original_caller(elog, caller, source)
original_caller, original_source = StateEngineTools.get_original_caller(self.__sh, elog, caller, source)
elog.info("get_caller({0}, {1}): original trigger by {2}:{3}", caller, source,
original_caller, original_source)
original = "{}:{}".format(original_caller, original_source)
Expand Down
Loading
Loading