
Всем привет, на Хабре уже есть несколько статей про автоматизацию игр типа «квесты в реальности» (раз, два, три, четыре, пять...), я хотел бы тоже поделиться своим опытом участия в подобном проекте. В далеком 2015 году мои друзья решили организовать квест типа escape-room «Ограбление банка» в нашем городе. Они знали, что я давно увлекаюсь различной автоматикой, в том числе системами типа «умный дом» на базе open source решений, поэтому попросили помощи в организации игры. Мне эта идея показалось интересной и я согласился — хотелось применить свой опыт и решения для чего то более интересного, чем поморгать лампочкой у себя в квартире.
Я постарался принять участие в полном цикле реализации проекта — от внесения правок в сценарий до последующей обкатки задач, выявления и исправления багов, последующие доработки. Я посетил несколько игр у нас в городе (в 2015 их можно было пересчитать по пальцам одной руки), не для фана, а скорее для получения опыта и реверс-инжиниринга решений, и это было хорошо заметно по реакции организаторов. Но после участия в игре в Москве, я понял настоящий масштаб «бедствия» и мне сильно захотелось сделать не хуже с технической стороны свою работу. Итак, квест «Ограбить банк» в г. Твери, за подробностями как он создавался и развивался в течении нескольких лет прошу под кат.
Описание технических решений
После того, как мои коллеги объяснили мне на пальцах, что от меня хотят и как всё должно работать, у меня в голове буквально за пару минут сформировалась архитектура: центральный сервер с платформой ioBroker, локальные контроллеры на базе плат и модулей Arduino, обмен данными с сервером и между контроллерами по протоколу MQTT. В итоге архитектура получилась примерно следующая:

Помимо взаимодействия контроллера задачи с центральным сервером, нужно было наладить взаимодействие между контроллерами разных квестовых задач. Для этого, по моему мнению, идеально подходил протокол MQTT с брокером на центральном сервере. Клиенты — контроллеры публикуют на сервер свои состояния, подписываются на команды от сервера и состояния других контроллеров. Для реализации этого решения был использован адаптер MQTT — он одновременно был и MQTT брокером и позволял создать иерархию топиков в дереве объектов ioBroker, чтобы использовать данные для визуализации и управления (скриншот ниже еще старой версии “админки”).

Впоследствии я не пожалел, что выбрал именно такое решение:
- MQTT — легковесный протокол, библиотека занимала мало места и его с лихвой хватало даже на Arduino UNO с чипом ATmega328
- При перезагрузке или первом включении контроллеров они по MQTT получали начальные условия старта работы — очень удобно
- Это решение оказалось самым надежным из опробованных и довольно простое для реализации и изучения новичку
По потокам данных получается всего несколько вариантов, самый простой из них — в контроллере задачи №1 возникает событие (нажали кнопку), он публикует в определенный топик состояние кнопки и ее состояние отображается изменением цвета графического элемента на визуальной форме АРМ оператора.

Не менее простой и обратный вариант — нужно вручную включить реле через контроллер задачи №1, подается управляющее событие через VIS-адаптер, который меняет состояние топика этого контроллера, причем с ask=false. Адаптер MQTT получает изменение топика с ask=false, значит этот топик не от контроллера прилетел, соответственно происходит публикация изменения в контроллер, который в свою очередь публикует в ответ подтверждение с ask=true.

Межконтроллерный обмен происходит по событию на одном из контроллеров. К примеру, первый контроллер отработал свою задачу и должен включить реле на втором контроллере — он публикует в общий топик свой статус, брокер отображает его в дереве и на страничке визуализации, так как второй контроллер подписан на этот топик, брокер публикует его во второй контроллер и последний в свою очередь публикует в ответ подтверждение.

В проект еще нужно было добавить задачу взаимодействия с компьютером. Интерфейс был написал на php, страничка крутилась на WEB-сервере с автозапуском в полноэкранном режиме браузера. Интеграция с основной системой осуществлялась посредством драйвера simple-api — через php просто дергались определенные http-запросы к ioBroker. Сам системный блок был спрятан в недрах офисного стола, управление интерфейсом осуществлялось мышкой, а беспроводная клавиатура была у диспетчера квеста.
Визуализация для оператора была разработана в драйвере VIS для одного разрешения — монитора оператора, но впоследствии сотрудники квеста смогли пользоваться и мобильными планшетами с этим же интерфейсом, оказалось удобно для сброса при подготовке к новой игре и для диагностики системы. Интерфейс получился спартанский, без модных дашбордов и рюшек-переключателей, но зато понятный, простой и быстрый. Особенной логики, слоев, графиков и прочего в интерфейсе не нужно было, только иконки для отображения состояния оборудования, кнопки для управления и несколько текстовых полей для вывода режима работы контроллеров и лога работы системы.

На момент разработки проекта других вариантов оформления визуализации особенно и не было. Позже появились адаптеры визуализации как для мобильных устройств (я использую material), так и для стационарных планшетов/компьютеров: habpanel, lovelace, tileboard и другие.
Основная логика была заложена в коде контроллеров, но общее взаимодействие, инициализация параметров для запуска, сервисные функции и пр. — реализовано на основном сервере с помощью адаптера javascript. Код писался на JS с использованием встроенных функций ioBroker с последующим «переездом» на blockly (этот функционал появился позднее начала работ по проекту).

Всего было задействовано несколько скриптов:
- скрипт для первоначальной инициализации системы (первое включение)
- скрипт сброса всех контроллеров перед очередной игрой
- один из контроллеров не сразу «переехал» на MQTT, поэтому некоторое время использовался скрипт для обмена с контроллером через HTTP — GET запросы
- скрипт для ведения отдельного лога хода игрового процесса
Все контроллеры на базе плат Arduino UNO (впоследствии несколько контроллеров пришлось переделать под платы Arduino MEGA — не хватало памяти) оснащались платой расширения Ethernet на базе чипа W5100. Обмен данными между контроллерами и сервером (как писал выше) по протоколу MQTT. Разработка алгоритмов в Arduino IDE велась с использованием стандартных библиотек. По железной части ничего сверхъестественного — максимальное использование готовых модулей и плат расширения с минимумом пайки и без изготовления кастомных плат — всё на макетных платах. Управление нагрузками через модули с реле обычными и твердотельными, транзисторные ключи для светодиодов индикации и маломощной нагрузки. По механической части старался как можно меньше применять подвижные элементы: микровыключатели, толкатели, Э/М замки и больше использовать готовые модули светодиод-фотодиод (открытые оптопары), твердотельные реле, обычные магнитные замки, считыватели бесконтактных карт и герконовые датчики. Несколько фото ниже:




Питание контроллеров на месте осуществлялось через самодельные POE-переходники — по витой паре незадействованные жилы «вещали» 12В постоянного тока. Преобразование на платах контроллеров через готовые платы DC-DC до 5В — от которых питались сами платы Arduino + Ethernet и маломощная нагрузка с логикой 5В: слаботочные светодиоды, реле и пр. Более мощная нагрузка 12В: магнитные замки, мощные реле или контакторы, различная светотехника — использовались отдельные кабельные линии проводом ШВВП или ПВС. В основной шкаф автоматики подвели два ввода 220В переменного тока и через АВР на контакторах подключили ИБП, который в свою очередь был подключен через байпас, для удобства обслуживания. Для питания всей автоматики и слаботочки, в шкафу установили мощные блоки питания 2 по 12В и один на 5В. От шкафа автоматики пустили кабельные линии 220В для питания компьютеров и различной периферии квеста: от пых-пых до виу-виу))


Остальные решения довольно стандартные для подобных проектов. Система видеонаблюдения на проводных IP-камерах, обязательно с ИК-подсветкой и встроенными микрофонами. Видеопоток используется в одной из задач квеста и дополнительно обрабатывается на ПК диспетчера квеста, используется open source программное обеспечение (ZoneMinder). Локальную сеть контроллеров Arduino отделили от остальных сетей, чтобы поток от видеокамер не нагружал и без того слабые чипы W5100 ethernet-плат.
Громкая связь с участниками игры с использованием обычного советского усилителя и встроенных потолочных динамиков.
В конце хотел описать немного центральный сервер. Платформа ioBroker развернута на ARM-одноплатнике BananaPi, мощности которого оказалось достаточно для всех задач. Окружение — операционная система Armbian, пару bash скриптов для работы с GPIO и для создания резервных копий в облако на Яндекс.Диск. Используются несколько GPIO для индикации состояния работы отдельных модулей и адаптеров (светодиоды) и кнопка для корректного выключения системы. На фото 19” шкафа выше видно, что плата в стандартном дешевом корпусе из оргстекла, впоследствии она была установлена в 1U корпус с нормальным блоком питания и прочей периферией.
Баги, подводные камни, трудности
Основную архитектуру мы с коллегами довольно хорошо продумали заранее (я делал проект) и многие узлы удалось собрать и протестировать «на столе», поэтому кардинальных изменений не было. Мелкие «шероховатости» исправлялись на месте. Основные проблемы, решение которых заняло довольно много времени:
- Нехватка памяти Arduino на чипе 328, переезд на плату Arduino MEGA. Предсказуемо уперся по некоторым контроллерам в память чипа. Основное время ушло на переделку плат расширения.
- Глюки в работе с MQTT-драйвером довольно оперативно решались автором проекта ioBroker.
- Долгий и непростой процесс подбора браузера для нормальной работы визуализации в драйвере VIS. Оказалось непросто работать с этим адаптером. В итоге редактирование осуществлял в браузере Chrome, а runtime оператор запускал через браузер Dragon определенной версии. По мере исправления ошибок, полностью переехали на браузер Chrome последней версии.
- Постепенное создание антивандальных решений — отказывались от микровыключателей, механических кнопок и толкателей, пленочных клавиатур и т.п.
- Электромеханические замки «Шериф» оказались очень низкого качества, приходилось по месту менять на обычные электромагнитные замки.
- Нестабильная работа контроллеров Arduino при работе IP-камер, в итоге разделили сети и всё заработало как надо.
Заключение
Весь проект от изучения и согласования сценария до запуска первых тестовых групп занял около полугода — да много, но это был первый опыт и к тому же, я почти не отставал от основных работ по стройке/ремонту помещений. Плюс к тому, было много работы «в стол» — в основном при использовании отдельных модулей Arduino, потому как они работали не совсем так, как я предполагал. При реализации проекта максимально старались придерживаться следующих принципов:
- Проектом подразумевалось обслуживание и мелкий ремонт любым инженером, который хоть раз держал в руках паяльник, знает что такое Arduino и сможет «помогать» распаянным на плате светодиодом.
- Разработка в Arduino IDE с использованием стандартных библиотек для максимальной простоты.
- Максимальное использование готовых, распространенных модулей в проекте для простоты обслуживания и замены
- Использовать стандартные протоколы и сети передачи данных
- Максимально уменьшить количество механических деталей для долговечности и антивандальности.
По итогу, в первые пару недель получилось избавиться от всех мелких недостатков и сейчас система почти в первоначальном окружении работает уже больше 4-х лет.
Автор: Андрей Андреев