Hi @toggledbits,
I have lots of logs with this:
<Engine:ERR> Assignment to alarm ignored -- expression-driven global cannot be set by assignmentAny hints to where look at to avoid this? Thanks.
Hi @toggledbits
I'd like to update my controllers with these new features, but I'm struggling to find any guidance in the docs - and in general to understand the context.
Could you please elaborate more? Thanks.
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.
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!
In Home Assistant I sometimes uses the TTS, either to my Sonos or Google speakers. With reactor in Vera I also use TTS.
But in MSR I can't select the TTS-service. It's simply not there. Am I missing something, or is this the case, so far?
Thanks!
/Fanan
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.
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.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.0Hi!
Is it possible to generate two additional log files, the first being the replica of what is displayed on screen by the Rule History widgets and the other with Recently Changed Entities?
And could I configure the generation of one file per day, and delete the older ones? For example, store the last 5 days?
And being more ambitious, does Windget have an icon to open these TXT files in the navigated?
Well, we're approaching Christmas, so here's my request to Santa Claus @toggledbits 🙂
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.
@togglebits I am curious as to why the tilt_sensor.state (primary) = NULL. I believe it should show true or false. I have to use binary_sensor.state instead in my rules.
Again, not sure if this is related to Reactor/ZwaveJSController implementation or the actual Z-Wave JS UI docker version. I have copied, below, the attributes of the tilt sensor in hopes it can help.
Thanks in advance.
Reactor version 23302
ZWaveJSController version 23254
Z-Wave JS UI version 9.3.0.724519f
zwave-js version 12.2.3
@toggledbits I have noticed after upgrading both Reactor and ZWaveJSController to version 24257 that two of my devices/entities, TILT-ZWAVE2.5-ECO and Zooz ZSE18, had their entity re-named in an unusual way and also appears to be duplicated.
Reactor version 24257
ZWaveJSController version 24257
Z-Wave JS UI version 9.18.1
zwave-js version 13.2.0
Vestibule Motion Sensor State attributes/partial screenshot of entities it created. All entities have the same attributes.
motion_sensor.state=true x_zwave_values.Notification_Home_Security_Motion_sensor_status=8 zwave_device.capabilities=[113] zwave_device.endpoint=0 zwave_device.failed=null zwave_device.manufacturer_info=null zwave_device.node_id=23 zwave_device.valueId=[113,"Notification","Home Security","Home Security","Motion sensor status","Motion sensor status"] zwave_device.version_info=nullTilt Sensor Door State and Tilt Sensor Door State Simple attributes/partial screenshot of entities it created. All entities have similar attributes with exception of x_zwave_values.Notification_Access_Control_Door_State = 22 or 23.
tilt_sensor.state=true x_zwave_values.Notification_Access_Control_Door_state=22 zwave_device.capabilities=[113] zwave_device.endpoint=0 zwave_device.failed=null zwave_device.manufacturer_info=null zwave_device.node_id=24 zwave_device.valueId=[113,"Notification","Access Control","Access Control","Door state","Door state"] zwave_device.version_info=null tilt_sensor.state=true x_zwave_values.Notification_Access_Control_Door_state_simple=22 zwave_device.capabilities=[113] zwave_device.endpoint=0 zwave_device.failed=null zwave_device.manufacturer_info=null zwave_device.node_id=24 zwave_device.valueId=[113,"Notification","Access Control","Access Control","Door state (simple)","Door state (simple)"] zwave_device.version_info=null tilt_sensor.state=false x_zwave_values.Notification_Access_Control_Door_state=23 zwave_device.capabilities=[113] zwave_device.endpoint=0 zwave_device.failed=null zwave_device.manufacturer_info=null zwave_device.node_id=24 zwave_device.valueId=[113,"Notification","Access Control","Access Control","Door state","Door state"] zwave_device.version_info=null tilt_sensor.state=false x_zwave_values.Notification_Access_Control_Door_state_simple=23 zwave_device.capabilities=[113] zwave_device.endpoint=0 zwave_device.failed=null zwave_device.manufacturer_info=null zwave_device.node_id=24 zwave_device.valueId=[113,"Notification","Access Control","Access Control","Door state (simple)","Door state (simple)"] zwave_device.version_info=nullI'm slowly migrating all my stuff to MQTT under MSR, so I have a central place to integrate everything (and, in a not-so-distant future, to remove virtual devices from my Vera and leave it running zwave only).
Anyway, here's my reactor-mqtt-contrib package:
Contrib MQTT templates for Reactor. Contribute to dbochicchio/reactor-mqtt-contrib development by creating an account on GitHub.
Simply download yaml files (everything or just the ones you need) and you're good to go.
I have mapped my most useful devices, but I'll add others soon. Feel free to ask for specific templates, since I've worked a lot in the last weeks to understand and operate them.
The templates are supporting both init and query, so you have always up-to-date devices at startup, and the ability to poll them. Online status is supported as well, so you can get disconnected devices with a simple expression.
Many-many thanks to @toggledbits for its dedication, support, and patience with me and my requests 🙂
Hi @toggledbits.
After a couple of weeks, I noticed that my Remotec zrc90 isn't working as expected.
Scenes are working in ZWaveJS, but this device has a strange behavior: the scene change, but then it's set again to null. In Reactor, this remains null:
battery_power.level=0.7 battery_power.since=1725817957361 x_debug.dt={"description":"Scene master 8 button remote","model":"BW8510/ZRC-90US","default_name":"Scene master 8 button remote","manufacturerId":21076,"productType":0,"productId":34064} x_zwave_values.Battery_isLow=false x_zwave_values.Battery_level=70 x_zwave_values.Central_Scene_scene_001=null x_zwave_values.Central_Scene_scene_002=null x_zwave_values.Central_Scene_scene_003=null x_zwave_values.Central_Scene_scene_004=null x_zwave_values.Central_Scene_scene_005=null x_zwave_values.Central_Scene_scene_006=null x_zwave_values.Central_Scene_scene_007=null x_zwave_values.Central_Scene_scene_008=null x_zwave_values.Central_Scene_slowRefresh=null x_zwave_values.Manufacturer_Specific_manufacturerId=21076 x_zwave_values.Manufacturer_Specific_productId=34064 x_zwave_values.Manufacturer_Specific_productType=1 x_zwave_values.Version_firmwareVersions=["1.1","1.1"] x_zwave_values.Version_hardwareVersion=3 x_zwave_values.Version_libraryType=2 x_zwave_values.Version_protocolVersion="4.5" x_zwave_values.Wake_Up_controllerNodeId=1 x_zwave_values.Wake_Up_wakeUpInterval=0 zwave_device.capabilities=[91,114,128,132,134] zwave_device.endpoint=0 zwave_device.failed=false zwave_device.generic_class="Remote Controller" zwave_device.impl_sig="24242:1:22315:1" zwave_device.is_beaming=false zwave_device.is_listening=false zwave_device.is_routing=false zwave_device.is_secure=false zwave_device.manufacturer_info=[21076,1,34064] zwave_device.max_data_rate=null zwave_device.node_id=154 zwave_device.specific_class="Simple Remote Control" zwave_device.status=2 zwave_device.status_text="awake" zwave_device.version_info=[null,"1.1"] zwave_device.wakeup_interval=0Anything I could look at? Thanks.
[Reactor] Services with sync response
-
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.
-