@toggledbits I understand that you do not perform testing on Mac computers but thought I'd share the following with you in case something can be done.
I started seeing these errors with version 24302. I thought that upgrading to 24343 would have fixed the issue but unfortunately not. I either have to close the browser or clear the cache for the errors to stop popping-up but they slowly come back.
I see these errors on the following browsers:
Safari 16.6.1 on macOS Big Sur Safari 18.1.1 on MacOS Sonoma DuckDuckGo 1.118.0 on macOS Big Sur and Sonoma Firefox 133.0.3 on macOS Big Sur Chrome 131.0.6778 on macOS Big SurHere are the errors
Safari while creating/updating an expression
@http://192.168.0.13:8111/reactor/en-ca/lib/js/reaction-editor.js:543:91 makeExprMenu@http://192.168.0.13:8111/reactor/en-ca/lib/js/reaction-editor.js:537:28 @http://192.168.0.13:8111/reactor/en-ca/lib/js/reaction-editor.js:92:64 @http://192.168.0.13:8111/reactor/en-ca/lib/js/reaction-editor.js:89:68 each@http://192.168.0.13:8111/node_modules/jquery/dist/jquery.min.js:2:3133 @http://192.168.0.13:8111/reactor/en-ca/lib/js/reaction-editor.js:89:35 @http://192.168.0.13:8111/client/MessageBus.js:98:44 forEach@[native code] @http://192.168.0.13:8111/client/MessageBus.js:95:54 @http://192.168.0.13:8111/client/MessageBus.js:106:44 @http://192.168.0.13:8111/client/Observable.js:78:28 signalModified@http://192.168.0.13:8111/reactor/en-ca/lib/js/ee.js:146:21 signalModified@http://192.168.0.13:8111/reactor/en-ca/lib/js/expression-editor.js:40:29 reindexExpressions@http://192.168.0.13:8111/reactor/en-ca/lib/js/expression-editor.js:71:32 @http://192.168.0.13:8111/reactor/en-ca/lib/js/expression-editor.js:608:40 dispatch@http://192.168.0.13:8111/node_modules/jquery/dist/jquery.min.js:2:40040DuckDuckGo while clicking on status
http://192.168.0.13:8111/reactor/en-ca/lib/js/reactor-ui-status.js:789:44 asyncFunctionResume@[native code] saveGridLayout@[native code] dispatchEvent@[native code] _triggerEvent@http://192.168.0.13:8111/node_modules/gridstack/dist/gridstack.js:1401:30 _triggerAddEvent@http://192.168.0.13:8111/node_modules/gridstack/dist/gridstack.js:1383:31 makeWidget@http://192.168.0.13:8111/node_modules/gridstack/dist/gridstack.js:968:30 addWidget@http://192.168.0.13:8111/node_modules/gridstack/dist/gridstack.js:388:24 placeWidgetAdder@http://192.168.0.13:8111/reactor/en-ca/lib/js/reactor-ui-status.js:183:44Firefox while updating a rule
@http://192.168.0.13:8111/reactor/en-ca/lib/js/reaction-editor.js:543:91 makeExprMenu@http://192.168.0.13:8111/reactor/en-ca/lib/js/reaction-editor.js:537:28 @http://192.168.0.13:8111/reactor/en-ca/lib/js/reaction-editor.js:92:64 @http://192.168.0.13:8111/reactor/en-ca/lib/js/reaction-editor.js:89:68 each@http://192.168.0.13:8111/node_modules/jquery/dist/jquery.min.js:2:3133 @http://192.168.0.13:8111/reactor/en-ca/lib/js/reaction-editor.js:89:35 @http://192.168.0.13:8111/client/MessageBus.js:98:44 forEach@[native code] @http://192.168.0.13:8111/client/MessageBus.js:95:54 @http://192.168.0.13:8111/client/MessageBus.js:106:44 @http://192.168.0.13:8111/client/Observable.js:78:28 notifySaved@http://192.168.0.13:8111/reactor/en-ca/lib/js/ee.js:82:21 notifySaved@http://192.168.0.13:8111/reactor/en-ca/lib/js/expression-editor.js:47:26 @http://192.168.0.13:8111/reactor/en-ca/lib/js/reactor-ui-rules.js:1460:39 forEach@[native code] @http://192.168.0.13:8111/reactor/en-ca/lib/js/reactor-ui-rules.js:1459:58Chrome while creating/updating an expression
TypeError: Cannot read properties of undefined (reading 'getEditor') at RuleEditor.makeExprMenu (http://192.168.0.13:8111/reactor/en-ca/lib/js/rule-editor.js:1788:86) at Object.handler (http://192.168.0.13:8111/reactor/en-ca/lib/js/rule-editor.js:2174:54) at http://192.168.0.13:8111/client/MessageBus.js:98:44 at Array.forEach (<anonymous>) at MessageBus._sendToBus (http://192.168.0.13:8111/client/MessageBus.js:95:54) at MessageBus.send (http://192.168.0.13:8111/client/MessageBus.js:106:44) at ExpressionEditor.publish (http://192.168.0.13:8111/client/Observable.js:78:28) at ExpressionEditor.signalModified (http://192.168.0.13:8111/reactor/en-ca/lib/js/ee.js:146:14) at ExpressionEditor.signalModified (http://192.168.0.13:8111/reactor/en-ca/lib/js/expression-editor.js:40:15) at ExpressionEditor.reindexExpressions (http://192.168.0.13:8111/reactor/en-ca/lib/js/expression-editor.js:71:18) ``Thanks to @toggledbits for adding a custom CSS. I've started doing a darker Reactor style.
Here's the file: https://gist.github.com/dbochicchio/825098ac13b7f8cac22012eae37ff7ce
A couple of things are still too bright and I'll eventually catch-up. Just place it under your /config directory, naming the file as customstyles.css. Hard refresh your browser.
Hi
Having to rebuild my Linux Debian box as the SSD failed. And I have forgotten exactly what I did the first time to get it all setup.
I have Debian 12 up and running on the new SSD, I only have console no Desktop GUI.
I am trying to do the bare metal install for MSR. However I am not sure if I am meant to install nodejs whlist logged in as the root user or as the none root user with my name ?
I used putty and connected via SSH and logged in as root and I installed nodejs but I think this was wrong as when logged in as my user name and I do a node -v command it says node is not installed or doesn't show any version number anyway.
But when logged in as root and I do a node -v command it does show me its installed and displays the version number. maybe its a path issue for my username and he can't see node is installed?
So now I am thinking I should of installed node whilst logged in as my user name and not as the root user.
This is how I installed nodejs as whilst logged in as root
ac7bf6c3-23ad-46fc-8ada-44af6704e63e-image.png
Thanks in advance.
Build 21228 has been released. Docker images available from DockerHub as usual, and bare-metal packages here.
Home Assistant up to version 2021.8.6 supported; the online version of the manual will now state the current supported versions; Fix an error in OWMWeatherController that could cause it to stop updating; Unify the approach to entity filtering on all hub interface classes (controllers); this works for device entities only; it may be extended to other entities later; Improve error detail in messages for EzloController during auth phase; Add isRuleSet() and isRuleEnabled() functions to expressions extensions; Implement set action for lock and passage capabilities (makes them more easily scriptable in some cases); Fix a place in the UI where 24-hour time was not being displayed.As the title says, here's my OpenAI Controller for Reactor:
OpenAI Controller per Reactor. Contribute to dbochicchio/reactor-openai development by creating an account on GitHub.
It supports both OpenAI and Azure OpenAI endpoints. You'll need keys/endpoints, according to each service.
The controller supports multiple models, and each one could be mapped as an entity.
It's quite easy to use, and responses can be stored in variables, for easy access. Or sent to another action (Text To Speech, another endpoint, etc).
9013ae50-fd68-42a2-87c3-97479132e465-image.png
80a88eec-7c89-464a-8196-690b4b72d044-image.png
Have fun with LLM into your scenes!
In Home Assistant I have an integration that if I add entities to it, I will get the following error in MSR as certain entity values I'm using in expressions are null for a moment. This is more or less cosmetic issue and happens very rarely as I rarely modify that integration on the hass side.
Screenshot 2024-11-28 at 22.20.41.png
And the expression is
Screenshot 2024-11-28 at 22.38.19.png
Could I "wrap" hass-entity shown above somewhat differently to prevent this error from happening? Using build 24302.
Hello
I am trying to set up Multi System Reactor to automate routines across multiple smart home devices & platforms (e.g., Home Assistant, SmartThings, and Hubitat). While I have successfully linked the systems; I am facing issues with:
-Delays in triggering actions on secondary devices.
-Inconsistent execution of complex logic conditions.
-Synchronization of states between devices when one system updates.
Is there a recommended way to optimize performance & confirm seamless state sharing across systems?
I have checked https://smarthome.community/category/22/multi-system-reactor-msbi guide for reference but still need advice.
Any tips on debugging or log analysis to pinpoint where the issue arises would also be appreciated.
Thank you !
I've managed to use MSR UI on iOS devices to some degree*, so that although UI elements (e.g. rule sets) are not visible in portrait mode, you've seen them in landscape. Now with recents builds (24302) this does not work anymore, elements (rule sets, entities) are not anymore visible in landscape mode.
Does anyone have similar experiences? Using iOS 18 and Safari/Chrome browser.
( *Drag & drop of rule conditions have never worked on a mobile)
@toggledbits Since I have upgraded ZWaveJSController to 24293 from 24257 I am seeing entries related to registering action set_volume, but action is not defined by the capability 143 every time I restart Reactor.
The Siren seems to be doing what it is supposed to do. The volume levels are fine. Should I worry about it?
Reactor version 24302
ZWaveJSController version 24293
Z-Wave JS UI version 9.27.4
zwave-js version 14.3.4
I have the following ACL defined:
groups: admin: users: - admin applications: true api_acls: # This ACL allows users in the "admin" group to access the API - url: "/api" group: admin allow: true log: true # This ACL allows anyone/thing to access the /api/v1/alive API endpoint - url: "/api/v1/alive" allow: trueAnd I have authenticated to MSR as "admin" user. However, I'm getting "access denied" when trying to access http://*******:8111/api/v1/log
So what I'm missing, is my ACL incorrectly defined?
Using build 24302 on Docker.
Hi
I have just connected a bunch of EzloPi controllers to MSR to import some ESP based devices etc.
They all seemed to have worked and imported in to MSR apart from I have one missing device. It is a Digital Gas Sensor device.
This is how that device looks in the Ezlo API.
Devices Info:
_id: "10696001" deviceTypeId: "ezlopi" parentDeviceId: "10696000" category: "level_sensor" subcategory: "" gatewayId: "457a5069" batteryPowered: false name: "Gas Sensor Digital" type: "sensor" reachable: true persistent: true serviceNotification: false armed: false roomId: "" security: "no" ready: true status: "idle" parentRoom: true protectConfig: "default"Items Info:
_id: "20696001" deviceId: "10696001" hasGetter: true hasSetter: false name: "smoke_density" show: true valueType: "substance_amount" scale: "parts_per_million" value: 2.7472610473632812 valueFormatted: "2.75" status: "idle"There is also an Analog Gas sensor that one did import in to MSR OK.
68d63dab-b871-4f44-912b-cf6e0b9eb4c6-image.png
Devices Info:
_id: "10696000" deviceTypeId: "ezlopi" parentDeviceId: "10696000" category: "security_sensor" subcategory: "gas" gatewayId: "457a5069" batteryPowered: false name: "Gas Sensor Analog" type: "sensor" reachable: true persistent: true serviceNotification: false armed: false roomId: "" security: "no" ready: true status: "idle" parentRoom: true protectConfig: "default"Items Info:
_id: "20696000" deviceId: "10696000" hasGetter: true hasSetter: false name: "gas_alarm" show: true valueType: "token" enum: 0: "no_gas" 1: "combustible_gas_detected" 2: "toxic_gas_detected" 3: "unknown" valueFormatted: "no_gas" value: "no_gas" status: "idle"And this is how this MQ2 Gas Sensor looks like on their dashboard:
Digital
cb77dfa3-4af5-4d06-9635-89207a716a89-image.png
Analog
4fb4da1b-e946-4b89-876c-bcd9f5699b6c-image.png
They have an EzloPi website here you can create your own sensor projects using ESP boards, which is very interesting stuff!
And I just wrote on the Ezlo forum here, how to connect an EzloPi controller to MSR.
THANKS.
A couple of things for you @toggledbits, since you mentioned that this release has new features and some tweaks are expected.
Local expressions cannot be deleted. Pushing the X button has no effect for me.
When cloning an entity action, the result is strange (first is cloned one, second is the original action):
a92ea094-9e2c-4aaa-bf47-2d07a6ffdbd0-image.png
When changing the action on the cloned element, the params are added to the original one. See screenshot:
92ac3011-83c8-466b-bd23-47d483ad7a52-image.png
Dark theme has a couple of strange contrasts. One is visible in the previous screenshots (white text on yellow background). Another one is in groups (blue text on blue background):
9b3c4988-53ef-44e6-9672-30e744cacb75-image.png
Overall, I found blue, yellow, red and green (in buttons and forms) to be too bright.
On the bright side:
I love the new script action: thank you! The dark theme is a great start to avoid getting blinded at night I promise I'll try very soon the new features around actions. Thanks!@toggledbits
I just upgraded to version MSR 24293, bare metal running on Fedora. Upon restart, I am getting a error banner:
I followed the new directions about npm
npm i --no-save --no-package-lock --omit dev
Any idea what the issue is?
Seems like switching the UI to the newly added dark mode (thank you for this) does nothing. The UI stays in light mode and only a few buttons turn into dark mode (see screenshot)
Things I have tried:
Hard refresh
Different browser
Different computer
Restarting Reactor
Failed troubleshooting attempts:
No errors in Chrome console
No relevant errors in Reactor log (can still PM the full log file)
Reactor version: latest-24293-ea42a81d
Hardware: Odroid N2+
Linux version: Ubuntu 24.04.1 LTS
3df2806f-9146-485b-9ec1-d056e91cefe5-image.png Dark mode enabled
ff823023-c079-4684-b01f-d6ac6527d31a-image.png Light mode enabled
Good morning,
I have a service MQTT service that needs a restart occasionally. The add-on (Smartbed MQTT) is for the smart bed base for my bed. It has a "safety light" that I can control from HAAS & MSR as a light entity, and also moves the head of the bed to a preset at bedtime, and then lies it back flat in the morning The problem is, from time to time, the light becomes "unavailable" Restarting from the Add-ons tab in HAAS always fixes it, but I should be able to detect when it happens when "light.tempur_pedic_safety_lights" is not true or false, i.e., unavailable.
What I don't know how to do is how to restart that service. Does anybody have experience in restarting add-ons from MSR?
Running:
Reactor (Multi-hub) latest-24212-3ce15e25 ZWaveJSController [0.1.24232]HAAS:
RPi5-64 (8GB) Core 2024.7.3 Supervisor 2024.08.0 Operating System 13.0 Frontend 20240710.0[Reactor] Services with sync response
-
Hi @toggledbits
I'm working on a controller to generate llm response from a prompt in reactor. I have http response coming thru an http request action at the moment, capturing the response inside a local variable. So, it's practically sync.
I want to create a controller, so I don't have to rely on a proxy (and have a simpler architecture), and duplicate absurd http actions, but AFAIK in the current implementation, actions are async only. But if I have multiple requests going on, I cannot be sure what it's really inside an attribute. I also thought that something like a correlation id when sending the request could be used to identity multiple responses, but I wanted to double check with you before starting with something too complicated. I also noticed that some actions in home assistant (ie forecast) are sync and I'm wondering if you have any plan or hint to address this situation. Thanks.
Thanks.
-
@therealdb said in [Reactor] Services with sync response:
I want to create a controller, so I don't have to rely on a proxy (and have a simpler architecture), and duplicate absurd http actions, but AFAIK in the current implementation, actions are async only. But if I have multiple requests going on, I cannot be sure what it's really inside an attribute.
Sorry, I'm not really clear on what you're asking here. When you say "actions are async only", in what context are you referring to? Do you mean an action running in a Reaction, or do you mean the implementation of an action in a Controller instance?
-
sorry, I was on my phone. I was referring to the fact it's impossible to get the response from a service inside a reaction. so, let's says I need to do that in order to pass a prompt and generate a response:
HTTP action is able to capture the reply in a variable. I want to build a custom controller with an action that could do the same, so reply in line with an output that I could capture inside a local variable (because replicating this code multiple times is not really efficient nor smart). Is that clear now?
-
Got it. Let me back up a second and supply a bit of background.
When a Reaction is asked to perform an action on an entity, the Engine's executive calls
Entity.perform()
on the target entity with the requested action name and parameters. By default, the entity will then call its Controller'sperformOnEntity()
with itself, the action name, and the action's parameters. The Controller is expected to provide whatever implementation is necessasry to cause the target object represented by the entity to perform the desired action. TheperformOnEntity()
implementation is expected to return a Promise that resolves when the command has been issued successfully (or, when the command complete successfully, if that is something that can be determined). That Promise is passed back as the call stack unwinds until the Engine gets it. At that point, the Engine will suspend execution of the Reaction until the action Promise is fulfilled (successfully or not).TL;DR: The Engine waits for a Controller to signal that an action in a Reaction has been requested (or completed) before moving on to the next action.
I think this is useful for you. Your implementation of the action must return a Promise that must resolve before the Engine moves on. So your action can launch its HTTP request (e.g. using
Controller.fetchJSON()
or.fetchText()
), which itself is an asynchronous operation, and wait for that response, then do whatever processing it needs to on that response, store the result wherever it needs to go, and then and only then resolve the original Promise. The Engine will be waiting that entire time before moving on to the next action in the running Reaction.A couple more things to know:
- If you don't supply an override of
performOnEntity()
in your Controller implementation, the default (Controller base class) implementation will try to call a method calledaction_<capability>_<actionname>
. For example, your Controller could implement the actionx_mycontroller.update_weather
by providing a methodaction_myController_update_weather( entity, parameters )
(whereentity
is the target andparameters
is an object of key/value pairs). - If you decide to implement an override of
performOnEntity()
, make sure it callssuper.performOnEntity()
if it can't figure out what to do (i.e. it is asked to perform an action it doesn't understand).
Hopefully I've answered your question and maybe provided some additional information that will help.
- If you don't supply an override of
-
Ok, that's clear and I think I've already done that in a coupe of controllers.
What I'm saying here is that I need to do something similar to be sure that I could capture the response and be sure I'm not getting another one. I want to capture the output in a variable like HTTP actions, but using an entity action.AFAIK I cannot do that in a reliable way.
-
I want to capture the output in a variable like HTTP actions
If you're building a Controller, it would (IMO) make more sense to store the query result on an entity (even if it's the system entity for the Controller) in an attribute rather than a global variable.
AFAIK I cannot do that in a reliable way.
I'm not really sure where you are going with the "capture the response and be sure I'm not getting another one". If you are using any of the fetch methods, for example, the response would be handled on the Promise that was created:
this.fetchJSON( "http://example.com/myquery" ).then( jsondata => { // The data from the response is now in `jsondata`. It will contain // only the data for this query, no other. this.getSystemEntity().setAttribute( 'x_mycontroller.myquery_result', jsondata ); });
There are many existing Controllers that can submit multiple commands to a hub/service and handle a truly asynchronous response (e.g. via a callback or a later message on the channel). In these instances, a unique (for the session) ID is passed as part of the request, and the hub's API returns the ID as part of its response, so we know what the hub is responding to. Both HassController and ZWaveJSController do this, for example.
Here's what that looks like for both of these Controllers. This method is used to send a request to the hub. It assigns a serial ID as part of its work:
/** Returns a Promise that sends a request to ZWave JS and resolves when it gets * the matching reply. The reply can time out, and the Promise rejects. */ _send_tracked_message( req, timeout ) { const self = this; timeout = timeout || DEFAULT_TASK_TIMEOUT; let slot = { req_id: ++this.next_msg_id, expires: Date.now() + timeout, resolve: false, reject: false, req: req }; slot.promise = new util.TimedPromise( (resolve,reject) => { // Now that we're in the Promise, save the resolvers for later use when we get the response. slot.resolve = resolve; slot.reject = reject; req.messageId = slot.req_id; self.log.debug( 5, "%1 sending #%2: %3", this, slot.req_id, req ); self.ws_send( JSON.stringify( req ) ); }, timeout ).catch( err => { self.log.err("%1 request %2 (%4) failed: %3\n%5", self, slot.req_id, err, slot.type, slot.req); slot.reject( err ); delete self.pending[String(slot.req_id)]; }); this.pending[String(slot.req_id)] = slot; return slot.promise; }
The Controller has an instance variable (an object) called
pending
that keeps track of all pending requests; it's created empty ({}
) in the Controller's constructor and when a connection to the hub is acquired. Likewise, thenext_msg_id
variable is initialized to 0 in the constructor. The method creates a slot, which is just an object with enough data to track the request, using aTimedPromise
(inutil
library) so that we can have a timeout if the hub never answers. The slot is stored inthis.pending
so we can get back to it later, whenever/however the response arrives.The hub later sends a response somehow. In Z-Wave JS that's a
result
type message on the WebSocket channel, and the handler looks like this:/** Called for "result" type messages. If associated with a tracked request, that Promise will * resolve or reject based on the returned success flag. Otherwise, the message is logged (if * level is high enough) and the message discarded. */ _handle_result( event ) { this.log.debug( 9, "%1 full result reply %2", this, event ); // Find the slot in pending let slot = this.pending[String(event.messageId)]; if ( slot ) { delete this.pending[String(event.messageId)]; if ( event.success ) { this.log.debug( 5, "%1 request %2 (%3) success notification", this, slot.req_id, slot.req.command); slot.resolve( event ); } else { // Ref: https://github.com/zwave-js/zwave-js-server#errors this.log.debug( 5, "%1 command result error: %2", this, event ); let err; if ( "zwave_error" === event.errorCode ) { err = new Error( `Z-Wave error ${event.zwaveErrorCode}: ${event.zwaveErrorMessage}` ); } else { err = new Error( event.errorCode ); } slot.reject( err ); } } else { this.log.debug( 6, "%1 can't resolve request %2 in reply, slot not found, maybe already timed out", this, event.messageId ); } }
In this case, the slot data is acquired from
this.pending
. The slot is removed fromthis.pending
, and then the storedresolve()
function is called (with the result message data) if the hub indicates success, orreject()
is called (with the error data) otherwise.Does this help?
-
that's fair, but I think the problem is different. My flow is this one:
Prompt => OpenAI => response
It's not really different from what HTTP action is doing, after all.
Prompt is by definition dynamic, so I cannot "bind" it to an entity. I think having multiple entities just because I need multiple response is cumbersome (and, probably, not efficient). It will eventually lead to confusion and complicate the final setup, because every time I need to write a new prompt, a new entity will be needed as well.Now, if I create multiple entities, your remarks are obviously right. I did a couple of controllers and the infrastructure is pretty clear to me. But if I want to create just the system entity, with an action like
x_ai.prompt
, I cannot store the response inside an entity attribute, because I could potentially run multiplex_ai.prompt
requests and this could cause a lot of troubles. I understand that in a entity-first world this is an edge case, and in fact this is more a service-oriented Controller than the traditional ones, but nevertheless I thinks this use case will eventually surface more and more. It's like theperform_action
returning an object as result using the Promise, instead of just being void.In my comment, I was referring to a local variable. Imagine a prompt giving you a number as a result, because you're using the GenAI engine to make some prediction based on your logic. By capturing this value inside a variable, I could write, inside the same rule, the logic necessary to tie this value to some specific actions, like turning on some light, or send a notification if a threshold is met. I know I can assign it to the system entity, but this will need multiple rules to capture the result, so this will probably make things very complicated.
I'm asking for some guidance in order to implement this kind of architecture, where the response is directly tied (and captured, and used) in the same context of the rule where the request is generated. I'm not sure if this is clearer than my previous attempt to describe the question. Thanks!
-
What causes the request? Local variables live in rules, but rules are only evaluated (and local variables updated) when a dependency notifies a change. What will cause the query to the remote endpoint?
-
It could be a door being opened, a time trigger - or something else. The prompt will be generated from a source (this could be some text coming from an e-mail, a web site, or status coming from sensors - sky's the limit), sent to the OpenAI (or something else), processed, and a response generated. The output could be a JSON, a string, or whatever you want. The GenAI model is capable of generating everything, based on the prompt. This is a basic example:
The prompt is composed inline, and the response is being generated (and, in this case, sent to Alexa for TTS).
Here's another variation, for a JSON payload:
It's crucial to send the request and get the response in the same logic, otherwise it will be impossible to easily build something with this. Thanks.
-
OK. Still not fully there for me. When you run the HTTP Request action, it waits for the response, and then stores the response in the specified local variable. That value is now available to the remainder of the Reaction, so you can send it to TTS.
What am I missing?
-
I don't want to use an HTTP action, but a controller one! Right now it's impossible to save entity action response to a variable, if I'm not missing something. The question is this: how to build the same flow using a controller action?
-
But you can use the entity-based action response as if it was a variable. It is in many ways better, in fact, because there's a ton more code required in Reactor to make rule conditions responsive to variables than there is to make it responsive to attributes — attributes are very efficient.
I know you don't want to use an HTTP Request, but I want to know why. I guess I'm not understanding what's inadequate about the HTTP Request for your purpose in the first place.
-
My /ai/prompt endpoint encapsulate the logic to query OpenAI. That's great for me personally (so, not really shareable with the community), but that's another moving part in the system that could potentially fail. This is a simple web API that is proxying OpenAI (in this case Azure Open AI, but that's the same). It is acting as my controller, but it's not reusable, it's prone to errors and I think an
OpenAIController
will be better than this.All that said:
But you can use the entity-based action response as if it was a variable. It is in many ways better, in fact, because there's a ton more code required in Reactor to make rule conditions responsive to variables than there is to make it responsive to attributes — attributes are very efficient.
So, you think that it's better to have two rules, one triggering the request and another looking for the response and watching the attributes (ie: response and response_id, tied to a request_id from the original prompt)?
-
I'm not understanding why you think it takes two rules.
If you run an HTTP Request and store the response in a local variable, the next step in the same Reaction has access to that local variable. And the contents of that local variable will be exactly the response to the request, not any other request (so no ID tracking is necessary). The Rule that triggers the request can be the same rule that processes it.
Are you assuming that the HTTP Request action is asynchronous when storing the result? Because it's not. It will wait for the result and store it before moving on to the next step of the Reaction. That's documented.
-
-
@therealdb said in [Reactor] Services with sync response:
No, I'm quite experienced and I know how a promise works
I'm not talking about a Promise, and of course I know well that you know how that works. I'm talking about the HTTP Request action in a Reaction. It waits for the response and stores it, so that the rest of the steps of the Reaction can work with the response received. If that doesn't address your need, I'm unclear how.
-
ok, so, here's a photoshopped version of the ideal world I'm trying to describe:
The point here is that I don't want to do an HTTP request, I want to call an entity action and capture the result, if any, in a variable. Keep in mind that I'm describing an ideal world, and I'm OK to alternative solutions that still uses a Controller (and not an HTTP Action, that's temporary and I want to move to a custom Controller), wait for a response from a service, capture it and use in the same flow, if possible.
So, more like services than entity-oriented controller.
I hope this is better explained now. Thanks!
-
OK. I think I see where you are going. I was bogged down by the HTTP part, since that's existing functionality you can solve the problem with today. You're really asking for something much bigger. You just generally want entity actions to be able to return data, which they currently don't, so you can do things like:
- Return the next upcoming event from a calendar;
- Receive a value and look it up in a table, then return the found result;
- Given the name of a playlist on a media player, return the list of media it contains.
- Given the symbol for a security or crypto coin, return its current price.
- Run a script on Home Assistant and receive whatever response it returned.
And you want this to work in-line in Reactions, without necessarily binding the result value to an attribute on the entity performing the action, or having to preconfigure an input in YAML config (e.g. the symbol for a stock or crypto asset to be fetched/polled). The result value is, in fact, typically temporary and not useful outside the context of the Reaction (although it and values derived from it can be stored otherwise by other steps of the Reaction).
Do I have it now?
-
@toggledbits yes sir. That why you're the master and I'm your humble follower
Because I know it's not trivial, I'm also asking for guidance on how to achieve something similar with what we have today. Thanks.
-
I'm on it. Sit tight.
-