与谷歌日历API交互的闹钟

时间:2016-07-15 09:54:45

标签: python-2.7 calendar raspberry-pi

我正在寻找与谷歌日历互动的闹钟的一些帮助。

我现在的代码存在问题,而不是拉下事件。

这是我现在得到的错误:

信息:主要:事件的投票日历...... 信息:googleapiclient.discovery:请求的网址:获取https://www.googleapis.com/calendar/v3/calendars/primary/events?alt=json&singleEvents=true 信息:主要:事件的投票日历...... 信息:googleapiclient.discovery:请求的网址:GET https://www.googleapis.com/calendar/v3/calendars/primary/events?alt=json&singleEvents=true

处理以退出代码-1

结束
# Inspired from 'Raspberry Pi as a Google Calender Alarm Clock'
# http://www.esologic.com/?p=634
#and this link as well https://github.com/ehamiter/get-on-the-bus

from datetime import datetime
import logging, os, platform, re, time

from apiclient import discovery

import httplib2
from oauth2client.client import flow_from_clientsecrets
from oauth2client.file import Storage
from oauth2client.tools import run_flow

SCOPES = 'https://www.googleapis.com/auth/calendar.readonly'
CLIENT_SECRET_FILE = 'client_secret.json'
APPLICATION_NAME = 'Google Calendar API Python Quickstart'
FREQUENCY_CHECK = 5 # in second
MP3_FOLDER = 'E:\Users\Andrew.Price\PycharmProjects\SimpleAlarm\MP3'
CALENDAR_ID ='primary'

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)


class Alarm():
    system = platform.system().lower()
    flow = flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)

    flow.params['access_type'] = 'offline'
    flow.params['approval_prompt'] = 'force'

    storage = Storage('calendar.dat')
    credentials = storage.get()
    if credentials is None or credentials.invalid == True:
        credentials = run_flow(flow, storage)

    http = httplib2.Http()
    http = credentials.authorize(http)
    service = discovery.build('calendar', 'v3', http=http)
    #service = build(serviceName='calendar', version='v3', http=http, developerKey=API_KEY)

    def check_credentials(self):
        if self.credentials is None or self.credentials.invalid == True:
            credentials = run_flow(self.flow, self.storage)

    def calendar_event_query(self):
        self.check_credentials()
        today = datetime.today()
        events = self.service.events().list(singleEvents=True, calendarId=CALENDAR_ID).execute()
        #events = self.service.events().list(singleEvents=True).execute()

        for i, event in enumerate(events['items']):
            name = event['summary'].lower()
            try:
                start = event['start']['dateTime'][:-9]
            except KeyError:
                start = ''

            description = event.get('description', '')
            repeat = True if description.lower() == 'repeat' else False
            now = today.strftime('%Y-%m-%dT%H:%M')

            if start >= now:
                logger.debug('Event #%s, Name: %s, Start: %s', i, name, start)

                if start == now:
                    if name.startswith('say'):
                        name = re.sub(r'[^a-zA-Z0-9\s\']', '', name)
                        command = '{0} "{1}"'.format('say' if system == 'darwin' else 'espeak -ven+m2', name[4:])
                        logger.info('Event starting. Announcing \'%s\'...', name[4:])
                    else:
                        mp3_files = os.listdir(MP3_FOLDER)
                        mp3_name = name.replace(' ', '_') + '.mp3'
                        mp3_name = mp3_name if mp3_name in mp3_files else 'default.mp3'
                        command = 'mpg123 \'{}/{}\''.format(MP3_FOLDER, mp3_name)
                        logger.info('Event %s starting. Playing mp3 file %s...', name, mp3_name)
                    os.system(command)
                    if repeat == False:
                        time.sleep(60)

    def poll(self):
        logger.info('Polling calendar for events...')
        self.calendar_event_query()


while True:
    a = Alarm()
    a.poll()
    time.sleep(FREQUENCY_CHECK)

1 个答案:

答案 0 :(得分:0)

我已经使用Matt http://mattdyson.org/projects/alarmpi/#comment-20249

中的代码更改了代码并使其工作

这是我更改过的代码。它现在还不是很好用

from __future__ import print_function
import pytz
import dateutil.parser
import httplib2
from oauth2client import tools
from oauth2client import client
import datetime
import logging
from googleapiclient.discovery import build
from apiclient import discovery
from oauth2client.file import Storage
import Settings

import os

try:
    import argparse
    flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()
except ImportError:
    flags = None

log = logging.getLogger('root')

# If modifying these scopes, delete your previously saved credentials
# at ~/.credentials/calendar-python-quickstart.json
SCOPES = 'https://www.googleapis.com/auth/calendar.readonly'
CLIENT_SECRET_FILE = 'client_secret.json'
APPLICATION_NAME = 'Smart-Alarm'
class AlarmGatherer:

    def __init__(self):
        #home_dir = os.path.expanduser('~')
        #credential_dir = os.path.join(home_dir, 'calendar.dat')
        #if not os.path.exists(credential_dir):
        #    os.makedirs(credential_dir)
        #credential_path = os.path.join(credential_dir, 'client_secret.json')

        SCOPES = 'https://www.googleapis.com/auth/calendar.readonly'
        CLIENT_SECRET_FILE = 'client_secret.json'
        APPLICATION_NAME = 'Smart-Alarm'

        self.FLOW = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)

        self.storage = Storage('calendar.dat')
        self.credentials = self.storage.get()

        if not self.checkCredentials():
            log.error("GCal credentials have expired")
            log.warn("Remove calendar.dat and run 'python AlarmGatherer.py' to fix")
            return

        http = httplib2.Http()
        http = self.credentials.authorize(http)

        self.service = build('calendar', 'v3', http=http)

    def checkCredentials(self):
        return not (self.credentials is None or self.credentials.invalid == True)

    def generateAuth(self):
        self.credentials = tools.run_flow(self.FLOW, self.storage)

    def getNextEvent(self, today=False):
        log.debug("Fetching details of next event")
        if not self.checkCredentials():
            log.error("GCal credentials have expired")
            log.warn("Remove calendar.dat and run 'python AlarmGatherer.py' to fix")
            raise Exception("GCal credentials not authorized")

        #time = datetime.datetime.utcnow().isoformat() + 'Z'  # 'Z' indicates UTC
        time = datetime.datetime.now()
        if not today:
            # We want to find events tomorrow, rather than another one today
            log.debug("Skipping events from today")
            #time += datetime.timedelta(days=1)  # Move to tomorrow
            time = time.replace(hour=10, minute=0, second=0, microsecond=0)  # Reset to 10am the next day
            # 10am is late enough that a night shift from today won't be caught, but a morning shift
            #  from tomorrow will be caught

        result = self.service.events().list(
            calendarId='primary',
            timeMin="%sZ" % (time.isoformat()),
            maxResults=1,
            singleEvents=True,
            orderBy='startTime'
        ).execute()

        events = result.get('items', [])
        return events[0]

    def getNextEventTime(self, includeToday=False):
        log.debug("Fetching next event time (including today=%s)" % (includeToday))
        nextEvent = self.getNextEvent(today=includeToday)
        start = dateutil.parser.parse(nextEvent['start']['dateTime'])
        # start = dateutil.parser.parse(nextEvent['start']['dateTime'],ignoretz=True)
        # start = start.replace(tzinfo=pytz.timezone('Africa/Johannesburg'))

        return start

    def getNextEventLocation(self, includeToday=False):
        log.debug("Fetching next event location (including today=%s)" % (includeToday))
        nextEvent = self.getNextEvent(today=includeToday)
        if (nextEvent['location']):
            return nextEvent['location']
        return None

    def getDefaultAlarmTime(self):
        defaultTime = ('0600')
        #defaultTime = self.settings.getint('default_wake')
        #defaultTime = self.settings.getint('default_wake')
        defaultHour = int(defaultTime[:2])
        defaultMin = int(defaultTime[2:])

        alarm = datetime.datetime.now(pytz.timezone('Africa/Johannesburg'))
        alarm += datetime.timedelta(days=1)  # Move to tomorrow
        alarm = alarm.replace(hour=defaultHour, minute=defaultMin, second=0, microsecond=0)

        return alarm

if __name__ == '__main__':
    print("Running credential check")
    a = AlarmGatherer()
    try:
        if not a.checkCredentials():
            raise Exception("Credential check failed")
    except:
        print("Credentials not correct, please generate new code")
        a.generateAuth()
        a = AlarmGatherer()

    print(a.getNextEventTime())
    print(a.getNextEventLocation())