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

Постановка задачи

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

Ограничения

Я не хочу, чтобы мне приходилось платить много денег за решение, потому что меня это мало волнует, это просто развлечение, которое приятно иметь. У меня также есть только один день, чтобы сделать это - мы делаем «Expo jam», когда мы начинаем работать над новым релизом, создавая что-то из него. На самом деле я мог бы потратить на это больше времени, но приятно иметь что-то готовое к отправке к концу дня.

Предложенное решение

Хотя я мог бы быть более внимательным, это требует изменения человеческого поведения, что намного сложнее, чем написание приложения. Поэтому вместо этого я создам приложение, которое позволит моим друзьям открывать дверь без какого-либо вмешательства от моего имени.

Приложение позволит им войти в систему через Facebook, и если их идентификатор пользователя находится в белом списке, им будет представлена ​​большая кнопка «Разблокировать». Чтобы войти в дверь, им нужно нажать эту кнопку, а затем набрать мой добавочный номер. В течение 30 секунд после нажатия кнопки разблокировки на звонок зуммера должен автоматически ответить какой-то робот, единственная цель жизни которого - подавать сигнал набора номера 6. Добро пожаловать в клуб, приятель.

Технология

  • Twilio: все это было бы невозможно без Twilio. За 1 доллар в месяц я могу зарегистрировать местный телефонный номер, который перехватывает входящие голосовые вызовы, чтобы определить, как он должен отвечать. Как вы увидите, API очень мощный.
  • Now.sh: мне нужен серверный процесс, работающий где-то, чтобы обрабатывать веб-перехватчики и хранить информацию о белом списке пользователей, а может быть, и другие вещи. С now.sh я получаю это бесплатно. Но у меня уже есть подписка, которую я использую для других целей (экономия на масштабе хобби-проекта снова окупается), что позволяет мне постоянно выделять как минимум 1 экземпляр для сервера, а не спать, когда он неактивен, например с бесплатным планом.
  • Expo: здесь должен быть какой-то интерфейс, чтобы мои друзья могли войти в систему и нажать кнопку. Вы можете использовать все, что может работать на телефоне, запускать HTTP-запросы и выполнять OAuth. Однако здесь Expo работает особенно хорошо, потому что я могу использовать React и компоненты собственной платформы, а также у него есть хорошие примитивы для социальной аутентификации. Я также могу поделиться своим приложением с друзьями, не помещая его в приложение и в игровой магазин, что всегда отнимает много времени и раздражает. В качестве альтернативы я мог бы создать веб-приложение, это тоже было бы хорошо.

Пора настроить Twilio

Первое, что мне нужно сделать, это зарегистрировать номер телефона. Если у вас нет учетной записи Twilio, зарегистрируйте ее, добавьте на нее немного кредита, затем перейдите на экран Купить номер телефона и найдите учетную запись с кодом города, а затем купите.

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

Создать корзину TwiML

TwiML Bin - это, по сути, стандартный ответ на телефонные звонки. TwiML - это язык разметки Twilio для описания того, как он должен отвечать на телефонный звонок или SMS. Перейдите на свою панель инструментов TwiML Bins и создайте новую корзину, назовите ее Позвони мне, а затем вставьте это в содержимое:

<?xml version="1.0" encoding="UTF-8"?>
<Response>
  <Dial>your-phone-number-including-country-code-here</Dial>
</Response>

Сохраните это сейчас. Отличная работа.

Свяжите TwiML Bin со своим зарегистрированным номером

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

Нажмите «Сохранить», теперь позвоните по зарегистрированному номеру, и он должен перенаправить на ваш телефон. Успех!

Получите голосовой ответ Twilio от сервера на now.sh

npm i now --global, а затем запустите now login и зарегистрируйтесь или войдите. Войдя в систему, создайте новый проект, запустите npm init, затем npm install express twilio --save и npm install nodemon --save-dev и добавьте их в сценарии в package.json:

"scripts": {
    "start": "node index.js",
    "dev": "NODE_ENV=development nodemon index.js",
    "deploy": "now -e NODE_ENV=production"
 },

Как и следовало ожидать, следующим шагом будет создание index.js.

const twilio = require('twilio');
const express = require('express');
let app = express();
app.post('/', (request, response) => {
  let twiml = new twilio.twiml.VoiceResponse();
  twiml.say('Hello world');
  response.type('text/xml');
  response.send(twiml.toString());
});
app.listen(3000);
console.log(`server running (${process.env.NODE_ENV})`);

Проверьте это, запустив npm run dev, а затем отправив запрос POST на localhost: 3000

Разверните это, запустив now - это автоматически скопирует URL-адрес, на который он развернут, в ваш буфер обмена. Вернитесь в панель управления телефонными номерами и выберите свой номер телефона. Измените тип Входящий вызов с TwiML на Webhook и вставьте свой URL-адрес, убедитесь, что он использует HTTP POST. Сохраните, конечно.

Теперь снова позвоните на свой номер Twilio, и вы должны услышать «Hello world».

Ой, вещи из реального мира

Здесь вы можете спросить себя - круто, я могу позвонить по номеру телефона и ответить «Привет, мир», но как это поможет мне попасть в мою квартиру? Нам действительно нужно изменить отображение вашего добавочного номера в системе зуммера вашего здания, чтобы оно указывало на ваш номер телефона Twilio. Не бойтесь, если ваш сервер выйдет из строя или что-то еще, мы уже настроили его для возврата к TwiML Bin, который вместо этого звонит на ваш номер телефона. Инструкции о том, как это изменить, действительно зависят от вашего здания, возможно, вам нужно попросить своего менеджера по зданию сделать это за вас. В зависимости от уровня технофобии они могут позволить или не захотеть позволить вам это сделать (к счастью, в моем случае это не проблема), поэтому, возможно, не говорите им, для чего это нужно. Наверное, все равно не спросят. Вернемся к переворачиванию битов.

Во-первых, давайте просто впустим всех автоматически

Это именно то, о чем будет беспокоиться ваш менеджер по зданию, так что давайте просто сделаем это и уберемся с пути. Вернитесь в свой index.js и измените обработчик app.post('/', ...) на следующее:

app.post('/', (request, response) => {
  let twiml = new twilio.twiml.VoiceResponse();
  twiml.play({ digits: 'ww666ww666ww666' });
  response.type('text/xml');
  response.send(twiml.toString());
});

Разверните его снова с помощью now и обновите URL-адрес веб-перехватчика в Twilio (каждое развертывание является неизменным, поэтому URL-адрес будет новым - вы можете использовать now со своим собственным доменом и псевдонимом новых развертываний, чтобы URL-адрес был постоянным, если хотите). Позвоните по номеру телефона еще раз, и вы заметите, что он делает паузу на 1 секунду, затем нажимает 6 три раза и повторяет это еще два раза. Если ваше здание требует, чтобы вы нажали 9, замените 6 на 9 или другое число.

Затем давайте сделаем его более безопасным

Снова откройте index.js и замените его следующим:

const twilio = require('twilio');
const express = require('express');
let app = express();
// State that persists across requests
let _unlockedAt = null;
app.post('/unlock', (request, response) => {
  _unlockedAt = new Date();
  response.type('application/json');
  response.send({ unlockedAt: _unlockedAt });
});
app.post('/lock', (request, response) => {
  _unlockedAt = null;
  response.type('application/json');
  response.send({ locked: true });
});
app.post('/', (request, response) => {
  let twiml = new twilio.twiml.VoiceResponse();
  if (_isUnlocked()) {
    twiml.play({ digits: 'ww666ww666ww666' });
  } else {
    // Have Twilio fallback to our "Call Me" bin
    throw new Error('Not permitted to unlock');
  }
  response.type('text/xml');
  response.send(twiml.toString());
});
function _isUnlocked() {
  return _unlockedAt && new Date().getTime() - _unlockedAt.getTime() < 30000;
}
app.listen(3000);
console.log(`server running (${process.env.NODE_ENV})`);

Круто, на самом деле это та часть, где мы приступаем к созданию приложения Expo. Давайте пока проделаем эту часть с Snack. Я пошел дальше и создал действительно простое приложение, которое взаимодействует с этой конечной точкой в ​​Snack: Basic Buzzer.

В приложении есть одна кнопка посередине: «Разблокировать». Когда вы ее нажимаете, он отправляет запрос POST на {your-server}/unlock, а затем обновляет дату разблокировки и запускает обратный отсчет. По истечении обратного отсчета мы снова переходим в заблокированное состояние. В качестве альтернативы, если пользователь нажимает «Заблокировать», мы отправляем запрос POST на {your-server}/lock и сбрасываем его в заблокированное состояние. Чтобы показать пользователю небольшую обратную связь, мы отображаем ActivityIndicator во время выполнения HTTP-запросов.

Чтобы проверить это, замените URL-адрес в верхней части примера Basic Buzzer на URL-адрес вашего сервера, затем отправьте запрос на публикацию / на вашем сервере с вашего http-клиента, и он должен выдать ошибку. Затем нажмите «Разблокировать» в приложении и снова отправьте этот почтовый запрос. Вы должны увидеть что-то подобное.

В следующий раз ... подтвердите личность, авторизуйтесь

То, что мы создали, на самом деле отлично справляется со своей задачей, и если вас устраивает безопасность через безвестность, то вы, вероятно, можете на этом остановиться.

Но частично deux я объясню, как добавить аутентификацию Facebook и белый список людей, которым разрешено разблокировать ваш зуммер.

Проект на данный момент: expo / buzzer-part-one.