--[[
%% autostart
%% properties
%% globals
--]]
--[[
MAIN SCENE FOR TIME BASED EVENTS CONTROL
Copyright © 2016 Zoran Sankovic - Sankotronic. All Rights Reserved.
Version 1.3.0
-- VERSION HISTORY
1.3.0 - cleaned some bugs, added some more checks to prevent scene from
stop running due to errors. Optimized and compacted code, removed
unnecessary comments. DemoMode only stops changing timers while
user code and scheduled events will continue to execute. Darkness
can now be changed by measured lux level or global variable that is
set to lux value measured by light measuring devices placed outside.
Scene is now running on setTimeout function instead on sleep for
better timing and also alignes to 0 seconds or exact minutes.
1.2.5 - since there was some misunderstanding with SleepState usage and
TimeOfDay setting, useSleepState is now added and by default set to
false. When useSleepState is set to false then Night will change to
Morning at surnise time adjusted by marginSunrise so if you wakeup
before sunrise then you will still be at Night. If useSleepState is
set to true then Night will change to Morning when SleepState is
set to Awake if it happen before sunrise time.
Some minor bug cleaning
1.2.4 - replaced functions for time calculation that are provided by
Fibaro international forum member @Tor Magnus
added function to change global variable values by scheduled time.
added possibility to define different buttons of VD to be pressed at
different scheduled times. See example bellow.
1.2.3 - added support for localisation so that scene knows where you are and
to properly set seasons. Also added checking of users GPS position
and calculation of distance from home of each user in meters. Further
usage of this will be added when Fibaro rectifies battery drain when
location services are turned on for Fibaro app. Sorry!
1.2.2 - "Sunrise & Sunset" VD is now generating missing global values needed
for setting up of sunrise, sunset and time of day times. User need
to first install this VD and define the rest of globals listed
bellow and can start using this scene.
1.2.1 - removed unecessary global variables MarginDay, MarginNight and
marignBlinds since calculation is done by "Sunrise & Sunset" VD
Please before using this scene import "Sunrise & Sunset" VD to set
time for Day, Night and Blinds.
1.2 - added support for repeating and scheduled scene and VD push button
activations. Also added control of holiday lights which are turned of
when time of day changes from Morning to Day, and turning then On again
at evening before sunset for time defined in variable marginHoliday.
done code cleaning and making it more readable by removing most of the
code from main loop to different functions and adding more instructions
and explanations for users how to setup this scene.
-- SCENE DESCRIPTION
This scene will take care of all time based events mostly by changing global
variables at specified time, but can also be used to call other scenes at
preferred time or pressing buttons on VDs! Before usage need to configure
following global variables:
-- LIST OF GLOBAL VARIABLES NEEDED
"HomeTable" - predefined global variable table with device and scene
IDs. Recommended to use since z-wave devices can change
their ID with re-inclusion and then is necesary to edit
only scene which make this table and only device ID in
scene headers. Much less time and effort is needed than
without that option!
"Darkness" - global variable, possible values: 0 - Day time,
1 - Night time, value is set by this scene
"SleepState" - predefined global variable with values "Awake", "Sleep" or
values in your language that you can map in code bellow.
Value is changed by other scenes or VD and it is up to you
"SeasonState" - predefined global variable with values of season names in
your language. Just remember to map your names in code
bellow - value is set by this scene
"WeekDay" - predefined global variable with values of weekday names
in your language. Remember to map your names in code bellow
- value set by this scene
"Month" - predefined global variable with values of month names in
your language. Remember to map your names in code bellow
- value set by this scene
"TimeOfDay" - predefined global variable with values of "Morning", "Day",
"Evening", "Night" in your language. Remember to map your
values in bellow code - value is set by this scene depending
on "Sunrise & Sunset" VD settings
"DemoMode" - predefined global variable with values: "Yes", "No" -
value changed by VD and if set to "Yes" then scene will
no more change time based variables like Darkness,
TimeOfDay, SeasonState so they can be changed by VD to
make test of the system or just demostration
"HolidayTime" - predefined global variable with two possible values:
"Yes" from 27th November till 6th January, "No" for the
rest of the year.
"HolidayLights" - predefined global variable with two possible values:
"On" - holiday lights are turned On
"Off" - holiday lights are turned Off
--]]
local hc=fibaro if(hc:countScenes()>1)then os.exit()end
-- LOCAL VARIABLES DEFINITIONS
-- please do not change this part until TIME BASED SCENES AND VD SETUP part.
local currenttime=os.date('*t')
local currentmonth=currenttime['month']
local currentday=currenttime['day']
local currentwday=currenttime['wday']
local currenthour=currenttime['hour']
local currentmin=currenttime['min']
local TimeCurrent=os.date("%H:%M", os.time())
local sunset=hc:getValue(1,"sunsetHour")
local sunrise=hc:getValue(1,"sunriseHour")
local count=1
local sunrisetime=hc:getGlobalValue("SunriseTime") or sunrise
local marginSunrise=tonumber(hc:getGlobalValue("MarginSunrise")) or 0
local sunsettime=hc:getGlobalValue("SunsetTime") or sunset
local marginSunset=tonumber(hc:getGlobalValue("MarginSunset")) or 0
local daytime=hc:getGlobalValue("DayTime") or "09:00"
local marginDay=hc:getGlobalValue("MarginDay") or "02:00"
local nighttime=hc:getGlobalValue("NightTime") or "21:00"
local marginNight=hc:getGlobalValue("MarginNight") or "02:00"
local blindtime=hc:getGlobalValue("OpenBlindTime") or "11:00"
local marginBlinds=hc:getGlobalValue("MarginBlinds") or "04:00"
local api_hc=api.get("/settings/location")
local HClat=tonumber(string.format("%.8f",api_hc.latitude))local HClon=tonumber(string.format("%.8f",api_hc.longitude))
local latitude=tonumber(hc:getGlobalValue("Latitude")) or HClat
local longitude=tonumber(hc:getGlobalValue("Longitude")) or HClon
local homelocation=tostring(longitude)..";"..tostring(latitude)
local userlocation,userdistance={},{}
-- end of local variables definitions
-- PART OF CODE FOR USERS TO EDIT AND SETUP
-- DARKNESS LIGHT SENSOR SETUP -- NEW!
-- if you setup light sensor here then scene will change global Darkness
-- according to sensor setup instead of using sunrise and sunset times
-- for example {400,320}
local luxID = {}
-- or you can setup global variables names that are set by other light sensors
-- for example {"LuxGarden","LuxShade"}
local luxGlo = {}
local luxLevelmin = 100
local luxLevelmax = 300
-- luxDelayTime is set in minutes and is used to avoid frequent change of Darkness
-- default setting is 5 minutes
local luxDelayTime = 5
-- do not change this variables
local luxDelay=(60*luxDelayTime)
local lastChange=os.time()-luxDelay
-- END DARKNESS LIGHT SENSOR SETUP
-- GLOBAL VARIABLES
-- enter names and value mapping of your global variables or leave as it is
-- get the table of device & scene ID's from global variable HomeTable. If
-- using then uncomment bellow line else leave it as it is!
-- local jT = json.decode(hc:getGlobalValue("HomeTable"))
-- "Darkness" is global variable with two possible states 0 - for day time and 1
-- for night time and it is changed at sunrise & sunset by main scene that is
-- responsible for all time based events. See my other posts for details
local darkness = "Darkness"
local darknessMapping = {Light="0", Dark="1"}
-- "SleepState" is predefined global variable with possible values:
-- "Sleep", "Awake".
local sleepState = "SleepState"
local sleepStateMapping = {Sleep="Sleep", Awake="Awake"}
-- if you want that TimeOfDay changes to Morning (or Day) if you wakeup
-- before sunrise time inestead at sunrise time then set useSleepState
-- to true therwise leave it false
local useSleepState = false
-- predefined global variable that keeps current day of week.
-- make sure that value mapping corresponds to day names in
-- your language
local weekDay = "WeekDay"
local weekDayMapping = {Sunday ="Sunday",
Monday ="Monday",
Tuesday ="Tuesday",
Wednesday ="Wednesday",
Thursday ="Thursday",
Friday ="Friday",
Saturday ="Saturday"}
-- enter week days in your language and mapped in previous variable
local weekDayMap = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}
-- predefined global variable that keeps current month name.
-- make sure that value mapping corresponds to month names in
-- your language
local month = "Month"
local monthMapping = {January ="January",
February ="February",
March ="March",
April ="April",
May ="May",
June ="June",
July ="July",
August ="August",
September="September",
October ="October",
November ="November",
December ="December"}
-- enter month names in your language and mapped in previous variable
local monthMap = {"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"}
-- predefined global variable that keeps current season and map
-- your values
local seasonState = "SeasonState"
local seasonStateMapping = {Spring="Spring", Summer="Summer", Autumn="Autumn", Winter="Winter"}
-- predefined global variable that keeps current time of day and map
-- your values
local timeOfDay = "TimeOfDay"
local timeOfDayMapping = {Morning="Morning", Day="Day", Evening="Evening", Night="Night"}
-- predefined global variable that determines normal or demo
-- mode of the system. Demo mode can be used for testing or
-- demostration of the system set by "Home state" VD
local demoMode = "DemoMode"
local demoModeMapping = {On="Yes", Off="No"}
-- GPS LOCATION AND USERS SETUP
-- define users for which you want to get GPS location. Enter users inside
-- braces separated by comma
local userID = {}
-- PUSH MESSAGES AND MOBILE DEVICE SETUP
-- define mobile devices to send push messages. Enter devices inside
-- braces separated by comma
local iosDeviceID = {}
-- flag for each user if 1 then send notifications else if 0 do not
-- send notifications. You can add code in function extraUserCodeFirst()
-- where you can change user flags depending on some global variable.
local iosDeviceFlag = {}
-- TIME BASED SCENES AND VD SETUP
-- REPEATING SCENES SETUP
-- here you can setup scenes that will be executed at predefined interval
-- in minutes. Lowest value is every 1 minute and longest interval is up to
-- you. 24h = 1440m, 1week = 10080m, 30d = 43200m etc.
-- enter scene names that will run repeatedly every X minutes separated
-- by comma. This is needed for debugging and can be used to send push
-- notification
local runSceneRepeatName = {}
-- enter scene IDs that will run repeatedly every X minutes separated
-- by comma.
local runSceneRepeatID = {}
-- enter at which interval time in minutes will scenes run separated
-- by comma.
local runSceneRepeatTime = {}
-- enter here flag for sending push message when scene is executed
-- 1 for sending message, 0 no messages
local runSceneRepeatPushFlag = {}
-- enter here message content that will be sent to you when scene is
-- executed. If above flag is 0 for any of the scenes then just put
-- empty "" for it.
local runSceneRepeatPushMessage = {}
-- for each scene enter variable with name "count" (must be all same name)
-- separated by comma. This is used to count interval at which scene will
-- be started and is neccessary for proper execution!
local runSceneRepeatCount = {}
-- enter here "Yes" for each scene if you want them to run immediatelly when
-- this scene starts running after reboot or saving or enter "No" if you
-- want scene to run after defined interval after scene is restarted
local runSceneAtStart = {}
-- SCHEDULED SCENES SETUP
-- here you can setup scenes that will be executed at predefined time of
-- day in format "00:00". You can set up more than one time during day.
-- Also you can enter flag for each day of the week when scene will be
-- executed or not. See more details bellow.
local runSceneSchedName = {}
-- enter scene IDs that will run at scheduled time separated by comma.
local runSceneSchedID = {}
-- enter at what time of day will scenes run separated by comma.
-- You can define more than one time in format "00:00" for one scene
-- or even use local or global variables like sunsettime or sunrisetime
-- Example: {{"13:30", "19:20"}, {sunrisetime, "13:00", sunsettime}}
-- in above example first scene will run at 13:30 and 19:20 while
-- second scene will run at sunrisetime, 13:00 and at sunsettime
-- IMPORTANT NOTE - if you use variable to set time then make sure that
-- you add refreshing of value in function extraUserCodeFirst() like
-- this for above example:
-- runSceneSchedHour[2][1] = sunrisetime
-- runSceneSchedHour[2][3] = sunsettime where first square brackets
-- [2] with number inside refers to second scene and second square
-- brackets [1] with number inside refers to time in order which means
-- sunrisetime is 1st time [1] for 2nd [2] scene and sunsettime is
-- 3rd [3] time for 2nd [2] scene in a row added to the variable.
local runSceneSchedHour = {}
-- enter here flag for each day of the week for scene to run at above
-- scheduled time. if flag 1 the scene will run and if flag 0 then
-- will not be run for that day. Remeber, Sunday is first day of the
-- week on HC2! Example for two scenes:
-- {{1, 0, 0, 0, 0, 0, 0}, {0, 1, 1, 1, 1, 1, 0}} - in this example
-- first scene will run only on Sunday, and second scene will run on
-- weekdays byt not on weekends (Saturday and Sunday).
local runSceneSchedWeek = {}
-- enter here flag for sending push message when scene is executed
-- 1 for sending message, 0 no messages
local runSceneSchedPushFlag = {}
-- enter here message content that will be sent to you when scene is
-- executed. If above flag is 0 for any of the scenes then just put
-- empty "" for it.
local runSceneSchedPushMessage = {}
-- REPEATING VIRTUAL DEVICE SETUP
-- here you can setup VD that will be executed at predefined interval
-- in minutes. Lowest value is every 1 minute and longest interval is up to
-- you. 24h = 1440m, 1week = 10080m, 30d = 43200m etc.
-- enter VD IDs that will run repeatedly every X minutes separated
-- by comma.
local runVDRepeatID = {}
-- enter here which button to press to execute command
local runVDRepeatButton = {}
-- enter at which interval time in minutes will VD run separated by comma.
local runVDRepeatTime = {}
-- enter here flag for sending push message when VD is executed 1 for
-- sending message, 0 no messages
local runVDRepeatPushFlag = {}
-- enter here message content that will be sent to you when VD is
-- executed. If above flag is 0 for any of the VD then just put
-- empty "" for it.
local runVDRepeatPushMessage = {}
-- for each VD enter variable with name "count" (can be all same name)
-- separated by comma. This is used to count interval at which VD will
-- be executed and is neccessary for proper execution!
local runVDRepeatCount = {}
-- enter here "Yes" for each VD if you want them to run immediatelly when
-- this scene starts running after reboot or saving or enter no if you
-- want VD to run after defined interval
local runVDAtStart = {}
-- SCHEDULED VD SETUP
-- here you can setup VDs that will be executed at predefined time of
-- day in format "00:00". You can set up more than one time during day.
-- Also you can enter flag for each day of the week when VD will be
-- executed or not. See more details bellow.
-- enter VD IDs that will run at scheduled time separated by comma.
local runVDSchedID = {}
-- enter here which button to press to execute command for each time that
-- you enter bellow. Example for Sonos remote VD from Krikroff. If you set
-- runVDSchedButton = {{"7", "9"}} and
-- runVDSchedHour = {{"07:00", "11:00}}
-- Then button "2" (Play) will be pressed at 07:00 to start music and
-- button "9" (Stop) will be pressed at 11:00 to stop music.
local runVDSchedButton = {{}}
-- enter at what time of day will VD button be pressed separated by comma.
-- You can define more than one time in format "00:00" for one VD
-- or even use local or global variables like sunsettime or sunrisetime
-- Example: {{"13:30", "19:20"}, {sunrisetime, "13:00", sunsettime}}
-- in above example first VD button will be pressed at 13:30 and 19:20
-- while second VDs button will be pressed at sunrisetime, 13:00 and
-- at sunsettime
local runVDSchedHour = {{}}
-- enter here flag for each day of the week for VD to press button
-- at above scheduled time. if flag 1 the VD button will be pressed and
-- if flag 0 then will not be pressed for that day. Remeber, Sunday is
-- first day of the week on HC2! Example for two VDs:
-- {{1, 0, 0, 0, 0, 0, 0}, {0, 1, 1, 1, 1, 1, 0}} - in this example
-- first VDs button will be pressed only on Sunday, and second VDs
-- button will be pressed on weekdays but not on weekends (Saturday
-- and Sunday).
local runVDSchedWeek = {{1, 1, 1, 1, 1, 1, 1}}
-- enter here flag for sending push message when VD buttons is pressed
-- 1 for sending message, 0 no messages
local runVDSchedPushFlag = {}
-- enter here message content that will be sent to you when VD is
-- executed. If above flag is 0 for any of the VDs then just put
-- empty "" for it.
local runVDSchedPushMessage = {}
-- SCHEDULED GLOBAL VARIABLE CHANGE SETUP
-- here you can setup global variable which value will be changed at
-- predefined time of day in format "00:00". You can set up more than one
-- time during day. Also you can enter flag for each day of the week when
-- global variable value will change or not. See more details bellow.
-- enter global variable name which value you want to change at scheduled
-- time separated by comma.
local chgGlobalSchedName = {}
-- enter here what value will be set to global variable for each time that
-- is entered bellow
local chgGlobalValue = {{}}
-- enter at what time of day will global value change separated by comma.
-- You can define more than one time in format "00:00" for one VD
-- or even use local or global variables like sunsettime or sunrisetime
-- Example: {{"13:30", "19:20"}, {sunrisetime, "13:00", sunsettime}}
-- in above example first global variable value will be changed at 13:30
-- and another value at 19:20 while second global variable value will be
-- changed at sunrisetime, 13:00 and at sunsettime
local chgGlobalHour = {{}}
-- enter here flag for each day of the week for VD to press button
-- at above scheduled time. if flag 1 the VD button will be pressed and
-- if flag 0 then will not be pressed for that day. Remeber, Sunday is
-- first day of the week on HC2! Example for two VDs:
-- {{1, 0, 0, 0, 0, 0, 0}, {0, 1, 1, 1, 1, 1, 0}} - in this example
-- first VDs button will be pressed only on Sunday, and second VDs
-- button will be pressed on weekdays but not on weekends (Saturday
-- and Sunday).
local chgGlobalWeek = {{1, 1, 1, 1, 1, 1, 1}}
-- enter here flag for sending push message when VD buttons is pressed
-- 1 for sending message, 0 no messages
local chgGlobalPushFlag = {}
-- enter here message content that will be sent to you when VD is
-- executed. If above flag is 0 for any of the VDs then just put
-- empty "" for it.
local chgGlobalPushMessage = {}
-- DEBUGGING VARIABLES
-- setup debugging, true is turned on, false turned off.
local deBug = true -- for showing events as they happen
local exDebug = false -- for checking repeating and scheduled scene
-- & VD variable values if correct
local gpsDebug = false -- GPS user location check and calculation
local sumDebug = true -- it shows summation of global var changes
-- EXTRA FUNCTION WHERE YOU CAN ADD YOUR CODE
-- use this function to add code that will be executed before all other
-- code in the loop
function extraUserCodeFirst()
-- if you use variable for scheduled execution of scene or VD then you
-- need to add here equanation to get last value calcualted
-- your code goes here
end
-- use this function to add code that will be executed after all other
-- code in the loop
function extraUserCodeLast()
-- your code goes here
end
-- END OF CODE PART FOR USERS TO EDIT AND SETUP
-- BELLOW CODE NO NEED TO MODIFY BY USER
-- FUNCTIONS CODE PART
local version,midnight="1.3.0","00:00"
local interval,pause,alignment=60,100,true
-- debug colors
local crc,okc,ekc,erc,evc,xec,cnc,xcc,tmc,stc="green","lightgreen","violet","red","orange","yellow","cyan","pink","magenta","lightgray"
-- other locals
local abort,miss,am="Please check. Scene aborting"," is missing ","Aligning to next minute..."
local crt="Main scene FTBE version "..version.." - © 2016-2018 Sankotronic"
function logbug(color,message)for line in message:gmatch("[^\010\013]+")do local txt=line:gsub("([\038\060\062])",function(c)return""..string.byte(c)..";"end) hc:debug(('%s'):format(color,txt))end end
function calculateTime(baseTime,diffHour,diffMinute)
if diffHour~=nil and diffMinute~=nil then
local origHour,origMinute=string.match(baseTime,"(%d+):(%d+)")local newMinute=(origMinute+diffMinute)%60
local excessHour=math.floor((origMinute+diffMinute)/60)local newHour=(origHour+diffHour+excessHour)%24
return string.format("%02d:%02d",newHour,newMinute)
else return baseTime end
end
function calculateTimeString(baseTime,duration,operand)
local diffHour,diffMinute=string.match(duration,"(%d+):(%d+)")if diffMinute==nil then diffMinute="00" end
if operand=="sub" then diffHour=0-diffHour diffMinute=0-diffMinute end
return calculateTime(baseTime,diffHour,diffMinute)
end
function sendPush(message)
if (#iosDeviceID==#iosDeviceFlag)then
if #iosDeviceID>0 then
for i=1,#iosDeviceID do if iosDeviceFlag[i]==1 then hc:call(iosDeviceID[i],"sendPush",message)
if deBug then logbug("lightgray", "Push notification sent to user "..hc:getName(iosDeviceID[i])) end
end end end
else if deBug then logbug(erc,"User and flag count is different, not setup correctly. Please check")end end
end
function getUserPosition()
if #userID>0 then
for i=1,#userID do if(hc:getValue(userID[i],'Location')==nil)then if gpsDebug then logbug(evc,"No GPS position for "..hc:getName(userID[i]))end
else userlocation[i]=hc:getValue(userID[i],'Location')userdistance[i]=tonumber(hc:calculateDistance(userlocation[i],homelocation))
if gpsDebug then logbug(okc,hc:getName(userID[i]).." distance from home is: "..string.format("%.2f",userdistance[i]).." meters")end
end end end end
function doTimeOfDay()
if(((TimeCurrent>=sunrisetime)and(TimeCurrent=midnight)and(TimeCurrent=daytime)and(TimeCurrent=sunsettime)and(TimeCurrent0 then for i,v in pairs(luxID)do totalLux=totalLux+tonumber(hc:getValue(v,'value'))end averageLux=math.floor(totalLux/#luxID)
elseif #luxGlo>0 then for i,v in pairs(luxGlo)do totalLux=totalLux+tonumber(hc:getGlobalValue(v))end averageLux=math.floor(totalLux/#luxGlo)
else averageLux=50 end
if exDebug then logbug(cnc,string.format("Set lux level min %s, max %s. Measured average lux level is %s.",luxLevelmin,luxLevelmax,averageLux))end
return averageLux
end
function doDarkness()
local dkc="Darkness changed to %s at lux: %s"
local ct,now=os.date("%H:%M",os.time()),os.time()
local val_dark=hc:getGlobalValue(darkness) or darknessMapping.Light
if #luxID>0 then local luxLevel=checkLux()
if luxLevel<=luxLevelmin and now-lastChange>=luxDelay and val_dark~=darknessMapping.Dark then
if exDebug then logbug(evc,string.format(dkc,"Dark",luxLevel))end hc:setGlobal(darkness,darknessMapping.Dark)lastChange=now
elseif luxLevel>=luxLevelmax and now-lastChange>=luxDelay and val_dark~=darknessMapping.Light then
if exDebug then logbug(evc,string.format(dkc,"Light",luxLevel))end hc:setGlobal(darkness,darknessMapping.Light)lastChange=now end
if deBug then logbug(xec,string.format("Luxmin: %s, Luxmax: %s, Delay: %s min, Last change: %s",luxLevelmin,luxLevelmax,os.date("%M",luxDelay),os.date("%H:%M:%S",lastChange)))end
else if TimeCurrent>=sunrisetime and TimeCurrent=1 and currentmonth<3)then if latitude>=0 then hc:setGlobal(seasonState,seasonStateMapping.Winter)else hc:setGlobal(seasonState,seasonStateMapping.Summer)end
elseif currentmonth==3 then if currentday<21 then
if latitude>=0 then hc:setGlobal(seasonState,seasonStateMapping.Winter)else hc:setGlobal(seasonState, seasonStateMapping.Summer)end
else if latitude>=0 then hc:setGlobal(seasonState,seasonStateMapping.Spring)else hc:setGlobal(seasonState,seasonStateMapping.Autumn)end end
elseif(currentmonth>3 and currentmonth<6)then
if latitude>=0 then hc:setGlobal(seasonState,seasonStateMapping.Spring)
else hc:setGlobal(seasonState,seasonStateMapping.Autumn)end
elseif currentmonth==6 then if currentday<21 then
if latitude>=0 then hc:setGlobal(seasonState,seasonStateMapping.Spring)else hc:setGlobal(seasonState,seasonStateMapping.Autumn)end else
if latitude>=0 then hc:setGlobal(seasonState,seasonStateMapping.Summer)else hc:setGlobal(seasonState,seasonStateMapping.Winter)end end
elseif(currentmonth>6 and currentmonth<9)then
if latitude>=0 then hc:setGlobal(seasonState,seasonStateMapping.Summer)else hc:setGlobal(seasonState,seasonStateMapping.Winter)end
elseif currentmonth==9 then if currentday<23 then
if latitude>=0 then hc:setGlobal(seasonState,seasonStateMapping.Summer)else hc:setGlobal(seasonState,seasonStateMapping.Winter)end
else if latitude>=0 then hc:setGlobal(seasonState,seasonStateMapping.Autumn)else hc:setGlobal(seasonState,seasonStateMapping.Spring)end end
elseif(currentmonth>9 and currentmonth<12)then
if latitude>=0 then hc:setGlobal(seasonState,seasonStateMapping.Autumn)else hc:setGlobal(seasonState,seasonStateMapping.Spring)end
elseif currentmonth==12 then if currentday<21 then
if latitude>=0 then hc:setGlobal(seasonState,seasonStateMapping.Autumn)else hc:setGlobal(seasonState,seasonStateMapping.Spring)end
else if latitude>=0 then hc:setGlobal(seasonState,seasonStateMapping.Winter)else hc:setGlobal(seasonState,seasonStateMapping.Summer)end end
end hc:setGlobal(month,monthMap[currentmonth])
if deBug and hc:getGlobalValue(seasonState)~=nil and hc:getGlobalValue(month)~=nil then
logbug(xec," Season is "..hc:getGlobalValue(seasonState)..", Month is "..hc:getGlobalValue(month))
else logbug(xec,"Missing global variable for Season and/or Month")end
end
function doSceneRepeat()
for i=1,#runSceneRepeatID do
if exDebug then logbug(evc,"Repeating scene "..runSceneRepeatName[i].." interval is: "..runSceneRepeatTime[i].." min current count is: "..runSceneRepeatCount[i].." min.")end
if runSceneRepeatTime[i]==runSceneRepeatCount[i] then hc:startScene(runSceneRepeatID[i])
if deBug then logbug(xec,"Repeating scene "..runSceneRepeatName[i].." started after "..runSceneRepeatCount[i].." min.")end
if runSceneRepeatPushFlag[i]==1 then sendPush(runSceneRepeatPushMessage[i])end
runSceneRepeatCount[i]=1
else runSceneRepeatCount[i]=runSceneRepeatCount[i]+1 end
end end
function doSceneSched()
for i=1,#runSceneSchedID do
if exDebug then logbug(evc,"Scheduled scene "..runSceneSchedName[i].." weekday flag is: "..runSceneSchedWeek[i][currentwday])end
if runSceneSchedWeek[i][currentwday]==1 then
for t=1,#runSceneSchedHour[i] do
if exDebug then logbug(ekc,"Scheduled scene "..runSceneSchedName[i].."run time["..i.."]["..t.."] is: "..runSceneSchedHour[i][t].."h current time is: "..TimeCurrent.."h")end
if runSceneSchedHour[i][t]==TimeCurrent then hc:startScene(runSceneSchedID[i])
if deBug then logbug(xec,"Scheduled scene "..runSceneSchedName[i].." started at "..runSceneSchedHour[i][t].."h")end
if runSceneSchedPushFlag[i]==1 then sendPush(runSceneSchedPushMessage[i]) end
end end end end end
function doVDRepeat()
for i=1,#runVDRepeatID do
if exDebug then logbug(evc,"Repeating VD "..hc:getName(runVDRepeatID[i]).." press button interval is: "..runVDRepeatTime[i].." min current count is: "..runVDRepeatCount[i].." min.")end
if runVDRepeatTime[i]==runVDRepeatCount[i] then hc:call(runVDRepeatID[i],"pressButton",runVDRepeatButton[i])
if deBug then logbug(xec,"Repeating VD "..hc:getName(runVDRepeatID[i]).." pressed button "..runVDRepeatButton[i].." after "..runVDRepeatCount[i].." min.")end
if runVDRepeatPushFlag[i]==1 then sendPush(runVDRepeatPushMessage[i])end
runVDRepeatCount[i]=1
else runVDRepeatCount[i]=runVDRepeatCount[i]+1 end
end end
function doVDSched()
for i=1,#runVDSchedID do
if exDebug then logbug(evc,"Scheduled VD "..hc:getName(runVDSchedID[i]).." weekday flag is: "..runVDSchedWeek[i][currentwday])end
if runVDSchedWeek[i][currentwday]==1 then
for t=1,#runVDSchedHour[i] do
if exDebug then logbug(ekc,"Scheduled VD "..hc:getName(runVDSchedID[i]).." run time["..i.."]["..t.."] is: "..runVDSchedHour[i][t].."h current time is: "..TimeCurrent.."h")end
if runVDSchedHour[i][t]==TimeCurrent then hc:call(runVDSchedID[i],"pressButton",runVDSchedButton[i][t])
if deBug then logbug(xec,"Scheduled VD "..hc:getName(runVDSchedID[i]).." button "..runVDSchedButton[i][t].." pressed at "..runVDSchedHour[i][t].."h")end
if runVDSchedPushFlag[i]==1 then sendPush(runVDSchedPushMessage[i])end
end end end end end
function doGlobalSched()
for i=1,#chgGlobalSchedName do
if exDebug then logbug(evc,"Scheduled global "..chgGlobalSchedName[i].." weekday flag is: "..chgGlobalWeek[i][currentwday])end
if chgGlobalWeek[i][currentwday]==1 then
for t=1,#chgGlobalHour[i] do
if exDebug then logbug(ekc,"Scheduled global "..chgGlobalSchedName[i].." run time["..i.."]["..t.."] is: "..chgGlobalHour[i][t].."h current time is: "..TimeCurrent.."h")end
if chgGlobalHour[i][t]==TimeCurrent then hc:setGlobal(chgGlobalSchedName[i],chgGlobalValue[i][t])
if deBug then logbug(xec,"Scheduled global "..chgGlobalSchedName[i].." changed value to "..chgGlobalValue[i][t].." at "..chgGlobalHour[i][t].."h")end
if chgGlobalPushFlag[i]==1 then sendPush(chgGlobalPushMessage[i])end
end end end end end
-- CHECK AND INITIALIZE SCENES & DEVICES
function chkUserSetting()
if #runSceneRepeatID>0 then
if((#runSceneRepeatID==#runSceneRepeatName)and(#runSceneRepeatID==#runSceneRepeatTime)and
(#runSceneRepeatID==#runSceneRepeatPushFlag)and(#runSceneRepeatID==#runSceneRepeatCount)and
(#runSceneRepeatID==#runSceneAtStart)and(#runSceneRepeatID==#runSceneRepeatPushMessage))then
for i=1,#runSceneRepeatID do if runSceneAtStart[i]=="Yes" then runSceneRepeatCount[i]=runSceneRepeatTime[i]else runSceneRepeatCount[i]=1 end end
if deBug then logbug(okc,"Repeating scene timers initialized!")end
else if deBug then logbug(erc,"Repeating scene setup error! Missing argument. Please check. Scene is stopped!")end os.exit()end
end
if #runVDRepeatID>0 then
if((#runVDRepeatID==#runVDRepeatButton)and(#runVDRepeatID==#runVDRepeatTime)and
(#runVDRepeatID==#runVDRepeatPushFlag)and(#runVDRepeatID==#runVDRepeatCount)and
(#runVDRepeatID==#runVDAtStart)and(#runVDRepeatID==#runVDRepeatPushMessage))then
for i=1,#runVDRepeatID do
if runVDAtStart[i]=="Yes" then runVDRepeatCount[i]=runVDRepeatTime[i]else runVDRepeatCount[i]=1 end end
if deBug then logbug(okc,"Repeating VD timers initialized!")end
else if deBug then logbug(erc,"Repeating VD setup error! Missing argument. Please check. Scene is stopped!")end os.exit()end
end
if #runSceneSchedID>0 then
local check=false
if((#runSceneSchedID==#runSceneSchedName)and(#runSceneSchedID==#runSceneSchedHour)and
(#runSceneSchedID==#runSceneSchedWeek)and(#runSceneSchedID==#runSceneSchedPushFlag)and
(#runSceneSchedID==#runSceneSchedPushMessage))then
for i=1,#runSceneSchedID do
if #runSceneSchedHour[i]==0 then
if deBug then logbug(erc,"Scheduled scene "..runSceneSchedName[i].." is missing time. Please chcek. Scene is stopped!")end check=true end
if #runSceneSchedWeek[i]~=7 then
if deBug then logbug(erc,"Scheduled scene "..runSceneSchedName[i].." is missing flags for whole week. Please check. Scene is stopped!")end check=true end
end
else if deBug then logbug(erc,"Scheduled scene setup error! Missing argument. Please check. Scene is stopped!")end check=true end
if check then os.exit() end
end
if #runVDSchedID>0 then
local check=false
if((#runVDSchedID==#runVDSchedButton)and(#runVDSchedID==#runVDSchedHour)and
(#runVDSchedID==#runVDSchedWeek)and(#runVDSchedID==#runVDSchedPushFlag)and
(#runVDSchedID==#runVDSchedPushMessage))then
for i=1,#runVDSchedID do
if #runVDSchedHour[i]==0 then
if deBug then logbug(erc,"Scheduled VD "..hc:getName(runVDSchedID[i]).." is missing time. Please chcek. Scene is stopped!")end check=true
elseif #runVDSchedButton[i]==0 then
if deBug then logbug(erc,"Scheduled VD "..hc:getName(runVDSchedID[i]).." is missing button. Please chcek. Scene is stopped!")end check=true
elseif #runVDSchedHour[i]~=#runVDSchedButton[i] then
if deBug then logbug(erc,"Scheduled VD "..hc:getName(runVDSchedID[i]).." number if time and buttons mismatch. Please chcek. Scene is stopped!")end check=true end
if #runVDSchedWeek[i]~=7 then
if deBug then logbug(erc,"Scheduled VD "..hc:getName(runVDSchedID[i]).." is missing flags for whole week. Please chcek. Scene is stopped!")end check=true end
end
else if deBug then logbug(erc,"Scheduled VD setup error! Missing argument. Please check. Scene is stopped!")end check=true end
if check then os.exit() end
end
if #chgGlobalSchedName>0 then
local check=false
if((#chgGlobalSchedName==#chgGlobalValue)and(#chgGlobalSchedName==#chgGlobalHour)and
(#chgGlobalSchedName==#chgGlobalWeek)and(#chgGlobalSchedName==#chgGlobalPushFlag)and
(#chgGlobalSchedName==#chgGlobalPushMessage))then
for i=1,#chgGlobalSchedName do
if #chgGlobalHour[i]==0 then
if deBug then logbug(erc,"Scheduled global "..chgGlobalSchedName[i].." is missing time. Please chcek. Scene is stopped!")end check=true
elseif #chgGlobalValue[i]==0 then
if deBug then logbug(erc,"Scheduled global "..chgGlobalSchedName[i].." is missing value. Please chcek. Scene is stopped!")end check=true
elseif #chgGlobalHour[i]~=#chgGlobalValue[i]then
if deBug then logbug(erc,"Scheduled global "..chgGlobalSchedName[i].." number of time and value mismatch. Please chcek. Scene is stopped!")end check=true end
if #chgGlobalWeek[i]~=7 then
if deBug then logbug(erc,"Scheduled global "..chgGlobalSchedName[i].." is missing flags for whole week. Please chcek. Scene is stopped!")end check=true end
end
else if deBug then logbug(erc,"Scheduled global variable setup error! Missing argument. Please check. Scene is stopped!")end check=true end
if check then os.exit()end
end
end
-- MAIN LOOP PART
function mainLoop()
currenttime=os.date('*t')
currentmonth=currenttime['month']currentday=currenttime['day']currentwday=currenttime['wday']
currenthour=currenttime['hour']currentmin=currenttime['min']TimeCurrent=os.date("%H:%M", os.time())
sunrise=hc:getValue(1,"sunriseHour")or "19:00"
sunset=hc:getValue(1,"sunsetHour")or "07:00"
marginSunrise=tonumber(hc:getGlobalValue("MarginSunrise"))or 0
marginSunset=tonumber(hc:getGlobalValue("MarginSunset"))or 0
marginDay=hc:getGlobalValue("MarginDay")or "02:00"
marginNight=hc:getGlobalValue("MarginNight")or "02:00"
marginBlinds=hc:getGlobalValue("MarginBlinds")or "04:00"
latitude=tonumber(hc:getGlobalValue("Latitude"))or HClat
longitude=tonumber(hc:getGlobalValue("Longitude"))or HClon
homelocation=tostring(latitude)..";"..tostring(longitude)
sunrisetime=calculateTime(sunrise,0,marginSunrise)hc:setGlobal("SunriseTime",sunrisetime)
sunsettime=calculateTime(sunset,0,marginSunset)hc:setGlobal("SunsetTime",sunsettime)
daytime=calculateTimeString(sunrisetime,marginDay,"add")hc:setGlobal("DayTime",daytime)
nighttime=calculateTimeString(sunsettime,marginNight,"add")hc:setGlobal("NightTime",nighttime)
blindtime=calculateTimeString(sunrisetime,marginBlinds,"add")hc:setGlobal("OpenBlindTime",blindtime)
if deBug then logbug(okc,"Day time: ".. daytime..", Night time: "..nighttime..", Time to raise blinds: "..blindtime)end
extraUserCodeFirst()
if((demoMode=="")or(hc:getGlobalValue(demoMode)==demoModeMapping.Off))then
if #userID>0 then getUserPosition()end doDarkness()doTimeOfDay()doTimeOfYear()
else if deBug then logbug("cyan","DEMO MODE ON! Home timers and geolocation will NOT update. User code will execute") end end
if #runSceneRepeatID>0 then doSceneRepeat()end
if #runSceneSchedID>0 then doSceneSched()end
if #runVDRepeatID>0 then doVDRepeat()end
if #runVDSchedID>0 then doVDSched()end
if #chgGlobalSchedName>0 then doGlobalSched()end
extraUserCodeLast()
if sumDebug then if hc:getGlobalValue(timeOfDay)~=nil and hc:getGlobalValue(darkness)~=nil then
logbug(okc,"Darkness: "..hc:getGlobalValue(darkness).." Sunrise: "..sunrise.." (set:"..sunrisetime..")".." Sunset: " ..sunset.." (set:"..sunsettime..")".." TimeOfDay: "..hc:getGlobalValue(timeOfDay))
else logbug(okc,"Sunrise: "..sunrise.." (set:"..sunrisetime..")".." Sunset: "..sunset.." (set:"..sunsettime.. ")")
logbug(xec,"Missing global variable for Darkness and/or Time Of Day") end end
logbug(xec,"Scene idle")
end
-- MAIN CODE PART
function start()local t=os.date("*t")
if t.hour==2 and t.min==5 and t.sec~=0 and alignment then logbug(cnc,string.format("Current time: %s:%s:%s. "..am,t.hour,t.min,t.sec))hc:sleep(1000*(60-t.sec))end
setTimeout(mainLoop,0)logbug(okc,"Scene running")setTimeout(start,1000*interval)
end
-- MAIN CODE PART
logbug(crc,crt)chkUserSetting()
local t=os.date("*t")if t.sec~=0 and alignment then logbug(cnc,string.format("Current seconds: %s sec. "..am,t.sec))hc:sleep(1000*(60-t.sec))end
start()