How to update this AppDaemon 3 script to AD 4

Hmm, try changing the last line from self.hass.set_state.... to self.adbase.set_state....

exact same error…almost:

2020-09-20 15:03:48.417463 WARNING address: Traceback (most recent call last):
  File "/usr/lib/python3.8/site-packages/appdaemon/app_management.py", line 150, in initialize_app
    await utils.run_in_executor(self, init)
  File "/usr/lib/python3.8/site-packages/appdaemon/utils.py", line 290, in run_in_executor
    response = future.result()
  File "/usr/lib/python3.8/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/config/appdaemon/apps/address.py", line 30, in initialize
    self.update_address(entity)
  File "/config/appdaemon/apps/address.py", line 60, in update_address
    self.adbase.set_state(entity, state=state, attributes=attributes, namespace="hass")
  File "/usr/lib/python3.8/site-packages/appdaemon/utils.py", line 195, in inner_sync_wrapper
    f = run_coroutine_threadsafe(self, coro(self, *args, **kwargs))
  File "/usr/lib/python3.8/site-packages/appdaemon/utils.py", line 299, in run_coroutine_threadsafe
    result = future.result(self.AD.internal_function_timeout)
  File "/usr/lib/python3.8/concurrent/futures/_base.py", line 439, in result
    return self.__get_result()
  File "/usr/lib/python3.8/concurrent/futures/_base.py", line 388, in __get_result
    raise self._exception
  File "/usr/lib/python3.8/site-packages/appdaemon/adapi.py", line 1440, in set_state
    return await self.AD.state.set_state(self.name, namespace, entity, **kwargs)
  File "/usr/lib/python3.8/site-packages/appdaemon/state.py", line 471, in set_state
    if entity in self.state[namespace]:
KeyError: 'hass'

changing namespace="hass" to namespace="HASS"?

tried that myself :slight_smile: nope:

2020-09-20 15:07:21.621843 WARNING address: Traceback (most recent call last):
  File "/usr/lib/python3.8/site-packages/appdaemon/app_management.py", line 150, in initialize_app
    await utils.run_in_executor(self, init)
  File "/usr/lib/python3.8/site-packages/appdaemon/utils.py", line 290, in run_in_executor
    response = future.result()
  File "/usr/lib/python3.8/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/config/appdaemon/apps/address.py", line 30, in initialize
    self.update_address(entity)
  File "/config/appdaemon/apps/address.py", line 60, in update_address
    self.adbase.set_state(entity, state=state, attributes=attributes, namespace="HASS")
  File "/usr/lib/python3.8/site-packages/appdaemon/utils.py", line 195, in inner_sync_wrapper
    f = run_coroutine_threadsafe(self, coro(self, *args, **kwargs))
  File "/usr/lib/python3.8/site-packages/appdaemon/utils.py", line 299, in run_coroutine_threadsafe
    result = future.result(self.AD.internal_function_timeout)
  File "/usr/lib/python3.8/concurrent/futures/_base.py", line 439, in result
    return self.__get_result()
  File "/usr/lib/python3.8/concurrent/futures/_base.py", line 388, in __get_result
    raise self._exception
  File "/usr/lib/python3.8/site-packages/appdaemon/adapi.py", line 1440, in set_state
    return await self.AD.state.set_state(self.name, namespace, entity, **kwargs)
  File "/usr/lib/python3.8/site-packages/appdaemon/state.py", line 471, in set_state
    if entity in self.state[namespace]:
KeyError: 'HASS'

When you go to the AppDaemon HTTP Web Interface at port 5050 to the section “entities”, what do you see there:

all! of my entities… including the device_trackers concerned here

In Default, I dont have a hass tab…?

and in which tab do you see all your entities? default? hass?

Ok, try this:

self.adbase.set_state(entity, state=state, attributes=attributes, namespace="default")

BINGOOOO!!!
Perfect!

Thank you so very much. Has been a long standing wish, but never got it to work. Magic!

(makes me wonder why I have Hass set in the app config, and no Hass tab is visible in the ui?)

I should have known it, if the namespace is not explicitly defined in the appdaemon config, it will default to “default”, I explicitly defined it in my system as I use other plugins and namespaces etc., that’s why it worked for me but didn’t for you.

  plugins:
    HASS:
      type: hass
      namespace: hass
      token: !secret appdaemon_token
      ha_url: http://192.168.0.30:3123
    MQTT:
      type: mqtt
      namespace: mqtt
      client_id: AD_4
      client_host: 192.168.0.30
      client_user: !secret mqtt_user
      client_password: !secret mqtt_password

so would I be wise to already do so?
If so, Id copy what you have here, and change to ‘hass’ again in the script?

and what about my history binary sensors app. Should that need edits too then?

would also think the ha_url to be the way you define it here (actual IP address, since in my case it tries to find it at mydomain.duckdns.org without any further port settings, which isnt correct…

You can leave that as it is.

I don’t know if one can set the ha_url and token in the app, I think in the docs it says to leave this empty as the add-on will handle this.

BTW do you have a gps tracker for your dog? :slight_smile: If yes, what kind of device is this?

NO! You remind me of a wish unfulfilled . Got a dachshund :wink: never unleash those…

All these device trackers are my daughters and yes they are unleashed.

I have the same wish as well :smiley: We recently got ourselves a Labrador :smiling_face_with_three_hearts:

anything you can make of this… happens after a system restart, didnt change anything to any of the AD apps or settings…

2020-09-20 23:11:50.064293 CRITICAL AppDaemon: Thread thread-1 has died
2020-09-20 23:11:50.065962 CRITICAL AppDaemon: Pinned apps were: ['LastMotionHistory']
2020-09-20 23:11:50.067152 CRITICAL AppDaemon: Thread will be restarted
2020-09-20 23:11:50.068185 INFO AppDaemon: Adding thread 1
2020-09-20 23:11:51.077583 CRITICAL AppDaemon: Thread thread-1 has died
2020-09-20 23:11:51.080205 CRITICAL AppDaemon: Pinned apps were: ['LastMotionHistory']
2020-09-20 23:11:51.081924 CRITICAL AppDaemon: Thread will be restarted
2020-09-20 23:11:51.083373 INFO AppDaemon: Adding thread 1
2020-09-20 23:11:52.095127 CRITICAL AppDaemon: Thread thread-1 has died

saw some triggers before when old_state was ‘unavailable’. Since these are Hue sensors, and Hue did tend to go unavailable quite frequently under system stress, I catered for that in yaml automations adding a condition from_state couldn’t be ‘unavailable’. Would you know how that could be achieved in the current multi_bin_sensor_history.py script I posted above?

Hey BurningStone,

Please le me get back to young this, as I ve seen the added attributes made by the AppDaemon app disappear lately. They are correctly added upon HA start, but after a while are lost. I need to restart the app/or the AppDaemon add-on to get everything back. Or a device_tracker changes location and kicks an update in action. And loses it again after a while (eg switching from data to wifi connection, just saw that happening)
Stationary devices seem to be the issue?

Thought is was the newly made code, so even tried the old code once more:

"""Address AppDaemon app."""
# pylint: disable=attribute-defined-outside-init, unused-argument, too-many-arguments
import appdaemon.plugins.hass.hassapi as hass
#
# Address App
# requires: "geopy" https://pypi.org/project/geopy/
#
#
# Args:
#   entity: entity_id of a device_tracker entity, example "device_tracker.my_entity"
#

class Address(hass.Hass):
    """Address class."""

    def initialize(self):
        """initialize Address."""
        self.log("App started.")
        entity_config = self.args["entity"]

        if isinstance(entity_config, str):
            entities = []
            entities.append(entity_config)
        else:
            entities = entity_config

        for entity in entities:
            self.listen_state(self.get_address, entity)
            self.log("State listener for {} started.".format(entity))

    def get_address(self, entity, attribute, old, new, kwargs):
        """Set the state + attributes of a defined device_tracker entity."""
        from geopy.geocoders import Nominatim
        geo = Nominatim(user_agent="AppDaemon")
        lat = self.get_state(entity, attribute="latitude")
        long = self.get_state(entity, attribute="longitude")

        if lat is None or long is None:
            self.log("{} does not have lat/long attributes.".format(entity))
            return

        lat_long = "{}, {}".format(lat, long)

        data = geo.reverse(lat_long)
        raw = data.raw["address"]
        attributes = self.get_state(entity, attribute="all")["attributes"]

        for attr in raw:
            attributes[attr] = raw[attr]

        self.log("Updating state for {}".format(entity))
        self.set_state(entity, state=state, attributes=attributes)

which, with the new line at the bottom and the adaptations in the config setting seems to work too now…

still even that setup loses the attributes after some time
So I am lost for now, and would really love to get things back up and running… could you have another look please?

maybe an extra trigger could be added, eg if no country_code is available anymore, the script re-runs?