Skip to content

Commit

Permalink
add goodnight script
Browse files Browse the repository at this point in the history
  • Loading branch information
hechi committed May 28, 2020
1 parent 1e82b3c commit 43dd02f
Show file tree
Hide file tree
Showing 4 changed files with 195 additions and 0 deletions.
39 changes: 39 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
[![hacs_badge](https://img.shields.io/badge/HACS-Default-orange.svg?style=for-the-badge)](https://github.com/custom-components/hacs)

### Description

This App will dim your lights for **X** minutes until it's finally off.

### Requirements

You need an [Xiaomi Mijia Smart Switch](https://www.banggood.com/Original-Xiaomi-Mijia-Smart-Home-Zig-bee-Wireless-Smart-Switch-Touch-Button-ON-OFF-WiFi-Remote-Control-Switch-p-1049175.html?rmmds=buy&cur_warehouse=HK). I think it will work with others too as long as they have two different event codes and the event comes via deconz.

### Device Events

| Action | Code | Description |
| -------------- | -------- | -------------- |
| SINGLE_CLICK | 1002 | start diming |
| DOUBLE_CLICK | 1004 | stop diming |

### Configuration

This is an example for your `apps.yaml` following entries are possible:
* module (required)
* class (required)
* light_ids (required) - comma separated if you which more lights to be controlled
* switch_id (required)
* switch_single_click_event_code (optional) - single click event code
* switch_double_click_event_code (optional) - double click event code
* durationInSeconds (optional) - default are 120 seconds
* start_birghtness (optional) - an integer which can go from 0 to 254. While 0 means off and 254 means maximum
```
goodnightt:
module: Goodnight
class: Goodnight
light_ids: light.osramlightbedroom,light.osramlightstrip02
switch_id: round02
switch_single_click_event_code: 1002
switch_double_click_event_code: 1004
durationInSeconds: 600 # 10 min (default 120 - 2min)
start_brightness: 254
```
9 changes: 9 additions & 0 deletions apps.example.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
goodnightt:
module: Goodnight
class: Goodnight
light_ids: light.osramlightbedroom,light.osramlightstrip02
switch_id: round02
switch_single_click_event_code: 1002
switch_double_click_event_code: 1004
durationInSeconds: 600 # 10 min (default 120 - 2min)
start_brightness: 254
142 changes: 142 additions & 0 deletions apps/goodnightt/Goodnight.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import appdaemon.plugins.hass.hassapi as hass

SINGLE_CLICK=1002
DOUBLE_CLICK=1004
TRIPLE_CLICK=1005
QUAD_CLICK=1006
FIVE_CLICK=1010
PRESS=1000
PRESS_3SEC=1001
PRESS_LONG=1003

class Goodnight(hass.Hass):
global SINGLE_CLICK
global DOUBLE_CLICK

def initialize(self):
self.log(self.args)
self.log("Hello from Goodnight module")
ids = self.args["light_ids"]
self.light_ids=[]
for light_id in self.split_device_list(ids):
self.light_ids.append(light_id)
self.log('register '+str(light_id))
self.switch_id = self.args["switch_id"]
SINGLE_CLICK = self.args["switch_single_click_event_code"] if 'switch_single_click_event_code' in self.args else SINGLE_CLICK
DOUBLE_CLICK = self.args["switch_double_click_event_code"] if 'switch_double_click_event_code' in self.args else DOUBLE_CLICK
self.durationInSeconds = self.args["durationInSeconds"] if 'durationInSeconds' in self.args else 120
self.brightness = self.args["start_brightness"] if 'start_brightness' in self.args else 254
self.stepSize = self.brightness/self.durationInSeconds
self.timer = None
self.currentBrightness = None
self.handle = self.listen_event(self.handle_event, "deconz_event")

def handle_event(self, event_name, data, kwargs):
if 'id' not in data or data['id'] != self.switch_id:
return
# self.log("Movement {}".format(data))
eventCode = data['event']
if eventCode == SINGLE_CLICK:
self.setStepBasedOnCurrentBirghtness()
self.getTimer().startTimer()
if eventCode == DOUBLE_CLICK:
self.getTimer().stopTimer()

def setStepBasedOnCurrentBirghtness(self):
brightness_max = None
# find brightest light
for light_id in self.light_ids:
try:
temp_brightness = int(self.get_state(light_id, "brightness")) # get lights current brightness
if not brightness_max or temp_brightness > brightness_max:
brightness_max=temp_brightness
except:
counter = 3
while(counter>0):
try:
temp_brightness = int(self.get_state(light_id, "brightness"))
if not brightness_max or temp_brightness > brightness_max:
brightness_max=temp_brightness
except:
time.sleep(1)
counter = counter - 1
if not brightness_max:
self.brightness = 254 # maximum light if nothing can be received
else:
self.brightness = brightness_max
self.stepSize = self.brightness/self.durationInSeconds

def startNightMode(self):
self.log('start night mode')
self.turnOnLight(brightness=self.brightness)

def stopNightMode(self):
self.log('stop night mode')
self.turnOffLight()

def turnOnLight(self, brightness=254):
for light_id in self.light_ids:
if self.get_state(light_id) == "off":
self.log('turn on light '+str(light_id)+' with '+str(brightness)+' brightness')
self.turn_on(light_id, brightness=brightness)

def turnOffLight(self):
for light_id in self.light_ids:
if self.get_state(light_id) == "on":
self.log('turn of light'+str(light_id))
self.turn_off(light_id)

def dimLights(self):
self.brightness = self.brightness - self.stepSize
for light_id in self.light_ids:
self.turn_on(light_id, brightness=self.brightness)

def getTimer(self):
if not self.timer or not self.timer.isAlive():
self.timer = Timer(controller=self,startFunction=self.startNightMode, stopFunction=self.stopNightMode, stepFunction=self.dimLights, stepInSeconds=1, timerInSeconds=self.durationInSeconds)
return self.timer


import threading
import time
# somehow i cant use this class outside of this script :(
class Timer(threading.Thread):

def __init__(self, controller, startFunction, stopFunction, stepFunction=None, stepInSeconds=1, timerInSeconds=120):
threading.Thread.__init__(self)
self.controller = controller
self.startFunction = startFunction
self.stopFunction = stopFunction
self.stepFunction = stepFunction
self.stepInSeconds = stepInSeconds
self.timerInSeconds = timerInSeconds
self.counter = 0
self.setDaemon(True)
self.stop=True

def startTimer(self):
self.stop=False
if self.isAlive():
self.counter = 0
else:
self.start()

def stopTimer(self):
self.stop=True
self.counter=0

def resetTimer(self):
self.counter = 0

def run(self):
if self.startFunction:
self.startFunction()
while self.counter < self.timerInSeconds:
time.sleep(self.stepInSeconds)
self.counter = self.counter + self.stepInSeconds
if self.stepFunction:
self.stepFunction()
if self.stop:
break
if self.stopFunction:
self.stopFunction()
5 changes: 5 additions & 0 deletions hacs.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Goodnight timer",
"render_readme": true,
"domains": ["switch", "light"]
}

0 comments on commit 43dd02f

Please sign in to comment.