Created
June 25, 2017 18:21
-
-
Save upgundecha/4ff18a55004b3640658b2c68c49b79c5 to your computer and use it in GitHub Desktop.
"If This Then That" Jenkins example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# Copyright (c) 2016 Anki, Inc. | |
# | |
# Licensed under the Apache License, Version 2.0 (the "License"); | |
# you may not use this file except in compliance with the License. | |
# You may obtain a copy of the License in the file LICENSE.txt or at | |
# | |
# http://www.apache.org/licenses/LICENSE-2.0 | |
# | |
# Unless required by applicable law or agreed to in writing, software | |
# distributed under the License is distributed on an "AS IS" BASIS, | |
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
# See the License for the specific language governing permissions and | |
# limitations under the License. | |
# Program modified by Unmesh Gundecha, http://unmesh.me | |
'''"If This Then That" Jenkins example | |
This example demonstrates how "If This Then That" (http://ifttt.com) can be used | |
make Cozmo respond when a Jenkins build job is completed. Instructions below | |
will lead you through setting up an applet on the IFTTT website. When the applet | |
trigger is called (which sends a web request received by the web server started | |
in this example), Cozmo will annouce the the Build status, play an animation and | |
light up the cubes. | |
Please place Cozmo on the charger for this example. When necessary, he will be | |
rolled off and back on. | |
Follow these steps to set up and run the example: | |
1) Provide a a static ip, URL or similar that can be reached from the If This | |
Then That server. One easy way to do this is with ngrok, which sets up | |
a secure tunnel to localhost running on your machine. | |
To set up ngrok: | |
a) Follow instructions here to download and install: | |
https://ngrok.com/download | |
b) Run this command to create a secure public URL for port 8080: | |
./ngrok http 8080 | |
c) Note the HTTP forwarding address shown in the terminal (e.g., http://55e57164.ngrok.io). | |
You will use this address in your applet, below. | |
WARNING: Using ngrok exposes your local web server to the internet. See the ngrok | |
documentation for more information: https://ngrok.com/docs | |
2) Set up your applet on the "If This Then That" website. | |
a) Sign up and sign into https://ifttt.com | |
b) Create an applet: https://ifttt.com/create | |
c) Set up your trigger. | |
1. Click "this". | |
2. Select "Maker Webhooks" as your service. | |
3. Under "Choose a Trigger", select “Receive a Web request". | |
4. In "Recive a Web Request", enter "JenkinsBuild" as "Event Name" | |
5. Click "Create Trigger" button | |
d) Set up your action. | |
1. Click “that". | |
2. Select “Maker Webhooks" to set it as your action channel. Connect to the Maker channel if prompted. | |
3. Click “Make a web request" and fill out the fields as follows. Remember your publicly | |
accessible URL from above (e.g., http://55e57164.ngrok.io) and use it in the URL field, | |
followed by "/iftttJenkins" as shown below: | |
URL: http://55e57164.ngrok.io/iftttJenkins | |
Method: POST | |
Content Type: application/json | |
Body: {"project" : "{{Value1}}", "build" : "{{Value2}}", "status": "{{Value3}}"} | |
5. Click “Create Action" then “Finish". | |
3) Test your applet. | |
a) Run this script at the command line: ./ifttt_jenkins.py | |
b) On ifttt.com, on your applet page, click “Check now”. See that IFTTT confirms that the applet | |
was checked. | |
4) Setup Jenkins Job - requires IFTTT Build Notification Plugin | |
a) In your Jenkins job "Post-build Action" section add a new "IFTTT Build Notifier" | |
action with following values: | |
Event Name: JenkinsBuild | |
Key: <Your Make Webhooks Key> | |
Note: You can get your unique Maker Webhooks Key from https://ifttt.com/services/maker_webhooks/settings | |
5) Run your Jenkins job to test the setup. | |
In response to the ifttt web request, Cozmo should roll off the charger, raise and lower | |
his lift, announce the status, and then animate and light-up the cubes. | |
''' | |
import asyncio | |
import re | |
import sys | |
try: | |
from aiohttp import web | |
except ImportError: | |
sys.exit("Cannot import from aiohttp. Do `pip3 install --user aiohttp` to install") | |
import cozmo | |
from common import IFTTTRobot | |
from cozmo.objects import LightCube1Id, LightCube2Id, LightCube3Id | |
app = web.Application() | |
async def serve_jenkins(request): | |
'''Define an HTTP POST handler for receiving requests from If This Then That. | |
You may modify this method to change how Cozmo reacts to the Jenkins build | |
notification | |
''' | |
json_object = await request.json() | |
# Extract the name of the project and build status. | |
project_name = json_object["project"] | |
status = json_object["status"] | |
robot = request.app['robot'] | |
async def read_name(): | |
try: | |
async with robot.perform_off_charger(): | |
'''If necessary, Move Cozmo's Head and Lift to make it easy to see Cozmo's face.''' | |
await robot.get_in_position() | |
# First, have Cozmo play an animation | |
await robot.play_anim_trigger(cozmo.anim.Triggers.ReactToPokeStartled).wait_for_completed() | |
# Next, have Cozmo speak the name of the project and the build status. | |
if status == "SUCCESS": | |
await robot.say_text("Build for " + project_name + " is successful").wait_for_completed() | |
elif status == "FAILURE": | |
await robot.say_text("Build for " + project_name + " is failed").wait_for_completed() | |
else: | |
await robot.say_text("Build for " + project_name + " is completed" + status).wait_for_completed() | |
# Last, have Cozmo animate & Cubes flash light based on build status | |
await rock_n_roll(robot, status) | |
except cozmo.RobotBusy: | |
cozmo.logger.warning("Robot was busy so didn't receive status for: "+ project_name) | |
# Perform Cozmo's task in the background so the HTTP server responds immediately. | |
asyncio.ensure_future(read_name()) | |
return web.Response(text="OK") | |
async def rock_n_roll(robot, status): | |
cube1 = robot.world.get_light_cube(LightCube1Id) # looks like a paperclip | |
cube2 = robot.world.get_light_cube(LightCube2Id) # looks like a lamp / heart | |
cube3 = robot.world.get_light_cube(LightCube3Id) # looks like the letters 'ab' over 'T' | |
if status == "SUCCESS": | |
light_color = cozmo.lights.green_light | |
await robot.play_anim_trigger(cozmo.anim.Triggers.PeekABooGetOutHappy).wait_for_completed() | |
elif status == "FAILURE": | |
light_color = cozmo.lights.red_light | |
await robot.play_anim_trigger(cozmo.anim.Triggers.FrustratedByFailure).wait_for_completed() | |
else: | |
light_color = cozmo.lights.blue_light | |
if cube1 is not None: | |
cube1.set_lights(light_color) | |
else: | |
cozmo.logger.warning("Cozmo is not connected to a LightCube1Id cube - check the battery.") | |
if cube2 is not None: | |
cube2.set_lights(light_color) | |
else: | |
cozmo.logger.warning("Cozmo is not connected to a LightCube2Id cube - check the battery.") | |
if cube3 is not None: | |
cube3.set_lights(light_color) | |
else: | |
cozmo.logger.warning("Cozmo is not connected to a LightCube3Id cube - check the battery.") | |
await asyncio.sleep(10) | |
cube1.set_lights_off()import asyncio | |
import re | |
import sys | |
try: | |
from aiohttp import web | |
except ImportError: | |
sys.exit("Cannot import from aiohttp. Do `pip3 install --user aiohttp` to install") | |
import cozmo | |
from common import IFTTTRobot | |
from cozmo.objects import LightCube1Id, LightCube2Id, LightCube3Id | |
app = web.Application() | |
async def serve_jenkins(request): | |
'''Define an HTTP POST handler for receiving requests from If This Then That. | |
You may modify this method to change how Cozmo reacts to the Jenkins build | |
notification | |
''' | |
json_object = await request.json() | |
# Extract the name of the project and build status. | |
project_name = json_object["project"] | |
status = json_object["status"] | |
robot = request.app['robot'] | |
async def read_name(): | |
try: | |
async with robot.perform_off_charger(): | |
'''If necessary, Move Cozmo's Head and Lift to make it easy to see Cozmo's face.''' | |
await robot.get_in_position() | |
# First, have Cozmo play an animation | |
await robot.play_anim_trigger(cozmo.anim.Triggers.ReactToPokeStartled).wait_for_completed() | |
# Next, have Cozmo speak the name of the project and the build status. | |
if status == "SUCCESS": | |
await robot.say_text("Build for " + project_name + " is successful").wait_for_completed() | |
elif status == "FAILURE": | |
await robot.say_text("Build for " + project_name + " is failed").wait_for_completed() | |
else: | |
await robot.say_text("Build for " + project_name + " is completed" + status).wait_for_completed() | |
# Last, have Cozmo animate & Cubes flash light based on build status | |
await rock_n_roll(robot, status) | |
except cozmo.RobotBusy: | |
cozmo.logger.warning("Robot was busy so didn't receive status for: "+ project_name) | |
# Perform Cozmo's task in the background so the HTTP server responds immediately. | |
asyncio.ensure_future(read_name()) | |
return web.Response(text="OK") | |
async def rock_n_roll(robot, status): | |
cube1 = robot.world.get_light_cube(LightCube1Id) # looks like a paperclip | |
cube2 = robot.world.get_light_cube(LightCube2Id) # looks like a lamp / heart | |
cube3 = robot.world.get_light_cube(LightCube3Id) # looks like the letters 'ab' over 'T' | |
if status == "SUCCESS": | |
light_color = cozmo.lights.green_light | |
await robot.play_anim_trigger(cozmo.anim.Triggers.PeekABooGetOutHappy).wait_for_completed() | |
elif status == "FAILURE": | |
light_color = cozmo.lights.red_light | |
await robot.play_anim_trigger(cozmo.anim.Triggers.FrustratedByFailure).wait_for_completed() | |
else: | |
light_color = cozmo.lights.blue_light | |
if cube1 is not None: | |
cube1.set_lights(light_color) | |
else: | |
cozmo.logger.warning("Cozmo is not connected to a LightCube1Id cube - check the battery.") | |
if cube2 is not None: | |
cube2.set_lights(light_color) | |
else: | |
cozmo.logger.warning("Cozmo is not connected to a LightCube2Id cube - check the battery.") | |
if cube3 is not None: | |
cube3.set_lights(light_color) | |
else: | |
cozmo.logger.warning("Cozmo is not connected to a LightCube3Id cube - check the battery.") | |
await asyncio.sleep(10) | |
cube1.set_lights_off() | |
cube2.set_lights_off() | |
cube3.set_lights_off() | |
# Attach the function as an HTTP handler. | |
app.router.add_post('/iftttJenkins', serve_jenkins) | |
if __name__ == '__main__': | |
cozmo.setup_basic_logging() | |
cozmo.robot.Robot.drive_off_charger_on_connect = False | |
# Use our custom robot class with extra helper methods | |
cozmo.conn.CozmoConnection.robot_factory = IFTTTRobot | |
try: | |
app_loop = asyncio.get_event_loop() | |
sdk_conn = cozmo.connect_on_loop(app_loop) | |
# Wait for the robot to become available and add it to the app object. | |
app['robot'] = app_loop.run_until_complete(sdk_conn.wait_for_robot()) | |
except cozmo.ConnectionError as e: | |
sys.exit("A connection error occurred: %s" % e) | |
web.run_app(app) | |
cube2.set_lights_off() | |
cube3.set_lights_off() | |
# Attach the function as an HTTP handler. | |
app.router.add_post('/iftttJenkins', serve_jenkins) | |
if __name__ == '__main__': | |
cozmo.setup_basic_logging() | |
cozmo.robot.Robot.drive_off_charger_on_connect = False | |
# Use our custom robot class with extra helper methods | |
cozmo.conn.CozmoConnection.robot_factory = IFTTTRobot | |
try: | |
app_loop = asyncio.get_event_loop() | |
sdk_conn = cozmo.connect_on_loop(app_loop) | |
# Wait for the robot to become available and add it to the app object. | |
app['robot'] = app_loop.run_until_complete(sdk_conn.wait_for_robot()) | |
except cozmo.ConnectionError as e: | |
sys.exit("A connection error occurred: %s" % e) | |
web.run_app(app) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment