Turn off TV if Chromecast isn't playing within 15 minutes

We have a challenge that our kids sometimes turn the TV on, but then just walks away leaving it on until an adult turns it off again.

We only use our TV with a Chromecast, so I would like to let the TV run in 15 minutes, then check if the Chromecast is playing, and if not turn the TV off.

I tried to make an app like below, but that doesn’t turn the TV off? I suppose it is the run_in() it is wrong?

import appdaemon.plugins.hass.hassapi as hass

class tv_off(hass.Hass):

  def initialize(self):
    self.listen_state(self.tv,"media_player.ps59d7000_ps59d7000", new="on")
   
  def tv (self, entity, attribute, old, new, kwargs):
    if self.run_in("media_player.ps59d7000_ps59d7000",900) == "on" and self.get_state("media_player.stue") == "off" :
        self.turn_off("media_player.ps59d7000_ps59d7000")

Please try the below, quick and dirty script I wrote, which should solve your problem.
There’s probably a more elegant solution to this, but it should work.

import appdaemon.plugins.hass.hassapi as hass

class tv_off(hass.Hass):

    def initialize(self):
        self.listen_state(self.tv,"media_player.ps59d7000_ps59d7000")

        def tv(self, entity, attribute, old, new, kwargs):
            if new == "on":
                self.run_in(turn_tv_off, 900)

        def turn_tv_off(self, kwargs):
            if self.get_state("media_player.stue") == "off":
                self.turn_off("media_player.ps59d7000_ps59d7000")

You should read a bit more in the documentation and try some examples.
However, I’ll quickly explain what the above script does:

self.listen_state(self.tv, ""media_player.ps59d7000_ps59d7000")

executes the function “tv” as soon as the state of the TV changes.

 def tv(self, entity, attribute, old, new, kwargs):
     if new == "on":
         self.run_in(turn_tv_off, 900)

if the new state of the TV is “on” it will execute the function “turn_tv_off” in 900 seconds.

def turn_tv_off(self, kwargs):
      if self.get_state("media_player.stue") == "off":
          self.turn_off("media_player.ps59d7000_ps59d7000")

if the state of the chromecast is “off” it turns the TV off.

Please try this, if it doesn’t work, please show the log files and I will try to help.

1 Like

the biggest part of programming is to learn how to program.
well written answer.

This can be done very easily using a normal automation rather than AppDaemon… just a thought. I have an automation which does exactly this but for my amplifier with a ChromeCast Audio. It also has conditions to ensure the amp doesnt get turned off if the TV is on since I may have stopped streaming audio and started watching TV

theoretical you can do everything you can do with AD also with automations.
the most important decision is: “do i have more feeling for YAML and JINJA, or do i find python more logical”

1 Like

true. I just figured that since this is such a simple automation, yaml would be an easy solution

1 Like

then maybe also post the automation as example?
what is simple for you might not be simple for someone else :wink:

my example. chromecast_audio_off_automation.yaml

alias: ChromeCast Audio off automations
initial_state: 'on'
trigger:
  - platform: state
    entity_id: media_player.lounge_speakers
    to: 'off'
    for:
      minutes: 1
  - platform: state
    entity_id: media_player.house
    to: 'off'
    for:
      minutes: 1
condition:
  condition: and
  conditions:
    - condition: state
      entity_id: media_player.lounge_tv
      state: 'off'
    - condition: state
      entity_id: media_player.lounge_speakers
      state: 'off'

    - condition: or
      conditions:
        - condition: state
          entity_id: media_player.house
          state: 'off'
        - condition: state
          entity_id: media_player.house
          state: 'unavailable'

action:
  - service: switch.turn_off
    entity_id: switch.onkyo_amp

Thanks for all your replies.

I have read the docs and also looked at quite a few examples. I have also made 5 other apps, but having difficulties by getting my head around run_in().

I get the following error when using above script:
2018-07-22 08:38:33.953615 WARNING AppDaemon: ------------------------------------------------------------
2018-07-22 08:38:33.957130 WARNING AppDaemon: Traceback (most recent call last):
File “/usr/lib/python3.6/site-packages/appdaemon/appdaemon.py”, line 1575, in init_object
init()
File “/config/appdaemon/apps/tv_off.py”, line 6, in initialize
self.listen_state(self.tv,“media_player.ps59d7000_ps59d7000”)
AttributeError: ‘tv_off’ object has no attribute ‘tv’

Regarding YAML then that looks cool also, but I really like the challenge of getting it to work in appdaemon, as most of my other automations are made here now.

The indentation for the functions “tv” and “tv_off” is wrong in my script, try to go one tab back in each line following “self.listen_state…”

that means that you dont have a callback function called “tv” in the class “tv_off”

@Burningstone did explain the run_in quite good, but ill try it with an another example

def some_function(self): 
    # do some stuff
    after_some_amount_of_seconds = 90
    self.run_in(self.start_some_callback_function, after_some_amount_of_seconds) 
    # do some more stuff

def start_some_callback_function(self, kwargs):
    # do some other stuff

i hope this helps to get your head around it :wink:

Thanks - it works now, and I think also understand why now :slight_smile:

1 Like

Glad that it finally worked :slight_smile:
Could you please post the final code? I’m wondering what was wrong in my script

Of course, here it is:

import appdaemon.plugins.hass.hassapi as hass

class tv_off(hass.Hass):

    def initialize(self):
        self.listen_state(self.tv,self.args["tvID"])

    def tv(self, entity, attribute, old, new, kwargs):
        if new == "on":
            self.run_in(self.turn_tv_off, self.args["delay_sec"])

    def turn_tv_off(self, kwargs):
        if self.get_state(self.args["streamerID"]) == "off":
            self.turn_off(self.args["tvID"])

I changed the references for the media players to some generic ones so I could use it on more than one TV.
It was not much that caused your original propsal not to work, it was as you also pointed out the indentation of the “tv” and “tv_off” and also that in:

def tv(self, entity, attribute, old, new, kwargs):
            if new == "on":
                self.run_in(turn_tv_off, 900)

had a missing “self” in front of self.run_in(turn_tv_off, 900) so it should be self.run_in(self.turn_tv_off,900).

Once again thanks for the help, it really has helped me forward in also understanding the code, not just getting it to work :slight_smile:

1 Like

Thanks for posting. I’m glad that we were able to help you :slight_smile:

Is it possible to turn off the tv where the chromecast is plugged without using appdaemon?

you can everything without appdaemon. in that case you need to create a normal automation for it

Thanks for the quick reply.
What I’m trying to find is the service call to make the chromecast turn the tv off.
It can be done via google assistant, but the media_player.turn_off service doesn’t do the trick.
I’ll keep searching

Reuse of appdaemon apps is another reason

1 Like