Appdaemon example

Hi All,

Could someone please share with me a simple configration.yaml file and a py file that shows how the two interact.
I’ve read the tutorials which was great (and funny) but as a suggestion if it was supplied with working examples it would go a long way in explaining how the two interact.

Thanks,

Rob.

1 Like

HomeAssistant is blistfully unaware of AppDaemon so nothing goes into your configuration.yaml file.

When you setup your appdaemon.cfg file, at the top, you entered the ha_url for your home_assistant installation. It should have looked something like this. Your directories may be different depending on where you want to put files.

[AppDaemon]
ha_url = http://localhost:8123
#ha_key = 
logfile = /home/hass/appdaemon/appdaemon.log
errorfile = /home/hass/appdaemon/appdaemon.err
app_dir = /home/hass/appdaemon/conf/apps
threads = 10  
time_zone: America/Chicago
# Apps
[test]
module=test
class=test

under the apps section you put the modules and classes of any python code you write. I think the actual example takes you through writing a hello_world type of app.

If you got that far, let us know if you are getting any errors and we will try to help.

here is a copy of the hello.py file that is in the appdaemon/conf/apps directory

(hass) hass@hass:~/appdaemon/conf/apps$ cat hello.py
import appdaemon.appapi as appapi

#
# Hellow World App
#
# Args:
#

class HelloWorld(appapi.AppDaemon):

  def initialize(self):
     self.log("Hello from AppDaemon")
     self.log("You are now ready to run Apps!") 

if you run appdaemon from the command line and you see the two lines above, you have succeeded.

Thanks Turboc,

I’ve have got to that stage, was having a heap of errors on HASS 0.33, created a new image with latest HASSbian with .37 and happy days get the hello world via AppDaemon!!!

So here’s a simple task which will open up the world of appdaemon.

when platform: rpi_gpio entity ID: sensor.dht_sensor_temperature goes above a certain temperature say 30deg C to then switch on EntityID: switch.fan and lets get really complicated :slight_smile: when it falls below 30deg C to switch fan off.

Once I get my head around this, I’m sure I’ll be totally embarrassed of how easy it all is.

Rob.

See self.listen_state()

Then in your callback routine do this for a start. In practice, I think you will need more of a hysteresis loop so that the fan doesn’t keep switching on and off all the time.

  if self.get_state("sensor.fan") > 30:
    self.turn_on("switch.fan")
  else:
    self.turn_off("switch.fan")

so to elaborate a little more on what gpbenton is saying,

in your initialize function you will setup a listener using self.listen_state() as part of that call you are going to reference a callback function. For the sake of simplicity lets call it fancontrol. you will the create a function called fancontrol tha conforms to the specs for a listener callback. basically make sure you have all the arguements in the function that are required for a callback. Then in that function, use the code that gpbenton gave you to check the temperature and turn the fan on or off. But like he also said you may want to add an additional condition in there to keep the fan from turning on/off ever time the fan climbs or falls 1 degree.

do you mean this with the tutorials:

http://appdaemon.reot.org/AppDaemon_for_beginner.html

because the apps i let people create there are working.
all you have to do is replace the entities with excisting entities and it will work.

3 Likes

@ReneTode
Where has this doc been hiding my whole life!

i dont know i mentioned it at a few places on the forum. :wink:

The guide looks awesome, but reading black text on a dark blue or olive background is tricky :wink: Any chance you could make your colour choices more accessible?

2 Likes

Okay thanks all…

I’ve modified the hello.py
And taking on what you all said, changed as follows:

class HelloWorld(appapi.AppDaemon):

  def initialize(self):
    self.listen_state(fancontrol) 
	if self.get_state("sensor.fan") > 30:
      self.turn_on("switch.fan")
    else:
      self.turn_off("switch.fan")

last error reported by is: TabError: inconsistent use of tabs and spaces in indentation
But reading the link to self.listen_state() if i read it right believe it’s missing what needs to go in the section.
Sorry all, I’m sure this is basic stuff but I can’t seem to get my head around it.

Rob.

you can’t use tabs, have to use spaces.

class HelloWorld(appapi.AppDaemon):

  def initialize(self):
    self.listen_state(fancontrol) 
    if self.get_state("sensor.fan") > 30:
      self.turn_on("switch.fan")
    else:
      self.turn_off("switch.fan")

Hi Rene,

I just think some working example would go a long way.
As an idea, using one of the examples in:
pi\appdaemon\conf\examples
include a .yaml file.
I now get appdaemon works independently but it still relies on what sensors etc… you’ve setup in HASS
Once I get my head around my first working code happy to help in this space.

Rob.

Thanks for that,

thought my notepad++ automatically changed tabs to spaces.

Getting closer…
NameError: name ‘fancontrol’ is not defined

fancontrol would be the name of the sensor that you are looking for in HA.

Rene has a good point, if you haven’t been through the tutorial he has put together, you really should. It will help give you understand some of the basics and it’s not very long.

hi again:

I’ve read it but just not getting it.
So my sensor being monitored in ha is:
sensor.dht_sensor_temperature
friendly_name: DHT Sensor Temperature
unit_of_measurement: °C

The switch I’m wanting to control is:
switch.fan on
friendly_name: fan

ok, in place of fancontrol use sensor.dht_sensor_temperature and switch.fan may work, I’m not sure if AD works with friendly names, or you could just change switch.fan to switch.fanon. Is that a space between fan and on? I’m not sure how HA and AD would react to the space. You might need to put an _ in there to make it all one string of letters without a space.

So you are telling AD to go over and check the state of the control in HA. It has to be the same name as it is in HA so that it can find it. It’s like calling the office and asking what the status is on the smith project. You will only get an answer that makes sense if there really is a smith project and it’s the one you really want information about. Sam thing on turning devices on or off. Your entity has to be the device.name of the entity in HA. Make sense??

Hi mate,

yes it definetely makes sense. ie It’s got to know what to look for.
Just not working, not in front of the computer did try all sorts of variations.
The on above I should have deleted (legacy of my cut and paste).
I’ll have a play around later on, I’ll send through the error as reported by AD.

But shouldn’t the below:
if self.get_state(“sensor.fan”) > 30:
be something along the lines of “sensor.dht_sensor_temperature” “not sensor.fan”

Rob.

hi rob,
the examples i give are also working, just like the examples you mention.
the examples included in the appdaemon install are a bit more complicated, so they could be used in a future part.
i did include yaml and translated that.

i showed how this automation in yaml

automation: 
  - alias: " Turn on light when input boolean is switched on and someone is home"
  trigger:
    platform: state
    entity_id: input_boolean.some_choice
    state: 'on'
  condition:
    condition: state
    entity_id: device_tracker.some_mobile
    state: 'home'
action:
    service: light.turn_on
    entity_id: light.some_light
 

would be translated to this working app

import appdaemon.appapi as appapi
 
class your_class_name(appapi.AppDaemon):
 
  def initialize(self):  
    self.listen_state(self.what_we_want_to_do,"input_boolean.some_choice", new="on")

  def what_we_want_to_do (self, entity, attribute, old, new, kwargs):
    a_variabele_with_a_usable_name = self.get_state("device_tracker.some_mobile")
    if  a_variabele_with_a_usable_name == "home":
      self.turn_on("light.some_light")

i have written this for people who have at least some basic understanding from home assistant.
so i expect people to see input_boolean.some_choice and device_tracker.some_mobile as normal homeassistant entities.

if people dont have enough knowledge from HA basics like entities, then appdaemon isnt an option anyway.

in that what you are trying out, there are a few problems i mentioned in the tutorial too.

class HelloWorld(appapi.AppDaemon):

  def initialize(self):
    self.listen_state(fancontrol) 
	if self.get_state("sensor.fan") > 30:
      self.turn_on("switch.fan")
    else:
      self.turn_off("switch.fan")

indention:
that what comes on the next line should be indented if it belongs to the line above, if not it should have the same indention (it is possible to use tabs, but like tuboc mentioned, better to avoid it. if you use it you should use it contiously the same way) (this is basic python, for more information about indention in python i would advice seaching for it on google).
the basic parts from the tutorial:
the trigger:
in your case your temperature sensor so that would make it:

    self.listen_state(self.what_we_want_to_do, "sensor.dht_sensor_temperature" )

then the action which would start with:

 def what_we_want_to_do (self, entity, attribute, old, new, kwargs): 

so that would change your app from::

class HelloWorld(appapi.AppDaemon):

  def initialize(self):
    self.listen_state(fancontrol) 
    if self.get_state("sensor.fan") > 30:
      self.turn_on("switch.fan")
    else:
      self.turn_off("switch.fan")

to:

class HelloWorld(appapi.AppDaemon):

  def initialize(self):
    self.listen_state(self.what_we_want_to_do, "sensor.dht_sensor_temperature" )

 def what_we_want_to_do (self, entity, attribute, old, new, kwargs): 
    if new > 30:
      self.turn_on("switch.fan")
    else:
      self.turn_off("switch.fan")

to make sure it doesnt go on and of and on and off again you could change that to:

class HelloWorld(appapi.AppDaemon):

  def initialize(self):
    self.listen_state(self.what_we_want_to_do, "sensor.dht_sensor_temperature" )

 def what_we_want_to_do (self, entity, attribute, old, new, kwargs): 
    if new > 30:
      self.turn_on("switch.fan")
    if new < 29:
      self.turn_off("switch.fan")

i hope that this helps you to understand things more.

by the way, thanks for making me have a closer look to the first app again, i see that i forgot a small part there :wink:

@Tinkerer i will check into the colors. (i am partly colorblind so i see colors different :wink: )

Hi Rene,

You could be right, but I’m going to battle through this and get it going.
I’ve setup a pretty good HA environment and don’t think I’m completely nuffy…well that’ my opinion anyway :slight_smile:

Even with the error below the penny is starting to drop on the formatting.
But do get the following error:
2017-02-04 13:29:42.083610 WARNING ------------------------------------------------------------
2017-02-04 13:30:13.066118 WARNING ------------------------------------------------------------
2017-02-04 13:30:13.066553 WARNING Unexpected error in worker for App hello_world:
2017-02-04 13:30:13.066946 WARNING Worker Ags: {‘function’: <bound method HelloWorld.fanmonitor of <hello.HelloWorld object at 0x701c3090>>, ‘type’: ‘attr’, ‘new_state’: ‘25.5’, ‘old_state’: ‘25.4’, ‘id’: UUID(‘390ab624-3a47-4feb-9338-64058969c2f4’), ‘attribute’: ‘state’, ‘name’: ‘hello_world’, ‘entity’: ‘sensor.dht_sensor_temperature’, ‘kwargs’: {}}
2017-02-04 13:30:13.067292 WARNING ------------------------------------------------------------
2017-02-04 13:30:13.067964 WARNING Traceback (most recent call last):
File “/usr/local/lib/python3.4/dist-packages/appdaemon/appdaemon.py”, line 455, in worker
function(entity, attr, old_state, new_state, ha.sanitize_state_kwargs(args[“kwargs”]))
File “/home/pi/appdaemon/conf/apps/hello.py”, line 9, in fanmonitor
if new> 30:
TypeError: unorderable types: str() > int()

I do apologies for my limited knowledge.

Rob.

After some soul searching I worked it out all by myself! yipeee!!!
Had to convert new from string to float.

  def fanmonitor (self, entity, attribute, old, new, kwargs): 
   newint=float(new)
   if newint > 30:
      self.turn_on("switch.fan")
   else:
      self.turn_off("switch.fan")

Thanks all for your input.

1 Like