#! /usr/bin/env python """ usage: google-muell [options] --config=PATH path to google-muell config --client-secrets=FILE Path to client secrets file (from application) [Default: licht-kalender-secrets.json] --credential-path=PATH Path to newly generated (or existing) credentials [Default: licht-creds.json] --sleepval=SEC seconds to sleep [Default: 900] --lol=LOL set log level [Default: debug] --default-color=R,G,B set default color as integers, separated by comma you can create the client-secrets by creating a new google application, create oauth2 token and download it ( url here) """ from docopt import docopt from ampel.fade import calc_chain import time from time import sleep import json import sys from datetime import datetime, timedelta import requests import httplib2 from dateutil.parser import parse from apiclient import discovery from oauth2client import client from oauth2client import tools from oauth2client.file import Storage import logging as log SCOPES = 'https://www.googleapis.com/auth/calendar.readonly' APPLICATION_NAME = 'licht-kalender-client' calendarId = 'o56ig681gla2a5vupm4vgiv7tc@group.calendar.google.com' # Mapping colorId from calendar to RGB colors colormap = { # "-1": [ 124, 179, 66 ], # default color (green) "-1": [ 54, 234, 255 ], # default color (green) "1": [ 121, 134, 203 ], # lavendel "2": [ 51, 182, 121 ], # salbei "3": [ 142, 36, 170 ], # grape "4": [ 230, 124, 115 ], # light red "5": [ 255, 183, 0 ], # banana, gelber sack "6": [ 244, 81, 30 ], # mandarin "7": [ 3, 155, 229], # pfau "8": [ 128,128,128 ], # grey "9": [ 63, 81, 181 ], # heidelbeere "10": [ 0x0B,0x80,0x43 ], # basilicum "11": [ 231,0,0 ], # true red } def set_lol(lol): numeric_level = getattr(log,lol.upper(),None) if not isinstance(numeric_level,int): raise AttributeError(f'No such log level {lol}') log.basicConfig(level=numeric_level) def get_creds(secrets_file,credential_path): ''' provide a cred_dir where the credentials would be stored to ''' import argparse flags = tools.argparser.parse_args(args=[]) store = Storage(credential_path) credentials = store.get() if not credentials or credentials.invalid: flow = client.flow_from_clientsecrets(secrets_file, SCOPES) flow.user_agent = APPLICATION_NAME credentials = tools.run_flow(flow, store, flags) log.info(f'Storing new credentials to {credential_path}') else: log.info(f'Using existing valid credentials {credential_path}') return credentials def next_date(credentials): http = credentials.authorize(httplib2.Http()) service = discovery.build('calendar', 'v3', http=http) now = datetime.utcnow().isoformat() + 'Z' # 'Z' indicates UTC time log.debug('Getting the upcoming 10 events') eventsResult = service.events().list( calendarId=calendarId, timeMin=now, maxResults=10, singleEvents=True, orderBy='startTime').execute() events = eventsResult.get('items', []) for event in events: rem = event['reminders'] # 'reminders': {'useDefault': False, 'overrides': [{'method': 'popup', 'minutes': 900}]} start = parse(event['start'].get('dateTime', event['start'].get('date'))) if rem.get('overrides',[]): reminder = timedelta(minutes=rem['overrides'][0]['minutes']) log.info(f"Got a reminder at {reminder}, subtracting time") start = start - reminder if 'dateTime' in event['end']: end = parse(event['end']['dateTime']) else: end = parse(event['end']['date']) - timedelta(seconds=1) # + timedelta(days=1) if start < datetime.now() < end: log.info(f"event {event['summary']} is active now ({start} - {end})") return event else: log.info(f"event between {start} and {end} is not active") pass def to_payload(arr): return "{:02x}{:02x}{:02x}".format(*arr) import paho.mqtt.publish as publish import paho.mqtt.client as mqtt def main(): args = docopt(__doc__) set_lol(args['--lol']) client_secrets = args['--client-secrets'] sleepval = float(args["--sleepval"]) cred_path = args["--credential-path"] with open(args["--config"]) as c: import json config = json.load(c) creds = get_creds(client_secrets,cred_path) while True: #try: log.info("Fetching next Date") t = next_date(creds) if t: log.debug("current entry is {}".format(t)) color = colormap[str(t.get('colorId',-1))] log.info(f"setting color to {color} according to colormap") else: color = colormap["-1"] if not args['--default-color'] else map(int,args['--default-color'].split(',')) log.info(f"setting default color {color}") topic = config['mq_topic'] if config.get('mq_password',None): auth = {"username": config['mq_username'], "password": config['mq_password']} else: auth = None publish.single(topic, payload=to_payload(color), hostname=config.get('mq_hostname','localhost'), port=config.get('mq_port',1883), client_id="", keepalive=60, auth=auth, protocol=mqtt.MQTTv311) #except Exception as e: # log.error(f"Something went wrong while calculating the next date:{e}") log.info(f"sleeping for {sleepval} seconds") sleep(sleepval) if __name__ == "__main__": main()