В этом посте, состоящем из двух частей, я объясню, как создать этот необычный инструмент, чтобы легко впустить друзей в вашу квартиру.
Постановка задачи
Я не всегда обращаю внимание на свой телефон, поэтому, когда друзья приходят и пытаются проникнуть в мою квартиру, я иногда пропускаю звонки, и они застревают у двери, пока я не отвечу или они не сдадутся и не уйдут.
Ограничения
Я не хочу, чтобы мне приходилось платить много денег за решение, потому что меня это мало волнует, это просто развлечение, которое приятно иметь. У меня также есть только один день, чтобы сделать это - мы делаем «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.