Stagger & randomise turning off of lights at night

Just a simple one from me today, as I wanted a way to turn off my external lights at night.

However, I wanted to add a bit of randomness to it, rather than the whole outside of the house being plunged into darkness at a specific time every night.

Firstly, I have a Group, and a number of Switch items which belong to this group:

Group gExternalLights "External Lights" <light> 

Switch	Light_Porch	"Porch Lights [%s]" <light> (gExternalLights)
Switch	Light_Patio	"Patio Lights [%s]" <light> (gExternalLights)
Switch	Light_Deck	"Deck Lights [%s]" <light> (gExternalLights)

Then, this simple rule:

rule "Turn External Lights off from 23:30"
when 
	Time cron "0 30 23 ? * * *"
then	
	gExternalLights.members.forEach[ temp | 
		var int randomTime = (new java.util.Random).nextInt(1800)
		createTimer(now.plusSeconds(randomTime)) [|
			temp.sendCommand(OFF)
		]
	]
end

This roughly translates to: At 23:30 every day, create a random timer (0-30 minutes) for each item that belongs to the group, and after that time has elapsed, turn that light off.

5 Likes

Good idea!
Simple concise clever code, I like it.

1 Like

you can simplify the code by turning off whole lights group instead of single item in it.

using something very similar.
cheers

That’s exactly what I didn’t want to do! :laughing:

I’m trying to use your excellent rule under OH3. The script I have is as follows but with noted error from log file. I would appreciate any suggestions. (I’m not a coder so I’m struggling a bit but do understand some of the syntax.) Thank you

ir.Item(“PowerOutlet”).members.forEach[temp |
var int randomTime = (new java.util.Random).nextInt(1800)
createTimer(now.plusSeconds(randomTime)) |
temp.sendCommand(OFF)

]

EOF

Log error: no viable alternative at input ‘|’; line 3, column 150, length 1

I’ve not tried OH3 yet, but you’ve not used the ‘code fences’ to paste your code here, so I’m not sure if it’s that, but it looks like you’re missing a [, and I’m not sure that the first part is correct - mine is acting on a Group, yours… isn’t?

Thanks for responding. Here is the rule:

triggers:
  - id: "1"
    configuration:
      cronExpression: 0 0 10 * * ? *
    type: timer.GenericCronTrigger
conditions: []
actions:
  - inputs: {}
    id: "2"
    configuration:
      type: application/vnd.openhab.dsl.rule
      script: |-
        ir.Item("PowerOutlet").members.forEach[temp | 
        		var int randomTime = (new java.util.Random).nextInt(1800)
        		createTimer(now.plusSeconds(randomTime)) |
        		temp.sendCommand(OFF)
                
        	]
        EOF
    type: script.ScriptAction

I think you’re definitely missing a [

triggers:
  - id: "1"
    configuration:
      cronExpression: 0 0 10 * * ? *
    type: timer.GenericCronTrigger
conditions: []
actions:
  - inputs: {}
    id: "2"
    configuration:
      type: application/vnd.openhab.dsl.rule
      script: |-
        ir.Item("PowerOutlet").members.forEach[temp | 
        		var int randomTime = (new java.util.Random).nextInt(1800)
        		createTimer(now.plusSeconds(randomTime)) [|
        		temp.sendCommand(OFF)
                
        	]
        EOF
    type: script.ScriptAction

Give that a try (I’ve not tested it, only added from my phone what I think it’s the missing [)

Here is what I get:

i> r.Item(“PowerOutlet”).members.forEach[temp |

  var int randomTime = (new java.util.Random).nextInt(1800)
  createTimer(now.plusSeconds(randomTime)) [|
  temp.sendCommand(OFF)
                                              
  ]  

EOF

The log response was mismatched input ‘EOF’ expecting ‘]’; line 7, column 239, length 3

Here is the rule:

Summary
> triggers:
>   - id: "1"
>     configuration:
>       cronExpression: 0 0 10 * * ? *
>     type: timer.GenericCronTrigger
> conditions: []
> actions:
>   - inputs: {}
>     id: "2"
>     configuration:
>       type: application/vnd.openhab.dsl.rule
>       script: |-
>         ir.Item("PowerOutlet").members.forEach[temp | 
>         		var int randomTime = (new java.util.Random).nextInt(1800)
>         		createTimer(now.plusSeconds(randomTime)) [|
>         		temp.sendCommand(OFF)
>                                                           
>               ]  
>         end
>     type: script.ScriptAction

I think you need another ] at the end…

Count the number of opening square and round brackets, you’ll find a mismatch in the number of closing ones :slight_smile:

1 Like

No go - and maybe a step backwards…

ir.Item(“PowerOutlet”).members.forEach ___ [temp |
var int randomTime = (new java.util.Random).nextInt(1800)
createTimer(now.plusSeconds(randomTime))] [|
temp.sendCommand(OFF)]
end

Log: 1. The method or field ir is undefined; line 1, column 0, length 2
2. The method or field temp is undefined; line 4, column 157, length 4
3. The method or field end is undefined; line 5, column 180, length 3
4. Invalid number of arguments. The method createTimer(ZonedDateTime, Procedure0) is not applicable for the arguments (ZonedDateTime); line 3, column 109, length 11
5. There is no context to infer the closure’s argument types from. Consider typing the arguments or put the closures into a typed context.; line 1, column 38, length 112
6. This expression is not allowed in this context, since it doesn’t cause any side effects.; line 3, column 151, length 28

here is the rule:

    triggers:
  - id: "1"
    configuration:
      cronExpression: 0 0 10 * * ? *
    type: timer.GenericCronTrigger
conditions: []
actions:
  - inputs: {}
    id: "2"
    configuration:
      type: application/vnd.openhab.dsl.rule
      script: |-
        ir.Item("PowerOutlet").members.forEach[temp | 
        		var int randomTime = (new java.util.Random).nextInt(1800)
        		createTimer(now.plusSeconds(randomTime))] [| 
        		temp.sendCommand(OFF)]
        end
    type: script.ScriptAction

Try this?

triggers:
  - id: "1"
    configuration:
      cronExpression: 0 0 10 * * ? *
    type: timer.GenericCronTrigger
conditions: []
actions:
  - inputs: {}
    id: "2"
    configuration:
      type: application/vnd.openhab.dsl.rule
      script: |-
        ir.Item("PowerOutlet").members.forEach[temp | 
        		var int randomTime = (new java.util.Random).nextInt(1800)
        		createTimer(now.plusSeconds(randomTime)) [|
        		temp.sendCommand(OFF)
                ]
        	]
        EOF
    type: script.ScriptAction

Thank you for your patience but still no luck. I made another change and got down to a single error.

The log error is: missing EOF at ‘:’; line 1, column 8, length 1 - this line is: itemName: PowerOutlet…

triggers:

  • id: “1”
    configuration:
    cronExpression: 0 0 10 * * ? *
    type: timer.GenericCronTrigger
    conditions: []
    actions:
  • inputs: {}
    id: “4”
    configuration:
    type: application/vnd.openhab.dsl.rule
    script: |-
    itemName: PowerOutlet.members.forEach[temp |
    var int randomTime = (new java.util.Random).nextInt(1800)
    createTimer(now.plusSeconds(randomTime)) [|
    temp.sendCommand(OFF)
    ]
    ]
    end
    type: script.ScriptAction
triggers:
  - id: "1"
    configuration:
      cronExpression: 0 0 10 * * ? *
    type: timer.GenericCronTrigger
conditions: []
actions:
  - inputs: {}
    id: "4"
    configuration:
      type: application/vnd.openhab.dsl.rule
      script: |-
        itemName: PowerOutlet.members.forEach[temp | 
                		var int randomTime = (new java.util.Random).nextInt(1800)
                		createTimer(now.plusSeconds(randomTime)) [|
                		temp.sendCommand(OFF)
                        ]
                	]
                end
    type: script.ScriptAction

It’s not valid DSL rules language. Are you actually trying to write in DSL? The original example was in DSL, but you seem to have mangled some javascript into your reworked version.
What is PowerOutlet,is this a Group type Item?

Yes, PowerOutlet is a Group item. In order to simplify the rule I could work with one of the items, for example: OfficeSmartOutlet.

Just get rid of that and the colon,the rest looks reasonable now.
I’m not sure if you might need to import Random, let’s see.

I deleted the colon and had the resulting errors:

  1. The method or field itemName is undefined; line 1, column 0, length 8
  2. The method or field end is undefined; line 7, column 236, length 3

I suppose I should have emphasised AND.
Get rid of itemName
Get rid of the colon following that.
Allow the line to begin with PowerOutlet.

And yes, you can get rid of end as well.

1 Like

I think that might have done it!!! The real test will be later tonight.

Thank you so much.