def set_blind_position(self, *args): current_elevation = elevation(self.locationInfo.observer) current_azimuth = azimuth(self.locationInfo.observer) self.log( "current_elevation: {}, open_elevation: {}, close_elevation: {}". format(current_elevation, self.open_elevation, self.close_elevation)) self.log( "current_azimuth: {}, start_azimuth: {}, end_azimuth: {}".format( current_azimuth, self.start_azimuth, self.end_azimuth)) for cover in self.covers: if self.start_azimuth <= current_azimuth <= self.end_azimuth: position = max( 0, min( 100, self.offset + ((current_elevation - self.close_elevation) / (self.open_elevation - self.close_elevation) * 100), ), ) self.log("setting {} to {}".format(cover, position)) self.call_service("cover/set_cover_position", entity_id=cover, position=position) else: self.log("not setting blinds, outside azimuth range")
def update(self, now): self.__current.update(now) # We only activate the stir mode if the sun elevation is greater than ~20°. # No need to stir at night, this mode is meant to lower the solar cover # temperature. if self.__period > timedelta() and self.__current.elapsed(): elevation = sun.elevation(self.__city) if self.__stir_state: self.__pause(None) elif elevation >= StirMode.SOLAR_ELEVATION and self.__duration > timedelta( ): self.__stir()
async def sun_position(self): """Calculate where the sun is in the sky.""" astral_now = now(tzinfo=self._tzinfo) sun_elevation = elevation(observer=self._siteinfo.observer, dateandtime=astral_now) sun_azimuth = azimuth(observer=self._siteinfo.observer, dateandtime=astral_now) results = [{ 'topic': 'sun/position', 'elevation': round(sun_elevation, 1), 'azimuth': round(sun_azimuth, 1) }] return results
def publishLightInfo(dateAndTime): if state.timezone is None: print("Could not determine the time zone") else: # Calculate solar elevation and twilight start and end times angle = sun.elevation(location, dateAndTime) print('solar elevation: ' + str(angle)) mqtt_publish('solarElevation', str(angle)) times_setting = sun.twilight(location, dateAndTime, SunDirection.SETTING) times_rising = sun.twilight(location, dateAndTime, SunDirection.RISING) if debug: print("DEBUG: rising start " + str(times_rising[0].astimezone(state.timezone))) print("DEBUG: rising end " + str(times_rising[1].astimezone(state.timezone))) print("DEBUG: setting start " + str(times_setting[0].astimezone(state.timezone))) print("DEBUG: setting end " + str(times_setting[1].astimezone(state.timezone))) # Classify and publish the current light situation on track as one of # night, dawn, day or dusk lightinfo = 'day' if dateAndTime < times_rising[0].astimezone(state.timezone): lightinfo = 'night' elif dateAndTime < times_rising[1].astimezone(state.timezone): lightinfo = 'dawn' elif dateAndTime < times_setting[0].astimezone(state.timezone): lightinfo = 'day' elif dateAndTime < times_setting[1].astimezone(state.timezone): lightinfo = 'dusk' else: lightinfo = 'night' print('lightinfo: ' + lightinfo) mqtt_publish('lightinfo', lightinfo)
def test_ElevationEqualsTimeAtElevation(elevation, london): o = london.observer td = today() et = sun.time_at_elevation(o, elevation, td) assert sun.elevation(o, et) == pytest.approx(elevation, abs=0.05)
def test_Elevation_Above85Degrees(): d = datetime.datetime(2001, 6, 21, 13, 11, 0) assert sun.elevation(Observer(86, 77.2), d) == pytest.approx(23.102501151619506, abs=0.001)
def test_Elevation_WithoutRefraction(new_delhi): d = datetime.datetime(2001, 6, 21, 13, 11, 0) assert sun.elevation( new_delhi, d, with_refraction=False) == pytest.approx(7.293490557358638)
def test_Elevation_NonNaive(new_delhi): d = datetime.datetime(2001, 6, 21, 18, 41, 0) d = new_delhi.tz.localize(d) assert sun.elevation(new_delhi, d) == pytest.approx(7.411009003716742)
def test_Elevation(new_delhi): d = datetime.datetime(2001, 6, 21, 13, 11, 0) assert sun.elevation(new_delhi, d) == pytest.approx(7.411009003716742)
def test_SolarAltitude_NoDate(london): assert sun.elevation(london) == pytest.approx(14.381311, abs=0.001)
def test_SolarAltitude(dt, angle, london): assert sun.elevation(london.observer, dt) == pytest.approx(angle, abs=0.001)
async def automatic_shading(self): """ Process every minute the automatic shading """ if not self.enabled: return # wait for brightness to come and end if not self.automatic_shading_sun_active and self.setpoint_brightness < self.outdoor_brightness: result = self.automatic_shading_sun_on.process() if result: self.logger.info( f"Sun is now active {self.outdoor_brightness:.2f}, {self.setpoint_brightness:.2f}" ) self.automatic_shading_sun_active = True else: self.automatic_shading_sun_on.reset() if self.automatic_shading_sun_active and self.outdoor_brightness < self.setpoint_brightness: result = self.automatic_shading_sun_off.process() if result: self.logger.info( f"Sun is now inactive {self.outdoor_brightness:.2f}, {self.setpoint_brightness:.2f}" ) self.automatic_shading_sun_active = False else: self.automatic_shading_sun_off.reset() sun_in_range = (self.automatic_shading_range.start_time_with_offset <= datetime.now(tz=self.location_info.tzinfo) <= self.automatic_shading_range.stop_time_with_offset) # wait for the sun to come in range if self.automatic_shading_state == AutomaticShadingState.IDLE and sun_in_range: self.logger.info(f"Sun has entered the range") self.automatic_shading_state = AutomaticShadingState.SHADING_READY # when sun goes out of range stop shading if (self.automatic_shading_state == AutomaticShadingState.SHADING or self.automatic_shading_state == AutomaticShadingState.SHADING_READY) and not sun_in_range: self.logger.info(f"Sun has left the range") await self.move_to_starting_position() self.automatic_shading_state = AutomaticShadingState.IDLE # when it is bright enough and the sun is in range we can start shading if self.automatic_shading_state == AutomaticShadingState.SHADING_READY and self.automatic_shading_sun_active: self.logger.info(f"Start automatic shading") self.automatic_shading_state = AutomaticShadingState.SHADING # when it gets darker again, stop the automatic shading and raise the shades if self.automatic_shading_state == AutomaticShadingState.SHADING and not self.automatic_shading_sun_active: self.logger.info(f"Stop automatic shading, it is too dark") await self.move_to_starting_position() self.automatic_shading_state = AutomaticShadingState.SHADING_READY # do the automatic shading if self.automatic_shading_state == AutomaticShadingState.SHADING: # get configuration device_config_parameter = self.device_config["parameter"] distance_slats = device_config_parameter["distance_slats"] wide_slats = device_config_parameter["wide_slats"] minimum_change_tracking = device_config_parameter[ "minimum_change_tracking"] # calculate the angle for the slats current_elevation = elevation(self.location_info.observer) alpha = ((math.pi / 2) - math.radians(current_elevation)) gamma = alpha + math.asin((distance_slats / 2.0) * (math.sin(alpha) / (wide_slats / 2.0))) _gamma = clamp(gamma, 0.0, math.pi) position_slat = (100.0 / math.pi) * _gamma if (position_slat < self.current_position_slat - minimum_change_tracking or self.current_position_slat + minimum_change_tracking < position_slat): self.logger.info( f"Shading new value: Height {100}/Slat {position_slat:.2f}" ) await self.actors_send(100, position_slat) self.current_position_slat = position_slat
def is_dark(lat, lng, alt=0): obs = Observer(lat, lng, alt) if elevation(obs) < _DUSK_ELEVATION: return True else: return False