Jump to content

Welcome to Smart Home Forum by FIBARO

Dear Guest,

 

as you can notice parts of Smart Home Forum by FIBARO is not available for you. You have to register in order to view all content and post in our community. Don't worry! Registration is a simple free process that requires minimal information for you to sign up. Become a part of of Smart Home Forum by FIBARO by creating an account.

 

As a member you can:

  •     Start new topics and reply to others
  •     Follow topics and users to get email updates
  •     Get your own profile page and make new friends
  •     Send personal messages
  •     ... and learn a lot about our system!

 

Regards,

Smart Home Forum by FIBARO Team


Retrieve multiple values from the UI during the onAction() method?


Recommended Posts

I want to do some normal validation of the UI (normal for people other than Fibaro which doesn't seem to understand the finer things of the user interface concepts). My immediate desire is to take two values from the UI and pass them both to the API where they will be processed. The device is a thermostat and is using the com.fibaro.hvacSystemAuto device type. This presents the user a heating setpoint and a cooling setpoint when the thermostat is in Auto mode. But when the "Set" button is pressed, it sends the heat setpoint as an action, then it sends the cool setpoint. But the API expects both setpoints when the device is in Auto. Further, it burps if the heat setpoint is hotter than the cool setpoint. Even worse, the device control is in the cloud so the round trip is quite slow. It appears that the heat setpoint property I retrieve using fibaro.getValue(self.id, "heatingThermostatSetpoint") doesn't appear to be the value which was just sent (and passed to the cloud) during the heat setpoint onAction() method [remember, BOTH values are sent to the API on each call]. My original idea was to adjust the current setpoints so that the cooling setpoint was 2° higher than the heating setpoint when that setpoint is about to be set if they are not already in a valid state. Then, during the cooling setpoint adjustment, I would change the heating setpoint to be 2° cooler than the cooling setpoint if they are not already in a valid state.

 

Of course an even better solution would be to be able to peek at the other setpoint in the UI and send it. And ideally, I would like to be able to keep the state of the two setpoints in a valid state at all times. The app used by the thermostat adjusts the heating down if the cooling setpoint is adjusted down too much or it adjusts the cooling up if the heating setpoint is adjusted up too much. So it would be good practice to do something similar in the Fibaro UI. 🙄 But that's not likely to happen anytime in my lifetime or my children's lifetimes either.

 

The code I'm using is:

Please login or register to see this code.

 

My first pass used the self.properties.coolingThermostatSetpoint value. Then I tried the call to fibaro.getValue() but that didn't seem to help either.

 

The code to set the cooling setpoint is a duplicate of the above except the heating setpoint is adjust downward by 2 vs. the cooling setpoint being adjusted upward.

 

So what am I doing wrong?

 

Thanks in advance to any ideas or solutions.

 

Peter

 

PS: After working on this some more I FINALLY recognized this is a symptom of the async nature of web communication. Both setpoints are called back to back (duh). But the first call gets all the way to sending the API command out and then yields while that happens asynchronously. Then the other setpoint is changed and does the same thing. EXCEPT, the original heating setpoint has not been updated in the hub because that process is not executed until the success of the API call. I know how basic this is to people but I'm something of a dinosaur and cannot get it through my pea-sized, dinosaur brain that things have to happen asynchronously because of the latency of internet communications. Ok....now I'm back on board with all of this and I must find some elegant solution to resolve this.

 

Forgive me for showing my ignorance but I learned a valuable lesson (again, but maybe it will stick this time).

Edited by PeterV959
Figured out my problem
Link to comment
Share on other sites

  • Topic Author
  • But now I have to figure out how to handle the two API calls which are happening in parallel, I think. I need some method to defer one of the API calls until both values have been updated. I think the challenge will be to defer the second call until the first call has completed. I fear that there are times when only one setpoint is updated and there will be no second update, hence no second API call. My inclination is to let the first API call happen. Once it completes (successfully or unsuccessfully) then the second update can take place if there is one pending. But that begs the question, is there a defined means to defer one task in this single child device while waiting on the completion of another task when the two tasks are spawned by the hub (through an action event) and not under my control? Or am I being stupid once again and making this harder than it has to be?

     

    I see that two properties exist but I have no idea why. They could very easily fix my problem. There is a heatingThermostatSetpointFuture and a coolingThermostatSetpointFuture. Both have values of zero right now which implies they are currently unused. I am thinking I could set the heating one to my new setpoint, start the API call to adjust the heating setpoint (but also adjusts the cooling setpoint), and zero it out after the completion of the API call. Likewise for the cooling setpoint. Then, while getting the heating setpoint API call ready, when I look at the cooling setpoint I can examine the future value first. If it is zero, use the current value of the property. If it is non-zero, then I would use that property. And likewise for the cooling setpoint. Of course monkeying around with undocumented stuff risks future problems (but there seems to be so much undocumented in the Fibaro system. What's new with that?).

     

    I discovered all these problems while trying to get my climate zones to schedule right. I could not figure out why only one setpoint would change. Now I get why and it's a matter of figuring out how to make it work properly.

     

    Thanks for any input.

     

    Peter

    Edited by PeterV959
    Additional details
    Link to comment
    Share on other sites

    I have no experience of the thermostat device so I don't know about the futurePoints... but could it work to listen the system event  that the first point is updated before doing the next set point update?

    That event is the receipt on that your first action succeeded.

     

    Link to comment
    Share on other sites

  • Topic Author
  • On 1/21/2024 at 2:54 AM, jgab said:

    I have no experience of the thermostat device so I don't know about the futurePoints... but could it work to listen the system event  that the first point is updated before doing the next set point update?

    That event is the receipt on that your first action succeeded.

     

     

    I have been pondering this since I saw your post. I played with the RefreshStateSubscriber() class and it will work to capture the event. I've been at work so I don't have the luxury of doing much until Friday. I couldn't get my head around what you were suggesting at first. Then I understood the elegance of that solution. I haven't been able to do much except think on it but I am curious about a couple things.

     

    I can catch the events that have been triggered and deal with them just fine. But I am wondering, can I stop an event from reaching my handler within the handler() callback of the subscribe function of the? My idea would be to prevent a second event from executing while the first event is processing. Then, the first event can spawn the deferred event (assuming there is one waiting) as it cleans up. Which begs the question, can I post the deferred event through some Fibaro method? Or should I find someplace to hold the event table which was passed to the event handler and just invoke the handler myself?

     

    Thanks for the help. Your assistance always is right on target.

     

    Peter

    Link to comment
    Share on other sites

    Ok, this is pseudo code - Haven't tested it and I don't know exactly what events you need/look for.

    Please login or register to see this code.

     

    Link to comment
    Share on other sites

  • Topic Author
  • Yeah, that was kind of my idea too except I see from your event viewer in fibemu that the two events happen "simultaneously." The timestamps are the same and the ids are sequential. I haven't looked hard at it yet, but I wouldn't be surprised if only one setpoint needs to be changed the other event is suppressed (it's what I'd do). Consequently I can't rely on their both occurring. So my idea would be to set a boolean indicating the event has been spawned. Examine the other setpoint event flag and see if it is already processing. If it is, exit the event method without resetting the boolean. The first setpoint then would continue and clear the boolean at the end. If the "other" setpoint has attempted to run, I guess I could simply call that setpoint handler. Not positive on all of that as I was "thinking out loud" (on the screen). I was curious about saving the event parameters for use when the setpoint update method is "respawned." Got to work on the timing and make sure things can run to completion. I would use a semaphor if there were a reliable mechanism for that but that might be overkill. I want to think that so long as everything is executing without any external API calls or HTTP calls that I could set the boolean and test the other boolean without too much fear of collision. Of course assumptions are a bitch and the source of impossible to track down errors. Maybe a timer mechanism to clear a stuck boolean.

     

    Link to comment
    Share on other sites

    Join the conversation

    You can post now and register later. If you have an account, sign in now to post with your account.

    Guest
    Reply to this topic...

    ×   Pasted as rich text.   Paste as plain text instead

      Only 75 emoji are allowed.

    ×   Your link has been automatically embedded.   Display as a link instead

    ×   Your previous content has been restored.   Clear editor

    ×   You cannot paste images directly. Upload or insert images from URL.

    ×
    ×
    • Create New...