Get_state attribute not working

Hi, I can’t get my first attempt at an app working. I’m trying to turn on the TV & a light when I get home from work ->

class HomeFromWork(hass.Hass):

  def initialize(self):  
    self.listen_state(self.home, "device_tracker.androidcf6f4e6dfddd8b64", new = "home")

  def home(self, entity, attribute, old, new, kwargs):
    self.log("Philip is home")
    state = self.get_state("remote.master", "current_activity")
    if state == "PowerOff":
      self.turn_on(self, "switch.schlage_link_unknown_type1122_id5501_switch_6")
      self.call_service(self, "remote.send_command", entity_id = "remote.master", command = "Watch Foxtel")

Unfortunately I get this error ->TypeError: get_state() takes from 1 to 2 positional arguments but 3 were given.

But it looks right according to the doc, what an I doing wrong?
Thanks in advance

It is not clear exactly what you are trying to retrieve from the entity, but to get a state, you just need one parameter - the entity id. To get an attribute, you need the enttity id and a named parameter attribute.

There are examples here

Looks like I forgot the ‘attribute’ part, so this ->

state = self.get_state("remote.master", "current_activity")

should be

state = self.get_state("remote.master", attribute="current_activity")

So does that mean the hassio doco is wrong?
https://www.home-assistant.io/docs/ecosystem/appdaemon/api/

# Return the brightness attribute for light.office_1
state = self.get_state("light.office_1", "brightness")

In any case that worked!
Thanks heaps for your help

The official documentation is here.

I have never seen the link you posted.

Ok, that’s nice to know, thanks again for your help.
Now I have to go and automate :slight_smile:

1 Like

just to make it clear.
hassio is an operating system like windows or linux.
the documents you point to are the home assistant docs, and home assistant is a program like word, excel or powerpoint.

you run home assistant on the hassio platform.

i say that, to avoid misunderstandings in the future.

Thanks for the clarification

Where I am trying to set message to the name of a device_tracker, the get_state attribute is returning None.
If I remove the attribute from the get_state function, it returns the state correctly.
Do I have a syntax or format issue?

import appdaemon.plugins.hass.hassapi as hass
import json
import urllib

class arive_home(hass.Hass):

  def arive_home_callback(self, entity, attribute, old, new, kwargs):
    self.log('callback started')
    message = str(self.get_state(entity='device_tracker.' + self.args['devicetracker_home_status'], attribute='full_name')) + " has arived"
    self.call_service("notify/"+self.args['send_alert_to'],title="",message=message)
    self.log("\n****************************\n"
             + message + "\n"
             + "****************************\n"
             + "Message Sent")
  def initialize(self):
    self.listen_state(self.arive_home_callback,
                      'device_tracker.' + self.args['devicetracker_home_status'],
                      new="home")
    self.log("Current State '"+self.get_state(entity='device_tracker.' + self.args['devicetracker_home_status'])+"'")
    self.log("Automaintion initialize.")

here is a list of attributes for device_tracker:

device_tracker.google_maps_1008683	not_home	
source_type: gps
latitude: 35.529587
longitude: -98.4408179
gps_accuracy: 10
address: I-40, Hinton, OK 73047, USA
full_name: Nancy xxxxxx
id: 100868
last_seen: 2018-07-09T07:24:12.608000
nickname: Nancy
friendly_name: google maps 1008683200
entity_picture: https://lh6.googleusercontent.co/photo.jpg

i would try to keep things a little more simple that makes logging more easy.
this line:

    message = str(self.get_state(entity='device_tracker.' + self.args['devicetracker_home_status'], attribute='full_name')) + " has arived"

i would translate to:

device = 'device_tracker.' + self.args['devicetracker_home_status']
full_name = self.get_state(device, attribute = 'full_name') # no need to say entity = ...
message = full_name + ' has arrived' # no need for str full name can only be a string.

now you can log for device, full_name and message and see if all 3 are what you expect.

@ReneTode Thanks. Doing the variables as you suggest is the right way to code it. It makes it so much easier to read. Out of curisioty, did you see what I did wrong or is it not worth time. I cool either way. :slight_smile:
BTW, here was my finale version:

import appdaemon.plugins.hass.hassapi as hass
import json
import urllib

class arive_home(hass.Hass):

  def arive_home_callback(self, entity, attribute, old, new, kwargs):
    self.log('callback started')
    message = self.device_tracker_full_name + " has arived"
    self.call_service("notify/"+self.args['send_alert_to'],title="",message=message)
    self.log("\n****************************\n"
             + message + "\n"
             + "****************************\n"
             + "Message Sent")
  def initialize(self):
    self.device_tracker = 'device_tracker.' + self.args['devicetracker_home_status']
    self.device_tracker_full_name = self.get_state(entity=self.device_tracker, attribute='full_name')
    self.listen_state(self.arive_home_callback,
                      self.device_tracker,
                      new="home")
    self.log("Current State '" 
             + self.device_tracker_full_name
             + " is "
             + self.get_state(entity=self.device_tracker)
             + "'")
    self.log("Automaintion initialize.")

with this i can see where it goes wrong. :wink:
and if i have time ill always will help.

  1. keep your apps clean. dont start to create callbacks before the initialise. its also the way the app works.
    when AD is started or when the code is changed the initialise is performed, and only on that time.
    so thats always the start from your app.
  2. follows from that. you got the get_state in your initialse now. so the value is set when the app starts, but wont get changed when the callback is activated
import appdaemon.plugins.hass.hassapi as hass
import json
import urllib

class arive_home(hass.Hass):

  def initialize(self):
    self.device_tracker = 'device_tracker.' + self.args['devicetracker_home_status']
    self.listen_state(self.arive_home_callback,
                      self.device_tracker,
                      new="home")
    self.log("Current State '" 
             + self.device_tracker_full_name
             + " is "
             + self.get_state(self.device_tracker)
             + "'")
    self.log("Automaintion has been initialized.")

  def arive_home_callback(self, entity, attribute, old, new, kwargs):
    self.log('callback started')
    self.device_tracker_full_name = self.get_state(self.device_tracker, attribute='full_name')
    self.log("Current State '" 
             + self.device_tracker_full_name
             + " is "
             + self.get_state(self.device_tracker)
             + "'")
    message = self.device_tracker_full_name + " has arived"
    self.call_service("notify/"+self.args['send_alert_to'],title="",message=message)
    self.log("\n****************************\n"
             + message + "\n"
             + "****************************\n"
             + "Message Sent")

and when changing this i noticed 2 more things:

  1. dont use entity=… in get_state (like i mentioned before)
  2. decide what you want to use for quotes. i see you sometimes use ‘’ and at other times use “” to create strings. pick 1 or the other and always keep using that. you will get crazy debugging at somepoint when you keep using both for the same purpose.

I did not mean the way it sounded, I was asking if it was worth either of our time. Looks like yes. I did learn a lot. Thanks.

I was trying to get in the “style” of hass code. Someday I would like to do a component. I thought the style was if one word, ‘’ if more than one word “”. Even at that I was not consistent. Thanks for keeping me honest.

Got it.

I had the message hard coded for what the event was going to be. I just reworked it, so now there will be one app with two apps.yaml definitions. I was using the developers state to change the device tracker entity. Right now I am away, so I was setting it to “home”. Then what confused me when the hass corrected the tracker on the next update, I was expecting the other to fire. Well I consolidated down to one app. In the course of debugging I notice the away is not “away” but “not-home”. That is why I was missing the other app.That is what prompted my about the question of instances. If I would have posted the “away” one instead of the “home” one you would have saw that. Everything behaves as I expected now. This is just a test to see when the “home” and “not-home” fires for future automation.
Here is the apps.yaml and “left_arived_home”

test_away_paul:
  module: "left_arived_home"
  class: "left_arived_home"
  devicetracker_home_status: !secret device_tracker_paul
  send_alert_to: "textalertspaul"
test_away_nancy:
  module: "left_arived_home"
  class: "left_arived_home"
  devicetracker_home_status: !secret device_tracker_nancy
  send_alert_to: "textalertspaul"


import appdaemon.plugins.hass.hassapi as hass
import json
import urllib

class left_arived_home(hass.Hass):

  def initialize(self):
    self.device_tracker = 'device_tracker.' + self.args['devicetracker_home_status']
    self.device_tracker_full_name = self.get_state(self.device_tracker, attribute='full_name')
    self.listen_state(self.left_arived_home_callback,
                      self.device_tracker)
    self.log("Current State '" 
             + self.device_tracker_full_name
             + " is "
             + self.get_state(self.device_tracker)
             + "'")
    self.log("Automaintion initialize.")

  def left_arived_home_callback(self, entity, attribute, old, new, kwargs):
    self.log('callback started')
    message = ""
    current_state = self.get_state(self.device_tracker)
    if current_state == 'not_home':
      message = self.device_tracker_full_name + " has left "
    else:
      message = self.device_tracker_full_name + " has arived "
    self.call_service("notify/"+self.args['send_alert_to'],title="",message=message)
    self.log("\n****************************\n"
            + message + "\n"
            + "****************************\n"
            + "Message Sent")
1 Like

and thats the most important thing. :wink:

i am glad that you now got it working.

Well… might have spoke too soon.
I took off the new= from the listen.state. Now the event is firing about ever 5 to 10 minutes.
Can I set the new= to new={“home”,“not-home”}? How can I trap the event only when it changes?

Here is the hass log https://hastebin.com/ladatogara.css
here is the AD log https://hastebin.com/awapowabad.md

You can see from the timings that AD is not fired ever time the geo code updates.

the calback only fires when something changes.
but most devicetrackers in HA are quite independable. so you can get unwanted state changes when you have set the delay to short.

and it also triggers the callback when an attribute changes if you dont set new.

you can do 2 things:

  1. use 2 listen_states 1 for home and 1 for not_home or
  2. in your callback check for what you want it to be with if new=“home”:

Like this? It did work when I forced a state change. Now let’s see if settles down.

self.listen_state(self.left_arived_home_callback,
                  self.device_tracker,
                  new='home')
self.listen_state(self.left_arived_home_callback,
                  self.device_tracker,
                  new='not_home')

[Edit], still fired a left event though I am still not_home.
I bet it is the custom code doing it.

yeah like that.

Actually, the device tracker is not custom.

device_tracker:
  #- platform: owntracks
  - platform: google_maps
    username: !secret locator_paul_username
    password: !secret locator_paul_password
sensor:
  - platform: google_geocode
    name: Paul
    origin: device_tracker.google_maps_108
    options: street_number, street, city
    display_zone: display
    gravatar: [email protected]
    api_key: !secret google_map_api    
  - platform: google_geocode
    name: Nancy
    origin: device_tracker.google_maps_100
    options: street_number, street, city
    display_zone: display
    gravatar: [email protected]
    api_key: !secret google_map_api

Still now sure what I am doing wrong. The event is firing even if there is not a change.
I added to the log the current state, old state, and new state. If there was a state change you would have expected the old and new to be different. It was not.
Just to test my theory, I then forced a state change and the old/new was what I expected. I can use that now to keep false fires from happening.
Here is the log showing what I am talking about. https://hastebin.com/uqoqagusil.md
and the code that go with it https://hastebin.com/tevukumomi.py

I am going to add a test that old != new.
Will report back?

the code you have has a problem.
you have a callback that gives you new as current state and the you go check the current state with get_state.
but that is a fraction of a second later.

if those 2 are different, then the state is changed twice and you get the callback to times.
with some devices and some devicetrackers you get a short state change. thats why i said that devicetrackers are not dependable. (there are people combining 4 or 5 devicetrackers to get an accurate state)

attribute should contain all attributes. log those and see if anything changes there.