DEVWKS-2074 - Create custom In-Room Controls and Macros for CE and Webex Devices
This workshop is run at Cisco Live events in the DevNet Zone. Check the deck from past editions: Cisco Live Barcelona 2019
Join this workshop to go hands-on with xAPI (ie Webex Devices APIs and Cisco Collaboration Endpoint APIs). You'll learn to interact with a Webex Device from code, and implement an end-to-end In-Room Control by creating a custom interface and deploying Macros onto your device check the sessions details
In 45 min, you will learn to
- use a sandbox’ed RoomKit
- build a custom In-Room Control
- listen to events via ssh
- create your first Macro
- post to a Webex Teams space with the HttpClient command
Walkthrough
If you're new to Cisco Collaboration Devices, take this DevNet learning module.
Then:
- reserve a Sandbox'ed CE9+ Roomkit or use the training pod provided at your event (VPN to devnetsandbox-emea-gwy.cisco.com:20339)
- load and deploy the provided In-Room control
- connect via ssh and type
xstatus UserInterface Extensions xfeedback register /Event/UserInterface/Extensions/Event/Clicked xfeedback deregisterall
- create and enable the provided JS macro
Step by step instructions
Tip: check the raw contents, these are ready to paste into a Webex Teams space
Step 0
Connect to your RoomKit
Sandbox VPN : devnetsandbox-emea-gwy.cisco.com:20339
Sandbox user : user01 user02 user03 user04
Sandbox password : cisco1234
RoomKit IP : https://10.10.1.171 172 173 174 …
RoomKit user : admin
RoomKit passwd : ciscopsdt
Step 1
Step 1.1
Open the In-Room Controls Editor.
Create a new Panel with a push
button with id: 'DEVWKS-2074'
or simply import the provided panel sample
Step 1.2
From the terminal, open a ssh session to your device (use PUTTY if on windows):
- ssh 10.10.20.17X
- user: admin
- password: ciscopsdt
Then type commands one at a time:
xfeedback register /Event/UserInterface/Extensions/Event/Clicked
When done, unregister with command:
xfeedback deregisterall
Step 2
Once the agenda In-Room control has been created,
open the Macro Editor and create a new listen
macro with the following script:
const xapi = require('xapi')
xapi.event.on('UserInterface Extensions Event Clicked Signal', (widgetId) => {
console.log(`new event from widget: ${widgetId}`)
// Add your custom logic
})
console.log('listening...')
Step 3
Step 3.1
We'll now configure your device to allow Http POST/PUT requests
Go back to your ssh session and type the commands below, one at a time:
xConfiguration HttpClient Mode: On
xConfiguration HttpClient AllowInsecureHTTPS: True
Step 3.2
Create another macro named push
with the following script,
and place your first name on the last line:
const xapi = require('xapi');
function push(msg, cb) {
// Replace with your bot token
const token = "YTJkZDlmZjAtMGM3NS00MDUxLWIzNzItNmU0M2I2MDE0ZGRmODcwMTExZGUtNzU0"
// replace with a space your bot is part of
const roomId = "Y2lzY29zcGFyazovL3VzL1JPT00vYmEzlkNDktZmI5NTAxNDlhODVl"
// Post message
let payload = {
"markdown": msg,
"roomId": roomId
}
xapi.command(
'HttpClient Post',
{
Header: ["Content-Type: application/json", "Authorization: Bearer " + token],
Url: "https://api.ciscospark.com/v1/messages",
AllowInsecureHTTPS: "True"
},
JSON.stringify(payload))
.then((response) => {
if (response.StatusCode == 200) {
console.log("message pushed to Webex Teams")
if (cb) cb(null, response.StatusCode)
return
}
console.log("failed with status code: " + response.StatusCode)
if (cb) cb("failed with status code: " + response.StatusCode, response.StatusCode)
})
.catch((err) => {
console.log("failed with err: " + err.message)
if (cb) cb("Could not post message to Webex Teams")
})
}
push('Hi, this is Steve! I am performing well so far...', console.log)
Step 4
Now disable the listen
and push
macros,
and create a new workshop
macro with the following contents:
const xapi = require('xapi')
xapi.event.on('UserInterface Extensions Event Clicked Signal', (widgetId) => {
console.log(`new event from widget: ${widgetId}`)
let markdown = buildMarkdownForSession(widgetId)
push(markdown)
})
function buildMarkdownForSession(widgetId) {
let markdown = `no session found for widget identifier: ${widgetId}`
let session = sessions[widgetId]
if (session) {
console.log(`found session with id: ${widgetId}`)
markdown = `${session.day}, ${session.time}, ${session.location}`
markdown += `<br/>**\[${session.id}\] - ${session.title}**`
markdown += `<br/>_${session.description}_`
}
return markdown
}
const sessions = {}
sessions['DEVWKS-2074'] = {
id: 'DEVWKS-2074',
title: "Create custom In-Room Controls and Macros for CE and Webex Devices",
description: "Join this workshop to go hands-on with xAPI (ie Webex Devices APIs and Cisco Collaboration Endpoint APIs). You'll learn to interact with a Webex Device from code, and implement an end-to-end In-Room Control by creating a custom interface and deploying Macros onto your device",
location: "Workshop 8",
type: "workshop",
day: "Monday",
time: "4:00PM",
duration: "45",
speaker: "Stève Sfartz",
href: "https://ciscolive.cisco.com/us/learn/sessions/content-catalog/?search=2074#/"
}
function push(msg, cb) {
// Replace with your bot token
const token = "YTJkZDlmZjAtMGM3NS00MDUxLWIzNzItNmU0M2I2MDE0ZGRmODcwMTExZGUtNzU0"
// replace with a space your bot is part of
const roomId = "Y2lzY29zcGFyazovL3VzL1JPT00vYmEzlkNDktZmI5NTAxNDlhODVl"
// Post message
let payload = {
"markdown": msg,
"roomId": roomId
}
xapi.command(
'HttpClient Post',
{
Header: ["Content-Type: application/json", "Authorization: Bearer " + token],
Url: "https://api.ciscospark.com/v1/messages",
AllowInsecureHTTPS: "True"
},
JSON.stringify(payload))
.then((response) => {
if (response.StatusCode == 200) {
console.log("message pushed to Webex Teams")
if (cb) cb(null, response.StatusCode)
return
}
console.log("failed with status code: " + response.StatusCode)
if (cb) cb("failed with status code: " + response.StatusCode, response.StatusCode)
})
.catch((err) => {
console.log("failed with err: " + err.message)
if (cb) cb("Could not post message to Webex Teams")
})
}
console.log('listening...')