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

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

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


Chima Open Door на Pebble и iOS

К настоящему моменту в нашем дверном эксперименте мы разработали решения для интеграции со Slack, нативные приложения iOS и Android, Apple Watch и Pebble. Остановлюсь подробнее на архитектуре мобильных приложений. Признаю, что финальный продукт слегка переусложнён, но мы так его любим!


Архитектура проекта нашего IoT дверного замка

Что конкретно происходит, когда вы нажимаете кнопку в своём приложении iOS/Android? Отправляется HTTP-запрос к облачному серверу, который является сигналом для отправки сообщения к демону дверного звонка через клиентский сервер, который затем указывает релейной плате открыть замок.

Традиционно дверной замок открывается нажатием кнопки рядом с дверью. Но современные технологии позволяют выйти за пределы непосредственной физической кнопки. Вдобавок к физической кнопке, которая сигнализирует Doorlock Daemon на диаграмме, мы добавили ещё два триггера: облачный триггер и Bluetooth Low Energy (BLE) триггер, благодаря нашему выбору железа.

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

С нажатия кнопки до записи, сохранённой на сервере Skygear



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

Две вещи происходят на облачном сервере. Во-первых, сохраняется запись. Мы выбрали сервер Skygear Cloud Database, который позволяет синхронизировать данные с облаком. Сервер ведёт лог запросов на открытие двери.

SKYDatabase *db = [[SKYContainer defaultContainer] publicCloudDatabase];
SKYRecord *openDoor = [SKYRecord recordWithRecordType:@"OpenDoor"];
[db saveRecord:openDoor completion:^(SKYRecord *record, NSError *error) {
    NSLog(@"saveOpenDoorRecordWithCompletion failed: %@", error);
    if (completion) {
        completion(error);
    }
}];

Как только запись сохранилась, срабатывает функция after_save из набора Skygear Cloud Functions, которая запускает в облаке наш код без необходимости развёртывания непосредственно на сервере.

Функция after_save вызывается самим фактом сохранения записи. Асинхронно вызывается def after_open_door_save(record, original_record, db):, когда сохраняется запись типа 'OpenDoor'. Эта функция публикует сообщение в канале 'xxx-channel'.

@skygear.after_save('OpenDoor', async=True)
def after_open_door_save(record, original_record, db):
    publish('xxx-channel', {
        'source': 'record-after-save',
        'data': record.get('data', None),
    })

Node Client и Clojure Server на Raspberry Pi


Следующий шаг — создать слушателя для запроса. Вот где пришло время клиента Node и сервера Clojure на Raspberry Pi. Клиент Node слушает сообщения на указанном канале сервера Skygear. Сервер Clojure — единственный, у кого есть право доступа к схеме Raspberry Pi 3. Клиент Node выдаёт запрос к серверу Clojure, как только получает сообщение.

Вот скрипт клиента Node, он содержит код, связанный с нашей конкретной конфигураций на Skygear. Указанные endPoint и API Key нужны для доступа к основному серверу на Skygear. skygear.on('xxx-channel', onReceiveOpenDoor) означает обратный вызов функции (onReceiveOpenDoor) при получении сообщения на канале 'xxx-channel'.

function onReceiveOpenDoor(data) {
  console.log('daemon-trigger-skygear: open door');
  exec(`curl localhost:8090 --header 'X-Source: Skygear'`);
}
 
skygear.config({
  endPoint: 'https://chimagun.skygeario.com/',
  apiKey: apiKey,
}).then(() => {
  skygear.loginWithUsername('xxx', 'xxx').then(() => {
    skygear.on('xxx-channel', onReceiveOpenDoor);
  });
});

Сервер Clojure напрямую контролирует контакты General Purpose Input/Output (GPIO) на Raspberry Pi. GPIO это штырьки на Raspberry Pi 3. Они подключены к внешней цепи, которая соединяется с дверным магнитом.



Вот код Clojure, который показывает, как Raspberry Pi открывает дверь. Когда сервер Clojure получает запрос от клиента Node, то открывает замок на три секунды. Но если в течение этих трёх секунд поступит новый запрос, то таймер переставляется ещё на три секунды. Когда время заканчивается, дверь опять запирается.

; listen on unlock-chan for unlock events
  ; if a new unlock event is received before the 3000ms timeout, the door is kept open.
  (go-loop [unlock nil]
           (when unlock
             (sh "gpio" "write" "1" "1")
             (loop [[trigger _] [unlock nil]]
               (when trigger
                 (log/info (str "Unlock triggered by " (:source trigger)))
                 (recur (alts! [unlock-chan (timeout 3000)]))))
             (sh "gpio" "write" "1" "0")
             (log/info "Door Locked"))
           (recur (<! unlock-chan)))
 
  ; http event listener
  (run-server (fn [req]
                (>!! unlock-chan {:source (or (get-in req [:headers "x-source"]) :network)})
                {:status 200})
              {:ip "127.0.0.1" :port 8090})

Примечание: Skygear использует американский AWS, тогда как дверь и Raspberry Pi находятся в Гонконге. Фактически, наш запрос ???? (Chima Open Door) путешествует по всему миру, прежде чем достигнет двери.

Почему Raspberry Pi?


Вы можете спросить, почему мы выбрали именно Raspberry Pi. Мы рассматривали и платы Arduino, потому что у нас в офисе такие есть. Дело в том, что мы не могли использовать конкретную модель Arduino, поскольку хотели синхронизировать данные с Skygear JS SDK, а эта конкретная Arduino не позволяла установить сервер Node.

Кроме того, Raspberry Pi поддерживает Bluetooth Low Energy (это значит, что мы можем открывать дверь, используя третий метод, Bluetooth).


Raspberry Pi с Linux совместима с open-source бессерверной платформой Oursky



Дополнительные интеграции


Принимая во внимание, что приложение только для внутреннего использования, мы реализовали кастомную команду Slack /chima-open-door на открытие двери, поскольку каждый сотрудник Oursky имеет доступ к Slack.

Позже другие коллеги вовлеклись в проект и написали приложение WatchOS и приложение Android, которые мы выложили на внутренней платформе. Помимо нажатия кнопки внутри приложения, мы также обеспечиваем альтернативные способы открытия двери, такие как прикосновение iOS 3D, расширение Today, виджет Android и даже интеграция с Pebble, поскольку некоторые из наших разработчиков носят такие часы.



Вот так всё сделано! Прежде чем вы погрузитесь в разработку, учтите два фактора: обратный ток (в данном случае для Raspberry Pi) и безопасность каждой из ваших интеграций. Например, мы также интегрировали доступ Bluetooth-приложения через Bluetooth Low Energy (BLE), что является самостоятельно реализуемым вариантом двухфакторной аутентификации. Среди других интеграций можете рассмотреть уведомления, когда дверь открыта (звонок, светодиод).

Если хотите узнать о любой из упомянутых технологий, не стесняйтесь выходить на контакт!

Хочу выразить благодарность моим коллегам Дэвиду Нг, Борису (akiroz), Брайану (b??????) и Мэю Юнгу за работу над Android-приложением, реализацию схемы и Clojure, приложение Pebble и текст этой статьи, соответственно. Это командная работа!



Ссылки на репозитории/файлы
> CloudCode
> Клиент iOS
> Клиент Android
> Клиент Pebble
Поделиться с друзьями
-->

Комментарии (22)


  1. VMichael
    23.06.2017 14:15
    +4

    А зачем все это?
    Следующий этап — как накатить патч на замок и что делать есть хакнули ваш замок?


    1. TimsTims
      23.06.2017 18:17

      Нет, следующий — собирать метрику входа / выхода людей, доставки пиццы, и датчика температуры. Анализ и прогнозирования изнашивания замка. Снятие пульса и температуры ладони с открывающего дверь человека и ведение его медицинской био-карты, а затем большой анализ всего этого и называние это big data, ведь люди любят все усложнять.


      1. myrkoxx
        24.06.2017 22:19

        Не знаю, как на счет вашего примера, но вот если бы эта штука автоматически открывала двери (именно открывала, не только замок) то било б огонь. Идешь такой с сумками, а тебе дверь раз и открылась когда подошел. Не надо ставить их на пол, доставать ключи из сумки/кармана.


        1. VMichael
          25.06.2017 22:53

          Ну это (открытие двери) не сложно сделать.


  1. vesper-bot
    23.06.2017 16:19
    +1

    Теперь весь мир сможет узнать, что вы открыли дверь. :D


  1. Regis
    23.06.2017 17:11

    Что будет, если AWS снова "приляжет"? Вы не сможете войти в офис?


    1. kirillaristov
      23.06.2017 21:14

      Да, делать замок, рассчитывая на постоянную стабильность двух каналов связи (телефон-облако, облако-офис) — это оптимистично.
      А вот сделать бы это с помощью rfid, вклеенного в телефон — было бы и удобно и надежно.


    1. nbytes
      23.06.2017 21:15

      Это же перевод, плюс ко всему тут вроде есть реализация через BT, а вот что делать если приляжет электростанция.


      1. da411d
        23.06.2017 23:14

        с ноги


        1. da411d
          23.06.2017 23:22

          или предвидить клемы для подключения внешнего акумулятора


      1. bano-notit
        23.06.2017 23:57

        Тогда, мой старый друг ;D, поможет стандартный метод с отвёрткой и молотком. Да и вообще говоря, там на фотографии даже есть замочная скважина, так что физический метод вполне сработает.


        1. Germanets
          26.06.2017 09:39

          Да и вообще говоря, там на фотографии даже есть замочная скважина, так что физический метод вполне сработает.
          — управляемый замок, судя по статье — электромагнитный, а тот, что на двери — это уже второй, механический. Так что если вдруг всё это дело решит повиснуть и больше не открывать двери, а в офисе никого не будет — придётся искать обходные пути… Самый печальный вариант — отключать свет и ждать, пока разрядится аккумулятор на замке, если такой есть.


          1. bano-notit
            27.06.2017 02:35

            Но метод с отвёрткой и молотком всё же сработает, дверь то стандартная офисная, а не семислойная гаражная с интереснейшим механизмом нескольких обратных засовов...


  1. superconductor
    24.06.2017 09:21

    Отличный троллинг на тему IoT и управления через смартфон! А если это не троллинг, то я поражен масштабами overengineering'а на тему удалённого открывания замка.


  1. D3fl4t3
    24.06.2017 10:29

    Интересно, и сколько времени проходит от момента нажатия кнопки до разблокировки двери? Даже секунда будет раздражать, если дверь открывают достаточно часто, и, как мне кажется, смарт-карты в этом плане гораздо удобнее.


  1. Mirza
    24.06.2017 11:54

    Здорово написали ;) я думал, что слишком толсто, но таки повелись :)


  1. ZaitsXL
    24.06.2017 14:52

    замок с вайфаем — это еще не IoT


  1. bano-notit
    25.06.2017 19:11

    А у меня у одного не работают ссылки на gitlab?


  1. Frolls
    26.06.2017 09:14

    В итоге Вы получили дверь, которую не открыть ключом, и которая откроется автоматически при пропаже напряжения в офисе?


    1. Germanets
      26.06.2017 09:42

      Уж лучше такой вариант, чем самодельные непродуманные схемы, в которых есть источник резервного питания)


  1. Germanets
    26.06.2017 09:34

    А можете дополнить пост или прикрепить к комментарием электрические схемы подключения и питания замка, кнопок, Raspberry Pi и т.д.?


    1. Germanets
      26.06.2017 09:39

      Увидел, что перевод, вопрос отпал.