Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
"pin_app": pin_app,
"pin_thread": pin_thread,
"kwargs": kwargs
}
if callback is None:
function_name = "cancel_callback"
else:
function_name = callback.__name__
await self.AD.state.add_entity("admin",
"scheduler_callback.{}".format(handle),
"active",
{
"app": name,
"execution_time": utils.dt_to_str(ts.replace(microsecond=0), self.AD.tz),
"repeat": str(datetime.timedelta(seconds=interval)),
"function": function_name,
"pinned": pin_app,
"pinned_thread": pin_thread,
"fired": 0,
"executed": 0,
"kwargs": kwargs
})
# verbose_log(conf.logger, "INFO", conf.schedule[name][handle])
if self.active is True:
await self.kick()
return handle
raise ValueError("pin_threads cannot be < 0")
self.logger.info("Starting Apps with %s workers and %s pins", self.total_threads, self.pin_threads)
self.next_thread = self.pin_threads
self.thread_count = 0
for i in range(self.total_threads):
await self.add_thread(True)
# Add thread object to track async
await self.add_entity("admin", "thread.async", "idle",
{
"q": 0,
"is_alive": True,
"time_called": utils.dt_to_str(datetime.datetime(1970, 1, 1, 0, 0, 0, 0)),
"pinned_apps": []
}
async def add_entity(self, namespace, entity, state, attributes=None):
if attributes is None:
attrs = {}
else:
attrs = attributes
state = {"state": state, "last_changed": utils.dt_to_str(datetime.datetime(1970, 1, 1, 0, 0, 0, 0)), "attributes": attrs}
self.state[namespace][entity] = state
data = \
{
"event_type": "__AD_ENTITY_ADDED",
"data":
{
"entity_id": entity,
"state": state,
}
}
await self.AD.events.process_event(namespace, data)
async def set_state(self, name, namespace, entity_id, **kwargs):
self.logger.debug("set_state(): %s, %s", entity_id, kwargs)
if entity_id in self.state[namespace]:
old_state = deepcopy(self.state[namespace][entity_id])
else:
old_state = {"state": None, "attributes": {}}
new_state = self.parse_state(entity_id, namespace, **kwargs)
new_state["last_changed"] = utils.dt_to_str((await self.AD.sched.get_now()).replace(microsecond=0), self.AD.tz)
self.logger.debug("Old state: %s", old_state)
self.logger.debug("New state: %s", new_state)
if not await self.AD.state.entity_exists(namespace, entity_id):
if not ("_silent" in kwargs and kwargs["_silent"] is True):
self.logger.info("%s: Entity %s created in namespace: %s", name, entity_id, namespace)
# Fire the plugin's state update if it has one
plugin = await self.AD.plugins.get_plugin_object(namespace)
if hasattr(plugin, "set_plugin_state"):
# We assume that the state change will come back to us via the plugin
self.logger.debug("sending event to plugin")
result = await plugin.set_plugin_state(namespace, entity_id, **kwargs)
if result is not None:
if "entity_id" in result:
if self.AD.apps is True:
self.logger.debug("Reading Apps")
await self.AD.app_management.check_app_updates(mode="init")
self.logger.info("App initialization complete")
#
# Fire APPD Started Event
#
await self.AD.events.process_event("global", {"event_type": "appd_started", "data": {}})
self.booted = await self.AD.sched.get_now()
await self.AD.state.add_entity("admin", "sensor.appdaemon_version", utils.__version__)
await self.AD.state.add_entity("admin", "sensor.appdaemon_uptime", str(datetime.timedelta(0)))
await self.AD.state.add_entity("admin", "sensor.appdaemon_booted", utils.dt_to_str((await self.AD.sched.get_now()).replace(microsecond=0), self.AD.tz))
warning_step = 0
warning_iterations = 0
s1 = 0
e1 = 0
# Start the loop proper
while not self.stopping:
start_time = datetime.datetime.now().timestamp()
try:
if self.AD.apps is True:
if self.AD.production_mode is False:
async def init_admin_stats(self):
# Initialize admin stats
await self.add_entity("admin", "sensor.callbacks_total_fired", 0)
await self.add_entity("admin", "sensor.callbacks_average_fired", 0)
await self.add_entity("admin", "sensor.callbacks_total_executed", 0)
await self.add_entity("admin", "sensor.callbacks_average_executed", 0)
await self.add_entity("admin", "sensor.threads_current_busy", 0)
await self.add_entity("admin", "sensor.threads_max_busy", 0)
await self.add_entity("admin", "sensor.threads_max_busy_time", utils.dt_to_str(datetime.datetime(1970, 1, 1, 0, 0, 0, 0)))
await self.add_entity("admin", "sensor.threads_last_action_time", utils.dt_to_str(datetime.datetime(1970, 1, 1, 0, 0, 0, 0)))
"kwargs": args["kwargs"]
})
# If it is a repeating entry, rewrite with new timestamp
if args["repeat"]:
if args["type"] == "next_rising" or args["type"] == "next_setting":
c_offset = self.get_offset(args)
args["timestamp"] = self.sun(args["type"], c_offset)
args["offset"] = c_offset
else:
# Not sunrise or sunset so just increment
# the timestamp with the repeat interval
args["basetime"] += timedelta(seconds=args["interval"])
args["timestamp"] = args["basetime"] + timedelta(seconds=self.get_offset(args))
# Update entity
await self.AD.state.set_state("_scheduler", "admin", "scheduler_callback.{}".format(uuid_), execution_time=utils.dt_to_str(args["timestamp"].replace(microsecond=0), self.AD.tz))
else:
# Otherwise just delete
await self.AD.state.remove_entity("admin", "scheduler_callback.{}".format(uuid_))
del self.schedule[name][uuid_]
except:
error_logger = logging.getLogger("Error.{}".format(name))
error_logger.warning('-' * 60)
error_logger.warning("Unexpected error during exec_schedule() for App: %s", name)
error_logger.warning("Args: %s", args)
error_logger.warning('-' * 60)
error_logger.warning(traceback.format_exc())
error_logger.warning('-' * 60)
if self.AD.logging.separate_error_log() is True:
self.logger.warning("Logged an error to %s", self.AD.logging.get_filename("error_log"))
# Update thread info
if thread_id == "async":
await self.set_state("_threading", "admin", "thread.{}".format(thread_id),
q=0,
state=callback,
time_called=utils.dt_to_str(now.replace(microsecond=0), self.AD.tz),
is_alive=True,
pinned_apps=[]
)
else:
await self.set_state("_threading", "admin", "thread.{}".format(thread_id),
q=self.threads[thread_id]["queue"].qsize(),
state=callback,
time_called=utils.dt_to_str(now.replace(microsecond=0), self.AD.tz),
is_alive=self.threads[thread_id]["thread"].is_alive(),
pinned_apps=await self.get_pinned_apps(thread_id)
)
await self.set_state("_threading", "admin", "app.{}".format(app), state=callback)
#if starttime is declared and entity_id is not declared, and days specified
elif filter_entity_id == "" and start_time != "" and end_time == "" and "days" in data:
end_time = start_time + datetime.timedelta(days=days)
#if endtime is declared and entity_id is not declared, and days specified
elif filter_entity_id == "" and end_time != "" and start_time == "" and "days" in data:
start_time = end_time - datetime.timedelta(days=days)
if start_time != "":
timestamp = "/{}".format(utils.dt_to_str(start_time.replace(microsecond=0), self.AD.tz))
if filter_entity_id != "": #if entity_id is specified, end_time cannot be used
end_time = ""
if end_time != "":
end_time = "?end_time={}".format(quote(utils.dt_to_str(end_time.replace(microsecond=0), self.AD.tz)))
# if no start_time is specified, other parameters are invalid
else:
timestamp = ""
end_time = ""
api_url = "{}/api/history/period{}{}{}".format(config["ha_url"], timestamp, filter_entity_id, end_time)
elif domain == "template":
api_url = "{}/api/template".format(config["ha_url"])
else:
api_url = "{}/api/services/{}/{}".format(config["ha_url"], domain, service)
try:
if domain == "database":