Average 3 device values and post results to 4th

jrfuda

Active Member
Guys, I need a script that will look at three HomeSeer device values take their average, and post the result to a 4th device. For example:

Device: Value
Y1: 75
Y21: 73
Y41: 74

In this case, the average of the three values is 74, therefore, the script would assign this value to a designated device, Y56

Y56: 74

This is the basic functionality I need. It would be even better, however, if the script was smart enough to throw out an obviously bad number and use the other numbers to perform the average instead. For example:

Y1: 75
Y21: 0
Y41: 74

In this case, the script would ignore the 0 for device Y21 and just take the average of Y1 and Y41, resulting in 75 (rounding up).

Currently, I want to use this script to average the temperatiure values for 3 weather stations deliverd by the HS Plugin, WeatherPlug. The three weather stations I moniotr withthe plugin are within 66 miles of my home, but sometimes their temperatures differ by as much as 5 degrees. I currently use the temperature reading from the nearest station to trigger the enabling/disabling of heating and cooling events in HomeSeer (Outside temp below a certain point puts the house in heat mode, and above a certain point in cool mode). I'd rather use the average of the three stations for the trigger, and maybe even add a fourth device - the current temp that WeatherXML delivers - into the "average" value.

I supopse this could be used to average other things too - average house temp, if you have multiple temp sensors in the house, etc.

Anyone got something?
 

CFGuy

Member
In your example of throwing out the 0 value, what would be your criteria for throwing out a value.

If its more than x% off the other values?
Or
If its more than x degrees?

The offset could be ini driven so you could change it easier until you get a setting you are happy with.
 

Squintz

Senior Member
I'd do it for you when i get home but someone will probably come up with something before then.

Where do you want your results to be displayed? Do you want them stored in a virtual device or simply calculated and displayed on a web page?
 

smee

Senior Member
Want you want can be done pretty simply with a few lines in a script. Add an event for each of your 3 original devices that triggers the script whenever their values change. The script can compute the new value and put it into the fourth device.

Coming up with a good criteria for throwing data out may be a bit more complicated, but whatever you (or someone else) come up with will be easy to put into the script.

Like Squintz mentioned, I'm sure someone will put something together for you (before I get a chance to).

The real solution is to be taking your own data - not averaging the data from other sources. I completely ignore other sources for temperature and humidity and rely on my own instruments.
 

jrfuda

Active Member
CFGuy said:
In your example of throwing out the 0 value, what would be your criteria for throwing out a value.

If its more than x% off the other values?
Or
If its more than x degrees?

The offset could be ini driven so you could change it easier until you get a setting you are happy with.
Jeff, I like the x% offset confgurable via the ini file idea.

Smee, If I had my weather equipment I'd use it. However, I think a script like this would be usefull even for soeone with their own equipment, and it can be used for more than just temperature.

You could use it to average the temps from multiple internal senors to get a "house" temp.

You could do the same with humidity, illumination, or anything else that has a value.
 

electron

Administrator
Staff member
I wrote something quickly to take care of the averages, all it does is add up the values of the specified devices and divide them by the # of devices specified, I will add the fancy stuff later, but I figured this might get you going. Save the following code to the txt file of your choice (we'll use average.txt in this example).


Code:
sub main(strDevices)
  myArray = split(strDevices)
  
  for x = lbound(myArray) + 1 to ubound(myArray)
    z = eval(z + Mid(hs.devicestring(myArray(x)),1,Instr(hs.devicestring(myArray(x))," ")))
  next

  z = Round(z / uBound(myArray),1)

  hs.SetDeviceString myArray(0),z
end sub

Let's assume that the temperatures are stored in w1, w2 and w3, and the device which will display the average value is y1, so the syntax would be:

average.txt("main","dev_average dev1 dev2 dev3 dev4 ..."

becomes

average.txt("main","y1 w1 w2 w3")

that's it! You can have as many devices as you want, the script will automatically strip the F or whatever measuring unit you use. I will put it in a nice package later this week, with all the options you want, as I can use this myself too.
 

jrfuda

Active Member
E, with the script pasted in like this:
Code:
sub main(strDevices)
	myArray = split(strDevices)
	for x = lbound(myArray) + 1 to ubound(myArray)
  z = eval(z + Mid(hs.devicestring(myArray(x)),1,Instr(hs.devicestring(myArray(x))," ")))
	next
	z = Round(z / uBound(myArray),1)
	hs.SetDeviceString myArray(0),z
end sub
I get
Script error in file: average.txt: 1002: Syntax error in line 4
I launched the script like this:
Code:
average.txt("main","y56 y1 y21 y41")
from an event that lookeduo for any change in the status of Y1, Y21, or Y41. Y56 is the device storing the average value.

Also, I noticed the script referenced device strings, I'd rather work with device values (then you wont have to worry about dropping non-numerical characters). I know how to throw together another script to build the deivce string for the average device, based on its value, that will include the degree and F symbols if I want.
 

smee

Senior Member
This
Code:
  z = eval(z + Mid(hs.devicestring(myArray(x)),1,Instr(hs.devicestring(myArray(x))," ")))
should all be on one line.
 

electron

Administrator
Staff member
there is only 1 line between the for and next statement, looks like it got wrapped in the code display here, I didn't even notice (so the line starts with z = eval(z + Mid( .... and ends with ))). As for Device values, all you have to do is replace the DeviceString function with the DeviceValue function. I decided not to use the device value as I have run into problems with that in the past, and most scripts don't use this field anyways. See if you can get it to work first.

edit: looks like smee beat me to it, someone was talking to me when I first started typing, so it took me 10 minutes to post lol.
 

electron

Administrator
Staff member
I attached a copy of the file I use, in case something else was screwed up.
 

Attachments

  • average.txt
    284 bytes · Views: 16

jrfuda

Active Member
Still getting the same error using the txt file you attached. Maybe there's something weird about my devices?
 

electron

Administrator
Staff member
what do your device strings look like?

you can add hs.writelog "debug", hs.devicestring(myArray(x)) above the Next line if you want the content dumped to the ah.log file (so you can cut and paste).

If the device strings are just numbers, change the eval line to:
Code:
z = eval(z + hs.devicestring(myArray(x)))
 

jrfuda

Active Member
E, that did the trick, my strings were raw numbers - not degree and F/C symbols. Once it worked, I went ahead and changed the script to read the values instead of string, and added a line that writes to the averge devices value - so the averages devices value and string are the same thing.

Thanks a alot for your help!

I do have some other stuff that I want to create average devices for, and some do have extra text in them that will require the original version of the script. I'm creating 2 versions:
average.txt : your orignal
averageinteger.txt : the modified number-only version
 
Top