<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Gaugette</title>
    <link>//guy.carpenter.id.au/gaugette/categories/python/index.xml</link>
    <description>Recent content on Gaugette</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <atom:link href="//guy.carpenter.id.au/gaugette/categories/python/index.xml" rel="self" type="application/rss+xml" />
    
    <item>
      <title>Google OAuth2 for Devices Revisited</title>
      <link>//guy.carpenter.id.au/gaugette/2017/01/01/google-oauth2-for-devices-revisited/</link>
      <pubDate>Sun, 01 Jan 2017 13:03:00 +1000</pubDate>
      
      <guid>//guy.carpenter.id.au/gaugette/2017/01/01/google-oauth2-for-devices-revisited/</guid>
      <description>&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2012-11-06/oauth-2-sm.png&#34;  class=&#34;right&#34;   /&gt;


&lt;p&gt;I just dusted off an old project that uses
&lt;a href=&#34;https://developers.google.com/identity/protocols/OAuth2ForDevices&#34; target=&#34;_blank&#34;&gt;Google&amp;rsquo;s OAuth 2.0 for Devices&lt;/a&gt; API to
authenticate against Google Docs, and cleaned up my implementation.&lt;/p&gt;

&lt;p&gt;OAuth2ForDevices is really useful for IoT projects
that use Google APIs.  I&amp;rsquo;m using it for a device that records data directly a Google Sheet.&lt;/p&gt;

&lt;p&gt;While the API itself is pretty straight forward, getting the implementation 100%
battle-hardened takes a bit of work and iteration, so I&amp;rsquo;ll share here what I&amp;rsquo;ve learned.
If you are coding in Python, you might find the OAuth class in the
 &lt;a href=&#34;https://github.com/guyc/py-gaugette&#34; target=&#34;_blank&#34;&gt;py-gaugette&lt;/a&gt; library useful.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h2 id=&#34;theory-of-operation&#34;&gt;Theory of operation&lt;/h2&gt;

&lt;h3 id=&#34;first-boot-oauth2-flow&#34;&gt;First-Boot OAuth2 Flow&lt;/h3&gt;

&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2017-01-01/deviceflow.png&#34;  class=&#34;right&#34;   /&gt;


&lt;p&gt;The first time a device boots, it needs to request permissions from the user to access
Google Docs.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;call the OAuth2 API to specify the permissions required and request an authorisation code.&lt;/li&gt;
&lt;li&gt;show the auth code to the user&lt;/li&gt;
&lt;li&gt;poll the OAuth2 API waiting for confirmation that the user has granted access to the device.&lt;/li&gt;
&lt;li&gt;save the refresh token in persistent storage for next startup.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To confirm access, the user uses a web browser on a separate device, and navigates to
&lt;a href=&#34;https://www.google.com/device&#34; target=&#34;_blank&#34;&gt;https://www.google.com/device&lt;/a&gt; to enter the authorisation code.&lt;br /&gt;
The user must be logged in to a Google account when they confirm the permissions, and the
device will be granted access on behalf of that account.  The level of access is determined
by the scope parameters passed by the device, and the user will be shown which permissions
have been requested before they confirm.&lt;/p&gt;

&lt;h3 id=&#34;after-the-first-boot&#34;&gt;After the First Boot&lt;/h3&gt;

&lt;p&gt;On subsequent boots the device can use the saved refresh token to authenticate, so
no further user interaction is required.&lt;/p&gt;

&lt;h2 id=&#34;here-s-what-it-looks-like&#34;&gt;Here&amp;rsquo;s What It Looks Like&lt;/h2&gt;

&lt;h3 id=&#34;1-the-device-presents-a-code&#34;&gt;1. The Device Presents a Code&lt;/h3&gt;

&lt;p&gt;On my time clock, I display the code on the one-line OLED display.  The device code can be quite long - the API docs
recommend ensuring you can display 15 &amp;lsquo;W&amp;rsquo;-sized characters, although current codes are formatted as XXXX-XXXX.  The length of generated codes
has increased since I first started using this API and I now need to use horizontal scrolling to
display the entire code.&lt;/p&gt;

&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2017-01-01/device-auth.png&#34;   /&gt;


&lt;h3 id=&#34;2-the-user-enters-the-code&#34;&gt;2. The User Enters the Code&lt;/h3&gt;

&lt;p&gt;You need to communicate the URL (&lt;a href=&#34;https://www.google.com/device&#34; target=&#34;_blank&#34;&gt;https://www.google.com/device&lt;/a&gt;) to the user somehow.&lt;br /&gt;
This is the web page they will see.  They may first be prompted to log in to their
Google account or select from multiple logged in accounts.&lt;/p&gt;

&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2017-01-01/oauth_1.png&#34;   /&gt;


&lt;h3 id=&#34;3-the-user-confirms-access&#34;&gt;3. The User Confirms Access&lt;/h3&gt;

&lt;p&gt;The permissions listed here are determined by the scope variables you have passed.  The list of
available scopes is &lt;a href=&#34;https://developers.google.com/identity/protocols/googlescopes&#34; target=&#34;_blank&#34;&gt;defined here&lt;/a&gt;.&lt;/p&gt;

&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2017-01-01/oauth_2.png&#34;   /&gt;


&lt;h2 id=&#34;on-the-device&#34;&gt;On the Device&lt;/h2&gt;

&lt;p&gt;Here&amp;rsquo;s what it looks like on the device.&lt;/p&gt;


&lt;div style=&#34;position: relative; padding-bottom: 56.25%; padding-top: 30px; height: 0; overflow: hidden;&#34;&gt;
  &lt;iframe src=&#34;//www.youtube.com/embed/tZ6XZ1yhHJM&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%;&#34; allowfullscreen frameborder=&#34;0&#34;&gt;&lt;/iframe&gt;
 &lt;/div&gt;


&lt;h2 id=&#34;making-api-calls-with-oauth2-tokens&#34;&gt;Making API Calls With OAuth2 tokens&lt;/h2&gt;

&lt;p&gt;The most complicated aspect of this API is passing the credentials and handling
exceptions, and a lot has changed since I wrote the earlier Feeds implementation.  Now
I&amp;rsquo;m using the &lt;a href=&#34;https://developers.google.com/api-client-library/python/start/installation&#34; target=&#34;_blank&#34;&gt;Google API Client Libraries for Python&lt;/a&gt;
and passing in the token via a  &lt;a href=&#34;http://oauth2client.readthedocs.io/en/latest/source/oauth2client.client.html#oauth2client.client.GoogleCredentials&#34; target=&#34;_blank&#34;&gt;oauth2client.client.GoogleCredientials&lt;/a&gt;
instance.&lt;/p&gt;

&lt;p&gt;One nasty little surprise I discovered with long-running applications
is that after the device has idled for a long time (say 24 hours without making an API call) I start getting
BadStatusLine exceptions on all API calls.  To handle this and other errors,
I use @wrap from functools to wrap all of the API calls in a retry function.  This keeps
the extra complexity of error recovery nicely abstracted away.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>py-gaugette Gets a Refresh</title>
      <link>//guy.carpenter.id.au/gaugette/2016/11/12/py-gaugette-gets-a-refresh/</link>
      <pubDate>Sat, 12 Nov 2016 14:39:00 +1000</pubDate>
      
      <guid>//guy.carpenter.id.au/gaugette/2016/11/12/py-gaugette-gets-a-refresh/</guid>
      <description>

&lt;p&gt;I&amp;rsquo;ve made some major changes to the py-gaugette library to address
several issues that have accumulated over time, namely:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;added interrupt-driven option to rotary encoder&lt;/li&gt;
&lt;li&gt;fully Python 3 compatible&lt;/li&gt;
&lt;li&gt;works with current version of Py-WiringPi&lt;/li&gt;
&lt;li&gt;uses dependency injection for GPIO and SPI interfaces&lt;/li&gt;
&lt;li&gt;updated Google Sheets code to use new API&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;dependency-injection-for-gpio-and-spi&#34;&gt;Dependency Injection for GPIO and SPI&lt;/h2&gt;

&lt;p&gt;Classes that interact with the GPIO or SPI interfaces now take
an instance of that interface as a parameter to the constructor.
This avoids the issue of having multiple classes trying to initialise
the GPIO library, and makes it easy to pass alternative interface
implementations.&lt;/p&gt;

&lt;h2 id=&#34;interrupts-for-rotary-encoders&#34;&gt;Interrupts for Rotary Encoders&lt;/h2&gt;

&lt;p&gt;The original implementation of the rotary encoder library used polling.
On the Raspberry Pi it now supports interrupts.  The previous polling
behaviour is still supported.&lt;/p&gt;

&lt;h2 id=&#34;fully-python-3-compatible&#34;&gt;Fully Python 3 Compatible&lt;/h2&gt;

&lt;p&gt;While the library has been mostly Python 3 compatible, there were a few
exceptions.  In particular the SSD1306 class depended heavily on the Python 2
behaviour of the division operator, which changed in Python 3.  I&amp;rsquo;ve rewritten
the calculations to mostly use bit shifts rather than division.&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>