Автоматизация квартиры с HomePod, Raspberry Pi и Node.js

в 11:46, , рубрики: homepod, IoT, siri, Блог компании Skillbox, Интернет вещей, Программирование, умный дом

Автоматизация квартиры с HomePod, Raspberry Pi и Node.js - 1

Перевели для вас статью Криса Хокинса, в которой он рассказывает о превращении своей квартиры в умный дом. В качестве базы используется HomePod от Apple, но, конечно, можно применять и другие системы.

У меня дома работает Apple HomePod, который помогает контролировать определенные системы в доме (к примеру, умные лампы) при помощи обычного запроса к Siri. Работает система как из дома, так и вне его (умный помощник есть на телефоне).

Skillbox рекомендует: двухлетний практический курс «Я — веб-разработчик PRO».

Напоминаем: для всех читателей «Хабра» — скидка 10 000 рублей при записи на любой курс Skillbox по промокоду «Хабр».

Изначально я скептически относился к управлению домом при помощи голосовых команд, ведь далеко не все распознается ассистентами (не только Siri) корректно. Но затем это вошло в привычку. Поскольку у ламп Hue нет физического выключателя, а в приложении нужно совершить несколько действий для управления освещением, я привлек к делу Siri.

Затем мне захотелось начать при помощи голосового помощника управлять и другими системами в доме, например, телевизором или консолью. В случае с ТВ я, например, обнаружил Simple IP Control — метод управления моим Sony Bravia путем отправки команд по TCP.

Кастомизируем Siri

Во второй половине 2018 года Apple открыла приложение Shortcuts для всех пользователей iOS. Оно позволяет автоматизировать работу с телефоном (или умным домом) без необходимости писать код.

У приложения много встроенных команд. Что ему недостает, так это возможности использовать TCP-команды, хотя там есть механизм работы с URL.

Плюс ко всему, можно писать собственные модули на Objective-C или Swift. Этого решил не делать, поскольку в будущем я могу сменить мой HomePod на другого помощника. Вместо этого мне захотелось написать веб-приложение, которое сможет отвечать на команды Siri.

Управление Sony Bravia TV

Вооружившись мануалом с командами для моего ТВ, я написал приложение на Node.js Express (Github), которое научил отвечать на некоторые из общих команд. Начал я с включения и громкости.

Команда setPowerStatus делает все, что нам нужно.

Автоматизация квартиры с HomePod, Raspberry Pi и Node.js - 2

Заголовок состоит из символов * и s, которые статичны и используются для всех команд. Затем третий байт (с) используется для Command. Есть четыре значения, которые могут занимать эту позицию. C для Command (отправка команды на ТВ), E — для Enquiry (проверка текущего значения определенного параметра, например, громкости), А — Answer (отправляется в ответ на Commands и Enquiries) и N для Notify (оповещение о событиях, вроде отключение громкости).

Для достижения своей цели мне пришлось изучить документацию Sony’s JSON-RPC. Как оказалось, природа JSON-RPC over HTTP позволила упростить задачу и сократить количество кода.

Работа с JSON-RPC API была простой. Возьмем, например, сервис (system), команду (getPowerStatus) плюс параметры (true или false) и сформируем HTTP-запрос, который затем отправляем на ТВ.

let body = JSON.stringify({
  method: command,
  id: ++this.id,
  params: params,
  version: "1.0",
});
return new Promise((resolve, reject) => {
  fetch('http://' + this.ip + ':' + this.port + '/sony/' + service, {
    method: 'post',
    headers: { 'X-Auth-PSK': this.psk },
    body: body,
  }).then(response => {
    return response.json();
  }).then(response => {
    if (response.error && (!response.result || response.result.length === 0)) {
      reject({ code: response.error[0] });
    } else {
      resolve(response.result[0]);
    }
  }).catch(error => {
    reject(error);
  });
});

По умолчанию аутентификация осуществляется при помощи предварительного ключа, отправляемого в заголовке HTTP-запроса. Но есть более безопасный и удобный способ сделать это при помощи accessControl. В этом случае мы можем отправлять команду на телевизор и осуществлять безопасный обмен кода при базовой HTTP-аутентификации. После того, как аутентификация выполнена один раз, дальнейшая авторизация выполняется при помощи cookie.

Но мой ТВ защищен файерволом, настроенным на роутере, так что я использовал предварительный ключ.

Включение Xbox One

Xbox, конечно, требовал иной настройки. Microsoft, похоже, приняла решение не использовать REST API, поэтому работа была выполнена при помощи UDP-пакетов.

К счастью, у Node.js есть модуль dgram, который «из коробки» работает со всеми возможностями USP. Вот, что у меня получилось в итоге.

turnOn() {
  let socket = dgram.createSocket('udp4');
  let powerPayload = new Buffer('x00' + String.fromCharCode(this.liveId.length) + this.liveId.toUpperCase() + 'x00');
  let powerHeader = Buffer.concat([new Buffer('dd0200', 'hex'), new Buffer(String.fromCharCode(powerPayload.length)), new Buffer('x00x00')]);
  let powerPacket = Buffer.concat([powerHeader, powerPayload]);
 
  return this._sendPacket(socket, powerPacket);
}
 
_sendPacket(socket, buffer) {
  return new Promise((resolve, reject) => {
    socket.send(buffer, 0, buffer.length, Constants.xboxPort, this.ip, function(err) {
      socket.close();
      if (err) {
        return reject(err);
      }
      resolve();
    });
  });
}

Для настрйоки я использовал список ID-устройств, который можно найти здесь. Если вы хотите просто взять код из моего репозитория, то вам нужно заменить ID в файле config.json.

Настройка Shortcuts для Siri

Для того, чтобы Siri могла выполнять команды, которые я только что создал, ей нужен помощник. Его я создал из Raspberry Pi, поскольку «малинка» подходит по всем параметрам. Для этого я купил Pi 3 Model B+, поддерживающий Wi-Fi.

У Raspbian есть GUI для настройки. Я подключился к Wi-Fi, затем отключил дисплей и продолжил работу по SSH. Для того, чтобы убедиться в постоянной активности веб-приложения, я настроил сокет активации сервиса в systemd, так что если бы процесс Node.js упал, система автоматически могла его перезапустить.

Собственно, Shortcuts для Siri были самым простым этапом работы. Это интуитивное приложение с нативной поддержкой голосовых команд. Оно по умолчанию уже умело работать с HomePod, дополнительно настраивать ничего не понадобилось.

Автоматизация квартиры с HomePod, Raspberry Pi и Node.js - 3

Собираем все вместе

Поскольку мой ТВ работает на Android, он поддерживает приложения вроде Netflix и YouTube. Помня об этом, я создал команды для запуска этих сервисов. Кроме того, я добавил команды для контроля громкости, режима работы ТВ, паузы и проигрывания контента.

Вот примеры всего, что я создал. Я также постарался сделать проект модульным, так что добавлять другие модели SmartTV — не проблема.

Вот пример модуля, который включает Xbox, ТВ и активизирует первый порт HDMI.

router.post('/turnOnXboxAndTV', function(req, res, next) {
  Promise.all([
    xbox.turnOn(),
    tv.turnOn()
      .then(() => new Promise(resolve => setTimeout(resolve, 2000)))
      .then(() => tv.setInput(config.scripts.xboxInput)),
  ]).then(() => {
    res.sendStatus(200);
  }).catch((error) => {
    res.status(500).send(error);
  });
});

А вот как это все работает на практике.

К сожалению, функциональность Siri не слишком хороша. У той же Alexa от Amazon гораздо более обширный спектр возможностей и весьма мощный API. Думаю, на основе Alexa можно создать куда более серьезные проекты.

Skillbox рекомендует:

Автор: Онлайн-университет Skillbox

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js