diff options
Diffstat (limited to 'tex/context/base/mkiv/util-evo.lua')
-rw-r--r-- | tex/context/base/mkiv/util-evo.lua | 847 |
1 files changed, 647 insertions, 200 deletions
diff --git a/tex/context/base/mkiv/util-evo.lua b/tex/context/base/mkiv/util-evo.lua index eeaad5843..25ad7f94d 100644 --- a/tex/context/base/mkiv/util-evo.lua +++ b/tex/context/base/mkiv/util-evo.lua @@ -14,88 +14,176 @@ if not modules then modules = { } end modules ['util-evo'] = { -- later). Anyway, apart from integrating it into my home automation setup so that I -- can add control based on someone present in a zone, I wanted to be able to render -- statistics. So that's why we have a module in ConTeXt for doing that. It's also --- an example of Lua. +-- an example of Lua and abusing LuaTeX for something not related to typesetting. -- -- As with other scripts, it assumes that mtxrun is used so that we have the usual --- libraries present. +-- Lua libraries present. -- -- The code is not that complex but figuring out the right request takes bit of -- searching the web. There is an api specification at: -- --- https://developer.honeywell.com/api-methods?field_smart_method_tags_tid=All +-- https://developer.honeywell.com/api-methods?field_smart_method_tags_tid=All -- --- Details like the application id can be found in several places. There are --- snippets of (often partial or old) code on discussion platforms so in the one can --- get there. +-- Details like the application id can be found in several places. There are snippets +-- of (often partial or old) code on the web but still one needs to experiment and +-- combine information. We assume unique zone names and ids across gateways; I only +-- have one installed anyway. +-- +-- The original application was to just get the right information for generating +-- statistics but in the meantime I also use this code to add additional functionality +-- to the system, for instance switching between rooms (office, living room, attic) and +-- absence for one or more rooms. --- todo: load everything and keep it in mem and only save it when there are changes --- todo: use a temp files per month -- todo: %path% in filenames require("util-jsn") +local next, type, setmetatable, rawset, rawget = next, type, setmetatable, rawset, rawget local json = utilities.json local formatters = string.formatters local floor, div = math.floor, math.div local resultof, ostime, osdate, ossleep = os.resultof, os.time, os.date, os.sleep local jsontolua, jsontostring = json.tolua, json.tostring -local savetable, loadtable = table.save, table.load -local setmetatableindex = table.setmetatableindex +local savetable, loadtable, sortedkeys = table.save, table.load, table.sortedkeys +local setmetatableindex, setmetatablenewindex = table.setmetatableindex, table.setmetatablenewindex local replacer = utilities.templates.replacer +local lower = string.lower -- no utf support yet (encoding needs checking in evohome) local applicationid = "b013aa26-9724-4dbd-8897-048b9aada249" ----- applicationid = "91db1612-73fd-4500-91b2-e63b069b185c" local report = logs.reporter("evohome") +local trace = false + +trackers.register("evohome.trace",function(v) trace = v end) -- not yet used local defaultpresets = { interval = 30 * 60, + files = { + everything = "evohome-everything.lua", + history = "evohome-history.lua", + latest = "evohome-latest.lua", + schedules = "evohome-schedules.lua", + actions = "evohome-actions.lua", + template = "evohome.lmx", + }, credentials = { -- username = "unset", -- password = "unset", -- accesstoken = "unset", -- userid = "unset", }, - -- everything = "evohome-everything", - -- history = "evohome-history", } +local function validfile(presets,filename) + if lfs.isfile(filename) then + -- we're okay + return filename + end + if file.pathpart(filename) ~= "" then + -- can be a file that has to be created + return filename + end + local presetsname = presets.filename + if not presetsname then + -- hope for the best + return filename + end + -- we now have the full path + return file.join(file.pathpart(presetsname),filename) +end + local function validpresets(presets) - if type(presets == "table") and presets.credentials then - setmetatableindex(presets,defaultpresets) - setmetatableindex(presets.credentials,defaultpresets.credentials) - return presets - else - report("invalid presets") + if type(presets) ~= "table" then + report("invalid presets, no table") + return + end + local credentials = presets.credentials + if not credentials then + report("invalid presets, no credentials") + return + end + local gateways = presets.gateways + if not gateways then + report("invalid presets, no gateways") + return + end + local files = presets.files + if not files then + report("invalid presets, no files") + return + end + for k, v in next, files do + files[k] = validfile(presets,v) or v end + local data = presets.data + if not data then + data = { } + presets.data = data + end + local g = data.gateways + if not g then + local g = { } + data.gateways = g + for i=1,#gateways do + local gi = gateways[i] + g[gi.macaddress] = gi + end + end + local zones = data.zones + if not zones then + zones = { } + data.zones = zones + setmetatablenewindex(zones,function(t,k,v) rawset(t,lower(k),v) end) + setmetatableindex (zones,function(t,k) return rawget(t,lower(k)) end) + end + local states = data.states + if not states then + states = { } + data.states = states + setmetatablenewindex(states,function(t,k,v) rawset(t,lower(k),v) end) + setmetatableindex (states,function(t,k) return rawget(t,lower(k)) end) + end + setmetatableindex(presets,defaultpresets) + setmetatableindex(credentials,defaultpresets.credentials) + setmetatableindex(files,defaultpresets.files) + return presets end local function loadedtable(filename) - for i=1,10 do - local t = loadtable(filename) - if t then - return t - else - ossleep(1/4) + if type(filename) == "string" then + for i=1,10 do + local t = loadtable(filename) + if t then + return t + else + ossleep(1/4) + end end end return { } end local function loadpresets(filename) - return loadtable(filename) + local presets = loadtable(filename) + if presets then + presets.filename = filename + presets.filepath = file.expandname(file.pathpart(filename)) + -- package.extraluapath(presets.filepath) -- better do that elsewhere and once + end + return presets end local function loadhistory(filename) - if type(filename) == "table" then - filename = filename.history + if type(filename) == "table" and validpresets(filename) then + filename = filename.files and filename.files.history end return loadedtable(filename) end local function loadeverything(filename) - if type(filename) == "table" then - filename = filename.everything + if type(filename) == "table" and validpresets(filename) then + filename = filename.files and filename.files.everything end return loadedtable(filename) end @@ -137,9 +225,9 @@ local function getaccesstoken(presets) } local r = s and resultof(s) local t = r and jsontolua(r) - return result(t,"getting access token: %s") + return result(t,"getting access token %a") end - return result(false,"getting access token: %s") + return result(false,"getting access token %a") end local f = replacer ( @@ -160,9 +248,9 @@ local function getuserinfo(presets) } local r = s and resultof(s) local t = r and jsontolua(r) - return result(t,"getting user info: %s") + return result(t,"getting user info for %a") end - return result(false,"getting user info: %s") + return result(false,"getting user info for %a") end local f = replacer ( @@ -184,9 +272,9 @@ local function getlocationinfo(presets) } local r = s and resultof(s) local t = r and jsontolua(r) - return result(t,"getting location info: %s") + return result(t,"getting location info for %a") end - return result(false,"getting location info: %s") + return result(false,"getting location info for %a") end local f = replacer ( @@ -198,19 +286,22 @@ local f = replacer ( [["https://tccna.honeywell.com/WebAPI/emea/api/v1/temperatureZone/%zoneid%/schedule"]] ) -local function getschedule(presets,zoneid,zonename) - if zoneid and validpresets(presets) then - local c = presets.credentials - local s = c and f { - accesstoken = c.accesstoken, - applicationid = applicationid, - zoneid = zoneid, - } - local r = s and resultof(s) - local t = r and jsontolua(r) - return result(t,"getting schedule for zone %s: %s",zonename or "?") +local function getschedule(presets,zonename) + if validpresets(presets) then + local zoneid = presets.data.zones[zonename].zoneId + if zoneid then + local c = presets.credentials + local s = c and f { + accesstoken = c.accesstoken, + applicationid = applicationid, + zoneid = zoneid, + } + local r = s and resultof(s) + local t = r and jsontolua(r) + return result(t,"getting schedule for zone %a, %s",zonename or "?") + end end - return result(false,"getting schedule for zone %s: %s",zonename or "?") + return result(false,"getting schedule for zone %a, %s",zonename or "?") end local f = replacer ( @@ -232,29 +323,128 @@ local function getstatus(presets,locationid,locationname) } local r = s and resultof(s) local t = r and jsontolua(r) - return result(t and t.gateways and t,"getting status for location %s: %s",locationname or "?") + return result(t and t.gateways and t,"getting status for location %a, %s",locationname or "?") end - return result(false,"getting status for location %s: %s",locationname or "?") + return result(false,"getting status for location %a, %s",locationname or "?") end local function validated(presets) if validpresets(presets) then - local data = getaccesstoken(presets) - if data then - presets.credentials.accesstoken = data.access_token - local data = getuserinfo(presets) + local data = getlocationinfo(presets) + if data and type(data) == "table" and data[1] and data[1].locationInfo then + return true + else + local data = getaccesstoken(presets) if data then - presets.credentials.userid = data.userId - return true + presets.credentials.accesstoken = data.access_token + local data = getuserinfo(presets) + if data then + presets.credentials.userid = data.userId + return true + end + end + end + end +end + +local function findzone(presets,name) + if not presets then + return + end + local data = presets.data + if not data then + return + end + local usedzones = data.zones + return usedzones and usedzones[name] +end + +local function gettargets(zone) -- maybe also for a day + local schedule = zone.schedule + local min = false + local max = false + if schedule then + local schedules = schedule.dailySchedules + if schedules then + for i=1,#schedules do + local switchpoints = schedules[i].switchpoints + for i=1,#switchpoints do + local m = switchpoints[i].temperature + if not min or m < min then + min = m + end + if not max or m > max then + max = m + end + end + end + else + report("zone %a has no schedule",name) + end + end + return min, max +end + +local function updatezone(presets,name,zone) + if not zone then + zone = findzone(presets,name) + end + if zone then + local oldtarget = presets.data.states[name] + local min = zone.heatSetpointCapabilities.minHeatSetpoint or 5 + local max = zone.heatSetpointCapabilities.maxHeatSetpoint or 12 + local mintarget, maxtarget = gettargets(zone) + -- todo: maybe get these from presets + if mintarget == false then + if min < 5 then + mintarget = 5 + -- report("zone %a, min target limited to %a",name,mintarget) + else + mintarget = min + end + end + if maxtarget == false then + if max > 18.5 then + maxtarget = 18.5 + -- report("zone %a, max target limited to %a",name,maxtarget) + else + maxtarget = max end end + local current = zone.temperatureStatus.temperature or 0 + local target = zone.heatSetpointStatus.targetTemperature + local mode = zone.heatSetpointStatus.setpointMode + local state = (mode == "FollowSchedule" and "schedule" ) or + (mode == "PermanentOverride" and target <= mintarget and "permanent") or + (mode == "TemporaryOverride" and target <= mintarget and "off" ) or + (mode == "TemporaryOverride" and target >= maxtarget and "on" ) or + ( "unknown" ) + local t = { + name = zone.name, + id = zone.zoneId, + schedule = zone.schedule, + mode = mode, + current = current, + target = target, + min = min, + max = max, + state = state, + lowest = mintarget, + highest = maxtarget, + } + -- report("zone %a, current %a, target %a",name,current,target) + presets.data.states[name] = t + return t end end -local function geteverything(presets,filename) + +local function geteverything(presets,noschedules) if validated(presets) then local data = getlocationinfo(presets) if data then + local usedgateways = presets.data.gateways + local usedzones = presets.data.zones for i=1,#data do local gateways = data[i].gateways local locationinfo = data[i].locationInfo @@ -263,48 +453,63 @@ local function geteverything(presets,filename) local status = getstatus(presets,locationid,locationinfo.name) if status then for i=1,#gateways do - local g = status.gateways[i] - local gateway = gateways[i] - local systems = gateway.temperatureControlSystems - if systems then - local s = g.temperatureControlSystems - for i=1,#systems do - local zones = systems[i].zones - if zones then - local z = s[i].zones - for i=1,#zones do - local zone = zones[i] - if zone.zoneType == "ZoneTemperatureControl" then - local z = z[i] - zone.schedule = getschedule(presets,zone.zoneId,zone.name) - if z.name == zone.name then - zone.heatSetpointStatus = z.heatSetpointStatus - zone.temperatureStatus = z.temperatureStatus + local gatewaystatus = status.gateways[i] + local gatewayinfo = gateways[i] + local gatewaysystems = gatewayinfo.temperatureControlSystems + local info = gatewayinfo.gatewayInfo + local statussystems = gatewaystatus.temperatureControlSystems + if gatewaysystems and statussystems and info then + local mac = info.mac + if usedgateways[mac] then + report("%s gateway with mac address %a","using",mac) + for j=1,#gatewaysystems do + local gatewayzones = gatewaysystems[j].zones + local zonestatus = statussystems[j].zones + if gatewayzones and zonestatus then + for k=1,#gatewayzones do + local zonestatus = zonestatus[k] + local gatewayzone = gatewayzones[k] + if zonestatus and gatewayzone then + local zonename = zonestatus.name + local zoneid = zonestatus.zoneId + if gatewayzone.zoneType == "ZoneTemperatureControl" and zonename == gatewayzone.name then + gatewayzone.heatSetpointStatus = zonestatus.heatSetpointStatus + gatewayzone.temperatureStatus = zonestatus.temperatureStatus + local zonestatus = usedzones[zonename] -- findzone(states,zonename) + local schedule = zonestatus and zonestatus.schedule + usedzones[zonename] = gatewayzone + if schedule and noschedules then + gatewayzone.schedule = schedule + else + gatewayzone.schedule = getschedule(presets,zonename) + end + updatezone(presets,zonename,gatewayzone) + end end end end end + else + report("%s gateway with mac address %a","skipping",mac) end end end end end end - if not filename then - filename = presets.everything - end - if filename then - savetable(filename,data) - end - return result(data,"getting everything: %s") + savetable(presets.files.everything,data) + return result(data,"getting everything, %s") end end - return result(false,"getting everything: %s") + return result(false,"getting everything, %s") end -local function gettemperatures(presets,filename) +local function gettemperatures(presets) if validated(presets) then - local data = loadeverything(filename or presets) + local data = loadeverything(presets) + if not data or not next(data) then + data = geteverything(presets) + end if data then local updated = false for i=1,#data do @@ -341,14 +546,14 @@ local function gettemperatures(presets,filename) end end end - if updated and filename then + if updated then data.time = ostime() - savetable(filename,data) + savetable(presets.files.latest,data) end - return result(data,"getting temperatures: %s") + return result(data,"getting temperatures, %s") end end - return result(false,"getting temperatures: %s") + return result(false,"getting temperatures, %s") end local function setmoment(target,time,data) @@ -389,98 +594,72 @@ local function setmoment(target,time,data) } end -local function loadtemperatures(filename) - local status = loadeverything(filename) - if status then - setmetatable(status,mt) - local zones = status[1].gateways[1].temperatureControlSystems[1].zones - if zones then - local summary = { time = status.time } - for i=1,#zones do - local zone = zones[i] - if zone.modelType == "HeatingZone" then - local temperatureStatus = zone.temperatureStatus - local heatSetpointCapabilities = zone.heatSetpointCapabilities - local heatSetpointStatus = zone.heatSetpointStatus - summary[#summary+1] = { - name = zone.name, - current = temperatureStatus and temperatureStatus .temperature or 0, - min = heatSetpointCapabilities and heatSetpointCapabilities.minHeatSetpoint or 0, - max = heatSetpointCapabilities and heatSetpointCapabilities.maxHeatSetpoint or 0, - target = heatSetpointStatus and heatSetpointStatus .targetTemperature or 0, - } +local function loadtemperatures(presets) + if validpresets(presets) then + local status = loadeverything(presets) + if status then + local usedgateways = presets.data.gateways + for i=1,#status do + local gateways = status[i].gateways + if gateways then + for i=1,#gateways do + local gatewayinfo = gateways[i] + local systems = gatewayinfo.temperatureControlSystems + local info = gatewayinfo.gatewayInfo + if systems and info and usedgateways[info.mac] then + for i=1,#systems do + local zones = systems[i].zones + if zones then + local summary = { time = status.time } + for i=1,#zones do + local zone = zones[i] + if zone.zoneType == "ZoneTemperatureControl" then + summary[#summary+1] = updatezone(presets,zone.name,zone) + end + end + return result(summary,"loading temperatures, %s") + end + end + end + end end end - return result(summary,"loading temperatures: %s") end end - return result(false,"loading temperatures: %s") + return result(false,"loading temperatures, %s") end -local function updatetemperatures(presets,filename,historyname) +local function updatetemperatures(presets) if validpresets(presets) then - if not filename then - filename = presets.everything - end - if not historyname then - historyname = presets.history - end - gettemperatures(presets,filename) - local t = loadtemperatures(filename) - if t then - local data = { } - for i=1,#t do - local ti = t[i] - data[ti.name] = ti.current - end - local history = loadhistory(historyname) or { } - setmoment(history,ostime(),data) - savetable(historyname,history) - return result(t,"updating temperatures: %s") - end - end - return result(false,"updating temperatures: %s") -end - -local mt = { __index = { [1] = { gateways = { [1] = { temperatureControlSystems = { [1] = { } } } } } } } - -local function findzone(status,name) - if status then - setmetatable(status,mt) - local zones = status[1].gateways[1].temperatureControlSystems[1].zones - if zones then - for i=1,#zones do - local zone = zones[i] - if zone.modelType == "HeatingZone" and zone.name == name then - return zone + local everythingname = presets.files.everything + local historyname = presets.files.history + if everythingname and historyname then + gettemperatures(presets,everythingname) + local t = loadtemperatures(presets) + if t then + local data = { } + for i=1,#t do + local ti = t[i] + data[ti.name] = ti.current end + local history = loadhistory(historyname) or { } + setmoment(history,ostime(),data) + savetable(historyname,history) + return result(t,"updating temperatures, %s") end end end + return result(false,"updating temperatures, %s") end -local function getzonestate(filename,name) - local status = loadeverything(filename) - local zone = findzone(status,name) - if zone then - local t = { - name = zone.name, - current = zone.temperatureStatus.temperature or 0, - min = zone.heatSetpointCapabilities.minHeatSetpoint, - max = zone.heatSetpointCapabilities.maxHeatSetpoint, - target = zone.heatSetpointStatus.targetTemperature, - mode = zone.heatSetpointStatus.setpointMode, - schedule = zone.schedule, - } - return result(t,"getting state of zone %s: %s",name) - end - return result(false,"getting state of zone %s: %s",name) +local function getzonestate(presets,name) + return validpresets(presets) and presets.data.states[name] end local f = replacer ( [[curl ]] .. - [[-X PUT ]] .. [[--silent --insecure ]] .. + [[-X PUT ]] .. [[-H "Authorization: bearer %accesstoken%" ]] .. [[-H "Accept: application/json, application/xml, text/json, text/x-json, text/javascript, text/xml" ]] .. [[-H "applicationId: %applicationid%" ]] .. @@ -489,62 +668,330 @@ local f = replacer ( [["https://tccna.honeywell.com/WebAPI/emea/api/v1/temperatureZone/%zoneid%/heatSetpoint"]] ) -local function setzonestate(presets,name,temperature) - if validated(presets) then - local data = loadeverything(presets) - local zone = findzone(data,name) - if zone then - local m = type(temperature) == "number" and temperature > 0 and - { +local function untilmidnight() + local t = osdate("*t") + t.hour = 23 + t.min = 59 + t.sec = 59 + return osdate("%Y-%m-%dT%H:%M:%SZ",ostime(t)) +end + +local followschedule = { + -- HeatSetpointValue = 0, + SetpointMode = "FollowSchedule", +} + +local function setzonestate(presets,name,temperature,permanent) + local zone = findzone(presets,name) + if zone then + local m = followschedule + if type(temperature) == "number" and temperature > 0 then + if permanent then + m = { HeatSetpointValue = temperature, - SetpointMode = "TemporaryOverride", - TimeUntil = osdate("%Y-%m-%dT%H:%M:%SZ",os.time() + 60*60), + SetpointMode = "PermanentOverride", } - or - { - HeatSetpointValue = 0, - SetpointMode = "FollowSchedule", + else + m = { + HeatSetpointValue = temperature, + SetpointMode = "TemporaryOverride", + TimeUntil = untilmidnight(), } + end + end + local s = f { + accesstoken = presets.credentials.accesstoken, + applicationid = applicationid, + zoneid = zone.zoneId, + settings = jsontostring(m), + } + local r = s and resultof(s) + local t = r and jsontolua(r) +-- inspect(r) +-- inspect(t) + return result(t,"setting state of zone %a, %s",name) + end + return result(false,"setting state of zone %a, %s",name) +end - local s = f { - accesstoken = presets.credentials.accesstoken, - applicationid = applicationid, - zoneid = zone.zoneId, - settings = jsontostring(m), +local function resetzonestate(presets,name) + setzonestate(presets,name) +end + +-- + +local function update(presets,noschedules) + local everything = geteverything(presets,noschedules) + if everything then + presets.data.everything = everything + return presets + end +end + +local function initialize(filename) + local presets = loadpresets(filename) + if presets then + return update(presets) + end +end + +local function off(presets,name) + local zone = presets and getzonestate(presets,name) + if zone then + setzonestate(presets,name,zone.lowest) + end +end + +local function on(presets,name) + local zone = presets and getzonestate(presets,name) + if zone then + setzonestate(presets,name,zone.highest) + end +end + +local function schedule(presets,name) + local zone = presets and getzonestate(presets,name) + if zone then + resetzonestate(presets,name) + end +end + +local function permanent(presets,name) + local zone = presets and getzonestate(presets,name) + if zone then + setzonestate(presets,name,zone.lowest,true) + end +end + +-- tasks + +local function settask(presets,when,tag,action) + if when == "tomorrow" then + local list = presets.scheduled + if not list then + list = loadtable(presets.files.schedules) or { } + presets.scheduled = list + end + if action then + list[tag] = { + time = ostime() + 24*60*60, + done = false, + category = category, + action = action, } - local r = s and resultof(s) - local t = r and jsontolua(r) - return result(t,"setting state of zone %s: %s",name) + else + list[tag] = nil + end + savetable(presets.files.schedules,list) + end +end + +local function gettask(presets,when,tag) + if when == "tomorrow" then + local list = presets.scheduled + if not list then + list = loadtable(presets.files.schedules) or { } + presets.scheduled = list + end + return list[tag] + end +end + +local function resettask(presets,when,tag) + settask(presets,when,tag) +end + +local function checktasks(presets) + local list = presets.scheduled + if not list then + list = loadtable(presets.files.schedules) or { } + presets.scheduled = list + end + if list then + local t = osdate("*t") + local q = { } + for k, v in next, list do + local d = osdate("*t",v.time) + if not v.done and d.year == t.year and d.month == t.month and d.day == t.day then + local a = v.action + if type(a) == "function" then + a() + end + v.done = true + end + if d.year <= t.year and d.month <= t.month and d.day < t.day then + q[k] = true + end end + if next(q) then + for k, v in next, q do + list[q] = nil + end + savetable(presets.files.schedules,list) + end + return list end - return result(false,"setting state of zone %s: %s",name) end -local evohome = { +-- predefined tasks + +local function settomorrow(presets,tag,action) + settask(presets,"tomorrow",tag,action) +end + +local function resettomorrow(presets,tag) + settask(presets,"tomorrow",tag) +end + +local function tomorrowset(presets,tag) + return gettask(presets,"tomorrow",tag) and true or false +end + +-- + +local evohome + +local function poller(presets) + -- + if type(presets) ~= "string" then + report("invalid presets file") + os.exit() + end + report("loading presets from %a",presets) + local presets = loadpresets(presets) + if not validpresets(presets) then + report("invalid presets, aborting") + os.exit() + end + -- + local actions = presets.files.actions + if type(actions) ~= "string" then + report("invalid actions file") + os.exit() + end + report("loading actions from %a",actions) + local actions = loadtable(actions) + if type(actions) ~= "table" then + report("invalid actions, aborting") + os.exit() + end + actions = actions.actions + if type(actions) ~= "table" then + report("invalid actions file, no actions subtable") + os.exit() + end + -- + report("updating device status") + update(presets) + -- + presets.report = report + presets.evohome = evohome + presets.results = { } + -- + function presets.getstate(name) + return getzonestate(presets,name) + end + function presets.tomorrowset(name) + return tomorrowset(presets,name) + end + -- + local template = actions.template or presets.files.template + -- + local process = function(t) + local category = t.category + local action = t.action + if category and action then + local c = actions[category] + if c then + local a = c[action] + if type(a) == "function" then + report("category %a, action %a, executing",category,action) + presets.results.template = template -- can be overloaded by action + a(presets) + update(presets,true) + else + report("category %a, action %a, invalid action, known: %, t",category,action,sortedkeys(c)) + end + else + report("category %a, action %a, invalid category, known categories: %, t",category,action,sortedkeys(actions)) + end + else + -- logs.report("invalid category and action") + end + end + -- + local delay = presets.delay or 10 + local interval = 15 * 60 -- 15 minutes + local interval = 60 * 60 -- 60 minutes + local refresh = 5 * 60 + local passed = 0 + local step = function() + if passed > interval then + report("refreshing states, every %i seconds",interval) + -- todo: update stepwise as this also updates the schedules that we don't really + -- change often and definitely not in the middle of the night, so maybe just + -- update 9:00 12:00 15:00 18:00 21:00 + update(presets) + passed = 0 + else + passed = passed + delay + end + checktasks(presets) + return delay + end + -- + presets.refreshtime = refresh + -- + return step, process, presets +end + +-- + +evohome = { helpers = { - getaccesstoken = getaccesstoken, - getuserinfo = getuserinfo, - getlocationinfo = getlocationinfo, - getschedule = getschedule, + getaccesstoken = getaccesstoken, -- presets + getuserinfo = getuserinfo, -- presets + getlocationinfo = getlocationinfo, -- presets + getschedule = getschedule, -- presets, name + -- + geteverything = geteverything, -- presets, noschedules + gettemperatures = gettemperatures, -- presets + getzonestate = getzonestate, -- presets, name + setzonestate = setzonestate, -- presets, name, temperature + resetzonestate = resetzonestate, -- presets, name + getzonedata = findzone, -- presets, name + -- + loadpresets = loadpresets, -- filename + loadhistory = loadhistory, -- presets | filename + loadeverything = loadeverything, -- presets | filename + loadtemperatures = loadtemperatures, -- presets | filename + -- + updatetemperatures = updatetemperatures, -- presets }, - geteverything = geteverything, - gettemperatures = gettemperatures, - getzonestate = getzonestate, - setzonestate = setzonestate, - loadtemperatures = loadtemperatures, - updatetemperatures = updatetemperatures, - loadpresets = loadpresets, - loadhistory = loadhistory, - loadeverything = loadeverything, + actions= { + initialize = initialize, -- filename + update = update, -- presets + -- + off = off, -- presets, name + on = on, -- presets, name + schedule = schedule, -- presets, name + permanent = permanent, -- presets, name + -- + settomorrow = settomorrow, -- presets, tag, function + resettomorrow = resettomorrow, -- presets, tag + tomorrowset = tomorrowset, -- presets, tag + -- + poller = poller, -- presets + } } if utilities then utilities.evohome = evohome end --- local presets = evohome.loadpresets("c:/data/develop/domotica/code/evohome-presets.lua") --- evohome.setzonestate(presets,"Voorkamer",22) --- evohome.setzonestate(presets,"Voorkamer") +-- local presets = evohome.helpers.loadpresets("c:/data/develop/domotica/code/evohome-presets.lua") +-- evohome.helpers.setzonestate(presets,"Voorkamer",22) +-- evohome.helpers.setzonestate(presets,"Voorkamer") return evohome |