消息服务为人类使用我们已经用来相互交谈的相同设备与可编程机器人进行交互提供了舞台。这种互动感觉有点像魔法,但任何编码的人都能召唤出魔法。为了告诉你我的意思,我们需要看看米斯蒂的照片展位技能,这是Misty演示在TwilioSIGNAL 2019。
当此技能运行时,您可以发送短信,要求您的 Misty 机器人拍摄您的照片。当 Misty 收到您的文本时,她停止她正在做的事情,转过身来看着你,用相机在遮阳板上捕捉您的肖像。然后,她通过彩信将图片直接发送回您的手机。
为了展示所有这些工作原理,本文细分了 Misty 照片展位技能的背后发生了什么,从手指触摸发送到您的肖像着陆回到您的设备中。它检查了技能组合的每个服务之间的链接,并解释了控制 Misty 响应的 JavaScript 代码的几个重要块。
让我们先看一下Twilio自动驾驶仪,你的文本首先访问的服务。
短信 -> Twilio 自动驾驶仪
为了引起Misty的注意,用户给一个连接到Twilio的自动驾驶仪服务的电话号码发了短信。如果您是自动驾驶仪的新人,以下是 Twilio 描述它的方式:
Autopilot 是一个对话式 AI 平台,用于构建具有自然语言理解和完全可编程功能的全渠道机器人和虚拟助手。
-特维利奥
当您发送此特殊号码时,Twilio 会将您的消息转发到与唯一的自动驾驶仪”机器人”关联的可编程消息通道。您创建的每个自动驾驶仪自动程序可以执行一个或多个”任务”(即在自动程序收到某种消息时触发的操作)。您可以在 Twilio 控制台中自定义任务,以编程触发时应执行的任务。
对于照片展位技能,我们的自动驾驶仪机器人的核心功能生活在一个任务,称为 take_picture
我们。我们”训练”我们的机器人,以触发 take_picture
任务时,它收到以下短语之一:
下一步是对任务触发时自动程序的作用进行 take_picture
编程。可能的操作包括将消息发送回用户、侦听响应或收集和存储信息。或者,如果内置操作不够,您可以对任务进行编程以重定向到其他服务当 take_picture
任务触发时,它会调用重定向以运行 Twilio 函数。
自动驾驶仪 -> Twilio 函数
Twilio 函数是处理入站 Twilio 通信的无服务函数。这些功能是一种快速的方法,将您在 Twilio 中处理的通信引入到 Web 的其余部分(一种通信媒介,其中像 Misty 这样的机器人非常精通)。
我们在照片展位技能中使用Twilio函数做了一些事情。首先,它将用户的电话号码分配给一个变量。然后,它使用 Twilio API 回复用户与 SMS: [••] Time to Pose
。最后,它将用户的电话号码(以及他们要求的操作的性质)输入 PubNub 频道,以便收听新消息。(下一节中将对此进行详细介绍)。
照片展位技能的 Twilio 函数代码如下所示:
exports.handler = function(context, event, callback) {
// Saves phone number to contact variable
var contact = event.UserIdentifier || "19294421336";
// Sends SMS to user
const replySms = {"actions": [{"say": "[••] Time to Pose"}]};
const replyErrorSms = {"actions": [{"say": "[••] Oops an error occured, Could you please try again.."}]};
const axios = require('axios')
// The PubNub URL includes publish/subscribe keys, a
// channel name (similar to the name of a chatroom),
// and a client name (a unique name identifying this
// device in the PubNub channel).
axios.post('https://ps.pndsn.com/publish/<publish-key>/<subscribe-key>/0/<channel-name>/0?store=0&uuid=<client-name>', {
'phNumber': contact, 'type': 'photo'
})
.then((res) => {
console.log(res);
callback(null, replySms);
})
.catch((error) => {
console.log(error);
callback(null, replyErrorSms);
});
};
随着Twilio函数和自动驾驶机器人的设置,我们准备看看PubNub,服务,通知Misty拍照。
Twilio 函数 -> PubNub
黑客机器人对短信做出反应是很酷的。更酷?当机器人几乎没有任何延迟响应时。这就是PubNub的用处。
PubNub提供了一个实时消息传递 API,开发人员可以通过 HTTP 通信协议利用该 API,从而允许各种计算机之间进行快速通信。当您使用 PubNub 的消息传递 API 时,您创建一个数据通道(类似于设备的聊天室),多个设备(如 Twilio 服务器和机器人)可以订阅消息并将其发布到在 PubNub 中创建新的”应用”时,您将获得用于发布和订阅该应用的唯一 API 密钥。要发布数据(如我们在上述 Twilio 函数中所做的),我们将 POST 请求发送到:
https://ps.pndsn.com/publish/<publish-key>/<subscribe-key>/0/<channel-name>/0?store=0&uuid=<client-name> |
您会注意到 PubNub URL 包括发布/订阅密钥、频道名称(类似于聊天室的名称)和客户端名称(在 PubNub 通道中标识此设备的唯一名称)。发送此请求时,我们会传递一个 JSON 正文以及要发布的消息。在我们的例子中,该消息类似于:
{
'phNumber': contact,
'type': 'photo'
}
您可以在PubNub 开发人员文档中阅读更多有关此内容的信息,但高级视图是,此请求会向我们为照片展位技能创建的 PubNub 应用发布一条消息。正在侦听该应用程序的外部设备(如可编程机器人)可以读取这些消息并自行使用它们。
PubNub -> 迷雾
在查看机器人的技能代码之前,了解我们所说的技能是很有帮助的。在 Misty 机器人节中,一项技能是您的 JavaScript 代码,在机器人上本地运行。每项技能都需要一个 JavaScript 代码文件,在技能运行时执行 JavaScript Misty 和 JSON 元文件,以及有关该技能的其他信息。
Misty 的板载 JavaScript API 提供了订阅来自传感器和其他事件的数据的方法,并且您定义用于在技能代码中处理此数据的回调。此 API 还包括移动机器人、使用传感器、播放声音和发送 Web 请求等命令的方法。最后一点就是 Misty 如何在照片展位技能中从 PubNub 获取数据。
对于快速响应,操作照片展位技能的机器人应在任何人向她发送文本之前打开电源并运行代码。在技能运行期间,Misty 会定期向我们的 PubNub 频道发送请求,从而侦听新的 SMS 通知。我们通过 misty.SendExternalRequest()
Misty JavaScript API 中的方法在代码中执行此操作。
如果 Misty 发送的每个请求在 20 秒后未收到响应,则发送的每个请求都将超时,并且不能保证有人会在该时间段内向 Misty 发送消息。我们将订阅请求与向 PubNub 通道发布空消息的请求配对,从而在技能中解决这一问题,该通道在循环上运行以保持通信线路的畅通。当我们的Twilio机器人将一条消息转发给PubNub时,Misty会将其返回我们的技能,并将其传递到 _pubNubSubscribe()
回调函数中。
在用于我们照片展位技能的 JavaScript 文件中,该代码如下所示(您还可以在 GitHub 上找到仅提取的 PubNub 功能的示例):
// Calls the keepActive() function every 15 seconds
misty.RegisterTimerEvent("keepActive", 15000, true);
// Sends a publish request to work around timeouts
function _keepActive() {
misty.SendExternalRequest("POST", "https://ps.pndsn.com/publish/<publish-key>/<subscribe-key/0/<channel-name>/myCallback", null, null, "{}", false, false, "", "application/json");
}
// Gets the message Twilio sends to PubNub and passes
// the response into the _pubNubSubscribe callback function
misty
pndsn.com/subscribe/<subscribe-key>/<channel-name>/0/0?uuid=<client-id>””,空,空,”*”,假,假,””,”应用程序/json”,”\pubNub订阅”;
提取电话号码并运行
有迷雾拍照
功能 [pubNub订阅(数据) ]
输出Ext(数据。结果.响应对象.数据);
}
outputExt()
函数(如上图所示)从 Twilio 函数发送的消息中提取电话号码和类型参数的值。Misty 存储电话号码并检查类型值是否等于照片。如果是,她会运行一个代码块,该代码块让她移动头部(和相机)以面对用户,更改显示图像,并播放声音,让用户知道发生了什么事情。下面是一个示例,可以这样显示:
if (data != [] && data.type == 'photo')
{
// Saves the user's contact info
misty.Set("contact", (data.phNumber).toString(), false);
// Changes display image, sets head position, and plays
// sounds to show she's taking a picture
misty.DisplayImage("DefaultEyes_SystemCamera.jpg");
misty.Pause(100);
misty.PlayAudio("DefaultSounds_Awe3.wav", 100);
misty.Set("pictureMode", true, false);
misty.MoveHeadPosition(0, 0, 0, 45);
misty.Pause(3000);
misty.DisplayImage("DefaultEyes_SystemFlash.jpg");
misty.ChangeLED(255, 255, 255);
misty.PlayAudio("DefaultSounds_SystemCameraShutter.wav", 100);
// Snaps a portrait! By default, this method passes
// a base64-encoded string with the image data for the
// picture into the _TakePicture() callback function.
misty.TakePicture("Photobooth", 375, 812, false, true);
misty.Pause(200);
misty.DisplayImage("DefaultEyes_SystemCamera.jpg");
misty.ChangeLED(140, 0, 255);
misty.Pause(500);
misty.DisplayImage("DefaultEyes_Joy2.jpg");
}
雾 – > 伊姆古尔
将 Misty 编码以拍摄照片时,可以将图片数据的 base64 编码字符串传递到回调函数中,以便进行其他处理。默认情况下,这些回调函数使用与 misty.TakePicture()
方法相同的名称,前缀有下划线: _TakePicture().
在我们的技能中,我们使用此 _TakePicture()
回调函数将 base64 编码的字符串与图片数据一起传递给 uploadImage()
函数。此回调类似于以下内容:
function _TakePicture(data) {
var base64String = data.Result.Base64;
uploadImage(base64String);
}
当我们调用 uploadImage()
该函数时,Misty 会将图片发布到私人 Imgur 相册中。有几个图像共享服务,我们可以用来托管这些图片,但 Imgur 的 API 执行两件事,使其成为照片展位技能的理想选择。事情一:它接受base64编码的字符串,而”第二”:它返回响应正文中上传图像的URL。通过将返回的 URL 传回 Twilio 的彩信 API,Misty 可以直接将图片发送给要求图片的人。
在照片展位技能中管理此内容的代码如下所示:
function uploadImage(imageData) {
// Sets up the JSON body for uploading the picture
var jsonBody = {
'image': imageData,
'type' : 'base64',
'album': '<album-name>
};
// Uploads the picture to a private album; then, passes Imgur
// response data into the _imageUploadResponse() callback
misty.SendExternalRequest("POST", "https://api.imgur.com/3/image", "Bearer", "<bearer-token>", JSON.stringify(jsonBody), false, false, "", "application/json", "_imageUploadResponse");
}
function _imageUploadResponse(responseData) {
// Saves the URL
misty
解析(响应数据.结果.响应对象.数据.数据.链接,假);
运行代码以发送图片
发送图片();
}
雾 – > 彩信
有了我们的Imgur专辑中的图片,剩下的只有一步:把图片放进手机,想要它。这也是通过Twilio API发生的。在我们的 JavaScript 技能代码中,我们使用 SendPicture()
函数发布请求,其中包含发送原始文本的人员的联系信息以及链接到其上传图像的 URL。
调用该 sendPicture()
函数时,Misty 会向 Twilio API 发送请求,该 API 会将给定 URL 处的图像放入用户的消息收件箱中。它有点像这样:
function sendPicture() {
misty.Debug("Sending Image to User");
// Sets up thee JSON body for the Twilio SMS API.
// Includes the phone number of the recipient and
// the URL for their photograph on Imgur
var jsonBody = {
'Body': '[••] Greetings from Misty!',
'From': '<number-to-send-from>',
'To': misty.Get("contact"),
'MediaUrl': misty.Get("imageLink")
};
// Sends a request to the Twilio API with our account
// credentials to send the picture to the person who asked for it
var credentials = "<base64-encoded-Twilio-credentials>"
misty.SendExternalRequest("POST", "https://api.twilio.com/2010-04-01/Accounts/<account-id>/Messages.json", "Basic", credentials, JSON.stringify(jsonBody), false, false, "", "application/x-www-form-urlencoded");
}
回顾
在这篇文章中,我们讨论了如何链接Twilio和PubNub的消息API,Imgur的照片共享服务,和机器人的JavaScript代码,以建立一个照片展位技能的Misty。当我们使用此技能时:
- 有人向我们的 Twilio 电话号码发送消息
- Twilio 将消息传递给我们的 Twilio 自动驾驶仪机器人
- 我们的自动驾驶仪机器人读取消息,识别任务,并重定向到我们的 Twilio 函数
- Twilio 函数将用户的电话号码发布到我们的 PubNub 频道
- 迷雾,谁一直在运行照片展位技能,从PubNub拉下消息
- 迷雾重新定位她的相机并拍照
- Misty 将图片上传到私人 Imgur 相册,并调用 Twilio API 将其作为彩信发送给我们的用户
向机器人发送短信是要求机器人做某事的一种非常社交的方式。当机器人回复其最喜欢的人的照片?那可是彻头彻尾的密友。