Google Calendar on your Yocto-MaxiDisplay

Google Calendar on your Yocto-MaxiDisplay

Some time ago, we found a post where someone had built a device showing his schedule on his office door using Google Calendar. We liked the idea and, this week, we are going to show you how to display your appointments of the day on your fridge door using a Yocto-MaxiDisplay and a YoctoHub-Wireless-SR.



To display the day's events on a Yocto-MaxiDisplay, you must start by retrieving these events from Google Calendar. To do so, you need to authenticate yourself with Google, following the OAuth2 protocol. This protocol is far from trivial, particularly if you are not used to developing web applications. In order for this post to remain at an appropriate size, we are going to concentrate only on the inner workings and on the setup of our example on a web server. But if you wish to know more details on OAuth2, we have written another post explaining how it works.

We are going to use three PHP scripts:

  • An index.php configuration script which the user can view. This scripts negotiates access tokens with Google (using OAuth2) and saves them in a database.
  • A callback.php script called by the YoctoHub-Wifi-SR. This script uses tokens (previously saved by the configuration script). It then questions the Google servers to retrieve the events to be displayed on the Yocto-MaxiDisplay.
  • A common.php script containing functions used by the two preceding scripts. Database access functions are located in this file.


The user and the YoctoHub do not connect themselves on the same script
The user and the YoctoHub do not connect themselves on the same script



Google Developers Console


Before anything else, we must go to the "Developers Console" and create a new project. In the "APIs" section, we must activate the Calendar API so that our web application can access the user's calendar.

We must then generate several keys in order for our application to access Google services. We must create a developer key ("Public API access key"). We must make sure to select "Server key" when creating this key as it is the PHP script hosted on the web server (and not the module or the browser) that is going to contact the Google services.

Then we must create the OAuth keys ("Client ID"). When creating these keys, we must select "Web application" and provide the web server domain name as well as the URL of the script to be used if the authentication is successful. In our case, all the requests come from http://www.yoctopuce.com and if authentication is successful, we must run http://www.yoctopuce.com/google/index.php.

All the necessary keys are available in the API section.
All the necessary keys are available in the API section.



Installing the libraries


For this project, we naturally need the Yoctopuce library available on our website or on GitHub. But we also need the Google API Client library available on GitHub (https://github.com/google/google-api-php-client.git). In PHP, we only need to copy the source files on our web server in a location that the three scripts can use.

Installing the project


It is important that we copy the three files on this project in the directory that we provided in the Google console. In our example, we must copy these three files in the /google directory because we said that our script was available with the http://www.yoctopuce.com/google/index.php URL.

We must edit the common.php file and modify the constants at the beginning of the file. We must update the DB_NAME, DB_USER, and DB_PASS constants with the parameters of our database. We must update the GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, and GOOGLE_REDIRECT_URI constants with the keys generated in the Google Developer console. Finally, YOCTO_DISPLAY_SERIAL must correspond to the serial number of our Yocto-MaxiDisplay.

define('DB_NAME', 'XXXXXXXXX');
define('DB_USER', 'XXXXXXXXX');
define('DB_PASS', 'XXXXXXXXX');
define('GOOGLE_CLIENT_ID', 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX');
define('GOOGLE_CLIENT_SECRET', 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXX');
define('GOOGLE_REDIRECT_URI', 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX');
define('YOCTO_DISPLAY_SERIAL',"YD128X64-XXXXX");



We must also configure the YoctoHub-Wireless-SR so that it connects itself to our http://www.yoctopuce.com/google/callback.php callback. If you have never used HTTP callbacks with our products, have a look at this post which explains the process in details.

Updating the Yocto-MaxiDisplay


We are not going to detail each line of code because this post is long enough as it is. We are going to concentrate only on the part displaying the events on the Yocto-MaxiDisplay.

// create an array with all connected displays
$display = YDisplay::FirstDisplay();
// iterate on all displays connected to the Hub
while ($display) {
  // get the display serial number
  $module = $display->module();
  $serial = $module->get_serialNumber();
  $events = getEventsFromSerial($serial);
  if ($events) {
    OutputMaxiDisplay($display, $events);
  } else {
    error2YDisplay($display, "Not registered");
  }
  // look if we get another display connected
  $display = $display->nextDisplay();
}



The OutputMaxiDisplay function takes as parameters a YDisplay object and an array of events to be displayed. We divide the screen into only five lines of text so that the events can be read from far enough. Each text line is drawn with the drawText method using an ALIGN_TOP_LEFT anchoring. Which means that the text is displayed below and to the right of the X and Y coordinates. The first line contains the date of the first event (starting with "Today:" if it's today). Then we display as many events as possible.

A Yocto-MaxiDisplay follows the principle of superposed and independent layers. You can write and draw independently in each of the five layers. A trick to avoid flickering when refreshing the screen: we draw the new version on layer 0 (which is hidden by layers 1, 2, 3, and 4). When we are done drawing the layer, we request the screen to swap the content of layer 1 with that of layer 0 with the swapLayerContent method. In this way, the screen never displays an incomplete layer.

function OutputMaxiDisplay($display, $events)
{
  $layer0 = $display->get_displayLayer(0);
  $layer0->clear();
  $h = $display->get_displayHeight();
  $w = $display->get_displayWidth();
  $layer0->selectGrayPen(0);
  $layer0->drawBar(0,0,$w-1,$h-1);
  $layer0->selectGrayPen(255);
  $nblines = 5;
  $line_height = $h / $nblines;
  $ev_pos = 0;
  $today = date('D j M:', $events[0]['when']);
  $last_day="";
  for($i =0; $i < $nblines; $i++) {
    $y =$line_height * $i;
    $day = date('D j M:', $events[$ev_pos]['when']);
    if ($last_day!=$day) {
      if ($i==$nblines-1){
        // do not display day header if it's the last line
        break;
      }
      $last_day = $day;
      if ($day==$today)
        $day="TODAY: ".$day;
      $layer0->drawBar(0,$y+8,$w-1,$y+8);
      $layer0->drawText(2, $y,
                YDisplayLayer::ALIGN_TOP_LEFT,
                $day);
    } else{
      $layer0->drawText(10, $y,
                YDisplayLayer::ALIGN_TOP_LEFT,
                $events[$ev_pos]['what']);
      $ev_pos++;
    }
  }
  $display->swapLayerContent(0,1);
}



As usual, the code is available on GitHub and you can send us an email if there are parts that you don't understand.

Conclusion

And here is a connected calendar
And here is a connected calendar



The only difficulty in this project is the OAuth 2.0 authentication. This authentication mechanism is very cunning, and it forces us to use a PHP script for the user and another one for the hub (plus another one to avoid writing twice the same functions). Apart from this, thanks to the Yocto-MaxiDisplay layer system, it is very easy to display the events on the screen.




1 - deleted deleled Saturday,february 06,2016 7H28

Hello, I am making a web app using Google Calendar API and I encountered this well-explained post about OAuth2 in Google Calendar API at below link, after searching for clarifying my understanding of OAuth mechanism.
https://www.yoctopuce.com/EN/interactive/OAuth2/

I read all documentations about Google API but still getting confused about one thing.

I understood to store refresh tokens into my database to get a new access token after the old access token got expired. and the limit of the number of refresh tokens is 25 per visitor who wants to use my web app with the authentication.

at this point, when I save the refresh token into my database, of course I need the visitor's information to clarify which refresh token is for which visitor. so I need at least "visitor_id", "refresh token" column in my database.

but how can I get this "visitor_id"?

2 - seb (Yocto-Team)Monday,february 08,2016 16H08

@Takebayashi : In your application you need a way to bind the user to his corresponding access token.In our examples we use the serial number of the display to identify the user. Our table has one record per user which contain the serial number of the display, the access token and the refresh token.

I guess that in your web application you have a way to identify each user (with a user/password) So you have to save the access token and the refresh token in the same table.

Yoctopuce, get your stuff connected.