Internal Documentation
These notes are intended to assist anyone that wants to understand AppDaemon’s internals better. Most modules are used from within the AppDaemon object, which is a centralized depository of configuration information and references to the other objects and subsystems within AppDaemon.
appdaemon object
- class appdaemon.appdaemon.AppDaemon(logging, loop, **kwargs)
Top-level container for the subsystem objects. This gets passed to the subsystem objects and stored in them as the
self.AD
attribute.Subsystems:
Attribute
Object
services
sequences
state
events
callbacks
futures
Futures
app_management
threading
Threading
executor
plugins
utility
admin
admin_loop
app_management
- class appdaemon.app_management.AppActions(init: ~typing.Dict[str, int] = <factory>, term: ~typing.Dict[str, int] = <factory>, total: int = 0, active: int = 0)
Stores which apps to initialize and terminate, as well as the total number of apps and the number of active apps.
- init
Dictionary of apps to initialize, which ultimately happens in
AppManagement._load_apps()
as part ofAppManagement.check_app_updates()
- term
Dictionary of apps to terminate, which ultimately happens in
AppManagement._terminate_apps()
as part ofAppManagement.check_app_updates()
- class appdaemon.app_management.AppManagement(ad: AppDaemon, use_toml: bool)
Subsystem container for managing app lifecycles
- monitored_files
Dictionary of the Python files that are being watched for changes and their last modified times
- Type:
Dict[str | pathlib.Path, float]
- filter_files
Dictionary of the modified times of the filter files and their paths.
- objects
Dictionary of dictionaries with the instantiated apps, plugins, and sequences along with some metadata
- Type:
Dict[str, Dict]
- async check_app_updates(plugin: str = None, mode: UpdateMode = UpdateMode.NORMAL)
Checks the states of the Python files that define the apps, reloading when necessary.
Called as part of
utility_loop.Utility.loop()
- Parameters:
plugin (str, optional) – Plugin to restart, if necessary. Defaults to None.
mode (UpdateMode, optional) – Defaults to UpdateMode.NORMAL.
- Check Process:
Refresh modified times of monitored files.
Checks for deleted files
Marks the apps for reloading or removal as necessary
Restarts the plugin, if specified
Terminates apps as necessary
Loads or reloads modules/pacakges as necessary
Loads apps from the modules/packages
- create_app(app=None, **kwargs)
Used to create an app, which is written to a config file
- edit_app(app, **kwargs)
Used to edit an app, which is already in Yaml. It is expecting the app’s name
- get_app_deps_and_prios(applist: Iterable[str], mode: UpdateMode) Dict[str, float]
Gets the dependencies and priorities for the given apps
- Parameters:
applist (Iterable[str]) – Iterable of app names
mode (UpdateMode) – UpdateMode
- Returns:
_description_
- Return type:
_type_
- get_app_file(app)
Used to get the file an app is located
- get_app_from_file(file)
Finds the apps that depend on a given file
- get_file_from_module(module_name: str) Path | None
Gets the module __file__ based on the module name.
- Parameters:
mod (str) – Module name
- Returns:
Path of the __file__
- Return type:
Optional[Path]
- get_path_from_app(app_name: str) Path
Gets the module path based on the app_name
Used in self._terminate_apps
- init_sequence_object(name, object)
Initialize the sequence
- read_app(reload_cfg: ModuleLoad)
Reads an app into memory by importing or reloading the module it needs
- remove_app(app, **kwargs)
Used to remove an app
Seems to be unreferenced?
- class appdaemon.app_management.ModuleLoad(path: Path, reload: bool = False)
Dataclass containing settings for calls to
AppManagement.read_app()
- path
Filepath of the module or path to the __init__.py of a package.
- Type:
- class appdaemon.app_management.UpdateMode(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)
Used as an argument for
AppManagement.check_app_updates()
to set the mode of the check.- INIT
Triggers AppManagement._init_update_mode to run during check_app_updates
- NORMAL
Normal update mode, for when
AppManagement.check_app_updates()
is called byutility_loop.Utility.loop()
- TERMINATE
Terminate all apps
callbacks
dashboard
events
- class appdaemon.events.Events(ad: AppDaemon)
Subsystem container for handling all events
- AD
Reference to the AppDaemon container object
- async add_event_callback(name, namespace, cb, event, **kwargs)
Adds a callback for an event which is called internally by apps.
- async cancel_event_callback(name, handle)
Cancels an event callback.
- Parameters:
name (str) – Name of the app or module.
handle – Previously supplied callback handle for the callback.
- Returns:
None.
- async fire_event(namespace, event, **kwargs)
Fires an event.
If the namespace does not have a plugin associated with it, the event will be fired locally. If a plugin is associated, the firing of the event will be delegated to the plugin, under the understanding that when the event is fired, the plugin will notify appdaemon that it occurred, usually via the system the plugin is communicating with.
- async has_log_callback(name)
Returns
True
if the app has a log callback,False
otherwise.Used to prevent callback loops. In the calling logic, if this function returns
True
the resulting logging event will be suppressed.- Parameters:
name (str) – Name of the app.
- async info_event_callback(name, handle)
Gets the information of an event callback.
- Parameters:
name (str) – Name of the app or subsystem.
handle – Previously supplied handle for the callback.
- Returns:
A dictionary of callback entries or rise a
ValueError
if an invalid handle is provided.
- async process_event(namespace, data)
Processes an event that has been received either locally or from a plugin.
- Parameters:
namespace (str) – Namespace the event was fired in.
data – Data associated with the event.
- Returns:
None.
- async process_event_callbacks(namespace, data)
Processes a pure event callback.
Locate any callbacks that may be registered for this event, check for filters and if appropriate, dispatch the event for further checking and eventual action.
- Parameters:
namespace (str) – Namespace of the event.
data – Data associated with the event.
- Returns:
None.
logging
- class appdaemon.logging.AppNameFormatter(fmt=None, datefmt=None, style=None)
Logger formatter to add ‘appname’ as an interpolatable field.
- format(record)
Format the specified record as text.
The record’s attribute dictionary is used as the operand to a string formatting operation which yields the returned string. Before formatting the dictionary, a couple of preparatory steps are carried out. The message attribute of the record is computed using LogRecord.getMessage(). If the formatting string uses the time (as determined by a call to usesTime(), formatTime() is called to format the event time. If there is exception information, it is formatted using formatException() and appended to the message.
- class appdaemon.logging.DuplicateFilter(logger, threshold, delay, timeout)
- filter(record)
Determine if the specified record is to be logged.
Returns True if the record should be logged, or False otherwise. If deemed appropriate, the record may be modified in-place.
- class appdaemon.logging.LogSubscriptionHandler(ad: AppDaemon, type)
Handle apps that subscribe to logs.
This Handler requires that it’s formatter is an instance of AppNameFormatter.
- emit(record)
Emit a record.
If a formatter is specified, it is used to format the record. The record is then written to the stream with a trailing newline. If exception information is present, it is formatted using traceback.print_exception and appended to the stream. If the stream has an ‘encoding’ attribute, it is used to determine how to do the output to the stream.
AppDaemon main() module.
AppDaemon module that contains main() along with argument parsing, instantiation of the AppDaemon and HTTP Objects, also creates the loop and kicks everything off
- class appdaemon.__main__.ADMain
Class to encapsulate all main() functionality.
- handle_sig(signum, frame)
Function to handle signals.
SIGUSR1 will result in internal info being dumped to the DIAG log SIGHUP will force a reload of all apps SIGINT and SIGTEM both result in AD shutting down
- Parameters:
signum – Signal number being processed.
frame – frame - unused
- Returns:
None.
- init_signals()
Setup signal handling.
- main()
Initial AppDaemon entry point.
Parse command line arguments, load configuration, set up logging.
- run(appdaemon, hadashboard, admin, aui, api, http)
Start AppDaemon up after initial argument parsing.
- Parameters:
appdaemon – Config for AppDaemon Object.
hadashboard – Config for HADashboard Object.
admin – Config for admin Object.
aui – Config for aui Object.
api – Config for API Object
http – Config for HTTP Object
- Returns:
None.
- stop()
Called by the signal handler to shut AD down.
- Returns:
None.
- appdaemon.__main__.main()
Called when run from the command line.
main
- class appdaemon.plugin_management.PluginBase(ad: AppDaemon, name, args)
Base class for plugins to set up _logging
scheduler
services
sequences
state
- class appdaemon.state.State(ad: AppDaemon)
Subsystem container for tracking states
- AD
Reference to the AppDaemon container object
- async add_namespace(namespace, writeback, persist, name=None)
Used to Add Namespaces from Apps
- add_persistent_namespace(namespace, writeback)
Used to add a database file for a created namespace
- async remove_entity(namespace, entity)
Removes an entity.
If the namespace does not have a plugin associated with it, the entity will be removed locally only. If a plugin is associated, the entity will be removed via the plugin and locally.
- async remove_entity_simple(namespace: str, entity_id: str) None
Used to remove an internal AD entity
- async remove_namespace(namespace)
Used to Remove Namespaces from Apps
- remove_persistent_namespace(namespace)
Used to remove the file for a created namespace
stream
thread_async
threading
utility_loop
Module to handle utility functions within AppDaemon.
- class appdaemon.utility_loop.Utility(ad: AppDaemon)
Subsystem container for managing the utility loop
Checks for file changes, overdue threads, thread starvation, and schedules regular state refreshes.
- async loop()
The main utility loop.
Loops until stop() is called, checks for file changes, overdue threads, thread starvation, and schedules regular state refreshes.
- stop()
Called by the AppDaemon object to terminate the loop cleanly
- Returns:
None
utils
- class appdaemon.utils.AttrDict(*args, **kwargs)
Dictionary subclass whose entries can be accessed by attributes (as well as normally).
- static from_nested_dict(data)
Construct nested AttrDicts from nested dictionaries.
- class appdaemon.utils.EntityStateAttrs(dict)
- class appdaemon.utils.PersistentDict(filename, safe, *args, **kwargs)
Dict-like object that uses a Shelf to persist its contents.
- update([E, ]**F) None. Update D from mapping/iterable E and F.
If E present and has a .keys() method, does: for k in E: D[k] = E[k] If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v In either case, this is followed by: for k, v in F.items(): D[k] = v
- class appdaemon.utils.StateAttrs(dict)
- appdaemon.utils.get_object_size(obj, seen=None)
Recursively finds size of objects
- appdaemon.utils.recursive_reload(module: module, reloaded: set = None)
Recursive reload function that does a depth-first search through all sub-modules and reloads them in the correct order of dependence.
Adapted from https://gist.github.com/KristianHolsheimer/f139646259056c1dffbf79169f84c5de