Статьи

Как подключить вашего помощника Api.ai к IoT

Если вы хотите больше узнать об искусственном интеллекте, посмотрите наши скринкасты Microsoft Cognitive Services и API Text Analytics , чтобы узнать настроения AI в своем боте.

Как подключить вашего помощника Api.ai к IoT

Потенциал личного помощника становится захватывающим, когда он имеет доступ к личным данным и реальному миру через Интернет вещей. Возникают новые возможности — от просьбы к вашему помощнику включить ваши огни, чтобы спросить, насколько хорошо вы спали. В качестве примера мы подключим вашего помощника Api.ai к API Jawbone Up.

Примечание: эта статья была обновлена ​​в 2017 году, чтобы отразить последние изменения в Api.ai.

Что вам нужно

Эта статья основана на различных концепциях, которые мы уже рассмотрели в предыдущих статьях здесь, на SitePoint. Чтобы вам было удобно следовать этому уроку, вам понадобится следующее.

  • Агент Api.ai, подключенный к простому веб-приложению HTML. Смотрите эту статью, если вы хотите понять этот процесс . В противном случае вы можете скачать код из этого руководства и использовать его тоже.
  • Агент, которому научили сущность «спать». Мы создали это в Empowering Your Api.ai Assistant с сущностями . Он должен понимать такие понятия, как «сколько сна у меня было прошлой ночью?» И «сколько сна REM я получил?». Если вы хотите адаптировать его к своему собственному устройству IoT, вам необходимо создать свой собственный пользовательский объект, который понимает вашу функциональность IoT.
  • Общие знания о Node.js и работе с сервером Node. Без этого вы не сможете запустить сервер!
  • Знание того, как использовать Jawbone UP API (или другой API, который вы намереваетесь использовать). Ранее мы описывали Jawbone Up API в разделе Подключение к Jawbone Up API с помощью Node.js , и я буду ссылаться на разделы из этой статьи.
  • Сертификат SSL для запуска вашего сайта по HTTPS. Это понадобится вам при работе с Jawbone Up API. Как упоминалось в начале этой серии, в целом немного проще сделать это на HTTPS. Мы расскажем, как настроить самозаверяющий сертификат в статье Jawbone Up API, если вам интересно, но в наши дни это не самый простой вариант. Вы можете сделать это очень легко, используя Let’s Encrypt, как упомянуто в первой статье серии. Glitch.com также предоставляет отличную среду для прототипирования, которая по умолчанию поставляется с HTTPS.

Код

Весь код для этой демонстрации доступен для скачивания и использования, как вам угодно! Вы можете найти все это на GitHub .

Как это работает

Ваш помощник Api.ai уже подключен к простому веб-приложению, которое принимает заявления через API распознавания речи HTML5. Отсюда вам нужно добавить новый функционал, который прослушивает конкретное действие от вашего агента Api.ai. В вашем случае это действие «sleepHours».

Всякий раз, когда ваш JavaScript обнаруживает это действие, он вызывает отдельный вызов вашего приложения Node.js, чтобы запросить эти данные у Jawbone API. Как только веб-приложение получит эти данные, ваше веб-приложение превратит их в приятное предложение и зачитает их, предоставляя вашему помощнику совершенно новый уровень интеллекта!

Структура вашего проекта

Я изменил приложение с исходной структуры только для HTML на структуру, использующую представления EJS, чтобы вы могли переключать страницы в своем веб-приложении при входе в Jawbone Up API через OAuth. В действительности у вас есть только одна страница, но этот метод позволяет вам добавлять больше в будущем, если это необходимо для других устройств IoT. Это единственное представление находится в /views/index.ejs Тогда ваш Node-сервер будет находиться в корневой папке как server.js Чтобы все было относительно просто и содержательно, весь интерфейсный JavaScript и CSS встроены. Не стесняйтесь перемещать их в файлы CSS и JS по своему усмотрению, уменьшать их и делать красивыми.

Ваша файловая структура

Отвечая на действия Api.ai в JavaScript

Как вы помните из предыдущей статьи, когда Api.ai возвращает ответ, он предоставляет объект JSON, который выглядит так:

 {
  "id": "6b42eb42-0ad2-4bab-b7ea-853773b90219",
  "timestamp": "2016-02-12T01:25:09.173Z",
  "result": {
    "source": "agent",
    "resolvedQuery": "how did I sleep last night",
    "speech": "I'll retrieve your sleep stats for you now, one moment!",
    "action": "sleepHours",
    "parameters": {
      "sleep": "sleep"
    },
    "metadata": {
      "intentId": "25d04dfc-c90c-4f55-a7bd-6681e83b45ec",
      "inputContexts": [],
      "outputContexts": [],
      "contexts": [],
      "intentName": "How many hours of @sleep:sleep did I get last night?"
    }
  },
  "status": {
    "code": 200,
    "errorType": "success"
  }
}

В этом объекте JSON есть два бита данных, которые вам нужно использовать — actionparameters.sleep

 "action": "sleepHours",
"parameters": {
  "sleep": "sleep"
},

action В случае с вашим примером сна вы назвали его «sleepHours». parameters В случае сна ваш параметр говорит вам, какой тип сна — «сон», «глубокий сон», «легкий сон» или «быстрый сон» (или просто «быстрый»).

Первоначально, в более ранней статье об Api.ai, prepareResponse() Вы полностью полагались на то, что сказал ваш агент Api.ai, не добавляя никаких собственных функций:

 function prepareResponse(val) {
  var debugJSON = JSON.stringify(val, undefined, 2),
    spokenResponse = val.result.speech;

  respond(spokenResponse);
  debugRespond(debugJSON);
}

На этот раз следите за полем действия и запустите собственную функцию requestSleepData()"sleepHours" В этой функции передайте параметр sleep, чтобы вы знали, какой тип сна запрашивается:

 function prepareResponse(val) {
  var debugJSON = JSON.stringify(val, undefined, 2),
    spokenResponse = val.result.speech;

  if (val.result.action == "sleepHours") {
    requestSleepData(val.result.parameters.sleep);
  } else {
    respond(spokenResponse);
  }

  debugRespond(debugJSON);
}

В requestSleepData()data.items[0].details В этих деталях у вас есть data.items[0].details.remdata.items[0].details.sounddata.items[0].details.lightdata.items[0].details.duration

 function requestSleepData(type) {
  $.ajax({
    type: "GET",
    url: "/sleep_data/",
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    success: function(data) {
      console.log("Sleep data!", data);

      if (data.error) {
        respond(data.error);
        window.location.replace("/login/jawbone");
      }

      switch (type) {
        case "REM sleep":
          respond("You had " + toHours(data.items[0].details.rem) + " of REM sleep.");
          break;
        case "deep sleep":
          respond("You had " + toHours(data.items[0].details.sound) + " of deep sleep.");
          break;
        case "light sleep":
          respond("You had " + toHours(data.items[0].details.light) + " of light sleep.");
          break;
        case "sleep":
          respond("You had " + toHours(data.items[0].details.duration) + " of sleep last night. That includes " + toHours(data.items[0].details.rem) + " of REM sleep, " + toHours(data.items[0].details.sound) + " of deep sleep and " + toHours(data.items[0].details.light) + " of light sleep.");
          break;
      }
    },
    error: function() {
      respond(messageInternalError);
    }
  });
}

toHours()

 function toHours(secs) {
  hours = Math.floor(secs / 3600),
  minutes = Math.floor((secs - (hours * 3600)) / 60),
  seconds = secs - (hours * 3600) - (minutes * 60);

  hourText = hours + (hours > 1 ? " hours, " : " hour, ");
  minuteText = minutes + (minutes > 1 ? " minutes " : " minute ");
  secondText = seconds + (seconds > 1 ? " seconds" : " second");

  return hourText + minuteText + "and " + secondText;
}

Как вы увидите при просмотре функции requestSleepData()respond() Вы повторно используете существующую функциональность, чтобы донести речь до своего собственного ответа, позволяя вашему помощнику сообщить пользователю эту информацию, как только она будет готова.

Последний аспект вашего внешнего JavaScript-кода — обработка ошибок. Если у вас есть проблема с тем, как Jawbone возвращает данные (обычно из-за отсутствия входа в службу), ваш сервер отвечает значением JSON в формате {"error" : "Your error message"} Помощник видит это и автоматически переносит пользователя на вашу страницу входа в OAuth:

 if (data.error) {
  respond(data.error);
  window.location.replace("/login/jawbone");
}

Ваш сервер Node.js

Ваш сервер Node.js основан на том, который использовался в Соединении с Jawbone UP API с Node.js. Если какой-либо код выглядит запутанным, не стесняйтесь ссылаться на эту более раннюю статью, так как она объясняет все о подключении к Jawbone API через OAuth и настройке HTTPS-сервера для его запуска. Если у вас нет Jawbone Up, те же понятия можно использовать для других устройств IoT. Вам просто нужно добавить свои собственные методы ответа на запросы GET с другими данными (и вам может не понадобиться беспокоиться об OAuth). Данные Jawbone Up здесь являются лишь примером.

Ваши данные Jawbone были скорректированы из предыдущей статьи, чтобы обеспечить простой ответ JSON, а не форматировать их все в виде шаблона таблицы. Переменные upoptions

Чтобы войти в Jawbone API через OAuth, пользователь может перейти в /login/jawbone Однако, как вы видели выше, им не нужно знать, чтобы сделать это. Ваш помощник также может перенаправить их, если он заметит, что они не вошли в систему. Вы также можете добавить новое намерение в свой агент Api.ai, который понимает фразу «войти в мои данные Jawbone Up», если вы хотите сделать это действительно бесшовные. Ваш маршрут входа в Node.js выглядит так:

 app.get("/login/jawbone",
  passport.authorize("jawbone", {
    scope: ["basic_read","sleep_read"],
    failureRedirect: "/"
  })
);

После того, как вы вошли в Jawbone API через passport.use("jawbone", new JawboneStrategy())up/barry Вы можете перенаправить пользователя на любой путь по вашему выбору, если он отличается от вашего корневого каталога (который, казалось, просто вызывает бесконечную борьбу за мой сервер). Я выбрал /barry Вы также можете использовать это как способ предоставления другого представления для пользователей, которые успешно вошли в свои устройства Jawbone, если вы того пожелаете. После входа в систему пользователь может вернуться на корневую страницу https://localhost:5000

Отправка ваших данных IoT

Ваш поиск данных Jawbone выполняется очень простым способом после получения запроса GET для /sleep_data Проверьте, определена ли переменная upup.sleeps.get()jawboneData.items

 app.get("/sleep_data", function(req, resp) {
  if (up !== undefined) {
    up.sleeps.get({}, function(err, body) {
      if (err) {
        console.log("Error receiving Jawbone UP data");
        resp.send({"error": "Your sleep tracker isn't talking to me. Let's try logging in again."});
      } else {
        var jawboneData = JSON.parse(body).data;

        if (jawboneData.items) {
          resp.send(jawboneData);
        } else {
          console.log("Error: " + jawboneData);
          resp.send({"error": "Your sleep tracker isn't talking to me. Let's try logging in again."});
        }
      }
    });
  } else {
    console.log("Up is not ready, lets ask to log in.");
    resp.send({"error": "Your sleep tracker isn't talking to me. Let's try logging in again."});
  }
});

Ошибки здесь могут быть вызваны и другими факторами, но для простоты я стараюсь заставить их снова войти в систему. В приложении производственного уровня вы захотите изучить различные причины и скорректировать свой ответ.

Если все в порядке, и вы получили правильный ответ, отправьте его в виде ответа JSON обратно в веб-приложение для чтения и анализа:

 if (jawboneData.items) {
  resp.send(jawboneData);
}

Благодаря совместному веб-приложению и серверу Node.js вы сможете получить данные о спящем режиме с вашего устройства Jawbone Up. Итак, давайте попробуем.

В бою

Запустите ваш сервер с обычным node server.js Помните, что вам нужно запустить npm installсертификат на вашем сервере, чтобы запустить его через HTTPS.

Посещение https://localhost:5000 (Если вы используете такой сервис, как Glitch, вместо этого у вас будет URL Glitch.) Спросите его, сколько у вас было сна:

Ваш помощник перенаправляет вас для входа

Оказывается, вы еще не вошли в систему. Он направляет вас к экрану входа в Jawbone Up OAuth. Войдите и согласитесь предоставить доступ к вашим данным, затем нажмите «Согласен»:

Вход в API Jawbone Up

Если вы спросите об этом в этот раз, вы получите правильный ответ:

Ваш помощник Api.ai рассказывает вам о ваших снах

Вы также можете задать что-то более конкретное, например «Сколько REM я получил?», Чтобы проверить параметры:

Ваш помощник Api.ai показывает, сколько вы быстро уснули

Вывод

На этом мы завершаем довольно разнообразное исследование возможностей Api.ai ! Вы можете расширить этот пример, чтобы он мог понять диапазоны дат (например, «Сколько я спал во вторник?») Или немного лучше отформатировать время (заметите небольшую ошибку в одном из ответов?). У вас также могут быть более приятные и короткие способы формулировки ответов. Персонализируй это — сделай это своим!

Как вы можете видеть, используя эти методы, вы можете подключить любую службу, совместимую с Node.js или веб-API, к вашему серверу Node.js, подключить ее к намерению в вашем агенте Api.ai и научить всему этому! Вы можете подключить множество устройств IoT через IFTTT , подключить интеллектуальные источники света LIFX через IFTTT или даже подключить свой собственный Nodebot . Возможности ограничены только теми устройствами, которые есть в вашем распоряжении!

Если вы следили за тем, как создавали своего личного помощника, используя Api.ai, я хотел бы услышать, как вы продвинулись! К чему ты это подключил? Дайте мне знать в комментариях ниже или свяжитесь со мной в Твиттере по адресу @thatpatrickguy .

Дайте вашему ИИ человеческое прикосновение с помощью инструмента чувств. Посмотрите наши скринкасты в Microsoft Cognitive Services и API Text Analytics .