I swear AppDaemon quit working when I wasn't looking

I had finally gotten AD working yesterday afternoon, sending some simple Harmony commands. I had to put everything down for a few hours to make dinner and spend time with my wife for a few hours. I opened up the laptop and everything had gone sideways.

My same script no longer worked. The config checker said my scripts.yaml was now illegal with my harmony commands. I’ve restored things from backup and can’t sort it out.

Can someone help me sort this out?

appdaemon.yaml (in /home/homeassistant/conf)

appdaemon:
  threads: 10
  time_zone: America/Chicago
  api_port: 8888
  app_dir: /home/homeassistant/.homeassistant/appdaemon/apps
  plugins:
    HASS:
      type: hass
      token: xxxxxxx
      ha_url: http://hassbian.local:8123

log:
  errorfile: /home/homeassistant/log-appdaemon/appdaemon.log
  logfile: /home/homeassistant/log-appdaemon/appdaemon.log
  accessfile: /home/homeassistant/log-appdaemon/appdaemon.log

apps.yaml (also in same directory)

harmony:
  module: harmony
  class: activity

harmony:
  module: harmony
  class: command

A couple examples from scripts.yaml:

tv:
  harmony:
    activity: Watch TV

xbox:
  harmony:
    activity: Play Xbox 

(…)

volumedown:
  harmony:
    command: VolumeDown

down:
  harmony:
    command: DirectionDown

And finally, my harmony.py script:

import appdaemon.appapi as appapi

# Harmony Hub  Control
# 
# Activities and commands
#
#
class activity(appapi.AppDaemon):

  def initialize(self):

     activity_name = self.args["param1"]
     command = self.args["param2"]

     self.log("Harmony app started.")
     self.log("Activity passed in: {}", activity_name)

     self.start_activity(self, activity_name)
     self.run_command(self, command)

  def start_activity(self, activity):
    self.turn_on("remote.harmony_hub", activity)

  def run_command(self, commands):
    harmony_state = self.get_state("remote.harmony_hub", attribute="CurrentActivity")

    if (harmony_state == "Watch TV"):
      target_device = "Xfinity DVR"
    else:
      target_device = "TCL TV"

    self.call_service("remote/send.command", entity_id="remote.harmony_hub", device=target_device, data="command")

Can anyone tell me if there’s something wrong with this? Perhaps HA restarted while I was AFK? I don’t have auto-update or anything. I checked and I’m running the most recent version of both AD and HA.

Any ideas?

We will need to see your logs to understand what errors are happening

Doh! I pasted in everything else. Here’s the last 50 lines of my log. It repeats and repeats.

The above is wrong - in the first place you have the same app name twice, meaning the first is being ignored, and in the seccond you have the wrong classname, it should be activity as you have in the first version. The error is saying it can;t find the class command in your .py file. I’ll make the error clearer but that is the issue.

Isn’t the structure for apps.yaml this?

script_command:
  module: python_script_without_py
  class: python_func_within_module

?

I’m not sure what you mean by script_command - that’s the app name, but it has to be unique for each app.

The app_name… you don’t mean the python script, do you? Or do you mean an arbitrary “command name” that runs the following two lines?

Each app consists of a .py file (the module), that has one or more classes in it. An individual app is defined as a unique name that uses a specific class from the module. Different apps can use the same module and class combination, and do different things based on their parameters, e.g. work with different devices etc.

In the above, I don;t know what scripts.yaml is supposed to be, it isn’t an AppDaemon construct.

The docs explain it in a little more depth:

https://appdaemon.readthedocs.io/en/latest/APPGUIDE.html#configuration-of-apps

1 Like

Thanks for your help. I know I’m not the only one who finIds the official docs a little hard to understand sometimes.

scripts.yaml is a list of scripts called by click spots on a picture-entity card that forms a primitive remote control. It used to be packed with manual remote.send_command calls, but AD makes it much simpler. Well, sort of. :wink:

I think I understand how this works, now. Some of the terminology has to get absorbed into my brain, but I think I’ve got it.

You rock.

Thanks.

1 Like

there may be some parts that are not that easy but this basic part is absolutely clear as a bell.

you dont find anything like this:

script_command:
  module: python_script_without_py
  class: python_func_within_module

in the docs, and just looking at some examples or in dozens of topic here on the forum shows that it is:

the_apps_name:
  module: python_script_without_py
  class: the_name_of_the_class_inside_the_python_script

its called class and not function :wink:

but i noticed something else:

class activity(appapi.AppDaemon):

unless you use an old version from appdaemon (version 2) this cant work.
if you dont i advice to upgrade, if do so you need to adapt your app, because its written for appdaemon V2

how to:
https://appdaemon.readthedocs.io/en/latest/UPGRADE_FROM_2.x.html

Okay, I got the module and class parts understood.

What’s the meaning (and usage) of the_apps_name? Is it just a name? Or is it tied to the Python script in some way?

So say I have a Python program defined in apps.yaml like you’ve pulled from the docs.

If I want a second class within the same Python script, I’d take the example you pulled from the docs and define it like this:

another_app_name:
  module: same_python_script_without_py
  class: a_different_class_in_the_same_python_script

Correct?

I think what’s confusing me is that my “apps” are actually Python functions sending Harmony remote functions, taking advantage of the advanced capabilities of Python for if/then blocks and such for different devices.

I thank you all for your help.

its the name from the app it ties to the python script with the module and class.

you can have several apps connecting to the same script and class as well.

the parameters that you use inside your python script will be set in the yaml.
so if you use
activity_name = self.args[“param1”]
you need to set the param1 like this:

the_apps_name:
  module: python_script_without_py
  class: the_name_of_the_class_inside_the_python_script
  param1: some_param

but your total app has no trigger.
it will only start once, when you restart appdaemon at that moment it will start run_command and it will call the service.

i think you need to read appdaemon for beginner, to understand how to build an app

because what you got now isnt an app, its a pyscript that needs to be started manually

Okay, I admit I must be in over my head. I’ll back up and read everything before bothering people with questions.

1 Like

i think that if you have read my tutorial you will understand more from how it works and then ill be happy to help you adchieve what you want.

I think I misunderstood the entire basic concept. I need a Python script that’s more flexible than what I can manage with YAML. I think Python Scripts might be more appropriate.

i think you misunderstand again.
appdaemon apps are python scripts.
the yaml is only there to start it and to put args in if you like

you need to use listen_state to listen to an action from HA
and then you need to put in the callback what you want it to do

I’m working on it. It’s been a long day and I’m too tired to try learning and understanding new technical stuff. Will try again tomorrow.

1 Like

dont start trying to create an app to use for your harmony at once.

read my tutorial again tommorow, create an app that logs something when you turn on a light, or recreate 1 of the apps i use in the tutorial.

when you understand what you are doing and know the concept then try to do something with the harmony.

i wish you a good night.

Okay, here’s a (hopefully) legitimate question based on reading the docs and studying the example apps.

All the example apps show AppDaemon responding to external events. I get that, and see a use for it in the future (monitoring power usage for a washer and dryer to tell when laundry is done).

However, I’m creating actions from within HA. I’ve got icons with tap-action methods that call a service. Each one was calling a script to trigger Harmony command. So I’m not monitoring the state of the Harmony and reacting to it - I’m trying to send commands to control it.

That’s why I’m now thinking Python Scripts are a better choice for what I’m trying to do. Although they’re quite limited, the services they create can contain just enough Python for me to assemble the right Harmony commands before triggering them. I need basic conditionals and the ability to build a string to send - nothing else, really. It was too messy and complicated with YAML and templates, so I decided to move to Python. It just seems I didn’t understand how AppDaemon works and how it’s supposed to be used.

I hope I’ve demonstrated enough understanding of AppDaemon and explained my project clearly enough to justify your previous help.

Thanks.

the tap-action that calls a service creates an event in HA.
in AD you can listen to that event with listen_event
and you can perform any python action based on that in the callback from the listen_event.

so instead of the script you got in ha you would have a callback in python.

appdaemon has all possible actions.

  • state change based
  • event based
  • time based
  • sunset/sunrise based

there is really nothing you can do with python scripts in HA that you cant do with appdaemon.

so if you didnt realise that, i guess you still didnt read enough :wink:

an app in your harmony case would look like (pseudocode):

import

class(hass.Hass):
  def initialise():
    self.listen_event(self.callbackname,"event","something in the event")
  def callbackname(...):
    self.log("you pussed button ... with tapaction something")
    # do what you want
    # including calling services, changing states, retrieving states, or prosponed actions