appdaemon 4.5.1__tar.gz → 4.5.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- appdaemon-4.5.3/PKG-INFO +80 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/adapi.py +20 -11
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/adbase.py +5 -3
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/app_management.py +13 -4
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/dependency.py +22 -7
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/dependency_manager.py +9 -3
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/entity.py +0 -2
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/exceptions.py +6 -3
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/http.py +13 -10
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/config/plugin.py +0 -1
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/internal/app_management.py +1 -1
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/plugins/hass/hassapi.py +14 -7
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/plugins/mqtt/mqttapi.py +6 -12
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/version.py +1 -1
- appdaemon-4.5.3/appdaemon.egg-info/PKG-INFO +80 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/pyproject.toml +1 -2
- appdaemon-4.5.1/PKG-INFO +0 -276
- appdaemon-4.5.1/appdaemon.egg-info/PKG-INFO +0 -276
- {appdaemon-4.5.1 → appdaemon-4.5.3}/LICENSE.md +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/MANIFEST.in +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/README.md +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/README.rst +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/__init__.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/__main__.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/admin.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/admin_loop.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/appdaemon.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/aui/appdaemon.png +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/aui/css/app.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/aui/css/chunk-vendors.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/aui/favicon.ico +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/aui/index.html +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/aui/js/app.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/aui/js/app.js.map +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/aui/js/chunk-vendors.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/aui/js/chunk-vendors.js.map +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/all.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/climacons-font.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/default/dashboard.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/default/variables.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/fontawesome.min.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/fonts.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/glassic/dashboard.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/glassic/img/carbon1.jpg +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/glassic/img/carbon2.jpg +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/glassic/img/carbon3.jpg +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/glassic/img/carbon4.jpg +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/glassic/img/glassic_bg.jpg +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/glassic/variables.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/images/ui-icons_444444_256x240.png +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/images/ui-icons_555555_256x240.png +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/images/ui-icons_777620_256x240.png +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/images/ui-icons_777777_256x240.png +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/images/ui-icons_cc0000_256x240.png +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/images/ui-icons_ffffff_256x240.png +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/jquery-ui.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/jquery.gridster.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/main.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/materialdesignicons.min.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/non_dashboard.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/obsidian/dashboard.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/obsidian/img/obsidian_bg.jpg +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/obsidian/img/obsidian_w_bg.jpg +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/obsidian/img/obsidianbg.jpg +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/obsidian/img/widgetbg.jpg +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/obsidian/variables.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/rickshaw.min.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/simplyred/dashboard.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/simplyred/img/goldgradient.png +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/simplyred/img/goldtexture.jpg +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/simplyred/js/timer.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/simplyred/variables.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/v4-shims.min.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/zen/dashboard.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/zen/img/zen_bg.jpg +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/zen/img/zen_bg2.jpg +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/zen/img/zen_weatherbg.jpg +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/css/zen/variables.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/fonts/TickingTimebombBB.ttf +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/fonts/climacons-webfont.eot +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/fonts/climacons-webfont.svg +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/fonts/climacons-webfont.ttf +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/fonts/climacons-webfont.woff +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/fonts/digital-7-mono.eot +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/fonts/digital-7-mono.ttf +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/fonts/materialdesignicons-webfont.eot +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/fonts/materialdesignicons-webfont.ttf +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/fonts/materialdesignicons-webfont.woff +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/fonts/materialdesignicons-webfont.woff2 +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/fonts/repetition.ttf +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/images/Blank.gif +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/images/android-chrome-192x192.png +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/images/android-chrome-512x512.png +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/images/apple-touch-icon.png +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/images/browserconfig.xml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/images/favicon-16x16.png +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/images/favicon-32x32.png +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/images/favicon.ico +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/images/manifest.json +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/images/mstile-144x144.png +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/images/mstile-150x150.png +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/images/mstile-310x150.png +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/images/mstile-310x310.png +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/images/mstile-70x70.png +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/javascript/admin.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/javascript/d3.layout.min.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/javascript/d3.min.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/javascript/dashboard.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/javascript/gauge.min.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/javascript/jquery-3.1.1.min.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/javascript/jquery-ui.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/javascript/jquery.gridster.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/javascript/justgage.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/javascript/knockout-3.4.1.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/javascript/list.min.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/javascript/plotly.min.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/javascript/raphael-2.1.4.min.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/javascript/reconnecting-websocket.min.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/javascript/rickshaw.min.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/javascript/socket.io.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/javascript/sockjs.min.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/javascript/stream.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/templates/admin.jinja2 +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/templates/body_include.jinja2 +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/templates/dashboard.jinja2 +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/templates/dashinit.jinja2 +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/templates/error.jinja2 +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/templates/head_include.jinja2 +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/templates/list.jinja2 +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/templates/logon.jinja2 +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/webfonts/fa-brands-400.eot +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/webfonts/fa-brands-400.svg +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/webfonts/fa-brands-400.ttf +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/webfonts/fa-brands-400.woff +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/webfonts/fa-brands-400.woff2 +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/webfonts/fa-regular-400.eot +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/webfonts/fa-regular-400.svg +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/webfonts/fa-regular-400.ttf +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/webfonts/fa-regular-400.woff +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/webfonts/fa-regular-400.woff2 +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/webfonts/fa-solid-900.eot +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/webfonts/fa-solid-900.svg +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/webfonts/fa-solid-900.ttf +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/webfonts/fa-solid-900.woff +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/assets/webfonts/fa-solid-900.woff2 +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/callbacks.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/dashboard.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/events.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/futures.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/logging.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/__init__.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/config/__init__.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/config/api.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/config/app.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/config/appdaemon.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/config/common.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/config/dashboard.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/config/http.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/config/log.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/config/misc.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/config/sequence.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/config/yaml.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/internal/__init__.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/internal/file_check.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/internal/plugin.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/internal/state.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/internal/threading.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/notification/__init__.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/notification/android.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/notification/base.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/models/notification/iOS.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/plugin_management.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/plugins/__init__.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/plugins/dummy/dummyapi.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/plugins/dummy/dummyplugin.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/plugins/hass/__init__.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/plugins/hass/exceptions.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/plugins/hass/hassplugin.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/plugins/hass/models.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/plugins/hass/notifications.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/plugins/hass/utils.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/plugins/mqtt/__init__.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/plugins/mqtt/mqttplugin.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/pyversions.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/scheduler.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/sequences.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/services.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/state.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/stream/__init__.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/stream/adstream.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/stream/socketio_handler.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/stream/sockjs_handler.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/stream/ws_handler.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/thread_async.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/threads.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/utility_loop.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/utils.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/AdminLog.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/AdminSummary.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/AdminTable.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/alarm.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basealarm/basealarm.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basealarm/basealarm.html +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basealarm/basealarm.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basecamera/basecamera.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basecamera/basecamera.html +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basecamera/basecamera.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseclimate/baseclimate.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseclimate/baseclimate.html +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseclimate/baseclimate.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseclock/baseclock.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseclock/baseclock.html +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseclock/baseclock.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basedatetime/basedatetime.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basedatetime/basedatetime.html +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basedatetime/basedatetime.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basedisplay/basedisplay.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basedisplay/basedisplay.html +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basedisplay/basedisplay.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseentitypicture/baseentitypicture.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseentitypicture/baseentitypicture.html +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseentitypicture/baseentitypicture.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseerror/baseerror.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseerror/baseerror.html +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseerror/baseerror.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basefan/basefan.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basefan/basefan.html +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basefan/basefan.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basegauge/basegauge.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basegauge/basegauge.html +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basegauge/basegauge.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseheater/baseheater.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseheater/baseheater.html +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseheater/baseheater.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseicon/baseicon.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseicon/baseicon.html +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseicon/baseicon.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseiframe/baseiframe.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseiframe/baseiframe.html +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseiframe/baseiframe.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseinputnumber/baseinputnumber.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseinputnumber/baseinputnumber.html +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseinputnumber/baseinputnumber.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basejavascript/basejavascript.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basejavascript/basejavascript.html +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basejavascript/basejavascript.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baselight/baselight.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baselight/baselight.html +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baselight/baselight.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basemedia/basemedia.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basemedia/basemedia.html +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basemedia/basemedia.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseradial/baseradial.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseradial/baseradial.html +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseradial/baseradial.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baserss/baserss.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baserss/baserss.html +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baserss/baserss.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseselect/baseselect.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseselect/baseselect.html +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseselect/baseselect.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseslider/baseslider.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseslider/baseslider.html +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseslider/baseslider.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseswitch/baseswitch.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseswitch/baseswitch.html +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseswitch/baseswitch.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basetemperature/basetemperature.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basetemperature/basetemperature.html +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basetemperature/basetemperature.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basetext/basetext.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basetext/basetext.html +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/basetext/basetext.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseweather/baseweather.css +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseweather/baseweather.html +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/baseweather/baseweather.js +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/binary_sensor.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/camera.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/climate.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/clock.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/cover.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/device_tracker.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/entitypicture.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/fan.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/gauge.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/group.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/heater.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/icon.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/iframe.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/input_boolean.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/input_datetime.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/input_number.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/input_select.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/input_slider.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/input_text.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/javascript.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/label.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/light.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/lock.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/london_underground.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/media_player.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/mode.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/navigate.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/person.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/pirateweather.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/radial.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/reload.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/rss.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/scene.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/script.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/sensor.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/sequence.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/switch.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/temperature.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/text_sensor.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/weather.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon/widgets/weather_summary.yaml +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon.egg-info/SOURCES.txt +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon.egg-info/dependency_links.txt +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon.egg-info/entry_points.txt +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon.egg-info/requires.txt +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/appdaemon.egg-info/top_level.txt +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/apps/hello.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/ObjectTracker/general_app_functions.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/ObjectTracker/objectcontrole.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/alexa.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/battery.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/bysykkel.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/commute.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/dark_day.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/door_notification.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/eventCache.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/eventMonitor.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/globals.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/grandfather.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/hwcheck.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/ical.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/minimote.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/modes.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/momentary_switch.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/motion_lights.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/motion_notification.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/occusim.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/outside_lights.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/presence.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/ruter.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/secure.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/sensor_notification.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/sensor_notify.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/sequence.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/smart_heat.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/sound.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/switch_reset.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/conf/example_apps/yr.py +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/setup.cfg +0 -0
- {appdaemon-4.5.1 → appdaemon-4.5.3}/tests/test_main.py +0 -0
appdaemon-4.5.3/PKG-INFO
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: appdaemon
|
|
3
|
+
Version: 4.5.3
|
|
4
|
+
Summary: Apps for the Home Assistant home automation package.
|
|
5
|
+
Author-email: Andrew I Cockburn <appdaemon@acockburn.com>
|
|
6
|
+
Project-URL: documentation, https://appdaemon.readthedocs.io
|
|
7
|
+
Project-URL: repository, https://github.com/AppDaemon
|
|
8
|
+
Project-URL: changelog, https://github.com/AppDaemon/appdaemon/blob/master/docs/HISTORY.rst
|
|
9
|
+
Keywords: appdaemon,home,automation
|
|
10
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Natural Language :: English
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Topic :: Home Automation
|
|
17
|
+
Requires-Python: <3.13,>=3.10
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
License-File: LICENSE.md
|
|
20
|
+
Requires-Dist: importlib-metadata; python_version < "3.8"
|
|
21
|
+
Requires-Dist: aiohttp<3.12.0,>=3.9.0
|
|
22
|
+
Requires-Dist: aiohttp_jinja2<1.7.0,>=1.5.1
|
|
23
|
+
Requires-Dist: astral~=3.2
|
|
24
|
+
Requires-Dist: bcrypt<4.3.0,>=4.0.1
|
|
25
|
+
Requires-Dist: deepdiff==8.2.0
|
|
26
|
+
Requires-Dist: feedparser~=6.0.10
|
|
27
|
+
Requires-Dist: iso8601<2.2,>=1.1
|
|
28
|
+
Requires-Dist: paho-mqtt<2.2.0,>=1.6.1
|
|
29
|
+
Requires-Dist: pid~=3.0.4
|
|
30
|
+
Requires-Dist: python-dateutil<2.10.0,>=2.8.2
|
|
31
|
+
Requires-Dist: python-socketio<5.12,>=5.5
|
|
32
|
+
Requires-Dist: pytz<2025.2.0,>=2022.7.1
|
|
33
|
+
Requires-Dist: pyyaml~=6.0.1
|
|
34
|
+
Requires-Dist: requests<2.33.0,>=2.28.2
|
|
35
|
+
Requires-Dist: sockjs<0.14,>=0.11
|
|
36
|
+
Requires-Dist: uvloop==0.21.0; sys_platform != "win32"
|
|
37
|
+
Requires-Dist: tomli==2.2.1
|
|
38
|
+
Requires-Dist: tomli_w<1.3,>=1.0
|
|
39
|
+
Requires-Dist: pydantic~=2.10.6
|
|
40
|
+
Provides-Extra: dev
|
|
41
|
+
Requires-Dist: pip-tools<7.5.0,>=6.12.3; extra == "dev"
|
|
42
|
+
Requires-Dist: build<1.3,>=0.10; extra == "dev"
|
|
43
|
+
Requires-Dist: flake8~=7.1.1; extra == "dev"
|
|
44
|
+
Requires-Dist: black<25.2,>=23.1; extra == "dev"
|
|
45
|
+
Requires-Dist: pre-commit<3.9.0,>=3.1.1; python_version > "3.7" and extra == "dev"
|
|
46
|
+
Requires-Dist: pytest<8.4.0,>=7.2.1; extra == "dev"
|
|
47
|
+
Requires-Dist: ruff<0.7.0,>=0.0.261; extra == "dev"
|
|
48
|
+
Requires-Dist: codespell>=2.4.1; extra == "dev"
|
|
49
|
+
Provides-Extra: doc
|
|
50
|
+
Requires-Dist: sphinx-autobuild<2024.10.0,>=2021.3.14; extra == "doc"
|
|
51
|
+
Requires-Dist: sphinx-rtd-theme==3.0.2; extra == "doc"
|
|
52
|
+
Requires-Dist: pygments<2.20,>=2.14; extra == "doc"
|
|
53
|
+
Requires-Dist: myst-parser==4.0.0; extra == "doc"
|
|
54
|
+
Dynamic: license-file
|
|
55
|
+
|
|
56
|
+
# Description
|
|
57
|
+
|
|
58
|
+
AppDaemon is a loosely coupled, multi-threaded, sandboxed python
|
|
59
|
+
execution environment for writing automation apps for various types of Home Automation Software including [Home
|
|
60
|
+
Assistant](https://home-assistant.io/) and MQTT. It has a pluggable architecture allowing it to be integrated with
|
|
61
|
+
practically any event driven application.
|
|
62
|
+
|
|
63
|
+
It also provides a configurable dashboard (HADashboard)
|
|
64
|
+
suitable for wall mounted tablets.
|
|
65
|
+
|
|
66
|
+
## Getting started
|
|
67
|
+
|
|
68
|
+
For full instructions on installation and usage check out the [AppDaemon Project Documentation](http://appdaemon.readthedocs.io).
|
|
69
|
+
|
|
70
|
+
## Release Cycle Frequency
|
|
71
|
+
|
|
72
|
+
AppDaemon has reached a very stable point, works reliably and is fairly feature rich at this point
|
|
73
|
+
in its development. For that reason, releases have been slow in recent months. This does not mean that AppDaemon has been abandoned -
|
|
74
|
+
it is used every day by the core developers and has an active discord server [here](https://discord.gg/sgSr79jW5x) - please join us for tips
|
|
75
|
+
and tricks, AppDaemon discussions and general home automation.
|
|
76
|
+
|
|
77
|
+
## Contributing
|
|
78
|
+
|
|
79
|
+
This is an active open-source project. We are always open to people who want to use the code or contribute to it. Thank you for being involved!
|
|
80
|
+
Have a look at the [official documentation](https://appdaemon.readthedocs.io/en/latest/DEV.html) for more information.
|
|
@@ -489,7 +489,8 @@ class ADAPI:
|
|
|
489
489
|
# Threading
|
|
490
490
|
#
|
|
491
491
|
|
|
492
|
-
|
|
492
|
+
@utils.sync_decorator
|
|
493
|
+
async def set_app_pin(self, pin: bool) -> None:
|
|
493
494
|
"""Sets an App to be pinned or unpinned.
|
|
494
495
|
|
|
495
496
|
Args:
|
|
@@ -506,7 +507,8 @@ class ADAPI:
|
|
|
506
507
|
"""
|
|
507
508
|
self.AD.app_management.set_app_pin(self.name, pin)
|
|
508
509
|
|
|
509
|
-
|
|
510
|
+
@utils.sync_decorator
|
|
511
|
+
async def get_app_pin(self) -> bool:
|
|
510
512
|
"""Finds out if the current App is currently pinned or not.
|
|
511
513
|
|
|
512
514
|
Returns:
|
|
@@ -519,7 +521,8 @@ class ADAPI:
|
|
|
519
521
|
"""
|
|
520
522
|
return self.AD.app_management.get_app_pin(self.name)
|
|
521
523
|
|
|
522
|
-
|
|
524
|
+
@utils.sync_decorator
|
|
525
|
+
async def set_pin_thread(self, thread: int) -> None:
|
|
523
526
|
"""Sets the thread that the App will be pinned to.
|
|
524
527
|
|
|
525
528
|
Args:
|
|
@@ -537,7 +540,8 @@ class ADAPI:
|
|
|
537
540
|
"""
|
|
538
541
|
self.AD.app_management.set_pin_thread(self.name, thread)
|
|
539
542
|
|
|
540
|
-
|
|
543
|
+
@utils.sync_decorator
|
|
544
|
+
async def get_pin_thread(self) -> int:
|
|
541
545
|
"""Finds out which thread the App is pinned to.
|
|
542
546
|
|
|
543
547
|
Returns:
|
|
@@ -590,7 +594,8 @@ class ADAPI:
|
|
|
590
594
|
# Keeping namespace get/set functions for legacy compatibility
|
|
591
595
|
return self.namespace
|
|
592
596
|
|
|
593
|
-
|
|
597
|
+
@utils.sync_decorator
|
|
598
|
+
async def namespace_exists(self, namespace: str) -> bool:
|
|
594
599
|
"""Check the existence of a namespace in AppDaemon.
|
|
595
600
|
|
|
596
601
|
See the `namespace documentation <APPGUIDE.html#namespaces>`__ for more information.
|
|
@@ -668,7 +673,8 @@ class ADAPI:
|
|
|
668
673
|
|
|
669
674
|
return await self.AD.state.remove_namespace(namespace)
|
|
670
675
|
|
|
671
|
-
|
|
676
|
+
@utils.sync_decorator
|
|
677
|
+
async def list_namespaces(self) -> list[str]:
|
|
672
678
|
"""Get a list of all the namespaces in AppDaemon.
|
|
673
679
|
|
|
674
680
|
Examples:
|
|
@@ -909,7 +915,8 @@ class ADAPI:
|
|
|
909
915
|
"""
|
|
910
916
|
return devices.split(",")
|
|
911
917
|
|
|
912
|
-
|
|
918
|
+
@utils.sync_decorator
|
|
919
|
+
async def get_plugin_config(self, namespace: str | None = None) -> Any:
|
|
913
920
|
"""Gets any useful metadata that the plugin may have available.
|
|
914
921
|
|
|
915
922
|
For instance, for the HASS plugin, this will return Home Assistant configuration
|
|
@@ -931,7 +938,8 @@ class ADAPI:
|
|
|
931
938
|
namespace = namespace or self.namespace
|
|
932
939
|
return self.AD.plugins.get_plugin_meta(namespace)
|
|
933
940
|
|
|
934
|
-
|
|
941
|
+
@utils.sync_decorator
|
|
942
|
+
async def friendly_name(self, entity_id: str, namespace: str | None = None) -> str:
|
|
935
943
|
"""Gets the Friendly Name of an entity.
|
|
936
944
|
|
|
937
945
|
Args:
|
|
@@ -1380,7 +1388,7 @@ class ADAPI:
|
|
|
1380
1388
|
# State
|
|
1381
1389
|
#
|
|
1382
1390
|
|
|
1383
|
-
@overload
|
|
1391
|
+
@overload # single entity
|
|
1384
1392
|
@utils.sync_decorator
|
|
1385
1393
|
async def listen_state(
|
|
1386
1394
|
self,
|
|
@@ -1399,7 +1407,7 @@ class ADAPI:
|
|
|
1399
1407
|
**kwargs: Any
|
|
1400
1408
|
) -> str: ...
|
|
1401
1409
|
|
|
1402
|
-
@overload
|
|
1410
|
+
@overload # multiple entities
|
|
1403
1411
|
@utils.sync_decorator
|
|
1404
1412
|
async def listen_state(
|
|
1405
1413
|
self,
|
|
@@ -3642,7 +3650,8 @@ class ADAPI:
|
|
|
3642
3650
|
self.AD.futures.add_future(self.name, future)
|
|
3643
3651
|
return future
|
|
3644
3652
|
|
|
3645
|
-
|
|
3653
|
+
@utils.sync_decorator
|
|
3654
|
+
async def create_task(
|
|
3646
3655
|
self,
|
|
3647
3656
|
coro: Coroutine[Any, Any, T],
|
|
3648
3657
|
callback: Callable | None = None,
|
|
@@ -5,8 +5,9 @@ from pathlib import Path
|
|
|
5
5
|
from typing import TYPE_CHECKING
|
|
6
6
|
|
|
7
7
|
from appdaemon import adapi
|
|
8
|
+
from appdaemon import utils
|
|
8
9
|
from appdaemon.models.config.app import AppConfig
|
|
9
|
-
|
|
10
|
+
|
|
10
11
|
|
|
11
12
|
# Check if the module is being imported using the legacy method
|
|
12
13
|
if __name__ == Path(__file__).name:
|
|
@@ -31,7 +32,7 @@ class Entities: # @todo
|
|
|
31
32
|
pass
|
|
32
33
|
|
|
33
34
|
def __get__(self, instance, owner):
|
|
34
|
-
stateattrs = StateAttrs(instance.get_state())
|
|
35
|
+
stateattrs = utils.StateAttrs(instance.get_state())
|
|
35
36
|
return stateattrs
|
|
36
37
|
|
|
37
38
|
|
|
@@ -165,7 +166,8 @@ class ADBase:
|
|
|
165
166
|
def get_ad_api(self) -> adapi.ADAPI:
|
|
166
167
|
return adapi.ADAPI(self.AD, self.config_model)
|
|
167
168
|
|
|
168
|
-
|
|
169
|
+
@utils.sync_decorator
|
|
170
|
+
async def get_plugin_api(self, plugin_name: str):
|
|
169
171
|
"""Get the plugin API for a specific plugin."""
|
|
170
172
|
if isinstance(cfg := self.app_config.root.get(self.name), AppConfig):
|
|
171
173
|
return self.AD.plugins.get_plugin_api(plugin_name, cfg)
|
|
@@ -615,7 +615,7 @@ class AppManagement:
|
|
|
615
615
|
self._compare_sequences(update_actions, cfg, files_to_read)
|
|
616
616
|
continue
|
|
617
617
|
|
|
618
|
-
if name in self.non_apps:
|
|
618
|
+
if name in self.non_apps or cfg.disable:
|
|
619
619
|
continue
|
|
620
620
|
|
|
621
621
|
# New config found
|
|
@@ -685,8 +685,14 @@ class AppManagement:
|
|
|
685
685
|
if not module_name.startswith("appdaemon"):
|
|
686
686
|
self.logger.debug("Importing '%s'", module_name)
|
|
687
687
|
importlib.import_module(module_name)
|
|
688
|
-
except
|
|
689
|
-
|
|
688
|
+
except Exception as exc:
|
|
689
|
+
match exc:
|
|
690
|
+
case SyntaxError():
|
|
691
|
+
path = Path(exc.filename)
|
|
692
|
+
case NameError():
|
|
693
|
+
path = Path(traceback.extract_tb(exc.__traceback__)[-1].filename)
|
|
694
|
+
case _:
|
|
695
|
+
raise exc
|
|
690
696
|
mtime = self.dependency_manager.python_deps.files.mtimes.get(path)
|
|
691
697
|
self.dependency_manager.python_deps.bad_files.add((path, mtime))
|
|
692
698
|
raise exc
|
|
@@ -989,13 +995,16 @@ class AppManagement:
|
|
|
989
995
|
update_actions.apps.reload -= failed_to_stop
|
|
990
996
|
|
|
991
997
|
async def _start_apps(self, update_actions: UpdateActions):
|
|
998
|
+
if failed := update_actions.apps.failed:
|
|
999
|
+
self.logger.warning('Failed to start apps: %s', failed)
|
|
1000
|
+
|
|
992
1001
|
start_order = update_actions.apps.start_sort(self.dependency_manager)
|
|
993
1002
|
if start_order:
|
|
994
1003
|
self.logger.info("Starting apps: %s", update_actions.apps.init_set)
|
|
995
1004
|
self.logger.debug("App start order: %s", start_order)
|
|
996
1005
|
|
|
997
1006
|
for app_name in start_order:
|
|
998
|
-
if isinstance((cfg := self.app_config.root[app_name]), AppConfig):
|
|
1007
|
+
if isinstance((cfg := self.app_config.root[app_name]), AppConfig) and not cfg.disable:
|
|
999
1008
|
@ade.wrap_async(self.error, self.AD.app_dir, f"'{app_name}' instantiation")
|
|
1000
1009
|
async def safe_create(self: "AppManagement"):
|
|
1001
1010
|
try:
|
|
@@ -92,6 +92,7 @@ def get_file_deps(file_path: str | Path) -> set[str]:
|
|
|
92
92
|
mod: ast.Module = ast.parse(file_content, filename=file_path)
|
|
93
93
|
except Exception as e:
|
|
94
94
|
logger.warning(f"Error parsing python module with AST: {e}")
|
|
95
|
+
raise e
|
|
95
96
|
else:
|
|
96
97
|
for node in get_imports(mod):
|
|
97
98
|
match node:
|
|
@@ -107,18 +108,32 @@ def get_file_deps(file_path: str | Path) -> set[str]:
|
|
|
107
108
|
return set(gen_modules())
|
|
108
109
|
|
|
109
110
|
|
|
110
|
-
def get_dependency_graph(
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
111
|
+
def get_dependency_graph(
|
|
112
|
+
files: Iterable[Path],
|
|
113
|
+
exclude: set[Path] | None = None
|
|
114
|
+
) -> tuple[dict[str, set[str]], set[Path]]:
|
|
115
|
+
"""Gets the dependency graph for some Python files.
|
|
116
|
+
|
|
117
|
+
Returns:
|
|
118
|
+
A tuple containing:
|
|
119
|
+
- A dictionary where keys are module names and values are sets of module names that the key module depends on.
|
|
120
|
+
- A set of paths that failed to parse or resolve dependencies.
|
|
121
|
+
"""
|
|
122
|
+
graph = {}
|
|
123
|
+
failed = set()
|
|
124
|
+
for f in files:
|
|
125
|
+
if exclude is None or f not in exclude:
|
|
126
|
+
try:
|
|
127
|
+
graph[get_full_module_name(f)] = get_file_deps(f)
|
|
128
|
+
except Exception:
|
|
129
|
+
failed.add(f)
|
|
130
|
+
continue
|
|
116
131
|
|
|
117
132
|
for mod, deps in graph.items():
|
|
118
133
|
if mod in deps:
|
|
119
134
|
deps.remove(mod)
|
|
120
135
|
|
|
121
|
-
return graph
|
|
136
|
+
return graph, failed
|
|
122
137
|
|
|
123
138
|
|
|
124
139
|
def get_all_nodes(deps: dict[str, set[str]]) -> set[str]:
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from abc import ABC
|
|
2
|
+
from copy import deepcopy
|
|
2
3
|
from dataclasses import InitVar, dataclass, field
|
|
3
4
|
from pathlib import Path
|
|
4
5
|
from typing import Iterable
|
|
@@ -16,14 +17,14 @@ class Dependencies(ABC):
|
|
|
16
17
|
ext: str = field(init=False) # this has to be defined by the children classes
|
|
17
18
|
dep_graph: dict[str, set[str]] = field(init=False)
|
|
18
19
|
rev_graph: dict[str, set[str]] = field(init=False)
|
|
19
|
-
bad_files: set[Path] = field(default_factory=set, init=False)
|
|
20
|
+
bad_files: set[tuple[Path, float]] = field(default_factory=set, init=False)
|
|
20
21
|
|
|
21
22
|
def __post_init__(self):
|
|
22
23
|
self.refresh_dep_graph()
|
|
23
24
|
|
|
24
25
|
def update(self, new_files: Iterable[Path]):
|
|
25
26
|
self.files.update(new_files)
|
|
26
|
-
for bf, mtime in self.bad_files:
|
|
27
|
+
for bf, mtime in deepcopy(self.bad_files):
|
|
27
28
|
new_mtime = self.files.mtimes.get(bf)
|
|
28
29
|
if new_mtime != mtime:
|
|
29
30
|
assert new_mtime > mtime, f"File {bf} was modified in the future"
|
|
@@ -65,7 +66,12 @@ class PythonDeps(Dependencies):
|
|
|
65
66
|
if self.bad_files:
|
|
66
67
|
bad_files, _ = zip(*self.bad_files)
|
|
67
68
|
bad_files = set(bad_files)
|
|
68
|
-
|
|
69
|
+
|
|
70
|
+
self.dep_graph, failed = get_dependency_graph(self.files, exclude=bad_files)
|
|
71
|
+
|
|
72
|
+
for file in failed:
|
|
73
|
+
self.bad_files.add((file, self.files.mtimes.get(file, 0)))
|
|
74
|
+
|
|
69
75
|
self.rev_graph = reverse_graph(self.dep_graph)
|
|
70
76
|
|
|
71
77
|
def modules_to_import(self) -> set[str]:
|
|
@@ -355,8 +355,6 @@ class Entity:
|
|
|
355
355
|
|
|
356
356
|
Args:
|
|
357
357
|
service (str): The service name, without the domain (e.g "toggle")
|
|
358
|
-
return_result(bool, option): If `return_result` is provided and set to `True` AD will attempt
|
|
359
|
-
to wait for the result, and return it after execution
|
|
360
358
|
callback: The non-async callback to be executed when complete.
|
|
361
359
|
**kwargs: Each service has different parameter requirements. This argument
|
|
362
360
|
allows you to specify a comma-separated list of keyword value pairs, e.g.,
|
|
@@ -54,9 +54,10 @@ def user_exception_block(logger: Logger, exception: AppDaemonException, app_dir:
|
|
|
54
54
|
"""Function to generate a user-friendly block of text for an exception. Gets the whole chain of exception causes to decide what to do.
|
|
55
55
|
"""
|
|
56
56
|
width = 75
|
|
57
|
+
spacing = 4
|
|
57
58
|
inset = 5
|
|
58
59
|
if header is not None:
|
|
59
|
-
header = f'{"=" * inset} {header} {"=" * (width - inset - len(header))}'
|
|
60
|
+
header = f'{"=" * inset} {header} {"=" * (width - spacing - inset - len(header))}'
|
|
60
61
|
else:
|
|
61
62
|
header = '=' * width
|
|
62
63
|
logger.error(header)
|
|
@@ -86,10 +87,12 @@ def user_exception_block(logger: Logger, exception: AppDaemonException, app_dir:
|
|
|
86
87
|
logger.error(f'{indent}{filename} line {line} in {func_name}')
|
|
87
88
|
case OSError() if str(exc).endswith('address already in use'):
|
|
88
89
|
logger.error(f'{indent}{exc.__class__.__name__}: {exc}')
|
|
89
|
-
case NameError():
|
|
90
|
+
case NameError() | ImportError():
|
|
90
91
|
logger.error(f'{indent}{exc.__class__.__name__}: {exc}')
|
|
91
92
|
if tb := traceback.extract_tb(exc.__traceback__):
|
|
92
93
|
frame = tb[-1]
|
|
94
|
+
file = Path(frame.filename).relative_to(app_dir.parent)
|
|
95
|
+
logger.error(f'{indent} line {frame.lineno} in {file.name}')
|
|
93
96
|
logger.error(f'{indent} {frame._line.rstrip()}')
|
|
94
97
|
error_len = frame.end_colno - frame.colno
|
|
95
98
|
logger.error(f'{indent} {" " * (frame.colno - 1)}{"^" * error_len}')
|
|
@@ -112,7 +115,7 @@ def user_exception_block(logger: Logger, exception: AppDaemonException, app_dir:
|
|
|
112
115
|
for line in lines:
|
|
113
116
|
logger.error(f'{indent}{line}')
|
|
114
117
|
|
|
115
|
-
logger.error('=' *
|
|
118
|
+
logger.error('=' * width)
|
|
116
119
|
|
|
117
120
|
|
|
118
121
|
def unexpected_block(logger: Logger, exception: Exception):
|
|
@@ -96,9 +96,7 @@ def route_secure(myfunc):
|
|
|
96
96
|
return await myfunc(*args)
|
|
97
97
|
|
|
98
98
|
elif "adcreds" in request.cookies:
|
|
99
|
-
match = await utils.run_in_executor(
|
|
100
|
-
self, bcrypt.checkpw, str.encode(self.password), str.encode(request.cookies["adcreds"])
|
|
101
|
-
)
|
|
99
|
+
match = await utils.run_in_executor(self, bcrypt.checkpw, str.encode(self.password), str.encode(request.cookies["adcreds"]))
|
|
102
100
|
if match:
|
|
103
101
|
return await myfunc(*args)
|
|
104
102
|
|
|
@@ -176,12 +174,19 @@ class HTTP:
|
|
|
176
174
|
|
|
177
175
|
try:
|
|
178
176
|
url = urlparse(self.url)
|
|
179
|
-
|
|
180
177
|
self.host = url.hostname
|
|
181
|
-
|
|
178
|
+
self.scheme = url.scheme
|
|
179
|
+
|
|
180
|
+
if url.port is None:
|
|
181
|
+
match url.scheme:
|
|
182
|
+
case "http":
|
|
183
|
+
self.port = 80
|
|
184
|
+
case "https":
|
|
185
|
+
self.port = 443
|
|
186
|
+
case _:
|
|
187
|
+
self.port = None # let the validation catch it
|
|
188
|
+
else:
|
|
182
189
|
self.port = url.port
|
|
183
|
-
except IndexError:
|
|
184
|
-
self.port = 80
|
|
185
190
|
|
|
186
191
|
if self.host == "":
|
|
187
192
|
raise ValueError("Invalid host for 'url'")
|
|
@@ -373,9 +378,7 @@ class HTTP:
|
|
|
373
378
|
|
|
374
379
|
self._process_arg("url", http)
|
|
375
380
|
if not self.url:
|
|
376
|
-
self.logger.warning(
|
|
377
|
-
"'{arg}' is '{value}'. Please configure appdaemon.yaml".format(arg="url", value=self.url)
|
|
378
|
-
)
|
|
381
|
+
self.logger.warning("'{arg}' is '{value}'. Please configure appdaemon.yaml".format(arg="url", value=self.url))
|
|
379
382
|
exit(0)
|
|
380
383
|
|
|
381
384
|
self._process_arg("transport", http)
|
|
@@ -100,7 +100,6 @@ class HASSConfig(PluginConfig):
|
|
|
100
100
|
BeforeValidator(utils.parse_timedelta)
|
|
101
101
|
] = Field(default_factory=lambda: timedelta(seconds=10))
|
|
102
102
|
"""Default timeout for waiting for responses from the websocket connection"""
|
|
103
|
-
# return_result: bool | None = None
|
|
104
103
|
suppress_log_messages: bool = False
|
|
105
104
|
retry_secs: int = 5
|
|
106
105
|
services_sleep_time: int = 60
|
|
@@ -71,7 +71,7 @@ class LoadingActions:
|
|
|
71
71
|
Uses a dependency graph to sort the internal ``init`` and ``reload`` sets together
|
|
72
72
|
"""
|
|
73
73
|
items = copy(self.init_set)
|
|
74
|
-
items |= find_all_dependents(items, dm.app_deps.
|
|
74
|
+
items |= find_all_dependents(items, dm.app_deps.dep_graph)
|
|
75
75
|
priorities = {
|
|
76
76
|
app_name: dm.app_deps.app_config.root[app_name].priority
|
|
77
77
|
for app_name in items
|
|
@@ -260,7 +260,8 @@ class Hass(ADBase, ADAPI):
|
|
|
260
260
|
"""
|
|
261
261
|
return self.get_state(*args, **kwargs)
|
|
262
262
|
|
|
263
|
-
|
|
263
|
+
@utils.sync_decorator
|
|
264
|
+
async def anyone_home(self, person: bool = True, namespace: str | None = None) -> bool:
|
|
264
265
|
"""Determines if the house/apartment is occupied.
|
|
265
266
|
|
|
266
267
|
A convenience function to determine if one or more person is home. Use
|
|
@@ -285,10 +286,11 @@ class Hass(ADBase, ADAPI):
|
|
|
285
286
|
>>> do something
|
|
286
287
|
|
|
287
288
|
"""
|
|
288
|
-
details = self.get_tracker_details(person, namespace, copy=False)
|
|
289
|
+
details = await self.get_tracker_details(person, namespace, copy=False)
|
|
289
290
|
return any(state['state'] == 'home' for state in details.values())
|
|
290
291
|
|
|
291
|
-
|
|
292
|
+
@utils.sync_decorator
|
|
293
|
+
async def everyone_home(self, person: bool = True, namespace: str | None = None) -> bool:
|
|
292
294
|
"""Determine if all family's members at home.
|
|
293
295
|
|
|
294
296
|
A convenience function to determine if everyone is home. Use this in
|
|
@@ -312,10 +314,11 @@ class Hass(ADBase, ADAPI):
|
|
|
312
314
|
>>> do something
|
|
313
315
|
|
|
314
316
|
"""
|
|
315
|
-
details = self.get_tracker_details(person, namespace, copy=False)
|
|
317
|
+
details = await self.get_tracker_details(person, namespace, copy=False)
|
|
316
318
|
return all(state['state'] == 'home' for state in details.values())
|
|
317
319
|
|
|
318
|
-
|
|
320
|
+
@utils.sync_decorator
|
|
321
|
+
async def noone_home(self, person: bool = True, namespace: str | None = None) -> bool:
|
|
319
322
|
"""Determines if the house/apartment is empty.
|
|
320
323
|
|
|
321
324
|
A convenience function to determine if no people are at home. Use this
|
|
@@ -340,7 +343,7 @@ class Hass(ADBase, ADAPI):
|
|
|
340
343
|
>>> do something
|
|
341
344
|
|
|
342
345
|
"""
|
|
343
|
-
return not self.anyone_home(person, namespace)
|
|
346
|
+
return not await self.anyone_home(person, namespace)
|
|
344
347
|
|
|
345
348
|
#
|
|
346
349
|
# Built-in constraints
|
|
@@ -1375,7 +1378,7 @@ class Hass(ADBase, ADAPI):
|
|
|
1375
1378
|
except (SyntaxError, ValueError):
|
|
1376
1379
|
return result
|
|
1377
1380
|
|
|
1378
|
-
def _template_command(self, command: str, *args:
|
|
1381
|
+
def _template_command(self, command: str, *args: str) -> str | list[str]:
|
|
1379
1382
|
"""Internal AppDaemon function to format calling a single template command correctly."""
|
|
1380
1383
|
if len(args) == 0:
|
|
1381
1384
|
return self.render_template(f'{{{{ {command}() }}}}')
|
|
@@ -1478,6 +1481,10 @@ class Hass(ADBase, ADAPI):
|
|
|
1478
1481
|
<https://www.home-assistant.io/docs/configuration/templating/#entities-for-an-integration>`_ for more
|
|
1479
1482
|
information.
|
|
1480
1483
|
"""
|
|
1484
|
+
entities = self._template_command('integration_entities', integration)
|
|
1485
|
+
assert isinstance(entities, list) and all(isinstance(e, str) for e in entities), \
|
|
1486
|
+
'Invalid return type from integration_entities'
|
|
1487
|
+
return entities
|
|
1481
1488
|
|
|
1482
1489
|
# Labels
|
|
1483
1490
|
# https://www.home-assistant.io/docs/configuration/templating/#labels
|
|
@@ -229,23 +229,17 @@ class Mqtt(adbase.ADBase, adapi.ADAPI):
|
|
|
229
229
|
result = self.call_service(service, **kwargs)
|
|
230
230
|
return result
|
|
231
231
|
|
|
232
|
-
def _run_service_call(self, task: str, topic:
|
|
232
|
+
def _run_service_call(self, task: str, topic: str | list[str], **kwargs: Optional[Any]) -> None:
|
|
233
233
|
"""Used to process the subscribe/unsubscribe service calls"""
|
|
234
234
|
|
|
235
235
|
# first we validate the topic
|
|
236
236
|
if not isinstance(topic, (str, list)):
|
|
237
237
|
raise ValueError(f"The given topic {topic} is not supported. Please only strs and lists are supported")
|
|
238
238
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
self.call_service(service, **kwargs)
|
|
239
|
+
kwargs["topic"] = topic
|
|
240
|
+
service = f"mqtt/{task}"
|
|
241
|
+
return self.call_service(service, **kwargs)
|
|
243
242
|
|
|
244
|
-
else: # its a list
|
|
245
|
-
for t in topic:
|
|
246
|
-
kwargs["topic"] = t
|
|
247
|
-
service = f"mqtt/{task}"
|
|
248
|
-
self.call_service(service, **kwargs)
|
|
249
243
|
|
|
250
244
|
def mqtt_subscribe(self, topic: Union[str, list], **kwargs: Optional[Any]) -> None:
|
|
251
245
|
"""Subscribes to a MQTT topic.
|
|
@@ -284,7 +278,7 @@ class Mqtt(adbase.ADBase, adapi.ADAPI):
|
|
|
284
278
|
|
|
285
279
|
"""
|
|
286
280
|
|
|
287
|
-
self._run_service_call("subscribe", topic, **kwargs)
|
|
281
|
+
return self._run_service_call("subscribe", topic, **kwargs)
|
|
288
282
|
|
|
289
283
|
def mqtt_unsubscribe(self, topic: Union[str, list], **kwargs: Optional[Any]) -> None:
|
|
290
284
|
"""Unsubscribes from a MQTT topic.
|
|
@@ -323,7 +317,7 @@ class Mqtt(adbase.ADBase, adapi.ADAPI):
|
|
|
323
317
|
|
|
324
318
|
"""
|
|
325
319
|
|
|
326
|
-
self._run_service_call("unsubscribe", topic, **kwargs)
|
|
320
|
+
return self._run_service_call("unsubscribe", topic, **kwargs)
|
|
327
321
|
|
|
328
322
|
@utils.sync_decorator
|
|
329
323
|
async def is_client_connected(self, **kwargs: Optional[Any]) -> bool:
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
__version__ = "4.5.
|
|
1
|
+
__version__ = "4.5.3"
|
|
2
2
|
__version_comments__ = ""
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: appdaemon
|
|
3
|
+
Version: 4.5.3
|
|
4
|
+
Summary: Apps for the Home Assistant home automation package.
|
|
5
|
+
Author-email: Andrew I Cockburn <appdaemon@acockburn.com>
|
|
6
|
+
Project-URL: documentation, https://appdaemon.readthedocs.io
|
|
7
|
+
Project-URL: repository, https://github.com/AppDaemon
|
|
8
|
+
Project-URL: changelog, https://github.com/AppDaemon/appdaemon/blob/master/docs/HISTORY.rst
|
|
9
|
+
Keywords: appdaemon,home,automation
|
|
10
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Natural Language :: English
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Topic :: Home Automation
|
|
17
|
+
Requires-Python: <3.13,>=3.10
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
License-File: LICENSE.md
|
|
20
|
+
Requires-Dist: importlib-metadata; python_version < "3.8"
|
|
21
|
+
Requires-Dist: aiohttp<3.12.0,>=3.9.0
|
|
22
|
+
Requires-Dist: aiohttp_jinja2<1.7.0,>=1.5.1
|
|
23
|
+
Requires-Dist: astral~=3.2
|
|
24
|
+
Requires-Dist: bcrypt<4.3.0,>=4.0.1
|
|
25
|
+
Requires-Dist: deepdiff==8.2.0
|
|
26
|
+
Requires-Dist: feedparser~=6.0.10
|
|
27
|
+
Requires-Dist: iso8601<2.2,>=1.1
|
|
28
|
+
Requires-Dist: paho-mqtt<2.2.0,>=1.6.1
|
|
29
|
+
Requires-Dist: pid~=3.0.4
|
|
30
|
+
Requires-Dist: python-dateutil<2.10.0,>=2.8.2
|
|
31
|
+
Requires-Dist: python-socketio<5.12,>=5.5
|
|
32
|
+
Requires-Dist: pytz<2025.2.0,>=2022.7.1
|
|
33
|
+
Requires-Dist: pyyaml~=6.0.1
|
|
34
|
+
Requires-Dist: requests<2.33.0,>=2.28.2
|
|
35
|
+
Requires-Dist: sockjs<0.14,>=0.11
|
|
36
|
+
Requires-Dist: uvloop==0.21.0; sys_platform != "win32"
|
|
37
|
+
Requires-Dist: tomli==2.2.1
|
|
38
|
+
Requires-Dist: tomli_w<1.3,>=1.0
|
|
39
|
+
Requires-Dist: pydantic~=2.10.6
|
|
40
|
+
Provides-Extra: dev
|
|
41
|
+
Requires-Dist: pip-tools<7.5.0,>=6.12.3; extra == "dev"
|
|
42
|
+
Requires-Dist: build<1.3,>=0.10; extra == "dev"
|
|
43
|
+
Requires-Dist: flake8~=7.1.1; extra == "dev"
|
|
44
|
+
Requires-Dist: black<25.2,>=23.1; extra == "dev"
|
|
45
|
+
Requires-Dist: pre-commit<3.9.0,>=3.1.1; python_version > "3.7" and extra == "dev"
|
|
46
|
+
Requires-Dist: pytest<8.4.0,>=7.2.1; extra == "dev"
|
|
47
|
+
Requires-Dist: ruff<0.7.0,>=0.0.261; extra == "dev"
|
|
48
|
+
Requires-Dist: codespell>=2.4.1; extra == "dev"
|
|
49
|
+
Provides-Extra: doc
|
|
50
|
+
Requires-Dist: sphinx-autobuild<2024.10.0,>=2021.3.14; extra == "doc"
|
|
51
|
+
Requires-Dist: sphinx-rtd-theme==3.0.2; extra == "doc"
|
|
52
|
+
Requires-Dist: pygments<2.20,>=2.14; extra == "doc"
|
|
53
|
+
Requires-Dist: myst-parser==4.0.0; extra == "doc"
|
|
54
|
+
Dynamic: license-file
|
|
55
|
+
|
|
56
|
+
# Description
|
|
57
|
+
|
|
58
|
+
AppDaemon is a loosely coupled, multi-threaded, sandboxed python
|
|
59
|
+
execution environment for writing automation apps for various types of Home Automation Software including [Home
|
|
60
|
+
Assistant](https://home-assistant.io/) and MQTT. It has a pluggable architecture allowing it to be integrated with
|
|
61
|
+
practically any event driven application.
|
|
62
|
+
|
|
63
|
+
It also provides a configurable dashboard (HADashboard)
|
|
64
|
+
suitable for wall mounted tablets.
|
|
65
|
+
|
|
66
|
+
## Getting started
|
|
67
|
+
|
|
68
|
+
For full instructions on installation and usage check out the [AppDaemon Project Documentation](http://appdaemon.readthedocs.io).
|
|
69
|
+
|
|
70
|
+
## Release Cycle Frequency
|
|
71
|
+
|
|
72
|
+
AppDaemon has reached a very stable point, works reliably and is fairly feature rich at this point
|
|
73
|
+
in its development. For that reason, releases have been slow in recent months. This does not mean that AppDaemon has been abandoned -
|
|
74
|
+
it is used every day by the core developers and has an active discord server [here](https://discord.gg/sgSr79jW5x) - please join us for tips
|
|
75
|
+
and tricks, AppDaemon discussions and general home automation.
|
|
76
|
+
|
|
77
|
+
## Contributing
|
|
78
|
+
|
|
79
|
+
This is an active open-source project. We are always open to people who want to use the code or contribute to it. Thank you for being involved!
|
|
80
|
+
Have a look at the [official documentation](https://appdaemon.readthedocs.io/en/latest/DEV.html) for more information.
|