Thanks for spotting the get_app() example - will be fixed in the next release.
Regarding multiple callback constraints - what would you want to do?
Callback constraints are meant to be a simple way of saving programming logic but you can easily perform more complex logic in the App itself. I am hesitant about adding multiples of the same type because the next question is “should they be ANDed or ORed” - then the obvious answer is “both, and by the way can we have complex nested expressions as well” - at that point I am trying to duplicate a Python interpreter in parameters - which is what we already have in HA Automations with YAML.
I am always happy to discuss and review on the basis of other people’s experiences but for now I want to keep constraints simple - they are there to make the Apps Simpler, not move the programming into the config file.
OK, I have it coded but it will take a few days to test on account of the fact that we are limited to one sunrise and sunset per day Look out for a release in the next few days.
This is great! I can finally start moving off OpenHAB! Quick question - in the motion light example, what would be the cleanest way of dealing with repeat motion triggers - would the function triggered check timestamp of the latest motion event or is there a good way to cancel previous timers when new one is set?
Great! … how is concurrency handled on this? I cannot see anything being returned from the cancel_timer function, therefore one always has to assume that the cancellation timer ran anyway.
Answering my own question a bit, I think that locks needs to be used to ensure proper functionality even for the smallest examples (unless there is something already provided?)
Imagine the following scenario:
light_off - triggered by a timer after the light is off
light_on - triggered by a motion sensor
In the past, I had issue when the light_on was triggered exactly when the light_off started running meaning that it sent command to switch the light off and finished but right after that the light_off finished as well, immediately switching the light off. I had put in a proper lock to ensure that ligt_off and light_on cannot be ran at the same time.
The cancellation is a simple key deletion in a Python dictionary - not necessarily atomic but pretty fast.
I think this is correct but in reality not something I have come across. In my setup the sensors can only activate every 4 minutes - if I keep the light on for less than that there will never be an issue.
I have mulled over the whole subject of locking and decided to shelve it unless it started to cause issues - the fact of the matter is that even though AppDaemon is a highly concurrent architecture, processing speeds relative to real world events are quick enough that it will probably be OK 99.99% of the time - scheduler ticks happen once a second, HA state updates are asynchronous to that.
If you can convince me other wise, my plan would be to make each App single threaded to the worker threads which would probably fix most issues, and then for extra credit I would lock the scheduler and state callback tables for inserts and deletes, all of which would be trandparent to the Apps themselves.
In the meantime you can use instance variables as a less threadsafe way of achieving the same thing, or if you prefer, nothing is stopping you from rolling your own using Python libraries.
Thank you, roger that - makes sense. I will most likely use a lock in my code to be on a safe side - I think that for many (if not most) use cases the locking may not be necessary, so I am fine using a per-app solution. Curious to see if I will be proven wrong over time
i’m trying to make some general functions and call 1 from the other, but i get stuck somehow.
in de API you have a wrong example and you mention the header section but for me thats not enough.
i’m trying and trying, dont seem to get it working.
i also tried to make a file and then import that, but somehow i get stuck with self and missing arguments.
so can you please make it clear for me how to use get_app?
I fixed up the example in the latest version so the entry now reads:
get_app()
get_app() will return the instantiated object of another app running within the system. This is useful for calling functions or accessing variables that reside in different apps without requiring duplication of code.
Synopsis
get_app(self, name)
Parameters
name
Name of the app required. This is the name specified in header section of the config file, not the module or class.
How are you starting appdaemon? You need to run it as an executable in your path, e.g. appdaemon instead of trying to run the python directly from the git repository - this is as a resulkt of the pip install.
You can then run AppDaemon from the command line as follows:
$ appdaemon -c conf/appdaemon.cfg
If all is well, you should see something like the following:
$ appdaemon -c conf/appdaemon.cfg
2016-08-22 10:08:16,575 INFO Got initial state
2016-08-22 10:08:16,576 INFO Loading Module: /export/hass/appdaemon_test/conf/apps/hello.py
2016-08-22 10:08:16,578 INFO Loading Object hello_world using class HelloWorld from module hello
2016-08-22 10:08:16,580 INFO Hello from AppDaemon
2016-08-22 10:08:16,584 INFO You are now ready to run Apps!