Exemple #1
0
 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())
Exemple #2
0
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)
Exemple #5
0
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)
Exemple #6
0
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
Exemple #7
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()
Exemple #8
0
    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
Exemple #9
0
    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
Exemple #10
0
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)
Exemple #11
0
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
Exemple #12
0
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})
Exemple #13
0
    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'
Exemple #14
0
    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
Exemple #15
0
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())
Exemple #17
0
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)
Exemple #18
0
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)

Exemple #20
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()
Exemple #21
0
 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"
Exemple #23
0
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)
Exemple #24
0
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"))
Exemple #25
0
    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)
Exemple #26
0
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)
Exemple #27
0
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)
Exemple #28
0
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']))
Exemple #29
0
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:
Exemple #30
0
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)