Help with self.args

I am trying to create an app that will adjust the volume of all the media players in the entities list when the state has been paused for 15 seconds. If I set this app up with just one entity hard coded it works. However when I try to implement the entities list it does not work, even though I don’t get any errors from the app daemon log. Considering the if new == paused self.log doesn’t occur I assume there is an issue with my state monitoring. Here is the code:
Apps.yaml file

night_volume_control:
  module: night-volume-control
  class: night_volume_control
  entities:
    - media_player.master_bedroom
    - media_player.lloyd_s_echo_dot_2

module file:

import appdaemon.plugins.hass.hassapi as hass

class night_volume_control(hass.Hass):

    def initialize(self):
        for media_player in self.args["entities"]:
            self.listen_state(self.control, self.args["entities"], new = "paused", duration = 15)

    def control(self, entity, attribute, old, new, kwargs):
        for media_player in self.args["entities"]:
            if new == "paused":
                self.log("module: __module__, function: __function__, MSG: Paused registered")
                self.call_service("media_player/volume_set", self.args["entities"], volume_level = .2)

Thanks in advance for any input!

In your initialize method you loop through the entities list and create a listener for each media_player. This means, in case one of the media_players in your list goes to “paused” for 15 seconds, then and ONLY then the method control will be called.
So in your control method, you just need to adjust the volume, no looping or if new == "paused".
In your control method you can use the argument entity, which is provided when the method is called, to determine which player has been paused for 15 seconds.

import appdaemon.plugins.hass.hassapi as hass

class night_volume_control(hass.Hass):

def initialize(self):
    for media_player in self.args["entities"]:
        self.listen_state(self.control, self.args["entities"], new="paused", duration=15)

def control(self, entity, attribute, old, new, kwargs):
    self.log("module: __module__, function: __function__, MSG: Paused registered")
    self.call_service("media_player/volume_set", entity, volume_level=.2)

Just curious, why do you need the the path to your module in the log?

Thanks for the input, I see that it should work. I will try it out when I get home tonight. As far as the path in the module log I just copied and pasted from an example I found online and haven’t had the chance to go through and clean things up. I am extremely green when it comes to programming and python but figured app daemon may be a good way to start learning python as someday I would like to give back to the HA community in the form of code contributions but I have a lot to learn before that happens. Thanks again for your help!

I advise you to read through the AppDaemon documentation. Especially this https://appdaemon.readthedocs.io/en/latest/APPGUIDE.html. It’s quite a bit to read, but it will help you improve your skills with AppDaemon.
I would also suggest to read a bit about code formatting for python in general, like PEP8. For example, class names should always be CamelCase, NightVolumeControl instead of night_volume_control

Many thanks. I will be sure to check out the mentioned resources.

I had a chance to try the revised code however it’s still not working, any suggestions or advice on how I could log what might be going on?

Here is a copy past from my file:

import appdaemon.plugins.hass.hassapi as hass

class NightVolumeControl(hass.Hass):

def initialize(self):
    for media_player in self.args["entities"]:
        self.listen_state(self.control, self.args["entities"], new ="paused", duration=15)

def control(self, entity, attribute, old, new, kwargs):
        if new == "paused":
            self.log("module: __module__, function: __function__, MSG: Paused registered")
            self.call_service("media_player/volume_set", entity, volume_level=.2)

I did notice, the self.log under the control method never gets called, I haven’t been able to figure out why though.

Your third line should be:

self.listen_state(self.control, media_player, new ="paused", duration=15)

Basically, when you say for media_player in self.args["entities"]:, you are looping through the list of entities and assigning each one to media_player and then doing something. So, you want to set up a listener for each media_player. Right now you’re trying to pass the whole list of entities in to a single listener which will not work.

@apop

With the addition of your code the control function now appears to getting called, however I get this error from app daemon:

2019-05-31 15:22:52.003746 WARNING AppDaemon: ------------------------------------------------------------
2019-05-31 15:24:37.013951 INFO audio_control: module: /config/appdaemon/apps/audio-control.py,function: control, MSG: Amp Off
2019-05-31 15:26:41.260096 INFO AppDaemon: Terminating night_volume_control
2019-05-31 15:26:41.260455 INFO AppDaemon: Reloading Module: /config/appdaemon/apps/night-volume-control.py
2019-05-31 15:26:41.261676 INFO AppDaemon: Initializing app night_volume_control using class NightVolumeControl from module night-volume-control
2019-05-31 15:26:42.264342 INFO AppDaemon: Terminating night_volume_control
2019-05-31 15:26:42.264574 INFO AppDaemon: Reloading Module: /config/appdaemon/apps/night-volume-control.py
2019-05-31 15:26:42.265848 INFO AppDaemon: Initializing app night_volume_control using class NightVolumeControl from module night-volume-control
2019-05-31 15:26:48.686788 INFO audio_control: module: /config/appdaemon/apps/audio-control.py, function: control, MSG: Amp on
2019-05-31 15:27:04.003192 INFO night_volume_control: module: /config/appdaemon/apps/night-volume-control.py, function: control, MSG: Paused registered
2019-05-31 15:27:04.003388 WARNING AppDaemon: ------------------------------------------------------------
2019-05-31 15:27:04.003659 WARNING AppDaemon: Unexpected error in worker for App night_volume_control:
2019-05-31 15:27:04.003788 WARNING AppDaemon: Worker Ags: {'name': 'night_volume_control', 'id': UUID('2dadd670-fbd3-4509-8eae-cc83f255165d'), 'type': 'attr', 'function': <bound method NightVolumeControl.control of <night-volume-control.NightVolumeControl object at 0x7f56ee66c278>>, 'attribute': 'state', 'entity': 'media_player.mpd', 'new_state': 'paused', 'old_state': 'playing', 'kwargs': {'entity': 'media_player.mpd', 'attribute': 'state', 'old_state': 'playing', 'new_state': 'paused', 'new': 'paused', 'duration': 15, 'handle': UUID('794cd5d7-c103-4033-88d7-7189a2c677c6')}}
2019-05-31 15:27:04.003891 WARNING AppDaemon: ------------------------------------------------------------
2019-05-31 15:27:04.004159 WARNING AppDaemon: Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/appdaemon/appdaemon.py", line 595, in worker
    self.sanitize_state_kwargs(app, args["kwargs"]))
  File "/config/appdaemon/apps/night-volume-control.py", line 13, in control
    self.call_service("media_player/volume_set", entity, volume_level=.2)
  File "/usr/local/lib/python3.7/site-packages/appdaemon/plugins/hass/hassapi.py", line 22, in func_wrapper
    return func(*args, **kwargs)
TypeError: call_service() takes 2 positional arguments but 3 were given

Here is the full code for reference.

import appdaemon.plugins.hass.hassapi as hass

class NightVolumeControl(hass.Hass):

def initialize(self):
    for media_player in self.args["entities"]:
        self.listen_state(self.control, self.args["entities"], new="paused", duration=15)
        self.listen_state(self.control, media_player, new ="paused", duration=15)

def control(self, entity, attribute, old, new, kwargs):
        if new == "paused":
            self.log("module: __module__, function: __function__, MSG: Paused registered")
            self.call_service("media_player/volume_set", entity, volume_level=.2)

import appdaemon.plugins.hass.hassapi as hass

class NightVolumeControl(hass.Hass):

def initialize(self):
    for media_player in self.args["entities"]:
        self.listen_state(self.control, self.args["entities"], new="paused", duration=5)
        self.listen_state(self.control, media_player, new ="paused", duration=5)

def control(self, entity, attribute, old, new, kwargs):
        if new == "paused":
            self.call_service("media_player/volume_set", entity_id = entity, volume_level=.2)

Thank you everyone for your help, this has been resolved. I did not have the service call syntax correct. it should be

You don’t need this line:

self.listen_state(self.control, self.args["entities"], new="paused", duration=5)

And you also don’t need the if new == "paused", because you already have this condition in your listener.

def initialize(self):
    for media_player in self.args["entities"]:
        self.listen_state(self.control, media_player, new ="paused", duration=5)

def control(self, entity, attribute, old, new, kwargs):
    self.call_service("media_player/volume_set", entity_id = entity, volume_level=.2)