Exemplo n.º 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())
Exemplo n.º 2
0
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
Exemplo n.º 3
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)))
Exemplo n.º 4
0
 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)
Exemplo n.º 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)
Exemplo n.º 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
Exemplo n.º 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()
Exemplo n.º 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
Exemplo n.º 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
Exemplo n.º 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)
Exemplo n.º 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
Exemplo n.º 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})
Exemplo n.º 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'
Exemplo n.º 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
Exemplo n.º 15
0
import os.path
import operator
from dateutil.relativedelta import relativedelta
from numpy import asarray
from astral import geocoder
from astral import location
import astral
import sys
import os
import subprocess
import glob
import time
from PIL import Image

#getting the list of all US cities in the astral database
db = geocoder.database()
locations = geocoder.all_locations(db)
locList = []
usaLocList = {}
for location in locations:
    locList.append(location)
    if location.region == 'USA':
        usaLocList[location.name] = location

#####################################
#setup GLOBALs time and sun calculations
utc = pytz.UTC

#####################################
# setup GLOBALs design: tower hight in meters, tracker dimensions
DistanceToSun = 10200  # far away so all rays are parallel
Exemplo n.º 16
0
def getSun(city_name):
    city = lookup(city_name, database())
    return sun(city.observer, date=datetime.date.today())
Exemplo n.º 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)
Exemplo n.º 18
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()
Exemplo n.º 19
0
 def __init__(self):
     self.sanDiego = lookup("San Diego", database())
     self.tz_sd = pytz.timezone(str(self.sanDiego.tzinfo))
Exemplo n.º 20
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)
Exemplo n.º 21
0
def test_database() -> LocationDatabase:
    return database()
Exemplo n.º 22
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)
Exemplo n.º 23
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)
Exemplo n.º 24
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']))
Exemplo n.º 25
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)
Exemplo n.º 26
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"))
Exemplo n.º 27
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)
Exemplo n.º 28
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)
Exemplo n.º 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:
Exemplo n.º 30
0
from http.server import HTTPServer, BaseHTTPRequestHandler
from sun_tracker import get_location_info, check_after_sunset, display_city_info, get_sun_info
from astral.geocoder import database
import datetime

notification = 'False'
is_connected = 'False'
should_break = 'False'

# Getting locational info
city = get_location_info(database(), 'Warsaw')

# Getting info about the sun today
sun = get_sun_info(city, datetime.date.today())

now = datetime.datetime.now()
hour_now = now.hour
hour_ss = sun['sunset'].hour
hour_sr = sun['sunrise'].hour
status = check_after_sunset(hour_sr, hour_ss, hour_now)
status = True


class Server(BaseHTTPRequestHandler):
    def do_GET(self):

        global notification, status, is_connected, should_break

        if self.path == '/':
            self.send_response(200)
            self.send_header('content-type', 'text/html')