def __init__(self, devices): self.__devices = devices self.__stir_state = False self.__current = Timer("stir") self.__period = timedelta(seconds=3600) self.__duration = timedelta(seconds=120) self.__city = geocoder.lookup(StirMode.LOCATION, geocoder.database())
def test_Wellington(): wellington = lookup("Wellington", database()) dt = datetime.date(2020, 2, 11) tz = pytz.timezone(wellington.timezone) s = sun(wellington.observer, dt, tzinfo=tz) assert datetime_almost_equal( s["sunrise"], tz.localize(datetime.datetime(2020, 2, 11, 6, 38, 42)))
def geolocate(address, try_all=True): try: # see https://astral.readthedocs.io/en/latest/#cities a = lookup(address, database()) return a.latitude, a.longitude except: pass # use online geocoder location_data = geocoder.geonames(address, method='details', key='jarbas') if not location_data.ok: location_data = geocoder.geocodefarm(address) if not location_data.ok: location_data = geocoder.osm(address) if try_all: # more are just making it slow if not location_data.ok: location_data = geocoder.google(address) if not location_data.ok: location_data = geocoder.arcgis(address) if not location_data.ok: location_data = geocoder.bing(address) if not location_data.ok: location_data = geocoder.canadapost(address) if not location_data.ok: location_data = geocoder.yandex(address) if not location_data.ok: location_data = geocoder.tgos(address) if location_data.ok: location_data = location_data.json lat = location_data.get("lat") lon = location_data.get("lng") return lat, lon raise ValueError
def __init__(self, city_name=default_city_name): if VERSION == 2: self._city = lookup("Amsterdam", database()) self._sun = self.sun(datetime.now()) else: self._a = Astral() self._a.solar_depression = 'civil' self._city = self._a[city_name] self._timezone = pytz.timezone(self._city.timezone)
def sun_moon_time(city_name, time_zone): """Calculate the progress through the current sun/moon period (i.e day or night) from the last sunrise or sunset, given a datetime object 't'.""" city = lookup(city_name, database()) # Datetime objects for yesterday, today, tomorrow utc = pytz.utc utc_dt = datetime.now(tz=utc) local_dt = utc_dt.astimezone(pytz.timezone(time_zone)) today = local_dt.date() yesterday = today - timedelta(1) tomorrow = today + timedelta(1) # DEBUG breakpoint TEST! # breakpoint() logger.info( ' The current date/time is %s in your local TimeZone/City of %s', local_dt, time_zone) # logger.debug(local_dt) # Sun objects for yesterday, today, tomorrow sun_yesterday = sun(city.observer, date=yesterday) sun_today = sun(city.observer, date=today) sun_tomorrow = sun(city.observer, date=tomorrow) # Work out sunset yesterday, sunrise/sunset today, and sunrise tomorrow sunset_yesterday = sun_yesterday["sunset"] sunrise_today = sun_today["sunrise"] sunset_today = sun_today["sunset"] sunrise_tomorrow = sun_tomorrow["sunrise"] # Work out lengths of day or night period and progress through period if sunrise_today < local_dt < sunset_today: day = True period = sunset_today - sunrise_today # mid = sunrise_today + (period / 2) progress = local_dt - sunrise_today elif local_dt > sunset_today: day = False period = sunrise_tomorrow - sunset_today # mid = sunset_today + (period / 2) progress = local_dt - sunset_today else: day = False period = sunrise_today - sunset_yesterday # mid = sunset_yesterday + (period / 2) progress = local_dt - sunset_yesterday # Convert time deltas to seconds progress = progress.total_seconds() period = period.total_seconds() return (progress, period, day, local_dt)
def length_day(series,lon,lat): db = database() lon = deg_to_dms(lon, 'lon') # 经度 lat = deg_to_dms(lat, 'lat') add_locations("Somewhere,Secret Location,UTC," + lat + ',' + lon, db) s = sun(lookup("Somewhere", db).observer, date=series['date']) print(series['date']) len_day = s['sunset']-s['sunrise'] return len_day.seconds/3600.0
def __init__(self, config_file_path=None): # catch SIGINT, SIGQUIT and SIGTERM self.__quit_signal = threading.Event() signal.signal(signal.SIGINT, self.__quit) signal.signal(signal.SIGQUIT, self.__quit) signal.signal(signal.SIGTERM, self.__quit) # catch SIGHUP and reload configuration signal.signal(signal.SIGHUP, self.__reload) # load config if config_file_path is None: self.__config_file_path = DEFAULT_CONFIG_FILE else: self.__config_file_path = config_file_path self.__load_settings() # this is the queue that holds the frames to display self.__frame_queue = queue.Queue(maxsize=1) # animation controller # gets initialized in mainloop method self.__animation_controller = AnimationController( self.config, self.frame_queue) # the animation scheduler self.__animation_scheduler = self.__create_scheduler() self.__schedule_lock = Lock() # the nighttime scheduler self.__location = lookup(tzlocal.get_localzone_name().split("/")[1], database()) self.__nighttime_scheduler = BackgroundScheduler() self.__sunrise_job = self.__nighttime_scheduler.add_job( func=self.apply_brightness) self.__sunset_job = self.__nighttime_scheduler.add_job( func=self.apply_brightness) self.__nighttime_scheduler.add_job(func=self.__calculate_nighttimes, trigger=CronTrigger(hour="0,12", minute=0, second=0)) self.__calculate_nighttimes() self.apply_brightness() self.__nighttime_scheduler.start() # create the display object self.__initialize_display() # server interfaces self.__http_server = None self.__rest_server = None self.__tpm2_net_server = None # this signal is set by the reload method self.__reload_signal = EventWithUnsetSignal()
def __init__(self, city=None): """ Initialize Sun class :param city: City name :type city: str """ from astral.geocoder import database, lookup if city is None: city = 'Brussels' if isinstance(city, str): city = lookup(city, database()) self._city = city
def make(self): self.info = sun(lookup(self.look_up, database()).observer, date=datetime.date(self.with_date.year, self.with_date.month, self.with_date.day)) if type(self.info) != dict: return for val in self.info: self.info[val] = { 'utc': self.info[val], 'local': self.info[val].astimezone(tz.gettz(self.time_zone)) } self.__create_wallpaper_time_slots() return self.info
def sun_moon_time(dt, city_name, time_zone): """Calculate the progress through the current sun/moon period (i.e day or night) from the last sunrise or sunset, given a datetime object 't'.""" city = lookup(city_name, database()) # Datetime objects for yesterday, today, tomorrow today = dt.date() dt = pytz.timezone(time_zone).localize(dt) yesterday = today - timedelta(1) tomorrow = today + timedelta(1) # Sun objects for yesterfay, today, tomorrow sun_yesterday = sun(city.observer, date=yesterday) sun_today = sun(city.observer, date=today) sun_tomorrow = sun(city.observer, date=tomorrow) # Work out sunset yesterday, sunrise/sunset today, and sunrise tomorrow sunset_yesterday = sun_yesterday["sunset"] sunrise_today = sun_today["sunrise"] sunset_today = sun_today["sunset"] sunrise_tomorrow = sun_tomorrow["sunrise"] # Work out lengths of day or night period and progress through period if sunrise_today < dt < sunset_today: day = True period = sunset_today - sunrise_today mid = sunrise_today + (period / 2) progress = dt - sunrise_today elif dt > sunset_today: day = False period = sunrise_tomorrow - sunset_today mid = sunset_today + (period / 2) progress = dt - sunset_today else: day = False period = sunrise_today - sunset_yesterday mid = sunset_yesterday + (period / 2) progress = dt - sunset_yesterday # Convert time deltas to seconds progress = progress.total_seconds() period = period.total_seconds() return (progress, period, day)
def get_max_theoretical_sun_hours(city, max_real_sun_hours): city_data = lookup(city, database()) start = f"{YEAR_MAX_SUN_HOURS}-01-01" end = f"{YEAR_MAX_SUN_HOURS}-12-31" dates = pd.date_range(start=start, end=end) daylight_hours = get_daylight_hours(city_data.observer, dates) grouped_daylight_hours = daylight_hours.groupby( [daylight_hours.index.month, daylight_hours.index.day]).max() grouped_daylight_hours = pd.Series(grouped_daylight_hours['daylight_h']) _max_real_sun_hours = pd.Series(max_real_sun_hours) delta_sun_and_daylight = grouped_daylight_hours - _max_real_sun_hours min_delta = delta_sun_and_daylight.nsmallest(10).mean() daylight_hours['sunhours'] = daylight_hours['daylight_h'] - min_delta return daylight_hours
def send(): if request.method=='POST': data=request.json startdate=datetime.strptime(data['date'],'%Y-%m-%d') enddate=datetime.strptime(data['date1'],'%Y-%m-%d') cityinfo=data['city'] city=lookup(cityinfo, database()) day = timedelta(days=1) table2=[] while startdate <= enddate: suns=sun(city.observer, date=startdate, tzinfo=pytz.timezone(city.timezone)) dawn=suns['dawn'].strftime("%H:%M:%S") sunrise=suns['sunrise'].strftime("%H:%M:%S") sunset=suns['sunset'].strftime("%H:%M:%S") dusk=suns['dusk'].strftime("%H:%M:%S") noon=suns['noon'].strftime("%H:%M:%S") table2.append({'date':startdate.strftime('%Y-%m-%d'),'dawn':dawn,'sunrise':sunrise,'sunset':sunset,'dusk':dusk,'noon':noon}) startdate=startdate+day table1={'city':city.name,'region':city.region,'timezone':city.timezone,'long':round(city.longitude,2),'lat':round(city.latitude,2)} return json.dumps({'table1':table1,'table2':table2})
def __init__(self): try: config = self._load_config() except Exception as ex: print(f'Using default config: {ex}') config = self.default_config self.config = config if isinstance(config['location'], str): location = lookup(config['location'], database()) position = {"lat": location.latitude, "lon": location.longitude} else: position = config['location'] self.position = position # Date and time formats self.time_format = self.time_formats[config['time']]\ if config['time'] in self.time_formats else self.time_formats['24h'] self.time_format_tz = self.time_format + ' %Z' self.date_format = '%b %d, %Y'
def geolocate(self, address, try_all=True): if address in self.geocache: return self.geocache[address] try: # should be installed from default skills from astral.geocoder import database, lookup # see https://astral.readthedocs.io/en/latest/#cities a = lookup(address, database()) self.geocache[address] = (a.latitude, a.longitude) return a.latitude, a.longitude except: pass # use online geocoder location_data = geocoder.osm(address) if not location_data.ok: location_data = geocoder.geocodefarm(address) if try_all: # more are just making it slow if not location_data.ok: location_data = geocoder.google(address) if not location_data.ok: location_data = geocoder.arcgis(address) if not location_data.ok: location_data = geocoder.bing(address) if not location_data.ok: location_data = geocoder.canadapost(address) if not location_data.ok: location_data = geocoder.yandex(address) if not location_data.ok: location_data = geocoder.tgos(address) if location_data.ok: location_data = location_data.json lat = location_data.get("lat") lon = location_data.get("lng") self.geocache[address] = (lat, lon) return lat, lon raise ValueError
def main(): # Create api credentials credentials = None if os.path.exists('credentials.dat'): with open('credentials.dat', 'rb') as credentials_dat: credentials = pickle.load(credentials_dat) if not credentials: flow = Flow.from_client_secrets_file( 'client_id.json', scopes=['https://www.googleapis.com/auth/calendar.readonly'], redirect_uri=REDIRECT_URI) code = request.args.get('code') if not code: auth_url, _ = flow.authorization_url(prompt='consent') return redirect(auth_url) flow.fetch_token(code=code) credentials = flow.credentials with open('credentials.dat', 'wb') as credentials_dat: pickle.dump(credentials, credentials_dat) if credentials and credentials.expired: credentials.refresh(Request()) bigfont = ImageFont.truetype("fonts/Roboto.ttf", 26, encoding="unic") font = ImageFont.truetype("fonts/Roboto.ttf", 20, encoding="unic") smallfont = ImageFont.truetype("fonts/Roboto.ttf", 18, encoding="unic") smallerfont = ImageFont.truetype("fonts/Roboto.ttf", 12, encoding="unic") boldfont = ImageFont.truetype("fonts/RobotoBold.ttf", 18, encoding="unic") # Get forecast r = requests.get( 'http://datapoint.metoffice.gov.uk/public/data/val/wxfcs/all/json/{}?res=3hourly&key={}' .format(MO_LOCATION_ID, MO_API_KEY)) data = r.json() # Convert forecast to something readable hourly_predictions = [] for day in data["SiteRep"]['DV']['Location']['Period']: date = day['value'][:-1] predictions = day['Rep'] for prediction in predictions: prediction['date'] = date prediction['time'] = str(int(int(prediction['$']) / 60)) + ':00' prediction['datetime'] = date + ' ' + str( int(int(prediction['$']) / 60)) + ':00' hourly_predictions.append(prediction) hourly_updated_at = arrow.get(data["SiteRep"]['DV']['dataDate']) r = requests.get( 'http://datapoint.metoffice.gov.uk/public/data/val/wxfcs/all/json/{}?res=daily&key={}' .format(MO_LOCATION_ID, MO_API_KEY)) data = r.json() # Convert forecast to something readable daily_predictions = [] for day in data["SiteRep"]['DV']['Location']['Period']: date = day['value'][:-1] daypred = day['Rep'][0] nightpred = day['Rep'][1] daily_predictions.append({ "date": date, "Dm": daypred['Dm'], "Nm": nightpred['Nm'], "PPd": daypred['PPd'], "PPn": nightpred['PPn'], "W": daypred['W'], "Dd": daypred['D'], "Dn": nightpred['D'], "Gn": daypred['Gn'], "Gm": nightpred['Gm'] }) daily_updated_at = arrow.get(data["SiteRep"]['DV']['dataDate']) # Get todays sunrise and sunset now = arrow.now(TIMEZONE) location = lookup(ASTRAL_LOCATION, database()) sun = sunny(location.observer, date=now) sunrise = sun['sunrise'] sunset = sun['sunset'] day_len = sunset - sunrise # Get yesterdays sunrise and sunset d_yest = now.shift(days=-1) sun_yest = sunny(location.observer, date=d_yest) sunrise_yest = arrow.get(sun_yest['sunrise']) sunset_yest = arrow.get(sun_yest['sunset']) day_len_yest = sunset_yest - sunrise_yest day_len_diff = time_diff(day_len, day_len_yest) sunrise_diff = time_diff(sunrise, sunrise_yest.shift(days=1)) sunset_diff = time_diff(sunset, sunset_yest.shift(days=1)) # Get upcoming calendar events calendar_sdk = build('calendar', 'v3', credentials=credentials) calendar_list = calendar_sdk.calendarList().list().execute() calendar_ids = [ calendar_list_entry['id'] for calendar_list_entry in calendar_list['items'] ] today = arrow.now(TIMEZONE) today_morning = today.strftime('%Y-%m-%dT00:00:00Z') tomorrow = today.shift(days=1) events = [] for calendar_id in calendar_ids: events_page = calendar_sdk.events().list( calendarId=calendar_id, timeMin=today_morning, maxResults=10, singleEvents=True, orderBy="startTime", ).execute() events += events_page['items'] def get_key(event): if 'dateTime' in event['start']: return arrow.get(event['start']['dateTime']) else: return arrow.get(event['start']['date']) events.sort(key=get_key) def calendar(draw, start_x, start_y, end_y): x = start_x y = start_y item_spacing = 25 extra_day_spacing = 5 current_date = None for event in events: if y >= end_y: break summary = event['summary'] if 'organizer' in event and 'displayName' in event['organizer']: calendar = event['organizer']['displayName'] if 'dateTime' in event['start']: start_time = arrow.get(event['start']['dateTime']) end_time = arrow.get(event['end']['dateTime']) diff = abs(start_time - end_time) time_text = start_time.strftime('%H:%M') + ' ' + str( diff.seconds // 3600) + ' hours' else: start_time = arrow.get(event['start']['date']) time_text = 'All day' if current_date != start_time.strftime('%Y/%m/%d'): if y + item_spacing + extra_day_spacing >= 750: break y += extra_day_spacing if start_time.strftime('%Y/%m/%d') == today.strftime( '%Y/%m/%d'): text = 'Today' elif start_time.strftime('%Y/%m/%d') == tomorrow.strftime( '%Y/%m/%d'): text = 'Tomorrow' else: text = start_time.humanize().capitalize( ) + ' on ' + start_time.format( 'dddd {} Do {} MMMM').format('the', 'of') draw.text((x, y), text, (0, 0, 0), boldfont) current_date = start_time.strftime('%Y/%m/%d') y += item_spacing text = time_text draw.text((x, y), text, (0, 0, 0), smallfont) text = summary if len(text) > 60: text = text[:57] + '...' draw.text((x + 125, y), text, (0, 0, 0), smallfont) y += item_spacing def landscape(): # Make blank image image_pixels = [(255, 255, 255) for i in range(800 * 600)] image = Image.new("RGBA", (800, 600)) image.putdata(image_pixels) draw = ImageDraw.Draw(image) # Big date title text = now.format('dddd {} Do {} MMMM YYYY').format('the', 'of') w, h = bigfont.getsize(text) center_offset = (800 - w) / 2 draw.text((center_offset, 5), text, (0, 0, 0), bigfont) # Render sunrise icon and todays sunrise time icon = Image.open('icons/sunrise.png') image.paste(icon, box=(10, 20), mask=icon) text = sunrise.strftime('%H:%M') w, h = bigfont.getsize(text) center_offset = (100 - w) / 2 draw.text((10 + center_offset, 110), text, (0, 0, 0), bigfont) # Render sunrise diff text = '(' + sunrise_diff + ')' w, h = smallfont.getsize(text) center_offset = (100 - w) / 2 draw.text((10 + center_offset, 145), text, (0, 0, 0), smallfont) start_offset = 112 start_height = 20 column_width = 100 spacing = 8 for index, prediction in enumerate(hourly_predictions[1:6]): left_offset = (spacing * (index + 1)) + ( index * (column_width + spacing)) + start_offset # Draw weather icon icon = Image.open('icons/' + prediction["W"] + '.png') image.paste(icon, box=(left_offset, start_height), mask=icon) # Write datetime text = prediction["time"] w, h = bigfont.getsize(text) center_offset = (100 - w) / 2 draw.text((left_offset + center_offset, start_height + 90), text, (0, 0, 0), bigfont) # Write temperature icon = Image.open('icons/small/thermometer.png') image.paste(icon, box=(left_offset, start_height + 120), mask=icon) text = prediction["F"] + '°C' w, h = font.getsize(text) center_offset = (100 - w) / 2 draw.text((left_offset + center_offset, start_height + 120), text, (0, 0, 0), font) # Write rain chance icon = Image.open('icons/small/rain.png') image.paste(icon, box=(left_offset, start_height + 145), mask=icon) text = prediction["Pp"] + '%' w, h = font.getsize(text) center_offset = (100 - w) / 2 draw.text((left_offset + center_offset, start_height + 145), text, (0, 0, 0), font) # Write wind icon = Image.open('icons/small/deg-' + prediction['D'] + '.png') image.paste(icon, box=(left_offset, start_height + 175), mask=icon) text = str(int(1.609344 * float(prediction["S"]))) + "kph" w, h = smallfont.getsize(text) center_offset = (100 - w) / 2 draw.text((left_offset + center_offset, start_height + 175), text, (0, 0, 0), smallfont) # Render sunset icon and todays sunset time icon = Image.open('icons/sunset.png') image.paste(icon, box=(680, 20), mask=icon) text = sunset.strftime('%H:%M') w, h = bigfont.getsize(text) center_offset = (100 - w) / 2 draw.text((680 + center_offset, 110), text, (0, 0, 0), bigfont) # Render sunset diff text = '(' + sunset_diff + ')' w, h = smallfont.getsize(text) center_offset = (100 - w) / 2 draw.text((680 + center_offset, 145), text, (0, 0, 0), smallfont) # Hourly updated text = 'Updated ' + hourly_updated_at.format('ddd h a') draw.text((5, 215), text, (0, 0, 0), smallerfont) # Horizontal Line draw.line((0, 230, 800, 230), fill=255) # 4 day forecast start_height = 230 spacing = 10 row_height = 70 for index, prediction in enumerate(daily_predictions[1:6]): top_offset = (spacing * (index + 1)) + ( index * (row_height + spacing)) + start_height # Write datetime text = arrow.get( prediction["date"]).format('dddd {} Do {} MMMM YYYY').format( 'the', 'of') draw.text((5, top_offset), text, (0, 0, 0), smallfont) # Draw weather icon icon = Image.open('icons/med/' + prediction["W"] + '.png') image.paste(icon, box=(0, top_offset + 25), mask=icon) # Write day draw.text((70, top_offset + 25), "Day", (0, 0, 0), smallfont) # Write night draw.text((70, top_offset + 50), "Night", (0, 0, 0), smallfont) # Write max temperature icon = Image.open('icons/small/thermometer.png') image.paste(icon, box=(120, top_offset + 25), mask=icon) text = prediction["Dm"] + '°C' draw.text((150, top_offset + 25), text, (0, 0, 0), smallfont) # Write min temperature icon = Image.open('icons/small/thermometer.png') image.paste(icon, box=(120, top_offset + 50), mask=icon) text = prediction["Nm"] + '°C' draw.text((150, top_offset + 50), text, (0, 0, 0), smallfont) # Write day rain chance icon = Image.open('icons/small/rain.png') image.paste(icon, box=(200, top_offset + 25), mask=icon) text = prediction["PPd"] + '%' draw.text((230, top_offset + 25), text, (0, 0, 0), smallfont) # Write night rain chance icon = Image.open('icons/small/rain.png') image.paste(icon, box=(200, top_offset + 50), mask=icon) text = prediction["PPn"] + '%' draw.text((230, top_offset + 50), text, (0, 0, 0), smallfont) # Write day wind icon = Image.open('icons/small/deg-' + prediction['Dd'] + '.png') image.paste(icon, box=(280, top_offset + 25), mask=icon) text = str(int(1.609344 * float(prediction["Gn"]))) + "kph" draw.text((310, top_offset + 25), text, (0, 0, 0), smallfont) # Write night wind icon = Image.open('icons/small/deg-' + prediction['Dn'] + '.png') image.paste(icon, box=(280, top_offset + 50), mask=icon) text = str(int(1.609344 * float(prediction["Gm"]))) + "kph" draw.text((310, top_offset + 50), text, (0, 0, 0), smallfont) # Vertical Line draw.line((400, 230, 400, 600), fill=255) # Calendar calendar(draw, 420, 235, 550) # Daily updated text = 'Updated ' + daily_updated_at.format('ddd h a') draw.text((5, 585), text, (0, 0, 0), smallerfont) # Calendar and General checked at text = 'Updated ' + now.format('ddd h a') draw.text((420, 585), text, (0, 0, 0), smallerfont) image = image.rotate(-90, expand=True) image.save(IMAGE_NAME, "PNG") def portrait(): # Make blank image image_pixels = [(255, 255, 255) for i in range(600 * 800)] image = Image.new("RGBA", (600, 800)) image.putdata(image_pixels) draw = ImageDraw.Draw(image) for index, prediction in enumerate(hourly_predictions[1:6]): left_offset = (10 * (index + 1)) + (index * 110) # Draw weather icon icon = Image.open('icons/' + prediction["W"] + '.png') image.paste(icon, box=(left_offset, 0), mask=icon) # Write datetime text = prediction["time"] w, h = bigfont.getsize(text) center_offset = (100 - w) / 2 draw.text((left_offset + center_offset, 90), text, (0, 0, 0), bigfont) # Write temperature icon = Image.open('icons/small/thermometer.png') image.paste(icon, box=(left_offset, 120), mask=icon) text = prediction["F"] + '°C' w, h = font.getsize(text) center_offset = (100 - w) / 2 draw.text((left_offset + center_offset, 120), text, (0, 0, 0), font) # Write rain chance icon = Image.open('icons/small/rain.png') image.paste(icon, box=(left_offset, 145), mask=icon) text = prediction["Pp"] + '%' w, h = font.getsize(text) center_offset = (100 - w) / 2 draw.text((left_offset + center_offset, 145), text, (0, 0, 0), font) # Write wind icon = Image.open('icons/small/deg-' + prediction['D'] + '.png') image.paste(icon, box=(left_offset, 175), mask=icon) text = str(int(1.609344 * float(prediction["S"]))) + "kph" w, h = smallfont.getsize(text) center_offset = (100 - w) / 2 draw.text((left_offset + center_offset, 175), text, (0, 0, 0), smallfont) # Render sunrise icon and todays sunrise time icon = Image.open('icons/sunrise.png') image.paste(icon, box=(130, 200), mask=icon) text = sunrise.strftime('%H:%M') w, h = bigfont.getsize(text) center_offset = (100 - w) / 2 draw.text((130 + center_offset, 290), text, (0, 0, 0), bigfont) # Render sun icon, day length and day length diff from yesterday icon = Image.open('icons/1.png') image.paste(icon, box=(250, 200), mask=icon) text = ':'.join(str(day_len).split(':')[:2]) w, h = bigfont.getsize(text) center_offset = (100 - w) / 2 draw.text((250 + center_offset, 290), text, (0, 0, 0), bigfont) text = '(' + day_len_diff + ')' w, h = smallfont.getsize(text) center_offset = (100 - w) / 2 draw.text((250 + center_offset, 320), text, (0, 0, 0), smallfont) # Render sunset icon and todays sunset time icon = Image.open('icons/sunset.png') image.paste(icon, box=(370, 200), mask=icon) text = sunset.strftime('%H:%M') w, h = bigfont.getsize(text) center_offset = (100 - w) / 2 draw.text((370 + center_offset, 290), text, (0, 0, 0), bigfont) # Write checked time and updated time text = 'Checked at ' + now.format( 'ddd h a') + ' and last updated at ' + hourly_updated_at.format( 'ddd h a') draw.text((10, 775), text, (0, 0, 0), smallfont) draw.line((0, 345, 600, 345), fill=255) text = now.format('dddd {} Do {} MMMM YYYY').format('the', 'of') w, h = bigfont.getsize(text) center_offset = (600 - w) / 2 draw.text((center_offset, 350), text, (0, 0, 0), bigfont) calendar(draw, 10, 380, 750) image.save(IMAGE_NAME, "PNG") landscape() if request.args.get('landscape') is not None else portrait() return send_file(IMAGE_NAME, as_attachment=False)
def getSun(city_name): city = lookup(city_name, database()) return sun(city.observer, date=datetime.date.today())
def run(): defaults = { 'log': "info" } # Parse any config file specification. We make this parser with add_help=False so # that it doesn't parse -h and print help. conf_parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, add_help=False ) conf_parser.add_argument("--config", help="Specify config file", metavar='FILE') args, remaining_argv = conf_parser.parse_known_args() # Read configuration file and add it to the defaults hash. if args.config: config = ConfigParser() config.read(args.config) if "Defaults" in config: defaults.update(dict(config.items("Defaults"))) else: sys.exit("Bad config file, missing Defaults section") # Parse rest of arguments parser = argparse.ArgumentParser( description=__doc__, parents=[conf_parser], ) parser.set_defaults(**defaults) parser.add_argument("--gw-station-id", help="GoodWe station ID", metavar='ID') parser.add_argument("--gw-account", help="GoodWe account", metavar='ACCOUNT') parser.add_argument("--gw-password", help="GoodWe password", metavar='PASSWORD') parser.add_argument("--pvo-system-id", help="PVOutput system ID", metavar='ID') parser.add_argument("--pvo-api-key", help="PVOutput API key", metavar='KEY') parser.add_argument("--pvo-interval", help="PVOutput interval in minutes", type=int, choices=[5, 10, 15]) parser.add_argument("--darksky-api-key", help="Dark Sky Weather API key") parser.add_argument("--openweather-api-key", help="Open Weather API key") parser.add_argument("--netatmo-username", help="Netatmo username") parser.add_argument("--netatmo-password", help="Netatmo password") parser.add_argument("--netatmo-client-id", help="Netatmo OAuth client id") parser.add_argument("--netatmo-client-secret", help="Netatmo OAuth client secret") parser.add_argument("--netatmo-device-id", help="Netatmo device id") parser.add_argument("--log", help="Set log level (default info)", choices=['debug', 'info', 'warning', 'critical']) parser.add_argument("--date", help="Copy all readings (max 14/90 days ago)", metavar='YYYY-MM-DD') parser.add_argument("--pv-voltage", help="Send pv voltage instead of grid voltage", action='store_true') parser.add_argument("--skip-offline", help="Skip uploads when inverter is offline", action='store_true') parser.add_argument("--city", help="Sets timezone and skip uploads from dusk till dawn") parser.add_argument('--csv', help="Append readings to a Excel compatible CSV file, DATE in the name will be replaced by the current date") parser.add_argument('--version', action='version', version='%(prog)s ' + __version__) args = parser.parse_args() # Configure the logging numeric_level = getattr(logging, args.log.upper(), None) if not isinstance(numeric_level, int): raise ValueError('Invalid log level: %s' % loglevel) logging.basicConfig(format='%(levelname)-8s %(message)s', level=numeric_level) logging.debug("gw2pvo version " + __version__) if isinstance(args.skip_offline, str): args.skip_offline = args.skip_offline.lower() in ['true', 'yes', 'on', '1'] if args.gw_station_id is None or args.gw_account is None or args.gw_password is None: sys.exit("Missing --gw-station-id, --gw-account and/or --gw-password") if args.city: city = Location(lookup(args.city, database())) os.environ['TZ'] = city.timezone time.tzset() else: city = None logging.debug("Timezone {}".format(datetime.now().astimezone().tzinfo)) # Check if we want to copy old data if args.date: try: copy(args) except KeyboardInterrupt: sys.exit(1) except Exception as exp: logging.error(exp) sys.exit() startTime = datetime.now() while True: try: run_once(args, city) except KeyboardInterrupt: sys.exit(1) except Exception as exp: logging.error(exp) if args.pvo_interval is None: break interval = args.pvo_interval * 60 time.sleep(interval - (datetime.now() - startTime).seconds % interval)
from datetime import datetime from astral.geocoder import database, lookup from astral.sun import sun from dateutil import tz loc = lookup("Ljubljana", database()) print('Lokacija: %s/%s' % (loc.name, loc.region)) print('Časovni pas: %s' % loc.timezone) print('Zemljepisna širina: %.02f, Zemljepisna dolžina: %.02f\n' % (loc.latitude, loc.longitude)) date_now = datetime.now() s = sun(loc.observer, date=date_now) print("Datum: " + date_now.strftime("%d.%m.%Y")) print('Zora: %s' % s['dawn'].astimezone(tz.tzlocal()).strftime("%H:%M:%S")) print('Sončni vzhod: %s' % s['sunrise'].astimezone(tz.tzlocal()).strftime("%H:%M:%S")) print('Sončni zahod: %s' % s['sunset'].astimezone(tz.tzlocal()).strftime("%H:%M:%S")) print('Mrak: %s' % s['dusk'].astimezone(tz.tzlocal()).strftime("%H:%M:%S"))
try: print("Give times in Universal Time.") print("EDT is 4 hours behind UTC. EST is 5 hours behind.") print("Use 24 hour time with 00:00 being midnight.") time = str(input("specify UTC time in HH:MM format: ")) except: print("Please enter correct UTC time in HH:MM format") sys.exit() if ":" not in time: print("") print("You need to include the ':' when writing the time.") print("Restart the program and try again.") sys.exit() try: city = input("Please enter your nearest major city: ") thing = lookup(city, database()) except KeyError: print("The city is not in the database. Try the nearest capital.") sys.exit() lat = thing.latitude long = thing.longitude time = time.replace(":", ".") time = float(time) #This formula only works from March 1900-Feb 2100 d = 367 * year - (7 * (year + ( (month + 9) / 12))) // 4 + (275 * month) // 9 + day - 730530 d = d + (time / 24.0)
def main(): time_now = datetime.datetime.now() timezone_delta = datetime.timedelta(hours=-13) honolulu_utc_delta = datetime.timedelta(hours=-10) one_day_delta = datetime.timedelta(days=1) # Time now on Haleakala, Hawaii haleakala_time = time_now + timezone_delta haleakala_midnight_time = haleakala_time - datetime.timedelta( hours=haleakala_time.hour, minutes=haleakala_time.minute, seconds=haleakala_time.second, microseconds=haleakala_time.microsecond) fig, ax = plt.subplots(1, 1, figsize=(15, 5)) numb_of_days = 14 midnights = np.arange(0, numb_of_days + 1, 1) ax.set_xlim(0, numb_of_days) ax.set_ylim(0, 1) ax.set_yticks([]) ax.set_xticks(midnights) date_labels = [ (haleakala_midnight_time + i * one_day_delta).strftime('%d.%m') for i in range(numb_of_days + 1) ] ax.set_xticklabels(date_labels) plot_objects(ax, haleakala_midnight_time, numb_of_days) city = lookup("Honolulu", database()) time_positions, time_labels = [], [] for day_number in range(numb_of_days + 1): s = sun(city.observer, date=haleakala_midnight_time + day_number * one_day_delta, tzinfo=city.timezone) time_dawn = s['dawn'] time_sunset = s['sunset'] dawn_hour = int(time_dawn.strftime('%H')) dawn_minute = int(time_dawn.strftime('%M')) dawn_position = (dawn_hour * 60 + dawn_minute) / 1440 time_positions.append(dawn_position + day_number) time_labels.append(time_dawn.strftime('%H:%M')) sunset_hour = int(time_sunset.strftime('%H')) sunset_minute = int(time_sunset.strftime('%M')) sunset_position = (sunset_hour * 60 + sunset_minute) / 1440 time_positions.append(sunset_position + day_number) time_labels.append(time_sunset.strftime('%H:%M')) ax.axvspan(day_number + dawn_position, day_number + sunset_position, alpha=.5, hatch='//', edgecolor='k') ax.vlines(day_number + dawn_position, ymin=0, ymax=1, color='k', linewidth=.5, linestyle='dashed') ax.vlines(day_number + sunset_position, ymin=0, ymax=1, color='k', linewidth=.5, linestyle='dashed') ax2 = ax.twiny() ax2.set_xlim(0, numb_of_days) ax2.set_xticks(time_positions[:-2]) ax2.set_xticklabels(time_labels[:-2]) ax2.xaxis.set_ticks_position('bottom') ax.vlines(midnights, ymin=0, ymax=1, color='k', linewidth=.5, linestyle='dotted') ax.xaxis.set_ticks_position('top') plt.tight_layout() plt.savefig('ephemeris.pdf') plt.show()
def __init__(self): self.sanDiego = lookup("San Diego", database()) self.tz_sd = pytz.timezone(str(self.sanDiego.tzinfo))
def test_BuenosAries(test_database): b = lookup("Buenos Aires", test_database) assert b.timezone == "America/Buenos_Aires"
class Config: # Motion Detection (MD) config MD_DAY_PIXEL_CHANGE_THRESHOLD = 50 MD_NIGHT_PIXEL_CHANGE_THRESHOLD = 15 MD_IMAGE_CHANGE_THRESHOLD = 0.02 MD_RESIZE_WIDTH = 240 MD_RESOLUTION = (640, 480) MD_MIN_DURATION_S = 5 MD_MAX_DURATION_S = 60 MD_STILL_FPS = 2 MD_MOTION_FPS = 10 MD_STORAGE_PATH = "data/video" MD_STORAGE_MAX_AGE = 30 * 24 * 3600 MD_DAY_BRIGHTNESS = 50 MD_NIGHT_BRIGHTNESS = 65 MD_LOCATION_INFO = lookup("Melbourne", database()) # Thermal Camera (TC) config TC_ENABLED = True TC_ADDR = 0x69 TC_MIN_TEMP_C = 0 TC_MAX_TEMP_C = 50 TC_CHANGE_TEMP_PIXEL_THRESHOLD = 2 TC_CHANGE_TEMP_IMAGE_THRESHOLD_PIXELS = 4 TC_STORAGE_PATH = "data/video/ir" TC_RESOLUTION = (8, 8) TC_MIN_DURATION_S = 3 TC_MAX_DURATION_S = 15 TC_STILL_FPS = 2 TC_MOTION_FPS = 10 # Auto Updater (AD) config AD_INTERVAL_S = 5 * 60 # Temp monitor (TM) config TM_MEASURE_INTERVAL_S = 15 TM_THRESHOLDS_C = { TempRange.HOT: 60, TempRange.VERY_HOT: 70, TempRange.DANGEROUS: 80 } # Fan Controller (FC) config FC_GPIO_PIN = 21 FC_FAN_MIN_TEMP = 50 FC_PWM_MIN_VAL = 0.3 FC_FAN_MAX_TEMP = 65 FC_PWM_MAX_VAL = 1.0 FC_PWM_FREQ_HZ = 25 FC_UPDATE_INTERVAL_S = 15 # Video Classification (VC) config VC_INPUT_SHAPE = (15, 96, 96, 3) # dims: frames, w, h, channels VC_PREPROCESS_CACHE_PATH = './data/cache/' VC_PET_CLASSES = { 'MIA': 1, 'LUNA': 2, 'OTHER': 3, } VC_EVENT_CLASSES = { 'SIGHTING': 1, 'WENT_INSIDE': 2, 'WENT_OUTSIDE': 3, 'HUNT': 4, 'FIGHT': 5, 'TOILET': 6, 'OTHER': 7, } # API API_BIND_ADDR = os.getenv("API_BIND_ADDR") API_TLS_CERT_PATH = os.getenv("API_TLS_CERT_PATH") API_TLS_KEY_PATH = os.getenv("API_TLS_KEY_PATH") API_BASIC_USER = os.getenv("API_BASIC_USER") API_BASIC_PASS = os.getenv("API_BASIC_PASS") # Video Processor (VP) VP_TFLITE_MODEL_PATH = "./data/model/model.tflite" VP_FRAMES_DIR = './data/frames/' VP_PUBLIC_DIR = './data/public/' VP_FFMPEG_THREADS = 1 # Database DB_SQLITE_PATH = "./data/db.sqlite" def __init__(self): self.logger = logging.getLogger('smartpetdoor') self.init_paths() def init_paths(self): os.makedirs(self.MD_STORAGE_PATH, exist_ok=True)
from datetime import datetime from astral.geocoder import database, lookup from astral.sun import sun from dateutil import tz loc = lookup("London", database()) print('Location: %s/%s' % (loc.name, loc.region)) print('Timezone: %s' % loc.timezone) print('Latitude: %.02f; Longitute: %.02f\n' % (loc.latitude, loc.longitude)) date_now = datetime.now() s = sun(loc.observer, date=date_now) print("Date: " + date_now.strftime("%d.%m.%Y")) print('Dawn: %s' % s['dawn'].astimezone(tz.tzlocal()).strftime("%H:%M:%S")) print('Sunrise: %s' % s['sunrise'].astimezone(tz.tzlocal()).strftime("%H:%M:%S")) print('Sunset: %s' % s['sunset'].astimezone(tz.tzlocal()).strftime("%H:%M:%S")) print('Dusk: %s' % s['dusk'].astimezone(tz.tzlocal()).strftime("%H:%M:%S"))
def run(self): global stats temp_upd = None if plugin_options['use_footer']: temp_upd = showInFooter() # instantiate class to enable data in footer temp_upd.button = "sunrise_and_sunset/status" # button redirect on footer temp_upd.label = _('Sunrise and Sunset') # label on footer msg = _('Waiting to state') temp_upd.val = msg.encode('utf8').decode('utf8') # value on footer try: from astral.geocoder import database except ImportError: log.clear(NAME) log.info(NAME, _('Astral is not installed.')) log.info(NAME, _('Please wait installing astral...')) cmd = "pip3 install astral" run_command(cmd) log.info(NAME, _('Astral is now installed.')) while not self._stop_event.is_set(): try: if plugin_options['use_astro']: log.clear(NAME) city = None found_name = '' found_region = '' found_timezone ='' found_latitude = 0 found_longitude = 0 try: if plugin_options['location'] != 0: # 0 is none location from astral.geocoder import database, lookup find_loc = city_table[plugin_options['location']] city = lookup(find_loc, database()) # return example: LocationInfo(name='Addis Ababa', region='Ethiopia', timezone='Africa/Addis_Ababa', latitude=9.033333333333333, longitude=38.7) found_name = city.name found_region = city.region found_timezone = city.timezone found_latitude = city.latitude found_longitude = city.longitude else: if plugin_options['custom_location'] and plugin_options['custom_region'] and plugin_options['custom_timezone'] and plugin_options['custom_lati_longit']: from astral.geocoder import add_locations, database, lookup db = database() _loc = '{},{},{},{}'.format(plugin_options['custom_location'], plugin_options['custom_region'], plugin_options['custom_timezone'], plugin_options['custom_lati_longit']) add_locations(_loc, db) # "Somewhere,Secret Location,UTC,24°28'N,39°36'E" city = lookup(plugin_options['custom_location'], db) found_name = city.name found_region = city.region found_timezone = city.timezone found_latitude = city.latitude found_longitude = city.longitude else: log.info(NAME, _('You must fill in all required fields (location, region, timezone/name, latitude and longitude!')) city = None s = None if city is not None: log.info(NAME, _('Found city')) log.info(NAME, _('Name') + ': {}'.format(found_name)) log.info(NAME, _('Region') + ': {}'.format(found_region)) log.info(NAME, _('Timezone') + ': {}'.format(found_timezone)) log.info(NAME, _('Latitude') + ': {}'.format(round(found_latitude, 2))) log.info(NAME, _('Longitude') + ': {}'.format(round(found_longitude, 2))) import datetime from astral.sun import sun today = datetime.date.today() _day = int(today.strftime("%d")) _month = int(today.strftime("%m")) _year = int(today.strftime("%Y")) s = sun(city.observer, date=datetime.date(_year, _month, _day), tzinfo=found_timezone) log.info(NAME, '_______________ ' + '{}'.format(today) + ' _______________') log.info(NAME, _('Dawn') + ': {}'.format(s["dawn"].strftime("%H:%M:%S"))) log.info(NAME, _('Sunrise') + ': {}'.format(s["sunrise"].strftime("%H:%M:%S"))) log.info(NAME, _('Noon') + ': {}'.format(s["noon"].strftime("%H:%M:%S"))) log.info(NAME, _('Sunset') + ': {}'.format(s["sunset"].strftime("%H:%M:%S"))) log.info(NAME, _('Dusk') + ': {}'.format(s["dusk"].strftime("%H:%M:%S"))) msg = _('Sunrise') + ': {}, '.format(s["sunrise"].strftime("%H:%M:%S")) + _('Sunset') + ': {}'.format(s["sunset"].strftime("%H:%M:%S")) from astral import moon m = moon.phase(datetime.date(_year, _month, _day)) log.info(NAME, _('Moon phase') + ': {}'.format(round(m, 2))) msg += ', ' + _('Moon phase') + ': ' if m < 7: log.info(NAME, '* ' + _('New moon')) msg += _('New moon') elif m >= 7 and m < 14: log.info(NAME, '* ' + _('First quarter')) msg += _('First quarter') elif m >= 14 and m < 21: log.info(NAME, '* ' + _('Full moon')) msg += _('Full moon') elif m >= 21 and m < 28: log.info(NAME, '* ' + _('Last quarter')) msg += _('Last quarter') else: log.info(NAME, '* ' + _('Unkown phase')) msg += _('Unkown phase') except Exception: self.started.set() log.error(NAME, _('Astro plug-in') + ':\n' + traceback.format_exc()) self._sleep(2) else: msg =_(u'Plugin is not enabled') if plugin_options['use_footer']: if temp_upd is not None: temp_upd.val = msg.encode('utf8').decode('utf8') # value on footer else: log.error(NAME, _('Error: restart this plugin! Show in homepage footer have enabled.')) self._sleep(3600) except Exception: self.started.set() log.error(NAME, _('Astro plug-in') + ':\n' + traceback.format_exc()) self._sleep(60)
def run_loop(config): delta = 0 base = config["base_path"] debugLog = config["debugLog"] # assumption that this program won't run for weeks so calc dawn/dusk once # check location is in astral db via online documentation city = lookup(config["location"], database()) citysun = sun(city.observer, date=now) Dawn = citysun["dawn"].astimezone(timezone(city.timezone)).time() Dusk = citysun["dusk"].astimezone(timezone(city.timezone)).time() while True: # grab config file try: filepath = config["base_path"] + "/config.yaml" with open(filepath) as f: config = yaml.load(f, Loader=yaml.FullLoader) debugLog = config["debugLog"] except FileNotFoundError: logger.info("--<opening '%s' failed>---", filepath) if debugLog: logger.info(" ") logger.info("=========== start capture ==========") now = datetime.now() startTime = config["start_time"] endTime = config["end_time"] pause = config["time_delay"] if debugLog: logger.info("Pause interval: %s", str(pause)) # set exposure or drop out of loop if night mode nowTime = now.time() if Dawn < nowTime and nowTime < Dusk: # Day if config["shooting_mode"] == "night": if debugLog: logger.info( "Shot cancelled as time is outside time window") continue exposureMode = 'auto' else: # Night exposureMode = 'night' take_shot = check_shot(startTime, endTime) if take_shot is True: path = prepare_dir(base, now) name = '{:%Y%m%d-%H%M%S-}'.format(now) + exposureMode + '.jpg' if debugLog: logger.info("Capturing %s in %s mode", name, exposureMode) fileName = base + "/" + path + "/" + name os_command = make_os_command(config, exposureMode, fileName) os.system(os_command) if debugLog: logger.info("Command: %s", os_command) delta = int((datetime.now() - now).seconds) if debugLog: logger.info("Capture File: %s/%s secs", str(delta), str(pause)) else: if debugLog: logger.info("Shot cancelled as time is outside time window") # night shots take about 10 x shooting time if pause - delta > 0: time.sleep(pause - delta)
def run(): defaults = {'log': "info"} # Parse any config file specification. We make this parser with add_help=False so # that it doesn't parse -h and print help. conf_parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, add_help=False) conf_parser.add_argument("--config", help="Specify config file", metavar='FILE') args, remaining_argv = conf_parser.parse_known_args() # Read configuration file and add it to the defaults hash. if args.config: config = ConfigParser() config.read(args.config) if "Defaults" in config: defaults.update(dict(config.items("Defaults"))) else: logging.error("Bad config file, missing Defaults section") sys.exit(1) # Parse rest of arguments parser = argparse.ArgumentParser( description=__doc__, parents=[conf_parser], ) parser.set_defaults(**defaults) parser.add_argument("--gw-station-id", help="GoodWe station ID", metavar='ID') parser.add_argument("--gw-account", help="GoodWe account", metavar='ACCOUNT') parser.add_argument("--gw-password", help="GoodWe password", metavar='PASSWORD') parser.add_argument("--mqtt-host", help="MQTT hostname", metavar='MQTT_HOST') parser.add_argument("--mqtt-port", help="MQTT port", metavar='MQTT_USER') parser.add_argument("--mqtt-user", help="MQTT username", metavar='MQTT_USER') parser.add_argument("--mqtt-password", help="MQTT password", metavar='MQTT_PASS') parser.add_argument("--mqtt-topic", help="MQTT topic", metavar='MQTT_TOPIC') parser.add_argument("--pvo-system-id", help="PVOutput system ID", metavar='ID') parser.add_argument("--pvo-api-key", help="PVOutput API key", metavar='KEY') parser.add_argument("--pvo-interval", help="PVOutput interval in minutes", type=int, choices=[5, 10, 15]) parser.add_argument("--telegram-token", help="Telegram bot token", metavar='TELEGRAM_TOKEN') parser.add_argument("--telegram-chatid", help="Telegram chat id", metavar='TELEGRAM_CHATID') parser.add_argument("--darksky-api-key", help="Dark Sky Weather API key") parser.add_argument("--openweather-api-key", help="Open Weather API key") parser.add_argument("--log", help="Set log level (default info)", choices=['debug', 'info', 'warning', 'critical']) parser.add_argument("--date", help="Copy all readings (max 14/90 days ago)", metavar='YYYY-MM-DD') parser.add_argument( "--upload-csv", help="Upload all readings from csv file (max 14/90 days ago)") parser.add_argument("--pv-voltage", help="Send pv voltage instead of grid voltage", action='store_true') parser.add_argument("--skip-offline", help="Skip uploads when inverter is offline", action='store_true') parser.add_argument( "--city", help="Sets timezone and skip uploads from dusk till dawn") parser.add_argument( '--csv', help= "Append readings to a Excel compatible CSV file, DATE in the name will be replaced by the current date" ) parser.add_argument('--version', action='version', version='%(prog)s ' + __version__) args = parser.parse_args() # Configure the logging numeric_level = getattr(logging, args.log.upper(), None) if not isinstance(numeric_level, int): raise ValueError('Invalid log level: %s' % loglevel) logging.basicConfig(format='%(levelname)-8s %(message)s', level=numeric_level) logging.debug("gw2pvo version " + __version__) if isinstance(args.skip_offline, str): args.skip_offline = args.skip_offline.lower() in [ 'true', 'yes', 'on', '1' ] if args.upload_csv is None: if args.gw_station_id is None or args.gw_account is None or args.gw_password is None: if args.mqtt_host is None or args.mqtt_topic is None: logging.error( "Missing configuation. Either MQTT configuration or Goodwe (SEMS Portal) credentails need to be provided.\nPlease add either --gw-station-id, --gw-account and --gw-password OR add --mqtt-host and --mqtt-topic (at a minimum). Alternatively, one of these options can also be configured in a configuration file." ) sys.exit(1) if args.city: city = Location(lookup(args.city, database())) os.environ['TZ'] = city.timezone time.tzset() else: city = None logging.debug("Timezone {}".format(datetime.now().astimezone().tzinfo)) # Check if we want to copy old data if args.date: try: copy(args) except KeyboardInterrupt: sys.exit(1) except Exception as exp: logging.error(exp) sys.exit() elif args.upload_csv: try: copy_csv(args) except Exception as exp: logging.error(exp) sys.exit(1) startTime = datetime.now() while True: currentTime = datetime.now() try: run_once(args, city) except KeyboardInterrupt: sys.exit(1) except Exception as exp: errorMsg = ("Failed to publish data PVOutput - " + str(exp)) logging.error(str(currentTime) + " - " + str(errorMsg)) try: telegram_notify(args.telegram_token, args.telegram_chatid, errorMsg) except Exception as exp: logging.error( str(currentTime) + " - Failed to send telegram notification - " + str(exp)) if args.pvo_interval is None: break interval = args.pvo_interval * 60 time.sleep(interval - (datetime.now() - startTime).seconds % interval)
import sys, pytz from datetime import date from astral.geocoder import database, lookup from astral.sun import sun city_name = sys.argv[1] city = lookup(city_name, database()) print('Information for %s/%s\n' % (city.name, city.region)) timezone = city.timezone print('Timezone: %s' % timezone) print('Latitude: %.02f; Longitude: %.02f\n' % (city.latitude, city.longitude)) s = sun(city.observer, date=date.today(), tzinfo=pytz.timezone(timezone)) print('Dawn: %s' % str(s['dawn'])) print('Sunrise: %s' % str(s['sunrise'])) print('Noon: %s' % str(s['noon'])) print('Sunset: %s' % str(s['sunset'])) print('Dusk: %s' % str(s['dusk']))
from astral import LocationInfo from astral.geocoder import database, lookup from astral.sun import sun # Configuation CITY = "Austin" # Choose from list of cities in README LED_DAY_BRIGHTNESS = 0.2 # Float from 0.0 (min) to 1.0 (max) LED_NIGHT_BRIGHTNESS= 0.08 # Float from 0.0 (min) to 1.0 (max) # Setup now_utc = datetime.datetime.utcnow() # astral times are in zulu now_local = datetime.datetime.now() year = now_local.date().year month = now_local.date().month day = now_local.date().day city = lookup(CITY,database()) s = sun(city.observer, date=datetime.date(year, month, day)) # query with local day to keep sunset and sunrise on local day not zulu day #times in zulu sunrise = (s["sunrise"]).replace(tzinfo=None) sunset = (s["sunset"]).replace(tzinfo=None) dawn = (s["dawn"]).replace(tzinfo=None) dusk = (s["dusk"]).replace(tzinfo=None) up = sunrise down = sunset if ((now_utc < up) | (now_utc > down)): LED_BRIGHTNESS = LED_NIGHT_BRIGHTNESS print("Nightime. Switching at " + str(up)) elif ((now_utc > up) & (now_utc < down)): LED_BRIGHTNESS = LED_DAY_BRIGHTNESS print("Daytime. Switching at " + str(down)) else:
def update_day_curve(): city = lookup(constants.location, database()) sun_info = sun(city.observer, date=datetime.datetime.now()) time_left = (sun_info['sunrise'].hour * 60) + sun_info['sunrise'].minute + 35 time_middle = ((sun_info['sunset'].hour * 60) + sun_info['sunset'].minute + 35) - ((sun_info['sunrise'].hour * 60) + sun_info['sunrise'].minute + 35) + time_left time_now = (datetime.datetime.now().time().hour * 60) + datetime.datetime.now().time().minute data_points = [] # clear screen GB.surface_day_main.fill(constants.black) # draw lines # main seperation line pygame.draw.lines(GB.surface_day_main, constants.gray1, False, [(25, 125), (425, 125)], 3) # left bottom line pygame.draw.lines(GB.surface_day_main, constants.gray2, False, constants.day_points_btm_left, 3) # main top line pygame.draw.lines(GB.surface_day_main, constants.white, False, constants.day_points_top, 3) # right bottom line pygame.draw.lines(GB.surface_day_main, constants.gray2, False, constants.day_points_btm_right, 3) if time_now <= time_left: # its night now, left GB.is_day_time = 0 # calculate index index = constants.map_num(time_now, 0, time_left, 0, 10) index = int(index) + 2 for i in range(0, index): data_points.append(constants.day_points_btm_left[i]) data_points.append((((index - 2) * 10) + 25, 125)) # fill graph pygame.gfxdraw.filled_polygon(GB.surface_day_main, data_points, constants.gray2) # draw circle pygame.draw.circle(GB.surface_day_main, constants.moon_blue, data_points[(index - 1)], 15, 0) elif time_now > time_left and time_now <= time_middle: # its day now # calculate index index = constants.map_num(time_now, time_left, time_middle, 0, 20) index = int(index) + 2 # save index GB.is_day_time = index for i in range(0, index): data_points.append(constants.day_points_top[i]) data_points.append((((index - 2) * 10) + 125, 125)) # fill graphs pygame.gfxdraw.filled_polygon(GB.surface_day_main, constants.day_points_btm_left, constants.gray2) pygame.gfxdraw.filled_polygon(GB.surface_day_main, data_points, constants.white) # draw circle pygame.draw.circle(GB.surface_day_main, constants.yellow, data_points[(index - 1)], 15, 0) elif time_now > time_middle: # its night now, right GB.is_day_time = -1 # calculate index index = constants.map_num(time_now, time_middle, 1440, 0, 10) index = int(index) + 2 for i in range(0, index): data_points.append(constants.day_points_btm_right[i]) data_points.append((((index - 2) * 10) + 325, 125)) # fill graphs pygame.gfxdraw.filled_polygon(GB.surface_day_main, constants.day_points_btm_left, constants.gray2) pygame.gfxdraw.filled_polygon(GB.surface_day_main, constants.day_points_top, constants.white) pygame.gfxdraw.filled_polygon(GB.surface_day_main, data_points, constants.gray2) # draw circle pygame.draw.circle(GB.surface_day_main, constants.moon_blue, data_points[(index - 1)], 15, 0)