def test_NorwaySunUp(): """Test location in Norway where the sun doesn't set in summer.""" june = datetime(2019, 6, 5, tzinfo=pytz.utc) obs = astral.Observer(69.6, 18.8, 0.0) with pytest.raises(ValueError): sun.sunrise(obs, june) with pytest.raises(ValueError): sun.sunset(obs, june) # Find the next sunset and sunrise: next_sunrise = _next_event(obs, june, "sunrise") next_sunset = _next_event(obs, june, "sunset") assert next_sunset < next_sunrise
def drawdaytime(clockface, city): """drawdaytime - Set all the LEDs around the clock to yellow (daytime) or blue (night time) Args: clockface: The 60 Neopixels to draw into city: The location to calculate sunrise/sunset for Notes: TODO: Unhandled exception for locations in the polar regions """ sunrise = sun.sunrise(city.observer, tzinfo=city.tzinfo) sunset = sun.sunset(city.observer, tzinfo=city.tzinfo) # Convert sunrise and sunset to LED numbers daystart = int(((sunrise.hour * 60) + sunrise.minute) / 24) dayend = int(((sunset.hour * 60) + sunset.minute) / 24) # Set the "day" LEDs to dim yellow, night LEDs to dark blue for led in range(0, daystart): clockface[led] = (0, 0, 4) for led in range(daystart, dayend + 1): clockface[led] = (1, 1, 0) for led in range(dayend + 1, 60): clockface[led] = (0, 0, 4)
def plotNighttime(self, axes=None, plot=True): dayList = [ (self.timerange[0] + dt.timedelta(days=x - 1)).date() for x in range((self.timerange[1] - self.timerange[0]).days + 3) ] for day in dayList: day = dt.datetime.combine(day, dt.datetime.min.time()) sunrise = sun.sunrise(self.loc.observer, date=day, tzinfo=self.to_tzone) sunset = sun.sunset(self.loc.observer, date=day, tzinfo=self.to_tzone) # print(F"#DEBUG: sunrise: {sunrise}, sunset: {sunset}") timelist = [ day, sunrise - dt.timedelta(seconds=1), sunrise, sunset, sunset + dt.timedelta(seconds=1), day + dt.timedelta(days=1) ] if plot: axes.autoscale(enable=False) limits = axes.get_ylim() axes.fill_between(timelist, np.full(len(timelist), limits[0]), np.full(len(timelist), limits[1]), where=[True, True, False, False, True, True], facecolor='black', alpha=0.05) return timelist
def clean_post(frame): frame = frame.dropna() post = frame.to_dict() post['dateandtime'] = (post['dateandtime'].replace(tzinfo=to_tzone) .astimezone(db_tzone) .to_pydatetime()) del post['Date'] del post['Time'] sunrise = sun.sunrise(loc.observer, date=post['dateandtime'].date(), tzinfo=to_tzone).astimezone(db_tzone) sunset = sun.sunset(loc.observer, date=post['dateandtime'].date(), tzinfo=to_tzone).astimezone(db_tzone) post['daylight'] = ((post['dateandtime'] > sunrise) and (post['dateandtime'] < sunset)) * 1 return post
async def getWELData(ip): tic = time.time() url = "http://" + ip + ":5150/data.xml" post = {} local_now = (dt.datetime.now() .replace(microsecond=0) .replace(tzinfo=TO_TZONE)) sunrise = sun.sunrise(LOC.observer, date=local_now.date(), tzinfo=TO_TZONE).astimezone(DB_TZONE) sunset = sun.sunset(LOC.observer, date=local_now.date(), tzinfo=TO_TZONE).astimezone(DB_TZONE) post['daylight'] = ((local_now > sunrise) and (local_now < sunset)) * 1 try: response = requests.get(url) except ConnectionError: message("Error in connecting to WEL, waiting 10 sec then trying again", mssgType='WARNING') time.sleep(10) try: response = requests.get(url) except ConnectionError: message("Second error in connecting to WEL, " "excluding WEL from post.", mssgType='ERROR') return post response_data = xmltodict.parse(response.content)['Devices']['Device'] for item in response_data: try: post[item['@Name']] = float(item['@Value']) except ValueError: post[item['@Name']] = item['@Value'] del post['Date'] del post['Time'] message([F"{'Getting WEL:': <20}", F"{time.time() - tic:.1f} s"], mssgType='TIMING') return post
def sunrise_sunset(date, lat, lon): """ Calculate sunrise and sunset times in utc for given date, lat and lon. Parameters ---------- date : datetime.date Date in yyyy-mm-dd. lat : float Latitude. lon : float Longitude. Returns ------- sunrise : datetime Sunrise time. sunset : datetime Sunset time. """ obs = Observer(latitude=lat, longitude=lon, elevation=0.0) sunrise = sun.sunrise(observer=obs, date=date) sunset = sun.sunset(observer=obs, date=date) return sunrise, sunset
def draw_astronomical(city_name, geo_data, config): datetime_day_start = datetime.datetime.now().replace(hour=0, minute=0, second=0, microsecond=0) city = LocationInfo() city.latitude = geo_data["latitude"] city.longitude = geo_data["longitude"] city.timezone = geo_data["timezone"] answer = "" moon_line = "" for time_interval in range(72): current_date = (datetime_day_start + datetime.timedelta(hours=1 * time_interval)).replace( tzinfo=pytz.timezone(geo_data["timezone"])) try: dawn = sun.dawn(city.observer, date=current_date) except ValueError: dawn = current_date try: dusk = sun.dusk(city.observer, date=current_date) except ValueError: dusk = current_date + datetime.timedelta(hours=24) try: sunrise = sun.sunrise(city.observer, date=current_date) except ValueError: sunrise = current_date try: sunset = sun.sunset(city.observer, date=current_date) except ValueError: sunset = current_date + datetime.timedelta(hours=24) char = "." if current_date < dawn: char = " " elif current_date > dusk: char = " " elif dawn <= current_date and current_date <= sunrise: char = u"─" elif sunset <= current_date and current_date <= dusk: char = u"─" elif sunrise <= current_date and current_date <= sunset: char = u"━" answer += char if config.get("view") in ["v2n", "v2d"]: moon_phases = constants.MOON_PHASES_WI moon_phases = [" %s" % x for x in moon_phases] else: moon_phases = constants.MOON_PHASES # moon if time_interval in [0, 23, 47, 69]: # time_interval % 3 == 0: moon_phase = moon.phase(date=datetime_day_start + datetime.timedelta(hours=time_interval)) moon_phase_emoji = moon_phases[int( math.floor(moon_phase * 1.0 / 28.0 * 8 + 0.5)) % len(moon_phases)] # if time_interval in [0, 24, 48, 69]: moon_line += moon_phase_emoji # + " " elif time_interval % 3 == 0: if time_interval not in [24, 28]: #se: moon_line += " " else: moon_line += " " answer = moon_line + "\n" + answer + "\n" answer += "\n" return answer
def test_Sunset_NoDate(london): ans = pytz.utc.localize(datetime.datetime(2015, 12, 1, 15, 55)) assert datetime_almost_equal(sun.sunset(london.observer), ans)
def test_Sunset(day, sunset, london): sunset = pytz.utc.localize(sunset) sunset_utc = sun.sunset(london.observer, day) assert datetime_almost_equal(sunset, sunset_utc)
def add_solar_variable(obj, latitude=None, longitude=None, solar_angle=0., dawn_dusk=False): """ Calculate solar times depending on location on earth. Astral 2.2 is recommended for best performance and for the dawn/dusk feature as it seems like the dawn calculations are wrong with earlier versions. Parameters ---------- obj : act object ACT object latitude : str Latitude variable, default will look for matching variables in object longitude : str Longitude variable, default will look for matching variables in object solar_angle : float Number of degress to use for dawn/dusk calculations dawn_dusk : boolean If set to True, will add values 2 (dawn) and 3 (dusk) to the solar variable Returns ------- obj : act object ACT object """ variables = list(obj.keys()) # Get coordinate variables if latitude is None: latitude = [s for s in variables if "latitude" in s] if len(latitude) == 0: latitude = [s for s in variables if "lat" in s] if len(latitude) == 0: raise ValueError( "Latitude variable not set and could not be discerned from the data" ) if longitude is None: longitude = [s for s in variables if "longitude" in s] if len(longitude) == 0: longitude = [s for s in variables if "lon" in s] if len(longitude) == 0: raise ValueError( "Longitude variable not set and could not be discerned from the data" ) # Get lat/lon variables lat = obj[latitude[0]].values lon = obj[longitude[0]].values # Set the the number of degrees the sun must be below the horizon # for the dawn/dusk calculation. Need to do this so when the calculation # sends an error it is not going to be an inacurate switch to setting # the full day. if ASTRAL: astral.solar_depression = solar_angle else: a = astral.Astral() a.solar_depression = 0. # If only one lat/lon value then set up the observer location # for Astral. If more than one, it will get set up in the loop if lat.size == 1 and ASTRAL: loc = Observer(latitude=lat, longitude=lon) # Loop through each time to ensure that the sunrise/set calcuations # are correct for each time and lat/lon if multiple results = [] time = obj['time'].values for i in range(len(time)): # Set up an observer if multiple lat/lon if lat.size > 1: if ASTRAL: loc = Observer(latitude=lat[i], longitude=lon[i]) else: s = a.sun_utc(pd.to_datetime(time[i]), lat[i], lon[i]) elif ASTRAL is False: s = a.sun_utc(pd.to_datetime(time[i]), float(lat), float(lon)) # Get sunrise and sunset if ASTRAL: sr = sunrise(loc, pd.to_datetime(time[i])) ss = sunset(loc, pd.to_datetime(time[i])) else: sr = s['sunrise'] ss = s['sunset'] # Set longname longname = 'Daylight indicator; 0-Night; 1-Sun' # Check to see if dawn/dusk calculations can be performed before preceeding if dawn_dusk: try: if ASTRAL: dwn = dawn(loc, pd.to_datetime(time[i])) dsk = dusk(loc, pd.to_datetime(time[i])) else: if lat.size > 1: dsk = a.dusk_utc(pd.to_datetime(time[i]), lat[i], lon[i]) dwn = a.dawn_utc(pd.to_datetime(time[i]), lat[i], lon[i]) else: dsk = a.dusk_utc(pd.to_datetime(time[i]), float(lat), float(lon)) dwn = a.dawn_utc(pd.to_datetime(time[i]), float(lat), float(lon)) except ValueError: print( 'Dawn/Dusk calculations are not available at this location' ) dawn_dusk = False if dawn_dusk and ASTRAL: # If dawn_dusk is True, add 2 more indicators longname += '; 2-Dawn; 3-Dusk' # Need to ensure if the sunset if off a day to grab the previous # days value to catch the early UTC times if ss.day > sr.day: if ASTRAL: ss = sunset( loc, pd.to_datetime(time[i] - np.timedelta64(1, 'D'))) dsk = dusk( loc, pd.to_datetime(time[i] - np.timedelta64(1, 'D'))) else: if lat.size > 1: dsk = a.dusk_utc( pd.to_datetime(time[i]) - np.timedelta64(1, 'D'), lat[i], lon[i]) s = a.sun_utc( pd.to_datetime(time[i]) - np.timedelta64(1, 'D'), lat[i], lon[i]) else: dsk = a.dusk_utc( pd.to_datetime(time[i]) - np.timedelta64(1, 'D'), float(lat), float(lon)) s = a.sun_utc( pd.to_datetime(time[i]) - np.timedelta64(1, 'D'), float(lat), float(lon)) ss = s['sunset'] if dwn <= pd.to_datetime(time[i], utc=True) < sr: results.append(2) elif ss <= pd.to_datetime(time[i], utc=True) < dsk: results.append(3) elif not (dsk <= pd.to_datetime(time[i], utc=True) < dwn): results.append(1) else: results.append(0) else: if dwn <= pd.to_datetime(time[i], utc=True) < sr: results.append(2) elif sr <= pd.to_datetime(time[i], utc=True) < ss: results.append(1) elif ss <= pd.to_datetime(time[i], utc=True) < dsk: results.append(3) else: results.append(0) else: if ss.day > sr.day: if ASTRAL: ss = sunset( loc, pd.to_datetime(time[i] - np.timedelta64(1, 'D'))) else: s = a.sun_utc( pd.to_datetime(time[i]) - np.timedelta64(1, 'D'), lat, lon) ss = s['sunset'] results.append( int(not (ss < pd.to_datetime(time[i], utc=True) < sr))) else: results.append( int(sr < pd.to_datetime(time[i], utc=True) < ss)) # Add results to object and return obj['sun_variable'] = ('time', np.array(results), { 'long_name': longname, 'units': ' ' }) return obj
def __init__(self, _location, _main_loop): self.location = _location self.main_loop = _main_loop self.id = f'urn:dev:ops:{self.location}-vorraum-led' self.name = f'{self.location}-LED_Strip' Thing.__init__(self, self.id, self.name, ['OnOffSwitch', 'Light'], 'A web connected LED-Strip') # GPIO18 (P26) pwm on Linkit Smart 7688 self.pwm = mraa.Pwm(26) self.pwm.period_us(20000) # 20ms period ==> 50Hz self.pwm.enable(True) # Start sending PWM signal # relay2 (P18) on Linkit Smart 7688 self.relay2 = mraa.Gpio(18) # relay1 (P19) on Linkit Smart 7688 self.relay1 = mraa.Gpio(19) self.relay2.dir(mraa.DIR_OUT) # set as OUTPUT pin # set as INPUT pin, its a pullup, so its High when the switch is open. self.relay1.dir(mraa.DIR_IN) self.relay1_read() # get initial Value of Relay1 self.r1_previous = False self.main_loop_time = None self.async_timeout = None self.locality = LocationInfo('Zürich', 'Switzerland', 'Europe/Zurich', 47.39, 8.07) logging.info( f'Information for {self.locality.name}/{self.locality.region}, ' f'Timezone: {self.locality.timezone}, ' f'Latitude: {self.locality.latitude:.02f}; ' f'Longitude: {self.locality.longitude:.02f}') self.day_time_start = sun.sunrise( self.locality.observer, date=datetime.now(), tzinfo=self.locality.timezone) - timedelta(minutes=30) logging.debug(f'LedStrip: day_time_start:{self.day_time_start}') self.day_time_stop = sun.sunset( self.locality.observer, date=datetime.now(), tzinfo=self.locality.timezone) + timedelta(minutes=30) logging.debug(f'LedStrip: day_time_stop:{self.day_time_stop}') self.state = Value(self.get_state(), self.toggle_digitalswitch) self.add_property( Property(self, 'digitalswitch', self.state, metadata={ '@type': 'OnOffProperty', 'title': f'{self.name}-digitalswitch', 'type': 'boolean', 'description': 'Whether the Strip is turned on', })) self.brightness = Value(self.get_brightness(), self.set_brightness) self.add_property( Property(self, 'brightness', self.brightness, metadata={ '@type': 'LevelProperty', 'title': 'Helligkeit', 'type': 'integer', 'description': 'The level of light from 0-100%', 'minimum': 0, 'maximum': 100, 'unit': 'percent', })) self.add_available_action( 'fade', { 'title': 'Helligkeitswert über eine Zeitdauer einstellen', 'description': 'Fade the lamp to a given level', 'input': { 'type': 'object', 'required': [ 'brightness', 'duration', ], 'properties': { 'brightness': { 'type': 'integer', 'minimum': 0, 'maximum': 100, 'unit': 'percent', }, 'duration': { 'type': 'integer', 'minimum': 1, 'unit': 'milliseconds', }, }, }, }, FadeLedStrip) self.motion_detection_delay = Value(self.get_motion_detection_delay(), self.set_motion_detection_delay) self.add_property( Property(self, 'motion_detection_delay', self.motion_detection_delay, metadata={ '@type': 'LevelProperty', 'title': 'Verzögertes Aus bei Bewegung (in Minuten)', 'type': 'integer', 'description': 'The delay in minutes', 'minimum': 0, 'maximum': 20, 'unit': 'minutes', })) self.motion_detection_active = Value( self.get_motion_detection_active(), self.set_motion_detection_active) self.add_property( Property(self, 'motion_detection_active', self.motion_detection_active, metadata={ '@type': 'BooleanProperty', 'title': 'Auf Bewegung reagieren?', 'type': 'boolean', 'description': 'Set Motion detection active or not', })) self.motion_detection_follower = Value(self.get_motion(), self.set_motion) self.add_property( Property(self, 'motion_detection_follower', self.motion_detection_follower, metadata={ '@type': 'MotionProperty', 'title': 'Bewegungs Sensor', 'type': 'boolean', 'description': 'motion=true, nomotion=false', })) self.timer = tornado.ioloop.PeriodicCallback(self.get_r1, 1000) self.timer.start()
# from https://stackoverflow.com/a/1060330 def daterange(start_date, end_date): for n in range(int((end_date - start_date).days)): yield start_date + timedelta(n) # could possibly also use dateutil module for loc_date in daterange(date_start, date_end): ### time vars time_dawn = dawn(loc.observer, loc_date, tzinfo=loc_tz) time_rise = sunrise(loc.observer, loc_date, tzinfo=loc_tz) time_set = sunset(loc.observer, loc_date, tzinfo=loc_tz) time_dusk = dusk(loc.observer, loc_date, tzinfo=loc_tz) ### description vars event_title_rise = '↑ {0}'.format(time_rise.strftime("%H:%M")) event_title_set = '↓ {0}'.format(time_set.strftime("%H:%M")) # could move coordinates to 'GEO' property, see https://www.kanzaki.com/docs/ical/geo.html event_location = vText('{0} / {1}, {2}'.format(loc_name, loc_lat, loc_long)) # timedelta doesn't allow strftime, find a way to format it better, see https://stackoverflow.com/questions/538666/format-timedelta-to-string event_desc_rise = 'Dawn at {0}, sunrise at {1}. Total sunlight time {2}'.format( time_dawn.strftime("%H:%M"), time_rise.strftime("%H:%M"), str(time_set - time_rise))
city = LocationInfo("London", "England", "Europe/London", 51.5, -0.116) print((f"Information for {city.name}/{city.region}\n" f"Timezone: {city.timezone}\n" f"Latitude: {city.latitude:.02f}; Longitude: {city.longitude:.02f}\n")) today = datetime.today() observer = city.observer timeformat = "%H:%M:%S" dawnAngle = 18.0 duskAngle = 18.0 dawn = datetime.fromtimestamp(dawn(observer, today, dawnAngle).timestamp()).strftime(timeformat) sunrise = datetime.fromtimestamp(sunrise( observer, today).timestamp()).strftime(timeformat) noon = datetime.fromtimestamp(noon(observer, today).timestamp()).strftime(timeformat) sunset = datetime.fromtimestamp(sunset(observer, today).timestamp()).strftime(timeformat) dusk = datetime.fromtimestamp(dusk(observer, today, duskAngle).timestamp()).strftime(timeformat) print((f"Dawn: {dawn}\n" f"Sunrise: {sunrise}\n" f"Noon: {noon}\n" f"Sunset: {sunset}\n" f"Dusk: {dusk}\n"))