I had a default ventilation time of 15 minutes when somebody visited the toilet. But in some cases this is not enough
I came up with the following code and I would like to get some feedback or other ideas.
When my pir sensor (ESP easy + mqtt) gets triggered I store the timestamp it was first triggered. I then block updating of this timestamp till the duration is calculated. This is because the pir sensor keeps being triggered when the toilet is occupied.
When the light switches off (180 sec after last movement) I get the latest timestamp from the pir sensor, calculate the difference, turn the fan on for 15 min if the visit was less then 5 minutes or 30 min if the visit was longer.
Items
Number pir_toilet "Toilet PIR [MAP(pir.map):%s]" <motion> (gToilet, gPIR, gSensorsStatuses) {channel="mqtt:topic:toilet:pir", expire="1m,state=0"}
DateTime pir_toilet_lastChanged "Toilet PIR [%1$td-%1$tm-%1$tY, %1$tR]" <time> (gToilet, gPIR, gSensorsStatuses) {channel="mqtt:topic:toilet:pir" [profile="timestamp-change"]}
DateTime StartToiletVisit "Start measurement toilet visit"
DateTime StopToiletVisit "Stop measurement toilet visit"
Switch VentilatieToilet "Ventilatie Toilet (15 min)" <switch> (gVentilation) {expire="15m,command=OFF"}
Switch VentilatieToiletLang "Ventilatie Toilet (30 min)" <switch> (gVentilation) {expire="30m,command=OFF"}
Dimmer Milight_ID0x2_G4_Level "Toiletlamp" (gToiletLightsLevel) {channel="espmilighthub:rgb_cct:milighthub_beneden:0x24:level"}
Rule
var boolean measurementRunning1 = false
rule "Start Detect toilet visit duration"
when
Item pir_toilet changed from 0 to 1
then
logInfo("Start Toilet Visit Measurement", "measurementRunning1 = " + measurementRunning1)
if (!measurementRunning1) {
measurementRunning1 = true
StartToiletVisit.sendCommand(pir_toilet_lastChanged.state.toString)
logInfo("Start Toilet Visit Measurement", "StartToiletVisit = " + StartToiletVisit.state.toString)
}
end
rule "Stop Detect toilet visit duration"
when
Item Milight_ID0x2_G4_Level changed to 0
then
StopToiletVisit.sendCommand(pir_toilet_lastChanged.state.toString)
logInfo("Stop Toilet Visit Measurement", "StopToiletVisit = " + StopToiletVisit.state.toString)
measurementRunning1 = false
Thread::sleep(500) // Give items time to update
val Number MyEpochFromDateTimeTypeItem_VariantB1 = new DateTime(StartToiletVisit.state.toString).millis
val Number MyEpochFromDateTimeTypeItem_VariantB2 = new DateTime(StopToiletVisit.state.toString).millis
logInfo("Calculate duration Toilet Visit", "MyEpochFromDateTimeTypeItem_VariantB1 = " + MyEpochFromDateTimeTypeItem_VariantB1)
logInfo("Calculate duration Toilet Visit", "MyEpochFromDateTimeTypeItem_VariantB2 = " + MyEpochFromDateTimeTypeItem_VariantB2)
if (MyEpochFromDateTimeTypeItem_VariantB1 === null || MyEpochFromDateTimeTypeItem_VariantB2 === null || MyEpochFromDateTimeTypeItem_VariantB1 == MyEpochFromDateTimeTypeItem_VariantB2) {
logWarn("Total duration toilet visit", "1 MyEpochFromDateTimeTypeItem_Variant is null or equal.")
return;
}
val Number toiletvisitduration = ((MyEpochFromDateTimeTypeItem_VariantB2 - MyEpochFromDateTimeTypeItem_VariantB1)/1000)
logInfo("Total duration toilet visit", "toiletvisitduration = " + toiletvisitduration + " seconds.")
if ( toiletvisitduration <= 300) {
logInfo("Total duration toilet visit", "Total duration toilet visit was less then 5 min, turn fan on for 15 min")
VentilatieToilet.sendCommand(ON)
} else {
logInfo("Total duration toilet visit", "Total duration toilet visit was longer then 5 min, turn fan on for 30 min")
if (VentilatieToilet.state == ON) {
VentilatieToilet.sendCommand(OFF)
}
VentilatieToiletLang.sendCommand(ON)
}
end