Depuis l'abandon par Google de l'authentification en mode OAuth 1.0, gcalcli ne fonctionne plus.
Je me suis donc penché sur l'accès à l'API Google en mode OAuth 2.0.
Après pas mal de soirée de labeur, voici une solution opérationnelle clef en main.
Les événements dans Google Calendar doivent être sous la forme de cet exemple : DZ:Lampe Salon[Off]
Entête : DZ: (afin de faire la différence avec les autres événements du calendrier familial, Dentiste,Musique,Sport,etc)
Device : Nom du Device : (Pas d'accent ou caractères spéciaux, [ et ] sont interdits)
Commande : [xxx]
A installer
https://developers.google.com/google-ap ... art/python
Evènements
Connexion à Domoticz
domoticz_ip='192.168.0.252'
domoticz_port='8084'
user=''
password='
Connexion à Google
Il faut éditer le code Python afin de définir les variables client_id et client_secret.
Pour les obtenir, se connecter sur le compte Google détenant le calendrier, puis allez sur https://console.developers.google.com
Il faut alors créer un projet dé développement, Domoticz par exemple, puis allez dans le menu à droite nommée "Identifiants".
Choisir le menu en bleu "Créer des identifiants" et sélectionner l'item "ID client OAuth", sélectionner Autre, une fenêtre s'ouvre alors avec l'identifiant (client_id) puis le token (client_secret)
Cela ressemble à cela
client_id='376277659069-he7XXXXX7kq23jgpnouec518cv7v56ma.apps.googleusercontent.com',
client_secret='u9cXkLW5Cwq6V_EEXCx1lGEu',
Pour vérifier que la connexion fonctionne, mettre la variable trace à 1.
Si la connexion fonctionne cette ligne s'affiche, si la connexion est KO, "None" s'affiche.
Debug Google Calendar : credentials : <oauth2client.client.OAuth2Credentials object at 0x7f6ff0392f50>
Intégration NAS Synology
Le lancement du script Python avec l'ordonnanceur Synology crée un environnement shell qui ne permet pas la connexion à Google.
Je n'ai pas trouvé la raison à cette heure, donc j'ai contourné en lançant manuellement un processus détaché qui boucle toutes les 60 secondes.
Je pense qu'il s'agit d'un problème d'environnement Interactif ou non. Si un spécialiste Linux passe par là ....

Code : Tout sélectionner
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright Avril 2016 C.BRUGEL All Rights Reserved.
#
#
# The client_id and client_secret are copied from the API Access tab on
# the Google APIs Console
# client_id='376277659069-he7me0mh7kq23jgpnouec518XXXXXXX.apps.googleusercontent.com',
# client_secret='u9cXkLW5Cwq6V_EEXCx1lGEu',
#
# Les évènements dans Google Calendar doivent être sous la forme suivante.
# A noter que
# DZ:Nom du Device[commande]
# Exemple DZ:Volet Chambre Marie[On]
#
#import pdb # Chargement du module Debug Python si nécessaire
import sys
import datetime
import time
import pytz
import re
import ConfigParser
import json
import requests
from requests.auth import HTTPBasicAuth
import httplib2
from oauth2client import client
from apiclient.discovery import build
from oauth2client.file import Storage
from oauth2client.client import OAuth2WebServerFlow
#------Paramètres généraux ----------
domoticz_ip='192.168.0.252'
domoticz_port='8084'
user=''
password=''
#------Variables Globales ----------
trace=1 # Affichage message Debug
deviceidx=[]
devicename=[]
#*********************************************
# Debug Output
#*********************************************
def DebugPrint(chaine,valeur):
if trace == 1:
print ("Debug Google Calendar : " + str(chaine) + " : " + str(valeur))
#*****************************************************************
# Renvoie le nombre de secondes d'une date ISO 2016-04-09T14:52:00
#*****************************************************************
def Secondes(s):
heure=s[8:10]+"/"+s[5:7]+"/"+s[0:4]+" "+s[11:19]
DebugPrint("Heure",heure)
d = datetime.datetime.strptime(heure, "%d/%m/%Y %H:%M:%S")
r = time.mktime(d.timetuple())
return (r)
#*********************************************
# Ecriture Device Domoticz
#*********************************************
write_url_text1='/json.htm?type=command¶m='
write_url_text2='&idx='
write_url_text3='&'
def WriteDevice(domoticz_idx,param,val):
requete='http://'+domoticz_ip+':'+domoticz_port+write_url_text1+param+write_url_text2+str(domoticz_idx)+write_url_text3+val
DebugPrint("WriteDevice Requete", requete)
r=requests.get(requete,auth=HTTPBasicAuth(user,password))
DebugPrint("WriteDevice Return", r)
if r.status_code != 200:
ErrorPrint ("-1-Erreur Lecture API Domoticz")
return("KO")
else:
return("OK")
#*********************************************
# Lecture Device Domoticz
#*********************************************
read_url_text1='/json.htm?type=devices&rid='
def ReadDevice(domoticz_idx,param):
requete='http://'+domoticz_ip+':'+domoticz_port+read_url_text1+str(domoticz_idx)
DebugPrint("ReadDevice Requete", requete)
r=requests.get(requete,auth=HTTPBasicAuth(user,password))
DebugPrint("ReadDevice Return", r)
domoticzjson=r.json()
for i, v in enumerate(domoticzjson["result"]):
val= domoticzjson["result"][i][param]
if r.status_code != 200:
ErrorPrint ("-2-Erreur Lecture API Domoticz")
return("KO")
else:
return(val)
#*******************************************************************
# Construction liste Device Switch Domoticz
# Cette liste permet de retrouver l'IDX en fonction du nom de device
#*******************************************************************
read_url_text1='/json.htm?type=command¶m=getlightswitches' # URL pour énumérer liste device type Switch
def ReadDeviceList():
requete='http://'+domoticz_ip+':'+domoticz_port+read_url_text1
DebugPrint("ReadDevice Requete", requete)
r=requests.get(requete,auth=HTTPBasicAuth(user,password))
DebugPrint("ReadDevice Return", r) # On récupère la liste dans "r"
domoticzjson=r.json()
for i, v in enumerate(domoticzjson["result"]): # On balaie la liste pour stocker les noms
devicename.append(domoticzjson["result"][i]['Name']) # On ajoute le nom du device à la liste
for i, v in enumerate(domoticzjson["result"]): # On balaie la liste pour stocker les IDX
deviceidx.append(domoticzjson["result"][i]['idx']) # On ajoute l'IDX du device à la liste
DebugPrint(i, devicename[i] + " : " + deviceidx[i])
if r.status_code != 200:
ErrorPrint ("-3-Erreur Lecture API Domoticz")
return("KO")
else:
DebugPrint("==============================","================================")
return(i)
#*********************************************
# Main fonction
#*********************************************
DebugPrint("*********************************** MAIN","***********************************")
#pdb.set_trace() # Activation du mode Debug Python
#Alimentation liste des devices de type Switchs
#Si la constuction de la liste plante, on sort
if ReadDeviceList() == "KO" : sys.exit(0)
# Définition NOW au format ISO
now = datetime.datetime.now(pytz.timezone('Europe/Paris')).isoformat()
DebugPrint("now",now)
# NOW en nombre de secondes
nowsec=Secondes(now)
DebugPrint("nowsec",nowsec)
# Authenticate and construct service.
# Set up a Flow object to be used if we need to authenticate. This
# sample uses OAuth 2.0, and we set up the OAuth2WebServerFlow with
# the information it needs to authenticate. Note that it is called
# the Web Server Flow, but it can also handle the flow for native
# applications
FLOW = OAuth2WebServerFlow(
client_id='376277659069-heXXXXXXXXXXXXXkq23jgpnouec518cv7v56ma.apps.googleusercontent.com',
client_secret='u9cXkLW5Cwq6V_EEXCx1lGEu',
scope='https://www.googleapis.com/auth/calendar',
user_agent='Domoticz/1.0')
# If the Credentials don't exist or are invalid, run through the native client
# flow. The Storage object will ensure that if successful the good
# Credentials will get written back to a file.
storage = Storage('calendar.dat')
credentials = storage.get()
DebugPrint("credentials",credentials)
if credentials is None or credentials.invalid == True:
credentials = run(FLOW, storage)
# Create an httplib2.Http object to handle our HTTP requests and authorize it
# with our good Credentials.
http = httplib2.Http()
http = credentials.authorize(http)
# Build a service object for interacting with the API. Visit
# the Google APIs Console
# to get a developerKey for your own application.
service = build(serviceName='calendar', version='v3', http=http,
developerKey='YOUR_DEVELOPER_KEY')
# Construction liste des 30 évènements à venir
eventsResult = service.events().list(
calendarId='primary', timeMin=now, maxResults=10, singleEvents=True,
orderBy='startTime').execute()
events = eventsResult.get('items', [])
if not events:
DebugPrint("No upcoming events found.","") # Pas d'évènement !
DebugPrint("################################### MAIN","###################################")
sys.exit(0)
else:
# On énumère chaque évènement
for event in events:
start = event['start'].get('dateTime', event['start'].get('date'))
chaine = start + event['summary']
if (chaine[25:28]) == "DZ:":
DebugPrint("==============================","================================")
DebugPrint("chaine",chaine) #2016-04-06T22:35:00+02:00DZ:Volet Marie[Off]
eventsec=Secondes(chaine[0:19]) # Date Event en nombre de secondes
DebugPrint("eventsec",eventsec)
deltasec=abs(eventsec-nowsec) # Calcul de l'écart en secondes entre NOW et Event
DebugPrint("deltasec",deltasec)
DZdevice=chaine[28:chaine.index("[")] # On extrait le nom du device de l'Event
DebugPrint("DZdevice",DZdevice)
DZcommand=chaine[chaine.index("[")+1:chaine.index("]")] # On extrait le nom de la commande de l'Event
DebugPrint("DZcommand",DZcommand)
DeviceAvailable=1 # On positionne le device par défaut comme existant dans Domoticz
try:
index=devicename.index(DZdevice) # On cherche le device de l'Event dans la liste des devices Domoticz
idx=deviceidx[index] # si le device est connu, on récupère l'IDX domoticz
DebugPrint("idx", idx)
except Exception, e: # Dans le cas ou le device de l'Event n'est pas dans Domoticz
DebugPrint("erreur", e)
DeviceAvailable=0 # On positionne le device comme n'existant pas Domoticz
DebugPrint("Erreur : ","Device inconnu")
pass
if DeviceAvailable==1 and deltasec < 35: # On traite l'action si le device de l'Event existe et si l'écart en sec est < à 35s
DebugPrint("Action : ", DZdevice + " : " + DZcommand)
Status=WriteDevice(idx,"switchlight","switchcmd="+DZcommand)
DebugPrint("################################### MAIN","###################################")
Code : Tout sélectionner
#!/bin/bash
while [ test ]
do
echo '****************************************** GoogleCalendar-V7.py ******************************************' >> /volume1/@appstore/domoticz/var/scripts/python/GoogleCalendar-V7.log
python GoogleCalendar-V7.py >> /volume1/@appstore/domoticz/var/scripts/python/GoogleCalendar-V7.log
echo '########################################## GoogleCalendar-V7.py ##########################################' >> /volume1/@appstore/domoticz/var/scripts/python/GoogleCalendar-V7.log
sleep 60
done
Code : Tout sélectionner
#!/bin/bash
nohup /volume1/@appstore/domoticz/var/scripts/python/GoogleCalendar.bash &