def update_sun_state(now): # pylint: disable=unused-argument """ Method to update the current state of the sun and set time of next setting and rising. """ observer = ephem.Observer() observer.lat = latitude observer.long = longitude next_rising_dt = ephem.localtime(observer.next_rising(sun)) next_setting_dt = ephem.localtime(observer.next_setting(sun)) if next_rising_dt > next_setting_dt: new_state = STATE_ABOVE_HORIZON next_change = next_setting_dt else: new_state = STATE_BELOW_HORIZON next_change = next_rising_dt logger.info( "Sun:{}. Next change: {}".format(new_state, next_change.strftime("%H:%M"))) state_attributes = { STATE_ATTR_NEXT_RISING: ha.datetime_to_str(next_rising_dt), STATE_ATTR_NEXT_SETTING: ha.datetime_to_str(next_setting_dt) } statemachine.set_state(STATE_CATEGORY, new_state, state_attributes) # +10 seconds to be sure that the change has occured ha.track_time_change(bus, update_sun_state, point_in_time=next_change + timedelta(seconds=10))
def __init__(self, bus, statemachine, device_scanner): self.statemachine = statemachine self.bus = bus self.device_scanner = device_scanner self.logger = logging.getLogger(__name__) self.lock = threading.Lock() # Dictionary to keep track of known devices and devices we track self.known_devices = {} # Did we encounter a valid known devices file self.invalid_known_devices_file = False self._read_known_devices_file() ha.track_time_change(bus, lambda time: self.update_devices( device_scanner.scan_devices())) bus.register_service(DOMAIN_DEVICE_TRACKER, SERVICE_DEVICE_TRACKER_RELOAD, lambda service: self._read_known_devices_file()) self.update_devices(device_scanner.scan_devices())
def handle_sun_rising(category, old_state, new_state): """The moment sun sets we want to have all the lights on. We will schedule to have each light start after one another and slowly transition in.""" def turn_light_on_before_sunset(light_id): """ Helper function to turn on lights slowly if there are devices home and the light is not on yet. """ if (device.is_home(statemachine) and not light.is_on(statemachine, light_id)): light.turn_on(bus, light_id, LIGHT_TRANSITION_TIME.seconds) def turn_on(light_id): """ Lambda can keep track of function parameters but not local parameters. If we put the lambda directly in the below statement only the last light will be turned on.. """ return lambda now: turn_light_on_before_sunset(light_id) start_point = time_for_light_before_sun_set() for index, light_id in enumerate(light_ids): ha.track_time_change(bus, turn_on(light_id), point_in_time=(start_point + index * LIGHT_TRANSITION_TIME))
def setup(bus, statemachine, light_control): """ Exposes light control via statemachine and services. """ def update_light_state(time): # pylint: disable=unused-argument """ Track the state of the lights. """ try: should_update = datetime.now() - update_light_state.last_updated \ > MIN_TIME_BETWEEN_SCANS except AttributeError: # if last_updated does not exist should_update = True if should_update: update_light_state.last_updated = datetime.now() status = {light_id: light_control.is_light_on(light_id) for light_id in light_control.light_ids} for light_id, state in status.items(): state_category = STATE_CATEGORY_FORMAT.format(light_id) statemachine.set_state(state_category, STATE_ON if state else STATE_OFF) statemachine.set_state(STATE_CATEGORY_ALL_LIGHTS, STATE_ON if True in status.values() else STATE_OFF) ha.track_time_change(bus, update_light_state, second=[0, 30]) def handle_light_event(service): """ Hande a turn light on or off service call. """ light_id = service.data.get("light_id", None) transition_seconds = service.data.get("transition_seconds", None) if service.service == ha.SERVICE_TURN_ON: light_control.turn_light_on(light_id, transition_seconds) else: light_control.turn_light_off(light_id, transition_seconds) update_light_state(None) # Listen for light on and light off events bus.register_service(DOMAIN, ha.SERVICE_TURN_ON, handle_light_event) bus.register_service(DOMAIN, ha.SERVICE_TURN_OFF, handle_light_event) update_light_state(None) return True
def setup(bus, statemachine, host): """ Listen for chromecast events. """ device = pychromecast.get_device_status(host) if not device: return False category = STATE_CATEGORY_FORMAT.format(util.slugify( device.friendly_name)) bus.register_service(DOMAIN_CHROMECAST, ha.SERVICE_TURN_OFF, lambda service: turn_off(statemachine, service.data.get("cc_id", None))) bus.register_service(DOMAIN_CHROMECAST, "start_fireplace", lambda service: pychromecast.play_youtube_video(host, "eyU3bRy2x44")) bus.register_service(DOMAIN_CHROMECAST, "start_epic_sax", lambda service: pychromecast.play_youtube_video(host, "kxopViU98Xo")) bus.register_service(DOMAIN_CHROMECAST, SERVICE_YOUTUBE_VIDEO, lambda service: pychromecast.play_youtube_video( host, service.data['video'])) def update_chromecast_state(time): # pylint: disable=unused-argument """ Retrieve state of Chromecast and update statemachine. """ status = pychromecast.get_app_status(host) if status: statemachine.set_state(category, status.name, {ATTR_FRIENDLY_NAME: pychromecast.get_friendly_name( status.name), ATTR_HOST: host, ATTR_STATE: status.state, ATTR_OPTIONS: status.options}) else: statemachine.set_state(category, STATE_NO_APP) ha.track_time_change(bus, update_chromecast_state) update_chromecast_state(None) return True
def _handle_sun_rising(self, category, old_state, new_state): """The moment sun sets we want to have all the lights on. We will schedule to have each light start after one another and slowly transition in.""" start_point = self._time_for_light_before_sun_set() def turn_on(light): """ Lambda can keep track of function parameters but not local parameters. If we put the lambda directly in the below statement only the last light would be turned on.. """ return lambda now: self._turn_light_on_before_sunset(light) for index, light_id in enumerate(self.light_control.light_ids): ha.track_time_change(self.eventbus, turn_on(light_id), point_in_time=(start_point + index * LIGHT_TRANSITION_TIME))
def __init__(self, eventbus, statemachine, device_scanner): self.statemachine = statemachine self.eventbus = eventbus self.device_scanner = device_scanner self.logger = logging.getLogger(__name__) self.lock = threading.Lock() # Dictionary to keep track of known devices and devices we track self.known_devices = {} # Did we encounter a valid known devices file self.invalid_known_devices_file = False # Read known devices if file exists if os.path.isfile(KNOWN_DEVICES_FILE): with open(KNOWN_DEVICES_FILE) as inp: default_last_seen = datetime(1990, 1, 1) # Temp variable to keep track of which categories we use # so we can ensure we have unique categories. used_categories = [] try: for row in csv.DictReader(inp): device = row['device'] row['track'] = True if row['track'] == '1' else False # If we track this device setup tracking variables if row['track']: row['last_seen'] = default_last_seen # Make sure that each device is mapped # to a unique category name name = row['name'] if not name: name = "unnamed_device" tries = 0 suffix = "" while True: tries += 1 if tries > 1: suffix = "_{}".format(tries) category = STATE_CATEGORY_DEVICE_FORMAT.format( name + suffix) if category not in used_categories: break row['category'] = category used_categories.append(category) self.known_devices[device] = row except KeyError: self.invalid_known_devices_file = False self.logger.warning(( "Invalid {} found. " "We won't update it with new found devices."). format(KNOWN_DEVICES_FILE)) if len(self.device_state_categories) == 0: self.logger.warning( "No devices to track. Please update {}.".format( KNOWN_DEVICES_FILE)) ha.track_time_change(eventbus, lambda time: self.update_devices( device_scanner.scan_devices()))