Compare commits
3 Commits
aa6fb42dd7
...
89b08b1fc5
| Author | SHA1 | Date | |
|---|---|---|---|
| 89b08b1fc5 | |||
| fc6673e98b | |||
| 728577647a |
@@ -60,3 +60,14 @@ informations_collector:
|
|||||||
# - group.dumb_lights
|
# - group.dumb_lights
|
||||||
# output_sensor: sensor.ad_number_of_lights_on
|
# output_sensor: sensor.ad_number_of_lights_on
|
||||||
|
|
||||||
|
haw_switch:
|
||||||
|
module: smartswitch
|
||||||
|
class: SmartSwitch
|
||||||
|
|
||||||
|
entity: input_boolean.haw
|
||||||
|
|
||||||
|
auto_switch_off_after: 28800 # 8h
|
||||||
|
|
||||||
|
off_events:
|
||||||
|
- WAKEUP
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ smart_heating_templates_library:
|
|||||||
templates_library:
|
templates_library:
|
||||||
clim_conditions:
|
clim_conditions:
|
||||||
trigger_conditions:
|
trigger_conditions:
|
||||||
- "not binary_sensor.heatpump_winter_mode and (ext_temperature >= room_temperature or ext_temperature >= target_temperature or cant_open_window) and room_temperature >= (quick_resume ? target_temperature : (target_temperature + 1))"
|
- "not binary_sensor.heatpump_winter_mode and (ext_temperature >= room_temperature or ext_temperature >= target_temperature or cant_open_window) and room_temperature >= ((quick_resume or sleeping_in_the_room)? target_temperature : (target_temperature + 1))"
|
||||||
- not binary_sensor.heatpump_winter_mode and self and (ext_temperature >= target_temperature or cant_open_window)
|
- not binary_sensor.heatpump_winter_mode and self and (ext_temperature >= target_temperature or cant_open_window)
|
||||||
- binary_sensor.heatpump_winter_mode and room_temperature <= (target_temperature - 1) and ext_temperature <= 10
|
- binary_sensor.heatpump_winter_mode and room_temperature <= (target_temperature - 1) and ext_temperature <= 10
|
||||||
- binary_sensor.heatpump_winter_mode and self and room_temperature < target_temperature
|
- binary_sensor.heatpump_winter_mode and self and room_temperature < target_temperature
|
||||||
@@ -50,8 +50,8 @@ desk_heatpump:
|
|||||||
room_temperature: sensor.desk_temperature
|
room_temperature: sensor.desk_temperature
|
||||||
room_occupancy: binary_sensor.desk_occupancy
|
room_occupancy: binary_sensor.desk_occupancy
|
||||||
target_temperature: sensor.target_temperature_heatpump
|
target_temperature: sensor.target_temperature_heatpump
|
||||||
cant_open_window: false #binary_sensor.cant_open_window
|
cant_open_window: binary_sensor.is_desk_sleeping
|
||||||
sleeping_in_the_room: false #binary_sensor.is_bureau_sleeping
|
sleeping_in_the_room: binary_sensor.is_desk_sleeping
|
||||||
quick_resume: binary_sensor.desk_heatpump_quick_resume
|
quick_resume: binary_sensor.desk_heatpump_quick_resume
|
||||||
stay_on_while_sleeping: false
|
stay_on_while_sleeping: false
|
||||||
|
|
||||||
@@ -90,10 +90,10 @@ bedroom_heatpump:
|
|||||||
room_temperature: sensor.bedroom_temperature
|
room_temperature: sensor.bedroom_temperature
|
||||||
room_occupancy: binary_sensor.bedroom_occupancy
|
room_occupancy: binary_sensor.bedroom_occupancy
|
||||||
target_temperature: sensor.target_temperature_heatpump
|
target_temperature: sensor.target_temperature_heatpump
|
||||||
cant_open_window: false #binary_sensor.cant_open_window
|
cant_open_window: binary_sensor.is_bedroom_sleeping
|
||||||
sleeping_in_the_room: binary_sensor.is_bedroom_sleeping
|
sleeping_in_the_room: binary_sensor.is_bedroom_sleeping
|
||||||
quick_resume: binary_sensor.bedroom_heatpump_quick_resume
|
quick_resume: binary_sensor.bedroom_heatpump_quick_resume
|
||||||
stay_on_while_sleeping: false
|
stay_on_while_sleeping: true
|
||||||
|
|
||||||
virtual_sensors:
|
virtual_sensors:
|
||||||
sensors:
|
sensors:
|
||||||
@@ -112,3 +112,36 @@ bedroom_heatpump:
|
|||||||
quick_resume:
|
quick_resume:
|
||||||
sensor: binary_sensor.bedroom_heatpump_quick_resume
|
sensor: binary_sensor.bedroom_heatpump_quick_resume
|
||||||
reset_event: good_morning
|
reset_event: good_morning
|
||||||
|
|
||||||
|
living_room_heatpump:
|
||||||
|
module: smartheatpump
|
||||||
|
class: SmartHeatpump
|
||||||
|
entity: climate.living_room_heatpump
|
||||||
|
|
||||||
|
templates_library: smart_heating_templates_library
|
||||||
|
|
||||||
|
virtual_sensors:
|
||||||
|
sensors:
|
||||||
|
binary_sensor.living_room_any_window_open: binary_sensor.living_room_french_door or binary_sensor.living_room_window
|
||||||
|
|
||||||
|
constants:
|
||||||
|
window_open: binary_sensor.living_room_any_window_open
|
||||||
|
ext_temperature: sensor.ext_front_temperature
|
||||||
|
room_temperature: sensor.living_room_temperature
|
||||||
|
room_occupancy: binary_sensor.living_room_occupancy
|
||||||
|
target_temperature: sensor.target_temperature_heatpump
|
||||||
|
cant_open_window: binary_sensor.is_living_room_sleeping
|
||||||
|
sleeping_in_the_room: binary_sensor.is_living_room_sleeping
|
||||||
|
quick_resume: binary_sensor.living_room_heatpump_quick_resume
|
||||||
|
stay_on_while_sleeping: false
|
||||||
|
|
||||||
|
target_temperature: sensor.target_temperature_heatpump
|
||||||
|
hvac_mode: "binary_sensor.heatpump_winter_mode ? 'heat' : 'cool'"
|
||||||
|
|
||||||
|
smart_conditions:
|
||||||
|
callback_delay: 10 # on the morning it can happen that we ask to start and stop the heat pump immediately afterwards which in result in the heat pump ignoring the second command
|
||||||
|
template_conditions: <clim_conditions>
|
||||||
|
|
||||||
|
quick_resume:
|
||||||
|
sensor: binary_sensor.living_room_heatpump_quick_resume
|
||||||
|
reset_event: good_morning
|
||||||
32
apps/global/notificationsmanagers.yaml
Normal file
32
apps/global/notificationsmanagers.yaml
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
notifications_manager:
|
||||||
|
module: notificationsmanager
|
||||||
|
class: NotificationsManager
|
||||||
|
|
||||||
|
priority: 100 # default priority app is 50, since the notification_manager doesn't create any sensor but is based on sensor created by many app, it's important it's created last
|
||||||
|
|
||||||
|
notifications:
|
||||||
|
back_home_notification:
|
||||||
|
recipients:
|
||||||
|
all:
|
||||||
|
services:
|
||||||
|
- notify/mobile_app_ipad_pro_11_de_pierre
|
||||||
|
conditions:
|
||||||
|
trigger_conditions:
|
||||||
|
- person.maeva == 'home'
|
||||||
|
- binary_sensor.is_bedroom_sleeping and (binary_sensor.hallway_motion or binary_sensor.corridor_motion or binary_sensor.bedroom_motion_bed_pierre)
|
||||||
|
blocking_conditions: not input_boolean.haw or not binary_sensor.someone_home
|
||||||
|
|
||||||
|
message:
|
||||||
|
content: Bisous
|
||||||
|
timeout: 600
|
||||||
|
|
||||||
|
leave_home_notification:
|
||||||
|
recipients:
|
||||||
|
all:
|
||||||
|
services:
|
||||||
|
- notify/mobile_app_macbook_m3_pro_de_pierre
|
||||||
|
conditions: input_boolean.haw and person.maeva != 'home' and binary_sensor.someone_home
|
||||||
|
|
||||||
|
message:
|
||||||
|
content: Good Bye
|
||||||
|
timeout: 600
|
||||||
@@ -10,12 +10,9 @@ sleep_sensors:
|
|||||||
binary_sensor.is_guestroom_sleeping: input_boolean.guestroom_sleeping
|
binary_sensor.is_guestroom_sleeping: input_boolean.guestroom_sleeping
|
||||||
|
|
||||||
binary_sensor.is_everybody_sleeping:
|
binary_sensor.is_everybody_sleeping:
|
||||||
- binary_sensor.is_bedroom_sleeping
|
- (binary_sensor.is_bedroom_sleeping or not input_boolean.bedroom_occupied_tonight) and (binary_sensor.is_living_room_sleeping or not input_boolean.living_room_occupied_tonight) and (binary_sensor.is_desk_sleeping or not input_boolean.desk_occupied_tonight) and (binary_sensor.is_guestroom_sleeping or not input_boolean.guestroom_occupied_tonight)
|
||||||
#- binary_sensor.is_living_room_sleeping and ...
|
|
||||||
#- binary_sensor.is_desk_sleeping and ...
|
|
||||||
#- binary_sensor.is_guestroom_sleeping and ...
|
|
||||||
binary_sensor.is_anybody_sleeping:
|
binary_sensor.is_anybody_sleeping:
|
||||||
- binary_sensor.is_bedroom_sleeping
|
- binary_sensor.is_bedroom_sleeping and input_boolean.bedroom_occupied_tonight
|
||||||
- binary_sensor.is_living_room_sleeping
|
- binary_sensor.is_living_room_sleeping and input_boolean.living_room_occupied_tonight
|
||||||
- binary_sensor.is_desk_sleeping
|
- binary_sensor.is_desk_sleeping and input_boolean.desk_occupied_tonight
|
||||||
- binary_sensor.is_guestroom_sleeping
|
- binary_sensor.is_guestroom_sleeping and input_boolean.guestroom_occupied_tonight
|
||||||
@@ -7,7 +7,7 @@ virtual_events:
|
|||||||
virtual_events:
|
virtual_events:
|
||||||
good_morning:
|
good_morning:
|
||||||
event_name: good_morning
|
event_name: good_morning
|
||||||
event_condition: not binary_sensor.is_everybody_sleeping
|
event_condition: not binary_sensor.is_anybody_sleeping
|
||||||
|
|
||||||
turn_off_all_lights:
|
turn_off_all_lights:
|
||||||
event_name: turn_off_all_lights
|
event_name: turn_off_all_lights
|
||||||
|
|||||||
94
apps/notificationsmanager.py
Normal file
94
apps/notificationsmanager.py
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
import appdaemon.plugins.hass.hassapi as hass
|
||||||
|
import appdaemon.exceptions as ad_exception
|
||||||
|
import ad_toolbox.smartcondition as SmartCondition
|
||||||
|
import uuid
|
||||||
|
from expressionparser import ParsingException
|
||||||
|
|
||||||
|
class Notification:
|
||||||
|
def __init__(self,ad_api,config,name):
|
||||||
|
self.recipients = dict()
|
||||||
|
self.config = config
|
||||||
|
self.ad_api = ad_api
|
||||||
|
try: self.auto_clear = config['message']['auto_clear']
|
||||||
|
except KeyError: self.auto_clear = False
|
||||||
|
self.uuid = str(uuid.uuid4())
|
||||||
|
for recipient in config["recipients"]:
|
||||||
|
try: self.recipients[recipient] = SmartCondition.Evaluator(self.ad_api,self.config["recipients"][recipient]['conditions'],condition_name = name,on_succeed_cb = self.on_condition_succeed, on_fail_cb = self.on_conditon_fail,pass_condition_name_to_cb = recipient, trigger_callback_on_activation = False)
|
||||||
|
except ParsingException as e:
|
||||||
|
self.log_error(str(e))
|
||||||
|
continue
|
||||||
|
|
||||||
|
def on_conditon_fail(self, recipient):
|
||||||
|
if self.auto_clear:
|
||||||
|
try: tag = self.config['message']['data']['tag']
|
||||||
|
except KeyError: tag = self.uuid
|
||||||
|
|
||||||
|
self.clear_notification(recipient,tag)
|
||||||
|
|
||||||
|
def on_condition_succeed(self,recipient):
|
||||||
|
self.send_notification(recipient)
|
||||||
|
|
||||||
|
def on_timeout_expired(self,kwargs):
|
||||||
|
tag = kwargs['tag']
|
||||||
|
recipient = kwargs['recipient']
|
||||||
|
|
||||||
|
self.clear_notification(recipient,tag)
|
||||||
|
|
||||||
|
def clear_notification(self,recipient,tag):
|
||||||
|
message = 'clear_notification'
|
||||||
|
data = { 'tag' : tag }
|
||||||
|
|
||||||
|
def clear_notification(service,tag):
|
||||||
|
self.ad_api.log(f"Clear notification {data} from {service}")
|
||||||
|
try: self.ad_api.call_service(service,message = message, data = data)
|
||||||
|
except ad_exception.ServiceException: self.log_error(f"Invalid service: {service}")
|
||||||
|
|
||||||
|
recipient_yaml = self.config["recipients"][recipient]
|
||||||
|
if isinstance(recipient_yaml['services'], str):
|
||||||
|
clear_notification(recipient_yaml['services'],tag)
|
||||||
|
else:
|
||||||
|
for service in recipient_yaml['services']:
|
||||||
|
clear_notification(service,tag)
|
||||||
|
|
||||||
|
def send_notification(self,recipient):
|
||||||
|
try: title = self.config['message']['title']
|
||||||
|
except KeyError: title = ""
|
||||||
|
try: message = self.config['message']['content']
|
||||||
|
except KeyError: message = ""
|
||||||
|
try: data = self.config['message']['data']
|
||||||
|
except KeyError: data = dict()
|
||||||
|
|
||||||
|
#TODO : maybe it's better to not send tag when it's not needed
|
||||||
|
if not 'tag' in data:
|
||||||
|
data['tag'] = self.uuid
|
||||||
|
|
||||||
|
if 'timeout' in self.config['message']:
|
||||||
|
timeout = self.config['message']['timeout']
|
||||||
|
self.ad_api.run_in(self.on_timeout_expired,timeout,tag = data['tag'],recipient = recipient)
|
||||||
|
|
||||||
|
def send_notification(service):
|
||||||
|
self.ad_api.log(f"Sending notification '{message}' to {service}{f' with data {data}' if data else ''}")
|
||||||
|
try: self.ad_api.call_service(service,title = title,message = message, data = data)
|
||||||
|
except ad_exception.ServiceException: self.log_error(f"Invalid service: {service}")
|
||||||
|
|
||||||
|
recipient_yaml = self.config["recipients"][recipient]
|
||||||
|
if isinstance(recipient_yaml['services'], str):
|
||||||
|
send_notification(recipient_yaml['services'])
|
||||||
|
else:
|
||||||
|
for service in recipient_yaml['services']:
|
||||||
|
send_notification(service)
|
||||||
|
|
||||||
|
def log_error(self,message,stop_app = False):
|
||||||
|
self.ad_api.log(message,level = "ERROR", log = "main_log")
|
||||||
|
self.ad_api.log(message,level = "ERROR", log = "error_log")
|
||||||
|
if stop_app:
|
||||||
|
self.ad_api.stop_app(self.ad_api.name)
|
||||||
|
|
||||||
|
class NotificationsManager(hass.Hass):
|
||||||
|
|
||||||
|
def initialize(self):
|
||||||
|
self.notifications = dict()
|
||||||
|
|
||||||
|
if "notifications" in self.args:
|
||||||
|
for notification in self.args["notifications"]:
|
||||||
|
self.notifications[notification] = Notification(self,self.args["notifications"][notification],notification)
|
||||||
@@ -167,6 +167,10 @@ bed_ledstrip:
|
|||||||
|
|
||||||
light_brightness_pct: 1
|
light_brightness_pct: 1
|
||||||
|
|
||||||
|
off_events:
|
||||||
|
- turn_off_all_lights
|
||||||
|
- good_morning
|
||||||
|
|
||||||
alarm_clock:
|
alarm_clock:
|
||||||
module: alarmclock
|
module: alarmclock
|
||||||
class: AlarmClock
|
class: AlarmClock
|
||||||
|
|||||||
@@ -22,7 +22,10 @@ class SmartHeatpump(SmartObject):
|
|||||||
else:
|
else:
|
||||||
self.horizontal_vane = None
|
self.horizontal_vane = None
|
||||||
|
|
||||||
|
if 'fan_mode' in self.args:
|
||||||
self.fan_mode = SmartValue.Evaluator(self,self.args['fan_mode'], expression_name = 'fan_mode', on_change_cb = self.on_change_fan_mode, constants = self.constants)
|
self.fan_mode = SmartValue.Evaluator(self,self.args['fan_mode'], expression_name = 'fan_mode', on_change_cb = self.on_change_fan_mode, constants = self.constants)
|
||||||
|
else:
|
||||||
|
self.fan_mode = None
|
||||||
self.smart_conditions_evaluator = SmartCondition.Evaluator(self,self.args['smart_conditions'],condition_name = "smart_conditions",on_change_cb = self.on_smart_conditions_change,constants = self.constants, templates_library = self.templates_library)
|
self.smart_conditions_evaluator = SmartCondition.Evaluator(self,self.args['smart_conditions'],condition_name = "smart_conditions",on_change_cb = self.on_smart_conditions_change,constants = self.constants, templates_library = self.templates_library)
|
||||||
|
|
||||||
if 'input_buttons' in self.args:
|
if 'input_buttons' in self.args:
|
||||||
@@ -44,7 +47,7 @@ class SmartHeatpump(SmartObject):
|
|||||||
self.set_state(self.args['quick_resume']['sensor'],state = 'on')
|
self.set_state(self.args['quick_resume']['sensor'],state = 'on')
|
||||||
temperature = self.target_temperature.evaluate(False)
|
temperature = self.target_temperature.evaluate(False)
|
||||||
hvac_mode = self.hvac_mode.evaluate(False)
|
hvac_mode = self.hvac_mode.evaluate(False)
|
||||||
fan_mode = self.fan_mode.evaluate(False)
|
fan_mode = self.fan_mode.evaluate(False) if self.fan_mode else None
|
||||||
self.log_info(f"Starting Heatpump in {hvac_mode} mode, with target_temperature of {temperature}° and {fan_mode} fan speed")
|
self.log_info(f"Starting Heatpump in {hvac_mode} mode, with target_temperature of {temperature}° and {fan_mode} fan speed")
|
||||||
|
|
||||||
#self.turn_on(self.entity_id)
|
#self.turn_on(self.entity_id)
|
||||||
@@ -53,6 +56,7 @@ class SmartHeatpump(SmartObject):
|
|||||||
self.call_service("climate/set_hvac_mode", entity_id = self.entity_id,hvac_mode = hvac_mode)
|
self.call_service("climate/set_hvac_mode", entity_id = self.entity_id,hvac_mode = hvac_mode)
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
self.call_service("climate/set_temperature", entity_id = self.entity_id,temperature = temperature,hvac_mode = hvac_mode)
|
self.call_service("climate/set_temperature", entity_id = self.entity_id,temperature = temperature,hvac_mode = hvac_mode)
|
||||||
|
if self.fan_mode:
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
self.call_service("climate/set_fan_mode", entity_id = self.entity_id,fan_mode = fan_mode)
|
self.call_service("climate/set_fan_mode", entity_id = self.entity_id,fan_mode = fan_mode)
|
||||||
if self.horizontal_vane:
|
if self.horizontal_vane:
|
||||||
|
|||||||
Reference in New Issue
Block a user