36
36
CONF_WEBHOOK_ID ,
37
37
)
38
38
from homeassistant .core import HomeAssistant , callback
39
- from homeassistant .helpers import config_validation as cv , device_registry as dr
39
+ from homeassistant .helpers import (
40
+ config_validation as cv ,
41
+ device_registry as dr ,
42
+ trigger ,
43
+ )
40
44
from homeassistant .helpers .dispatcher import async_dispatcher_send
41
45
from homeassistant .helpers .entity_registry import async_entries_for_device , async_get
42
46
from homeassistant .helpers .typing import HomeAssistantType
58
62
NODERED_ENTITY ,
59
63
VERSION ,
60
64
)
65
+ from .utils import NodeRedJSONEncoder
61
66
62
67
CONF_ALLOWED_METHODS = "allowed_methods"
63
68
CONF_LOCAL_ONLY = "local_only"
@@ -70,6 +75,7 @@ def register_websocket_handlers(hass: HomeAssistantType):
70
75
71
76
async_register_command (hass , websocket_device_action )
72
77
async_register_command (hass , websocket_device_remove )
78
+ async_register_command (hass , websocket_device_trigger )
73
79
async_register_command (hass , websocket_discovery )
74
80
async_register_command (hass , websocket_entity )
75
81
async_register_command (hass , websocket_config_update )
@@ -81,7 +87,7 @@ def register_websocket_handlers(hass: HomeAssistantType):
81
87
@require_admin
82
88
@websocket_command (
83
89
{
84
- vol .Required (CONF_TYPE ): "nodered/device_action " ,
90
+ vol .Required (CONF_TYPE ): "nodered/device/action " ,
85
91
vol .Required ("action" ): cv .DEVICE_ACTION_SCHEMA ,
86
92
}
87
93
)
@@ -97,13 +103,15 @@ async def websocket_device_action(
97
103
98
104
try :
99
105
await platform .async_call_action_from_config (hass , msg ["action" ], {}, context )
100
- connection .send_message (result_message (msg [CONF_ID ], { "success" : True } ))
106
+ connection .send_message (result_message (msg [CONF_ID ]))
101
107
except InvalidDeviceAutomationConfig as err :
102
108
connection .send_message (error_message (msg [CONF_ID ], "invalid_config" , str (err )))
103
109
except DeviceNotFound as err :
104
110
connection .send_message (
105
111
error_message (msg [CONF_ID ], "device_not_found" , str (err ))
106
112
)
113
+ except Exception as err :
114
+ connection .send_message (error_message (msg [CONF_ID ], "unknown_error" , str (err )))
107
115
108
116
109
117
@require_admin
@@ -131,7 +139,7 @@ async def websocket_device_remove(
131
139
132
140
device_registry .async_remove_device (device .id )
133
141
134
- connection .send_message (result_message (msg [CONF_ID ], { "success" : True } ))
142
+ connection .send_message (result_message (msg [CONF_ID ]))
135
143
136
144
137
145
@require_admin
@@ -157,7 +165,7 @@ def websocket_discovery(
157
165
async_dispatcher_send (
158
166
hass , NODERED_DISCOVERY .format (msg [CONF_COMPONENT ]), msg , connection
159
167
)
160
- connection .send_message (result_message (msg [CONF_ID ], { "success" : True } ))
168
+ connection .send_message (result_message (msg [CONF_ID ]))
161
169
162
170
163
171
@require_admin
@@ -178,7 +186,7 @@ def websocket_entity(
178
186
async_dispatcher_send (
179
187
hass , NODERED_ENTITY .format (msg [CONF_SERVER_ID ], msg [CONF_NODE_ID ]), msg
180
188
)
181
- connection .send_message (result_message (msg [CONF_ID ], { "success" : True } ))
189
+ connection .send_message (result_message (msg [CONF_ID ]))
182
190
183
191
184
192
@require_admin
@@ -198,7 +206,7 @@ def websocket_config_update(
198
206
async_dispatcher_send (
199
207
hass , NODERED_CONFIG_UPDATE .format (msg [CONF_SERVER_ID ], msg [CONF_NODE_ID ]), msg
200
208
)
201
- connection .send_message (result_message (msg [CONF_ID ], { "success" : True } ))
209
+ connection .send_message (result_message (msg [CONF_ID ]))
202
210
203
211
204
212
@require_admin
@@ -260,7 +268,7 @@ def remove_webhook() -> None:
260
268
pass
261
269
262
270
_LOGGER .info (f"Webhook removed: { webhook_id [:15 ]} .." )
263
- connection .send_message (result_message (msg [CONF_ID ], { "success" : True } ))
271
+ connection .send_message (result_message (msg [CONF_ID ]))
264
272
265
273
try :
266
274
hass .components .webhook .async_register (
@@ -270,13 +278,16 @@ def remove_webhook() -> None:
270
278
handle_webhook ,
271
279
allowed_methods = allowed_methods ,
272
280
)
273
- except ValueError :
274
- connection .send_message (result_message (msg [CONF_ID ], {"success" : False }))
281
+ except ValueError as err :
282
+ connection .send_message (error_message (msg [CONF_ID ], "value_error" , str (err )))
283
+ return
284
+ except Exception as err :
285
+ connection .send_message (error_message (msg [CONF_ID ], "unknown_error" , str (err )))
275
286
return
276
287
277
288
_LOGGER .info (f"Webhook created: { webhook_id [:15 ]} .." )
278
289
connection .subscriptions [msg [CONF_ID ]] = remove_webhook
279
- connection .send_message (result_message (msg [CONF_ID ], { "success" : True } ))
290
+ connection .send_message (result_message (msg [CONF_ID ]))
280
291
281
292
282
293
@require_admin
@@ -322,10 +333,78 @@ def remove_trigger() -> None:
322
333
assert isinstance (default_agent , DefaultAgent )
323
334
324
335
_remove_trigger = default_agent .register_trigger (sentences , handle_trigger )
325
- except ValueError :
326
- connection .send_message (result_message (msg [CONF_ID ], {"success" : False }))
336
+ except ValueError as err :
337
+ connection .send_message (error_message (msg [CONF_ID ], "value_error" , str (err )))
338
+ return
339
+ except Exception as err :
340
+ connection .send_message (error_message (msg [CONF_ID ], "unknown_error" , str (err )))
327
341
return
328
342
329
343
_LOGGER .info (f"Sentence trigger created: { sentences } " )
330
344
connection .subscriptions [msg [CONF_ID ]] = remove_trigger
331
- connection .send_message (result_message (msg [CONF_ID ], {"success" : True }))
345
+ connection .send_message (result_message (msg [CONF_ID ]))
346
+
347
+
348
+ @require_admin
349
+ @websocket_command (
350
+ {
351
+ vol .Required (CONF_TYPE ): "nodered/device/trigger" ,
352
+ vol .Required (CONF_NODE_ID ): cv .string ,
353
+ vol .Required (CONF_DEVICE_TRIGGER , default = {}): dict ,
354
+ }
355
+ )
356
+ @async_response
357
+ async def websocket_device_trigger (
358
+ hass : HomeAssistant , connection : ActiveConnection , msg : dict [str , Any ]
359
+ ) -> None :
360
+ """Create device trigger."""
361
+ node_id = msg [CONF_NODE_ID ]
362
+ trigger_data = msg [CONF_DEVICE_TRIGGER ]
363
+
364
+ def forward_trigger (event , context = None ):
365
+ """Forward events to websocket."""
366
+ message = event_message (
367
+ msg [CONF_ID ],
368
+ {"type" : "device_trigger" , "data" : event ["trigger" ]},
369
+ )
370
+ connection .send_message (
371
+ json .dumps (message , cls = NodeRedJSONEncoder , allow_nan = False )
372
+ )
373
+
374
+ def unsubscribe () -> None :
375
+ """Remove device trigger."""
376
+ remove_trigger ()
377
+ _LOGGER .info (f"Device trigger removed: { node_id } " )
378
+
379
+ try :
380
+ trigger_config = await trigger .async_validate_trigger_config (
381
+ hass , [trigger_data ]
382
+ )
383
+ remove_trigger = await trigger .async_initialize_triggers (
384
+ hass ,
385
+ trigger_config ,
386
+ forward_trigger ,
387
+ DOMAIN ,
388
+ DOMAIN ,
389
+ _LOGGER .log ,
390
+ )
391
+
392
+ except vol .MultipleInvalid as err :
393
+ _LOGGER .error (
394
+ f"Error initializing device trigger '{ node_id } ': { str (err )} " ,
395
+ )
396
+ connection .send_message (
397
+ error_message (msg [CONF_ID ], "invalid_trigger" , str (err ))
398
+ )
399
+ return
400
+ except Exception as err :
401
+ _LOGGER .error (
402
+ f"Error initializing device trigger '{ node_id } ': { str (err )} " ,
403
+ )
404
+ connection .send_message (error_message (msg [CONF_ID ], "unknown_error" , str (err )))
405
+ return
406
+
407
+ _LOGGER .info (f"Device trigger created: { node_id } " )
408
+ _LOGGER .debug (f"Device trigger config for { node_id } : { trigger_data } " )
409
+ connection .subscriptions [msg [CONF_ID ]] = unsubscribe
410
+ connection .send_message (result_message (msg [CONF_ID ]))
0 commit comments