[DRIVER] NUT Discovery + UPS & Outlet Status

OK I don't really understand Groovy or the device driver architecture in Hubitat but I think I figured this out with some old skool printf-style debugging.

First, I noticed that the error message

ParseOK: Couldn't process message: "[]"

disappeared when I turned on Debug Logging in the driver...hmmm. :roll_eyes:

Second, I also noticed that the default (ie, error) choice for the switch() statement in the ParseOK routine was being selected when the device.currentState equaled STATE_CONNECTING.

These two behaviors suggested to me there was a timing problem or race condition around the message parsing and the device state detection, so I added a log.info() message as the first line of the ParseOK() routine, and the execution of this log statement created enough delay that the device.currentState had time to transition from STATE_CONNECTING to STATE_AUTH_PHASE1 or STATE_AUTH_PHASE2, which were the only two choices that the message parser state machine was expecting. Cleaning it up by replacing the log.info() statement with a proper delay loop conditioned on STATE_CONNECTING gave me this revised version of the ParseOK() routine:

def parseOK(String[] msg) {
    int i = 0 
    while ( device.currentState("State", true).value == STATE_CONNECTING ) {
        if( i++ > 1000 ) 
            break ;
    }
    switch(device.currentState("State", true).value) {
		case STATE_AUTH_PHASE1:
			nutAuthPhase2()
			break
		case STATE_AUTH_PHASE2:
			nutListUPS()
			break
		default:
			log.error("ParseOK: Unexpected State is: \"${device.currentState("State", true).value}\", couldn't process message: \"${msg}\"")
	}
}

This has eliminated the error messages from the driver and I don't think it is changing the driver's execution semantics at all.

2 Likes

Which driver is this in? I'm not seeing parseOK in any of the 3... nevermind.

It's in NUT UPS Driver. For whatever reason the search in the Driver Code wasn't seeing it.

1 Like

Sorry, did I mistake which NUT drivers this thread is referencing? I'm using @guyeeba 's drivers from https://github.com/guyeeba/Hubitat/blob/master/Drivers/NUT%20UPS%20Driver.groovy and the relevant code for parseOK() is at line 129.

Backstory, I got a slightly used APC (free from work) and hooked it all up. Its connected to a Windows 10 machine, so I put apcupsd on there. The Hubitat driver for apcupsd is less than desirable needing a web server to host a php file and all sorts of odd stuff. So... I slapped NUT on a linux VM and used the apcups driver to poll and then serve the stats out for this Hubitat driver. Therein possibly is the problem, the run time is being reported with a decimal but this Hubitat driver is expecting a whole number only. Here is the error I was getting.

image

Here is my fix for the NUT Child UPS file (around line 119).
Also added attribute batteryRuntimeMins, use if you want. I will run this for a few weeks and if I dont find any other problems I may submit a PR to the repo.

		case "runtime":
			Integer runTimeS = Math.round(Float.parseFloat(value))
			Integer runTimeM = runTimeS/60
			sendEvent( [
				name: 'batteryRuntimeSecs',
				value: runTimeS,
				unit: "sec",
				descriptionText: "Remaining runtime is ${runTimeS} seconds"
			])
			sendEvent( [
				name: 'batteryRuntimeMins',
				value: runTimeM,
				unit: "min",
				descriptionText: "Remaining runtime is ${runTimeM} minutes"
			])
			break;
1 Like

I've managed to get the driver and device all set up and working fine for my APC1500 that's attached to my Synology. THANKS FOR THE AWESOME DRIVER!

BUT, has anyone succeeded in using this to auto shutdown when Hub Authentication is enabled? I've read this whole thread twice and didn't see it.

Yes, get the Hub Information Driver which now has a shutdown command in it. That driver will handle the hub login security part for you and activate the shutdown. There is also a much simpler driver that has the shutdown option only but I highly recommend this info driver as the extra info is often useful.

Here is my overly complicated rule to feed me updates on the UPS and then shut the hub down before it dies

4 Likes

Awesome! I already have the Hub Information Driver installed. Thank you!

I got this working perfectly and tied into RM just the way I want it. I just have one issue. The parent device is generating excessive events. I extended the polling interval from 10s to 15s, but it's still happening. Over 400/hr.

Anyone else experience this?

I have mine set to 30s, any longer and the telnet times out before it refreshes so it has to keep reconnecting. That would cut your events by half from 15s. Here is my stats. Where are you getting the 400/hr, is that part of the alert? I don't see the per/hr listed anywhere for me.

I lengthened my polling setting to 20sec. That got me under the default threshold.

I have a followup question though. What screen is your screenshot from? I can't seem to find that one.

Logs > Device Stats (tabs at the top of logs page)

1 Like

Question. In the middle of your actions in your rule I see a "Wait for events" between your While and your ORR statements. How did you do that? I can't seem to find out how to insert the wait and then insert an OR. Can you explain?

LJ

The OR is part of the Wait, the indenting does not show that very clearly. It might make more sense shown with the new grid layout:

Once you add one Wait event, you just add another to the bottom (there is a button) and it puts in the OR. The Wait for Event page has a really confusing layout I see now, and there is no way to remove an event if you add too many.

2 Likes

Steve,

I know this old but I tried your code change above and I am still getting the "telnetStatus: receive error: Stream is closed" message in my logs each time it tries to reconnect. It does seem to reconnect after a retry and download the required information, but the error message is still flooding my logs. you seem to think this fixed your instance. Any other suggestions or changes you made to get this to work?

LJ

What is your update interval set to? I found if it was more than 30 seconds the telnet would have to reconnect. I have modified the code myself to add a sort of "NOP" keepalive command so that I can refresh less often but the connection stays active. I could post it on a Gist later today for you to try out if you want.

My update interval is 15 seconds. Might there be a setting in the RPi that would keep the connection alive longer? These are my settings in Nut UPS Server.

"Gist"?? Not familiar. but any help would be welcome. Just trying to keep things clean in the logs and smooth functioning.

Thanks,

LJ

I found mine worked without the user/pass so maybe try that out. Mine is running on a Debian variant OS so should be similar. For me it will only disconnect if it goes more than 30 seconds. Checking every 15 seconds it should not be getting disconnected.

You could just find that line of code where it logs the error and comment it out.

I was asked for my modified version of this driver set, so I have posted it in a Gist linked below.
I posted the original first then my version so if you click on the "Revisions" tab you can see the changes. Make sure you get all 3 files.

This could probably be further optimized to only process the data points every refresh that we would expect to actually change. The rest could be checked once a day or something. If there is interest I could look at adding that as well.

2 Likes

I ran into the same issue: with or without a password, the NUT server on my Synology NAS would disconnect 60 secs after the most recent Telnet message. Rather than generate a "keep alive" NOP message every minute I restructured the driver so that it doesn't use a persistent Telnet connection to the server, instead it reconnects each nutPollingInterval period and then closes the connection once it's finished refreshing all the UPS parameters.

I actually switched over to this driver now, and recommended it: