https://gadget-freakz.com/2018/04/make- ... scripting/
I have include an option to log to an csv file, So I can run Dryrun and write the reason to change into an CSV file.
And that excel file must give the details of the conditions/reason to pull up or going down. and that is handy to debug or to adjust the thresholds.
But the only Thing I log right now is the message: reason. that's an text string.
what would be the right way to do it as simple as possible and log the information the best way?
All tips and feedback is helpfull..
myfunc
Code: Select all
- MyFunc --
-- Function library --
-- --
-- Release notes: --
-- 2016-06-01 First release --
--------------------------------------------------------------------------------
MyScript = 'MyFunc' --
MyFuncVersion = 100 --
MyFuncVersion_Type = 'Beta 01' --
LuaDebug = false --
--------------------------------------------------------------------------------
--
-- Functions
--
tempfilename = '/home/pi/domoticz/Logs/buienradar.tmp' --
local My ={}
function My.isBlank(x)
return not not tostring(x):find("^%s*$")
end
function My.PlaySound(msg)
Debug='Y'
if (Debug == 'Y') then print('>> Alarm zegt: '.. msg) end
os.execute ("sudo killall mplayer")
os.execute ("sh /home/pi/domoticz/scripts/bash/Play_sound.sh '" .. msg .. "' ")
end
function My.GetUserVar(UserVar)
Waarde=uservariables[UserVar]
if Waarde==nil then
print(". User variable not set for : " .. UserVar)
if My.isBlank(UserVarErr) or UserVarErr==nil then UserVarErr=0 end
UserVarErr=UserVarErr+1
end
return Waarde
end
function My.File_exists(file)
local f = io.open(file, "rb")
if f then f:close() end
return f ~= nil
end
function My.Round(num, idp)
local mult = 10^(idp or 0)
return math.floor(num * mult + 0.5) / mult
end
function My.GetValue(Text, GetNr)
Part=1
if Text==nil then
print(". GetValue error at : null " .. GetNr)
MyValue=0
else
for match in (Text..';'):gmatch("(.-)"..';') do
if Part==GetNr then MyValue = tonumber(match) end
Part=Part+1
end
end
return MyValue
end
-- replace the last character
function My.EnumClear(Text)
a=string.len(Text)
b=string.sub(Text,a,a)
if b=="," or b==" " then Text=string.sub(Text,1,a-1) end
a=string.len(Text)
b=string.sub(Text,a,a)
if b=="," or b==" " then Text=string.sub(Text,1,a-1) end
return Text
end
function My.ConvTime(TimeX)
year = string.sub(TimeX, 1, 4)
month = string.sub(TimeX, 6, 7)
day = string.sub(TimeX, 9, 10)
hour = string.sub(TimeX, 12, 13)
minutes = string.sub(TimeX, 15, 16)
seconds = string.sub(TimeX, 18, 19)
ResTime = os.time{year=year, month=month, day=day, hour=hour, min=minutes, sec=seconds}
return ResTime
end
function My.TimeDiff(Time1,Time2)
if Time1==nil then
print(". TimeDiff with a nill value : Time1 ")
ResTime=0
else
if string.len(Time1)>12 then Time1 = My.ConvTime(Time1) end
end
if Time2==nil then
print(". TimeDiff with a nill value : Time2 ")
ResTime=0
else
if string.len(Time2)>12 then Time2 = My.ConvTime(Time2) end
ResTime=os.difftime (Time1,Time2)
end
return ResTime
end
function My.IsItGonnaRain( minutesinfuture, lat, lon )
url='http://gadgets.buienradar.nl/data/raintext?lat='..lat..'&lon='..lon
if LuaDebug then print(url) end
--read = os.execute('curl -s -o '..tempfilename..' "'..url..'"')
read = os.execute('curl --retry 1 --connect-timeout 1 -s -o '..tempfilename..' "'..url..'"')
file = io.open(tempfilename, "r")
totalrain=0
rainlines=0
-- now analyse the received lines, format is like 000|15:30 per line.
-- print (". http://www.google.com/maps/place/" .. lat .. "," .. lon .."/data=!3m1!1e3")
-- http://www.google.com/maps/place/51.840756,4.6249/data=!3m1!1e3
while true do
line = file:read("*line")
if not line then break end
if LuaDebug then print('Line:'..line) end
linetime=string.sub(tostring(line), 5, 9)
if LuaDebug then print('Linetime: '..linetime) end
-- Linetime2 holds the full date calculated from the time on a line
linetime2 = os.time{year=os.date('%Y'), month=os.date('%m'), day=os.date('%d'), hour=string.sub(linetime,1,2), min=string.sub(linetime,4,5), sec=os.date('%S')}
difference = os.difftime (linetime2,os.time())
-- When a line entry has a time in the future AND is in the given range, then totalize the rainfall
if (difference > 0) then
if (difference<=minutesinfuture*60) then
if LuaDebug then print('Line in time range found') end
rain=tonumber(string.sub(tostring(line), 0, 3))
totalrain = totalrain+rain
rainlines=rainlines+1
if LuaDebug then print('Rain in timerange: '..rain) end
if LuaDebug then print('Total rain now: '..totalrain) end
else
if LuaDebug then print('Done processing rain data') end
break
end
end
end
file:close()
-- Returned value is average rain fall for next time
-- 0 is no rain, 255 is very heavy rain
-- When needed, mm/h is calculated by 10^((value -109)/32) (example: 77 = 0.1 mm/hour)
averagerain=totalrain/rainlines
return(averagerain)
end
return My
Code: Select all
-- Define all the sensors which needs to be considered for the sunscreen to close
local sensors = {
temperature = {
active = true,
device = 'Daikin - buitentemperatuur', --'Buienradar - Temperature',
closeRule = function(device)
return device.temperature <= 19
end
},
wind = {
active = true,
device = 'Wu - Wind',
closeRule = function(device)
return device.speed >= 50 or device.gust >= 150
end
},
rain = {
active = true,
device = 'Wu - Rain',
closeRule = function(device)
return device.rainRate > 0
end
},
rainExpected = {
active = true,
device = 'IsItGonnaRain', -- This needs to be a virtual sensor of type 'percentage'
closeRule = function(device)
return device.percentage > 15
end
},
uv = {
active = false,
device = 'Wu - Uv',
closeRule = function(device)
return device.uv <= 2
end
},
lux = {
active = false,
device = 'Lux',
closeRule = function(device)
return device.lux <= 500
end
}
}
local sunscreenDevice = 'Sunscreen' -- Define the name of your sunscreen device
local dryRun = 'Y' -- Enable dry run mode to test the sunscreen script without actually activating the sunscreen
-- Define the name of a virtual switch which you can use to disable the sunscreen automation script, Set to false to disable this feature
local manualOverrideSwitch = 'Sunscreen - Manual'
local timeBetweenOpens = 10 -- Minutes to wait after a sunscreen close before opening it again.
local LogFile= '/home/pi/domoticz/Logs/Sunscreen.csv ~m.csv'
local LogAction = 'Y'
local message = '.'
return {
active = true,
on = {
timer = {'every minute'}
},
logging = {
level = domoticz.LOG_DEBUG,
marker = 'Sunscreen: '
},
execute = function(domoticz)
-- FUNCTIONS
function LogActions()
LogFile=string.gsub(LogFile,"~d",os.date("%Y-%m-%d"))
LogFile=string.gsub(LogFile,"~m",os.date("%Y-%m"))
if not My.File_exists(LogFile) then
f=io.open(LogFile,"a")
f:write("Datum ; Tijd ; dryRun ; Manual_or_Auto ; Message")
f:write("\r\n")
else
f=io.open(LogFile,"r")
c=f:read("*line")
f:close()
f=io.open(LogFile,"a")
end
f:write(os.date("%Y-%m-%d;%H:%M:%S") .. ";" .. dryRun .. ";" .. domoticz.devices(manualOverrideSwitch).state .. ";" .. message )
f:write("\r\n")
f:close()
end
local function switchOn(sunscreen, message)
if LogAction == 'Y' or LogAction == 'A' then LogActions() end
if (sunscreen.state == 'Closed') then
if dryRun == 'N' then
sunscreen.switchOn()
--domoticz.notify('Sunscreen', message)
end
domoticz.log(message, domoticz.LOG_INFO)
--domoticz.notify('Sunscreen', message)
else
domoticz.log('Sunscreen is already down' , domoticz.LOG_INFO)
end
if LogAction == 'Y' or LogAction == 'A' then LogActions() end
end
local function switchOff(sunscreen, message)
if (sunscreen.state == 'Open') then
if dryRun == 'N' then
sunscreen.switchOff()
end
domoticz.log(message, domoticz.LOG_INFO)
--domoticz.notify('Sunscreen', message)
end
if LogAction == 'Y' or LogAction == 'A' then LogActions() end
end
-- PROGRAM STARTS
if (manualOverrideSwitch and domoticz.devices(manualOverrideSwitch).state == 'On') then
domoticz.log('Automatic sunscreen script is manually disabled', domoticz.LOG_DEBUG)
return
end
local sunscreen = domoticz.devices(sunscreenDevice)
-- Sunscreen must always be up during nighttime
if (domoticz.time.isNightTime) then
switchOff(sunscreen, 'Closing sunscreen, It is night')
message = 'Closing sunscreen, It is night'
if LogAction == 'Y' or LogAction == 'A' then LogActions() end
return
end
-- Check all sensor tresholds and if any exeeded close sunscreen
for sensorType, sensor in pairs(sensors) do
if (sensor['active'] == true) then
local device = domoticz.devices(sensor['device'])
local closeRule = sensor['closeRule']
domoticz.log('Checking sensor: ' .. sensorType, domoticz.LOG_DEBUG)
if (closeRule(device)) then
switchOff(sunscreen, sensorType .. ' treshold exceeded, Sunscreen up')
domoticz.log(sensorType .. ' treshold exceeded', domoticz.LOG_DEBUG)
message = (sensorType .. ' treshold exceeded')
if LogAction == 'Y' or LogAction == 'A' then LogActions() end
-- Return early when we exeed any tresholds
return
end
else
domoticz.log('Sensor not active skipping: ' .. sensorType, domoticz.LOG_DEBUG)
end
end
-- All tresholds OK, sunscreen may be lowered
if (sunscreen.lastUpdate.minutesAgo > timeBetweenOpens) then
message = 'Sun is shining, all thresholds OK, lowering sunscreen'
switchOn(sunscreen, message)
end
end
}