Anti burglary presence simulation

What persistence service do you use to retrieve the historical items of gLights_auto?

1 Like

Very cool approach.
Some ideas that could improve the solution:

  • Store the date when the auto-lighting has been activated.
  • Get the historic value from the stored date -7 + (days since then mod 7)
  • Add probabilty factor when switching on the lights (e.g. switch on by 90% only).
  • Switch-off time should vary as well, but it needs to be ensured by a rule the at a certain point in time (e.g. midnight) lights will be set to OFF so no light burns forever.

This would ensure that

  1. the pattern never repeats 100% (which it currently does). If you are away for more than a few days this will make things even more realistic.
  2. we avoid that the changed pattern results in shifting the switching time after some days to someting unrealistic.

Pretty sure I missed some scenarios but the basic idea should be clear.

Regards,
Oggerschummer

I like it ! :tada:

Already implemented it in my OH2 rules :slight_smile: Thanx!

I use influx db, but i Think it doesnt latter which one you use

Wow, a cool and simple solution.

Just for my understanding, since I just started using a MySQL database together with OpenHAB 2, and the state(s) some light switches are placed into the database. I use the strategy “everyChange”.

Now if I use these rules shown here, the periodic check is done every 10 minutes.

In case, e.g. I go into the bath room, turn on the light, stay there for about 2 minutes, and then leave it and turn the light off again, this won’t be replayed, as the check is done only every 10 minutes, right?

Would it make sence, to do the periodic check every 1 minute, if not present? Would this lead to a more accurate presence simulation? Or would this be too much for my little raspi 3? In Addition, I would’t log the check, as this leads to a real full log then.

I think reducing the interval to 1 minute would really replay the “real life”.

What’s your opinion about that?

And now for beginners like me: where would I implement this rule? Up to now, I only used the PaperUI on OpenHAB with Raspi 3. Where could I store the values for Presence and Lights_away_auto?

I have my trigger at 5 minutes on an rPi3. Works fine, although Im not using the code above. I do mine differently. I also never toggle the simulation, it’s automatic. I have several rules to determine human presence based on door/window contacts, my indoor camera motion etc. If no human presence is detected for a configurable amount of time, then human simulation begins:

Random lights

  • max 2 hours each light
  • max 2 lights on at a time
  • max 20 minutes of ‘no’ light turned on
  • lights only turn on based on astro sunset time

During day time

  • I randomly play 2 radios, 1 upstairs, 1 downstairs.
  • Both chromecast audios
  • Random play uri/stations
  • Max 2 hours each per continuous play
  • Max 20 minutes of silence (both off)

when simulation has started, it does not rely on cron to determine the next ‘tick’ but I rely on a timer. Once timer has ended, a new timer starts with the new random duration.

Visual Studio Code shows error warning: Type mismatch, cannot convert from State to command.

Have things changed since 2017? Must I explicitly typecast/transform/convert State so it is accepted as command?

Thanks!

Does it work, though? Despite the VS code warning?

Actually I didn’t try, I’m used that warnings like that would cause runtime exceptions (I’m new to openHAB) and I wouldn’t know where those would be logged

They would be logged in /var/log/openhab2/openhab.log and /var/log/openhab2/events.log

Nothing showing up about that (nor about “logInfo(“LightsAuto”, “Auto Light Check”)”) in either file

The correct syntax should be

lamp.sendCommand( lamp.historicState(now.minusDays(7)).state.toString )
1 Like

Thanks, it works now!
Hint for newbies (note to self…): It won’t work if you put a group that only contains other groups as “gLights_auto”
It will iterate over the groups and will be unable to access their historic state etc. You want to iterate over a group of Lamps (or Things for that matter).

Give a try with

gLights_auto.allMembers

instead of

gLights_auto.members

Then all items should be touched in the nested groups, but I am not sure then about the state.

1 Like

Great idea and I’m just about to implement it.
One general question about the behaviour of persistence:
I’m using influx with a „onChange“ strategy. When I turn a light on persistence will insert the state with timestamp into the influxdb. So far so good. Let‘s say I turn on a light 7 days ago at exactly 7pm. The presence simulation queries the state of that light at 7:05pm. There won’t be an entry in the influx db with timestamp 7:05. I guess the persistence service will return the „last known“ state which is the State with timestamp 7pm, right?

Yes

So, just wanted to add some findings to this topic. I implemented the simulation, tested it (worked fine) and went for vacation. When I returned home and checked the logs, it turns out things didn’t work so great, as I found this in the logs:

2019-03-28 17:10:00.132 [ERROR] [ntime.internal.engine.ExecuteRuleJob] - Error during the execution of rule ‘Presence Simulation’: Could not invoke method: org.eclipse.smarthome.model.script.actions.BusEvent.sendCommand(org.eclipse.smarthome.core.items.Item,java.lang.String) on instance: null

The script blew up on the first group member item. After some debugging, it turns out that the member and all other items are returning valid presence states so it has nothing to do with items not being initialized or returning null-values. Upon adding changes as suggested in Anti burglary presence simulation - #15 by dascrip, everything works fine. Can’t understand why it worked during test and then suddenly started to crash but now we are back to normal!

I’m trying to implement similar thing. When I’m gone, turn on light based on its state from a week ago. It worked once, but then it always returns the rror “could not invoke… on instance null”

GLV_PENDEL_HAL.sendCommand (GLV_PENDEL_HAL.historicState(now.minusDays(7)).state )

or

GLV_PENDEL_HAL.sendCommand (GLV_PENDEL_HAL.historicState(now.minusDays(7)).state.toString )

I’ve been reading on other threads similar behavior but haven’t succeeded, it worked a few times. but i’m not sure why. Any ideas?

thanks
philippe

Start with debugging and see what

GLV_PENDEL_HAL.historicState(now.minusDays(7)).state

returns

I included the first two points of the ideas of @Oggerschummer to the initial solution:

  • Store the date when the auto-lighting has been activated.

  • Get the historic value from the stored date -7 + (days since then mod 7)

Further, I added:

  • A distinction by means of two groups between lights, which already have an automatic switch off and lamps which do not have such automatic switch off.

  • A check if the lamp state is equal to the historic state to avoid unnecessary commands.

Currently, I use Influxdb as backend i.e. val historicItem = lamp.historicState(JavaTimestamp_toGetHistStateOf,"influxdb")

burglerlights.rules

import java.time.temporal.ChronoUnit;

rule "Periodically check auto lights"
when
    Time cron "0/30 * * ? * * *"
then

	// If lights away mode is on
	if (SwitchLightAutoMode_state.state == ON){

        val JavaTimestamp_AutoLightModeSwitchedON = ZonedDateTime.parse(Timestamp_AutoLightModeSwitchedON.state.toString).withZoneSameInstant(ZoneId.systemDefault())
        val diffDays = ChronoUnit.DAYS.between(JavaTimestamp_AutoLightModeSwitchedON.truncatedTo(ChronoUnit.DAYS), now.truncatedTo(ChronoUnit.DAYS))
        val sevenMinusModDiffDays = 7 - diffDays % 7 + diffDays
        val JavaTimestamp_toGetHistStateOf = now.minusDays(sevenMinusModDiffDays)

		// for lights with manual switch off, forward the historic state
		gLightManualOff.members.forEach[lamp|
			val historicItem = lamp.historicState(JavaTimestamp_toGetHistStateOf)
                        // if there is no historic item in case e.g. the item is added in the last 7 days 
			if (historicItem !== null){
                                val historicState = historicItem.state as OnOffType

				// only send command with historic state if different from current state
				if (historicState != lamp.state) {
					lamp.sendCommand(historicState)
					logInfo("Burgler Light","Burgler light mode switched " + historicState.toString + " manual-off-light: " + lamp.name)
				}
			}
		]

		// for lights with automatic switch off, only forward the ON state
		gLightAutoOff.members.forEach[lamp|
			val historicItem = lamp.historicState(JavaTimestamp_toGetHistStateOf)
			// if there is no historic item in case e.g. the item is added in the last 7 days
			if (historicItem !== null){
				val historicState = historicItem.state as OnOffType

				// only send ON command and only send it if current state is OFF
				if (lamp.state == OFF && historicState == ON) {
					lamp.sendCommand(ON)
					logInfo("Burgler Light","Burgler light mode switched ON auto-off-light: " + lamp.name)
				}
			}
		]
	}
end

rule "SwitchLightAutoMode_state switched on"
when
	Item SwitchLightAutoMode_state changed from OFF to ON
then
	Timestamp_AutoLightModeSwitchedON.sendCommand(now.toString())
end

burglerlight.items

Group     gLightManualOff
Group     gLightAutoOff
Switch    SwitchLightAutoMode_state            "Burgler Light: [%s]"    <wallswitch>
String    Timestamp_AutoLightModeSwitchedON

mapdb.persist

Strategies {
  default = everyUpdate
}

Items {
        Timestamp_AutoLightModeSwitchedON : strategy = everyChange, restoreOnStartup
}