Resource management solution?

does @Hubitat_Staff intend to come up with a more powerful unit some day, with much more computing capability than the current hubs? Or a platform that can run directly from a PC? resources management is really becoming a pain in the a.. these days, since the platform allows for parameters, number of devices, apps and overall running times that go too far beyond hubs capacities.

Without such an upgrade I am going to have to go for Home Assistant. I suppose there must be ways to keep HE running with a bridge between the two? I haven't had time to look into it so far but I will.

They never comment on future hardware, so I don't expect you will get a direct answer to your question.

3 Likes

Not answering for Hubitat staff BUT they have said they will not be entertaining a 'bring your own hardware" platform release. The usual never-say-never trope applies but they seemed quite set against the idea. I remember it because it's one of the many wishes I've had too.

Good Luck with your life on Home Assistant. Several people have gone that path and presumably with success. I was unable to achieve the success I desired and have given up on all 8 attempts I've made. It's just too time consuming to get any one device working. Once it was working, it was really rock solid, but I only took the time to get 3 unique ZWave devices added. More than a few are using their Hubitat Hub as a device controller, and that seems like what you're proposing. Smarter than my attempt anyway. :slight_smile:

3 Likes

As a matter of fact I have some processing time consuming apps and drivers that I have designed (available in my github) but some are still so badly designed that I am facing some serious challenges. For instance, I have been trying to design a way for my thermostat manager to learn from user's input and record current conditions (humidity, outside temp, user target input) but, even with dynamic map creation, with so many possible configurations (thousands of configurations since you want, for instance, to remember a value such as [outsideTem, [humidity:target]] and then decline "outside temp" for an array of maps of possible humidity levels and vice-versa...), HE hub just couldn't cut it, even when I tried running this app on a dedicated hub (app name: A.I. Thermostat Manager). I had to give up on such complexity and run a simple map such as [outside: target_amplitude] => target_temperature... which updates itself based on user's new inputs. But, as is, it is very limited because depending on outside / inside humidity, 73°F doesn't feel the same.

Anyway, I am still wondering whether it is due to my coding skills (really self learned over the past couple years) or an actual computing limitation. Anyone wanting to look over my github apps and make comments is welcome ! I'll take every critique as a new source of learning.

1 Like

I don't think there's much if any argument with "Hubitat's Platform code is great, but more horsepower in the hardware is desirable."

BYOH is an obvious answer... but you'd want a PC and I'd want a Mac and then there's the rPi4 version and support on any ONE of those would be a nightmare.. "what version of Java is installed on your PC?"

I know that with HubConnect, Steve chose to release a NodeJS package to augment the performance. It runs on my Mac or would run on your PC or their rPi :smiley:

This is rather a lot like WebCoRE in the sense that half the tool runs externally to the Hub. A json file that contains the "answers" could be downloaded hourly from the local NodeJS instance.

I clearly faced a "horsepower" limitation with one of my algorithms. to give you an idea, here is how the main db is built in this old deprecated app of mine:

This is a function that dynamically generates a quite long database that will then be implemented with new values based on users' inputs, time of day (location mode), outside humidity levels and outside temperature levels. This snippet below is just one of many other functions, including db check and repairs processes. This will not work without overwhelming even a dedicated hub.

def createDb(){


int ms = baseMode.size()
    int m = 0
    long start = now()
    long timer = 120000
    long startDebug = 1000
    long delay = now()
    def bsln = baseline ? baseline : 75

    if(saveOldData)
    {
        log.info "REPAIRING DATABASE WITHOUT DELETING OLD VALUES"
    }
    else
    {
        log.info "CREATNG NEW DATABASE..."
        state.db = [:] 
    }

    for(ms != 0; m < ms && !learning; m++) // location mode loop
    {

        def dbX = []

        if(saveOldData)   //not creation of database here but overwrite instead

        {
            dbX = state.db.find{it.key == baseMode[m]}?.value
            log.trace "redefining db with ${baseMode[m]} mode"

            if(state.backupRepair == null) {log.warn "NO DATA TO COMPARE WITH !"; return}
            def dbBackup = state.backupRepair.find{it.key == baseMode[m]}?.value // state.backupRepair = last time database was fully recreated


            int s = dbX.size()
            int i = 0
            for(s != 0; i < s; i++) {

                def ref = dbX[i][2]
                def compare = dbX[i] // data that will be compared then, if needed, overwritten
                def insert = dbBackup[i]
                boolean skip = false
                def valuestosave = state.valuestosave 
                boolean baseLinePresentInValues = valuestosave.find{it == bsln.toString()} 
                //log.debug "$bsln present in valuestosave = $baseLinePresentInValues"
                if(baseLinePresentInValues)
                {
                    log.debug "deleting baseline reference $bsln redundancy from $valuestosave"
                    def index = valuestosave.indexOf(bsln.toString())
                    valuestosave.remove(index)
                }               

                skip = valuestosave.find{it == ref.toString()}                    
                if(skip) // preserve previously learned values
                {
                    log.warn "value $ref not replaced in ${compare} at user's request"
                }
                else // if this is not to be saved, then just replace the value
                {
                    boolean identical = compare == insert
                    if(identical)
                    {
                        //log.info "identical values"
                    }
                    else 
                    {
                        if(now() - startDebug > delay) {log.info "$compare becomes $insert"}
                        dbX[i] = insert
                    }
                }
                if(now() - start > timer)
                {
                    log.warn "createDb() (inner loop) took more than $timer seconds to execute, BREAK"
                    return
                }
            }
        }
        else   // depending on whether we want to save old data, or not, we apply a different writing method: replacement or increment         
        {
            int maxTemp = 120
            int minTemp = -50 // minimum outside temp // If you think it can get below that... move to Venus...
            int h = 10 // minimum humidity value
            int i = minTemp 
            int s = maxTemp + Math.abs(i) // total size of iterations to be covered from - 50 to 120


            dbX = []
            def insert = []
            for(s!=0;i<s;i++)
            {
                int a = 0
                h = 10
                for(s!=0;(i <= maxTemp && a <= maxTemp);a++) // for each i (outside temp max = 120) we create all variations of humidity (max = 100)
                { // s is max size = 120+abs(i) don't put <sh here
                    h = h < 100 ? h + 1 : h 
                    //log.info "$a --- $i"
                    insert = [i,h,bsln] // create [[outsideTemp, humidity, setpoint]] i is the temp value, can be negative, that's why we don't use 'a' here

                    //simple database increment, we're creating a fresh new db
                    dbX << insert

                    if(now() - start > timer)
                    {
                        log.warn "createDb() (inner loop) took more than $timer seconds to execute, BREAK"
                        return
                    }
                }

            }
            if(now() - start > timer)
            {
                log.warn "createDb() (outer loop) took more than $timer seconds to execute, BREAK"
                return
            }

        }
        def newIt = ["${baseMode[m]}" : dbX]
        state.db << newIt
        if(!saveOldData){state.backupRepair = state.db}// backup the db for upcoming comparisons 
        log.debug "DB for ${baseMode[m]} mode done...  "
    }

    //metaDB = ["Day":["test", "test", "test"], "Night":["test", "test", "test"], "Evening":["test", "test", "test"]]
    //state.metaDB = metaDB

    log.debug "ALL DATA SUCCESSFULY GENERATED"

}

Is there some reason you don't implement systems such as this database on an appropriate processor, and use Maker API to feed events to it? Why does this have to run on the hub?

6 Likes

We don't see a viable business opportunity to do this.

3 Likes

:+1:

Same here. Total disaster, and it was a maintenance nightmare.

In my opinion, this is the crux of the matter. I am far from a coder, but with those fairly simple parameters, and that few lines of code, I cannot see how it should be slamming the hub that badly unless it is poorly thought out. Rule Machine must be 10 times that much code, Echo Speaks has multiple drivers and apps that are longer than your code, and both work fine and don't kill your hub.

That's what I'm going to look into when I find the time. For now, I think I simply don't have the detailed Know-how. I am already using the Maker API for a cust. tiles page and I guess I'm gonna have to learn how to use java or python... that's something I still need to learn.

These few lines of code generate a huge database.

If you know Groovy, why not just run Groovy on whatever system you intend to use?

1 Like

Hum... Because I didn't know I could do that... lol

Wonder if you could build this on a running basis with running averages somehow. Might not be something you'd want to put in full control mode until you had run through the full range of seasonal variation and extremes.

I'd think the learning stage of this would in effect be "the task" and the actual application of that lookup table "the easy bit". I can't believe this couldn't be binned into some reasonable bands that would get you into the occupant's desired setting range 90% of the time, (with some bias towards energy savings of course :stuck_out_tongue_winking_eye: ), ....and maybe 10% of the time they are having to touch it up a bit.

Then of course there's the conditionals in execution like "is a bird sitting on the outdoor temp sensor" right now or, is the battery dead :innocent:.

1 Like