mendhak / waveshare-epaper-display

At-a-glance dashboard for Raspberry Pi with a Waveshare ePaper 7.5 Inch HAT. Date/Time, Weather, Alerts, Google/Outlook Calendar
https://code.mendhak.com/raspberrypi-epaper-dashboard/
449 stars 66 forks source link

google calendar requires me to re-authorize each time #19

Closed esprittordu closed 2 years ago

esprittordu commented 3 years ago

Ok full disclosure I'm a total slobbering idiot when it comes to this but I think I'm almost there. I've got the code mostly working. The weather displays which is great. The calendar isn't though. I know that this is probably partially google's fault changing code and authentication protocols around on you but this is what it is: Each time I run run.sh I get the prompt to put the google url into a browser window. I follow the instructions in a different ssh window with curl and run.sh continues. When I run run.sh again I am again prompted with the url and have to paste it into another curl session. The other problem is that my display (which looks great, nice formatting!) instead of showing calendar entries says: CAL_ONE CAL_DESC_ONE CAL_TWO CAL_DESC_TWO ...and so on. This may be because I think the calendar id for google format changed. Now it shows just my email address for calendar id. There is no number as seen in your example.

mendhak commented 3 years ago

@esprittordu so after you get prompted, and after you run that URL in another curl session, and the first session continues, do you see a token.pickle file appear in your waveshare directory? Could you do an ls -lah in that waveshare directory and paste the output here?

Two possibilities I'm thinking of are, either that token.pickle isn't being written, so the code doesn't know what tokens to use to get your calendar info. Or, the tokens are being written but whatever permissions it has been given aren't sufficient for calendar operations.

You can give it another go, try deleting credentials.json (which you downloaded from Google API Console) and token.pickle (which this script generates), and then regenerate and redownload credentials.json, and then run the script again.

esprittordu commented 3 years ago
climacell-timelines-response.json
-rw-r--r--  1 pi pi  424 Feb 15 01:57 credentials.json
drwxr-xr-x  5 pi pi 4.0K Feb 15 01:41 display
-rw-r--r--  1 pi pi 685K Feb 15 01:40 display.png
-rwxr-xr-x  1 pi pi 1.1K Feb 15 01:40 display.py
-rw-r--r--  1 pi pi  259 Feb 15 01:56 env.sh
drwxr-xr-x  8 pi pi 4.0K Feb 15 01:40 .git
-rw-r--r--  1 pi pi  104 Feb 15 01:40 .gitignore
-rw-r--r--  1 pi pi 6.3K Feb 15 01:40 README.md
-rwxr-xr-x  1 pi pi  825 Feb 15 01:40 run.sh
-rwxr-xr-x  1 pi pi 3.6K Feb 15 01:40 screen-calendar-get.py
-rw-r--r--  1 pi pi  58K Feb 15 03:22 screen-output.png
-rw-r--r--  1 pi pi 112K Feb 15 03:21 screen-output-weather.svg
-rw-r--r--  1 pi pi 112K Feb 15 01:40 screen-template.svg
-rw-r--r--  1 pi pi 7.4K Feb 15 01:40 screen-weather-get.py

I don't see a .pickle file anywhere in this directory. What a whimsical file extension name! I will delete credentials and redo them and see if anything is generated. I am doubtful that anything will be different because like i said google appears to have changed the format of their calendar token, they don't give me an alphanumeric code or anything but then again I have a thick head.

esprittordu commented 3 years ago

Ok after going through the python3 screen-calendar-get.py I receive all of these errors:

Traceback (most recent call last):
  File "screen-calendar-get.py", line 33, in <module>
    creds = flow.run_local_server()
  File "/home/pi/.local/lib/python3.7/site-packages/google_auth_oauthlib/flow.py", line 474, in run_local_server
    self.fetch_token(authorization_response=authorization_response)
  File "/home/pi/.local/lib/python3.7/site-packages/google_auth_oauthlib/flow.py", line 288, in fetch_token
    return self.oauth2session.fetch_token(self.client_config["token_uri"], **kwargs)
  File "/home/pi/.local/lib/python3.7/site-packages/requests_oauthlib/oauth2_session.py", line 240, in fetch_token
    authorization_response, state=self._state
  File "/home/pi/.local/lib/python3.7/site-packages/oauthlib/oauth2/rfc6749/clients/web_application.py", line 203, in parse_request_uri_response
    response = parse_authorization_code_response(uri, state=state)
  File "/home/pi/.local/lib/python3.7/site-packages/oauthlib/oauth2/rfc6749/parameters.py", line 274, in parse_authorization_code_response
    raise MissingCodeError("Missing code parameter in response.")
oauthlib.oauth2.rfc6749.errors.MissingCodeError: (missing_code) Missing code parameter in response.
mendhak commented 3 years ago

Let's see if our steps are the same and make sure the file being downloaded is the same. I go to https://console.cloud.google.com and sign in. On the left, APIs and Services > Credentials

image

On the credentials screen, at the top, New Credentials, OAuth client ID

image

Application type = Limited input device or Desktop. I think both should be acceptable.

image

image

After the credentials get created, you should see a list of Client IDs in a table like this.

image

On the right the 'down' arrow should prompt you to download the credentials.json file.

The contents look like this. I've deleted some bits for secrecy

{"installed":{"client_id":"817873112028-e3jXXXXXXXX185p.apps.googleusercontent.com","project_id":"quickstart-15562222225","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"5XXXXXXXX","redirect_uris":["urn:ietf:wg:oauth:2.0:oob","http://localhost"]}}

Now the contents of that file should become credentials.json. I did nano credentials.json and copied the contents into the file and saved it. Does this match up with what you've done so far?

Once credentials.json is in place, I did a python3 screen-calendar-get.py and I am told to browse to a URL like https://accounts.google.com/o/oauth2......... in a browser.

I open it in a browser, I get a warning screen, Google hasn't verified this app!. Show advanced, Go to Quickstart(unsafe) - basically it's trying to warn me as a safety mechanism, but I know I generated this. I go ahead. I get a dialog saying, Grant Quickstart Permission. More prompts, I'm allowing Quickstart to view my calendar.

image

I allow it, and the browser shows an error page, because it's trying to go to a http://localhost:8080/?state=........... URL. I copy that from the address bar. I open a new SSH session to the Raspberry Pi. I do a curl "http://localhost:8080/?state=....." (note the double quotes around the URL)

A message appears: The authentication flow has completed. You may close this window.

I go back to the first SSH session, and the script has continued and should have listed things from your calendar.

I also see a token.pickle in the same folder when I do ls -lah

-rw-r--r-- 1 pi pi  744 Feb 17 08:40 token.pickle

Now try running run.sh again. It should not prompt you.

mendhak commented 3 years ago

So I got curious about the pickle name after you pointed it out :grin: and found this StackOverflow post. I think it comes down to Python being Python... and the naming goes back to 1994!

mendhak commented 3 years ago

Did the screenshots help @esprittordu ?

danwooller commented 3 years ago

I'm at exactly the same sticking point. No pickled token.

Maquis90 commented 3 years ago

I get 404 if I execute ./run.sh :

 File "screen-calendar-get.py", line 124, in <module>
    main()
  File "screen-calendar-get.py", line 114, in main
    events = get_events(max_event_results)
  File "screen-calendar-get.py", line 69, in get_events
    orderBy='startTime').execute()
  File "/usr/local/lib/python3.7/dist-packages/googleapiclient/_helpers.py", line 134, in positional_wrapper
    return wrapped(*args, **kwargs)
  File "/usr/local/lib/python3.7/dist-packages/googleapiclient/http.py", line 915, in execute
    raise HttpError(resp, content, uri=self.uri)
googleapiclient.errors.HttpError: <HttpError 404 when requesting https://www.googleapis.com/calendar/v3/calendars/XXXXXXXXX0uabvhh3ilf0%2540group.calendar.google.com/events?timeMin=2021-03-09T18%3A03%3A19.478947Z&maxResults=6&singleEvents=true&orderBy=startTime&alt=json returned "Not Found". Details: "Not Found">
---------------------------------------
EXPORT TO PNG

But if I run python screen-calendar-get.pyon it's own a new calendar.pickle is created just fine. I don't know why this doesn't work...

mendhak commented 3 years ago

I'm wondering what's different between us that could be causing this.

Can all of you show me the output of these commands: cat /etc/os-release and uname -a and whoami and in the waveshare directory, ls -lah so we can see file permissions. I don't actually know if this will help, just trying to see if some pattern or anomaly exists.

Maybe if there's something different I need to experiment and try to match your environments.

Here's mine:


pi@epaper:~ $ cat /etc/os-release 
PRETTY_NAME="Raspbian GNU/Linux 10 (buster)"
NAME="Raspbian GNU/Linux"
VERSION_ID="10"
VERSION="10 (buster)"
VERSION_CODENAME=buster
ID=raspbian
ID_LIKE=debian
HOME_URL="http://www.raspbian.org/"
SUPPORT_URL="http://www.raspbian.org/RaspbianForums"
BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs"

pi@epaper:~ $ uname -a
Linux epaper 5.4.79+ #1373 Mon Nov 23 13:18:15 GMT 2020 armv6l GNU/Linux

pi@epaper:~ $ whoami
pi

pi@epaper:~/waveshare-epaper-display $ ls -lah
total 1.1M
drwxr-xr-x  5 pi pi 4.0K Mar  9 18:37 .
drwxr-xr-x 10 pi pi 4.0K Feb 17 21:20 ..
-rw-r--r--  1 pi pi 4.0K Mar  9 18:24 calendar.pickle
-rw-r--r--  1 pi pi 1.8K Mar  9 17:56 climacell-timelines-response.json
-rw-r--r--  1 pi pi  431 Feb 17 21:21 credentials.json
-rw-r--r--  1 pi pi 685K Feb 17 21:20 display.png
-rwxr-xr-x  1 pi pi 1.1K Feb 17 21:20 display.py
-rw-r--r--  1 pi pi  423 Feb 17 21:21 env.sh
-rwxr-xr-x  1 pi pi  201 Feb 17 21:20 env.sh.sample
drwxr-xr-x  9 pi pi 4.0K Feb 17 21:21 .git
-rw-r--r--  1 pi pi   97 Feb 17 21:20 .gitignore
-rw-r--r--  1 pi pi  129 Feb 17 21:20 .gitmodules
drwxr-xr-x  3 pi pi 4.0K Feb 17 21:20 lib
drwxr-xr-x  2 pi pi 4.0K Feb 17 21:21 __pycache__
-rw-r--r--  1 pi pi 6.1K Feb 17 21:20 README.md
-rw-r--r--  1 pi pi  965 Mar  9 18:38 run.log
-rwxr-xr-x  1 pi pi  615 Feb 17 21:20 run.sh
-rwxr-xr-x  1 pi pi 4.1K Feb 17 21:20 screen-calendar-get.py
-rw-r--r--  1 pi pi  49K Mar  9 18:38 screen-output.png
-rw-r--r--  1 pi pi 112K Mar  9 18:38 screen-output-weather.svg
-rw-r--r--  1 pi pi 112K Feb 17 21:20 screen-template.svg
-rw-r--r--  1 pi pi 6.6K Feb 17 21:20 screen-weather-get.py
-rw-r--r--  1 pi pi  746 Mar  9 17:55 token.pickle
-rw-r--r--  1 pi pi  993 Feb 17 21:20 utility.py
mendhak commented 3 years ago

@Maquis90 When you call screen-calendar-get.py on its own, it must be defaulting to the "primary" calendar, as it's picking the default value. When you run it with run.sh it's reading from env.sh first.

My guess is that the value set in env.sh for GOOGLE_CALENDAR_ID isn't right, or isn't correctly formatted.

Can you re-copy-paste the Calendar ID from Google Calendar into your env.sh. Here's what mine looks like, I'm obscuring the first part.

export GOOGLE_CALENDAR_ID=xxxxx99999999999@group.calendar.google.com

I was able to reproduce the 404 problem by changing random letters in the Google Calendar ID to one that didn't exist.

Maquis90 commented 3 years ago

Seems like my calendar ID was the problem: export GOOGLE_CALENDAR_ID=xxxxx99999999999@group.calendar.google.com In the past I had errors because of the @ so I encoded it with %40 . Doesn't seem to be an issue now. Thank you for your help :)

danwooller commented 3 years ago

I sorted my problem, I wasn't putting bunny ears around the curl url. Works like a dream now, thanks.