Go to content Go to menu

cli_mirror.jpgGoogle’s Mirror API is, beside native GDK apps, one way to communicate with Google Glass. It is based on a range of OAuth authenticated web-service methods. The default way to use the Mirror API is to present the user a Web application where he could first register his Glass using a Google account. After this step the app or service is able to send info’s like text messages, contacts, images etc. to the users Glass device. But what if you just want to make a quick test and don’t want to develop even a simple web app or you need a way to quickly send info’s from a cron job every hour?
This is where cli_mirror comes in handy.

The cli_mirror utility is based on node.js and provides some Mirror API functions via the command line. It also shows how to authenticate a user via OAuth without the need of a web app and also how the get started with Google Glass Mirror development in general.

Prerequisites

Of course you will need a Google Glass *, a Google account and you must configure some parameters first. To use cli_mirror you must create a project in the Google Developer Console. In case you are one of the lucky ones with a physical device you can start right away.
 
*) If you don’t have a Glass lying on the table in front of you not everything is lost. I will show you how to use the Google Mirror API Playground which simulates a Google Glass and allows you to play with cli_mirror.

Follow these steps to get started:

Download and install

Install cli_mirror from https://npmjs.org/package/cli_mirror. You will need node.js and npm installed if you have not already done so. Execute

c:/somepath> npm -g install cli_mirror

to install cli_mirror and all required node modules.

Creating a Google API project

  1. Navigate to https://cloud.google.com/console/project with your web browser and create a Project on the Google Developer Console
    GoogleDevelopersConsole-1.png GoogleDevelopersConsole-2.png
     

  2. Under APIs enable the Google Mirror API
    GoogleDevelopersConsole-3.png
     

  3. Create a Client ID for native applications under Credentials
    GoogleDevelopersConsole-4.png
     

  4. Click Download JSON and save the file locally
    GoogleDevelopersConsole-5.png
     

  5. Ensure that you have set Email address and Product name for the consent screen
    GoogleDevelopersConsole-6.png
     

  6. Place the JSON file from step 4 into the cli_mirror root directory and name it config.json.

 

Preparing the Google Mirror API Playground

  1. Goto the Mirror API Playground and follow these steps (copied from the bottom of the playground page where they are hidden behind the Show Playground usage information button):
    GlassPlayground-1.png
     
  2. Enter the client id to allow playground to access your timeline
    GlassPlayground-2.png
     
  3. Congratulations. You now have your virtual Glass. In the playground its possible to try out content and styling but also to watch your timeline which is updated by cli_mirror.
    GlassPlayground-3.png
     

Registering cli_mirror with a Google account

Now you are ready to use cli_mirror. The first time you use it you must grant cli_mirror access to a Google account. This is done using OAuth and is normally done using a web app which provides the user a GUI to perform this. cli_mirror’s only GUI is the console so the first time you run cli_mirror for a Glass for which cli_mirror has no OAuth tokens (or if you use the command line option -r, –register) perform the following steps:
 

  1. You will be prompted by cli_mirror to use your webbrowser to navigate to the shown url. cli_mirror tries to open a browser to the shown url automatically.
    GlassOAuth-1.png
     

  2. If you are not logged into your Google account you have to log in. A logged in user will be presented with info’s about the app (these are info’s you have entered in the Google Developer console earlier) and the permission the app requests. If you want to authenticate more than one Glass (see the -o command line parameter) be sure to be not logged in to any Google account because otherwise you will authenticate against the currently logged in Google account.
    GlassOAuth-2.png GlassOAuth-3.png
     

  3. After granting the requesting permissions the user will either be redirected to a configured URL or will be shown an info screen with a code. In case you have not used urn:ietf:wg:oauth:2.0:oob as callback Google tries to redirect the user to the configured URL appending a code= query parameter. Either way. Copy the code and enter it at the cli_mirror prompt.
    GlassOAuth-4.png GlassOAuth-4-1.png
     
    GlassOAuth-5.png
     

 
If all goes well you will find a file named like the Glass name you have specified with the -o parameter (or default.json if you dont have specified -o) in the ./glasses subdirectory of cli_mirror’s root directory which will contain the OAuth credentials for any further requests you will send to this Glass using cli_mirror.

Using cli_mirror

cli_mirror is started on the command line with one or more command line parameters. It displays additional info’s on the console while running. Error and success are reported back also as return codes where 0 means OK and 1 means ERROR.

cli_mirror takes the following command line arguments:

USAGE: node cli_mirror.js [OPTIONS] , where OPTIONS are:
  -h, --help                                    Shows this help infos
  -v, --verbose                                 Verbose debug output
  -q, --quiet                                   Don't show any output
  -o, --glassid <ARG1>                          Specify which Google Glass to communicate with.
  -l, --list                                    List active timeline (no deleted entries)
  -L, --listids                                 List active timeline (no deleted entries) as id list
  -d, --delete <ARG1>                           Delete timeline entry with ID
  -D, --deleteall                               Delete ALL entries in the timeline
  -g, --get <ARG1>                              Get timeline entry with ID
  -i, --insert <ARG1> <ARG2>                    Insert text timeline content and optional attachment
                                                (use - for no attachment)
  -I, --insertJson <ARG1> <ARG2>                Insert JSON timeline object and optional attachment
                                                (use - for no attachment)
  -u, --update <ARG1> <ARG2> <ARG3>              Update text timeline content and optional attachment
  -U, --updateJson <ARG1> <ARG2> <ARG3>          Update JSON timeline object and optional attachment
                                                (use - for no attachment)
  -p, --position <ARG1> <ARG2> <ARG3> <ARG4>    Attach a position (LAT LON Marker Zoom) as Google Map

-h

shows a short help information as shown above and exits.

-v

Outputs additional (debug) information’s.

-q

Be quiet. Does not output anything except data retrieved from Googles services. This can be useful when data should be piped to other utilities.

-o GlassID

Specifies the Google Glass to communicate with. cli_mirror is capable to communicate with any number of Google Glass devices. Each Glass belongs to a Google account. The corresponding OAuth information’s are stored in the ./glasses subdirectory of cli_mirrors root directory as JSON files. -o requires a unique id/name to identify a Glass. This id/name can be any name you want. If you don’t specify -o a Glass named default will be used.

-l

List all current active entries in the Glass timeline formatted as JSON.

-L

List all current active entries in the Glass timeline but only outputs a list of entry ID’s.

-d TimelineID

Deletes the entry with the given timeline id from the Glass timeline.

-D

Deletes ALL entries from the Glass timeline.

-g TimelinieID

Retrieves the timeline entry with the given id.

-i Content <Attachment>

Inserts simple text content on top of the Glass timeline including an optionally attachment file (e.g. image). If there is no attachment you must specify - (minus) as the attachment name.

-I JSON <Attachment>

Inserts a JSON object into the timeline which conforms to Mirror API insert including an optionally attachment file (e.g. image). If there is no attachment you must specify - (minus) as the attachment name. You can either specify the JSON content on the command line which could be problematic in case of special shell characters like > which must be quoted. To make things simple you can place the JSON content into a file and specify the name of the file instead prefixed by an @ (AT) character. cli_mirror will then send the content of this file.

-p Lat Lon <Marker> <Zoom>

You can send a map for a given position specified as latitude and longitude and attach it to a timeline entry. To do this specify NO attachment when inserting a timeline entry using either -i or -I and add -p instead. Marker, and Zoom are optional and can be - (minus) instead. Marker is a string which first character will be used to label a Placemark. Zoom ranges from 0 to 19 and specifies the zoom level of the generated map.

-u EntryID Content <Attachment>

Works the same like -i but updates an existing timeline entry specified by EntryID.

-U EntryID Content <Attachment>

Works the same like -I but updates an existing timeline entry specified by EntryID.

Examples

First insert a simple text message without and with image as attachment into the timeline:

C:/glass_node> cli_mirror -i "Hello World" -

GlassText.png

C:/glass_node> cli_mirror -i "I am an attachment" ./examples/ColorBars.png

[INF] Existing Google OAuth tokens available for Google Glass (default)
[INF] Inserting timeline entry
[OK ] a186fe22-1945-4714-9484-b10ec68f2fcb
[OK ] cli_mirror completed

This looks like this in the timeline:
GlassAttachment.png

Now lets list the contents of the timeline as JSON object:

C:/glass_node> cli_mirror -l

[INF] Existing Google OAuth tokens available for Google Glass (default)
[OK ] Glass timeline:
{
  "kind": "mirror#timeline",
  "nextPageToken": "CrIBCqQBwnQ9lsY3sAD__wAA_wG4k56MjNGKjJqN18nGxsnIzsjJ
      zcnPydbRlouaktfKmZ2by5vKztKensua0suby87Sxp3MmtKcmsvNxseemp6ezJzW_wD-
      __73zxCU9__v__1HbGFzcy51c2VyKDY5OTY3MTc2MjYwNikuaXRlbSg1ZmJkNGQ1MS1h
      YTRlLTRkNDEtOWIzZS1jZTQyOThhZWFhM2MpAAEQCiEYPPZ5rZNisCAA8ISVfAE=",
  "items": [
    {
      "kind": "mirror#timelineItem",
      "id": "a186fe22-1945-4714-9484-b10ec68f2fcb",
      "selfLink": "https://www.googleapis.com/mirror/v1/timeline/
          a186fe22-1945-4714-9484-b10ec68f2fcb",
      "created": "2014-01-28T15:25:42.269Z",
      "updated": "2014-01-28T15:25:42.269Z",
      "etag": "1390922742269",
      "text": "I am a test",
      "attachments": [
        {
          "id": "bs:2b9c9722-756a-4039-8d9d-d4d05a797eff",
          "contentType": "image/png"
        }
      ],
      "menuItems": [
        {
          "action": "DELETE"
        }
      ]
    }
  ]
}
[OK ] Glass API completed

C:/glass_node>

Or just as list of ID’s without additional info’s:

C:/glass_node> cli_mirror -L -q

a186fe22-1945-4714-9484-b10ec68f2fcb

C:/glass_node>

Get a specific entry in the timeline:

C:/glass_node> cli_mirror -g a186fe22-1945-4714-9484-b10ec68f2fcb

[INF] Existing Google OAuth tokens available for Google Glass (default)
[INF] Reading timeline entry:
a186fe22-1945-4714-9484-b10ec68f2fcb
[OK ] Timeline entry
{ kind: 'mirror#timelineItem',
  id: 'a186fe22-1945-4714-9484-b10ec68f2fcb',
  selfLink: 'https://www.googleapis.com/mirror/v1/timeline/
      a186fe22-1945-4714-9484-b10ec68f2fcb',
  created: '2014-01-28T15:25:42.269Z',
  updated: '2014-01-28T15:25:42.269Z',
  etag: '1390922742269',
  text: 'I am a test 2',
  attachments:
   [ { id: 'bs:2b9c9722-756a-4039-8d9d-d4d05a797eff',
       contentType: 'image/png',
       contentUrl: 'https://www.googleapis.com/mirror/v1/timeline/
           a186fe22-1945-4714-9484-b10ec68f2fcb/attachments/
           bs:2b9c9722-756a-4039-8d9d-d4d05a797eff?alt=media' } ],
  menuItems: [ { action: 'DELETE' } ] }
[OK ] Glass API completed

C:/glass_node>

Now delete an entry from the timeline:

C:/glass_node> cli_mirror -d a186fe22-1945-4714-9484-b10ec68f2fcb

[INF] Existing Google OAuth tokens available for Google Glass (default)
[INF] Delete timeline entry:
a186fe22-1945-4714-9484-b10ec68f2fcb
[OK ] Timeline entry deleted
[OK ] Glass API completed

C:/glass_node>

Add a timeline entry with a position map attachment for position 48.209117 16.369522 including a Placemark labeled ‘X’ at zoom level 10:

C:/glass_node> cli_mirror -i "I am a map" - -p 48.209117 16.369522 X 10

[INF] Existing Google OAuth tokens available for Google Glass (default)
[INF] Inserting timeline entry
[INF] Using generated map image as attachment
[OK ] Map image successfully generated
[OK ] Timeline entry ID
e6426f53-df2c-4028-9096-2bd88ba6e133
[OK ] cli_mirror completed

C:/glass_node>

This will produce the following timeline entry
GlassMap.png