Consider this problem: my kitchen is in an old decrepit farm house built in 1920. The kitchen has a challenging layout with no good space for any modern appliance. The only wall for the refrigerator is annoyingly narrower than an average refrigerator. Unfortunately, the only switches for the kitchen and pantry lights are on that wall, too. The refrigerator blocks the switches to the point they can only be felt, not seen.
For twenty years, I've been fine slipping my hand into the dusty cobwebs behind the refrigerator to turn on the lights. I can foresee the end of this era. I'm imagining two Samsung Buttons magnetically tacked to a convenient and accessible side of the refrigerator: one for the pantry and one for the kitchen.
The pantry light is the most common light to be inadvertently left on for hours at a time. Nobody wants to reach behind the refrigerator to turn off the light. This gives me an idea. I'm going to make the new pantry button turn on the light for only 10 minutes at a time. Rarely is anyone in there for longer than that. Sometimes, however, it is handy to have it on for longer. So I'll make each button press add ten minutes to the timer. Need the light on for 30 minutes? Press the button three times. To appease the diligent one in the household that always remembers to turn lights off, a long press to the button turns the light off and cancels the timer:
class PantryLightTimerRule(Rule): def register_triggers(self): self.delay_timer = DelayTimer(self.config, "adjustable_delay", "10m") self.PantryButton.subscribe_to_event('pressed') self.PantryButton.subscribe_to_event('longPressed') return (self.PantryButton, self.delay_timer, self.PantryLight) def action(self, the_triggering_thing, the_trigger_event, new_value): if the_triggering_thing is self.PantryButton and the_trigger_event == 'pressed': if self.PantryLight.on: self.delay_timer.add_time() # add ten minutes else: self.PantryLight.on = True elif the_triggering_thing is self.PantryButton and the_trigger_event == 'longPressed': self.PantryLight.on = False elif the_triggering_thing is self.delay_timer: self.PantryLight.on = False elif the_triggering_thing is self.PantryLight and new_value is False: self.delay_timer.cancel() elif the_triggering_thing is self.PantryLight and new_value is True: self.delay_timer.add_time() # add ten minutes(see this code in situ in the timer_light_rule.py file in the pywot rule system demo directory)
This rules uses three triggers: the PantryButton (as played by Samsung), a timer called delay_timer, and the PantryLight (as played by an IKEA bulb). The register_triggers method creates the timer with a default time increment of 10 minutes. It subscribes to the "pressed" and "longPressed" events that the PantryButton can emit. It returns a tuple containing these two things coupled with the reference to the PantryLight itself.
How is the PantryLight itself considered to be a trigger? Since the bulb in the pantry is to be a smart bulb, any other controller in the house could theoretically turn it on. No matter what turns it on, I want my timer rule to eventually turn it off. Anytime something turns that light on, my rule will fire.
In the action method, in the last two lines you can see how I exploit the idea that anything turning the light on triggers the timer. If the_triggering_thing is the PantryLight and it was turned from off to on, this rule will add time to the delay_timer. If the delay_timer wasn't running, adding time to it will start it.
Further, going back up two more lines, you can see how turning off the light by any means cancels the delay_timer.
Going back up another line, you can see how I handle the timer naturally timing out. It just turns off the light. Yeah, that will result in the action method getting a message about the light turning off. We've already seen that action will try to cancel the timer, but in this case, the timer isn't running anymore, so the cancel is ignored.
This will change with the second Samsung button. It seems we only use the kitchen lights in certain combinations. Multiple presses to the Samsung button will cycle through these combinations in this order:
- all off
- stove light only
- stove light & counter light
- stove light, counter light & sink light
- counter light & sink light
- sink light only
- counter light only
class CombinationLightRule(Rule): def initial_state(self): self.index = 0 self.combinations = [ (False, False, False), (True, False, False), (True, True, False), (True, True, True), (False, True, True), (False, False, True), (False, True, False), ] def register_triggers(self): self.KitchenButton.subscribe_to_event('pressed') self.KitchenButton.subscribe_to_event('longPressed') return (self.KitchenButton, ) def set_bulb_state(self): self.StoveLight.on = self.combinations[self.index] self.CounterLight.on = self.combinations[self.index] self.SinkLight.on = self.combinations[self.index] def action(self, the_triggering_thing, the_trigger_event, new_value): if the_trigger_event == "pressed": self.index = (self.index + 1) % len(self.combinations) self.set_bulb_state() elif the_trigger_event == "longPressed": self.index = 0 self.set_bulb_state()(see this code in situ in the combination_light_rule.py file in the pywot rule system demo directory)
I can think of so many applications for these Samsung Buttons, I may need to acquire a pallet of them...