[Release] Hub Variable Sync

This app is designed to allow 2 hubs to synchronize the values of hub variables, HSM Status, and Hub Mode. (Can have multiple copies of the app if running 3 or hubs.) Much of this functionality will, at some point be is now available via Hub Mesh for hubs on the same LAN segment, but this app will also allow the use of HE's cloud endpoints for hubs that are not on the same segment.

Suggested setup steps:

  1. Setup the hub variables on both hubs (Names and Type must agree)
  2. Import the app code from https://raw.githubusercontent.com/thebearmay/hubitat/main/apps/hubVarSync.groovy (or use HPM when I get it updated) to each hub and enable OAuth
  3. Create the app on each hub using Add a User App
  4. Go to your first hub and open the Remote Hub Information
  5. Go to the second hub and open up the Local Hub Information
  6. Copy the API from the #5 to #6 (use the cloud API if not on the same LAN)
  7. Copy the Access Token from #5 to #6
    7a) Optional - Select to resync from remote hub at reboot
  8. Click Done
  9. Repeat #4-7 reversing the hubs
  10. Select the Variables you want to sync on both hubs (can be a 1-way sync or a 2-way)
  11. Optional Click Send Update on one of the hubs to send values of the selected variables to the other hub

After doing all of that, whenever a selected hub variable value changes it will be transmitted to the other hub for update.

4 Likes

[Reserved for Future detail]

1 Like

Feels like this should be built in to hub mesh....

It will be ...

7 Likes

It will be in the Hub Mesh at some point, but this would also allow you to sync with hubs that aren't on the same LAN if desired (not the reason I wrote it though - I just had a few minutes and wanted to see if I could do it...)

2 Likes

I’m confused. I’m syncing Hub Variables via hub mesh already. At least I think I am. Granted, it’s between hubs on the same LAN. What am I missing?

Are you sharing the connectors across, or??

Yes I'm sharing the connectors.

Just dawned on me that's the difference. In the remote hub, I'm no longer using a Hub Variable, which I imagine has a performance disadvantage. Is that the point?

I'm trying to wrap my head around the advantage of this app over hub meshing the connector.

Couple less devices, and the fact that connectors will eventually go away creation of new connectors won't be supported when Hub Mesh does include the capability of sharing variables across (thinking this will be sooner rather than later). Probably not a real performance hit, but possibly a little slower using the connector and this allows me to make my rule changes now and look for something else to dig into.

1 Like

Existing connectors will not go away.

Sorry, I'll correct that to say that the creation of new connectors won't be available.

v0.1.6 adds the capability of sending and receiving variable updates with nodeRed.

To send from nodeRed use an httpRequest node, with method = GET or POST, and a URL that looks similar to (most of the data is from the Local Server Information page in the app):

$Local_Server_API/setVar/$variable_name/$variable_value?access_code=$access_code

or

$Cloud_Server_API/setVar/$variable_name/$variable_value?access_code=$access_code

Recieving data into nodeRed requires an http In node with method *Post * and URL equal to the value you entered as the Node Red Endpoint path in the app. Some method of parsing the incoming value - a sample from a function node:

msg.payload = "received update for variable "+msg.payload.varName+" with value "+msg.payload.varValue+" and type "+ msg.payload.varType
return msg;

and an http out node

Can't get this to work. A quick examination of the code seems to indicate that manageSubscriptions() is never called.

I think it's never called because on a new installation, atomicState.priorList is null, and the test on line 105 fails, preventing the subscriptions from being set up and priorList from being updated.

Edit:
Confirmed, that's the problem. Add the test for a null priorList:

void manageSubscriptions(){
    if (atomicState.priorList?.value != null) {
        atomicState.priorList.value.each{
            if(debugEnabled) log.debug "unsub $it"
            unsubscribe(location, it.toString())
        }
    }

and change the conditional on line 105 to

if(varList != null )

Maybe this isn't the best way to fix the problem, but it does confirm that manageSubscriptions() was not being called because priorList was null.

Perhaps just set priorLIst to an empty list in initialize(). Looks like you're trying to optimize away the call to manageSubscriptions() if the lists are equal but why bother, it's not something that's going to be called a zillion times in a loop.

Try updating to v0.1.8 (just pushed it up)

I'd have to uninstall the app and start over to test, but line 314 is going to throw an exception if priorLIst is null, isn't it?

each will = 0 so never executes (I think), if it does a change to

atomicState.priorList?.value.each{

should fix it. May make that change anyway.

Yeah, I'd think calling each() on a null object would throw an exception w/o the null conditional op.

Yeah, I think you’re right. Made the change but didn’t increment the version.

1 Like

Thanks for sharing the app, it does exactly what I needed w/o having to set up a more complicated solution.

Glad it works for you, let me know if you have any ideas to improve it.