Introduction: Make an Intelligent Desk Clock, Written in JavaScript, Powered by the Intel Edison

About: Technologist & Educator.

Why my clocks need to be more intelligent...

I always set up reminders for my calendar meetings but when that little "XYZ meeting starting in 15 minutes" desktop notification pops up in the corner of my computer screen I hit the Snooze or Close button. "15 minutes is enough time to get one more thing done," I think to myself and get back to work. 20 minutes later, I snap out of it and realize that I'm late!

Other times, I stress about an upcoming meeting. Every minute I will double-check the time on the clock, then double-check the event start time, and then I have to figure out myself how long it is until the event... The worry of being late occupies my mind so I don't get any work done. :(

I could surround myself with clocks but most clocks are pretty "dumb" objects. They show you time and that's it. But with a little IoT magic, it's possible to make dumb things smart.

What can I do about this?

Imagine if you will, a smart clock that automatically checks for your next calendar event.

When the clock knows an event is coming up, it automatically gives you a contextual countdown to the event start time (e.g. "45 minutes to your meeting" vs. "Meeting starts at 4pm"). And as the event start time draws closer, the clock gently alerts you to the urgency of when you need to get moving by changing colour. (e.g. Yellow means "be mellow", orange means "get on it", and red means "danger zone".)

Well, don't imagine. Make it today!

In this Instructables, I'll show you how to turn an Intel Edison and a Grove LCD into a smart desk clock that fetches events using the Google Calendar API. The smart clock application is written as a NodeJS application (JavaScript code here on Github) and uses the Intel XDK for IoT for uploading files and running the IoT app.

Step 1: Gather All of the Materials

To make an "Intel-ligent Clock", you will need:

To program your Intel Edison, you will need:

  • A computer.
    • Any OS will do (Mac/Windows/Linux) but I'll be showing the examples on a Mac.
  • The Intel XDK for IoT IDE installed on your computer.
    • I'll be using the Intel XDK since the code for this application was written in JavaScript for NodeJS.
  • A micro-USB cable.
    • To be used when running shell commands and configuring WiFi directly on your Intel Edison.
      (Note: If your Intel Edison is already configured to connect to Wi-Fi, you don't need this extra cable.)

(*Note: The code for this project will also work on an Intel Galileo. If you use an Intel Galileo, get your board online using wired ethernet or a WiFi card.)

Step 2: Configure Wi-Fi on Your Edison

Your Intel Edison needs to be online in order to be wirelessly programmable from the Intel XDK and to make calls to the Google Calendar API.

If your Intel Edison is not already configured to connect to your WiFi hotspot, follow the steps below:

1. Gain shell access of your Intel Edison

Instructions for Mac:

(Written documentation)

Instructions for Windows:

(Written documentation)

2. Run the "configure_edison --wifi" command

Video: https://docs.google.com/a/karma-laboratory.com/file/d/0B2ywC78pxngCS2c3TndOT2EtT0k/preview

(Written documentation)

Step 3: Set Up Intel XDK for IoT

If you don't have the Intel XDK for IoT already installed, download and install this IDE from https://software.intel.com/en-us/html5/xdk-iot.

If you need further help installing the Intel XDK, follow the setup guide:

To confirm that the Intel XDK can program your Intel Edison, run a sample project to blink the onboard LED:

Step 4: Assemble the Grove Shield Onto the Arduino Expansion Board for the Intel Edison

  1. Unplug the Arduino expansion board from all power.
  2. Install the Grove Base Shield onto the Intel Edison by lining up all the pins and firmly inserting the shield into the expansion board.
  3. Connect a Grove 4-pin connector wire to the Grove LCD.
  4. Connect the other end of the Grove wire to the Grove Base Shield. You must use one of the slots labelled "I2C".
  5. Power the board back on.

Step 5: Enable the Google Calendar API

Learn how to set up the Google Calendar API by going through the Node Quickstart guide on the Google Developers site: https://developers.google.com/google-apps/calendar/quickstart/node.

I recorded a video walkthrough of this process that you can watch on here:

After going through the Quickstart Guide you should have:

  • A Google Calendar API project (perhaps called "smart-clock") enabled in the Google Developer Console.
  • A client_secret.json file.
  • A NodeJS script that will print out your next 10 calendar events to the console.

Step 6: Port the Google Calendar API Node Quickstart Code to the Edison

The Intel Edison is a Linux-based microcontroller so porting Node scripts that work on your desktop to the Intel Edison can be done with only minimal edits.

I recorded a video walkthrough of this process that you can watch on here:

  1. In the Intel XDK for IoT: Start a new project > Import Your Node.js Project
    • Use the folder from the previous step (the one that you have quickstart.js in).
    • Give your project a name like "smart-clock".
  2. Create a package.json file.
  3. Delete the node_modules folder (and its contents) from your project folder.
    • It's way too big for the Intel XDK to copy over to the board wirelessly and will timeout. We'll install the Node libraries directly on the board in a later step.
  4. Create a main.js file.
  5. Make sure any files you have created have been saved.
  6. Connect to your board in the IoT Device dropdown, if you're not already connected.
  7. Click the "Manage your daemon/IoT device" button from the bottom toolbar.
    • Click "Sync PC time w/clock on target device"
    • Check "Run npm install directly on IoT Device" (this will use the dependencies defined in package.json)
  8. Click the "Upload" button from the bottom toolbar.
  9. Click the "Build" button next to "Upload" in the bottom toolbar.
  10. Use the SSH Terminal tab (wireless connection) or the Serial Terminal tab (micro-USB connection) to connect to your board.
  11. Type: "cd /node_app_slot". This is where the Intel XDK copies over any project files.
  12. Run your main.js Node script from here: "node main.js"
  13. Follow the prompts to get your token and past it back into the terminal command line.
  14. If you see your next 10 calendar events outputted, your Intel Edison has successfully communicated with the Google Calendar API wirelessly!
  15. Now try running the Node app from the Intel XDK instead of executing "node main.js". Click the "Run" button from the bottom toolbar.
  16. You will see an error message: "Error loading client secret file". This is because the Intel XDK runs applications from outside of the context of the project folder.
  17. In main.js, make the edits below, save the file, then click the "Run" button again. You should see your next 10 calendar events.
// add this line at the top:
var SECRET_FILE = '/node_app_slot/client_secret.json';

// edit this line (around line 13-14)
// fs.readFile('client_secret.json', function processClientSecrets(err, content) {
// to be:
fs.readFile(SECRET_FILE, function processClientSecrets(err, content) {

Congrats!!

In the next step, add in support for the LCD screen.

Step 7: Import the MRAA and UPM LCD Libraries

Enough acronyms for you? ;)

MRAA is a low level C++ library that allows the Linux (software) side of the Edison to communicate for the general input/out pins (hardware) side of the Edison. Intel maintains the mraa library on Github here: https://github.com/intel-iot-devkit/mraa.

For example, to turn an LED connected to pin 13 on, you would use MRAA like this:

var mraa = require('mraa');
var led = new mraa.Gpio(13);
led.dir(mraa.DIR_OUT);
led.write(1);

UPM is a higher level library that uses MRAA to simplify working with off-the-shelf electronics components that require more than simple on/off commands like the LED example above. To get an LCD screen to show text, you need to send over some very exactly timed electrical bleeps and bloops so that extra work gets bundled up into individual UPM libraries. Intel maintains the UPM libraries on Github here: https://github.com/intel-iot-devkit/upm.

(LCD stands for Liquid Crystal Display. If you're interested in what goes into an LCD screen, watch "Building a liquid crystal display" on YouTube.)

For the Grove LCD component (Jhd1313m1), you would still include the MRAA library as above, in addition to using the individual UPM I2C LCD library like this:

var mraa = require('mraa');
var jsUpmI2cLcd = require ('jsupm_i2clcd');

// Initialize the LCD.
// The 1st param is the BUS ID:
//   Intel Edison: Use 6
//   Intel Galileo Gen 2: Use 6 (I think)
//   Intel Galileo Gen 1: Use 0
var lcd = new jsUpmI2cLcd.Jhd1313m1(6, 0x3E, 0x62);

// Make the backlight red
lcd.setColor(255, 0, 0);

// Go to the 2nd row, 6th character (0-indexed)
// and print out "Hello!"
lcd.setCursor(1,5);
lcd.write('Hello!');

You can find more sensor sample code in the UPM examples folder on Github or the Intel IoT sensors page.

So at the top of your main.js file, you need this:

var mraa = require('mraa');
var jsUpmI2cLcd = require ('jsupm_i2clcd');
var lcd = new jsUpmI2cLcd.Jhd1313m1(6, 0x3E, 0x62);

Step 8: Add My LCD Text Helper Library

The UPM LCD library for JavaScript is fairly rudimentary. It only gives you commands to write text to the screen, clear the screen, and change the RGB backlight colour.

And if you try to write text that is more than 16 characters long, it gets truncated (goes off the screen).

In the case of the smart desk clock, it's likely that your calendar event names will be longer than 16 characters so I wrote a Node module to scroll the text in a row if it won't fit.

1. Download it from: https://github.com/pearlchen/iot-smart-desk-clock/blob/master/iot-version/lcd_text_helper.js.

2. Place lcd_text_helper.js in your project directory, next to main.js.

3. In main.js, include it alongside the UPM LCD library:

var jsUpmI2cLcd  = require ('jsupm_i2clcd');
var LcdTextHelper = require('./lcd_text_helper');
var lcd = new jsUpmI2cLcd.Jhd1313m1(6, 0x3E, 0x62);
var lcdText = new LcdTextHelper(lcd);

4. And use it like this:

/**
 * Try it out with some test messages.
 */
 
var LCD_MESSAGE_VERY_LONG = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvxyz"; // >16 characters long (48 chars)
var LCD_MESSAGE_LONG = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // >16 characters long (24 chars)
var LCD_MESSAGE_16CHAR = "1234567890ABCDEF"; // ==16 characters long
var LCD_MESSAGE_SHORT = "1234567890"; // <16 characters long (10 chars)
var LCD_MESSAGE_VERY_SHORT = "ABC"; // <16 characters long (3 chars)
 
lcdText.set([
  "  Hello,", 
  "        World!"
]);
 
setTimeout(function(){
  lcdText.set([
    LCD_MESSAGE_SHORT, 
    LCD_MESSAGE_VERY_SHORT
  ]);
}, 5000);
 
setTimeout(function(){
  lcdText.set([
    LCD_MESSAGE_LONG, 
    LCD_MESSAGE_VERY_LONG
  ]);
}, 10000);

Now that you have the basic (yet very impressive) ability to get text printed to an LCD screen, let's add some calendar logic to the code.

Step 9: Adding Final Calendar Event Logic

Have a look at the final code for main.js on Github. https://github.com/pearlchen/iot-smart-desk-clock/blob/master/iot-version/main.js.

One thing I did in the final version is move the Google Calendar API stuff out of main.js into its own Node module called GoogleCalendarEventFetcher.

1. Download it from: https://github.com/pearlchen/iot-smart-desk-clock/blob/master/iot-version/google_calendar_event_fetcher.js.

2. Place google_calendar_event_fetcher.js in your project directory, next to main.js.

3. In main.js, include it alongside the LCD Text Helper.

var LcdTextHelper = require('./lcd_text_helper');
var GoogleCalendarEventFetcher = require('./google_calendar_event_fetcher');

4. Use it like this:

// Initialize it
var calendar = new GoogleCalendarEventFetcher();
calendar.init(successCallback, optionalErrorDisplayCallback);

// Then, in the success callback:
calendar.getEvents(eventsReceivedCallback, MAX_EVENTS, beginTimeToQuery.toISOString(), endTimeToQuery.toISOString());

Step 10: Code Recap

If you got lost in code in Step 7 or 8: don't worry!

You can download the entire smart clock code from the Github repo, inside the "iot-version" folder: https://github.com/pearlchen/iot-smart-desk-clock/tree/master/iot-version.

Remember that you need to include your own client_secret.json which you should have gotten in Step 5.

Place these files in your Intel XDK project directory and, using the Intel XDK:

  1. Click the "Upload" button from the bottom toolbar.

  2. Click the "Run" button from the bottom toolbar.

  3. Check your Intel XDK console for any errors.

  4. Check the LCD screen of your clock!

Step 11: Build an Enclosure for Your Clock

To give your DIY smart clock some professionalism, make an enclosure for your Intel Edison and mount the LCD screen at an angle that you can easily see while sitting at your desk.

To make a simple cardboard enclosure for your smart clock, you'll need:

  • cardboard or very stiff card stock
  • tape and/or glue
  • exacto knife and/or scissors
  • ruler
  • T-square (not required but very useful)
  • sharpies for decorating

If you want to get extra fancy, consider 3D printing or laser cutting a clock case. At the moment, cardboard will do just fine as I continue to prototype and add features. This thing is literally held together with tape. ;)

I also added an Adafruit NeoPixel Ring for decoration. Eventually I'll hook it up to the Intel Edison but that will be in the future.

Step 12: Place the Clock on Your Desk

You're done!

The nice thing about using the Intel XDK to write your NodeJS-based IoT applications is that an app found in /node_app_slot will automatically be configured to autostart once the Intel Edison boots up.

So this means you just need to plug in the clock to a stable power supply via the power barrel jack and your clock will immediately connect to the Google Calendar API and keep an eye on your schedule for you!

Step 13: Next Steps

I hope you enjoyed this tutorial! Please let me know via the Instructables comments below or the Github repo issue tracker if you run into any bugs.

See the Github README for features on the "Intel-ligent Clock" roadmap: https://github.com/pearlchen/iot-smart-desk-clock#iot-smart-desk-clock

And if you end up making one yourself, post a photo!