Skip to content

Commit

Permalink
ha - context blinds
Browse files Browse the repository at this point in the history
  • Loading branch information
ph4r05 committed Aug 22, 2024
1 parent 58789df commit ae9b7e5
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 5 deletions.
82 changes: 78 additions & 4 deletions ph4ha/apps/blinds.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
import datetime
import json
from datetime import time
from enum import Enum, auto
from typing import Optional

import hassapi as hass
import requests


class BlindsState(Enum):
INITIAL = auto()
MORNING_SCHEME = auto()
AFTERNOON_UP = auto()
PRIVACY_MODE = auto()
NIGHT_MODE = auto()


class Blinds(hass.Hass):
"""
TODO: collect manual state changes. manual state change cancels the next routine
Expand All @@ -27,34 +38,55 @@ def __init__(self, *args, **kwargs):
self.guest_weekdays_open_time = None
self.guest_mode: bool = False
self.automation_enabled: bool = True
self.bedroom_automation_enabled: bool = True
self.next_dusk_time = None

self.field_weekdays_open_time = None
self.field_guest_mode = None
self.field_automation_enabled = None
self.field_guest_weekdays_open_time = None
self.field_bedroom_automation_enabled = None
self.field_weekend_open_time = None
self.field_sunset_offset_time = None
self.field_full_open_time = None
self.field_full_close_time = None

def initialize(self):
self.blinds = {x["name"]: x for x in self.args["blinds"]}
self.field_weekdays_open_time = self.args["weekdays_open_time"]
self.field_guest_weekdays_open_time = self.args["guest_weekdays_open_time_input"]
self.field_guest_mode = self.args["guest_mode_input"]
self.field_automation_enabled = self.args["automation_enabled_input"]
self.field_bedroom_automation_enabled = self.args["bedroom_automation_enabled"]
# self.field_weekend_open_time = self.args["weekend_open_time_input"]
# self.field_sunset_offset_time = self.args["sunset_offset_time_input"]
# self.field_full_open_time = self.args["full_open_time_input"]
# self.field_full_close_time = self.args["full_close_time_input"]

# Set initial blind open time
self.update_blind_open_time()
self.update_blind_open_time_guest()
self.update_blind_guest_mode()
self.update_blind_automation_enabled()
self.update_blind_bedroom_automation_enabled()
self.update_dusk_time()

# Listen for changes to the input_datetime entity
self.listen_state(self.update_blind_open_time, self.field_weekdays_open_time)
self.listen_state(self.update_blind_open_time_guest, self.field_guest_weekdays_open_time)
self.listen_state(self.update_blind_guest_mode, self.field_guest_mode)
self.listen_state(self.update_blind_automation_enabled, self.field_automation_enabled)
self.listen_state(self.update_blind_bedroom_automation_enabled, self.field_bedroom_automation_enabled)

# Listen to scene changes
self.listen_event(self.scene_activated, "call_service", domain="scene", service="turn_on")

# Daily update new dusk time
self.run_daily(self.update_dusk_time(), time(hour=0, minute=0))

# TODO: separate bedroom - add another timer, bedroom mode.
# TODO: dusk timer, sensor.sun_next_dusk

# # Schedule for weekdays
# self.run_daily(self.open_blinds, time(hour=7, minute=30), weekdays="mon,tue,wed,thu,fri")
#
Expand All @@ -72,7 +104,23 @@ def initialize(self):

self.log(f"initialized, {self.weekdays_open_time=}, {self.guest_mode=}")

def update_dusk_time(self, entity=None, attribute=None, old=None, new=None, kwargs=None):
self.log(f"on_update: {entity=}, {attribute=}, {old=}, {new=}, {kwargs=}")

dusk_time_str = self.get_state("sensor.sun_next_dusk")
if dusk_time_str is None:
self.log("Failed to retrieve dusk time state.")
return

try:
self.log(f"{dusk_time_str=}")
self.next_dusk_time = datetime.datetime.fromisoformat(dusk_time_str.replace("Z", "+00:00"))
self.log(f"{self.next_dusk_time=}")
except Exception as e:
self.log(f"Failed to retrieve dusk time state: {e}")

def update_blind_open_time(self, entity=None, attribute=None, old=None, new=None, kwargs=None):
self.log(f"on_update: {entity=}, {attribute=}, {old=}, {new=}, {kwargs=}")
weekday_blind_open_time = self.get_state(self.field_weekdays_open_time)

if weekday_blind_open_time is None:
Expand All @@ -90,6 +138,7 @@ def update_blind_open_time(self, entity=None, attribute=None, old=None, new=None
# self.run_daily(self.open_blinds, self.weekdays_open_time)

def update_blind_open_time_guest(self, entity=None, attribute=None, old=None, new=None, kwargs=None):
self.log(f"on_update: {entity=}, {attribute=}, {old=}, {new=}, {kwargs=}")
open_time = self.get_state(self.field_guest_weekdays_open_time)

if open_time is None:
Expand All @@ -99,15 +148,20 @@ def update_blind_open_time_guest(self, entity=None, attribute=None, old=None, ne
self.log(f"{self.guest_weekdays_open_time=}")

def update_blind_guest_mode(self, entity=None, attribute=None, old=None, new=None, kwargs=None):
guest_mode = self.get_state(self.field_guest_mode)
self.guest_mode = guest_mode == "on"
self.log(f"on_update: {entity=}, {attribute=}, {old=}, {new=}, {kwargs=}")
self.guest_mode = self.to_bool(self.get_state(self.field_guest_mode))
self.log(f"{self.guest_mode=}")

def update_blind_automation_enabled(self, entity=None, attribute=None, old=None, new=None, kwargs=None):
automation_enabled = self.get_state(self.field_automation_enabled)
self.automation_enabled = automation_enabled == "on"
self.log(f"on_update: {entity=}, {attribute=}, {old=}, {new=}, {kwargs=}")
self.automation_enabled = self.to_bool(self.get_state(self.field_guest_mode))
self.log(f"{self.automation_enabled=}")

def update_blind_bedroom_automation_enabled(self, entity=None, attribute=None, old=None, new=None, kwargs=None):
self.log(f"on_update: {entity=}, {attribute=}, {old=}, {new=}, {kwargs=}")
self.bedroom_automation_enabled = self.to_bool(self.get_state(self.field_guest_mode))
self.log(f"{self.bedroom_automation_enabled=}")

def scene_activated(self, event_name, data, kwargs):
# Extract the scene ID or entity ID
scene_id = data.get("service_data", {}).get("entity_id")
Expand Down Expand Up @@ -144,6 +198,8 @@ def handle_scene(self, scene_id):
self.blinds_all_down_open()
elif scene_id == "scene.blinds_morning":
self.blinds_morning()
elif scene_id == "scene.blinds_morning_context":
self.blinds_morning_context()
elif scene_id == "scene.blinds_living_down_close":
self.blinds_living_down_close()
elif scene_id == "scene.blinds_living_down_open":
Expand Down Expand Up @@ -246,6 +302,21 @@ def blinds_morning(self):
if not self.guest_mode:
self.blinds_pos_tilt(self.BLIND_SKLAD, 0, self.OPEN_HALF)

def blinds_morning_context(self):
if not self.automation_enabled:
self.log("Automation disabled")
return

self.blinds_living_morning()
self.blinds_pos_tilt(self.BLIND_LIV_DOOR, 100, 0)
self.blinds_pos_tilt(self.BLIND_STUDY, 0, self.OPEN_HALF)

if not self.guest_mode:
self.blinds_pos_tilt(self.BLIND_SKLAD, 0, self.OPEN_HALF)

if self.bedroom_automation_enabled:
self.blinds_pos_tilt(self.BLIND_BEDROOM, 100, 0)

def blind_move(self, blind, pos: Optional[float], tilt: float):
if pos is None:
self.blinds_tilt(blind, tilt)
Expand All @@ -268,3 +339,6 @@ def blinds_req(self, blind, data):
)
self.log(f"Req: {blind_host}, data: {json.dumps(data)}, response: {response}")
return response

def to_bool(self, inp):
return inp == "on"
3 changes: 3 additions & 0 deletions ph4ha/config-ha/configuration.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ input_boolean:
blinds_automation_enabled:
name: "Blinds Automation enabled"
initial: true
blinds_bedroom_automation_enabled:
name: "Blinds Bedroom enabled"
initial: false

input_datetime:
blinds_weekday_open_time:
Expand Down
5 changes: 5 additions & 0 deletions ph4ha/config-ha/scenes.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@
entities: { }
icon: mdi:blinds
metadata: { }
- id: 'scene-blinds-morning-context'
name: Blinds Morning Context
entities: { }
icon: mdi:blinds
metadata: { }
- id: 'scene-living-down-open'
name: Blinds Living Down Open
entities: { }
Expand Down
2 changes: 1 addition & 1 deletion ph4ha/config/apps.example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ blinds:
guest_mode_input: "input_boolean.blinds_guest_mode"
guest_weekdays_open_time_input: "input_datetime.blinds_weekday_guest_open_time"
automation_enabled_input: "input_boolean.blinds_automation_enabled"
bedroom_automation_enabled: "input_boolean.blinds_bedroom_automation_enabled"

morning_routine_time_input: "input_text.weekday_blind_open_time"
full_open_time_input: "input_text.weekday_blind_open_time"
full_close_time_input: "input_text.weekday_blind_open_time"
privacy_time_input: "input_text.weekday_blind_open_time"

0 comments on commit ae9b7e5

Please sign in to comment.