Как переусложнить дверной замок

в 8:55, , рубрики: IoT, Raspberry Pi, дверной замок, Разработка для интернета вещей

Как переусложнить дверной замок - 1

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

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

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

Как переусложнить дверной замок - 2
Chima Open Door на Pebble и iOS

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

Как переусложнить дверной замок - 3
Архитектура проекта нашего IoT дверного замка

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

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

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

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

Как переусложнить дверной замок - 4

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

Две вещи происходят на облачном сервере. Во-первых, сохраняется запись. Мы выбрали сервер 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. Они подключены к внешней цепи, которая соединяется с дверным магнитом.

Как переусложнить дверной замок - 5

Вот код 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).

Как переусложнить дверной замок - 6
Raspberry Pi с Linux совместима с open-source бессерверной платформой Oursky

Как переусложнить дверной замок - 7

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

Принимая во внимание, что приложение только для внутреннего использования, мы реализовали кастомную команду 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: gitlab.com/oursky/doorlock-cloudcode
Клиент iOS: https://gitlab.com/oursky/doorlock-ios
Клиент Android: https://gitlab.com/oursky/doorlock-android
Клиент Pebble: https://gitlab.com/oursky/doorlock-pebble

Автор: m1rko

Источник

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


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