Sunscreen script (feedback needed)

Post Reply
User avatar
remb0
Posts: 976
Joined: Thursday 11 July 2013 22:21
Target OS: Raspberry Pi
Domoticz version: Beta
Location: The Netherlands
Contact:

Sunscreen script (feedback needed)

Post by remb0 » Thursday 26 April 2018 19:13

I posted an article on gadget-freakz.com about my sunscreen script:
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
}

User avatar
waaren
Posts: 822
Joined: Tuesday 03 January 2017 15:18
Target OS: Raspberry Pi
Domoticz version: Beta
Location: Netherlands
Contact:

Re: Sunscreen script (feedback needed)

Post by waaren » Monday 30 April 2018 21:30

Hi Rembo,

can you elaborate a little bit more on what you want. My current understanding is that you want more info in th csv file.
An example line of what you have now and one line with an example of what you want might give me enough information to work with.
Raspberry (debian stretch via berryboot on Synology DS916+) , Domoticz (almost) latest Beta, , dzVents 2.6, RFLink, RFXtrx433e, P1, Youless, Harmony, Hue, Yeelight, Xiaomi, HomeWizard, Zwave, Amazon echo

User avatar
remb0
Posts: 976
Joined: Thursday 11 July 2013 22:21
Target OS: Raspberry Pi
Domoticz version: Beta
Location: The Netherlands
Contact:

Re: Sunscreen script (feedback needed)

Post by remb0 » Sunday 20 May 2018 21:44

Sorry for my late response.

Indeed I want more info in the csv. All the time the script changes something or not I want the data of that decision.
That way you can check in excel how many times the screen is moving and why. so you can easily adjust the thresholds.

The log works. but this is the current output:
Datum ; Tijd ; dryRun ; Manual_or_Auto ; Message
2018-05-01;00:00:00;Y;Off;.
2018-05-01;00:00:00;Y;Off;Closing sunscreen, It is night
2018-05-01;00:01:00;Y;Off;.
2018-05-01;00:01:00;Y;Off;Closing sunscreen, It is night
2018-05-01;00:02:00;Y;Off;.
2018-05-01;00:02:00;Y;Off;Closing sunscreen, It is night
2018-05-01;00:03:00;Y;Off;.
2018-05-01;00:03:00;Y;Off;Closing sunscreen, It is night
2018-05-01;00:04:00;Y;Off;.
2018-05-01;00:04:00;Y;Off;Closing sunscreen, It is night

so I don't want the same repeating messages but only for changes.

User avatar
waaren
Posts: 822
Joined: Tuesday 03 January 2017 15:18
Target OS: Raspberry Pi
Domoticz version: Beta
Location: Netherlands
Contact:

Re: Sunscreen script (feedback needed)

Post by waaren » Monday 21 May 2018 2:15

My approach would be to safe the message using the dzVents script level persistent variable method and check if the message that you want to write to the logfile is different from the one last written.

See below (not tested):

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' },

    data    =   {   safedMessage = { initial = "-" } },
            
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
        if domoticz.data.safedMessage == message then
            domoticz.log("Same message skip write action",domoticz.LOG_DEBUG)
        else    
            domoticz.data.safedMessage = message
            f:write(os.date("%Y-%m-%d;%H:%M:%S") .. ";" .. dryRun .. ";" .. domoticz.devices(manualOverrideSwitch).state .. ";" .. message )
            f:write("\r\n")
        end
        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
        message = 'Closing sunscreen, It is night'
        switchOff(sunscreen, message)
        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
                message = (sensorType .. ' treshold exceeded , Sunscreen up')
                switchOff(sunscreen, message )
                domoticz.log(message, domoticz.LOG_DEBUG)
                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
}
Raspberry (debian stretch via berryboot on Synology DS916+) , Domoticz (almost) latest Beta, , dzVents 2.6, RFLink, RFXtrx433e, P1, Youless, Harmony, Hue, Yeelight, Xiaomi, HomeWizard, Zwave, Amazon echo

User avatar
EdwinK
Posts: 1248
Joined: Sunday 22 January 2017 22:46
Target OS: Raspberry Pi
Domoticz version: BETA
Location: Rhoon
Contact:

Re: Sunscreen script (feedback needed)

Post by EdwinK » Monday 21 May 2018 9:45

waaren wrote:
Monday 21 May 2018 2:15
My approach would be to safe the message using the dzVents script level persistent variable method and check if the message that you want to write to the logfile is different from the one last written.

See below (not tested):
Spoiler: show

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' },

    data    =   {   safedMessage = { initial = "-" } },
            
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
        if domoticz.data.safedMessage == message then
            domoticz.log("Same message skip write action",domoticz.LOG_DEBUG)
        else    
            domoticz.data.safedMessage = message
            f:write(os.date("%Y-%m-%d;%H:%M:%S") .. ";" .. dryRun .. ";" .. domoticz.devices(manualOverrideSwitch).state .. ";" .. message )
            f:write("\r\n")
        end
        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
        message = 'Closing sunscreen, It is night'
        switchOff(sunscreen, message)
        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
                message = (sensorType .. ' treshold exceeded , Sunscreen up')
                switchOff(sunscreen, message )
                domoticz.log(message, domoticz.LOG_DEBUG)
                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
}
Will this also work with your buienradar script, or does it only rely on WU?
Running latest BETA on a Pi-3 | Toon Thermostat | RFxcom | Dashticz V2 |

User avatar
waaren
Posts: 822
Joined: Tuesday 03 January 2017 15:18
Target OS: Raspberry Pi
Domoticz version: Beta
Location: Netherlands
Contact:

Re: Sunscreen script (feedback needed)

Post by waaren » Monday 21 May 2018 10:05

EdwinK wrote:
Monday 21 May 2018 9:45
Will this also work with your buienradar script, or does it only rely on WU?
@EdwinK,

this script is made by remb0. I only made a suggestion how to prevent double entries in the csv file. My guess is that if you change the names of the devices (sunscreen and sensors) to the names you use, it will work.
But as long as you leave the dryRun variable to "Y" you can test and modify the script to your own liking until everything reacts as expected.
Only when dryRun is "N" the script will send commands to your sunscreen.
Raspberry (debian stretch via berryboot on Synology DS916+) , Domoticz (almost) latest Beta, , dzVents 2.6, RFLink, RFXtrx433e, P1, Youless, Harmony, Hue, Yeelight, Xiaomi, HomeWizard, Zwave, Amazon echo

User avatar
remb0
Posts: 976
Joined: Thursday 11 July 2013 22:21
Target OS: Raspberry Pi
Domoticz version: Beta
Location: The Netherlands
Contact:

Re: Sunscreen script (feedback needed)

Post by remb0 » Thursday 24 May 2018 20:42

Thanks waaren.
A simple but very effective!!

User avatar
EdwinK
Posts: 1248
Joined: Sunday 22 January 2017 22:46
Target OS: Raspberry Pi
Domoticz version: BETA
Location: Rhoon
Contact:

Re: Sunscreen script (feedback needed)

Post by EdwinK » Thursday 24 May 2018 21:17

So far I get this:

Code: Select all

2018-05-24 21:15:00.348 dzVents: Info: Sunscreen: : ------ Start internal script: SunScreen:, trigger: every minute
2018-05-24 21:15:00.349 dzVents: Debug: Sunscreen: : Processing device-adapter for Zonwering: Switch device adapter
2018-05-24 21:15:00.349 dzVents: Debug: Sunscreen: : Sensor not active skipping: rainExpected
2018-05-24 21:15:00.349 dzVents: Debug: Sunscreen: : Sensor not active skipping: uv
2018-05-24 21:15:00.349 dzVents: Debug: Sunscreen: : Checking sensor: rain
2018-05-24 21:15:00.350 dzVents: Debug: Sunscreen: : Checking sensor: temperature
2018-05-24 21:15:00.350 dzVents: Debug: Sunscreen: : Checking sensor: lux
2018-05-24 21:15:00.350 dzVents: Debug: Sunscreen: : Checking sensor: wind
2018-05-24 21:15:00.350 dzVents: Error (2.4.5): Sunscreen: : An error occured when calling event handler SunScreen
2018-05-24 21:15:00.350 dzVents: Error (2.4.5): Sunscreen: : ...domoticz/scripts/dzVents/generated_scripts/SunScreen.lua:73: attempt to index global 'My' (a nil value)
2018-05-24 21:15:00.350 dzVents: Info: Sunscreen: : ------ Finished SunScreen
Seems the script can't write to the specified location. For the rest, the sensors I have at 'buienradar' seem to work. (Dryrun = Y)
Running latest BETA on a Pi-3 | Toon Thermostat | RFxcom | Dashticz V2 |

User avatar
papoo
Posts: 90
Joined: Friday 22 January 2016 23:14
Target OS: Raspberry Pi
Domoticz version: 4.700
Location: France
Contact:

Re: Sunscreen script (feedback needed)

Post by papoo » Thursday 24 May 2018 21:32

place the function library into: /home/pi/domoticz/scripts/lua/

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

User avatar
EdwinK
Posts: 1248
Joined: Sunday 22 January 2017 22:46
Target OS: Raspberry Pi
Domoticz version: BETA
Location: Rhoon
Contact:

Re: Sunscreen script (feedback needed)

Post by EdwinK » Thursday 24 May 2018 21:45

papoo wrote:
Thursday 24 May 2018 21:32
place the function library into: /home/pi/domoticz/scripts/lua/
Spoiler: show

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
Spoiler: show
It was already there.
Running latest BETA on a Pi-3 | Toon Thermostat | RFxcom | Dashticz V2 |

User avatar
EdwinK
Posts: 1248
Joined: Sunday 22 January 2017 22:46
Target OS: Raspberry Pi
Domoticz version: BETA
Location: Rhoon
Contact:

Re: Sunscreen script (feedback needed)

Post by EdwinK » Wednesday 06 June 2018 10:26

rainExpected = {
active = true,
device = 'WUrainExpected', -- This needs to be a virtual sensor of type 'percentage' = Weather Underground
closeRule = function(device)
return device.percentage > 15
end
Weather underground makes this a rain device, so I think this might be a problem.
Running latest BETA on a Pi-3 | Toon Thermostat | RFxcom | Dashticz V2 |

User avatar
EdwinK
Posts: 1248
Joined: Sunday 22 January 2017 22:46
Target OS: Raspberry Pi
Domoticz version: BETA
Location: Rhoon
Contact:

Re: Sunscreen script (feedback needed)

Post by EdwinK » Sunday 10 June 2018 11:15

It's lying to me :(
dzVents: Info: Sunscreen: : Sunscreen is already down
It was not...
Running latest BETA on a Pi-3 | Toon Thermostat | RFxcom | Dashticz V2 |

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest