Sunscreen script (feedback needed)

Moderator: leecollings

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

Sunscreen script (feedback needed)

Post by remb0 »

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: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: Sunscreen script (feedback needed)

Post by waaren »

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.
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
User avatar
remb0
Posts: 499
Joined: Thursday 11 July 2013 22:21
Target OS: Raspberry Pi / ODroid
Domoticz version: Beta
Location: The Netherlands
Contact:

Re: Sunscreen script (feedback needed)

Post by remb0 »

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: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: Sunscreen script (feedback needed)

Post by waaren »

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
}
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
User avatar
EdwinK
Posts: 1820
Joined: Sunday 22 January 2017 21:46
Target OS: Raspberry Pi / ODroid
Domoticz version: BETA
Location: Rhoon
Contact:

Re: Sunscreen script (feedback needed)

Post by EdwinK »

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 (rooted) | Hue | Tuya | IKEA tradfri | Dashticz V3 on Lenovo Huawei Tablet | Conbee
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: Sunscreen script (feedback needed)

Post by waaren »

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.
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
User avatar
remb0
Posts: 499
Joined: Thursday 11 July 2013 22:21
Target OS: Raspberry Pi / ODroid
Domoticz version: Beta
Location: The Netherlands
Contact:

Re: Sunscreen script (feedback needed)

Post by remb0 »

Thanks waaren.
A simple but very effective!!
User avatar
EdwinK
Posts: 1820
Joined: Sunday 22 January 2017 21:46
Target OS: Raspberry Pi / ODroid
Domoticz version: BETA
Location: Rhoon
Contact:

Re: Sunscreen script (feedback needed)

Post by EdwinK »

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 (rooted) | Hue | Tuya | IKEA tradfri | Dashticz V3 on Lenovo Huawei Tablet | Conbee
User avatar
papoo
Posts: 126
Joined: Friday 22 January 2016 22:14
Target OS: Raspberry Pi / ODroid
Domoticz version: 4.10
Location: France
Contact:

Re: Sunscreen script (feedback needed)

Post by papoo »

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: 1820
Joined: Sunday 22 January 2017 21:46
Target OS: Raspberry Pi / ODroid
Domoticz version: BETA
Location: Rhoon
Contact:

Re: Sunscreen script (feedback needed)

Post by EdwinK »

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 (rooted) | Hue | Tuya | IKEA tradfri | Dashticz V3 on Lenovo Huawei Tablet | Conbee
User avatar
EdwinK
Posts: 1820
Joined: Sunday 22 January 2017 21:46
Target OS: Raspberry Pi / ODroid
Domoticz version: BETA
Location: Rhoon
Contact:

Re: Sunscreen script (feedback needed)

Post by EdwinK »

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 (rooted) | Hue | Tuya | IKEA tradfri | Dashticz V3 on Lenovo Huawei Tablet | Conbee
User avatar
EdwinK
Posts: 1820
Joined: Sunday 22 January 2017 21:46
Target OS: Raspberry Pi / ODroid
Domoticz version: BETA
Location: Rhoon
Contact:

Re: Sunscreen script (feedback needed)

Post by EdwinK »

It's lying to me :(
dzVents: Info: Sunscreen: : Sunscreen is already down
It was not...
Running latest BETA on a Pi-3 | Toon® Thermostat (rooted) | Hue | Tuya | IKEA tradfri | Dashticz V3 on Lenovo Huawei Tablet | Conbee
grpfge
Posts: 4
Joined: Saturday 29 July 2017 8:57
Target OS: Raspberry Pi / ODroid
Domoticz version: 4.10164
Location: Germany NRW
Contact:

Re: Sunscreen script (feedback needed)

Post by grpfge »

Hey
I place the function library into /home/pi/domoticz/scripts/lua/
Start the sunscreen script and get:
2019-01-28 19:38:00.636 Status: dzVents: Debug: Sunscreen: Processing device-adapter for Sonnenschutz: Switch device adapter
2019-01-28 19:38:00.637 Status: dzVents: Debug: Sunscreen: Processing device-adapter for Test: Switch device adapter
2019-01-28 19:38:00.637 Status: dzVents: Error (2.4.7): Sunscreen: An error occured when calling event handler sunscreen
2019-01-28 19:38:00.637 Status: dzVents: Error (2.4.7): Sunscreen: ...domoticz/scripts/dzVents/generated_scripts/sunscreen.lua:74: attempt to index global 'My' (a nil value)
2019-01-28 19:38:00.638 Status: dzVents: Info: Sunscreen: ------ Finished sunscreen

function LogActions()
-- LogFile=string.gsub(LogFile,"~d",os.date("%Y-%m-%d"))
LogFile=string.gsub(LogFile,"~m",os.date("%Y-%m"))

74: 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

What's wrong with My ?
Matthias
User avatar
EdwinK
Posts: 1820
Joined: Sunday 22 January 2017 21:46
Target OS: Raspberry Pi / ODroid
Domoticz version: BETA
Location: Rhoon
Contact:

Re: Sunscreen script (feedback needed)

Post by EdwinK »

It's part of the logging on line 53. Change the 'Y' to 'N', and the script will work. I don't know why it doesn't want to writ the file, but it isn't really important for the working of the script.
Running latest BETA on a Pi-3 | Toon® Thermostat (rooted) | Hue | Tuya | IKEA tradfri | Dashticz V3 on Lenovo Huawei Tablet | Conbee
User avatar
EdwinK
Posts: 1820
Joined: Sunday 22 January 2017 21:46
Target OS: Raspberry Pi / ODroid
Domoticz version: BETA
Location: Rhoon
Contact:

Re: Sunscreen script (feedback needed)

Post by EdwinK »

Since today I notice that my sunscreen isn't going to lower or raise automaticly anymore using this script although the debug output says it is. When I press the button on my tablet it just works, so the right signal is send to the KAKU switch.
2019-04-18 14:46:00.539 Status: dzVents: Info: Sunscreen: ------ Start internal script: SunScreen:, trigger: every minute
2019-04-18 14:46:00.540 Status: dzVents: Debug: Sunscreen: Processing device-adapter for Sunscreen - Manual: Switch device adapter
2019-04-18 14:46:00.541 Status: dzVents: Debug: Sunscreen: Processing device-adapter for Sunscreen: Switch device adapter
2019-04-18 14:46:00.542 Status: dzVents: Debug: Sunscreen: Sensor not active skipping: rainExpected
2019-04-18 14:46:00.542 Status: dzVents: Debug: Sunscreen: Processing device-adapter for Temperature: Temperature device adapter
2019-04-18 14:46:00.542 Status: dzVents: Debug: Sunscreen: Checking sensor: temperature
2019-04-18 14:46:00.543 Status: dzVents: Debug: Sunscreen: Processing device-adapter for Wind: Wind device adapter
2019-04-18 14:46:00.543 Status: dzVents: Debug: Sunscreen: Checking sensor: wind
2019-04-18 14:46:00.543 Status: dzVents: Debug: Sunscreen: Sensor not active skipping: uv
2019-04-18 14:46:00.544 Status: dzVents: Debug: Sunscreen: Checking sensor: lux
2019-04-18 14:46:00.544 Status: dzVents: Debug: Sunscreen: Processing device-adapter for Rain: Rain device
2019-04-18 14:46:00.544 Status: dzVents: Debug: Sunscreen: Checking sensor: rain
2019-04-18 14:46:00.545 Status: dzVents: Info: Sunscreen: Sun is shining, all thresholds OK, lowering sunscreen
2019-04-18 14:46:00.545 Status: dzVents: Info: Sunscreen: ------ Finished SunScreen
Running latest BETA on a Pi-3 | Toon® Thermostat (rooted) | Hue | Tuya | IKEA tradfri | Dashticz V3 on Lenovo Huawei Tablet | Conbee
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest