При проектировании системы видеонаблюдения большого объекта потребовалось разместить камеры на плане, учитывая их углы обзора/наклона и получаемую плотность пикселей (необходима для определения зон задач идентификации, распознавания и т. п.). Вcпомнил математику 8 класса и сделал параметрический блок для AutoCAD, потом захотелось большего — чтобы прикинуть расстановку камер мог каждый желающий. Только была небольшая проблема — я не программист...

БОЛЬШОЕ СПАСИБО всем тем, кто делится различными обучающими материалами — именно благодаря вам можно попробовать сделать что‑то новое.

Статья можно сказать уровня «джунам от джуна» или немного о том, как можно написать свое приложение отличное от калькулятора и to‑do листа. Сейчас, когда смотрю на итоговый результат, иногда думаю: «Это точно я сделал?»:)

Небольшое замечание

На Хабре мы с братом «сидим» под одним ником, поэтому пусть вас не смущает, что часть статей в профиле написана программистом:) Он же мне и помогал в освоении JS и всячески поддерживал, хотя кажется не верил, что я доделаю проект до уровня, чтобы можно было показать не сильно краснея.

Предисловие

Листая Хабр, наткнулся на любопытный пост Эффективный расчёт области видимости и линии взгляда в играх — как раз то что нужно, чтобы начать осуществлять задуманное.

Решено — это будет SPA‑приложение, а для его создания нужно подучить JavaScript. Не так страшно, когда есть Замечательный учебник, статьи на Хабре и Stackoverflow — место, где можно найти ответы на свои вопросы (не всегда верные или идеальные, но лучше, чем ничего). СSS и HTML на простейшем уровне я уже немного знал.

Как оказалось, встроенный в JS канвас весьма примитивен, и тут встретился цикл статей «Знакомимся с Fabric.js» 1, 2, 3, 4 (это «перевод» части справки фреймворка, но я тогда об этом не знал). Fabric.js создает весьма удобный дополнительный слой абстракции, с помощью которого объекты канваса становятся JS‑объектами и манипуляции идут уже с ними.

Можно было попробовать реализовывать на Pixijs (статья), но я счел избыточным такой фреймворк для моей задачи.

Так потихоньку ковыряя JS и решая простейшие математические задачи с помощью статей (1, 2, 3), я «выпустил» первую версию программы (видео). Ее пришлось «забросить», так как на работе засел за изучение новых для меня тем.

Спустя год

Вернувшись к проекту, я его критически осмотрел и понял: нужно сделать рефакторинг кода, устранить ошибки, немного улучшить внешний вид и расширить функционал. Серверную часть мне согласился написать брат (Node.js, express, SQLite).

Проектный подход в действии
Проектный подход в действии

Выбор инструментария

Ранее при создании менюшек и диалогов очень раздражали постоянные querySelector и обработка eventListner, поэтому решил, что нужно подучить что‑то модное, чтобы жизнь была веселее. Выбор пал на Vue 2 (Vue.js), так как обещался низкий порог входа и развитое сообщество (Vue 3 не рискнул именно из‑за «новизны»).

Для «вкатывания» во Vue очень помог цикл статей Vue.js для начинающих (ссылка на 11 урок, так как в нем есть ссылки на все остальные уроки), хотя в комментариях писали «Для кого это? Кто не умеет читать документацию?!». Ну хотя для тех у кого нет опыта работы с другими фреймворками и еще не умеют читать код «фрагментами без обвязки».

Если раньше я писал код JS в Atom, то с изучением Vue открыл для себя VS Code (с плагином Vetur), а также встроенных помощников в vue‑cli — контроля внешнего вида кода ESLint и систему сборки проекта на базе webpack. Для ведения версий файлов начал использовать GitHub Desktop. Жить стало веселее.

В первой версии программы хранение данных у меня было в глобальных переменных, в экосистеме Vue для этого есть Хранилище (Store) Vuex с немного загадочной для начинающего логикой. Помогли разобраться полезные статьи и ценные комментария в них — 1, 2, 3. Хотя сейчас топят за pinia, переписывать уже не стал.

Очень сильно при отладке помогает расширение для браузера — Vue Devtools, которое добавляется в «Панель для разработчика».

Для получения данных с API остановился на Axios: Axios или Fetch: чем пользоваться в 2019 году?

Для канваса так и остался Fabric.js.

Архитектура проекта

Ранее я не сильно заморачивался архитектурой (с JS бы совладать), но при рефакторинге стало понятно, что при создании редактора канваса нужно отделять сущности:

  • Объекты — линии, прямоугольники, камеры и т. п., которые состоят из нескольких объектов fabric.js и вспомогательных данных (типа id, type и т. п.).

  • Layout Manager — ничего не знает о fabric.js и о внутреннем устройстве объектов, а только манипулирует ими на основании id/type и публичных методов. Хранит в себе перечень объектов для канваса.

  • Canvas Editor — почти ничего не знает об объектах (совсем оторвать не получилось и пришлось сделать пару костылей). Выкладывает на канвас то, что ему передает Layout Manager, а также обновляет данные в Хранилище. Отвечает за канвас и манипуляции с ним.

  • Хранилище — хранит в себе информацию обо всех объектах проекта в минимальном виде, но только в глобальных координатах (а не координатах канваса). Так например, зоны обзора строятся каждый раз заново. Используется как источник данных для сохранения и загрузки данных проекта. Является более общим хранилищем данных, чем хранилище объектов в Layout Manager, так как содержит данные нескольких площадок (канвасов).

Получилось «не очень», но все равно стало удобнее работать. Эх вышла бы немного пораньше статья Frontend архитектура MVP (Model‑View‑Presenter).

Vuex разбил на модули по функционалу (а не как чаще делают по Actions, Mutations и т. п.):

  • авторизация,

  • перечень проектов,

  • данные графического редактора (инициализируются при выборе проекта):

    • перечень площадок,

    • перечень объектов,

    • данные для расчета системы хранения видеонаблюдения,

    • настройки.

Авторизация сделана на базе токена (строки), получаемой от бекенда и хранимой в HttpOnly coockie. Просто и незамысловато:)

Немного о Fabric.js

К сожалению, он хоть и дает возможность оторваться от манипулирования канвасом, но остается весьма своеобразным. Так линия — это нарисованная диагональ в BBox (boundary box). Все хорошо, пока не захочется ее отредактировать с помощью ручек BBox — толщина линии становится слабо управляемой. В итоге от предоставляемых ручек решено было отказаться и сделать свои, например, у меня линия — это 4 объекта fabric.js (без отображения BBox): сама линия (перерисовывается при таскании ручек), 2 ручки‑кружочка и вспомогательная скрытая линия для более «цепкого» выделения.

Аналогично, решение для зумирования, предлагаемое авторами фреймворка меня не устроило из‑за «расплывающихся» объектов и ограниченности рабочей области. В итоге зумирование и панирование сделал без встроенных в фреймворк методов (путем перерасчета объектов).

Графический интерфейс

Придумать графический интерфейс с нуля не так‑то просто, как может показаться на первый взгляд.

В первой версии я «вдохновлялся» ленточным интерфейсом от Microsoft — получилось что‑то «так себе». Поговорил со знакомым маркетологом, тот сказал — смотри веб‑интерфейсы программ для дизайнеров (figma, supa и т. п.). Посмотрел, переработал, добавил пару подсмотренных идей у Яндекс‑карт и конфигуратора серверов Dell:0.

Конечно, можно попробовать самому сделать более‑менее симпатичные элементы интерфейса, но для pet‑проекта imho использование UI‑фреймворка более чем достаточно и был взят Vuetify (хотя также есть альтернативный Quasar, который выглядит «корпоративненько»:) ). Благодаря Vuetify не пришлось хотя бы с отступами сильно возиться и адаптивностью (хотя благодаря flexbox сейчас не нужны всякие грязные трюки с CSS). Также Vuetify предоставляет элементы с широким функционалом настройки — например, data‑tables: ничего самому писать не надо, остается только сконфигурировать. Говорят, что Vuetify потихоньку помирает, но это не точно.

Что еще?

Так как системы видеонаблюдения делаются не только у нас в стране, решил добавить мультиязычность (i18n) — оказалось не так сложно (к сожалению доступ к статье на Хабре закрыт, поэтому ссылка на сторонней ресурс «зеркало»). Программы для создания JSON‑файлов перевода не нашел, поэтому их веду в Excel, который мне через формулу собирает JSON‑строку, которую я уже копирую в файлы локализации. Так себе решение и что‑то нужно с эти делать, хотя бы кнопку в файле xls‑прилепить, при нажатии на которую файлики локализации будут перезаписываться:)

Чтобы все было как у «взрослых» конечно же потребовался роутинг (работа со строкой ввода) — тут все стандартно Vue Router. Не стоит забывать, что пользователь может и страницу перезагрузить и кнопками браузера «вперед/назад» попользоваться.

Программа предназначена больше для наружного видеонаблюдения (в помещениях и так примерно ясно, как будет показывать), поэтому добавил вставку плана из OpenStreetMap (OSM c OpenLayers). Если внезапно:) будет большой спрос на вставку карт, то можно развернуть карты на сервере (а не использовать внешний API), а вот за Google‑карты и Яндекс‑карты при превышениях лимитов уже нужно будет платить.

Данные о камерах у меня есть — так почему же не прикрутить расчет системы хранения? Ничего сложного, только основная характеристика — битрейт от камер сильно зависит от снимаемой сцены. Но все‑таки как‑то емкость архива нужно прикидывать — в итоге нашел рекомендации Hikvision, которые и легли в основу расчетов.

Казалось бы вот и все — приложение готово, можно и выпускаться. Какая же программа без справки? Разработка документации на VuePress. Все хорошо, но есть нюанс — подготавливать графические материалы (например, картинки с выносками над элементами управления) нужно в какой‑нибудь другой программе. К тому же теряется интерактивность. Попробовал Dr.Explain — не впечатлило, хотя что‑то в нем есть: для создания толмутов документации для госструктур наверное годный продукт. Опять же наличие упоминаний «Сделано в Dr.Explain» в бесплатной версии ПО как‑то не очень. Поиски бесплатных аналогичных программ для документирования ничего не дали. В итоге остановился на VuePress.

И последний штрих — создание небольшого видеоролика про кролика Как снять обучающий видеоролик: 10 секретов технического писателя. Захват экрана делаю в CamStudio, а для аудио использую Audacity.

Тестирование, автотесты, QA — наверное что‑то хорошее, раз так много на Хабре о них часто пишут. Не знаю:)

Развертывание приложения

Приложение написано, остается поработать немного DevOps:

  • Собрать проект: в моем случае vue‑cli все делает за меня — минифицирует и склеивает всю кучу моих мелких файлов в несколько больших JS‑ и CSS‑ файлов.

  • Зарегистрировать веб‑домен: при выборе регистратора заметил, что нужно смотреть, сколько будет стоить продление на следующий год, а не первоначальный платеж‑замануха.

  • Оформить SSL‑сертификат: сайты с доступом по http сейчас «не котируются». SSL‑сертификат можно получить у регистратора/хостера (как правило за денежку на год) или, как вариант, раз в 90 дней получать его в Let's Encrypt.

  • Завести сервер: реальную железку или арендовать виртуальный (виртуальную машину). Мне было проще поднять дома, так как имеется «белый» ip‑адрес, используя небольшой безвентиляторный ПК на базе Celeron J1900 / 4Gb. На него накатил Linux Mint 21, удаленный доступ (tigervnc), node.js и прочие мелочи. Отказоустойчивость данного решения — ну совсем «так‑себе», потом как‑нибудь переделаю.

  • Настроить веб‑сервер, который будет отдавать JS‑файлы: в моем случае — nginx. В случае размещения сервера дома нужно еще пробросить порты на маршрутизаторе.

  • Поднять почтовый сервис для регистрации пользователей и поддержки или воспользоваться готовым (например, я использовал VK WorkSpace с бесплатным базовым тарифом — не знаю, доступен ли тариф сейчас).

Почесать репу дня три и получить итоговый результат.

Для тех, кто не хочет регистрироваться, но желает пощупать — есть тестовая учетная запись: test@survy.ru / 123 (просьба не «шалить»).

Что впереди?

Проект все равно еще на стадии MVP: нужно делать учет дисторсии объективов (тут уже математикой 11 класса пахнет), hotkeys, отмену последних действий и т. п. — что уже есть «у всех». Исправление багов также никто не отменял.

P. S. Для тех кто дочитал: вам фронтендер не нужен?:)

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


  1. Dart55
    00.00.0000 00:00

    На Хабре мы с братом «сидим» под одним ником, поэтому пусть вас не смущает, что часть статей в профиле написана программистом:)

    Зачем?


    1. little-brother Автор
      00.00.0000 00:00

      Почему бы и нет? Так исторически получилось, как-то не напрягает.


  1. anonymous
    00.00.0000 00:00

    НЛО прилетело и опубликовало эту надпись здесь


    1. little-brother Автор
      00.00.0000 00:00

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

      Спасибо, подкорректировал.

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

      С шаблоном - это наверное сюда: https://pikabu.ru/story/uglyi_obzora_kameryi_videonablyudeniya_ot_chego_zavisyat_i_kak_izmerit_7546670#comments


      1. anonymous
        00.00.0000 00:00

        НЛО прилетело и опубликовало эту надпись здесь


        1. little-brother Автор
          00.00.0000 00:00

          Пока основная задача - сделать расчеты с учетом дисторсии, так как она сильно влияет на поле зрения. Сейчас пошла мода ставить объективы с дисторсией даже на камеры с оптикой 6-8 мм (угол же обзора больше, неважно что по краям ничего не разобрать).


  1. cranedy
    00.00.0000 00:00

    Классно, что наконец появляются бесплатные аналоги всяким jvsg, которые, конечно, круты, но хотят денег. Удачи.


    1. little-brother Автор
      00.00.0000 00:00

      Хотеть денег за свою работу вполне нормальная позиция (опять же с учетом того, что они разрабатывают узкоспециализированное ПО). У них основной рынок - это буржуи, так как у нас не привыкли платить за ПО.