Growing Degree Days Script

Moderator: leecollings

Post Reply
Ittiz
Posts: 48
Joined: Tuesday 03 January 2017 0:37
Target OS: Linux
Domoticz version: 13939
Location: USA
Contact:

Growing Degree Days Script

Post by Ittiz »

I'm not sure how many people are gardeners out there. I've found gardening and fruit trees to be a nice past time, so I created a script in Domoticz to keep track of Growing Degree Days. Which is a useful measure for figuring out when fruits and vegetables will flower or ripen and also when certain pests will appear and start to attack your crops. It resets your sensors in winter either on Jan 1st or Jul 1st, you pick whether you're in the northern or southern hemispheres respectively. Best time to install the script is BEFORE the beginning of the growing season before it gets above freezing (if possible). If you live in a warm place then before Jan/Jul 1st is best. I live in the US so I've set mine to Fahrenheit but it can be changed to use Celsius.
Oh, it's a time based script.
Anyway I've provided the script below :

Code: Select all

function round(num, numDecimalPlaces)
  local mult = 10^(numDecimalPlaces or 0)
  return math.floor(num * mult + 0.5) / mult
end

function findDevID(name)
   return otherdevices_idx[name] or false
end


--NEEDED: 
--   1: External Temperature Sensor
--   2: 4 new custom DUMMY sensors named GDM 50, GDD 50, GDM 32 and GDD 32. Can be changed if you use Celcius.
--   3: Unpassworded access for localhost (IP 127.0.0.1)

commandArray = {}
local MaxTemp = 90-- If over this temp, set to this temp 
local MinTemp50 = 50-- Turn on GDD50 at this temp
local MinTemp32 = 32-- Turn on GDD32 at this temp
local UserTempScale = "F" --Input variables, are they Celcius (C) or Fahrenheit (F)?
local ODThrmtrNm = 'Outside Temperature' --Thermometer name in Domoticz
local gdm50 = "GDM 50" -- Name of growing degree minutes over 50F custom DUMMY sensor in Domoticz
local gdd50 = "GDD 50" -- Name of growing degree days over 50F custom DUMMY sensor in Domoticz
local gdm32 = "GDM 32" -- Name of growing degree minutes over 32F custom DUMMY sensor in Domoticz
local gdd32 = "GDD 32" -- Name of growing degree days over 32F custom DUMMY sensor in Domoticz
local rstmnt = 1 --the number of the month we reset on.  Usually Jan (1) or Jul (7)


local Temp = tonumber(otherdevices[ODThrmtrNm])
local stop1 = string.find(Temp,";")

if(stop1 ~= nil) then --If your sensor does more than Temp
	Temp = tonumber(string.sub(Temp,0,stop1-1))
else
	Temp = tonumber(Temp)
end
if (UserTempScale == "F") then
	Temp = round(Temp*(9/5)+32,2)
else
	Temp = round(Temp,2)
end

local s1 = otherdevices_lastupdate[gdm32]
local year1 = string.sub(s1, 1, 4)
local tR = os.time{year=os.date("%Y"), month=rstmnt, day=1, hour=0, min=0, sec=0}
if (Temp >= MinTemp50) then
	if (Temp >= MaxTemp) then
		Temp = MaxTemp
	end
	--new code in case the script doesn't fire every minute
	local month1 = string.sub(s1, 6, 7)
	local day1 = string.sub(s1, 9, 10)
	local hour1 = string.sub(s1, 12, 13)
	local minutes1 = string.sub(s1, 15, 16)
	local seconds1 = string.sub(s1, 18, 19)

	local s2 = otherdevices_lastupdate[gdm50]
	local year2 = string.sub(s2, 1, 4)
	local month2 = string.sub(s2, 6, 7)
	local day2 = string.sub(s2, 9, 10)
	local hour2 = string.sub(s2, 12, 13)
	local minutes2 = string.sub(s2, 15, 16)
	local seconds2 = string.sub(s2, 18, 19)

	local t0 = os.time()
	local t1 = os.time{year=year1, month=month1, day=day1, hour=hour1, min=minutes1, sec=seconds1}
	local t2 = os.time{year=year2, month=month2, day=day2, hour=hour2, min=minutes2, sec=seconds2}
	local delta1 = (t0-t1)/60
	local delta2 = (t0-t2)/60
	if (delta1 > 1440) then
		delta1=1
	end
	if (delta2 > 1440) then
		delta2=1
	end
	print(tostring(delta1) .. ", " .. tostring(delta2))
	table.insert (commandArray, { ['UpdateDevice'] =  findDevID(gdm50) .. '|2|' .. tostring(tonumber(otherdevices[gdm50])+(Temp-MinTemp50)*delta2)})
	table.insert (commandArray, { ['UpdateDevice'] =  findDevID(gdm32) .. '|2|' .. tostring(tonumber(otherdevices[gdm32])+(Temp-MinTemp32)*delta1)})
	table.insert (commandArray, { ['UpdateDevice'] =  findDevID(gdd50) .. '|2|' .. tostring((tonumber(otherdevices[gdm50])+(Temp-MinTemp50)*delta2)/1440)})
	table.insert (commandArray, { ['UpdateDevice'] =  findDevID(gdd32) .. '|2|' .. tostring((tonumber(otherdevices[gdm32])+(Temp-MinTemp32)*delta1)/1440)})
elseif (Temp >= MinTemp32) then
	if (Temp >= MaxTemp) then
		Temp = MaxTemp
	end
	--new code in case the script doesn't fire every minute
	local month1 = string.sub(s1, 6, 7)
	local day1 = string.sub(s1, 9, 10)
	local hour1 = string.sub(s1, 12, 13)
	local minutes1 = string.sub(s1, 15, 16)
	local seconds1 = string.sub(s1, 18, 19)
	local t0 = os.time()
	local t1 = os.time{year=year1, month=month1, day=day1, hour=hour1, min=minutes1, sec=seconds1}
	local delta1 = (t0-t1)/60
	if (delta1 > 1440) then
		delta1=1
	end
	table.insert (commandArray, { ['UpdateDevice'] =  findDevID(gdm32) .. '|2|' .. tostring(tonumber(otherdevices[gdm32])+(Temp-MinTemp32)*delta1)})
	table.insert (commandArray, { ['UpdateDevice'] =  findDevID(gdd32) .. '|2|' .. tostring((tonumber(otherdevices[gdm32])+(Temp-MinTemp32)*delta1)/1440)})
end
if (os.time()-tR <= 300) then--less than five mins after the reset month?  then reset!
	table.insert (commandArray, { ['UpdateDevice'] =  findDevID(gdm50) .. '|2|0'})
	table.insert (commandArray, { ['UpdateDevice'] =  findDevID(gdm32) .. '|2|0'})
	table.insert (commandArray, { ['UpdateDevice'] =  findDevID(gdd50) .. '|2|0'})
	table.insert (commandArray, { ['UpdateDevice'] =  findDevID(gdd32) .. '|2|0'})
end

return commandArray

EDIT: Updated script. Old script had a bug where it only reset if it was below freezing. Also if Domoticz was lagging or was down for several minutes that time would be missed. New update compensates for that.
Last edited by Ittiz on Thursday 02 January 2025 3:02, edited 2 times in total.
Toulon7559
Posts: 848
Joined: Sunday 23 February 2014 17:56
Target OS: Raspberry Pi / ODroid
Domoticz version: mixed
Location: Hengelo(Ov)/NL
Contact:

Re: Growing Degree Days Script

Post by Toulon7559 »

Just in time with your script, because indeed 1st of January is a well-known, common starting point for the accumulating values for GrowingDegreeDays!

When using GGD for various applications quite often also a upper threshold is set for a cumulating value:
when that value is reached, an alarm is triggered that 'some' action is required.
Reverse also possible: at certain values a defined phenomenum may take place in nature
See the definition for fenology.
Fenology is used 2 ways:
- when monitoring the time-series, you can see when to expect something happening based on historic data
- monitoring the events, you can register timing, compare with above time-series, and determine whether early or late and how much, and why (although the latter only to some very limited extend!)

In that perspective you might meaningfully extend your script with a few accumulating counters, dependent on purpose.
Interestingly, many different purposes dependent on region of the world and dependent on aspect to be monitored.
Examples in my region (but many more if you look at internet):
Netherlands has T-Som which (as rather simple accumulation) is applied as a triggermonitor to fertilize grassland when an upper limit is passed.
Germany has Grünland which has similar aim, but with a different calculation on the time values and different upper limit.

Not only for nature, but DegreeDays also well known for energy-functions:
Heating Degree Days and related Cooling Degree Days.
Opens a whole world of interesting discussions!
Set1 = RPI-Zero+RFXCom433+S0PCM+Shield for BMP180/DS18B20/RS485+DDS238-1ZNs
Set2 = RPI-3A++RFLinkGTW+ESP8266s+PWS_WS7000
Common = KAKUs+3*PVLogger+PWS_TFA_Nexus
plus series of 'satellites' for dedicated interfacing, monitoring & control.
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: Growing Degree Days Script

Post by waaren »

Ittiz wrote: Sunday 27 December 2020 6:28

Code: Select all

	local da = assert(io.popen('curl --silent -m 5  -k "http://127.0.0.1/json.htm?type=devices&filter=all&used=true" &'))
You don't need to retrieve the full list of all used devices every time you need a deviceID.
Below function will also return the deviceID based on a given name or false when no such used device exist.

Code: Select all

function findDevID(name)
   return otherdevices_idx[name] or false
end
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
Ittiz
Posts: 48
Joined: Tuesday 03 January 2017 0:37
Target OS: Linux
Domoticz version: 13939
Location: USA
Contact:

Re: Growing Degree Days Script

Post by Ittiz »

waaren wrote: Sunday 27 December 2020 13:19
Ittiz wrote: Sunday 27 December 2020 6:28

Code: Select all

	local da = assert(io.popen('curl --silent -m 5  -k "http://127.0.0.1/json.htm?type=devices&filter=all&used=true" &'))
You don't need to retrieve the full list of all used devices every time you need a deviceID.
Below function will also return the deviceID based on a given name or false when no such used device exist.

Code: Select all

function findDevID(name)
   return otherdevices_idx[name] or false
end
Thanks, will correct.
Ittiz
Posts: 48
Joined: Tuesday 03 January 2017 0:37
Target OS: Linux
Domoticz version: 13939
Location: USA
Contact:

Re: Growing Degree Days Script

Post by Ittiz »

Toulon7559 wrote: Sunday 27 December 2020 8:06

Wow thanks for the in depth description. I made my script because I was fed up with how inaccurate the GDD reported by the local weather station was. Not only were their numbers based on a fudge (a sine wave estimate based on Tmin and Tmax) but it was also interpolated for my location. My script works by accumulating the Growing Degree Minutes as they accumulate. It's more accurate than the local guesstimates, even with my server being down occasionally. It's extremely useful if you live in a micro climate that's smaller than the resolution of publicly available data. It does have an upper limit, I set to 90F as that's the norm we use in the US.

I certainly could add more, one thing I'd like to do is guesstimate the GDM if the script detects there's a gap, like restarting your server for instance. If I was going to do Phenology stuff I would make separate scripts for that. At the moment I don't have any other scripts that monitor my GDM and GDD devices. I use the data to eyeball when I expect to see certain things happen like a tree flower or a pest to arrive.

On a side note, cooling degree days can also be important for gardeners but in a more hidden way. Many seeds need a certain number of days below a temperature (known as stratification) in order to germinate.
Toulon7559
Posts: 848
Joined: Sunday 23 February 2014 17:56
Target OS: Raspberry Pi / ODroid
Domoticz version: mixed
Location: Hengelo(Ov)/NL
Contact:

Re: Growing Degree Days Script

Post by Toulon7559 »

Indeed, your near micro-climate very often paints different pictures!
One of the reason to have your own meteo-registration, with related derived calculations!!!
Set1 = RPI-Zero+RFXCom433+S0PCM+Shield for BMP180/DS18B20/RS485+DDS238-1ZNs
Set2 = RPI-3A++RFLinkGTW+ESP8266s+PWS_WS7000
Common = KAKUs+3*PVLogger+PWS_TFA_Nexus
plus series of 'satellites' for dedicated interfacing, monitoring & control.
Ittiz
Posts: 48
Joined: Tuesday 03 January 2017 0:37
Target OS: Linux
Domoticz version: 13939
Location: USA
Contact:

Re: Growing Degree Days Script

Post by Ittiz »

just bumping this since it's the 1st of the year and I made relevant changes to the script. see original edited post.
Post Reply

Who is online

Users browsing this forum: No registered users and 0 guests