Reuse custom constrain

Hi
I created at custom constrain, but I’ve like to use it across different Appdaemon Apps/Classes. Is there a dynamic way to register a constraint? I tried using a second Class, but keep getting error. If not, what the best Pythonway to reuse the function?
And second, Globals parameters in App daemon? I’m using the time constrain, it would be nice if I only had to set the time period one place.

Thanks
/Lars

            if "constrain_list" in self.args:
                self.register_constraint("custom_constrain_multi")
                self.listen_event(self.start_preset, custom_constrain_multi=self.args["constrain_list"],
                    event="MQTT_MESSAGE", namespace="mqtt", topic="home/preset/"+self.topic, payload="on")
            else:
                self.listen_event(self.start_preset, event="MQTT_MESSAGE", namespace="mqtt", 
                    topic="home/preset/"+self.topic, payload="on")

I’m not sure if this works, but you could try creating an app for your custom constraints, like my_constraints.py and then import the constrain from this app whenever you want to use it with:

from my_constraints import custom_constrain_multi

You’d need to try it, but I think this should work.

Regarding globals, check this part of the docs.

I can’t find a working combo. I’m still stuck on how to parse the custom constraint.
AttributeError: ‘Test’ object has no attribute ‘custom_constraint_multi’

test.py
I been using my test Class and trying the different imports etc,

import hassapi as hass
import mqttapi as mqtt
from include import utils
from include import constraints
#from include.constraints import CustomConstrains

class Test(mqtt.Mqtt, hass.Hass):
    def initialize(self):
        self.convert = utils.Converter()
        self.register_constraint("custom_constraint_multi")
        self.listen_event(self._deconz_event,"deconz_event", id="kon_swi_bord02", 
            custom_constraint_multi=self.args["constrain_list"])
        self.listen_event(self._deconz_event, event="MQTT_MESSAGE", 
            namespace="mqtt", topic="home/preset/test",
            custom_constraint_multi=self.args["constrain_list"])

Constraints.py

import hassapi as hass
from include import utils

class CustomConstraints(hass.Hass):
    def custom_constrain_multi(self, constrain_list):
        list_true = []
        list_false = []
        for item in constrain_list:
            try:
                entity = self.split_device_list(item)[0]
                action = self.split_device_list(item)[1]

                if action.lower() in ("true","on"):
                    list_true.append(entity)
                elif action.lower() in ("false", "off"):
                    entity_state = self.convert.str2bool(self.get_state(entity))
                    self.log("Get False State %s (%s)" % (entity,entity_state))
                    list_false.append(entity_state)
            except IndexError:
                    self.error("Failed to sort %s" % item)

        self.log("%s vs %s" % (self.custom_constrain_list(list_true),all(e == False for e in list_false)))
        if self.custom_constrain_list(list_true) and all(e == False for e in list_false):
            return True
        else:
            return False

    def custom_constrain_list(self, entity_list):
        condition_list = []
        for item in entity_list:
            self._verbose("Get State %s (%s)" % (item,self.get_state(item, attribute="state")))
            condition_list.append(
                self.convert.str2bool(
                    self.get_state(item, attribute="state")))
 
        if all(condition_list):
            return True
        else:
            return False

Your import is not correct.

it would have to be:
from constraints import custom_constrain_multi

But I don’t understand your custom_constrain_multi. Where does self.split_device_list come from?

Sorry, I didn’t mention constraint.py was in separate directory “include”. I moved constraint.py into same directory as test.py and trimmed test.py down to the basic and still get the same error.

  File "/appdaemon/lib/python3.7/site-packages/appdaemon/threading.py", line 552, in check_constraint
    method = getattr(app, key)
AttributeError: 'Test' object has no attribute 'custom_constraint_multi'

test.py

import hassapi as hass
from constraints import CustomConstraints

class Test(hass.Hass):
    def initialize(self):
        self.register_constraint("custom_constraint_multi")
        self.listen_event(self._deconz_event,"deconz_event", id="kon_swi_bord02", 
            custom_constraint_multi=self.args["constrain_list"])

    def _deconz_event(self, deconz_event, deconz_entity, kwargs):
        light = "light.kon_loftlys"
        self.toggle(light)

If I try to import function direcly i get import error.

from constraints import custom_constrain_multi

ImportError: cannot import name 'custom_constrain_multi' from 'constraints' (/appdaemon/conf/apps/test/constraints.py)
    from constraints import custom_constrain_multi

I’m parsing boolean and sensors in constrain_list using split_device_list to split up sensor and wanted state. The custom constraint is working when in the Test class.

test:
  module: test
  class: Test
  log: test_log
  constrain_list:
   - input_boolean.input_bool_guest_mode,off
   - input_boolean.input_bool_test01,on
   - input_boolean.input_bool_night_mode,off
   - calendar.skema_fri,off

I got help on AppDaemon Discord
Load constraint from “dummy app”

class Test(hass.Hass):
    def initialize(self):
        self.register_constraint("custom_constraint")
        self.listen_event(self._deconz_event,"deconz_event", id="kon_swi_bord02",
             custom_constraint=self.args["constrain_list"])
    def custom_constraint(self, conditions):
        return self.get_app("constrain_app").my_constrain(conditions)

class Constrain(hass.Hass):
    def initialize(self):
        return
    def my_constrain(conditions):
        return False

with yaml:

test_app:
  module: ...
  class: Test
  constrain_list:
    - ...
constrain_app:
  module: ...
  class: Constrain