Home Assistant Community Add-on: AppDaemon 4

This add-on is provided by the Home Assistant Community Add-ons project.

GitHub Release GitLab CI Project Stage Project Maintenance

Supports armhf Architecture Supports armv7 Architecture Supports aarch64 Architecture Supports amd64 Architecture Supports i386 Architecture

logo

hadashboard

About


AppDaemon is a loosely coupled, multithreaded, sandboxed python execution environment for writing automation apps for Home Assistant home automation software. It also provides a configurable dashboard (HADashboard) suitable for wall mounted tablets.

Installation


The installation of this add-on is pretty straightforward and not different in comparison to installing any other add-on.

  1. Search for the “AppDaemon 4” add-on in the add-on store and install it.
  2. Start the “AppDaemon 4” add-on
  3. Check the logs of the “AppDaemon 4” add-on to see if everything went well.

:information_source: Please note, the add-on is pre-configured to connect with Home Assistant. There is no need to create access tokens or to set your Home Assistant URL in the AppDaemon configuration.

:books: Please read the documentation for more information about the use and configuration of this add-on.

Upgrading from AppDaemon 3.x


Upgrading from AppDaemon 3.x? Please make sure you read the following upgrade guides:

Support


You can always try to get support from the community here at the Home Assistant community forums, join the conversation!

Questions? You have several options to get them answered:

You could also open an issue on GitHub, in case you ran into a bug, or maybe you have an idea on improving the addon:

:information_source: At this moment our Home Assistant Community Add-ons Discord chat server and GitHub are our only official support channels. All others rely on community effort.

Repository on GitHub


Looking for more add-ons?


The primary goal of our add-ons project is to provide you (as a Home Assistant user) with additional, high quality, add-ons that allow you to take your automated home to the next level.

Check out some of our other add-ons in our Home Assistant Community Add-ons project.

3 Likes

About the author of this add-on

Hi there!

I am Franck Nijhof, and I have 30 years of programming experience, in many languages. I am using this experience to work on the Home Assistant project by giving back my knowledge and time to the open source community.

The add-on you are currently looking at right now was developed/packaged by me. It is not the only add-on I have created; there are many many more :wink:

However, I have a problem… I am an addict. A :coffee: addict that is. Lucky for you, I turn that C8H10N4O2 (caffeine molecule) into code (and add-ons)!

If you want to show your appreciation, consider supporting me for buying a cup of high octane wakey juice via one of the platforms below! :heart:

Sponsor Frenck via GitHub Sponsors

Support Frenck on Patreon

Enjoy your add-on, while I enjoy the brain juice. :coffee:

Thanks for all the :two_hearts:

…/Frenck

Join our Discord server Follow me on Twitter Flollow me on Instragram Follow me on GitHub Follow me on YouTube Follow me on Twitch patreon-icon

P.S.: In case you want to ask me a question: AMA (Ask Me Anything). Most of the time I am online at the Discord chat. (I go by @Frenck in there as well).

1 Like

And to complete the information right at the start from this thread.

Appdaemon is created by @aimc, and in the moment developed by a team from 5 people.
full docs about creating apps, and how to work with Dashboards can be found here:

https://appdaemon.readthedocs.io/en/stable/

do you have questions about dashboard, or apps that are not related to the addon, then come to our discord server:

do you have issues or ideas related to appdaemon, please contact us on discord first, after that you can create an issue on github:

we hope you enjoy working with Appdaemon.

Loaded this on a fairly clean generic HassIo install.

I note the lat/log and elevation do not match what is in HA. Is this correct or do they need to be set manually?

In addition the url created is not correct.

secrets: /config/secrets.yaml
appdaemon:
  latitude: 52.379189
  longitude: 4.899431
  elevation: 2
  time_zone: Europe/Amsterdam
  plugins:
    HASS:
      type: hass
http:
  url: http://127.0.0.1:5050
admin:
api:
hadashboard:

The initial setup section in the docs is also different to this default and seems to be cthe opposite of the statement re ha_url not being needed. https://appdaemon.readthedocs.io/en/latest/CONFIGURE.html#initial-setup

There is some verys confusing and conflicting information
first https://github.com/hassio-addons/addon-appdaemon/blob/v0.1.0/README.md#home-assistant-access-tokens-and-ha_url-settings says you don’t need a url or token, but https://appdaemon.readthedocs.io/en/latest/CONFIGURE.html#configuration-of-the-hass-plugin says you do (i.e. required).


very confused!

Hey m8, the add-on documentation clarifies that:

https://github.com/hassio-addons/addon-appdaemon#home-assistant-access-tokens-and-ha_url-settings

Nevertheless, you are free to provide those settings if you wish.

It actually confuses. It either is required (as per the image) or not as per your link. It can’t be both :grin:.

Further down the docs go into detail how to provide the token, but your link implies this is not now required.

Still confused :grin:.

when you use AD in any other way then as hassio addon, it is required.
thats why we tell so in the AD docs.
but Frenck created the addon so that it is provided on the background, so in that case it isnt required anymore.

i hope that makes it more clear @baz123

Ah that makes more sense.

I think it needs to be clearer that installing it as an add-on is a special case. It makes sense now you have explained it, but I feel it was not clear from the documentation as it is.

Cheers

How do I refresh the add on list as I can only see ver 3.0 no v4.0 in the list. Thanks

if we would have known it we could have put it in the docs :wink:
that kind of things happens when more parties work on the same thing.

1 Like

Pushed additional comment for that to the add-on docs, thank you for the feedback. :+1:

1 Like

I have upgraded the addon from Appdaemon 3 to 4.

I get this error when pushing a Xiaomi button which is connected via an app:

2020-01-15 00:21:39.610419 INFO deconz_helper: Deconz event received from kamer_s_xiaomi_schakelaar. Event was: 1002
2020-01-15 00:21:39.625159 WARNING deconz_helper: ------------------------------------------------------------
2020-01-15 00:21:39.626062 WARNING deconz_helper: Unexpected error in worker for App deconz_helper:
2020-01-15 00:21:39.627270 WARNING deconz_helper: Worker Ags: {'id': 'f3e6e3900dc841a598300b5e4a0fe295', 'name': 'deconz_helper', 'objectid': '725d79c732a14b1b8acb7b3184038c90', 'type': 'event', 'event': 'deconz_event', 'function': <bound method DeconzHelper.event_received of <deconz_helper.DeconzHelper object at 0x7fe32d4689a0>>, 'data': {'id': 'kamer_s_xiaomi_schakelaar', 'unique_id': '00:15:8d:00:02:01:6f:23', 'event': 1002}, 'pin_app': True, 'pin_thread': 2, 'kwargs': {'__thread_id': 'thread-2'}}
2020-01-15 00:21:39.629579 WARNING deconz_helper: ------------------------------------------------------------
2020-01-15 00:21:39.630939 WARNING deconz_helper: Traceback (most recent call last):
  File "/usr/lib/python3.8/site-packages/appdaemon/threading.py", line 794, in worker
    funcref(args["event"], data, args["kwargs"])
  File "/config/appdaemon/apps/deconz/deconz_helper.py", line 15, in event_received
    self.set_state("sensor.deconz_event", state = event_id, attributes = {"event_data": event_data, "event_received": str(event_received)})
  File "/usr/lib/python3.8/site-packages/appdaemon/utils.py", line 191, in inner_sync_wrapper
    f = run_coroutine_threadsafe(self, coro(self, *args, **kwargs))
  File "/usr/lib/python3.8/site-packages/appdaemon/utils.py", line 285, 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 1360, in set_state
    return await self.AD.state.set_state(self.name, namespace, entity_id, **kwargs)
  File "/usr/lib/python3.8/site-packages/appdaemon/state.py", line 431, in set_state
    result = await plugin.set_plugin_state(namespace, entity_id, **kwargs)
  File "/usr/lib/python3.8/site-packages/appdaemon/plugins/hass/hassplugin.py", line 369, in set_plugin_state
    api_url = "{}/api/states/{}".format(config["ha_url"], entity_id)
KeyError: 'ha_url'
2020-01-15 00:21:39.631946 WARNING deconz_helper: ------------------------------------------------------------

My appdeamon.yaml:

secrets: /config/secrets.yaml
appdaemon:
  latitude: !secret latitude
  longitude: !secret longitude
  elevation: 3
  time_zone: Europe/Amsterdam
  plugins:
    HASS:
      type: hass
http:
  url: http://127.0.0.1:5050
hadashboard:
admin:
api:

I have tried adding ha_url and token but that gave a connection error. Am I missing something here?

:tada: Release v0.1.1

Full Changelog

Nothing beats a first bug release just hours after the initial release :wink:

:hammer: Changes

  • :ambulance: Fix Patreon link
  • :ambulance: Hot patch AppDaemons internal config for Hass.io
  • :books: Clarified add-on docs on conflict with AppDaemon docs
  • :pencil2: Fix Typo (#1)

Questions? Join our Discord server! https://discord.me/hassioaddons
Enjoying my add-ons? Consider supporting my work:
https://github.com/sponsors/frenck or https://patreon.com/frenck

1 Like

Could you have waited 5 more minutes :wink: :joy:

See release above.

3 Likes

Haha, it’s fixed now indeed :sunglasses:
The next time I will wait 5 more minutes before posting :wink:

1 Like

Hahaha! that fixed Apop’s config-check as well.

Updated to 0.1.1 and hass works fine now. My local set-up is such that I have a local subdomain/SSL cert so I connect via https. When I click on the
image
It tries to make an HTTPS connection using port 5050, but fails.

What is the best way to solve this? I use HADashboard, connecting via http.

I can connect to the Web UI using the IP and http instead of the subdomain.

Do the ssl settings under the http config just work for the dash or the UI as well?

Can I just point to /ssl/ for the certificates as they are inside HassIO?

Could the SSL settings be set in the add-on as most other add-ons do?

1 Like

got the update to AD 4 running fine, until my app address wants to track its configured device_trackers, and the following error is displayed:

2020-01-16 11:24:15.186232 WARNING address: Unexpected error in worker for App address:
2020-01-16 11:24:15.187151 WARNING address: Worker Ags: {'id': 'redacted25f9cf8b5da74b5be63a6a7d0566a', 'name': 'address', 'objectid': 'redacted40af235cf9abad41a46436c7376f', 'type': 'state', 'function': <bound method Address.get_address of <address.Address object at 0xb5280d48>>, 'attribute': 'state', 'entity': 'device_tracker.life360_marijn', 'new_state': 'not_home', 'old_state': 'home', 'pin_app': True, 'pin_thread': 1, 'kwargs': {'__thread_id': 'thread-1'}}
2020-01-16 11:24:15.188611 WARNING address: ------------------------------------------------------------
2020-01-16 11:24:15.196667 WARNING address: Traceback (most recent call last):
  File "/usr/lib/python3.8/site-packages/appdaemon/threading.py", line 777, in worker
    funcref(entity, attr, old_state, new_state,
  File "/config/appdaemon/apps/address/address.py", line 35, in get_address
    lat = self.get_state(entity=entity, attribute="latitude")
  File "/usr/lib/python3.8/site-packages/appdaemon/utils.py", line 191, in inner_sync_wrapper
    f = run_coroutine_threadsafe(self, coro(self, *args, **kwargs))
  File "/usr/lib/python3.8/site-packages/appdaemon/utils.py", line 285, 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 1310, in get_state
    return await self.AD.state.get_state(
TypeError: get_state() got an unexpected keyword argument 'entity'

using this address.py app by Ludeeus.

Ive checked the changes on https://appdaemon.readthedocs.io/en/latest/HISTORY.html but don’t see anything that would cause the issue?

reverting to AD3 makes it work immediately again
please help me get this back up and running? I really can’t do without this beautiful and small little gem of an app.

thanks!

btw, I couldn’t connect through 127.0.0.1 so had to set that to hassio.local. 2 things about that: how can I set that to ssl, and how do I check the dashboard when not on the local network…
what settings do I set in http: for that please?

you got this in an app:

self.get_state(entity=something)

and in the breaking changes it has been missed out to add that that is now:

self.get_state(entity_id=something)

but its easier to use:

self.get_state(something)
1 Like

thanks Rene!

will pass this on to @ludeeus too with this.

edit

still see this:

2020-01-16 14:28:04.286135 WARNING address: ------------------------------------------------------------
2020-01-16 14:28:04.287247 WARNING address: Unexpected error in worker for App address:
2020-01-16 14:28:04.288426 WARNING address: Worker Ags: {'id': 'redacted15743cd807f9a92bd884a4d', 'name': 'address', 'objectid': 'redacted138c7e41deac29e2859f37774f', 'type': 'state', 'function': <bound method Address.get_address of <address.Address object at 0xb4ebf1a8>>, 'attribute': 'state', 'entity': 'device_tracker.life360_marijn', 'new_state': 'bij Marijn', 'old_state': 'home', 'pin_app': True, 'pin_thread': 1, 'kwargs': {'__thread_id': 'thread-1'}}
2020-01-16 14:28:04.289536 WARNING address: ------------------------------------------------------------
2020-01-16 14:28:04.297138 WARNING address: Traceback (most recent call last):
  File "/usr/lib/python3.8/urllib/request.py", line 1319, in do_open
    h.request(req.get_method(), req.selector, req.data, headers,
  File "/usr/lib/python3.8/http/client.py", line 1230, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "/usr/lib/python3.8/http/client.py", line 1276, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "/usr/lib/python3.8/http/client.py", line 1225, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/usr/lib/python3.8/http/client.py", line 1004, in _send_output
    self.send(msg)
  File "/usr/lib/python3.8/http/client.py", line 944, in send
    self.connect()
  File "/usr/lib/python3.8/http/client.py", line 1392, in connect
    super().connect()
  File "/usr/lib/python3.8/http/client.py", line 915, in connect
    self.sock = self._create_connection(
  File "/usr/lib/python3.8/socket.py", line 808, in create_connection
    raise err
  File "/usr/lib/python3.8/socket.py", line 796, in create_connection
    sock.connect(sa)
OSError: [Errno 99] Address not available
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "/usr/lib/python3.8/site-packages/geopy/geocoders/base.py", line 355, in _call_geocoder
    page = requester(req, timeout=timeout, **kwargs)
  File "/usr/lib/python3.8/urllib/request.py", line 525, in open
    response = self._open(req, data)
  File "/usr/lib/python3.8/urllib/request.py", line 542, in _open
    result = self._call_chain(self.handle_open, protocol, protocol +
  File "/usr/lib/python3.8/urllib/request.py", line 502, in _call_chain
    result = func(*args)
  File "/usr/lib/python3.8/urllib/request.py", line 1362, in https_open
    return self.do_open(http.client.HTTPSConnection, req,
  File "/usr/lib/python3.8/urllib/request.py", line 1322, in do_open
    raise URLError(err)
urllib.error.URLError: <urlopen error [Errno 99] Address not available>
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "/usr/lib/python3.8/site-packages/appdaemon/threading.py", line 777, in worker
    funcref(entity, attr, old_state, new_state,
  File "/config/appdaemon/apps/address.py", line 44, in get_address
    data = geo.reverse(lat_long)
  File "/usr/lib/python3.8/site-packages/geopy/geocoders/osm.py", line 449, in reverse
    self._call_geocoder(url, timeout=timeout), exactly_one
  File "/usr/lib/python3.8/site-packages/geopy/geocoders/base.py", line 386, in _call_geocoder
    raise GeocoderServiceError(message)
geopy.exc.GeocoderServiceError: [Errno 99] Address not available

using the changed code for the address.py:

"""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_id=entity, attribute="latitude")
        long = self.get_state(entity_id=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_id=entity, attribute="all")["attributes"]

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

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

and has now changed into:

2020-01-16 14:50:39.748035 INFO address: Updating state for device_tracker.life360_marijn
2020-01-16 14:50:39.932944 WARNING HASS: Error setting Home Assistant state default.device_tracker.life360_marijn, {'attributes': {'source_type': 'gps', 'latitude': xxxxx, 'longitude': xxxxx, 'gps_accuracy': 15, 'battery': 29, 'address': 'Home', 'at_loc_since': '2020-01-15T15:57:10+00:00', 'battery_charging': False, 'driving': False, 'last_seen': '2020-01-16T13:50:34+00:00', 'moving': False, 'place': 'Home', 'raw_speed': -1, 'speed': 0, 'wifi_on': True, 'friendly_name': 'Life360 Marijn', 'entity_picture': 'https://www.life360.com/img/user_images/be8redacted8058df15c86/44648e5e--9b30-40f6f3717e22.jpg?fd=2', 'custom_ui_state_card': 'state-card-custom-ui', 'show_last_changed': True, 'house_number': 'xx', 'cycleway': 'xxxweg', 'neighbourhood': 'xxxdijk', 'suburb': 'xxxal', 'town': 'xxxal', 'state': 'Noord-Brabant', 'postcode': 'xxxxx', 'country': 'Nederland', 'country_code': 'nl'}}
2020-01-16 14:50:39.934356 WARNING HASS: Code: 400, error: {"message": "No state specified."}

all attributes are correct, but it can’t be set in the final set_state

do I need something else there? @ReneTode please let me know if you can see some, or, if there is an online checker I can run the code in.