diff --git a/Expert Mode.ipynb b/Expert Mode.ipynb deleted file mode 100644 index c67040d..0000000 --- a/Expert Mode.ipynb +++ /dev/null @@ -1,312 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "import sys\n", - "import json\n", - "from pathlib import Path\n", - "\n", - "import yaml\n", - "from rich import print" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "class EmptyClass:\n", - " pass\n", - "\n", - "self = EmptyClass()\n", - "self.AD = EmptyClass()\n", - "self.AD.app_dir = '/mnt/ad_dev_conf/apps'" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
Python parents:\n", - "\n" - ], - "text/plain": [ - "Python parents:\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "
- /mnt/ad_dev_conf/apps/my_repo/my_pkg\n", - " - /mnt/ad_dev_conf/apps\n", - " - /mnt/ad_dev_conf/apps/my_repo/my_pkg/my_sub_pkg\n", - "\n" - ], - "text/plain": [ - " - \u001b[35m/mnt/ad_dev_conf/apps/my_repo/\u001b[0m\u001b[95mmy_pkg\u001b[0m\n", - " - \u001b[35m/mnt/ad_dev_conf/\u001b[0m\u001b[95mapps\u001b[0m\n", - " - \u001b[35m/mnt/ad_dev_conf/apps/my_repo/my_pkg/\u001b[0m\u001b[95mmy_sub_pkg\u001b[0m\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "
Module parents:\n", - "\n" - ], - "text/plain": [ - "Module parents:\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "
- /mnt/ad_dev_conf/apps\n", - "\n" - ], - "text/plain": [ - " - \u001b[35m/mnt/ad_dev_conf/\u001b[0m\u001b[95mapps\u001b[0m\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "
Package parents:\n", - "\n" - ], - "text/plain": [ - "Package parents:\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "
- /mnt/ad_dev_conf/apps/my_repo/my_pkg\n", - " - /mnt/ad_dev_conf/apps/my_repo/my_pkg/my_sub_pkg\n", - "\n" - ], - "text/plain": [ - " - \u001b[35m/mnt/ad_dev_conf/apps/my_repo/\u001b[0m\u001b[95mmy_pkg\u001b[0m\n", - " - \u001b[35m/mnt/ad_dev_conf/apps/my_repo/my_pkg/\u001b[0m\u001b[95mmy_sub_pkg\u001b[0m\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "
Top package parents:\n", - "\n" - ], - "text/plain": [ - "Top package parents:\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "
- /mnt/ad_dev_conf/apps/my_repo/my_pkg\n", - "\n" - ], - "text/plain": [ - " - \u001b[35m/mnt/ad_dev_conf/apps/my_repo/\u001b[0m\u001b[95mmy_pkg\u001b[0m\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "
Imports\n", - "\n" - ], - "text/plain": [ - "Imports\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "
- /mnt/ad_dev_conf/apps\n", - " - /mnt/ad_dev_conf/apps/my_repo\n", - "\n" - ], - "text/plain": [ - " - \u001b[35m/mnt/ad_dev_conf/\u001b[0m\u001b[95mapps\u001b[0m\n", - " - \u001b[35m/mnt/ad_dev_conf/apps/\u001b[0m\u001b[95mmy_repo\u001b[0m\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "base_path = Path(self.AD.app_dir)\n", - "\n", - "python_file_parents = set(\n", - " f.parent.resolve()\n", - " for f in base_path.rglob('*.py')\n", - ")\n", - "print('Python parents:')\n", - "print('\\n'.join(f' - {p.as_posix()}' for p in python_file_parents))\n", - "\n", - "module_parents = set(\n", - " p for p in python_file_parents\n", - " if not (p / '__init__.py').exists()\n", - ")\n", - "print('Module parents:')\n", - "print('\\n'.join(f' - {p.as_posix()}' for p in module_parents))\n", - "\n", - "package_parents = set(\n", - " p for p in python_file_parents\n", - " if (p / '__init__.py').exists()\n", - ")\n", - "print('Package parents:')\n", - "print('\\n'.join(f' - {p.as_posix()}' for p in package_parents))\n", - "\n", - "top_packages_dirs = set(\n", - " p for p in package_parents\n", - " if not (p.parent / '__init__.py').exists()\n", - ")\n", - "print('Top package parents:')\n", - "print('\\n'.join(f' - {p.as_posix()}' for p in top_packages_dirs))\n", - "\n", - "import_dirs = module_parents | set(p.parent for p in top_packages_dirs)\n", - "print('Imports')\n", - "print('\\n'.join(f' - {p.as_posix()}' for p in import_dirs))" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
{\n", - " PosixPath('/mnt/ad_dev_conf/apps/my_repo/my_pkg/__init__.py'): 'my_pkg',\n", - " PosixPath('/mnt/ad_dev_conf/apps/my_repo/my_pkg/motion.py'): 'my_pkg',\n", - " PosixPath('/mnt/ad_dev_conf/apps/my_repo/my_pkg/my_sub_pkg/__init__.py'): 'my_pkg',\n", - " PosixPath('/mnt/ad_dev_conf/apps/my_repo/my_pkg/my_sub_pkg/hello.py'): 'my_pkg'\n", - "}\n", - "\n" - ], - "text/plain": [ - "\u001b[1m{\u001b[0m\n", - " \u001b[1;35mPosixPath\u001b[0m\u001b[1m(\u001b[0m\u001b[32m'/mnt/ad_dev_conf/apps/my_repo/my_pkg/__init__.py'\u001b[0m\u001b[1m)\u001b[0m: \u001b[32m'my_pkg'\u001b[0m,\n", - " \u001b[1;35mPosixPath\u001b[0m\u001b[1m(\u001b[0m\u001b[32m'/mnt/ad_dev_conf/apps/my_repo/my_pkg/motion.py'\u001b[0m\u001b[1m)\u001b[0m: \u001b[32m'my_pkg'\u001b[0m,\n", - " \u001b[1;35mPosixPath\u001b[0m\u001b[1m(\u001b[0m\u001b[32m'/mnt/ad_dev_conf/apps/my_repo/my_pkg/my_sub_pkg/__init__.py'\u001b[0m\u001b[1m)\u001b[0m: \u001b[32m'my_pkg'\u001b[0m,\n", - " \u001b[1;35mPosixPath\u001b[0m\u001b[1m(\u001b[0m\u001b[32m'/mnt/ad_dev_conf/apps/my_repo/my_pkg/my_sub_pkg/hello.py'\u001b[0m\u001b[1m)\u001b[0m: \u001b[32m'my_pkg'\u001b[0m\n", - "\u001b[1m}\u001b[0m\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "association = {}\n", - "for dir in top_packages_dirs:\n", - " associated_modules = list(dir.rglob('*.py'))\n", - " # print('\\n'.join(f' - {p.as_posix()}' for p in associated_modules))\n", - " for module_file in associated_modules:\n", - " association[module_file] = dir.stem\n", - "\n", - "print(association)" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "['hello_sub', 'motion']" - ] - }, - "execution_count": 15, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "module_name = 'my_pkg'\n", - "\n", - "with Path('apps/apps.yaml').open('r') as f:\n", - " self.app_config = yaml.load(f, Loader=yaml.SafeLoader)\n", - "\n", - "self.non_apps = []\n", - "\n", - "[\n", - " app_name\n", - " for app_name, app_cfg in self.app_config.items()\n", - " if app_cfg['module'].split('.')[0] == module_name\n", - "]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "ad_dev", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.7" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/Imports.ipynb b/Imports.ipynb deleted file mode 100644 index a7b5cca..0000000 --- a/Imports.ipynb +++ /dev/null @@ -1,42 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import importlib\n", - "from pathlib import Path" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "ad_dev", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.7" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/appdaemon.yaml b/appdaemon.yaml index 89246e4..2f67d53 100644 --- a/appdaemon.yaml +++ b/appdaemon.yaml @@ -1,4 +1,6 @@ appdaemon: + # ffake_ketys: asdfasdf + # starttime: '2024-07-14 12:00:00' # YYYY-MM-DD HH:MM:SS uvloop: True use_dictionary_unpacking: True # import_method: expert @@ -8,9 +10,15 @@ appdaemon: longitude: 0 elevation: 30 time_zone: America/Chicago - check_app_updates_profile: True + # check_app_updates_profile: True + module_debug: + _app_management: DEBUG + _callbacks: DEBUG + # _events: DEBUG + # _threading: DEBUG + # mqtt: DEBUG plugins: - HASS: + hass: type: hass ha_url: http://192.168.1.82:8123 token: !secret long_lived_token @@ -19,6 +27,7 @@ appdaemon: # namespace: mqtt # client_host: zigbee.localdomain # client_user: homeassistant + # client_id: test_dev_client # client_password: !secret mqtt_password # client_topics: # - zigbee2mqtt/# diff --git a/apps/app1/button.py b/apps/app1/button.py new file mode 100644 index 0000000..283721c --- /dev/null +++ b/apps/app1/button.py @@ -0,0 +1,29 @@ +import json + +from appdaemon.adapi import ADAPI + + +class Button(ADAPI): + def initialize(self): + name = self.args['button'] + self.handle = self.listen_event( + self.handle_button, + 'MQTT_MESSAGE', + topic=f'zigbee2mqtt/{name}', + payload=self.payload_filter, + ) + self.log(f"Started MQTT app in namespace '{self._namespace}'") + # raise ValueError + + @staticmethod + def payload_filter(payload: str): + try: + return json.loads(payload)['action'] != '' + except Exception: + return False + + def handle_button(self, event_name, data, **kwargs): + data['payload'] = json.loads(data['payload']) + # if data['payload']['action'] != '': + json_str = json.dumps(data, indent=4) + self.logger.info(f'{event_name} callback with\n{json_str}\n{kwargs}') diff --git a/apps/app1/database.py b/apps/app1/database.py index c58bb21..059a013 100644 --- a/apps/app1/database.py +++ b/apps/app1/database.py @@ -1,6 +1,12 @@ from appdaemon.adapi import ADAPI -class Database: +class Database(ADAPI): + def initialize(self): + self.comp = DatabaseComponent(self) + self.log('Database with component') + + +class DatabaseComponent: def __init__(self, ad: ADAPI) -> None: self.ad = ad diff --git a/apps/apps.yaml b/apps/apps.yaml new file mode 100644 index 0000000..4c84034 --- /dev/null +++ b/apps/apps.yaml @@ -0,0 +1,3 @@ +hello_world: + module: hello + class: HelloWorld diff --git a/apps/automationlib/automationlib.py b/apps/automationlib/automationlib.py new file mode 100644 index 0000000..882064b --- /dev/null +++ b/apps/automationlib/automationlib.py @@ -0,0 +1,13 @@ +import arrow +from appdaemon.adapi import ADAPI + + +class AutomationLib: + """This is the documentation for AutomationLib""" + + def __init__(self, ad: ADAPI) -> None: + self.ad = ad + self.ad.log(f"AutomationLib initialised for app '{self.ad.name}'", level='DEBUG') + + def dow(self): + return arrow.now().isoweekday() diff --git a/apps/automationlib/automationlib.yaml b/apps/automationlib/automationlib.yaml new file mode 100644 index 0000000..e6425b0 --- /dev/null +++ b/apps/automationlib/automationlib.yaml @@ -0,0 +1,10 @@ +automationlib: + module: automationlib + global: true + +my_test_app: + module: test + class: Test + log_level: DEBUG + dependencies: + - automationlib \ No newline at end of file diff --git a/apps/automationlib/requirements.txt b/apps/automationlib/requirements.txt new file mode 100644 index 0000000..330f94e --- /dev/null +++ b/apps/automationlib/requirements.txt @@ -0,0 +1 @@ +arrow \ No newline at end of file diff --git a/apps/automationlib/test.py b/apps/automationlib/test.py new file mode 100644 index 0000000..76bca93 --- /dev/null +++ b/apps/automationlib/test.py @@ -0,0 +1,14 @@ +from appdaemon.plugins.hass.hassapi import Hass +from automationlib import AutomationLib + + +class Test(Hass): + """This is the documentation for Test""" + + def initialize(self): + """.""" + + self.lib = AutomationLib(self) + self.log('-' * 72) + self.log(f'Day of the week: {self.lib.dow()}') + self.log('-' * 72) diff --git a/apps/button.yaml b/apps/button.yaml new file mode 100644 index 0000000..540cea8 --- /dev/null +++ b/apps/button.yaml @@ -0,0 +1,6 @@ +button_test: + module: app1.button + class: Button + button: Living Room Button + dependencies: + - hello_world diff --git a/apps/databases.yaml b/apps/databases.yaml index f1bc02c..211e174 100644 --- a/apps/databases.yaml +++ b/apps/databases.yaml @@ -1,5 +1,5 @@ App1: - module: aadfasdf + module: app1.database class: Database other_kwargs: value dependencies: Sound @@ -17,3 +17,9 @@ App2: - App1 - App1Foo - globals + +App3: + module: app2.database + class: OtherDatabaseApp + dependencies: + - App2 diff --git a/apps/family/__init__.py b/apps/family/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/family/child.py b/apps/family/child.py new file mode 100644 index 0000000..dad033f --- /dev/null +++ b/apps/family/child.py @@ -0,0 +1,10 @@ +from appdaemon.adapi import ADAPI + +from .utils import UTILS_VALS + + +raise ImportError('Fake import error') + +class Child(ADAPI): + def initialize(self): + self.log(f'Initialized child with: {UTILS_VALS}') diff --git a/apps/family/family.yaml b/apps/family/family.yaml new file mode 100644 index 0000000..c706e85 --- /dev/null +++ b/apps/family/family.yaml @@ -0,0 +1,7 @@ +parent: + module: family.parent + class: Parent + +child: + module: family.child + class: Child diff --git a/apps/family/parent.py b/apps/family/parent.py new file mode 100644 index 0000000..1e34c60 --- /dev/null +++ b/apps/family/parent.py @@ -0,0 +1,8 @@ +from appdaemon.adapi import ADAPI + +from .utils import UTILS_VALS + + +class Parent(ADAPI): + def initialize(self): + self.log(f'Initialized parent with: {UTILS_VALS}') diff --git a/apps/family/relatives/__init__.py b/apps/family/relatives/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/family/relatives/city.py b/apps/family/relatives/city.py new file mode 100644 index 0000000..d4fe228 --- /dev/null +++ b/apps/family/relatives/city.py @@ -0,0 +1 @@ +OTHER_CITY = 'NYC again' \ No newline at end of file diff --git a/apps/family/utils.py b/apps/family/utils.py new file mode 100644 index 0000000..2859941 --- /dev/null +++ b/apps/family/utils.py @@ -0,0 +1,3 @@ +from .relatives.city import OTHER_CITY + +UTILS_VALS = 100, 600 diff --git a/apps/globals/globals.py b/apps/globals/my_globals.py similarity index 100% rename from apps/globals/globals.py rename to apps/globals/my_globals.py diff --git a/apps/hello.py b/apps/hello.py index 1dcac73..1262f1c 100755 --- a/apps/hello.py +++ b/apps/hello.py @@ -5,4 +5,4 @@ from appdaemon.adapi import ADAPI class HelloWorld(ADAPI): def initialize(self): - self.log(f'Initialized app from {Path(__file__).relative_to(self.AD.app_dir.parent)}') + self.log(f'Initialized app from {Path(__file__).relative_to(Path(self.AD.app_dir).parent)}') diff --git a/apps/requirements.txt b/apps/requirements.txt index bf47204..b523ac1 100644 --- a/apps/requirements.txt +++ b/apps/requirements.txt @@ -1,3 +1,4 @@ rich anyio -pydantic \ No newline at end of file +pydantic +# arrow \ No newline at end of file diff --git a/apps/test/test.yaml b/apps/test/test.yaml index c7fd69b..06ab77d 100644 --- a/apps/test/test.yaml +++ b/apps/test/test.yaml @@ -4,4 +4,8 @@ test_notifier: module: variant class: Variant log_level: DEBUG - # dependencies: companion_app \ No newline at end of file + # dependencies: companion_app + +TestApp: + module: test_notify + class: TestNotifier diff --git a/apps/test/variant.py b/apps/test/variant.py index b19119f..bef2256 100644 --- a/apps/test/variant.py +++ b/apps/test/variant.py @@ -3,7 +3,6 @@ from appdaemon.adapi import ADAPI class Variant(TestNotifier, ADAPI): def initialize(self): - self.adapi = self.get_ad_api() - self.log = self.adapi.log + super().initialize() self.log('Variant of the TestNotifier') # self.log(' VARIANT '.center(50, '*')) diff --git a/docker-compose.yml b/docker-compose.yml index 32ed1e5..e5ee80a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,6 +2,7 @@ services: appdaemon: container_name: appdaemon_dev image: appdaemon:local-dev + # image: acockburn/appdaemon:dev volumes: - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro diff --git a/modules.ipynb b/modules.ipynb deleted file mode 100644 index 3c8128c..0000000 --- a/modules.ipynb +++ /dev/null @@ -1,144 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import importlib\n", - "\n", - "import pathlib\n", - "from types import ModuleType\n", - "from typing import List\n", - "from pathlib import Path\n", - "\n", - "from IPython.lib import deepreload" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "=============== Importing my_pkg ===============\n", - "-------------- Importing motion.py ---------------\n", - "===================== Done =====================\n" - ] - } - ], - "source": [ - "import sys\n", - "\n", - "sys.path.insert(0, Path('apps/my_repo').resolve().as_posix())\n", - "\n", - "import my_pkg" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "['importlib._abc',\n", - " 'importlib._bootstrap',\n", - " 'importlib._bootstrap_external',\n", - " 'importlib._imp',\n", - " 'importlib.abc',\n", - " 'importlib.machinery',\n", - " 'importlib.metadata',\n", - " 'importlib.resources',\n", - " 'importlib.sys',\n", - " 'importlib.util',\n", - " 'importlib.warnings']" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "def recursive_modules(module_obj: ModuleType) -> List[str]:\n", - " sub_modules = [\n", - " f'{module_obj.__name__}.{name}' for name in dir(module_obj)\n", - " if isinstance(getattr(module_obj, name), ModuleType)\n", - " ]\n", - " return sub_modules\n", - "\n", - "recursive_modules(importlib)" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[