Skip to content

Commit 71b5286

Browse files
dlashuaraman325
authored andcommitted
handle logbook
1 parent fe0d419 commit 71b5286

File tree

4 files changed

+105
-9
lines changed

4 files changed

+105
-9
lines changed

custom_components/pyscript/function.py

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ class Function:
2626
unique_task2name = {}
2727
unique_name2task = {}
2828

29+
#
30+
# Mappings of task id to hass contexts
31+
task2context = {}
32+
2933
#
3034
# Set of tasks that are running
3135
#
@@ -117,12 +121,21 @@ async def async_sleep(cls, duration):
117121
@classmethod
118122
async def event_fire(cls, event_type, **kwargs):
119123
"""Implement event.fire()."""
124+
curr_task = asyncio.current_task()
120125
if "context" in kwargs and isinstance(kwargs["context"], Context):
121126
context = kwargs["context"]
122127
del kwargs["context"]
123-
cls.hass.bus.async_fire(event_type, kwargs, context=context)
128+
elif curr_task in cls.task2context:
129+
context = cls.task2context[curr_task]
124130
else:
125-
cls.hass.bus.async_fire(event_type, kwargs)
131+
context = Context()
132+
133+
cls.hass.bus.async_fire(event_type, kwargs, context=context)
134+
135+
@classmethod
136+
def store_hass_context(cls, hass_context):
137+
curr_task = asyncio.current_task()
138+
cls.task2context[curr_task] = hass_context
126139

127140
@classmethod
128141
def task_unique_factory(cls, ctx):
@@ -177,12 +190,16 @@ def service_has_service(cls, domain, name):
177190
@classmethod
178191
async def service_call(cls, domain, name, **kwargs):
179192
"""Implement service.call()."""
193+
curr_task = asyncio.current_task()
180194
if "context" in kwargs and isinstance(kwargs["context"], Context):
181195
context = kwargs["context"]
182196
del kwargs["context"]
183-
await cls.hass.services.async_call(domain, name, kwargs, context=context)
197+
elif curr_task in cls.task2context:
198+
context = cls.task2context[curr_task]
184199
else:
185-
await cls.hass.services.async_call(domain, name, kwargs)
200+
context = Context()
201+
202+
await cls.hass.services.async_call(domain, name, kwargs, context=context)
186203

187204
@classmethod
188205
async def service_completions(cls, root):
@@ -239,12 +256,16 @@ def get(cls, name):
239256
return None
240257

241258
async def service_call(*args, **kwargs):
259+
curr_task = asyncio.current_task()
242260
if "context" in kwargs and isinstance(kwargs["context"], Context):
243261
context = kwargs["context"]
244262
del kwargs["context"]
245-
await cls.hass.services.async_call(domain, service, kwargs, False, context)
263+
elif curr_task in cls.task2context:
264+
context = cls.task2context[curr_task]
246265
else:
247-
await cls.hass.services.async_call(domain, service, kwargs)
266+
context = Context()
267+
268+
await cls.hass.services.async_call(domain, service, kwargs, context=context)
248269

249270
return service_call
250271

@@ -266,6 +287,8 @@ async def run_coro(cls, coro):
266287
if task in cls.unique_task2name:
267288
del cls.unique_name2task[cls.unique_task2name[task]]
268289
del cls.unique_task2name[task]
290+
if task in cls.task2context:
291+
del cls.task2context[task]
269292
cls.our_tasks.discard(task)
270293

271294
@classmethod

custom_components/pyscript/logbook.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
"""Describe logbook events."""
2+
from homeassistant.core import callback
3+
4+
from .const import DOMAIN
5+
6+
import logging
7+
8+
_LOGGER = logging.getLogger(__name__)
9+
10+
11+
@callback
12+
def async_describe_events(hass, async_describe_event): # type: ignore
13+
"""Describe logbook events."""
14+
15+
@callback
16+
def async_describe_logbook_event(event): # type: ignore
17+
"""Describe a logbook event."""
18+
data = event.data
19+
func_args = data.get("func_args", {})
20+
ev_name = data.get("name", "unknown")
21+
ev_entity_id = data.get("entity_id", "pyscript.unknown")
22+
23+
ev_trigger_type = func_args.get("trigger_type", "unknown")
24+
if ev_trigger_type == "event":
25+
ev_source = f"event {func_args.get('event_type', 'unknown event')}"
26+
elif ev_trigger_type == "state":
27+
ev_source = f"state change {func_args.get('var_name', 'unknown entity')} == {func_args.get('value', 'unknown value')}"
28+
elif ev_trigger_type == "time":
29+
ev_trigger_time = func_args.get("trigger_time", "unknown")
30+
if ev_trigger_time is None:
31+
ev_trigger_time = "startup"
32+
ev_source = f"time {ev_trigger_time}"
33+
else:
34+
ev_source = ev_trigger_type
35+
36+
message = f"has been triggered by {ev_source}"
37+
38+
return {
39+
"name": ev_name,
40+
"message": message,
41+
"source": ev_source,
42+
"entity_id": ev_entity_id,
43+
}
44+
45+
async_describe_event(DOMAIN, "pyscript_running", async_describe_logbook_event)

custom_components/pyscript/state.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""Handles state variable access and change notification."""
22

3+
import asyncio
34
import logging
45

56
from homeassistant.core import Context
@@ -117,10 +118,14 @@ async def set(cls, var_name, value, new_attributes=None, **kwargs):
117118
else:
118119
new_attributes = {}
119120

120-
context = None
121+
curr_task = asyncio.current_task()
121122
if "context" in kwargs and isinstance(kwargs["context"], Context):
122123
context = kwargs["context"]
123124
del kwargs["context"]
125+
elif curr_task in Function.task2context:
126+
context = Function.task2context[curr_task]
127+
else:
128+
context = Context()
124129

125130
if kwargs:
126131
new_attributes = new_attributes.copy()

custom_components/pyscript/trigger.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from croniter import croniter
1212

1313
import homeassistant.helpers.sun as sun
14+
from homeassistant.core import Context
1415

1516
from .const import LOGGER_PATH
1617
from .eval import AstEval
@@ -826,14 +827,31 @@ async def trigger_watch(self):
826827
)
827828
continue
828829

830+
# Create new HASS Context with incoming as parent
831+
if "context" in func_args and isinstance(func_args["context"], Context):
832+
hass_context = Context(parent_id=func_args["context"].id)
833+
else:
834+
hass_context = Context()
835+
836+
# Fire an event indicating that pyscript is running
837+
# Note: the event must have an entity_id for logbook to work correctly.
838+
ev_name = self.name.replace(".", "_")
839+
ev_entity_id = f"pyscript.{ev_name}"
840+
841+
event_data = dict(name=ev_name, entity_id=ev_entity_id, func_args=func_args)
842+
Function.hass.bus.async_fire("pyscript_running", event_data, context=hass_context)
843+
829844
_LOGGER.debug(
830845
"trigger %s got %s trigger, running action (kwargs = %s)",
831846
self.name,
832847
notify_type,
833848
func_args,
834849
)
835850

836-
async def do_func_call(func, ast_ctx, task_unique, task_unique_func, **kwargs):
851+
async def do_func_call(func, ast_ctx, task_unique, task_unique_func, hass_context, **kwargs):
852+
# Store HASS Context for this Task
853+
Function.store_hass_context(hass_context)
854+
837855
if task_unique and task_unique_func:
838856
await task_unique_func(task_unique)
839857
await func.call(ast_ctx, **kwargs)
@@ -844,7 +862,12 @@ async def do_func_call(func, ast_ctx, task_unique, task_unique_func, **kwargs):
844862

845863
Function.create_task(
846864
do_func_call(
847-
self.action, action_ast_ctx, self.task_unique, task_unique_func, **func_args
865+
self.action,
866+
action_ast_ctx,
867+
self.task_unique,
868+
task_unique_func,
869+
hass_context,
870+
**func_args,
848871
)
849872
)
850873

0 commit comments

Comments
 (0)