Google Code offered in: English - Español - 日本語 - 한국어 - Português - Pусский - 中文(简体) - 中文(繁體)
Learn about the Google Wave Federation Protocol and get involved
The easiest way to understand how extensions work in Wave is to build a Wave robot. Robots are applications that interact with a Wave through the Wave protocol (HTTP interface). Currently, we only support robots hosted with Google App Engine. In the future, we will support any client architecture that implements the Wave protocol.
In this tutorial, we'll use the Python client library to develop a sample robot. (The concepts apply here equally well to users of the Java™ client library, though implementation details will be different.) In this brief tutorial, you will create a simple robot, upload it to App Engine, and see it working with Wave.
Before you get started, make sure you have Python 2.5 or higher installed on your system. You can determine if you have Python installed (and what version is installed) by executing the following command from the command line:
hostname$ python --version Python 2.6.2
You can download Python from the Python downloads page.
Development of Google Wave robots requires compiling with a client library. This tutorial uses the Wave Robot Python Client Library available on Google Project Hosting. This project contains the source code for the library itself at the following location:
Create a directory to hold your source code for your Python robot and
extract the Python client library into a waveapi directory
using the following svn command:
hostname$ svn checkout http://wave-robot-python-client.googlecode.com/svn/trunk/src/waveapi waveapi
This command will create a waveapi directory within your current
source code directory. Note that if you check out the code using the
HTTPS protocol and authenticate, you can contribute back to the open
source project directly.
You can develop Wave robots and other web applications for App Engine using your Python development tools. Before you continue, follow the instructions for installing the Python SDK in the App Engine Documentation.
You will also want to register your robot using an Application ID at https://appengine.google.com.. You are allowed to register up to 10 application IDs, and application registrations cannot be undone or deleted, nor can an application ID be changed after it is registered. If you wish to conserve your allotted application registrations, you may want to choose an application ID you know you will use for a future project. As well, you may wish to reserve one ID for testing purposes of your robots.
Go to the App Engine Administrator Console in your web browser. Sign in using your Google account, creating one if necessary. If you haven't used this account with App Engine before, you may also be prompted to verify your account using SMS and a mobile phone.
Under My Applications click the Create an Application button. Choose an application ID, and follow the prompts to complete the registration. The new application appears in the list. You can click its name to visit the Administrator Console for this application.
Once you have a valid application ID, create a new app.yaml
application specification within the root of your source directory with the
following content:
application: applicationName version: 1 runtime: python api_version: 1 handlers: - url: /_wave/.* script: applicationName.py - url: /assets static_dir: assets
You don't need to name your Python script to the same name as your application ID, though this is customary. We also specify a URL pattern to serve any static assets for the application, such as images, stylesheets, etc.
For more information on getting started with App Engine, see the App Engine Getting Started Guide for Python.
Now it's time to write our Python code. First create a *.py
file with the same name as you noted in your app.yaml file (e.g.
applicationName.py). Add the following code:
from waveapi import events
from waveapi import model
from waveapi import robot
def OnParticipantsChanged(properties, context):
"""Invoked when any participants have been added/removed."""
added = properties['participantsAdded']
for p in added:
Notify(context)
def OnRobotAdded(properties, context):
"""Invoked when the robot has been added."""
root_wavelet = context.GetRootWavelet()
root_wavelet.CreateBlip().GetDocument().SetText("I'm alive!")
def Notify(context):
root_wavelet = context.GetRootWavelet()
root_wavelet.CreateBlip().GetDocument().SetText("Hi everybody!")
if __name__ == '__main__':
myRobot = robot.Robot('appName',
image_url='http://appName.appspot.com/icon.png',
version='1',
profile_url='http://appName.appspot.com/')
myRobot.RegisterHandler(events.WAVELET_PARTICIPANTS_CHANGED, OnParticipantsChanged)
myRobot.RegisterHandler(events.WAVELET_SELF_ADDED, OnRobotAdded)
myRobot.Run()
We'll explain this code in the next sections.
To make a python application into a robot, we need
to include the Python robot library using the following import
statements:
from waveapi import events from waveapi import model from waveapi import robot
Once you have imported the proper libraries, define your main function. Note
that we do this at the bottom of the file, so that we can refer to defined
functions above the __main__ declaration.
if __name__ == '__main__':
myRobot = robot.Robot('appName',
image_url='http://appName.appspot.com/icon.png',
version='1',
profile_url='http://appName.appspot.com/')
myRobot.RegisterHandler(events.WAVELET_PARTICIPANTS_CHANGED, OnParticipantsChanged)
myRobot.RegisterHandler(events.WAVELET_SELF_ADDED, OnRobotAdded)
myRobot.Run()
This code simply defines a new robot with the given name, sets some
additional profile information, registers
a single event handler, telling the system we are interested in the
WAVELET_PARTICIPANTS_CHANGED and WAVELET_SELF_ADDED
events, and then runs the robot.
Note that the Robot() constructor implicitly defines the Robot's
Profile by assigning constructor arguments
to profile settings. The Robot's name, passed as the first argument, is assigned
as the Robot profile's name property, for example. An
image passed within image_url will be used as the Robot's
avatar, while profile_url specifies a URL which explains
the purpose and usage of the robot.
We want to use the WAVELET_SELF_ADDED event to detect when
the robot itself is added to the wave, and write information back into the wave.
We'll write an OnRobotAdded() function to handle our event
first:
def OnRobotAdded(properties, context):
"""Invoked when the robot has been added."""
root_wavelet = context.GetRootWavelet()
root_wavelet.CreateBlip().GetDocument().SetText("I'm alive!")
We'll also want to to use the WAVELET_PARTICIPANTS_CHANGED event
to detect when anyone other than a robot is added to the wave. We'll write an
OnParticipantsChanged() function to handle that event:
def OnParticipantsChanged(properties, context):
"""Invoked when any participants have been added/removed"""
added = properties['participantsAdded']
for p in added:
Notify(context)
Whenever any participants are added or removed from the wave, it will receive
this event. For each participant that is added,
we'll invoke the Notify() function. Notice that we explicitly call
Notify() for each participant added, as we are not guaranteed to
get discrete events for each participant. (The event system may bundle
multiple participants together into one event.)
The Notify() function does the business of actually writing
to the wave:
def Notify(context):
"""Called when this robot is first added to the wave."""
"""Also called whenever a new participant is added to the wave>"""
root_wavelet = context.GetRootWavelet()
root_wavelet.CreateBlip().GetDocument().SetText("Hi everybody!")
Note that we create a new Blip within the Wavelet, retrieve the document for that blip, and set the text explicitly.
Robots within the Wave API are versioned. This allows the Wave system to detect when robots have changed and/or their capabilities have been altered. If you modify a robot's capabilities (by adding or removing monitored events, for example), you should also modify the version identifier in the Robot's constructor.
When deploying a robot, the Wave system will check if the robot identifer is different than what it has cached. (The robot identifier is simply a text string.) If so, Wave will refresh the robot and alter the system to generate any new events you've indicated interest in.
You can test your new robot by deploying it to App Engine, and then adding it to a wave.
Note: No mechanism currently exists to test Wave robots on your local machine with the App Engine development server. A future release of the Wave SDK will include tools to test robots locally before deploying them to App Engine.
To deploy the application to App Engine, use whichever App Engine launcher is
applicable for your Operating System. (This tutorial was written using the Mac OS
GoogleAppEngineLauncher.) When deploying, the App Engine launcher will
ask you for the username and password associated with the registered application,
and execute appfg.py.
The following is sample output from the Mac OS launcher:
*** Running appfg.py with the following flags:
--no_cookies --email=username@gmail.com --passin update
Scanning files on local disk.
Initiating update.
Password for username@gmail.com: Cloning 1 application file.
Deploying new version.
Checking if new version is ready to serve.
Closing update: new version is ready to start serving.
Uploading index definitions.
If deploy fails you might need to 'rollback' manually.
The "Make Symlinks..." menu option can help with command-line work.
*** appcfg.py has finished with exit code 0 ***
You can check that your application is available by loading the
Robot's http://appName.appspot.com/_wave/capabilities.xml
file. This XML file is auto-generated by the Python client
library and indicates the events with which the robot is programmed
to respond. A typical file is shown below:
Note: this capabilities.xml
is not generated automatically by the Java client library. For that library,
you must create and supply the file manually. For more information, see
Configuring Your Robot
in the Java tutorial.
You add a robot to a wave by adding it as a participant in the wave with which you want it to interact. To do so, you must first add the Robot's address to your existing contacts. (You must do this outside of the current wave, currently.)
Within Wave, now create a new wave. Add your robot to the wave using its
Wave ID, which is the App Engine application ID followed by
@appspot.com (for example, dummyrobot@appspot.com.)
The robot joins the wave, and adds its greeting.
Congratulations! You've built your first Wave Robot!