So I wrote my script, actually is made of 2 Lua and 1 bash script.
I'm sure it can be optimized, sorry I am not a programmer and know just a little bit of coding.
The script is for managing a 4 zone irrigation system thru an ESP8266 and a 4 relay board.
First of all, I've created four new Dummy Switch, one for each irrigation zone.
The main script uses the fantastic Google Calendar for Domoticz by BakSeeDaa (thanks!) to check for a specific calendar event.
It will check for an event that start with IRRIG and separated by comma with the irrigation time for each zone (ie. IRRIG,10,4,0,8)
If the event is correct, it will check for previous and upcoming rainfall forecast, to avoid irrigation. Using Weather Underground.
If all is ok, it can call the bash script that will manage zone activation in a serialized way (sleep).
The third script is "listening" for activation of one of the Dummy Switch and will send http commands to the ESP, to switch off all the relay except the one I want to activate, to be sure that only one is active.
Here is the code:
Main Script
Code: Select all
---------------------------------
--Main script for manage a 4 zone irrigation system thru an ESP8266
--Is based on Gmail Calendar event (thanks to BakSeeDaa for his Google Calendar for Domoticz).
--It will check for an event that start with Irrig and separated by comma with the irrigation time for each zone (ie. Irrig,10,4,0,8)
--If the event is correct, it will check for previous and upcoming rain, to avoid irrigation.
--If all is ok, it will call a bash script that will manage zone activation in a serialized way (sleep)
--Author : woody4165
--Date : 17 April 2016
---------------------------------
commandArray = {}
if (devicechanged['GCalTicz'] == 'On') then
local innaffia = 1
else
return
end
local innaffia = 1
oggi = os.date("%Y%m%d")
-- The irrigation event must be this format "IRRIG,xx,xx,xx,xx" where xx are the activation minutes for each zone. Can be also 0.
local_uservar = uservariables['GCal88NextEvent']
-- function to split the string comma separated
function string:split( inSplitPattern, outResults )
if not outResults then
outResults = { }
end
local theStart = 1
local theSplitStart, theSplitEnd = string.find( self, inSplitPattern, theStart )
while theSplitStart do
table.insert( outResults, string.sub( self, theStart, theSplitStart-1 ) )
theStart = theSplitEnd + 1
theSplitStart, theSplitEnd = string.find( self, inSplitPattern, theStart )
end
table.insert( outResults, string.sub( self, theStart ) )
return outResults
end
-- Split the Event to check if this is an irrigation event and grab the activation minutes per zone
local CalEvent = local_uservar:split(",")
-- If the first element is not "IRRIG" or if does not contain all the parameters, it's not an irrigation event. Exit
if ((CalEvent[1] ~= "IRRIG") or (#CalEvent ~= 5)) then
return
end
--need to find "<" in the calendar event string to cut the last parameter at that position
w = string.find(CalEvent[5], "<")
w = w-1
local minuti_irrig1 = 0
local minuti_irrig2 = 0
local minuti_irrig3 = 0
local minuti_irrig4 = 0
-- If all is ok, define minutes per zone
minuti_irrig1 = tostring(CalEvent[2]*60)
minuti_irrig2 = tostring(CalEvent[3]*60)
minuti_irrig3 = tostring(CalEvent[4]*60)
minuti_irrig4 = (string.sub(CalEvent[5], 1, w)*60)
-- Now can control weather
function checkWeather(fake)
json = (loadfile "/home/pi/domoticz/scripts/lua/JSON.lua")()
-- Check if it has rained
-- get data from Weather Underground history of current day
local jsondata = assert(io.popen('curl "http://api.wunderground.com/api/xxxxxxx/history_'..oggi..'/q/zmw:00000.x.xxxx.json"'))
local jsondevices = jsondata:read('*all')
jsondata:close()
local rained = json:decode(jsondevices)
pioggia = tonumber(rained.history.dailysummary[1].precipm)
-- If has rained exit
if (pioggia > 0) then
-- print("Ha piovuto ieri "..pioggia.."mm")
innaffia = 0
return
end
-- Check if it's going to rain
-- get data from Weather Underground forecast
local jsondata = assert(io.popen('curl "http://api.wunderground.com/api/xxxxxx/forecast/q/zmw:00000.x.xxxxx.json"'))
local jsondevices = jsondata:read('*all')
jsondata:close()
local willrain = json:decode(jsondevices)
local piove_mattina = 0
local piove_sera = 0
local precip_oggi_mattina = 0
local precip_oggi_sera = 0
-- Grab only the forecast data for today
precip_oggi_mattina = tonumber(willrain.forecast.simpleforecast.forecastday[1].qpf_day.mm)
precip_oggi_sera = tonumber(willrain.forecast.simpleforecast.forecastday[1].qpf_night.mm)
if ((precip_oggi_mattina == nil) or (precip_oggi_mattina == 0)) then
piove_mattina = 1
end
if ((precip_oggi_sera == nil) or (precip_oggi_sera == 0)) then
piove_sera = 1
end
-- If is going to rain, exit
if ((piove_mattina == 0) or (piove_sera == 0)) then
innaffia = 0
print("Pioverà la mattina "..precip_oggi_mattina.."mm e la sera "..precip_oggi_sera.."mm")
return
end
end
checkWeather(fake)
-- Now call the bash irrigation script with irrigation time per zone
comando="/home/pi/domoticz/scripts/irrigation.sh "..minuti_irrig1..' '..minuti_irrig2..' '..minuti_irrig3..' '..minuti_irrig4
os.execute(comando)
return commandArray
Bash Script
Code: Select all
#!/bin/bash
MIN_ZONE1=$1
MIN_ZONE2=$2
MIN_ZONE3=$3
MIN_ZONE4=$4
DOMO_IP="192.168.x.xx" # Domoticz IP Address
DOMO_PORT="xxxx" # Domoticz Port
IDX_ZONE1="xx"
IDX_ZONE2="xx"
IDX_ZONE3="xx"
IDX_ZONE4="xx"
if expr "$MIN_ZONE1" '>' 0
then
echo $MIN_ZONE1
curl -s "http://$DOMO_IP:$DOMO_PORT/json.htm?type=command¶m=switchlight&idx=$IDX_ZONE1&switchcmd=On" > /dev/null
sleep $MIN_ZONE1
curl -s "http://$DOMO_IP:$DOMO_PORT/json.htm?type=command¶m=switchlight&idx=$IDX_ZONE1&switchcmd=Off" > /dev/null
fi
if expr "$MIN_ZONE2" '>' 0
then
echo $MIN_ZONE2
curl -s "http://$DOMO_IP:$DOMO_PORT/json.htm?type=command¶m=switchlight&idx=$IDX_ZONE2&switchcmd=On" > /dev/null
sleep $MIN_ZONE2
curl -s "http://$DOMO_IP:$DOMO_PORT/json.htm?type=command¶m=switchlight&idx=$IDX_ZONE2&switchcmd=Off" > /dev/null
fi
if expr "$MIN_ZONE3" '>' 0
then
echo $MIN_ZONE3
curl -s "http://$DOMO_IP:$DOMO_PORT/json.htm?type=command¶m=switchlight&idx=$IDX_ZONE3&switchcmd=On" > /dev/null
sleep $MIN_ZONE3
curl -s "http://$DOMO_IP:$DOMO_PORT/json.htm?type=command¶m=switchlight&idx=$IDX_ZONE3&switchcmd=Off" > /dev/null
fi
if expr "$MIN_ZONE4" '>' 0
then
echo $MIN_ZONE4
curl -s "http://$DOMO_IP:$DOMO_PORT/json.htm?type=command¶m=switchlight&idx=$IDX_ZONE4&switchcmd=On" > /dev/null
sleep $MIN_ZONE4
curl -s "http://$DOMO_IP:$DOMO_PORT/json.htm?type=command¶m=switchlight&idx=$IDX_ZONE4&switchcmd=Off" > /dev/null
fi
Executing script
Code: Select all
---------------------------------
--Script to activate a 4 relay board connected to an ESP8266 to control 4 irrigation zones
--Author : woody4165
--Date : 17 April 2016
---------------------------------
commandArray = {}
-- When one of the 4 Irrigation Dummy Switch will change Status
-- For each zone activation, first switch Off all the others.
if (devicechanged['IrrigZone1'] == 'On') then
os.execute('curl "http://192.168.x.xx/control?cmd=GPIO,xx,1"')
os.execute('curl "http://192.168.x.xx/control?cmd=GPIO,xx,1"')
os.execute('curl "http://192.168.x.xx/control?cmd=GPIO,xx,1"')
os.execute('curl "http://192.168.x.xx/control?cmd=GPIO,xx,0"')
elseif (devicechanged['IrrigZone1'] == 'Off') then
os.execute('curl "http://192.168.x.xx/control?cmd=GPIO,xx,1"')
os.execute('curl "http://192.168.x.xx/control?cmd=GPIO,xx,1"')
os.execute('curl "http://192.168.x.xx/control?cmd=GPIO,xx,1"')
os.execute('curl "http://192.168.x.xx/control?cmd=GPIO,xx,1"')
end
if (devicechanged['IrrigZone2'] == 'On') then
os.execute('curl "http://192.168.x.xx/control?cmd=GPIO,xx,1"')
os.execute('curl "http://192.168.x.xx/control?cmd=GPIO,xx,1"')
os.execute('curl "http://192.168.x.xx/control?cmd=GPIO,xx,1"')
os.execute('curl "http://192.168.x.xx/control?cmd=GPIO,xx,0"')
elseif (devicechanged['IrrigZone2'] == 'Off') then
os.execute('curl "http://192.168.x.xx/control?cmd=GPIO,xx,1"')
os.execute('curl "http://192.168.x.xx/control?cmd=GPIO,xx,1"')
os.execute('curl "http://192.168.x.xx/control?cmd=GPIO,xx,1"')
os.execute('curl "http://192.168.x.xx/control?cmd=GPIO,xx,1"')
end
if (devicechanged['IrrigZone3'] == 'On') then
os.execute('curl "http://192.168.x.xx/control?cmd=GPIO,xx,1"')
os.execute('curl "http://192.168.x.xx/control?cmd=GPIO,xx,1"')
os.execute('curl "http://192.168.x.xx/control?cmd=GPIO,xx,1"')
os.execute('curl "http://192.168.x.xx/control?cmd=GPIO,xx,0"')
elseif (devicechanged['IrrigZone3'] == 'Off') then
os.execute('curl "http://192.168.x.xx/control?cmd=GPIO,xx,1"')
os.execute('curl "http://192.168.x.xx/control?cmd=GPIO,xx,1"')
os.execute('curl "http://192.168.x.xx/control?cmd=GPIO,xx,1"')
os.execute('curl "http://192.168.x.xx/control?cmd=GPIO,xx,1"')
end
if (devicechanged['IrrigZone4'] == 'On') then
os.execute('curl "http://192.168.x.xx/control?cmd=GPIO,xx,1"')
os.execute('curl "http://192.168.x.xx/control?cmd=GPIO,xx,1"')
os.execute('curl "http://192.168.x.xx/control?cmd=GPIO,xx,1"')
os.execute('curl "http://192.168.x.xx/control?cmd=GPIO,xx,0"')
elseif (devicechanged['IrrigZone4'] == 'Off') then
os.execute('curl "http://192.168.x.xx/control?cmd=GPIO,xx,1"')
os.execute('curl "http://192.168.x.xx/control?cmd=GPIO,xx,1"')
os.execute('curl "http://192.168.x.xx/control?cmd=GPIO,xx,1"')
os.execute('curl "http://192.168.x.xx/control?cmd=GPIO,xx,1"')
end
return commandArray
And now some help request:
I have defined the function
This function doesn't need (?) a parameter, but I haven't found a way to declare without it and to call it without.
Main issue instead is related to the bash script call. I've done it thru
Code: Select all
-- Now call the bash irrigation script with irrigation time per zone
comando="/home/pi/domoticz/scripts/irrigation.sh "..minuti_irrig1..' '..minuti_irrig2..' '..minuti_irrig3..' '..minuti_irrig4
os.execute(comando)
The os.execute do nothing or it does not call the bash script
I've tried copying the value of "comando" and execute it into a terminal and it works.
It's like "/home/pi/domoticz/scripts/irrigation.sh 10 8 0 4"
Weird thing is this.
I tried grabbing only some code from the main one and it works.
Only difference is that the "local_uservar" is not taken from Calendar Event, but is in the same format.
What can be the issue?
Code: Select all
commandArray = {}
local_uservar = "IRRIG,10,0,8,4"
-- function to split the string comma separated
function string:split( inSplitPattern, outResults )
if not outResults then
outResults = { }
end
local theStart = 1
local theSplitStart, theSplitEnd = string.find( self, inSplitPattern, theStart )
while theSplitStart do
table.insert( outResults, string.sub( self, theStart, theSplitStart-1 ) )
theStart = theSplitEnd + 1
theSplitStart, theSplitEnd = string.find( self, inSplitPattern, theStart )
end
table.insert( outResults, string.sub( self, theStart ) )
return outResults
end
-- Split the Event to check if this is an irrigation event and grab the activation minutes per zone
local CalEvent = local_uservar:split(",")
-- If the first element is not "Irrig" it's not an irrigation event. Exit
if ((CalEvent[1] ~= "IRRIG") or (#CalEvent ~= 5)) then
return
end
local minuti_irrig1 = 0
local minuti_irrig2 = 0
local minuti_irrig3 = 0
local minuti_irrig4 = 0
-- If all is ok, define minutes per zone
minuti_irrig1 = tostring(CalEvent[2])
minuti_irrig2 = tostring(CalEvent[3])
minuti_irrig3 = tostring(CalEvent[4])
minuti_irrig4 = tostring(CalEvent[5])
-- Now call the bash irrigation script with irrigation time per zone
comando="/home/osmc/domoticz/scripts/irrigation.sh "..minuti_irrig1..' '..minuti_irrig2..' '..minuti_irrig3..' '..minuti_irrig4
os.execute(comando)
return commandArray