LogicMachine as gateway to IrrigationCaddy sprinkler system
Example: LogicMachine as gateway to IrrigationCaddy sprinkler system
Task
This examples will show how to integrate/control IrrigationCaddy sprinkler system into common KNX/ModBus/BACnet/EnOCean/DALI network through LogicMachine.
IrrigationCaddy user library
Add this program to Scripting –> User Libraries
- --------------------------------------------------------------------------------
- -- LUA IrrigationCaddy control module.
- -- A module to control and monitor IrrigationCaddy controller
- --
- -- @module irrigationcaddy
- -- @return #irrigationcaddy
-
- ---@type luavbus
-
- local irrigationcaddy = {}
-
- irrigationcaddy.__index = irrigationcaddy
- ---
- -- IP or hostname of irrigationcaddy
- --
- -- @field [parent=#irrigationcaddy] #string IP or hostname
- irrigationcaddy.ip = ""
- ---
- -- user of irrigationcaddy
- --
- -- @field [parent=#irrigationcaddy] #string username
- irrigationcaddy.login = nil
- ---
- -- Password of irrigationcaddy
- --
- -- @field [parent=#irrigationcaddy] #string password
- irrigationcaddy.password = nil
-
- -- Status
- ---
- -- Statusof irrigationcadd
- --
- -- @field [parent=#irrigationcaddy] #number 0 disable 1 enabled
- irrigationcaddy.allowRun = 0
- irrigationcaddy.zoneNumber = 0
- irrigationcaddy.progNumber = 0
- irrigationcaddy.progSecLeft = 0
- irrigationcaddy.zoneSecLeft = 0
-
- json = require('cjson')
- socket = require('socket')
- require('socket.http')
- require("ltn12")
-
- --- Creates and issue HTTP post query
- -- @author Luca Palazzo
- -- @return res result of HTTP query, err in case of errors
- --
- function irrigationcaddy.query ( uri, reqbody )
- irrigationcaddy.log(DEBUG3, "irrigationcaddy.query("..uri.."): query irrigationcaddy" )
-
- url = string.format('http://%s/%s', irrigationcaddy.ip, uri)
- if ( reqbody ~= nil and url ~= nil ) then
- irrigationcaddy.log(DEBUG3, "irrigationcaddy.query("..url.."): query with POST" )
-
- res, err, header = socket.http.request{
- url = url,
- method = "POST",
- headers = {
- ["Content-Type"] = "application/x-www-form-urlencoded",
- ['Content-Length'] = string.len(reqbody)
- },
- source = ltn12.source.string(reqbody),
- sink = ltn12.sink.table(respbody)
- }
- elseif ( url ~= nil ) then
- irrigationcaddy.log(DEBUG3, "irrigationcaddy.query("..url.."): query without POST" )
- res, err = socket.http.request(url)
- else
- print ( "Nil request" )
- return nil
- end
- irrigationcaddy.log(DEBUG3, "irrigationcaddy.query("..url.."): url ".. url )
-
- return res, err
-
- end
-
- --- Creates a new instance of irrigationcaddy
- -- @author Luca Palazzo
- -- @return instance of irrigationcaddy
- --
- function irrigationcaddy.new ( ip, login, password )
- local _irrigationcaddy = {}
- setmetatable(_irrigationcaddy,irrigationcaddy)
- if ( ip ~= nil and login ~= nil and password ~= nil ) then
- irrigationcaddy.log(DEBUG3, "irrigationcaddy.new("..ip..", "..login..", "..password.."): creating new instance of irrigationcaddy" )
- _irrigationcaddy.ip = ip
- _irrigationcaddy.login = login
- _irrigationcaddy.password = password
- elseif ( ip ~= nil ) then
- irrigationcaddy.log(DEBUG3, "irrigationcaddy.new("..ip.."): creating new instance of irrigatincaddy" )
- _irrigationcaddy.ip = ip
- else
- irrigationcaddy.log(DEBUG3, "irrigationcaddy.new(): creating new instance of irrigationcaddy" )
- end
- return _irrigationcaddy
- end
-
-
- --- Prints the status of irrigationcaddy
- -- @author Luca Palazzo
- -- @return status string of irrigationcaddy
- --
- function irrigationcaddy.print ( ... )
- irrigationcaddy.log(DEBUG3, "irrigationcaddy.print(): printing irrigationcaddy status" )
- status_string = string.format ( "Status %s program %s zone %s prog left %s zone left %s", irrigationcaddy.allowRun, irrigationcaddy.progNumber, irrigationcaddy.zoneNumber, irrigationcaddy.progSecLeft, irrigationcaddy.zoneSecLeft )
-
- irrigationcaddy.log(DEBUG3, string.format ( "irrigationcaddy.print(): status %s", status_string ) )
-
- return status_string
-
- end
-
- --- Updates the status from irrigationcaddy
- -- @author Luca Palazzo
- -- @return true on successfull update, false in case of error
- --
- function irrigationcaddy.update ( ... )
- irrigationcaddy.log(DEBUG3, "irrigationcaddy.update(): getting irrigationcaddy status" )
-
- res,err = irrigationcaddy.query ( "status.json" )
-
- if res then
- jsonstatus = json.decode(res)
- status = jsonstatus['allowRun']
- irrigationcaddy.allowRun = jsonstatus['allowRun']
- irrigationcaddy.zoneNumber = jsonstatus['zoneNumber']
- irrigationcaddy.progNumber = jsonstatus['progNumber']
- irrigationcaddy.progSecLeft = jsonstatus['progSecLeft']
- irrigationcaddy.zoneSecLeft = jsonstatus['zoneSecLeft']
- irrigationcaddy.log ( 5, string.format ( "irrigationcaddy.update(): Status %s program %s zone %si prog left %s zone left %s", irrigationcaddy.allowRun, irrigationcaddy.progNumber, irrigationcaddy.zoneNumber, irrigationcaddy.progSecLeft, irrigationcaddy.zoneSecLeft ) )
- return true
- end
-
- irrigationcaddy.log ( ERR, "Error getting JSON" )
- return false
-
- end
-
- --- Gets the calendar scheduled action of irrigationcaddy
- -- @author Luca Palazzo
- -- @return a table containing
- --
- function irrigationcaddy.get_calendar ( calendarperiod )
- irrigationcaddy.log(DEBUG3, "irrigationcaddy.get_calendar(): getting irrigationcaddy calendar status" )
-
- local cal_start_time = os.time();
- if ( calendarperiod == nil or type(calendarperiod) ~= "number" ) then
- local cal_end_time = cal_start_time + 3600*24*2;
- else
- cal_end_time = calendarperiod
- end
-
-
- uri = string.format('calendar.json?start=%d&end=%d', cal_start_time, cal_end_time)
- res, err = irrigationcaddy.query( uri, reqbody )
-
- if res then
- calendar = json.decode(res)
- if ( type(calendar) ~= 'table' ) then
- irrigationcaddy.log(DEBUG1, string.format ( "irrigationcaddy.get_calendar(): calendar not a table" ) )
- return false
- end
- for k, v in pairs ( calendar ) do
- if ( calendar[k]["title"] == nil ) then
- irrigationcaddy.log(DEBUG1, string.format ( "irrigationcaddy.get_calendar(): nil calndar voice" ) )
- else
- irrigationcaddy.log(DEBUG3, string.format ( "irrigationcaddy.get_calendar(): Program: %s next start %s ends %s ", calendar[k]["title"], calendar[k]["start"], calendar[k]["end"] ) )
- end
- end
- return calendar, err
- else
- log ( "Error getting JSON" )
- return nil, err
- end
- end
-
- --- Gets the time of irrigationcaddy
- -- @author Luca Palazzo
- -- @return a timestamp, or nil and err in case of error
- --
- function irrigationcaddy.time ()
- irrigationcaddy.log(DEBUG3, "irrigationcaddy.time(): getting time from device" )
-
- uri = string.format('dateTime.json')
-
- res, err = irrigationcaddy.query( uri, reqbody )
-
- if res then
- time = json.decode(res)
- -- log ( dump ( calendar ) )
- if ( type(time) == 'table' ) then
- for k, v in pairs ( time ) do
- irrigationcaddy.log(DEBUG3, string.format ( "irrigationcaddy.time(): %s %s", tostring(k), tostring(v) ) )
- end
- ictime = os.time({day=time.day,month=time.month,year="20"..time.year,hour=time.hr,min=time.min,sec=time.sec})
- irrigationcaddy.log(DEBUG3, string.format ( "irrigationcaddy.time(): caddy's timestamp %d", ictime ) )
- return ictime, false
- else
- irrigationcaddy.log(DEBUG3, string.format ( "irrigationcaddy.time(): time not a table" ) )
- return nil
- end
- end
-
- log ( "Error getting JSON" )
- return nil, err
-
- end
-
- --- Gets the boot time of irrigationcaddy
- -- @author Luca Palazzo
- -- @return a timestamp, or nil and err in case of error
- --
- function irrigationcaddy.boottime ()
- irrigationcaddy.log(DEBUG3, "irrigationcaddy.boottime(): getting last boot from device" )
-
- uri = string.format('bootTime.json')
-
- res, err = irrigationcaddy.query( uri, reqbody )
-
-
- if res then
- boottime = json.decode(res)
- -- log ( dump ( calendar ) )
- if ( type(boottime) == 'table' ) then
- for k, v in pairs ( boottime ) do
- irrigationcaddy.log(DEBUG3, string.format ( "irrigationcaddy.boottime(): %s %s", tostring(k), tostring(v) ) )
- end
- icboottime = os.time({day=boottime.day,month=boottime.month,year="20"..boottime.year,hour=boottime.hr,min=boottime.min,sec=boottime.sec})
- irrigationcaddy.log(DEBUG3, string.format ( "irrigationcaddy.time(): caddy boot's timestamp %d", icboottime ) )
-
- return boottime
- else
- irrigationcaddy.log(DEBUG3, string.format ( "irrigationcaddy.boottime(): boot time not a table" ) )
- return nil
- end
- end
- irrigationcaddy.log( INFO, "Error getting JSON" )
- return nil, err
- end
-
-
- --- Disable the system
- -- @author Luca Palazzo
- -- @return true in case of successful disable, false in case of error
- --
- function irrigationcaddy.disable ( ... )
- irrigationcaddy.log(DEBUG3, "irrigationcaddy.disable(): disabling" )
-
- uri = string.format('stopSprinklers.htm')
- reqbody = "stop=off"
-
- res, err = irrigationcaddy.query( uri, reqbody )
-
- irrigationcaddy.log(DEBUG3, "irrigationcaddy.disable(): return resource " .. res .. " error " .. err )
- if ( not err ) then
- return true
- end
-
- return false
- end
-
- --- Enable the system
- -- @author Luca Palazzo
- -- @return true in case of successful disable, false in case of error
- --
- function irrigationcaddy.enable ( ... )
- irrigationcaddy.log(DEBUG3, "irrigationcaddy.disable(): enabling" )
-
- uri = string.format('runSprinklers.htm')
- reqbody = "run=run"
-
- res, err = irrigationcaddy.query( uri, reqbody )
-
- if ( not err ) then
- return true
- end
-
- return false
-
- end
-
- ERR, WARN, INFO, DEBUG1, DEBUG2, DEBUG3, DEBUG4, DEBUG5 = 1, 2, 3, 4, 5, 6, 7, 8
-
- function irrigationcaddy.log ( level, ... )
- local prefix = ""
- local log_string = ""
- if ( log_level ~= nil and level ~= nil and level <= log_level ) then
- if ( level == ERR ) then
- log_string = "ERROR"
- elseif ( level == WARN ) then
- log_string = "WARN"
- elseif ( level == INFO ) then
- log_string = "INFO"
- elseif ( level == DEBUG1 ) then
- log_string = "DEBUG1"
- elseif ( level == DEBUG2 ) then
- log_string = "DEBUG2"
- elseif ( level == DEBUG3 ) then
- log_string = "DEBUG3"
- elseif ( level == DEBUG4 ) then
- log_string = "DEBUG4"
- elseif ( level == DEBUG5 ) then
- log_string = "DEBUG5"
- else
- log_string = "UNKNOWN"
- end
- print ( log_string .. ": " .. ... )
- end
- end
-
- return irrigationcaddy
TestIrrigationCaddy user library
- irrigationcaddy = require("irrigationcaddy")
- log_level = ERR
- irrigationcaddy.ip = "192.168.168.73"
- -- irrigationcaddy.disable()
- icboottimestamp = irrigationcaddy.boottime()
- schedules = irrigationcaddy.get_calendar()
- -- irrigationcaddy.enable()
- irrigationcaddy.update()
- ictimestamp = irrigationcaddy.time()
-
- irrigationcaddy.print()
Event-based script for updating status
- old_print = print
- debug_level = 0
- print = function(...)
- if ( verbose ) then
- log(...)
- end
- end
-
- irrigationcaddy = require("user.IrrigationCaddy")
- syslog_level = ERR
- verbose = false
-
-
- irrigationcaddy.ip = "192.168.1.100"
-
- irrigationcaddy.update()
-
- print ( string.format ( "IC status %s", irrigationcaddy.allowRun ) )
-
- ic = grp.getvalue ( '0/1/40' )
- ic_status = grp.getvalue ( '0/1/41' )
-
- if ( ic_status ~= irrigationcaddy.allowRun ) then
- print ( string.format ( "IC status (%s) different from device (%s)", tostring(ic_status), tostring(irrigationcaddy.allowRun) ) )
- grp.write ( '0/1/41', irrigationcaddy.allowRun, dt.boolean )
- end
Event-based script for updating the configuration
- irrigationcaddy = require("user.IrrigationCaddy")
- debug_level = 5
- verbose = true
-
-
- irrigationcaddy.ip = "192.168.168.73"
-
- ic = grp.getvalue ( '0/1/40' )
- ic_status = grp.getvalue ( '0/1/41' )
-
- print ( string.format ( 'Evento da %s per %s tipo %s', event['src'], event['dst'], event['type']) )
-
- group = event['dst']
-
- if ( group == '0/1/40' ) then
- if ( ic_status ~= ic ) then
- print ( string.format ( "Changing IC status (%s) to %s", tostring(ic_status), tostring(ic) ) )
- if ( ic == false ) then
- irrigationcaddy.disable()
- elseif ( ic == true ) then
- irrigationcaddy.enable()
- end
- grp.write( '0/1/49', true, dt.boolean )
- end
- end
Script that triggers the update
Where 0/1/49 is triggering group address
- log ( 'Triggering IC update' )
- grp.write('0/1/49', true, dt.boolean )
- return
Please consult LogicMachine forum IrrigationCaddy thread for more functionality and updated scripts.
Created by Luca Palazzo