Luup Repeat for x

Hi Again,

Does anyone know how to/best way to have a function repeat an action for x every y?

I have an ASR-RF Z-Wave dual channel boiler actuator. It seems to go into “fail-safe” if it does not receive a command within a 60 min period.
Because of this fail-safe, i need to send a “HeatOn” command every 30 mins to be sure that it stays on. BUT sometimes it does stay ON.

So what I need to do is have the function repeat every 30 mins for 3 hours then after 3 hours, send the OFF command.

I have this as 2 issues really, In the Morning i check if there was any motion in the house in the last 12 hours and if true then turn send the HeatOn command. As this is triggered by a schedule this can work fine with luup.call_delay though i find it to be less elegant than i would like.
My main issue is the evening as i want the heating triggered if there is motion in the house and as such this can get triggered many times an evening but i want it to stay on until 22:30 regardless of motion as I may be flopped in front of the TV not moving much. This when sticking delays in is not great as it will put hundreds of delays in if i put 4 or so 30 min call_delay’s in.

Any ideas how i can optermise my heating realy calls?

This is what i do currently for the evening (triggered by any PIR):

Evening:

local day = luup.variable_get("urn:rts-services-com:serviceId:DayTime", "Status", 105) local Cold = math.floor(luup.variable_get("urn:upnp-org:serviceId:TemperatureSensor1", "CurrentTemperature", 87));

local t = os.date(‘*t’)
local current_second = t.hour * 3600 + t.min * 60 + t.sec – number of seconds since midnight
local min_time_in_seconds = 5 * 3600 + 45 * 60 – 05:45
local max_time_in_seconds = 21 * 3600 + 30 * 60 – 21:30
local MASTERBEDRADDESIRED = 21
local RADTHERMO = “urn:upnp-org:serviceId:TemperatureSetpoint1_Heat”
local MASTERBEDRAD = 93
local MASTERBEDRADTEMP = luup.variable_get(“urn:upnp-org:serviceId:TemperatureSetpoint1_Heat”,“SetpointTarget”,93)

function MasterBedroomRad ()
if (MASTERBEDRADTEMP ~= MASTERBEDRADDESIRED) then
luup.call_action( RADTHERMO, “Set SetCurrentSetpoint”,{ NewCurrentSetpoint= MASTERBEDRADDESIRED}, MASTERBEDRAD)
end
end

function Heating()
if (current_second > max_time_in_seconds) and (current_second < min_time_in_seconds) then
luup.call_action(“urn:upnp-org:serviceId:HVAC_UserOperatingMode1”, “SetModeTarget”,{ NewModeTarget= “Off”}, 97)
elseif (current_second > min_time_in_seconds) and (current_second < max_time_in_seconds) and (day == “0”) and (Cold < 9) then
luup.call_action(“urn:upnp-org:serviceId:HVAC_UserOperatingMode1”, “SetModeTarget”,{ NewModeTarget= “HeatOn”}, 97)
end
end

luup.call_delay(‘Heating’, 0)
luup.call_delay(‘MasterBedroomRad’, 0)
luup.call_delay(‘Heating’, 1800)
luup.call_delay(‘Heating’, 3600)

Morning (Triggered by schedule):

local DININGPIR = 156 local DOGPIR = 158 local FDPIR = 160 local GARAGEPIR = 160 local KITCHENPIR = 157 local LANDINGPIR = 167 local LIVINGPIR = 155 local BDPIR = 161

local HSWITCH = 97
local DELAY = 43200

local SES_SID = “urn:micasaverde-com:serviceId:SecuritySensor1”
local HVACO_SID = “urn:upnp-org:serviceId:HVAC_UserOperatingMode1”
local Cold= math.floor(luup.variable_get(“urn:upnp-org:serviceId:TemperatureSensor1”, “CurrentTemperature”, 87));
local RADTHERMO = “urn:upnp-org:serviceId:TemperatureSetpoint1_Heat”
local MASTERBEDRADDESIRED = 21
local MASTERBEDRADTEMP = luup.variable_get(“urn:upnp-org:serviceId:TemperatureSetpoint1_Heat”,“SetpointTarget”,93)

local t = os.date(‘*t’)
local maxtime = 08 * 3600 + 30 * 60 – 08:30
local current_second = t.hour * 3600 + t.min * 60 + t.sec – number of seconds since midnight

local lastTripDiPIR = luup.variable_get( SES_SID, “LastTrip”, DININGPIR) or os.time()
local lastTripDoPIR = luup.variable_get( SES_SID, “LastTrip”, DOGPIR) or os.time()
local lastTripFDPIR = luup.variable_get( SES_SID, “LastTrip”, FDPIR) or os.time()
local lastTripGPIR = luup.variable_get( SES_SID, “LastTrip”, GARAGEPIR) or os.time()
local lastTripKPIR = luup.variable_get( SES_SID, “LastTrip”, KITCHENPIR) or os.time()
local lastTripLaPIR = luup.variable_get( SES_SID, “LastTrip”, LANDINGPIR) or os.time()
local lastTripLiPIR = luup.variable_get( SES_SID, “LastTrip”, LIVINGPIR) or os.time()
local lastTripBDPIR = luup.variable_get( SES_SID, “LastTrip”, BDPIR) or os.time()

function heating ()
if (current_second < maxtime) and ((os.time() - lastTripDiPIR) < DELAY) or ((os.time() - lastTripDoPIR) < DELAY) or ((os.time() - lastTripFDPIR) < DELAY) or ((os.time() - lastTripGPIR) < DELAY) or ((os.time() - lastTripKPIR) < DELAY) or ((os.time() - lastTripLaPIR) < DELAY) or ((os.time() - lastTripLiPIR) < DELAY) or ((os.time() - lastTripBDPIR) < DELAY) and (Cold <= 7) then
luup.call_action( HVACO_SID, “SetModeTarget”,{ NewModeTarget= “HeatOn”}, HSWITCH)
heatingREPEAT()
end
end

function heatingOff ()
luup.call_action( HVACO_SID, “SetModeTarget”,{ NewModeTarget= “Off”}, HSWITCH)
end

function heatingREPEAT ()
if (current_second > maxtime) then
heatingOff()
elseif (current_second < maxtime) then
luup.call_timer(“heating”, “1”, “30m”, “”)
luup.call_timer(“heating”, “2”, “1,2,3,4,5,6,7” , “09:00:00” ,“”)
end
end

function MasterBedroomRad ()
if (MASTERBEDRADTEMP ~= MASTERBEDRADDESIRED) then
luup.call_action( RADTHERMO, “Set SetCurrentSetpoint”,{ NewCurrentSetpoint= MASTERBEDRADDESIRED}, MASTERBEDRAD)
end
end

heating ()
MasterBedroomRad ()

I only just added the heatingREPEAT function today so i have not tested it yet, for the Morning scene i think it would work fine but for the motion triggered scene i know its rubbish and thats what i need to find a good solution for primarily.

I have an ASR-RF Z-Wave dual channel boiler actuator. It seems to go into "fail-safe" if it does not receive a command within a 60 min period.

I’m using two single-channel versions of this device (ASR-ZW) and do not need to periodically resend the commands. It’s my understanding that it enters “fail-safe” if it believes it has lost Z-Wave communication. You could try reducing the poll interval in case some of the polls are failing - you should see that in LuaUPnP.log Physical location of these devices can be a challenge as the devices they control are usually large lumps of signal-sucking metal!

Having written that, a quick check in the manual for this device does hint that, when used with its intended partner (HRT4-ZW) it gets refreshed at hourly intervals so maybe yours is working properly and mine aren’t…

My solution to the complex logic requirements of heating is to use the Program Logic Event Generator plugin: http://forum.micasaverde.com/index.php/topic,12759.0.html Adding a resend every 30 minutes would require adding a schedule for 30 minute intervals, and-ing the name of that schedule with the existing condition calling for heat and setting an action that sends “on” to the relay. CodingTime < 00:00:30. :slight_smile:

Thanks RexBeckett! That might explain why sometimes the heating stays on when I do not specify a delay/timer. I will have a play with that and see if I can put a powered z-wave device close. I would much prefer not to have to repeat if I did not have to.

I will take a look at the PL Event plugin, I think that a mind much more experienced than mine at this would be the best place to put my requirement. I have downloaded the plugins and will give it a whirl. Having never used the plugin, it might take more than 30 seconds but once i get my head around it, im sure my issues will be resolved. For the sake of others, i will post what i do, once i figure it out.

OK I have stared at the PLEG plugin for a while now and I can not see how to do the following:

If Motion on any one of my 8 PIR sensors
and it is after 17:00
and it is before 22:30
and it is Colder that 7c outside

then

Set my radiator to the desired temp if not set to that temp already (save battery)
Turn on the heating and repeat the “HeatOn” command every 30 mins

then

at 22:30 send the “Off” command
and do not send the “HeatOn” command if there is motion between 22:30 and 17:00 the next day.

Also in the Morning i want to check if there was anyone in the house in the last 12 hours (LastTrip of PIR’s)
if so put the heating on at 3am on Monday and 5AM every other day
if it is cold outside

then send Off at 9am.

I also have a pipe freeze scene if it drops below 5c inside to turn the heating on for 15 mins and check temp again in 3 hours.

Can you help here RexBeckett or anyone familiar with PLEG?

The following does most of what you specified. I changed the 15 minutes on for freeze to 30 minutes … otherwise I would need another schedule.

With PLEG
Inputs:
Triggers:
M1 - M8 for the 8 Motion Sensors
Device Property
OutSideTemp
InsideTemp
Schedule
Periodic - Every 30 Minutes
FreezeCheck - Every 3 Hours
Weekly5 - Scheduled at 5AM on specified days
Weekly3 - Scheduled at 3AM on specified days

Conditions:
AnyMotion = M1 or M2 or … M8
HeatOnNight = (17:00:00; Periodic; 22:30:00) and (OutSideTemp < 7) and (AnyMotion; Periodic < 30:00)
HeatOnMorning = (Weekly3 or Weekly5) and (OutSideTemp < 7) and (AnyMotion; NOW < 12:00:00)
FreezeOn = FreezeCheck and (InsideTemp < 5)
HeatOff = (9:00:00; Periodic; 9:30:00) or (22:30; Periodic; 23:00) or (FreezeOn; Periodic > 30:00)

Brilliant. Thankyou RichardTSchaefer! I was just starring at your anim gif on your site and managed to get a bit further but the above is exactly what I was missing. Now I have a much greater understanding of how PLEG is configured! Thanks!

Getting RichardTSchaefer to write your whole heating logic is quite some achievement, andyvirus. I would think it ranks with an autographed first edition! ;D

I know, I never expected such a kind gesture! Thank you again! :smiley:

@andyvirus

You’ve probably got this all bolted down now but it may help others. I decided to add the refresh logic to my system (belt, suspenders and a length of string… ;D). Simple is good so I went with the following additions to my existing heating control logic:

Inputs Schedule
I30M: Interval, 30 minutes

Inputs Device Properties
HWRelayMode: Hot Water Relay, Mode Target

Conditions
HWRelayPulse: I30M

Actions
HWRelayPulse: Hot Water Relay, NewModeTarget {(HWRelayMode)}

All it does is resend the last set mode (Off or Heat) every 30 minutes. As long as the HWRelayPulse condition expression is below any condition that changes the state of Hot Water Relay, it should not interfere with existing logic.

Hi Again! ;D

Checking my logs today I can see that HeatOn is being triggered every half hour (on the half hour) and every 3 hours (on the hour) FreezeOn is triggered even though the temp in the room is not less than “5” (its 16).

Here is my exact logic:

Inputs Triggers
PIRDIN
PIRDOG
PIRLIV
PIRKIT … and so on (all PIR’s)

Inputs Schedules
periodic: Interval:30m
FreezeCheck: Interval:3h
Weekly5: Weekly:2,3,4,5,6,7
Weekly3: Weekly:1

Inputs Device Properties
Bed1Temp : MasterBedroom_4 in 1 sensor (temp) CurrentTemperature - 16
OutsideTemp: Temperature CurrentTemperature - 0.6
Bed1Rad: Master Bedroom Radiator SetpointTarget - 21
Bed4Temp Grants_4 in 1 sensor (temp): CurrentTemperature - 16

Conditions

AnyMotion: PIRDIN or PIRDOG or PIRHALL or PIRBED4 or PIRKIT or PIRLAN or PIRLIV or PIRBED1 or PIRUTIL
HeatOnNight: (17:00:00; Periodic; 22:30:00) and (OutSideTemp < 7) and (AnyMotion; Periodic < 30:00)
HeatOnMorning: (Weekly3 or Weekly5) and (OutSideTemp < 7) and (AnyMotion; NOW < 12:00:00)
FreezeOn: FreezeCheck and (Bed1Temp < 5)
HeatOff: (09:00:00; Periodic; 09:30:00) or (22:30:00; Periodic; 23:00:00) or (FreezeOn; Periodic > 30:00)

Actions
I have Scenes triggered by above conditions met. HeatON HeatOFF (Do I need scenes? Or can PLEG fire off the On/OFF?)

From the Logs (false statements omitted):
09 02/21/13 9:58:38.078 JobHandler_LuaUPnP::Run device 185 Heating PLEG room 19 type urn:schemas-rts-services-com:device:ProgramLogicEG:1 id parent 0/0x9b8fb0 upnp: 0 <0x2b7af000>
07 02/21/13 10:00:00.053 Event::Evaluate 30 HeatOff scene Heating PLEG OFF is true users:(null) allow:1 <0x2f2e3680>
08 02/21/13 10:00:00.054 Scene::RunScene running 49 Heating PLEG OFF <0x2f2e3680>
07 02/21/13 10:30:00.133 Event::Evaluate 30 HeatOff scene Heating PLEG OFF is true users:(null) allow:1 <0x2f2e3680>
08 02/21/13 10:30:00.133 Scene::RunScene running 49 Heating PLEG OFF <0x2f2e3680>
07 02/21/13 11:00:00.130 Event::Evaluate 30 HeatOff scene Heating PLEG OFF is true users:(null) allow:1 <0x2f2e3680>
08 02/21/13 11:00:00.130 Scene::RunScene running 49 Heating PLEG OFF <0x2f2e3680>
09 02/21/13 11:18:33.775 JobHandler_LuaUPnP::Run device 185 Heating PLEG room 19 type urn:schemas-rts-services-com:device:ProgramLogicEG:1 id parent 0/0xc56fb0 upnp: 0 <0x2ac6f000>
07 02/21/13 11:30:00.132 Event::Evaluate 30 HeatOff scene Heating PLEG OFF is true users:(null) allow:1 <0x2e7a3680>
08 02/21/13 11:30:00.133 Scene::RunScene running 49 Heating PLEG OFF <0x2e7a3680>
07 02/21/13 12:00:00.124 Event::Evaluate 29 FreezeOn scene Heating PLEG ON is true users:(null) allow:1 <0x2e7a3680>
08 02/21/13 12:00:00.125 Scene::RunScene running 47 Heating PLEG ON <0x2e7a3680>
07 02/21/13 13:00:00.129 Event::Evaluate 30 HeatOff scene Heating PLEG OFF is true users:(null) allow:1 <0x2e7a3680>
08 02/21/13 13:00:00.129 Scene::RunScene running 49 Heating PLEG OFF <0x2e7a3680>
09 02/21/13 13:01:56.626 JobHandler_LuaUPnP::Run device 185 Heating PLEG room 19 type urn:schemas-rts-services-com:device:ProgramLogicEG:1 id parent 0/0xd66fc0 upnp: 0 <0x2b133000>
07 02/21/13 13:30:00.133 Event::Evaluate 30 HeatOff scene Heating PLEG OFF is true users:(null) allow:1 <0x2ec67680>
08 02/21/13 13:30:00.134 Scene::RunScene running 49 Heating PLEG OFF <0x2ec67680>
07 02/21/13 14:00:00.129 Event::Evaluate 30 HeatOff scene Heating PLEG OFF is true users:(null) allow:1 <0x2ec67680>
08 02/21/13 14:00:00.130 Scene::RunScene running 49 Heating PLEG OFF <0x2ec67680>
07 02/21/13 14:30:00.133 Event::Evaluate 30 HeatOff scene Heating PLEG OFF is true users:(null) allow:1 <0x2ec67680>
08 02/21/13 14:30:00.133 Scene::RunScene running 49 Heating PLEG OFF <0x2ec67680>
09 02/21/13 14:43:45.885 JobHandler_LuaUPnP::Run device 185 Heating PLEG room 19 type urn:schemas-rts-services-com:device:ProgramLogicEG:1 id parent 0/0x9b8fb0 upnp: 0 <0x2abc8000>
07 02/21/13 15:00:00.129 Event::Evaluate 30 HeatOff scene Heating PLEG OFF is true users:(null) allow:1 <0x2e6fb680>
08 02/21/13 15:00:00.130 Scene::RunScene running 49 Heating PLEG OFF <0x2e6fb680>
07 02/21/13 15:00:00.163 Event::Evaluate 29 FreezeOn scene Heating PLEG ON is true users:(null) allow:1 <0x2e6fb680>
08 02/21/13 15:00:00.164 Scene::RunScene running 47 Heating PLEG ON <0x2e6fb680>
07 02/21/13 16:00:00.173 Event::Evaluate 30 HeatOff scene Heating PLEG OFF is true users:(null) allow:1 <0x2e6fb680>
08 02/21/13 16:00:00.174 Scene::RunScene running 49 Heating PLEG OFF <0x2e6fb680>

Any idea why that happens?

It does not help for me to see the log of the scene activation … I need to send the log of PLEG actions.
Just show the complete log near one of the 3Hr marks … that will also cover the 30 minute interval.

Here you go: Lua PLEG Heat - Pastebin.com (did not want to flood the screen of the forum)

Actually, by sticking it into pastebin and formating it with Lua highlighting i can see the following so think i twigged it:

{name =‘Bed1Temp’, state = false, seq = 0}

when my other sensor says:

{name =‘Bed4Temp’, state = 16, seq = 0}

Odd that in the GUI it shows 16 but not in the state… I will have a look at the sensor this weekend, it seems to have sync error in the Vera gui so that might be that issue.
I have changed the FreezeOn Condition to use Bed4Temp as that reports correctly. but still every 30 mins an off command is sent and every evaluation HeatOff is True: Luup.log HeatOff - Pastebin.com

Any idea why HeatOff is always true?

OK I think I know why it is always true,

(FreezeOn; Periodic > 30:00)

If i read that correctly the expression is true if Periodic is greater than FreezeOn by 30 mins.

As it has been more than 30 mins since FreezeOn triggered last (erroneously due to my sensor i think), it is always true. But even if it had not triggered it would still be true as FreezeOn would be 0.

Am I reading that correctly?

Your analysis is correct … but where is the rest of the clause …

This fragment will be true even if it Froze last week.

This should have been something like:
FreezeOn and (FreezeOn; Periodic > 30:00)

The sequence expression does not care if the FreezeON is still true … it only cares when it last became true!

Thanks again RichardTSchaefer, I think it is sorted now.

I was using

Condition
HeatOff: (09:00:00; Periodic; 09:30:00) or (22:30:00; Periodic; 23:00:00) or (FreezeOn; Periodic > 30:00)

I am now using
Condition
HeatOff: (09:00:00; Periodic; 09:30:00) or (22:30:00; Periodic; 23:00:00) or (FreezeOn and (FreezeOn; Periodic > 30:00))

@RexBeckett

Thanks for the additional condition example for the 30 min repeat. I did not want the OFF to be sent every 30 mins so I tried a Trigger for the relay when it was set to “Heat” instead of and ModeTarget but that failed as I have a weird bug with both relays in Vera. Even though if I click Heat or Off in the GUI, the TargetMode never changes to reflect the gui. So I went with this addition to the existing HeatOn condition:

Condition
(Weekly3; Periodic; 09:00:00) or (Weekly5; Periodic; 09:00:00) and (OutSideTemp < 7) and (AnyMotion; NOW < 12:00:00)

Hopefully that will work. It seems to but I will know in the morning :slight_smile:

Thanks for your continued help RexBeckett & RichardTSchaefer!

I have a weird bug with both relays in Vera.
We may be seeing the same thing: Vera seems to treat the ASR-ZW relay the same as it does the combination of HRT4-ZW and ASR-ZW. So in scenes and PLEG/PLTS, it offers a lot of commands that don't actually do anything to an ASR-ZW on its own (like setpoints etc.)..

The only commands that seem to work reliably for the ASR-ZW on my system are SetModeTarget and GetModeTarget. The values for these are “Off” and “Heat”.

@andyvirus

I did not want the OFF to be sent every 30 mins...
I don't think there's any penalty in re-sending a command periodically - as long as it's the [u]right[/u] command. :) I am just repeating the last command that got sent to the relay - whatever it was. Perusal of the log suggests that both Vera and the ASR-ZW are [i]dumb and happy[/i] with this arrangement - even when a new status was set just milliseconds before the repeat.

I agree, there is not harm in sending the correct command every 30 mins, if vera reported the state correctly then I would be doing this too.

As it goes my heating and hot water is coming on every 30 mins from midnight now. No idea why. It looks to me that Periodic is firing this action so i have probably used it wrong. Any idea what the correct usage would be to have this repeat the the HeatOn command every 30 mins?

Conditions

HeatOnMorning: (Weekly3; Periodic; 09:00:00) or (Weekly5; Periodic; 09:00:00) and (OutSideTemp < 7) and (AnyMotion; NOW < 12:00:00)
HotWMorning: (Weekly3; Periodic; 07:00:00) or (Weekly5; Periodic; 07:30:00) and (AnyMotion; NOW < 12:00:00)

Log from 1 min to midnight to a few mins after. Heating and hot water keep being fired up constantly.

So sorry to have to keep asking for help…

I see a couple of problems:

HeatOnMorning: (Weekly3; Periodic; 09:00:00) or (Weekly5; Periodic; 09:00:00) and (OutSideTemp < 7) and (AnyMotion; NOW < 12:00:00) HotWMorning: (Weekly3; Periodic; 07:00:00) or (Weekly5; Periodic; 07:30:00) and (AnyMotion; NOW < 12:00:00)
Your are missing a parenthesis around the Weekly3 and Weekly5 parts of these clauses. The expresions: (Weekly3; Periodic; 07:00:00) Will fire at midnight ... Because Weekly3 has a time the from the previoius day, Periodic is at midnight and 7:00PM are all ordered!

You should replace with:
((Weekly3; Periodic < 4:00) or (Weekly5; Periodic < 4:00:00)) and … ((OutSideTemp < 7) and (AnyMotion; Periodic < 12:00:00)

So sorry to have to keep asking for help...
I believe that's the point of this forum: To help each other! :)

I think the expanded form of RichardTSchaefer’s suggestions would be:

HeatOnMorning: ((Weekly3; Periodic < 6:00:00) or (Weekly5; Periodic < 4:00:00)) and (OutSideTemp < 7) and (AnyMotion; Periodic < 12:00:00)

HotWMorning: ((Weekly3; Periodic < 6:00:00) or (Weekly5; Periodic < 4:00:00)) and (AnyMotion; Periodic < 12:00:00)

Watch out for parenthesis in mixed and/or expressions. They can make a big difference in how the terms are evaluated so it is usually better to have too many rather than too few. By grouping the Weekly3… and Weekly5… sequences with outer parenthesis, the condition will fire if either of the two Weekly… sequences are true but only if both the OutSideTemp… and AnyMotion… clauses are true.