Skip to content

Commit

Permalink
stateengine plugin: refactor se_instant_leaveaction. Can now be overw…
Browse files Browse the repository at this point in the history
…ritten by a settings item. Further adjust initialization of SE Item
  • Loading branch information
onkelandy committed Aug 22, 2023
1 parent 04791d7 commit 42581b1
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 43 deletions.
3 changes: 0 additions & 3 deletions stateengine/StateEngineDefaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@

lamella_open_value = 0

instant_leaveaction = False

plugin_identification = "StateEngine Plugin"

VERBOSE = logging.DEBUG - 1
Expand All @@ -44,4 +42,3 @@ def write_to_log(logger):
logger.info("StateEngine default suntracking lamella open value = {0}".format(lamella_open_value))
logger.info("StateEngine default startup delay = {0}".format(startup_delay))
logger.info("StateEngine default suspension time = {0}".format(suspend_time))
logger.info("StateEngine default instant_leaveaction = {0}".format(instant_leaveaction))
113 changes: 82 additions & 31 deletions stateengine/StateEngineItem.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,14 @@ def logger(self):
def instant_leaveaction(self):
return self.__instant_leaveaction

@property
def default_instant_leaveaction(self):
return self.__default_instant_leaveaction.get()

@default_instant_leaveaction.setter
def default_instant_leaveaction(self, value):
self.__default_instant_leaveaction = value

@property
def laststate(self):
_returnvalue = None if self.__laststate_item_id is None else self.__laststate_item_id.property.value
Expand Down Expand Up @@ -166,6 +174,8 @@ def __init__(self, smarthome, item, se_plugin):
self.__se_plugin = se_plugin
self.__active_schedulers = []
self.__all_releasedby = {}
self.__default_instant_leaveaction = StateEngineValue.SeValue(self, "Default Instant Leave Action", False,
"bool")
#self.__all_torelease = {}
try:
self.__id = self.__item.property.path
Expand Down Expand Up @@ -205,6 +215,9 @@ def __init__(self, smarthome, item, se_plugin):
if _startup_log_level > 0:
base = self.__sh.get_basedir()
SeLogger.manage_logdirectory(base, SeLogger.log_directory, True)
self.__log_level = _log_level
self.__instant_leaveaction = StateEngineValue.SeValue(self, "Instant Leave Action", False, "num")

# get startup delay
self.__startup_delay = StateEngineValue.SeValue(self, "Startup Delay", False, "num")
self.__startup_delay.set_from_attr(self.__item, "se_startup_delay", StateEngineDefaults.startup_delay)
Expand Down Expand Up @@ -280,9 +293,7 @@ def __init__(self, smarthome, item, se_plugin):
self.__action_status = {}
self.__state_issues = {}
self.__webif_infos = OrderedDict()
self.__instant_leaveaction = StateEngineValue.SeValue(self, "Instant Leave Action", False, "bool")
self.__instant_leaveaction.set_from_attr(self.__item, "se_instant_leaveaction",
StateEngineDefaults.instant_leaveaction)

self.__repeat_actions = StateEngineValue.SeValue(self, "Repeat actions if state is not changed", False, "bool")
self.__repeat_actions.set_from_attr(self.__item, "se_repeat_actions", True)

Expand All @@ -295,6 +306,7 @@ def __init__(self, smarthome, item, se_plugin):
self.__update_original_item = None
self.__update_original_caller = None
self.__update_original_source = None
self.__using_default_instant_leaveaction = False

# Check item configuration
self.__check_item_config()
Expand All @@ -303,7 +315,7 @@ def __init__(self, smarthome, item, se_plugin):
self.__variables = {
"item.suspend_time": self.__suspend_time.get(),
"item.suspend_remaining": 0,
"item.instant_leaveaction": self.__instant_leaveaction.get(),
"item.instant_leaveaction": 0,
"current.state_id": "",
"current.state_name": "",
"current.conditionset_id": "",
Expand All @@ -329,16 +341,37 @@ def __init__(self, smarthome, item, se_plugin):
self.__logger.error("Issue finishing states because {}", ex)
return

# Write settings to log
self.__write_to_log()

def __repr__(self):
return self.__id

def startup(self):
try:
self.__has_released.pop('initial')
except Exception:
pass
self.__logger.develop("".ljust(80, "_"))
self.__logger.develop("ALL RELEASEDBY: {}", self.__all_releasedby)
self.__logger.develop("HAS RELEASED: {}", self.__has_released)
self.__logger.info("".ljust(80, "_"))
# start timer with startup-delay
_startup_delay_param = self.__startup_delay.get()
startup_delay = 1 if self.__startup_delay.is_empty() or _startup_delay_param == 0 else _startup_delay_param
if startup_delay > 0:
first_run = self.__shtime.now() + datetime.timedelta(seconds=startup_delay)
self.__logger.info("Will start stateengine evaluation at {}", first_run)
scheduler_name = self.__id + "-Startup Delay"
value = {"item": self.__item, "caller": "Init"}
self.__se_plugin.scheduler_add(scheduler_name, self.__startup_delay_callback, value=value, next=first_run)
elif startup_delay == -1:
self.__startup_delay_over = True
self.__add_triggers()
else:
self.__startup_delay_callback(self.__item, "Init", None, None)
self.__logger.info("Reset log level to {}", self.__log_level)
self.__logger.log_level = self.__log_level

def show_issues_summary(self):
# show issues summary
filtered_dict = {key: value for key, value in self.__unused_attributes.items() if
key not in self.__used_attributes or 'issue' in value.keys()}
Expand All @@ -356,26 +389,31 @@ def __init__(self, smarthome, item, se_plugin):
if self.__state_issues:
self.__log_issues('states')

self.__logger.info("".ljust(80, "_"))
# start timer with startup-delay
_startup_delay_param = self.__startup_delay.get()
startup_delay = 1 if self.__startup_delay.is_empty() or _startup_delay_param == 0 else _startup_delay_param
if startup_delay > 0:
first_run = self.__shtime.now() + datetime.timedelta(seconds=startup_delay)
self.__logger.info("Will start stateengine evaluation at {}", first_run)
scheduler_name = self.__id + "-Startup Delay"
value = {"item": self.__item, "caller": "Init"}
self.__se_plugin.scheduler_add(scheduler_name, self.__startup_delay_callback, value=value, next=first_run)
elif startup_delay == -1:
self.__startup_delay_over = True
self.__add_triggers()
def update_leave_action(self, default_instant_leaveaction):
self.__default_instant_leaveaction = default_instant_leaveaction

_returnvalue_leave, _returntype_leave, _using_default_leave = self.__instant_leaveaction.set_from_attr(
self.__item, "se_instant_leaveaction", default_instant_leaveaction)

if len(_returnvalue_leave) > 1:
self.__logger.warning("se_instant_leaveaction for item {} can not be defined as a list"
" ({}). Using default value {}.", self.id, _returnvalue_leave, default_instant_leaveaction)
self.__instant_leaveaction.set(default_instant_leaveaction)
self.__variables.update({"item.instant_leaveaction": default_instant_leaveaction})
elif len(_returnvalue_leave) == 1 and _returnvalue_leave[0] is None:
self.__instant_leaveaction.set(default_instant_leaveaction)
self.__variables.update({"item.instant_leaveaction": default_instant_leaveaction})
self.__logger.info("Using default instant_leaveaction {0} "
"as no se_instant_leaveaction is set.".format(default_instant_leaveaction))
elif _using_default_leave:
self.__variables.update({"item.instant_leaveaction": default_instant_leaveaction})
self.__logger.info("Using default instant_leaveaction {0} "
"as no se_instant_leaveaction is set.".format(default_instant_leaveaction))
else:
self.__startup_delay_callback(self.__item, "Init", None, None)
self.__logger.info("Reset log level to {}", _log_level)
self.__logger.log_level = _log_level

def __repr__(self):
return self.__id
self.__variables.update({"item.instant_leaveaction": _returnvalue_leave})
self.__logger.info("Using instant_leaveaction {0} "
"from attribute se_instant_leaveaction. "
"Default value is {1}".format(_returnvalue_leave, default_instant_leaveaction))

def updatetemplates(self, template, value):
if value is None:
Expand Down Expand Up @@ -407,8 +445,14 @@ def run_queue(self):
base = self.__sh.get_basedir()
SeLogger.manage_logdirectory(base, SeLogger.log_directory, True)
self.__logger.debug("Current log level {}, default {}, currently using default {}",
self.__logger.log_level, _default_log_level, self.__logger.using_default)
self.__logger.debug("Current instant leave action {}", self.__instant_leaveaction)
self.__logger.log_level, _default_log_level, self.__logger.using_default_log_level)
if self.__instant_leaveaction.get() == -1:
self.__using_default_instant_leaveaction = True
else:
self.__using_default_instant_leaveaction = False
self.__logger.debug("Current instant leave action {}, default {}, currently using default {}",
self.__instant_leaveaction, self.__default_instant_leaveaction,
self.__using_default_instant_leaveaction)
self.update_lock.acquire(True, 10)
while not self.__queue.empty() and self.__ab_alive:
job = self.__queue.get()
Expand Down Expand Up @@ -459,8 +503,8 @@ def run_queue(self):
StateEngineCurrent.update()
self.__variables["item.suspend_time"] = self.__suspend_time.get()
self.__variables["item.suspend_remaining"] = -1
self.__variables["item.instant_leaveaction"] = self.__instant_leaveaction.get()

self.__variables["item.instant_leaveaction"] = self.__default_instant_leaveaction.get() \
if self.__using_default_instant_leaveaction is True else self.__instant_leaveaction.get()
# get last state
last_state = self.__laststate_get()
if last_state is not None:
Expand Down Expand Up @@ -560,7 +604,14 @@ def run_queue(self):

if not _releasedby:
# New state is different from last state
if result is False and last_state == state and self.__instant_leaveaction.get() is True:
_instant_leaveaction = self.__instant_leaveaction.get()
if self.__using_default_instant_leaveaction:
_instant_leaveaction = self.__default_instant_leaveaction.get()
if _instant_leaveaction == 1:
_instant_leaveaction = True
elif _instant_leaveaction == 0:
_instant_leaveaction = False
if result is False and last_state == state and _instant_leaveaction is True:
self.__logger.info("Leaving {0} ('{1}'). Running actions immediately.", last_state.id,
last_state.name)
last_state.run_leave(self.__repeat_actions.get())
Expand Down Expand Up @@ -1284,7 +1335,7 @@ def __verbose_crons_and_cycles(self):
return crons, cycles

# log item data
def __write_to_log(self):
def write_to_log(self):
# get crons and cycles
crons, cycles = self.__verbose_crons_and_cycles()
triggers = self.__verbose_triggers()
Expand Down
10 changes: 7 additions & 3 deletions stateengine/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,9 @@ def __init__(self, sh):
StateEngineDefaults.startup_delay = self.get_parameter_value("startup_delay_default")
StateEngineDefaults.suspend_time = self.get_parameter_value("suspend_time_default")
default_instant_leaveaction = self.get_parameter_value("instant_leaveaction")
default_instant_leaveaction_value = StateEngineValue.SeValue(self, "Instant Leave Action", False, "bool")
default_instant_leaveaction_value.set(default_instant_leaveaction)
StateEngineDefaults.instant_leaveaction = default_instant_leaveaction_value
self.__default_instant_leaveaction = StateEngineValue.SeValue(self, "Default Instant Leave Action", False, "bool")
self.__default_instant_leaveaction.set(default_instant_leaveaction)

StateEngineDefaults.suntracking_offset = self.get_parameter_value("lamella_offset")
StateEngineDefaults.lamella_open_value = self.get_parameter_value("lamella_open_value")
StateEngineDefaults.write_to_log(self.logger)
Expand Down Expand Up @@ -142,6 +142,10 @@ def run(self):
try:
abitem = StateEngineItem.SeItem(self.get_sh(), item, self)
abitem.ab_alive = True
abitem.update_leave_action(self.__default_instant_leaveaction)
abitem.write_to_log()
abitem.show_issues_summary()
abitem.startup()
self._items[abitem.id] = abitem
except ValueError as ex:
self.logger.error("Problem with Item: {0}: {1}".format(item.property.path, ex))
Expand Down
14 changes: 8 additions & 6 deletions stateengine/plugin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -291,17 +291,19 @@ item_attributes:
type: foo
default: False
description:
de: 'Ist dieser Parameter auf True gesetzt, werden "on leave" Aktionen
de: 'Ist dieser Parameter auf True bzw. 1 gesetzt, werden "on leave" Aktionen
sofort ausgeführt, wenn der aktuelle Zustand nicht mehr eingenommen wird.
Standardmäßig werden die Aktionen erst direkt vor dem Eintreten in
einen neuen Zustand getriggert. Kann auch über ein Item zur Laufzeit geändert werden,
beispielsweise durch item:..settings.instant_leaveaction.
beispielsweise durch item:..settings.instant_leaveaction. Der Wert -1 sorgt dafür,
dass der in der plugin.yaml angegebene Standardwert herangezogen wird.
'
en: 'If this parameter is set to True the "on leave" actions are run
en: 'If this parameter is set to True or 1 the "on leave" actions are run
immediately after not entering the current state
again. By default the actions are triggered directly before
entering a new state. Can also be defined by a valid item,
e.g. item:..settings.instant_leaveaction
e.g. item:..settings.instant_leaveaction. By setting the value to -1
the default value from the plugin.yaml file is used.
'

se_plugin:
Expand Down Expand Up @@ -741,9 +743,9 @@ item_structs:
initial_value: -1

instant_leaveaction:
type: bool
type: num
cache: True
initial_value: False
initial_value: -1

settings_edited:
type: bool
Expand Down

0 comments on commit 42581b1

Please sign in to comment.