pre-merge (kinda fucked up before)
This commit is contained in:
@@ -1,6 +1,4 @@
|
||||
appdaemon:
|
||||
invalid_yaml_warnings: 0
|
||||
missing_app_warnings: 0
|
||||
latitude: 30.250968
|
||||
longitude: -97.748193
|
||||
elevation: 150
|
||||
|
||||
@@ -13,9 +13,9 @@ scene_detect:
|
||||
module: scene_detect
|
||||
class: MotionCanceller
|
||||
scene: bedsport
|
||||
app: bedroom
|
||||
app: bedroom_motion
|
||||
|
||||
scene_detect:
|
||||
scene_detect2:
|
||||
module: scene_detect
|
||||
class: MotionCanceller
|
||||
scene: in_bed
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import json
|
||||
from copy import deepcopy
|
||||
|
||||
from appdaemon.plugins.hass.hassapi import Hass
|
||||
from appdaemon.plugins.mqtt.mqttapi import Mqtt
|
||||
|
||||
|
||||
class AqaraCube(Mqtt):
|
||||
class AqaraCube(Hass, Mqtt):
|
||||
def initialize(self):
|
||||
self.set_namespace('mqtt')
|
||||
topic = f'zigbee2mqtt/{self.args["cube"]}'
|
||||
self.mqtt_subscribe(topic)
|
||||
self.listen_event(self.handle_event, "MQTT_MESSAGE", topic=topic)
|
||||
self.mqtt_subscribe(topic, namespace='mqtt')
|
||||
self.listen_event(self.handle_event, "MQTT_MESSAGE", topic=topic, namespace='mqtt')
|
||||
self.log(f'Listening for cube events on: {topic}')
|
||||
|
||||
self.app = self.get_app(self.args['app'])
|
||||
@@ -39,12 +39,9 @@ class AqaraCube(Mqtt):
|
||||
self.call_service('scene/turn_on', entity_id=description, namespace='default')
|
||||
self.log(f'Turned on {description}')
|
||||
|
||||
elif description == 'toggle':
|
||||
cause = f'{action} from {self.args["cube"]}'
|
||||
if self.app.entity_state:
|
||||
self.app.deactivate(cause=cause)
|
||||
else:
|
||||
self.app.activate(cause=cause)
|
||||
elif description.startswith('toggle'):
|
||||
cause = f'{self.args["cube"]} {action}'
|
||||
self.app.toggle_activate(kwargs={'cause': cause})
|
||||
|
||||
# def handle_rotate_right(self, payload):
|
||||
# self.log(f'{self.args["cube"]}: Rotate right')
|
||||
|
||||
@@ -1,7 +1,29 @@
|
||||
from datetime import datetime
|
||||
|
||||
from appdaemon.plugins.hass.hassapi import Hass
|
||||
|
||||
|
||||
class HelloWorld(Hass):
|
||||
def initialize(self):
|
||||
# self.set_state(entity_id='input_boolean.enable', state='on')
|
||||
self.log('Hello World')
|
||||
|
||||
now: datetime = self.get_now()
|
||||
eid = self.args['eid']
|
||||
self.log(eid)
|
||||
self.listen_state(self.my_callback, eid)
|
||||
self.set_state(eid, state=now.isoformat(), attributes=dict(name='Test Fade Start'))
|
||||
self.log(f'Set state to {now.time()}')
|
||||
|
||||
def my_callback(self, entity, attribute, old, new, kwargs):
|
||||
new = self.convert_time(new)
|
||||
old = self.convert_time(old)
|
||||
self.log(f'{attribute} {old} -> {new}')
|
||||
|
||||
def convert_time(self, time_str: str) -> datetime:
|
||||
dt = datetime.fromisoformat(time_str)
|
||||
try:
|
||||
dt = self.AD.tz.localize(dt)
|
||||
except ValueError:
|
||||
dt = dt.astimezone(self.AD.tz)
|
||||
finally:
|
||||
return dt
|
||||
@@ -1,18 +1,16 @@
|
||||
from appdaemon.adapi import ADAPI
|
||||
from appdaemon.plugins.hass.hassapi import Hass
|
||||
|
||||
class Leaving(ADAPI):
|
||||
|
||||
class Leaving(Hass):
|
||||
def initialize(self):
|
||||
self.listen_state(self.handle_state_change, entity_id=self.args['person'])
|
||||
|
||||
def handle_state_change(self, entity, attribute, old, new, kwargs):
|
||||
self.log(f'Changed state {old} -> {new}')
|
||||
if old == 'home' and new != 'home':
|
||||
self.turn_everything_off()
|
||||
self.listen_state(self.turn_everything_off, entity_id=self.args['person'], old='home')
|
||||
|
||||
def turn_everything_off(self):
|
||||
def turn_everything_off(self, entity, attribute, old, new, kwargs):
|
||||
self.log(f'turning everything off')
|
||||
self.log(kwargs)
|
||||
for app_name in self.args['apps']:
|
||||
try:
|
||||
self.get_app(app_name).deactivate(cause='leaving')
|
||||
self.get_app(app_name).deactivate(kwargs={'cause': 'leaving'})
|
||||
except Exception as e:
|
||||
self.log(f'{type(e).__name__}: {e}')
|
||||
continue
|
||||
|
||||
33
apps/rich_logging.py
Normal file
33
apps/rich_logging.py
Normal file
@@ -0,0 +1,33 @@
|
||||
import logging
|
||||
|
||||
from rich.console import Console
|
||||
from rich.highlighter import NullHighlighter
|
||||
from rich.logging import RichHandler
|
||||
|
||||
|
||||
def init_logging(log_level: int = logging.INFO):
|
||||
rich_handler = RichHandler(
|
||||
console=Console(width=150),
|
||||
highlighter=NullHighlighter(),
|
||||
markup=True,
|
||||
rich_tracebacks=True,
|
||||
tracebacks_suppress=['pandas', 'discord'],
|
||||
)
|
||||
dt_fmt = '%Y-%m-%d %I:%M:%S %p'
|
||||
# https://docs.python.org/3/library/logging.html#logrecord-attributes
|
||||
log_format = '[magenta]%(name)s[/]: [cyan]%(funcName)s[/] %(message)s'
|
||||
|
||||
root_logger = logging.getLogger()
|
||||
formatter = logging.Formatter(log_format)
|
||||
formatter.datefmt = dt_fmt
|
||||
rich_handler.setFormatter(formatter)
|
||||
root_logger.addHandler(rich_handler)
|
||||
root_logger.setLevel(log_level)
|
||||
# logging.debug(f'Set up logging')
|
||||
|
||||
# logging.basicConfig(
|
||||
# level=log_level,
|
||||
# format=log_format,
|
||||
# datefmt=dt_fmt,
|
||||
# handlers=[rich_handler]
|
||||
# )
|
||||
Submodule apps/room_control updated: c9cc841d58...d8a9d3d83a
@@ -6,22 +6,22 @@ bathroom:
|
||||
- time: '05:00:00'
|
||||
scene:
|
||||
light.bathroom:
|
||||
brightness_pct: 40
|
||||
brightness: 100
|
||||
color_temp: 250
|
||||
- time: '12:00:00'
|
||||
scene:
|
||||
light.bathroom:
|
||||
brightness_pct: 70
|
||||
brightness: 175
|
||||
color_temp: 300
|
||||
- time: sunset
|
||||
scene:
|
||||
light.bathroom:
|
||||
brightness_pct: 50
|
||||
brightness: 125
|
||||
color_temp: 350
|
||||
- time: '23:00:00'
|
||||
scene:
|
||||
light.bathroom:
|
||||
brightness_pct: 20
|
||||
brightness: 50
|
||||
color_temp: 350
|
||||
sleep: input_boolean.sleeping
|
||||
sleep_state:
|
||||
@@ -33,10 +33,10 @@ bathroom:
|
||||
|
||||
bathroom_button:
|
||||
module: button
|
||||
class: ButtonController
|
||||
class: Button
|
||||
app: bathroom
|
||||
ref_entity: light.bathroom
|
||||
button: Bathroom Button
|
||||
ref_entity: light.bathroom
|
||||
|
||||
bathroom_motion:
|
||||
module: motion
|
||||
|
||||
@@ -8,11 +8,11 @@ bedroom:
|
||||
light.bedroom:
|
||||
state: on
|
||||
color_temp: 200
|
||||
brightness_pct: 20
|
||||
brightness: 50
|
||||
light.globe:
|
||||
state: on
|
||||
color_temp: 200
|
||||
brightness_pct: 20
|
||||
brightness: 50
|
||||
light.overhead:
|
||||
state: off
|
||||
- time: '06:00:00'
|
||||
@@ -20,62 +20,62 @@ bedroom:
|
||||
light.bedroom:
|
||||
state: on
|
||||
color_temp: 250
|
||||
brightness_pct: 20
|
||||
brightness: 50
|
||||
light.globe:
|
||||
state: on
|
||||
color_temp: 250
|
||||
brightness_pct: 20
|
||||
brightness: 50
|
||||
light.overhead:
|
||||
state: on
|
||||
color_temp: 250
|
||||
brightness_pct: 15
|
||||
brightness: 40
|
||||
- time: '12:00:00'
|
||||
scene:
|
||||
light.bedroom:
|
||||
state: on
|
||||
color_temp: 325
|
||||
brightness_pct: 30
|
||||
brightness: 75
|
||||
light.globe:
|
||||
state: on
|
||||
color_temp: 325
|
||||
brightness_pct: 30
|
||||
brightness: 75
|
||||
light.overhead:
|
||||
state: on
|
||||
color_temp: 325
|
||||
brightness_pct: 50
|
||||
brightness: 50
|
||||
- time: 'sunset'
|
||||
scene:
|
||||
light.bedroom:
|
||||
state: on
|
||||
color_temp: 325
|
||||
brightness_pct: 50
|
||||
brightness: 50
|
||||
light.globe:
|
||||
state: on
|
||||
color_temp: 325
|
||||
brightness_pct: 50
|
||||
brightness: 50
|
||||
light.overhead:
|
||||
state: on
|
||||
color_temp: 350
|
||||
brightness_pct: 10
|
||||
brightness: 65
|
||||
- time: '01:00:00'
|
||||
scene:
|
||||
light.bedroom:
|
||||
state: on
|
||||
color_name: green
|
||||
brightness_pct: 50
|
||||
brightness: 50
|
||||
light.globe:
|
||||
state: on
|
||||
color_name: blue
|
||||
brightness_pct: 50
|
||||
brightness: 50
|
||||
light.overhead:
|
||||
state: on
|
||||
color_name: blueviolet
|
||||
brightness_pct: 100
|
||||
brightness: 255
|
||||
sleep: input_boolean.sleeping
|
||||
|
||||
bedroom_buttons:
|
||||
module: button
|
||||
class: ButtonController
|
||||
class: Button
|
||||
app: bedroom
|
||||
ref_entity: light.bedroom
|
||||
button:
|
||||
|
||||
@@ -6,22 +6,22 @@ closet:
|
||||
- time: 'sunrise - 03:00:00'
|
||||
scene:
|
||||
light.closet:
|
||||
brightness_pct: 10
|
||||
brightness: 25
|
||||
color_temp: 200
|
||||
- time: 'sunrise'
|
||||
scene:
|
||||
light.closet:
|
||||
brightness_pct: 30
|
||||
brightness: 75
|
||||
color_temp: 200
|
||||
- time: '12:00:00'
|
||||
scene:
|
||||
light.closet:
|
||||
brightness_pct: 70
|
||||
brightness: 175
|
||||
color_temp: 300
|
||||
- time: sunset
|
||||
scene:
|
||||
light.closet:
|
||||
brightness_pct: 40
|
||||
brightness: 100
|
||||
color_temp: 400
|
||||
|
||||
closet_motion:
|
||||
|
||||
@@ -2,46 +2,46 @@ kitchen:
|
||||
module: room_control
|
||||
class: RoomController
|
||||
off_duration: '00:10:00'
|
||||
ha_button: input_button.activate_kitchen
|
||||
# ha_button: input_button.activate_kitchen
|
||||
sleep: input_boolean.sleeping
|
||||
sleep_state:
|
||||
scene:
|
||||
light.kitchen:
|
||||
state: on
|
||||
brightness: 1
|
||||
states:
|
||||
- time: sunrise
|
||||
scene:
|
||||
light.kitchen:
|
||||
state: on
|
||||
color_temp: 200
|
||||
brightness_pct: 10
|
||||
brightness: 25
|
||||
- time: '12:00:00'
|
||||
scene:
|
||||
light.kitchen:
|
||||
state: on
|
||||
color_temp: 300
|
||||
brightness_pct: 30
|
||||
brightness: 75
|
||||
- time: sunset
|
||||
scene:
|
||||
light.kitchen:
|
||||
state: on
|
||||
color_temp: 450
|
||||
brightness_pct: 40
|
||||
brightness: 100
|
||||
- time: '22:00:00'
|
||||
off_duration: '00:02:00'
|
||||
scene:
|
||||
light.kitchen:
|
||||
state: on
|
||||
color_temp: 650
|
||||
brightness_pct: 10
|
||||
sleep: input_boolean.sleeping
|
||||
sleep_state:
|
||||
scene:
|
||||
light.kitchen:
|
||||
state: on
|
||||
brightness_pct: 1
|
||||
|
||||
brightness: 25
|
||||
|
||||
kitchen_button:
|
||||
module: button
|
||||
class: ButtonController
|
||||
class: Button
|
||||
app: kitchen
|
||||
ref_entity: light.kitchen
|
||||
button: Kitchen Button
|
||||
ref_entity: light.kitchen
|
||||
|
||||
kitchen_motion:
|
||||
module: motion
|
||||
|
||||
@@ -8,42 +8,42 @@ living_room:
|
||||
light.living_room:
|
||||
state: on
|
||||
color_temp: 200
|
||||
brightness_pct: 30
|
||||
brightness: 75
|
||||
light.couch_corner:
|
||||
state: on
|
||||
color_temp: 200
|
||||
brightness_pct: 7
|
||||
brightness: 20
|
||||
- time: '09:00:00'
|
||||
scene:
|
||||
light.living_room:
|
||||
state: on
|
||||
color_temp: 250
|
||||
brightness_pct: 50
|
||||
brightness: 130
|
||||
light.couch_corner:
|
||||
state: on
|
||||
color_temp: 250
|
||||
brightness_pct: 25
|
||||
brightness: 65
|
||||
- time: '12:00:00'
|
||||
scene:
|
||||
light.living_room:
|
||||
state: on
|
||||
color_temp: 300
|
||||
brightness_pct: 100
|
||||
brightness: 255
|
||||
light.couch_corner:
|
||||
state: on
|
||||
color_temp: 450
|
||||
brightness_pct: 50
|
||||
brightness: 125
|
||||
- time: sunset
|
||||
off_duration: 01:00:00
|
||||
scene:
|
||||
light.living_room:
|
||||
state: on
|
||||
color_temp: 350
|
||||
brightness_pct: 70
|
||||
brightness: 175
|
||||
light.couch_corner:
|
||||
state: on
|
||||
color_temp: 650
|
||||
brightness_pct: 10
|
||||
brightness: 25
|
||||
- elevation: -20
|
||||
direction: setting
|
||||
off_duration: 00:30:00
|
||||
@@ -51,29 +51,29 @@ living_room:
|
||||
light.living_room:
|
||||
state: on
|
||||
color_temp: 350
|
||||
brightness_pct: 50
|
||||
brightness: 125
|
||||
light.couch_corner:
|
||||
state: on
|
||||
color_temp: 650
|
||||
brightness_pct: 5
|
||||
brightness: 5
|
||||
sleep: input_boolean.sleeping
|
||||
sleep_state:
|
||||
off_duration: '00:02:00'
|
||||
# off_duration: '00:02:00'
|
||||
scene:
|
||||
light.living_room:
|
||||
state: 'on'
|
||||
color_name: 'red'
|
||||
brightness_pct: 10
|
||||
rgb_color: [255, 0, 0]
|
||||
brightness: 25
|
||||
|
||||
front_door:
|
||||
module: door
|
||||
class: DoorControl
|
||||
class: Door
|
||||
app: living_room
|
||||
door: binary_sensor.front_contact
|
||||
|
||||
living_room_button:
|
||||
module: button
|
||||
class: ButtonController
|
||||
class: Button
|
||||
app: living_room
|
||||
button: Living Room Button
|
||||
ref_entity: light.living_room
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from appdaemon.plugins.hass.hassapi import Hass
|
||||
|
||||
|
||||
class SceneDetector(Hass):
|
||||
def initialize(self):
|
||||
self.scene_entity = self.args['scene'] if self.args['scene'].startswith('scene.') else f'scene.{self.args["scene"]}'
|
||||
@@ -21,4 +22,12 @@ class MotionCanceller(SceneDetector):
|
||||
def scene_detected(self):
|
||||
super().scene_detected()
|
||||
app = self.get_app(self.args['app'])
|
||||
app.cancel_motion_callback(new='off')
|
||||
try:
|
||||
self.run_in(
|
||||
callback=lambda *args, **kwargs: app.cancel_motion_callback(),
|
||||
delay=0.5
|
||||
)
|
||||
except:
|
||||
self.log(f'Error cancelling motion callback for {self.args["app"]}', level='ERROR')
|
||||
else:
|
||||
self.log('Cancelled motion callback')
|
||||
|
||||
@@ -8,9 +8,8 @@ from appdaemon.plugins.mqtt.mqttapi import Mqtt
|
||||
class SleepSetter(Hass, Mqtt):
|
||||
def initialize(self):
|
||||
assert self.entity_exists(entity_id=self.variable), f'{self.variable} does not exist'
|
||||
self.variable_entity.listen_state(callback=self.handle_state)
|
||||
self.listen_state(callback=self.handle_state, entity_id=self.variable)
|
||||
self.setup_buttons()
|
||||
self.log(f'{self.variable} can be set using {self.button}, currently {self.state}')
|
||||
|
||||
def setup_buttons(self):
|
||||
if isinstance(self.button, list):
|
||||
@@ -23,7 +22,7 @@ class SleepSetter(Hass, Mqtt):
|
||||
topic = f'zigbee2mqtt/{name}'
|
||||
self.mqtt_subscribe(topic, namespace='mqtt')
|
||||
self.listen_event(self.handle_button, "MQTT_MESSAGE", topic=topic, namespace='mqtt', button=name)
|
||||
self.log(f'Listening for sleep setting on {name}')
|
||||
self.log(f'Subscribed: {topic}')
|
||||
|
||||
@property
|
||||
def button(self) -> str:
|
||||
@@ -56,15 +55,13 @@ class SleepSetter(Hass, Mqtt):
|
||||
|
||||
@property
|
||||
def sun_elevation(self) -> float:
|
||||
try:
|
||||
return float(self.get_state('sun.sun', 'elevation'))
|
||||
except:
|
||||
self.log(f'Failed to return sun elevation')
|
||||
return
|
||||
state = self.get_state('sun.sun', 'elevation')
|
||||
assert isinstance(state, float)
|
||||
return state
|
||||
|
||||
def handle_state(self, entity, attribute, old, new, kwargs):
|
||||
self.log(f'{entity}: {old} -> {new}')
|
||||
if self.state and self.sun_elevation < float(self.args['elevation_limit']):
|
||||
self.log(f'new state: {self.state}')
|
||||
if self.state:
|
||||
self.all_off()
|
||||
try:
|
||||
self.call_service('scene/turn_on', entity_id=self.scene)
|
||||
@@ -86,22 +83,18 @@ class SleepSetter(Hass, Mqtt):
|
||||
return
|
||||
else:
|
||||
self.handle_action(action)
|
||||
|
||||
|
||||
def handle_action(self, action: str):
|
||||
if action == '':
|
||||
return
|
||||
elif action == 'hold':
|
||||
|
||||
if action == 'hold':
|
||||
self.log(f' {action.upper()} '.center(50, '='))
|
||||
self.state = True
|
||||
elif action == 'double':
|
||||
self.log(f' {action.upper()} '.center(50, '='))
|
||||
self.state = not self.state
|
||||
if (on_apps := self.args.get('on_apps', None)) is not None:
|
||||
for app_name in on_apps:
|
||||
try:
|
||||
self.get_app(app_name).activate(cause='sleep setter')
|
||||
except:
|
||||
return
|
||||
else:
|
||||
self.log(f'Activated {app_name}')
|
||||
self.on_apps()
|
||||
|
||||
def all_off(self):
|
||||
self.log(f'Deactivating apps')
|
||||
@@ -119,3 +112,13 @@ class SleepSetter(Hass, Mqtt):
|
||||
except:
|
||||
self.log(f'Failed to turn off {entity}')
|
||||
continue
|
||||
|
||||
def on_apps(self):
|
||||
if (on_apps := self.args.get('on_apps', None)) is not None:
|
||||
for app_name in on_apps:
|
||||
try:
|
||||
self.get_app(app_name).activate(kwargs={'cause': 'sleep setter'})
|
||||
except:
|
||||
return
|
||||
else:
|
||||
self.log(f'Activated {app_name}')
|
||||
@@ -6,7 +6,7 @@ services:
|
||||
volumes:
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
- config:/conf
|
||||
- config:/conf:ro
|
||||
ports:
|
||||
- 5050:5050
|
||||
restart: unless-stopped
|
||||
|
||||
Reference in New Issue
Block a user