NEW] Control Flair Vents with Hubitat - Free Open Source App and Driver

Hey all,

I wanted to share a new free integration I've been working on to control Flair smart vents through Hubitat. I created a 100% free beta app and driver that allows discovering and controlling Flair vents.

You can find the code here:

It's still in early stages but so far allows:

  • Finds the right percentage each vent should be opened translating to less motor movements via an Dynamic Air Flow Balancing algorithm
  • Leverages remote occupancy sensors to deactivate vents on unoccupied rooms
  • Allows monitoring and changing open percentage and active or inactive for each vent
  • Controlling vents from Hubitat rules

This lets you create rules like closing vents at night, opening them when home, and integrating with other devices.

Unlike some other solutions, this is completely free and open source. I'm not charging any fees or commissions.

If you find this useful, please star the GitHub repo! Starring helps raise awareness and is greatly appreciated.

I'm looking for testers and feedback from the community - since it's beta code there could still be issues. Please try it out if you are interested and open GitHub issues for any problems.

I welcome feature requests too! I created this mainly for presence-based automation. But it has potential for more integrations like temp sensors, HVAC control, etc. Let me know what else you'd like it to do!

Thanks and look forward to hearing any feedback!


Thanks for this.

A few issues: When I received my API authorization from flair, I received two sets of credentials. Oauth 2.0 and Oauth 1.0. I first tried the 2.0 and that did not work. Error: "Login failed -- status code: 401, reason phrase: UNAUTHORIZED: [error:invalid_client]"

Is that expected?

When I tried the 1.0 (Legacy) authorization, I only get one of four vent device discovered.

Lastly, I know this is very early in development, but could you look into adding the ability to control flair "rooms" active/away settings instead of controlling vent open/close directly?

IMO that is one of the most useful ways to control Flair vents through automation. It still keeps Flair's logic for opening/closing vents based on set points and their backpressure prevention logic but allows you to prioritize which vents should be opened/closed based on logic you could build through rules.

I think I would be interested in manual control of vents if anyone ever figured out a way to bypass Flair's cloud and control the devices locally. In that scenario, building out a complex set of rules to control the vents directly would be worthwhile. Otherwise, if it's a cloud integration, I would rather leverage Flair's built-in logic for open/close and would prefer to adjust it with the active/away settings.

I just added your app/device code and used an existing API authorization (from the other product). As with @grooves12 only one device was discovered (a puck), and none of my actual vents.

I look forward to your ongoing development!

Hi @grooves12 thanks for trying it out and sharing the details. Yes, my initial implementation uses OAuth 1.0 as I was having trouble with 2.0, but after cutting a ticket to the Flair team, they helped me identifying the problem, it was basically my fault as I was passing the parameters in the URL instead of in the headers. I'll work on an update (hopefully today) and post it on the GitHub repo, so that it uses OAuth 2.0.

For the second part of you comment, it's actually a good ides, I'd have to check if that is supported by the API, but if so I will add the capability to the driver's code.

I totally agree on that it's be ideal to be able to bypass the Flair cloud, there's actually a feature request for Flair to work on this, let's make sure to vote on this request to increase the chances.

Hi @davidscottjackson , thanks for trying it out, when you get a chance, please Enable Debug Logging from the hubitat-flair-vents-app, and share what you see in your app logs. That'll help me identify the root of why only one device was discovered for you and include the proper handling to that situation.

All right, I just updated the code with the suggestions above (OAuth 2.0 and New Command to set room active/inactive), also added some additional validations to prevent potential problems. This is a breaking change as I upgraded the credentials to OAuth 2.0, so please ensure you update them from the app after updating.

Good news-switching to OA 2 (or something else random!) allowed a all three vents and a puck to be discovered. Thanks—and I’ll keep testing!

1 Like

I switched up to the new code and was able to get my vents onboard. It did take a couple of times hitting the discover button before they all of my vents came in. But since they did, it seems to be working well. Should I also have a puck device? My puck doesn't show as a device.

I appreciate the addition of the room active/inactive control.

I'll play with this in some automations over the next week or so and report back.

Have you thought about adding this to Hubitat Package Manager?

I'm just getting back with some feedback on how it's working for me. I programmed a couple of rules, which seem to work well.

For an example of what I am doing:

  • I have an ecobee thermostat.
  • I am using window sensors in each room to trigger a routine.
  • If a window in a given room is opened, it removes the temp sensors in that room from ecobee's comfort profiles (so it doesn't get used to calculate the home's temperature) and sets the room as "away" in the flair app (defaults to closing the vent unless needed to open for backpressure protection.)
  • When the windows close, the opposite happens.

This worked great over the weekend when I had someone staying in the guest room who likes to sleep with the window open. Their vent stayed closed, room stayed colder than the rest of the house, meanwhile the rest of the house held temperature without overheating to try to deal with the room with the open window.

This code was just what I needed. Thanks!!!

Pucks should not show up as the code only lists vents. Adding it to Package manager is in my to do list, thanks for the suggestion!

I'm glad it worked out great for you, this is the best pay for me to know it makes someone's life better :slight_smile:

1 Like

I'm excited to announce a new update with Dynamic Airflow Balancing - the biggest feature addition yet.

Dynamic Airflow Balancing minimizes vent adjustments while maintaining even temperatures across rooms. It learns the temperature change rate for each room based on vent positions.

It then sets vents only as open as needed to reach the thermostat setpoint together. This reduces noise and wear from constant vent changes.

The default Flair logic simply opens vents fully or closes them completely. This causes loud servo noises from constant adjustments, even when HVAC is off.

My algorithm replicates industrial balancing systems. On first use, it fully opens vents to learn room rates.

After a few minutes of HVAC runtime (minimum 5), it calculates the ideal vent position for each room. Next cycle, vents adjust proportionally.

Rooms now hold steadier temperatures, better than Flair's own app in my testing. Servo noise is greatly reduced since position changes are minimized.

To enable, toggle on "Dynamic Airflow Balancing" in the Flair Vents App in Hubitat. This switches control from Flair to the custom algorithm.

I'm releasing this as a beta after positive tests over several days. Eager to hear feedback on this exciting upgrade! Let me know how it works in your home.

1 Like

Most vent configurations I've seen are squar/rectangular vents fed by a smaller round duct. Example: I have 6x10 vents fed by 6" round ducts. This results in vent adjustments having little to no effect on airflow over a large portion of the adjustment range. All they do is increase velocity resulting in more noise, but no change in heating/cooling. (the reduced noise is why vent sizes don't usually match duct sizes.)

This is also why Flair was initially reluctant to offer vent adjustments other than 0% and 100%.

I'm curious what your experience has been in the dynamic adjustment. Is it adjusting in single digit increments? Do you see many of the adjustments are between 0 and 25%. How has it affected wind speed noise?

1 Like

Thanks for the feedback! You raise a good point about vent and duct sizing.

In my case, I have a mix of vent sizes - 10x10, 6x14, 8x8, and 12x12. The ducts match the vents. So I am seeing direct flow rate changes from vent adjustments.

The algorithm calculates openings to the decimal point. As an example my current % openings are: 5%, 12%, 34%, 94%, 40%, 44%, 100%.

The minimum is 5% open to prevent loud hissing noises and HVAC damage from fully closed vents.

The key benefit is temperature stability within 1°F rather than swinging 2-4° before.

You asked about adjustment increments and noise. Yes, most changes are within 0-10% range - translating to very slight motor movements and minimal noise.

So vent adjustments from 34% to 40% for example have no noticeable sound increase though they help maintain even room temps.

The main noise reduction is from avoiding the full 0-100% oscillations that occurred before. Now positions stay more steady.

Appreciate you sharing your experience! Let me know if you have any other thoughts.

Does your algorithm capture how often adjustments are being made. I am curious if it is making more frequent adjustments. Part of flair's explanation for why they are using the 1 degree hysteresis is to reduce the frequency of adjustments to save battery life?

Another thing flair does to increase battery life is only make adjustment to the vents when the HVAC is running. If it is not actively running, it will ignore temperature changes that would trigger a vent opening/closing. Does you programming do the same?

The default Flair algorithm does make continuous vent adjustments, this constant oscillating is what drains battery life faster in my experience.

My algorithm takes a different approach. It collects temperature change rate data for each room during HVAC runtime.

It then calculates optimal vent positions to reach setpoint together. Adjustments only occur at next HVAC startup.

So rather than vent changes happening constantly to follow temperature fluctuations, mine tunes positions periodically.

This means after initial setup, vent openings remain steady for longer periods. Greatly reducing adjustment frequency and battery drain.

The key is learning the right room rates to determine ideal vent settings. Since changes are minimized once calibrated.

1 Like

How long does your algorithm take to start working. I enabled it and it doesn't seem to be making any adjustments. All vents are either 100% open or 0% closed.

The dynamic airflow balancing feature takes one full HVAC cycle to start adjusting vents. Once your system turns on heating or cooling, the app measures temperature changes in each room to calculate individual room rates. It uses this data to optimize vent positions on the next cycle.

To enable it:

  • Make sure the Flair app is set to Manual mode (although my app changes this automatically, but just in case)
  • Let your HVAC system complete one full on/off cycle after activating the feature

The vents will then begin dynamic balancing.

A few things to check:

  • Update to the latest for improved error handling and logging
  • Check the App Logs for any errors
  • In App Details > Application State, look at the "roomState" variable to see if room data is being captured

Let me know if the roomState data is missing or if any errors show in logs. Having the latest app code will provide better troubleshooting.

pp:2462024-02-17 06:20:43.325 PMdebugpatchDataAsync:, body:[data:[type:structures, attributes:[mode:auto]]]
app:2462024-02-17 06:03:34.032 PMdebugpatchDataAsync:, body:[data:[type:rooms, attributes:[active:true]]]
app:2462024-02-17 06:03:34.015 PMdebugSetting room attributes for 134703 to active:true%
app:2462024-02-17 04:51:54.618 PMdebugpatchDataAsync:, body:[data:[type:rooms, attributes:[active:false]]]
app:2462024-02-17 04:51:54.600 PMdebugSetting room attributes for 134703 to active:false%
app:2462024-02-17 02:31:02.717 PMdebugpatchDataAsync:, body:[data:[type:rooms, attributes:[active:true]]]
app:2462024-02-17 02:31:02.701 PMdebugSetting room attributes for 134708 to active:true%
app:2462024-02-17 11:49:20.607 AMdebugHubitat Flair App updating
app:2462024-02-17 11:49:18.420 AMdebugpatchDataAsync:, body:[data:[type:structures, attributes:[mode:auto]]]
app:2462024-02-17 11:49:09.403 AMdebugpatchDataAsync:, body:[data:[type:structures, attributes:[mode:manual]]]
app:2462024-02-17 11:49:08.793 AMdebugDiscovery started
app:2462024-02-17 11:49:05.800 AMdebugpatchDataAsync:, body:[data:[type:structures, attributes:[mode:manual]]]
app:2462024-02-17 10:59:27.243 AMdebugfinalizeRoomStates()
app:2462024-02-17 10:59:27.240 AMdebugthermostat1ChangeStateHandler:idle
app:2462024-02-17 10:57:43.659 AMdebugpatchDataAsync:, body:[data:[type:rooms, attributes:[active:true]]]
app:2462024-02-17 10:57:43.641 AMdebugSetting room attributes for 134703 to active:true%
app:2462024-02-17 10:39:27.729 AMdebuginitializeRoomStates(heating)
app:2462024-02-17 10:39:26.707 AMdebugthermostat1ChangeStateHandler:heating
app:2462024-02-17 10:21:22.713 AMdebugpatchDataAsync:, body:[data:[type:rooms, attributes:[active:false]]]
app:2462024-02-17 10:21:22.696 AMdebugSetting room attributes for 134708 to active:false%
app:2462024-02-17 07:41:26.491 AMdebugfinalizeRoomStates()
app:2462024-02-17 07:41:26.486 AMdebugthermostat1ChangeStateHandler:idle
app:2462024-02-17 07:22:27.677 AMdebuginitializeRoomStates(heating)
app:2462024-02-17 07:22:26.651 AMdebugthermostat1ChangeStateHandler:heating
app:2462024-02-17 05:58:26.708 AMdebugthermostat1ChangeStateHandler:idle
app:2462024-02-17 05:45:57.734 AMdebugHubitat Flair App updating
app:2462024-02-17 05:45:49.996 AMdebugpatchDataAsync:, body:[data:[type:structures, attributes:[mode:manual]]]
app:2462024-02-17 05:45:41.870 AMdebugHubitat Flair App updating
app:2462024-02-17 05:45:29.626 AMdebugpatchDataAsync:, body:[data:[type:structures, attributes:[mode:manual]]]
app:2462024-02-17 05:45:26.292 AMdebugpatchDataAsync:, body:[data:[type:structures, attributes:[mode:auto]]]
app:2462024-02-16 07:31:01.027 PMdebugpatchDataAsync:, body:[data:[type:rooms, attributes:[active:true]]]
app:2462024-02-16 07:31:01.012 PMdebugSetting room attributes for 134708 to active:true%
app:2462024-02-16 07:49:31.474 AMdebugpatchDataAsync:, body:[data:[type:rooms, attributes:[active:false]]]
app:2462024-02-16 07:49:31.456 AMdebugSetting room attributes for 134708 to active:false%

I've turned it back off, becasue it didn't seem to be working right, but the above are logs from the app. I do not see a "roomstate" listing in app details.