First stab at Appdeamon

Hey all.

This is probably something obvious, but this is my first stab at Appdaemon, but would anyone have any idea why this simple app fails?

import appdaemon.plugins.hass.hassapi as hass

class TestScriptTrigger(hass.Hass):
    def initialize(self):
      self.listen_state(self.update_now,"input_boolean.script_trigger")

    def update_now(self, entity, attribute, old, new, kwargs):
      self.turn_on("script.dish_keys", channel = "1", room = "media_player.office_tv__dish")

I get this error in hass:

Invalid service data for script.turn_on: extra keys not allowed @ data['channel']. Got '1' extra keys not allowed @ data['room']. Got 'media_player.office_tv__dish'

Meanwhile, running the script directly in the hass services panel works fine:

sequence:
- service: media_player.select_source
  data_template:
    entity_id: "{{room}}"
    source: "{{channel}}"

Script parameters

{"room":"media_player.office_tv__dish","channel":"1"}

the datatemplate wants 2 things:

  1. entity_id
  2. source

and those have to be provided by the service
so i guess you need this:

      self.turn_on("script.dish_keys", source = "1", entity_id = "media_player.office_tv__dish")

But isnā€™t that what is being passed in the ā€œroomā€ variable?

In your automation you are assigning the room variable and then using it to assign the entity_id.

room = "media_player.office_tv__dish"
entity_id = room

To make them function the same, you could have done this for the script parameters for the automation (I believe - not sure if this is actually allowed but functionally this may help you see how they are different):

{"entity_id":"media_player.office_tv__dish","channel":"1"}

in appdaemon you call a service and you give the values for the datafields.
you dont fill the variables that you create in a template (those are not visible from outside HA)

the service has some vars to fill, in this case source and entity_Id

thats why the error says: invalid service data

Iā€™m not sure I quite understand what you are attempting. If you want to run the script you need to use the call_service api. Iā€™m not sure what turning on a script does.

Personally, I would move whatever the script does to appdaemon.

its also possible to use turn on for scripts. (i needed to look it up too :wink: )
but i also would call_service or do all parts in AD.

Hello @toddw65,

I think it should be

self.turn_on("script.dish_keys", data = {channel = "1", room = "media_player.office_tv__dish"})

If I remember correctly, I have come across this problem before, but not using appdaemon, but when I newly started with python scripts before moving to appdaemon. Try the above, or

self.turn_on("script.dish_keys", data = {'channel' : '1', 'room' : 'media_player.office_tv__dish'})

I think one of them should solve it. It is expecting only one key which is data in my opinion. So you pass your dictionary within it.

Hope it helps.

Thanks guys. Figured it out. My goal was to combine this project and this project and thanks to you guys I was finally successful.

Now I can say, ā€œHey Google. Change the office tv to channel 132.ā€ or ā€œOk Google. Change the master bedroom tv to channel 205.ā€

Not much really, but Iā€™m happy with it.

Hereā€™s what I ended up with:

import appdaemon.plugins.hass.hassapi as hass

#
# Change Channel on Dish Receiver using BroadLink IR
# To call it, fire a change_channel event with a "channel" and a "room" param
#

class SetChannel(hass.Hass):
    def initialize(self):
        self.log("SetChannel loaded")
        self.listen_event(self.do_change, 'change_channel')

    def do_change(self, event_name, data, kwargs): 
        delay = 0        
        for c in str(data["channel"]):
            if delay == 0:
                self.do_channel({"channel":c, "room":data["room"]})
            else:
                self.run_in(self.do_channel, delay, channel = c, room = data["room"])
            delay += 1

    def do_channel(self, kwargs):
        self.call_service("media_player/select_source", source = "chan_0"+kwargs["channel"], entity_id = "media_player."+kwargs["room"]+"_tv__dish")
4 Likes

Hi, do you mind giving a proper instruction for appdeamon noobs like me?
What youā€™re doing is exactly what I intend to with changing TV channels at different rooms

Well, keeping in mind that I am an AD newbie myself, hereā€™s what I did:

First I set up Vassilisā€™ cool custom component per this thread. This creates a media player component that you use to change channels by using the ā€˜media_player.select_sourceā€™ service. For example, in the case of my Dish Network Joey, I have channels 0-9 set up like this:

chan_01 = JgBIAA3EDF0LXQxdDDYLXQxdC10LXg1cDFwMXQtdC14LXgtdDVwLxQxeDFwMXQs2C10MXQxdC10NXAtdC14MXQxcDF0LXQteDAANBQ==
chan_02 = JgBIAAzFDF0NWwteCzYLXg00DF0LXQxdC10MXQxdDFwOWwtdDF0Mww5dC10MXQs2C14LNgxdDVsMXQtdDF0MXQtdDF0LXQxdDAANBQ==
chan_03 = JgBIAAvFDV0MXAtdDDYLNgxdC10MXQxdC10LXgtdDF0LXQxdC14LxgxdC10LXQw2CzYMXQxdDVsMXQtdDF0MXQtdDF0MXAteDQANBQ==
chan_04 = JgBIAA3GDlsLXQs3DFwMXA5bDF0NWwxdC10OWw1cDFwMXQtdDlsMxQxdC10OMg5bDlwLXQxdC10MXQxdDFwMXQtdDlsNXAtdDAANBQ==
chan_05 = JgBIAAzGC10MXQs2C14LXQw1DF0NXAtdDF0LXQxdDF0MXAxdC10NxQtdDVwLNgteC10NNA1cDVwLXQ1cC10MXQxdDFwMXQxdDAANBQ==
chan_06 = JgBIAA7FDF0MXAw2DFwLNwtdDF0MWg5dC14LXQxdC14LXQteC10NxAxdC10MNgtdDDYLXQxdDF0NWwteC10NXAxdC10NXAtdDAANBQ==
chan_07 = JgBIAAvFDF0MXQs2DDYMXAxdC10NXAxdC10LXgtdDF0MXQtdC14LxgteDFwLNgw2C10MXQxdC10MXQtdC14MXQxcC14LXQteCwANBQ==
chan_08 = JgBIAAvGDF0LXQw2DTQNXAs2C10MXQxdC10MXQtdDF0NXAtdDF0LxgxdC10MNgw1C14LNgtdDF0NXAxcDVwLXQxdDF0NWwxdCwANBQ==
chan_09 = JgBIAAzFDF0MXQ00DDYLNgteDFwLXQ1cDVwLXgtdC10MXQxdDFwMxQxdDF0LNgw2DDUMXQtdC14LXQxdC14NWwtdDF0MXQtdDAANBQ==
chan_00 = JgBIAA3EDF0MNQxdC10MXQw1DVwMXQtdC14LXQ5bC14MXAtdDF0NxAxdCzYMXQxcDF0MNQxdDF0LXQteC10MXQ1cDFwLXgtdDQANBQ==

And my media player is set up like:

- platform: broadlink
  name: Office TV & Dish
  host: 192.168.0.132
  mac: 'XX:XX:XX:XX:XX:XX'
  ircodes_ini: '/devices/broadlink/broadlink_media_codes/office.ini'

Next I set up an IFTTT applet that uses webhooks and the HASS API like this:

CaptureCapture2Capture3

The IFTTT applet calls a HASS script (change_channel.yaml) that consists of:

alias: "Change the Dish channel"
sequence:
  - service: python_script.set_channel
    data_template:
      channel: "{{channel}}"
      room: "{{room}}"

This, in turn, calls the HASS python script (set_channel.py) below:

channel = data.get('channel')
#for some reason IFTT passes the word "the" when sending "Change the $ tv to channel #" so strip out the word "the"
room = data.get('room').replace('the ', '')
#replace any spaces in the room name with underscores
room = room.replace(" ","_")
hass.bus.fire("change_channel", {"channel": channel, "room": room})

Once the change channel event fires, itā€™s picked up by the appdaemon script (set_channel.py) below:

import appdaemon.plugins.hass.hassapi as hass

#
# Change Channel on Dish Receiver
# To call it, fire a change_channel event with a "channel" and a "room" param
#

class SetChannel(hass.Hass):
    def initialize(self):
        self.log("SetChannel loaded")
        self.listen_event(self.do_change, 'change_channel')

    def do_change(self, event_name, data, kwargs): 
        delay = 1      
        for c in str(data["channel"]):
            if delay == 0:
                self.do_channel({"channel":c, "room":data["room"]})
            else:
                self.run_in(self.do_channel, delay, channel = c, room = data["room"])
            delay += 1
            
    def do_channel(self, kwargs):
        self.call_service("media_player/select_source", source = "chan_0"+kwargs["channel"], entity_id = "media_player."+kwargs["room"]+"_tv__dish")

which then calls the media_player.select_source service sending the concatenated source and entity_id.

Itā€™s a real Rube Goldberg machine that Iā€™m sure can be improved upon a lot but it works well.
Hopefully that covers it all. Good luck!

1 Like

Thanks for the detailed instructions!
So far, Iā€™ve already setup custom component, media player & iftt
Just wanna make sure I get it right for the HASS scripts & appdaemon scripts,

HASS python script --> /.homeassistant/python_scripts/set_channel.py
appdaemon scripts --> /appdaemon/conf/apps/set_channel.py
For change_channel script in configuration.yaml :
ā€“> change_channel: !include change_channel.yaml
ā€“> /.homeassistant/change_channel.yaml)

Yep. This looks correct and donā€™t forget to add to your apps.yaml for AD.

set channel:
  module: set_channel
  class: SetChannel

Hi, just one more thing, which phrase should I use for ifttt?
Should I use the fourth option since thereā€™s numbers & text.

Yes. Youā€™ll want the fourth one. Like ā€œChange the $ tv to channel #ā€

Thanks, Iā€™m just getting error with invalid config for the script

 Configuration invalid
Testing configuration at /home/homeassistant/.homeassistant
ERROR:homeassistant.loader:Unable to find component change_channel
ERROR:homeassistant.setup:Setup failed for change_channel: Component not found.
Failed config
  General Errors: 
    - Component not found: change_channel
    - Setup failed for change_channel: Component not found.

Iā€™m not quite sure how to fix this. anything else I might be missing?

Looking back at what you said earlier, Iā€™m not sure this is correct. Iā€™m assuming you have other scripts besides this one so if those are in a single scripts.yaml file, the config would look like:

script: !include scripts.yaml

and then the change_channel script would be in that file.

Iā€™m curious if this could be used to search the Dish guide and automate my television to turn to a certain station on days my favorite sports teams are playing? That would be awesome

it is possible, but i wouldnt try it like the way it is done here.

you can do it with 1 app without the need for hass scripts and hass python scripts.

if you have a mediaplayer in your HA that can change channels for your TV, you can do that from appdaemon
and you can search any webpage for anything with python too.

but it would involve some programming.

I do have a harmony hub that I can change channels with, its figuring out how to search the guide on dish and tell harmony to change the channel at a certain date and time.

Its probably way over my head at this point but Ill research it a bit, it would be very cool to do!

Thanks for your reply ReneTode! :slight_smile: