Русский
Русский
English
Статистика
Реклама

Iot платформа

Вернуть пропавший скутер, или история одного IoT мониторинга

23.09.2020 20:15:33 | Автор: admin

Год назад мы запустили пилотную версию промо проекта по децентрализованному прокату электроскутеров.


Изначально проект назывался Road-To-Barcelona, позже стал Road-To-Berlin (отсюда встречающиеся на скриншотах R2B), а в итоге и вовсе был назван xRide.


Основная идея проекта была в следующем: вместо того чтобы иметь централизованный сервис проката автомобилей или скутеров (речь пойдет о скутерах aka электро-мотоциклах, а не kickscooter/самокатах)
мы хотели сделать платформу для децентрализованной аренды. О сложностях с которыми мы столкнулись уже писали ранее.


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


Пользователь устанавливал iOS или Android приложение на телефон, подходил к понравившемуся ему скутеру, после чего телефон и скутер устанавливали peer-to-peer соединение, происходил обмен ETH и пользователь мог начать поездку включив скутер через телефон. По завершении поездки так же можно было провести оплату поездки за счет эфира из кошелька пользователя на телефоне.


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


Так в целом и выглядел наш пилот, запущенный в сентябре прошлого года в двух городах Германии: Бонн и Берлин.



И вот, однажды, в Бонне, ранним утром наша команда поддержки (находящаяся в локации для поддержания скутеров в работоспособном состоянии) была поднята по тревоге: один из скутеров бесследно исчез.
Как его найти и вернуть?


В этой статье я расскажу об этом, но для начала о том как мы построили нашу собственную IoT платформу и как мы осуществляли мониторинг над ней.


Что и зачем мониторить: скутеры, инфраструктура, зарядки?


Итак, что же мы хотели мониторить в нашем проекте?
В первую очередь это сами скутеры электроскутеры сами по себе довольно дорогие, нельзя запускать такой проект не будучи достаточно подготовленными, по возможности хочется собирать как можно больше информации о скутерах: об их местоположении, уровне заряда, итд.


Помимо этого, хотелось бы отслеживать состояние нашей собственной IT инфраструктуры базы, сервисы и все что им необходимо для работы. Нужно было отслеживать и состояние "умных зарядок", на случай если они сломались или в них кончились полные батареи.


Скутеры


Что же из себя представляли наши скутеры и что мы хотели о них знать?


Первое, и самое существенное GPS координаты, так как благодаря им мы можем понимать, где они находятся и куда двигаются.


Далее заряд батареи, благодаря ему мы можем определять, что зарядка скутеров подходит к концу и отправить juicer'а или хотя бы предупредить пользователя.


Конечно, необходимо также проверять что происходит с нашими Hardware компонентами:


  • работает ли Bluetooth?
  • работает ли сам GPS модуль?
    • так же у нас была проблема с тем, что GPS мог отсылать неверные координаты и "залипать", а определить это можно было только на уровне дополнительных проверок на скутере,
      и нотифицировать поддержку как можно скорее для устранения проблемы

И последнее: проверки софтверной части, начиная с ОС и загрузки процессора, сети и диска, заканчивая уже более специфичными для нас проверками наших собственных модулей (jolocom, keycloak).


Hardware



Что же представляла наша "железная" часть?
Учитывая максимально сжатые сроки и необходимость быстрого прототипирования мы выбрали для себя максимально простой для реализации и подбора компонентов вариант Raspberry Pi.
Помимо самого Rpi мы имели кастомную борду (которые мы сами разработали и заказывали в Китае для ускорения процесса сборки конечного решения) и набор компонентов реле (для включения/выключения скутера), считыватель заряда батареи, модем, антенны. Все это было компактно укомплектовано в специальную коробочку "xRide box".


Следует также отметить, что вся коробочка питалась дополнительным павербанком, который в свою очередь питался от основной батареи скутера.
Это позволяло использовать мониторинг и включать скутер, даже после окончания поездки, так как основная батарея отключалась сразу после поворота ключа зажигания в положение "off".


Docker? Plain linux? и деплой


Вернемся к мониторингу, итак Raspberry что же мы имеем?


Одна из первых вещей которую мы хотели использовать для ускорения процесса деплоя, обновления и доставки компонентов на физические устройства был Docker.


К сожалению, довольно быстро стало ясно что Docker на RPi хоть и работает, но дает достаточно много накладных расходов, в частности по энергопотреблению.


Разница с использованием "нативной" ОС пусть и не была настолько сильной, но все же достаточной чтобы мы опасались возможности слишком быстрой потери заряда.


Второй причиной стала одна из библиотек наших партнеров на Node.js (sic!) единственный компонент системы, который не был написан на Go/C/C++.
Авторы библиотеки не успели вовремя предоставить рабочую версию на любом из "нативных" языков.
Мало того, что нода сама по себе не является самым элегантным решением для низкопроизводительных девайсов, так еще и сама библиотека была весьма прожорлива по ресурсам.


Мы поняли, что при всем желании использование Docker для нас будет слишком большим оверхедом. Был сделан выбор в пользу нативной OS и работы под ней напрямую.


OS


В итоге, качестве ОС мы, опять же, избрали самый простой вариант и использовали Raspbian (сборка Debian для Pi).
Весь наш софт мы пишем на Go, поэтому и основной hardware-агент модуль в нашей системе мы также написали на Go.
Именно он и отвечает за работу с GPS, Bluetooth, считывание заряда, включение скутера, итд.


Деплой

Тут же встал вопрос о необходимости реализации механизма доставки обновлений на девайсы (OTA) как обновлений самого нашего агента/приложения, так и обновления самой ОС/"прошивки"
(так как новые версии агента могли требовать обновлений ядра или компонентов системы, библиотек итд).


После довольно долгого анализа рынка выяснилось, что существует довольно много решений для доставки обновлений на девайс.
От относительно простых утилит, по большей части ориентированных на обновление/dual-boot вроде swupd/SWUpdate/OSTree до полноценных платформ вроде Mender и Balena.


В первую очередь мы решили, что нас интересуют именно end-to-end решения, поэтому выбор сразу пал на платформы.
Самым Balena была исключена ввиду того, что фактически использует тот же самый Docker внутри своего balenaEngine.
Но отмечу, что несмотря на это, в конечном итоге мы постоянно использовали их продукт Balena Etcher для флеша прошивок на SD карты простая и крайне удобная утилита для этого.


Поэтому в итоге выбор пал на Mender. Mender представляет из себя полноценную платформу для сборки, доставки и установки прошивок.
В целом платформа выглядит просто замечательно, но нам потребовалось около полутора недель только на то, чтобы собрать правильную версию нашей прошивки с помощью сборщика mender.
И чем больше мы погружались в тонкости его использования,
тем больше становилось ясно, что на полноценное его развертывание нам понадобилось бы сильно больше времени, чем у нас было.


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


Ansible

Самым простым решением в нашей ситуации оказалось использование Ansible. Пары playbook'ов для начала было вполне достаточно.
Суть их сводилась к тому, что мы просто подключались с хоста (CI сервер) по ssh к нашим расберри и разливали на них обновления.


В самом начале все было просто нужно было находиться в единой сети с устройствами, разливка шла через Wi-Fi.
В офисе просто находилось десяток тестовых малинок, подключенных к одной сети, каждое устройство имело статический IP адрес так же указанный в Ansible Inventory.


Именно Ansible доставлял наш мониторинг-агент на конечные устройства


3G/LTE


К сожалению, такой вариант использования Ansible мог работать только в режиме разработки, пока у нас еще не было реальных скутеров.
Потому что скутеры, как вы понимаете, не стоят подключенные к одному Wi-Fi роутеру постоянно ожидая обновления по сети.


В реальности у скутеров вообще не может быть никакого соединения кроме мобильного 3G/LTE (и то не постоянно).
Это накладывает сразу много проблем и ограничений, вроде низкой скорости соединения и нестабильной связи.


Но самое главное в 3G/LTE сети мы не можем просто надеяться на статичный IP присвоенный в сети.
Это частично решается некоторыми провайдерами SIM карт, есть даже специальные симки предназначенные для IoT устройств со статическими IP адресами. Но мы не имели доступа к таким SIM картам и не могли использовать IP адреса.


Конечно, были идеи делать некую регистрацию IP адресов aka service discovery где-то вроде Consul, но от подобных идей пришлось отказаться,
так как у нас в тестах IP адрес мог меняться слишком часто, что приводило к большой нестабильности работы.


По этой причине, наиболее удобное использование для доставки метрик было бы не с использованием pull модели, где мы ходили бы за нужными метриками на устройства,
а push с доставкой метрик с устройства напрямую на сервер


VPN


В качестве решения этой проблемы мы выбрали VPN а конкретно Wireguard.


Клиенты (скутеры) на старте системы подключались к VPN серверу и держали возможность подключения к ним. Этот туннель и использовался для доставки обновлений.



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


Облачные ресурсы


Последнее необходимо отслеживать наши облачные сервисы и БД, так как для них мы используем Kubernetes, в идеале чтобы разворачивание мониторинга в кластере было максимально простым. В идеале с использованием Helm, так как для деплоя, мы в большинстве случаев используем его. И, само собой, для мониторинга облака нужно использовать те же решения, что и для самих скутеров.


Дано


Фуф, вроде с описанием разобрались, давайте составим список того, что нам было нужно в итоге:


  • Быстрое решение, так как мониторить необходимо уже во время процесса разработки
  • Объем/количество нужно множество метрик
  • Сбор логов обязателен
  • Надежность данные критически важны для успеха запуска
  • Нельзя использовать pull модель нужен push
  • Нужен единый мониторинг не только железа, но и облака

Конечная картинка выглядела примерно так



Выбор стека


Итак, перед нами встал вопрос выбора стека для мониторинга.


В первую очередь, мы искали наиболее полноценное all-in-one решение, которое одновременно покрывало бы все наши требования, но при этом и было бы достаточно гибким чтобы подогнать его использование под наши нужды. Все-таки, у нас было много ограничений наложенных на нас железом, архитектурой и сроками.


Существует огромное множество решений для мониторинга,
начиная полноценными системами вроде Nagios, icinga или zabbix и заканчивая уже готовыми решениями по Fleet management.



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


После анализа какого-то количества подобных решений мы быстро пришли к выводу, что проще и быстрее будет собрать схожий стек самостоятельно. Да, это будет чуть сложнее чем разворачивание полностью готовой Fleet management платформы, но зато нам не придется идти на компромиссы.
Почти наверняка, во всем огромном обилии решений и есть уже готовое которое полностью бы нам подошло,
но в нашем случае значительно быстрее было собрать некий стек самостоятельно и подогнать "под себя", нежели тестировать готовые продукты.


При всем этом, мы не стремились собирать целиковую платформу для мониторинга самостоятельно, а искали максимально функциональные "готовые" стеки, только с возможностью их гибко настраивать.


(B)ELK?


Первое решение, которое реально рассматривалось широко известный ELK стек.
На самом деле он должен называться BELK, ведь начинается все с Beats https://www.elastic.co/what-is/elk-stack



Конечно, ELK это одно из самых известных и мощных решений в области мониторинга, а уж в сборе и обработке логов, так и самое.


Мы подразумевали, что ELK будет использоваться для сбора логов и, так же как долговременное хранилище метрик полученных из Prometheus.
Для визуализации можно использовать Grafan'у.


На самом деле, свежий ELK стек умеет собирать метрики и самостоятельно (metricbeat), Kibana так же умеет показывать их.


Но все-таки изначально ELK вырос из логов и пока функционал метрик имеет ряд серьезных недостатков:


  • Значительно медленнее Prometheus
  • Интегрируется в куда меньшее количество мест чем Prometheus
  • Сложно настроить алертинг по ним
  • Метрики занимают большое количество места
  • Настройка дашбордов с метриками в Kiban'е значительно сложнее Grafan'ы

В общем, метрики в ELK тяжелые и пока не такие удобные как в других решениях, которых сейчас на самом деле значительно больше чем просто Prometheus: TSDB,
Victoria Metrics, Cortex итд итп. Конечно, очень бы хотелось иметь сразу полноценное all-in-one решение, но в случае с metricbeat выходило слишком много компромиссов.


Да и у самого ELK стека есть ряд непростых моментов:


  • Он тяжелый, порой даже очень, если у вас собирается довольно большое количество данных
  • Его нужно "уметь готовить" скалировать его необходимо, но делается это нетривиально
  • Урезанная бесплатная версия в бесплатной версии нет нормального алертинга, на момент выбора не было и аутентификации

Надо сказать, что в последнее время с последним пунктом стало получше и помимо вывода в open-source X-pack (в том числе аутентификация) начала меняться сама модель прайсинга.
Но на момент, когда мы собирались разворачивать это решение, алертинга не было совсем.
Возможно, можно было попробовать собрать что-то с использованием ElastAlert или других community решений, но все же решили рассмотреть другие альтернативы.


Loki Grafana Prometheus


На данный момент неплохим решением может быть сборка стека мониторинга на основе чисто Prometheus как поставщика метрик,
Loki для логов, а для визуализации можно использовать все ту же Grafana.
К сожалению, на момент старта прода пилота проекта (сентярбь-октябрь 19ого года) Loki еще находился в бета версии 0.3-0.4,
а на момент старта разработки и вовсе не мог рассматриваться как produtcion решение.


Я пока не имею опыта реального использования Loki в серьезных проектах, но могу сказать, что Promtail (агент для сбора логов) здорово работает как для bare-metal, так и для подов в kubernetes.


TICK


Пожалуй, наиболее достойной (единственной?) полнофункциональной альтернативой ELK стеку сейчас можно назвать только TICK стек Telegraf, InfluxDB, Chronograf, Kapacitor.



Я опишу все компоненты ниже более подробно, но в целом идея такая:


  • Telegraf агент для сборки метрик
  • InfluxDB база данных метрик
  • Kapacitor обработчик метрик в реальном времени для алертинга
  • Chronograf веб панель для визуализации

Для InfluxDB, Kapacitor и Chronograf есть официальные helm чарты, которые мы использовали для их разворачивания.


Надо отметить, что в свежей версии Influx 2.0 (beta) Kapacitor и Chronograf стали частью InfluxDB и больше не существуют отдельно


Telegraf



Telegraf это очень легковесный агент для сбора метрик на конечной машине.
Он умеет мониторить огромное количество всего, от nginx до
сервера minecraft.


У него есть ряд классных преимуществ:


  • Быстрый и легкий (написан на Go)
    • Ест минимальное количество ресурсов
  • Push метрик по умолчанию
  • Собирает все необходимые метрики
    • Системные метрики без каких-либо настроек
    • Хардварные метрики вроде информации с датчиков
    • Очень легко добавлять собственные метрики
  • Много плагинов "из коробки"
  • Собирает логи

Так как push метрик был для нас необходим, все остальные преимущества были более чем приятными дополнениями.


Сборка логов самим же агентом так же очень удобна, так как нет необходимости подключать дополнительные утилиты для тейлинга логов.
Influx предлагает максимально удобный опыт работы с логами если вы используете syslog.


Telegraf вообще отличный агент для сборки метрик, даже если вы не используете весь остальной ICK стек.
Многие скрещивают его и с ELK и с различными другими time-series базами по удобству, так как он умеет писать метрики почти куда угодно.


InfluxDB



InfluxDB основное ядро TICK стека, а именно time-series база данных для метрик.
Помимо метрик Influx также может хранить и логи, хотя, по сути логи для него это всего лишь такие же метрики,
только вместо обычных числовых показателей основную функцию несет строка текста лога.


InfluxDB тоже написан на Go и работает, по ощущениям, значительно быстрее в сравнении с ELK на нашем (не самом мощном) кластере.


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


Недостатки $$$ или скалирование ?

У TICK стека есть только один обнаруженный нами недостаток он дорогой. Даже очень.


А что есть в платной версии, чего нет в бесплатной?


Насколько нам удалось понять, единственное чем отличается платная версия TICK стека от бесплатной возможности скалирования.


А именно поднять кластер с High availability можно только в Enterprise версии.


Хотите полноценное HA нужно либо платить, либо городить какие-нибудь костыли. Есть пара решений сообщества например influxdb-ha похоже на грамотное решение, но написано что не подходит для продакшена, а так же
influx-spout простое решение с прокачкой данных через NATS (его тоже придется скалировать, но это решаемо).
Жаль, но оба они, похоже, заброшены нет свежих коммитов, предположу, что дело в скором ожидаемом выходе новой версии Influx 2.0 в которой многое будет иначе (пока информации о скалировании в ней нет).


Официально для бесплатной версии существует Relay фактически это примитивное HA, но только посредством балансировки,
так как все данные будут писаться во все инстансы InfluxDB за load balancer'ом.
У него есть некоторые недостатки вроде потенциальных проблем с перезаписью точек и необходимости создавать базы для метрик заранее
(что при обычной работе с InfluxDB происходит автоматически).
К тому же шардирование не поддерживается, это означает дополнительные накладные расходы на дуплицированные метрики (и обработка и хранение),
которые могли вам быть не нужны, но разделить их возможности нет.


Victoria Metrics?


В итоге, несмотря на то, что во всем помимо платного скалирования TICK стек нас полностью устраивал, мы решили посмотреть нет ли бесплатных решений, которыми можно заменить InfluxDB базу,
оставив при этом остальные компоненты T_CK.



Time-series баз немало, но наиболее подающая надежды Victoria Metrics, у нее целый ряд плюсов:


  • Быстрая и легкая, по крайней мере по результатам бенчмарков
  • Есть кластерная версия, про которую сейчас даже есть хорошие отзывы
    • Она можешь шардироваться
  • Поддерживает InfluxDB протокол

Мы не собирались строить полностью кастомный стек на основе Victoria и основная надежда была на то, что мы сможем воспользоваться ею как drop-in заменой для InfluxDB.


К сожалению, это невозможно, несмотря на то, что поддерживается протокол InfluxDB, это работает только для записи метрик "наружу" доступно только Prometheus API,
а значит натравить Chronograf на нее не получится.
Более того, для метрик поддерживаются только числовые значения (мы использовали строковые значения для кастомных метрик об этом в разделе админка).
Очевидно, по той же причине VM не может хранить логи, как это делает Influx.


Также, надо отметить, что на момент поиска оптимального решения Victoria Metrics еще не была так популярна, документация была значительно меньше и функционал был слабее
(не припоминаю подробного описания кластерной версии и шардирования).


Выбор базы

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


Основных причин такого выбора было несколько:


  • Нам очень нравился функционал TICK стека целиком
  • Мы уже успели его развернуть и оно отлично работало
  • Сроки поджимали и не оставалось много времени тестировать другие варианты
  • У нас не ожидалось такой большой нагрузки

Скутеров у нас для первой фазы пилота было не так много, и тестирование во время разработки не выявило каких-либо проблем с производительностью.
Поэтому мы решили, что для данного проекта нам вполне хватит и одно ноды Influx без необходимости скалирования (cм выводы в конце).


Со стеком и базой решили теперь об остальных компонентах TICK стека.


Kapacitor



Kapacitor это часть TICK стека, сервис который может следить за попадающими в базу метриками в реальном времени и выполнять на основе правил различные действия.


Вообще он позиционируется как тул для потенциального отслеживания аномалий и машинного обучения (не уверен что эти функции востребованы),
но наиболее популярный кейс его использования более банален это алертинг.


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



Это позволяло быстро реагировать на проблемы, а также получать нотификации о том, что все пришло в норму.
Простой пример сломалась или по какой-то причине разрядилась дополнительная батарея для питания нашей "коробочки",
просто поставив новую мы должны через некоторое время получить нотификацию о восстановлении работоспособности скутера.


В Influx 2.0 Kapacitor стал частью DB


Chronograf



Я повидал много различных UI решений для мониторинга, но могу сказать, что по функционалу и UX ничто не сравнится с Chronograf'ом.


Начинали мы использовать TICK стек, как ни странно, с Grafan'ой в качестве веб-интерфейса.
Описывать ее функционал не буду, всем известны ее широкие возможности по настройке всего что угодно.


Однако, Grafana все же представляет из себя совсем универсальный инструмент, тогда как Chronograf в основном заточен под использование с Influx.
И конечно, благодаря этому, Chronograf может позволить себя куда более хитрый или удобный функционал.


Пожалуй, основное удобство работы с Chronograf в том, что вы можете смотреть внутренности вашей InfluxDB через Explore.


Казалось бы, в Grafana есть почти идентичный функционал, но в реальности настройка дашборда в Chronograf может осуществляться несколькими кликами мыши
(попутно смотря на визуализацию там же), тогда как в Grafana вам все равно рано или поздно придется редактировать JSON конфигурацию
(само собой Chronograf позволяет выгрузить ваши настроенные "руками" даши и редактировать в виде JSON если необходимо но мне никогда не приходилось их трогать после создания на UI).


В Kibana куда более богатые возможности по созданию дашбордов и контролов для них, но и UX для таких операций ну очень сложный.
Потребуется неплохо разобраться чтобы создать себе удобный дашборд. И хотя функционал дашбордов у Chronograf меньше, делать и настраивать их значительно проще.


Сами дашборды, помимо приятного визуального стиля, фактически ничем от дашбордов в Grafana или Kibana не отличаются:


Так выглядит то самое окно запросов:


Важно отметить, помимо прочего, что зная типы полей в базе InfluxDB хронограф иногда сам может
автоматически помогать вам с написанием Query или выбором правильной функции агрегации типа mean.


Ну и конечно же, Chronograf максимально удобен для просмотра логов. Выглядит это так:



По умолчанию Influx логи заточны под использование syslog и поэтому в них есть важный параметр severity.


Особенно полезен график сверху, на нем можно увидеть возникающие ошибки и цветом сразу отчетливо видно если severity более высокий.
Пару раз таким образом мы ловили важные баги, зайдя в просмотр логов за последнюю неделю и увидев красный спайк.


Конечно, в идеале было бы настроить алертинг на такие ошибки, благо у нас уже было все для этого.
Мы даже на какое-то время включали это, но, в процессе подготовки пилота выяснилось, что у нас возникает довольно много ошибок
(в том числе системных вроде недоступности LTE сети), которые слишком сильно "спамят" в Slack канал, при этом не неся большой пользы.


Правильным решением было бы обработать большинство подобных типов ошибок, настроить для них severity и уже потом включить алертинг.
Таким образом в Slack попадали бы только новые или важные ошибки. На подобный сетап банально не хватило времени в условиях сжатых сроков.


Аутентификация


Отдельно стоит упомянуть то, что Chronograf поддерживает OAuth и OIDC в качестве аутентификации.
Это очень удобно, так как позволяет легко прикрутить его к вашему серверу и сделать полноценное SSO.


В нашем случае сервером был Keycloak он использовался для подключения к мониторингу,
но при этом тот же сервер использовался и для аутентификации скутеров и запросов на back-end.


Админка


Последний компонент, который я опишу это наша самописная "админка" на Vue.
В целом это просто отдельный сервис, который отображает информацию о скутерах одновременно из наших собственных баз данных, микросервисов и данные метрик из InfluxDB.


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


Также там были карты. Я уже упоминал, что начинали мы с Grafana вместо Chronograf потому что для Grafana в виде плагинов доступны карты, на которых можно было смотреть координаты скутеров. К сожалению, возможности виджетов карт для Grafana очень ограничены, и в результате было гораздо проще за несколько дней написать свое собственное веб приложение с картами, для того чтобы не только видеть координаты в данный момент, но и отображать пройденный скутером маршрут, уметь фильтровать данные на карте, итд (весь тот функционал, который мы не смогли бы настроить в простом дашборде).


Один из уже упомянутых плюсов Influx возможность легко создавать свои собственные метрики.
Это позволяет использовать его для огромного множества сценариев.
Мы старались записывать туда всю полезную информацию: заряд батареи, состояние замка, работоспособность датчиков, bluetooth, GPS, множество других healthcheck'ов.
Все это мы и отображали на админ панели.


Конечно, самым главным критерием для нас было состояние работы скутера фактически Influx проверяет это сам и показывает в разделе Nodes "зелеными лампочками".
Делается это функцией deadman мы использовали ее же для понимания работоспособности нашей коробочки и отсылки тех самых алертов в Slack.


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


Да и вообще так было веселее. Постоянно звучали фразы вроде "Ребята Смитерс умер!"



Строковые метрики


Важно, что InfluxDB позволяет хранить не только числовые значения, как в случае с Victoria Metrics.


Казалось бы, это не так важно ведь если не считать логов, любые метрики можно хранить в виде чисел (всего лишь добавить маппинг для известных состояний своего рода enum)?


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


В результате API зарядок было далеко от идеала, но основной проблемой было то, что мы не всегда могли понять их состояние.
Тут на помощь и пришел Influx. Мы просто-напросто записывали приходящий нам строковый status в поле базы InfluxDB без изменений.


Какое-то время туда попадали только значения вида "online" и "offline", на основе чего у нас в админке отображалась информация,
а в Slack приходили уведомления. Однако в какой-то момент туда стали попадать так же значения вида "disconnected".
Как позже выяснилось, этот статус высылался однократно после потери связи, если зарядка не могла установить соединение с сервером после какого-то количества попыток.


Таким образом, если бы мы использовали только фиксированный набор значений мы могли бы не увидеть этих изменений в прошивке в нужный момент времени.


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



Помимо обычных метрик, мы так же записывали в InfluxDB информацию о GPS локации. Это было невероятно удобно для мониторинга местонахождения скутеров в нашей админской панели.
Фактически, мы всегда знали где и какой скутер был в нужный нам момент времени.


Очень сильно нам это пригодилось, когда мы разыскивали скутер (смотри выводы в конце).


Мониторинг инфраструктуры


Помимо самих скутеров, нам было необходимо мониторить и всю нашу (довольно обширную) инфраструктуру.
Очень обобщенная архитектура выглядела примерно так:



Если выделить чисто стек мониторинга, то он выглядит следующим образом:


Из того что мы хотели бы проверять в облаке, это:


  • Базы данных
  • Keycloak
  • Микросервисы

Так как все наши облачные сервисы находятся в Kubernetes, то было бы неплохо собирать информацию и о его состоянии.
К счастью, Telegraf "из коробки" может собирать огромное количество метрик о состоянии Kubernetes кластера, а Chronograf сразу предлагает для этого красивые дашборды.


Мы следили в основном за работоспособностью подов и потреблением памяти. В случае падения алерты в Slack.


Для отслеживания подов в Kubernetes есть два пути: DaemonSet и Sidecar.
Оба способа подробно описаны в этом блог посте.
Мы использовали Telegraf Sidecar и помимо метрик собирали логи подов.
В нашем случае с логами пришлось повозится. Несмотря на то что Telegraf умеет вытаскивать логи из Docker API, мы хотели иметь единообразный сбор логов с нашими конечными устройствами и настраивали для этого syslog для контейнеров. Возможно, это решение не было красивым, но нареканий в его работе не было и логи хорошо отображались в Chronograf'e.


Мониторить мониторинг???

В конце концов встал извечный вопрос мониторинга систем мониторинга, но к счастью, или к сожалению, на это у нас просто не хватило времени.
Хотя Telegraf легко умеет отправлять свои собственные метрики или собирать метрики InfluxDB базы для отправки либо в тот же Influx, либо куда-то еще.


Выводы


Какие выводы мы сделали по результатам пилота?


Как можно делать мониторинг


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


Производительность

Основная проблема TICK стека в бесплатной версии отсутствие возможностей по скалированию. Для нас это не стало проблемой.


Мы не собирали точных данных/цифр о нагрузке, но мы собирали данные с примерно 30и скутеров одновременно.
Каждый из них собирал более трех десятков метрик. Одновременно собирались логи с устройств. Сбор и отправка данных происходили каждые 10 секунд.


Важно отметить, что спустя полторы недели пилота, когда основную массу "детских болячек" удалось исправить и самые важные проблемы уже были решены,
нам пришлось снизить частоту отправки данных на сервер до 30и секунд. Это стало необходимо, потому что трафик на наших LTE SIM картах начал быстро таять.
Основную массу трафика съедали логи, сами метрики даже с 10и-секундным интервалом практически не тратили его.


В итоге, спустя еще какое-то время мы совсем отключили сбор логов на устройствах, так как конкретные проблемы уже были очевидны и без постоянного сбора.
В некоторых случаях, если просмотр логов все же был необходим мы просто подключались через WireGuard по VPN.


Еще добавлю, что каждый отдельный environment у нас был отделен друг от друга, и вышеописанная нагрузка была актуальна только для продакшен среды.
В среде разработчиков у нас был поднят отдельный инстанс InfluxDB который продолжал собирать данные раз в 10 секунд и мы не уткнулись в какие-либо проблемы с производительностью.


TICK идеально для небольших-средних проектов

На основе этой информации я бы сделал вывод, что TICK стек идеально подходит для относительно небольших проектов или проектов, у которых точно не ожидается какого-либо HighLoad.


Если у вас нет тысяч подов или сотен машин даже один инстанс InfluxDB прекрасно справится с нагрузкой.
В некоторых случаях вас может устроить Influx Relay как примитивное решение по High Availability.


И, само собой, никто не мешает вам настраивать "вертикальное" скалировние и просто выделить различные сервера под различные типы метрик.


Если же вы не уверены в ожидаемой нагрузке на сервисы мониторинга, или у вас гарантированно есть/будет очень "тяжелая" архитектура бесплатную версию TICK стека использовать я бы не порекомендовал.
Конечно, простым решением было бы приобретение InfluxDB Enterprise но тут я не могу как-то прокомментировать, так как сам не знаком с тонкостями. Кроме того, что это очень дорогои точно не подойдет для мелких компаний.


В таком случае, на сегодняшний день, я бы порекомендовал посмотреть в сторону сбора метрик через Victoria Metrics и логов с помощью Loki.
Правда, снова оговорюсь, что Loki/Grafana значительно менее удобны (в виду своей большей универсальности) чем готовый TICK, но зато они бесплатны.


Важно: вся описанная здесь информация актуальна для версии Influx 1.8, в данный момент вот-вот должен выйти в релиз Influx 2.0.
Пока не довелось попробовать его в боевых условиях и сложно делать выводы об улучшениях, точно еще лучше стал интерфейс, упростилась архитектура (без kapacitor и chronograf),
появились темплейты ("киллер фича" можно отслеживать игроков в Fortnite и получать нотификации когда твой любимый игрок выигрывает партию). Но, к сожалению, в данный момент в версии 2 нет ключевой вещи, по которой мы выбрали первую версию нет сбора логов.
Этот функционал в Influx 2.0 тоже появится, но каких-либо сроков, даже примерных, найти не удалось.


Как не нужно делать IoT платформы (теперь)


В конце концов, запустив пилот мы сами собрали свой полноценный IoT стек, за неимением подходящей по нашим меркам альтернативы.
Однако, с недавнего времени в Beta версии доступна OpenBalena жаль ее не было когда мы начинали делать проект.


Конечный результат и та платформа на основе Ansible + TICK + WireGuard, которую мы собрали самостоятельно нас полностью устраивает. Но на сегодняшний день, я бы порекомендовал внимательней посмотреть на Balena прежде чем пытаться собрать свою IoT платформу самим.


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


А совсем недавно они и вовсе выпустили свою Hardware, которая легко подключается в их экосистему.


Эй, а что с пропавшим скутером?


Итак скутер, "Ральф", бесследно исчез.
Мы сразу побежали смотреть карту в нашей "админке", с данными GPS метрик из InfluxDB.


Благодаря данным мониторинга, мы легко определили, что парковку скутер покинул около 21:00 прошлого дня, проехал где-то полчаса до какого-то района и был запаркован до 5и утра рядом с каким-то немецким домом.
После 5и утра данных мониторинга не поступало это означало либо полный разряд дополнительной батареи, либо злоумышленник догадался-таки извлечь умную начинку из скутера.
Несмотря на это, по тому адресу, где находился скутер все же была вызвана полиция. Скутера там не оказалось.
Однако владелец дома тоже был этому удивлен, так как он действительно вчера вечером приехал на этом скутере из офиса домой.


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


Мы украли скутер сами у себя. Не знаю, кстати, как и кто потом разруливал вопрос с делом в полиции, но мониторинг отработал отлично...

Подробнее..

Путь одной команды от велосипедов до IoT-платформы

28.10.2020 20:04:59 | Автор: admin
Привет, Хабр!
Мы, команда Rightech, наконец-то решили начать вести блог. У нас накопилось много опыта в построении высоконагруженных IoT-систем, и мы решили, что просто обязаны им делиться! Совсем недавно прошел запуск публичной версии нашей платформы RIC (Rightech IoT Cloud), и теперь ей может воспользоваться каждый желающий. Но сначала расскажем, кто мы и откуда появились.

C чего всё начиналось


В далеком 2011 году мы скорее были командой фрилансеров из города Орел и начинали с того, что программировали ряд аппаратных разработок, связанных с реализацией систем автоматизированных измерений и управления. Подключали сенсоры и актуаторы к микроконтроллерам, реализовывали протоколы обмена, первичную обработку данных и автоматизацию.

Через какое-то время команда стала замечать общее между всеми проектами. Мы писали на различных языках программирования, работали с разным оборудованием, но выстраивали идентичную архитектуру решения. В определенный момент мы пришли к выводу, что можно создать универсальный фреймворк, который позволит сразу перейти к разработке интерфейса системы.

Наши заказчики искренне не понимали, почему они не могут смотреть/тестировать промежуточный результат. Почему он выглядит как бегущие строки в консоли, а для управления актуатором нужно не нажать на тачскрин, а отправить Modbus команду. К программированию интерфейсов мы приступали в тот момент, когда было уже готово API и проработана автоматизация.

На тот период времени наш рабочий процесс представлял собой следующую последовательность:

  1. физически подключить компоненты системы в одну сеть;
  2. реализовать протоколы обмена данными;
  3. реализовать обработку данных (фильтрация, применение функций преобразования, проведение косвенных измерений и т.д.);
  4. преобразовать данные в высокоуровневые структуры;
  5. описать конечные автоматы системы;
  6. реализовать API для вывода данных в интерфейс и запуска автоматов;
  7. реализовать интерфейс системы (тачскрин/нативное приложение/интеграция во внутренние системы заказчика).

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



В результате мы приняли решение создать универсальный фреймворк. На наше решение повлияли и интересы заказчиков. Управленцы и владельцы бизнеса, как правило, заинтересованы в создании конечных пользовательских кейсов и часто не углубляются в механизм работы системы. Для успешного выполнения поставленных ими задач нам требовалось больше фокусироваться на разработке пользовательских сценариев и интерфейсов, так как именно они несут в себе основную коммерческую ценность создаваемого решения. При этом 90% затрат на разработку сосредоточено во внутренних, невидимых конечному пользователю системах проекта.



Первоначальная идея платформы RIC трансформировалась и изменялась вместе с рынком, находила все больше областей применения. Разработанный нами за 4 года фреймворк позволял сосредоточиться на процессах создания ценности решения, воплощения задуманной бизнес-логики и продвижения конечного продукта на рынок. RIC был полностью готов в 2016 году, оставалось только создать компанию и найти деньги

Rightech. История создания


У нас совершенно отсутствовал опыт в привлечении денег. Однако в 2016 году нам удалось привлечь первые инвестиции от фонда, вложившегося в компанию Делимобиль. На эти деньги мы создали компанию Rightech, которая стала домом для нашего проекта. А первым действительно крупным внедрением нашей технологии, как вы уже догадались, стал каршеринг Делимобиль. Сразу оговорюсь, что приложения и CRM систему разрабатывали не мы, но тысячи автомобилей и терабайты машинногенеренных данных стали достойной проверкой, которую RIC уверенно прошел.

Помимо шерингов, к 2019 году мы успели автоматизировать Digital Out Of Home рекламу, построить сбор данных с газотурбинных генераторов электроэнергии и многое другое. Команда занималась не только рыночными внедрениями, но и развивала RIC в целом: реализовали множество транспортных протоколов, оптимизировали серверную инфраструктуру и расширили систему автоматизации.

Как и следовало ожидать, нам стало тесно в рамках Делимобиль и мы начали развивать платформу в сторону публичного облака. К этому времени цели инвестирования со стороны фонда были достигнуты, и в начале 2019 года мы выкупили его долю. Это позволило команде проекта сконцентрироваться на реализации по-настоящему массовой технологии.

Подробнее о платформе


Так что же такое IoT-платформа? Во что превратился наш фреймворк заменитель велосипедов RIC?

Любой IoT проект состоит из следующих принципиальных компонентов или слоев:

  • устройства умные устройства, датчики и актуаторы, на основе которых осуществляется сбор данных и автоматизация;
  • сети передачи данных по ним происходит передача данных и команд между компонентами IoT системы;
  • платформа инфраструктура, обеспечивающая интероперабельность (способность к взаимодействию) компонентов системы, обработку данных и передачу ее в прочие системы;
  • приложения представляет собой конечную цель IoT-проекта, на этом уровне работают конечные пользователи и на нем же, по сути, создается ценность всей системы.



Rightech IoT Cloud (или RIC) это облачная платформа Интернета Вещей, выступающая в качестве промежуточного программного обеспечения (middleware) при разработке IoT-решения. RIC включает в себя все необходимые программные элементы, позволяющие инженерам любого уровня создавать приложения с использованием любых IoT-устройств без необходимости создавать соответствующую программно-аппаратную инфраструктуру. Да-да, именно любых устройств. Мы выложили не все реализованные протоколы в публичную версию RIC. Если вы не нашли протокол своего устройства, можете нам написать и мы его обязательно добавим в публичную версию.

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

В отличие от существующих аналогов платформа Rightech не требует написания кода, кроме относящегося к созданию Приложений, являющихся целью IoT-проекта. Интеграция платформы с уровнем приложений происходит посредством высокоуровневого REST API, и производится не сложнее, чем интеграция Google карт.



Проще говоря, платформа это конвейер IoT данных. И этот конвейер можно настраивать так, как захочется каждому отдельному пользователю. Он решает базовые задачи, связанные с обеспечением подключения устройств и их взаимодействия между собой, управления устройствами, обработкой, хранением и анализом поступающих от устройств данных, проектированием сценариев автоматизации бизнес-логики и их исполнением, интеграцию с приложениями и сторонними системами, обеспечение безопасности на каждом уровне взаимодействия компонентов системы и многие другие.

Публичное облако


Весной мы запустили регистрацию на наше публичное облако, и теперь каждый пользователь может бесплатно подключить до 10 устройств и спрототипировать свой будущий бизнес или же автоматизировать, например, теплицу или дом. Любой IoT проект может взять всё необходимое в платформе RIC и реализовать свою уникальную систему обработки и представления получаемых данных практически без программирования тех самых 90% айсберга.

Наш короткий рассказ подошел к концу. Надеемся, что мы вам понравились, и в свою очередь обещаем делиться своим опытом и актуальной информацией в сфере IoT.
Кстати, мы есть и в Телеграм с чатом единомышленников.
Just do IoT!

Полезные ссылки:


Обучающие видеоролики на примере мини-кейсов
Создайте свой IoT-проект уже сейчас
Присоединяйтесь к единомышленникам
Подробнее..

Анонсируем новую версию Rightech IoT Cloud v2.2. Небольшой обзор

04.12.2020 16:09:39 | Автор: admin
Всем привет!

В рамках нашего блога мы планируем делиться не только историями и опытом, но также освещать последние нововведения и изменения, связанные с платформой Rightech IoT Cloud (RIC).
Недавно мы опубликовали версию RIC v2.2. А теперь рассказываем, что же именно вошло в релиз этого квартала.

Ну что, погнали?

Опираясь на отзывы и предложения наших пользователей, мы решили добавить следующие функции:

  • Import/export сущностей платформы, а именно моделей, объектов и автоматов.
  • Обработку ошибок в редакторе автоматов.
  • RIC-app упрощенную мобильную версию платформы.

image

Предисловие


Если вы новый пользователей нашей платформы, то наверное, многие из перечисленных параметров выше вам непонятны. Давайте немного разберем, что есть что.

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

Объект является представлением устройства, над которым осуществляется контроль и управление посредством использования функций платформы.

Автомат это сценарий автоматизации, позволяющий выстраивать логику поведения вашего устройства.

Более подробно ознакомиться со всеми параметрами платформы можно в нашей документации.

Вернемся к обновлениям

Import/export сущностей платформы


Все сущности в платформе представляют собой JSON-файлы. Такой формат позволяет организовать удобный обмен данными. Мы добавили в интерфейс возможность экспортировать и импортировать отдельные элементы ваших решений в формате JSON. Импортировать сущность можно из файлов или напрямую по ссылке, например, через raw-режим просмотра файлов на github.

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

Модели

Возможность импорта/экспорта моделей особенно помогает при передаче своей реализации задачи другому человеку. Очень удобно поделиться программным кодом в виде, например, скетча Arduino и моделью объекта в виде JSON-файла.

Экспорт модели:

image

Импорт модели из файла:

image

Импорт модели по ссылке:

image

Объекты

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

Экспорт объекта:

image

Импорт объекта из файла:

image

Импорт объекта по ссылке:

image

Автоматы

Также появилась возможность поделиться своими сценариями и использовать автоматы других пользователей. Изучайте опыт других пользователей. Делитесь своими достижениями. Спрашивайте совета и не бойтесь критики. Мы также будем выкладывать собственные проекты на github например, те решения, которые уже используются в нашем офисе и в повседневной жизни наших сотрудников.

Экспорт автомата:

image

Импорт автомата из файла:

image

Импорт автомата по ссылке:

image

Обработка ошибок в редакторе автоматов


Сущности модель и автомат тесно связаны. При этом может возникнуть ситуация их несоответствия. Например, когда модель редактируется после создания автомата или при попытке использовать один автомат с разными моделями. Такая же проблема может возникнуть и при импорте автоматов со сторонних источников. Возникающие при этом ошибки приводят к тому, что в исполняемом автомате могут оказаться параметры, команды и события, которых нет в модели устройства. Соответственно, при исполнении такого автомата эти параметры не могут участвовать в проверке условий, события не могут вызвать перехода, а команды не будут быть отправлены.

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

Именно поэтому мы добавили в интерфейс создания и редактирования автоматов дополнительную информацию о возникающих ошибках.

Автомат с ошибками:

image

Состояния

В состояниях автомата может возникнуть ситуация, когда в модели отсутствует выбранные действия, например, отправка команды при смене состояния автомата. Это может случится при редактировании модели устройства, изменении модели выбранной в автомате, импорте автомата. Действия, отсутствующие в модели, не смогут быть выполнены во время его выполнения и будут проигнорированы.

Ошибки в состоянии:

image

Переходы

Возникающие в переходах ошибки влияют на механизм смены состояний в исполняемом автомате. В случае ошибок событие, которое вызывает переход, не может произойти и условие, которое проверяется, не будет выполнено.

Возможно несколько вариантов ошибок:

  • Отсутствие события, которое вызывает переход между состояниями;
  • Отсутствие параметра, который используется в условии перехода.


Ошибки в переходах:

image

Ric-app


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

Приложение для Android доступно в Play Market по ссылке. Приложение для iOS в скором времени появится в App Store.

Объекты

В списке объектов видна информация о статусе объектов. Можно зайти в каждый объект, посмотреть все его параметры, историю пакетов. Кроме того, доступна возможность отправки команд на устройства.

Список объектов:

image

Состояние объекта:

image

История объекта:

image

Управление объектом:
image

Карта

Меню с картой аналогично карте в интерфейсе платформы.

Карта:

image

Оповещения

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

Оповещения:

image

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

Ждем ваших комментариев, и не забывайте делиться своими предложениями. Возможно, именно ваши идеи будут воплощены в последующих релизах!

Stay tuned & just do IoT!

Полезные ссылки:


Обучающие видеоролики на примере мини-кейсов rightech.io/video-tutorials
Создайте свой IoT-проект уже сейчас dev.rightech.io/signup
Присоединяйтесь к единомышленникам t.me/rightech_iot
GitHub github.com/Rightech/ric-public
Вопросы и предложения development@rightech.io
Подробнее..

IoT-елочка, гори!..

26.12.2020 22:16:10 | Автор: admin
Пришел новый русский в магазин, чтобы сдать новогоднюю гирлянду.
Не работает? спрашивает его продавец.
Почему? Очень даже работает, отвечает тот.
А в чем тогда дело?
Покупатель вздохнул и ответил:
Не радует.


Привет, друзья!

Очень надеемся, что гирлянда, изготовление которой мы опишем в статье, порадует вас и своим видом, и тем фактом, что вы можете ее сделать сами. Совсем не претендуя на то, что эта гирлянда станет серьезным конкурентом недорогих китайских вариантов, мы все же считаем, что такой небольшой DIY в преддверии новогоднего праздника может стать прекрасным развлечением для всей семьи, ведь тут и сборка железочек, и программирование, и составление сценария логики работы гирлянды, и, в конечном счете, созидание красоты, сделанной собственной руками!

Под катом:
  1. Собираем прототип гирлянды
  2. Пишем код для нескольких режимов работы
  3. Подключаем к платформе Rightech IoT Cloud
  4. Придумываем и реализовываем сценарий работы гирлянды
  5. Создаем праздничное настроение


image



Идея сделать гирлянду возникла не случайно. Украшая офис, мы нашли в мешке маленькую елочку, которой совершенно не холодно в офисе зимой, но совсем одиноко без огоньков, тем более что основной елке в офисе достались и игрушки, и гирлянды, а маленькой ничего. Но мы посчитали, что это не беда, а даже ее преимущество. Значит сделаем для нее не только уникальную гирлянду своими руками, но и сами выберем ей цвета светодиодов (возьмем цвета нашей компании: белый и голубой) и даже организуем ей беспроводное управление режимами по Zigbee-кнопке. А для гарантии безопасности еще и добавим автоматическое выключение по расписанию.

Модели устройств, файлы со сценариями автоматов, код для NodeMCU в конце статьи (не пытайтесь повторить это дома попробуйте повторить это дома!).

image

Собираем прототип


Создание прототипов это процесс сборки простой рабочей модели продукта или системы. Для начала построим его на макетной плате, а затем, как водится, красиво спаяем.

Итак, для маленькой гирлянды нам понадобится:

  • 12 белых и 6 голубых светодиодов, управление которыми производится независимо (назначение: гореть и радовать)
  • 2 резистора на 220 Ом, подбираемые исходя из расчета сопротивления и мощности по закону Ома (назначение: защита светодиодов от перегрева и выхода из строя)
  • 2 биполярных NPN транзистора (назначение: управляем транзистором маленьким током от управляющего пина, а пропускаем на диоды большой ток с выхода 3.3 В, так мы защищаем управляющий пин платы)
  • 2 резистора на 1 кОм на базу транзистора (назначение аналогичное, ограничиваем ток)
  • плата NodeMCU (назначение: подключение к IoT-платформе и управление транзисторами)
  • батарейки или блок питания (назначение: источник питания для платы)

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

Если изобразить на схеме, то это выглядит так:

image

При таком соединении повреждение и перегорание одного светодиода не приведёт к поломке всей гирлянды, всё будет работать, только без выбывшего диода. Также добавляем по одному резистору на каждую группу светодиодов. Управляющие пины платы подключаем к базе транзисторов через резисторы.




Пишем код


Ниже представлен код для управления режимами гирлянды. Его функции:

1) установить Wi-Fi соединение и подключиться к платформе;

2) подписаться на команды сообщения с топиками led_on, led_off, led_attenuation, led_flashing и выполнять соответствующие действия по управлению светодиодами.

Команды led_on и led_off включают и выключают гирлянду, а команды led_attenuation и led_flashing задают режимы плавного горения и быстрого мигания с периодом, указанным в payload команды.

Обратите внимание, в коде мы используем библиотека Sheduler, которая нужна для того, чтобы одновременно запускать несколько потоков с задачами. Если этого не сделать, то при запуске бесконечного цикла горения светодиодов параллельно получать команды с платформы уже не получится.

#include "Arduino.h"#include "Scheduler.h"      /* https://github.com/nrwiersma/ESP8266Scheduler */#include "EspMQTTClient.h"  /* https://github.com/plapointe6/EspMQTTClient */                           /* https://github.com/knolleary/pubsubclient */// Даем разумные имена для пинов, управляемых светодиодами#define BLUE_LED_PIN 12#define WHITE_LED_PIN 13EspMQTTClient client( "<wifi-ssid>", "<wifi-password>" "dev.rightech.io", "<ric-mqtt-client-id>");// Задача для обработки поступающих командclass ClientTask : public Task { public:   void loop() {     client.loop();   }} client_task;// Задача для включения светодиодовclass LedOnTask : public Task { protected:   void loop()   {     digitalWrite(WHITE_LED_PIN, HIGH);     digitalWrite(BLUE_LED_PIN, HIGH);     shouldRunValue = false; // останавливаем этот цикл сразу после включения   }   bool shouldRun()   {     return shouldRunValue;   } public:   bool shouldRunValue = false;} led_on_task;// Задача для выключения светодиодовclass LedOffTask : public Task { protected:   void loop()   {     digitalWrite(WHITE_LED_PIN, LOW);     digitalWrite(BLUE_LED_PIN, LOW);     shouldRunValue = false; // останавливаем этот цикл сразу после выключения   }   bool shouldRun()   {     return shouldRunValue;   } public:   bool shouldRunValue = false;} led_off_task;// Задача для плавного горения светодиодов в противофазеclass LedAttenuationTask : public Task { protected:   void loop()   {     // Вычисляем задержку на один проход цикла в зависимости от полученного в payload значения     float delayValue = period.toInt() * 1000 /*в миллисекунды*/ / 2 /*на два цикла*/ / 1024 /*на каждую итерацию в цикле*/;     for (int i = 0; i <= 1023; i++) {       analogWrite(WHITE_LED_PIN, i); // горит ярче       analogWrite(BLUE_LED_PIN, 1023 - i); // тускнеет       delay(delayValue);     }     for (int i = 1023; i >= 0; i--) {       analogWrite(WHITE_LED_PIN, i); // тускнеет       analogWrite(BLUE_LED_PIN, 1023 - i); // горит ярче       delay(delayValue);     }   }   bool shouldRun()   {     updateDelayTimer();     if (isDelayed()) return false;     if (!run_group_active) return false;     return shouldRunValue;   } public:   bool shouldRunValue = false;   String period;} led_attenuation_task;// Задача для быстрого мигания светодиодов в противофазеclass LedFlashingTask : public Task { protected:   void loop()   {     float delayValue = period.toInt() * 1000 /*в миллисекунды*/;     digitalWrite(WHITE_LED_PIN, HIGH);     digitalWrite(BLUE_LED_PIN, LOW);     delay(delayValue);     digitalWrite(WHITE_LED_PIN, LOW);     digitalWrite(BLUE_LED_PIN, HIGH);     delay(delayValue);   }   bool shouldRun()   {     updateDelayTimer();     if (isDelayed()) return false;     if (!run_group_active) return false;     return shouldRunValue;   } public:   bool shouldRunValue = false;   String period;} led_flashing_task;void setup() { // Настраиваем пины в режим выхода, т.е. в режим источника напряжения pinMode(WHITE_LED_PIN, OUTPUT); pinMode(BLUE_LED_PIN, OUTPUT); // Библиотека Scheduler позволяет при необходимости запустить несколько потоков Scheduler.start(&led_on_task); Scheduler.start(&led_off_task); Scheduler.start(&led_attenuation_task); Scheduler.start(&led_flashing_task); Scheduler.start(&client_task); Scheduler.begin();}void onConnectionEstablished() { // Подписываемся на команды и запускаем нужный поток путем изменения переменной shouldRunValue client.subscribe("led_on", [] (const String & payload)  {   client.publish("base/state/light", "on");   led_off_task.shouldRunValue = false;   led_attenuation_task.shouldRunValue = false;   led_flashing_task.shouldRunValue = false;   led_on_task.shouldRunValue = true; }); client.subscribe("led_off", [] (const String & payload)  {   client.publish("base/state/light", "off");   led_on_task.shouldRunValue = false;   led_attenuation_task.shouldRunValue = false;   led_flashing_task.shouldRunValue = false;   led_off_task.shouldRunValue = true; }); client.subscribe("led_attenuation", [] (const String & payload)  {   client.publish("base/state/light", "attenuation " + payload + " sec");   led_on_task.shouldRunValue = false;   led_off_task.shouldRunValue = false;   led_flashing_task.shouldRunValue = false;   led_attenuation_task.period = payload;   led_attenuation_task.shouldRunValue = true; }); client.subscribe("led_flashing", [] (const String & payload)  {   client.publish("base/state/light", "flashing " + payload + " sec");   led_on_task.shouldRunValue = false;   led_off_task.shouldRunValue = false;   led_attenuation_task.shouldRunValue = false;   led_flashing_task.period = payload;   led_flashing_task.shouldRunValue = true; });}void loop() {}


Подключаем к платформе Rightech IoT Cloud


Подключение гирлянды:


1) Создаем модель




2) Создаем объект с этой моделью




Подключение кнопки:


1) Создаем модель




2) Создаем объект с этой моделью




Подробнее о том, как подключать ZigBee устройства, можно посмотреть в видеоуроке и почитать в статье.

Разрабатываем сценарий работы


От сценария автоматизации мы хотим следующей логики:

1) один клик (single) режим постоянного свечения и выключения;

2) два клика (double) режим плавного свечения;

3) три клика (triple) режим мигания;

4) после 20:00 автоматическое выключение гирлянды (здесь также можно использовать не просто расписание, а данные еще из одного объекта СКУДа, который собирает информацию о том, есть ли люди в офисе. Если вам интересен материал по такой теме, дайте обратную связь в комментариях ).

Готовый автомат




Давайте вкратце разберем, что тут происходит и зачем:
  1. Первым делом при старте автомата запускаем планировщик, который выключит гирлянду по расписанию, обезопасив нас от забывчивости. Запустили и забыли, он будет срабатывать каждый день автоматически.
  2. В следующем состоянии не делаем ничего, просто ждем нажатия кнопки. В это состояние мы возвращаемся каждый раз после отработки определенного режима гирлянды. Из него есть переход по событию получения данных и срабатыванию планировщика.
  3. Если получили какой-то пакет от кнопки, то переходим в состояние Получен пакет, из которого по таймеру и типу клика переходим в соответствующие режимы. Вы можете спросить, зачем тут таймер. А причина в том, что кнопка работает довольно интересненько. При нажатии три раза, она сначала присылает пакет с double, а сразу за ним triple. Такой нюанс мы и обходим таймером, иначе срабатывало бы по неактуальному клику.
  4. Также есть промежуточное состояние для одинарного клика. Как мы помним, вкл/выкл у нас работают по одному и тому же событию. Поэтому, если гирлянда не выключена (находится в любом из режимов активной работы), то мы ее выключаем, а если выключена, то включаем.

Запускаем автомат на наших объектах, проверяем фуууух, работает! Время паять!




Собираем готовое устройство


Самый простой вариант пайки гирлянды это один за другим спаивать светодиоды, предварительно надевая термоусадку. Примерно вот так:

image

Но можно пойти немного другим путем сделать не просто гирлянду, которой мы обвяжем елку, облачив ее дополнительно во все эти провода. Вместо этого на каждую веточку посадим по светодиоду (в цветочках это смотрится особенно чудесно, см. итоговое фото), стянем провода по стеблю вниз и спаяем, спрятав всю электронику в горшочке. На выходе остается только разъем под кабель питания. Ювелирно, аккуратно и очень симпатично получается. Судите сами.

image

термоусадку нагреваем паяльным феном

image

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

image

и лудим (наносим небольшой слой припоя)

image

проводок готов воссоединяться со светодиодом

image

соединяем (паяем поверхности, на которых уже есть припой)

image

фиксируем на веточке, сгибая ножки (необходимо предварительно оставить не менее 10 мм) светодиода

image

на данном этапе проводим последнее тестирование

image

готово!





В заключение хотим сказать, что неважно, какие гирлянды именно в вашем доме цветные или однотонные, ультрасовременные или, напротив, винтажные, светодиодные или галогеновые. Главное, чтобы они создавали праздничное настроение перед Новым годом, несли тепло и радость в сердца ваших близких.

С наступающим праздником!

Материалы к статье


image
Подробнее..

IoT-елочка, гори!.

27.12.2020 00:14:52 | Автор: admin
Пришел новый русский в магазин, чтобы сдать новогоднюю гирлянду.
Не работает? спрашивает его продавец.
Почему? Очень даже работает, отвечает тот.
А в чем тогда дело?
Покупатель вздохнул и ответил:
Не радует.

Привет, друзья!

Очень надеемся, что гирлянда, изготовление которой мы опишем в статье, порадует вас и своим видом, и тем фактом, что вы можете ее сделать сами. Совсем не претендуя на то, что эта гирлянда станет серьезным конкурентом недорогих китайских вариантов, мы все же считаем, что такой небольшой DIY в преддверии новогоднего праздника может стать прекрасным развлечением для всей семьи, ведь тут и сборка железочек, и программирование, и составление сценария логики работы гирлянды, и, в конечном счете, созидание красоты, сделанной собственной руками!

Под катом:

  1. Собираем прототип гирлянды
  2. Пишем код для нескольких режимов работы
  3. Подключаем к платформе Rightech IoT Cloud
  4. Придумываем и реализовываем сценарий работы гирлянды
  5. Создаем праздничное настроение

image

Идея сделать гирлянду возникла не случайно. Украшая офис, мы нашли в мешке маленькую елочку, которой совершенно не холодно в офисе зимой, но совсем одиноко без огоньков, тем более что основной елке в офисе достались и игрушки, и гирлянды, а маленькой ничего. Но мы посчитали, что это не беда, а даже ее преимущество. Значит сделаем для нее не только уникальную гирлянду своими руками, но и сами выберем ей цвета светодиодов (возьмем цвета нашей компании: белый и голубой) и даже организуем ей беспроводное управление режимами по Zigbee-кнопке. А для гарантии безопасности еще и добавим автоматическое выключение по расписанию.

Модели устройств, файлы со сценариями автоматов, код для NodeMCU в конце статьи (не пытайтесь повторить это дома попробуйте повторить это дома!).

image

Собираем прототип


Создание прототипов это процесс сборки простой рабочей модели продукта или системы. Для начала построим его на макетной плате, а затем, как водится, красиво спаяем.

Итак, для маленькой гирлянды нам понадобится:

  • 12 белых и 6 голубых светодиодов, управление которыми производится независимо (назначение: гореть и радовать)
  • 2 резистора на 220 Ом, подбираемые исходя из расчета сопротивления и мощности по закону Ома (назначение: защита светодиодов от перегрева и выхода из строя)
  • 2 биполярных NPN транзистора (назначение: управляем транзистором маленьким током от управляющего пина, а пропускаем на диоды большой ток с выхода 3.3 В, так мы защищаем управляющий пин платы)
  • 2 резистора на 1 кОм на базу транзистора (назначение аналогичное, ограничиваем ток)
  • плата NodeMCU (назначение: подключение к IoT-платформе и управление транзисторами)
  • батарейки или блок питания (назначение: источник питания для платы)

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

Если изобразить на схеме, то это выглядит так:

image

При таком соединении повреждение и перегорание одного светодиода не приведёт к поломке всей гирлянды, всё будет работать, только без выбывшего диода. Также добавляем по одному резистору на каждую группу светодиодов. Управляющие пины платы подключаем к базе транзисторов через резисторы.




Пишем код


Ниже представлен код для управления режимами гирлянды. Его функции:

  1. установить Wi-Fi соединение и подключиться к платформе;
  2. подписаться на команды сообщения с топиками led_on, led_off, led_attenuation, led_flashing и выполнять соответствующие действия по управлению светодиодами.

Команды led_on и led_off включают и выключают гирлянду, а команды led_attenuation и led_flashing задают режимы плавного горения и быстрого мигания с периодом, указанным в payload команды.

Обратите внимание, в коде мы используем библиотека Sheduler, которая нужна для того, чтобы одновременно запускать несколько потоков с задачами. Если этого не сделать, то при запуске бесконечного цикла горения светодиодов параллельно получать команды с платформы уже не получится.

#include "Arduino.h"#include "Scheduler.h"      /* https://github.com/nrwiersma/ESP8266Scheduler */#include "EspMQTTClient.h"  /* https://github.com/plapointe6/EspMQTTClient */                           /* https://github.com/knolleary/pubsubclient */// Даем разумные имена для пинов, управляемых светодиодами#define BLUE_LED_PIN 12#define WHITE_LED_PIN 13EspMQTTClient client( "<wifi-ssid>", "<wifi-password>" "dev.rightech.io", "<ric-mqtt-client-id>");// Задача для обработки поступающих командclass ClientTask : public Task { public:   void loop() {     client.loop();   }} client_task;// Задача для включения светодиодовclass LedOnTask : public Task { protected:   void loop()   {     digitalWrite(WHITE_LED_PIN, HIGH);     digitalWrite(BLUE_LED_PIN, HIGH);     shouldRunValue = false; // останавливаем этот цикл сразу после включения   }   bool shouldRun()   {     return shouldRunValue;   } public:   bool shouldRunValue = false;} led_on_task;// Задача для выключения светодиодовclass LedOffTask : public Task { protected:   void loop()   {     digitalWrite(WHITE_LED_PIN, LOW);     digitalWrite(BLUE_LED_PIN, LOW);     shouldRunValue = false; // останавливаем этот цикл сразу после выключения   }   bool shouldRun()   {     return shouldRunValue;   } public:   bool shouldRunValue = false;} led_off_task;// Задача для плавного горения светодиодов в противофазеclass LedAttenuationTask : public Task { protected:   void loop()   {     // Вычисляем задержку на один проход цикла в зависимости от полученного в payload значения     float delayValue = period.toInt() * 1000 /*в миллисекунды*/ / 2 /*на два цикла*/ / 1024 /*на каждую итерацию в цикле*/;     for (int i = 0; i <= 1023; i++) {       analogWrite(WHITE_LED_PIN, i); // горит ярче       analogWrite(BLUE_LED_PIN, 1023 - i); // тускнеет       delay(delayValue);     }     for (int i = 1023; i >= 0; i--) {       analogWrite(WHITE_LED_PIN, i); // тускнеет       analogWrite(BLUE_LED_PIN, 1023 - i); // горит ярче       delay(delayValue);     }   }   bool shouldRun()   {     updateDelayTimer();     if (isDelayed()) return false;     if (!run_group_active) return false;     return shouldRunValue;   } public:   bool shouldRunValue = false;   String period;} led_attenuation_task;// Задача для быстрого мигания светодиодов в противофазеclass LedFlashingTask : public Task { protected:   void loop()   {     float delayValue = period.toInt() * 1000 /*в миллисекунды*/;     digitalWrite(WHITE_LED_PIN, HIGH);     digitalWrite(BLUE_LED_PIN, LOW);     delay(delayValue);     digitalWrite(WHITE_LED_PIN, LOW);     digitalWrite(BLUE_LED_PIN, HIGH);     delay(delayValue);   }   bool shouldRun()   {     updateDelayTimer();     if (isDelayed()) return false;     if (!run_group_active) return false;     return shouldRunValue;   } public:   bool shouldRunValue = false;   String period;} led_flashing_task;void setup() { // Настраиваем пины в режим выхода, т.е. в режим источника напряжения pinMode(WHITE_LED_PIN, OUTPUT); pinMode(BLUE_LED_PIN, OUTPUT); // Библиотека Scheduler позволяет при необходимости запустить несколько потоков Scheduler.start(&led_on_task); Scheduler.start(&led_off_task); Scheduler.start(&led_attenuation_task); Scheduler.start(&led_flashing_task); Scheduler.start(&client_task); Scheduler.begin();}void onConnectionEstablished() { // Подписываемся на команды и запускаем нужный поток путем изменения переменной shouldRunValue client.subscribe("led_on", [] (const String & payload)  {   client.publish("base/state/light", "on");   led_off_task.shouldRunValue = false;   led_attenuation_task.shouldRunValue = false;   led_flashing_task.shouldRunValue = false;   led_on_task.shouldRunValue = true; }); client.subscribe("led_off", [] (const String & payload)  {   client.publish("base/state/light", "off");   led_on_task.shouldRunValue = false;   led_attenuation_task.shouldRunValue = false;   led_flashing_task.shouldRunValue = false;   led_off_task.shouldRunValue = true; }); client.subscribe("led_attenuation", [] (const String & payload)  {   client.publish("base/state/light", "attenuation " + payload + " sec");   led_on_task.shouldRunValue = false;   led_off_task.shouldRunValue = false;   led_flashing_task.shouldRunValue = false;   led_attenuation_task.period = payload;   led_attenuation_task.shouldRunValue = true; }); client.subscribe("led_flashing", [] (const String & payload)  {   client.publish("base/state/light", "flashing " + payload + " sec");   led_on_task.shouldRunValue = false;   led_off_task.shouldRunValue = false;   led_attenuation_task.shouldRunValue = false;   led_flashing_task.period = payload;   led_flashing_task.shouldRunValue = true; });}void loop() {}

Подключаем к платформе Rightech IoT Cloud


Подключение гирлянды:


1) Создаем модель




2) Создаем объект с этой моделью




Подключение кнопки:


1) Создаем модель




2) Создаем объект с этой моделью




Подробнее о том, как подключать ZigBee устройства, можно посмотреть в видеоуроке и почитать в статье.

Разрабатываем сценарий работы


От сценария автоматизации мы хотим следующей логики:

1) один клик (single) режим постоянного свечения и выключения;

2) два клика (double) режим плавного свечения;

3) три клика (triple) режим мигания;

4) после 20:00 автоматическое выключение гирлянды (здесь также можно использовать не просто расписание, а данные еще из одного объекта СКУДа, который собирает информацию о том, есть ли люди в офисе. Если вам интересен материал по такой теме, дайте обратную связь в комментариях ).

Готовый автомат




Давайте вкратце разберем, что тут происходит и зачем:

  1. Первым делом при старте автомата запускаем планировщик, который выключит гирлянду по расписанию, обезопасив нас от забывчивости. Запустили и забыли, он будет срабатывать каждый день автоматически.
  2. В следующем состоянии не делаем ничего, просто ждем нажатия кнопки. В это состояние мы возвращаемся каждый раз после отработки определенного режима гирлянды. Из него есть переход по событию получения данных и срабатыванию планировщика.
  3. Если получили какой-то пакет от кнопки, то переходим в состояние Получен пакет, из которого по таймеру и типу клика переходим в соответствующие режимы. Вы можете спросить, зачем тут таймер. А причина в том, что кнопка работает довольно интересненько. При нажатии три раза, она сначала присылает пакет с double, а сразу за ним triple. Такой нюанс мы и обходим таймером, иначе срабатывало бы по неактуальному клику.
  4. Также есть промежуточное состояние для одинарного клика. Как мы помним, вкл/выкл у нас работают по одному и тому же событию. Поэтому, если гирлянда не выключена (находится в любом из режимов активной работы), то мы ее выключаем, а если выключена, то включаем.

Запускаем автомат на наших объектах, проверяем фуууух, работает! Время паять!




Собираем готовое устройство


Самый простой вариант пайки гирлянды это один за другим спаивать светодиоды, предварительно надевая термоусадку. Примерно вот так:

image

Но можно пойти немного другим путем сделать не просто гирлянду, которой мы обвяжем елку, облачив ее дополнительно во все эти провода. Вместо этого на каждую веточку посадим по светодиоду (в цветочках это смотрится особенно чудесно, см. итоговое фото), стянем провода по стеблю вниз и спаяем, спрятав всю электронику в горшочке. На выходе остается только разъем под кабель питания. Ювелирно, аккуратно и очень симпатично получается. Судите сами.

image

термоусадку нагреваем паяльным феном

image

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

image

и лудим (наносим небольшой слой припоя)

image

проводок готов воссоединяться со светодиодом

image

соединяем (паяем поверхности, на которых уже есть припой)

image

фиксируем на веточке, сгибая ножки (необходимо предварительно оставить не менее 10 мм) светодиода

image

на данном этапе проводим последнее тестирование

image

готово!




В заключение хотим сказать, что неважно, какие гирлянды именно в вашем доме цветные или однотонные, ультрасовременные или, напротив, винтажные, светодиодные или галогеновые. Главное, чтобы они создавали праздничное настроение перед Новым годом, несли тепло и радость в сердца ваших близких.

С наступающим праздником!

Материалы к статье


image
Подробнее..

Системы контроля управления доступом в IoT умеем, знаем, практикуем

27.01.2021 14:17:26 | Автор: admin

И снова привет, мир!

В прошлой статье про IoT-елочку в голосовании многие отметили, что интересна тема управления устройствами в зависимости от количества человек в помещении. Это довольно масштабная задача, и мы предлагаем разделить ее решение на несколько этапов. Сегодня поговорим о системе контроля управления доступом (СКУД), которая, будучи подключенной к платформе интернета вещей Rightech IoT Cloud (далее по тексту - платформа), является базовым элементом в системе подсчета количества человек в офисе. Мы уже поверхностно освещали этот кейс в одной из статей, но сегодня рассмотрим этот проект более подробно и погрузимся в особенности исполнения.

СКУД?

Система контроля и управления доступом, СКУД (англ. Physical Access Control System, PACS) совокупность программно-аппаратных средств контроля и управления, главная цель которой - ограничение и регистрация входа-выхода объектов (людей, транспорта) на заданной территории через точки прохода: двери, ворота, КПП.

С чего все началось

Задача обеспечить контроль за входом-выходом в офисе возникла еще в те времена, когда у нас был выход на крышу с отличным видом на Москву, и поэтому часто приходили люди, не являющиеся нашими сотрудниками. Тогда мы решили принять какие-то меры по безопасности и установить СКУД.

Архитектура

Система открытия дверей по карте

В качестве модуля, отвечающего за обработку информации по считыванию бесконтактных карт, выбрали GATE-8000.

Основные достоинства контроллера:

  • формирование и хранение необходимой информации о факте открытия двери по карте и времени прохода человека в офис;

  • возможность автономной работы и защиты от зависания;

  • хранение 16 тысяч ключей и 8 тысяч событий;

  • простое подключение и управление;

  • российский производитель, хорошая документация с описанием работы контроллера.

Внешний вид платы с контроллеромВнешний вид платы с контроллером

Основной принцип работы: контроллер обрабатывает информацию, поступающую со считывателя, и с помощью встроенного реле коммутирует исполнительное устройство - электромагнитный замок двери.

Система взаимодействия с платформой

После того, как контроллер установили в систему по общей схеме подключения, а карты записали в память, мы уже обезопасили себя от прохода в офис посторонних. А дальше возник вопрос, как подключить этот контроллер к платформе Rightech ioT Cloud. Ведь очень здорово иметь а) графический интерфейс, в котором можно полистать историю всех проходов, б) возможность отправки команд на открытие двери удаленно, не отходя от рабочего места, например, для гостей или доставщика еды.

У контроллера нет выхода в Интернет и видимой возможности подключения к платформе, к тому же все события нужно принудительно считывать из его циклического буфера. Однако у него есть свой протокол обмена данными с компьютером управления, благодаря которому можно отправлять на контроллер команды, такие как считать из контроллера, записать в контроллер, открыть/закрыть замок и другие. Значит, нужно сделать некоторую программно-аппаратную прослойку между контроллером и платформой - агента, который будет отправлять команды на чтение событий и управление контроллером.

Обращаем внимание, что в данной архитектуре функция открытия двери при прикладывании карты не перестанет выполняться при отсутствии Интернета. За открытие двери и сбор информации отвечает контроллер СКУД, поэтому в случае потери Интернета, единственное, что нам грозит, - это то, что агент, который доставляет данные на платформу, не будет функционировать, так как не сможет получать команды на чтение буфера. Однако при восстановлении соединения все события считаются в полном объеме и не потеряются, так как они будут сохранены в буфере контроллера СКУД.

Аппаратная часть

Для начала нужно было выбрать устройство, которое будет всегда в активном состоянии с включенной программой-агентом в непосредственной близости от платы СКУД. Из многообразия микрокомпьютеров первое что попало под руку выбор пал на Raspberry Pi.

Дальше возник вопрос, как подсоединить GATE-8000 к Raspberry - то есть как подключить последовательный интерфейс RS485 от GATE к USB от микрокомпьютера. Начались поиски переходника USB-RS485. Первый вариант, который мы испробовали, - Espada за 200 рублей. Надежда на то, что маленький хлипкий китайский переходник заработает, была небольшой. Он и не заработал. Вместо нужных данных приходило что-то похожее по виду и размеру, но всё же не то. В чем было дело: в отсутствии гальванической развязки, невозможности поддерживать скорость 19200 bps или же просто в некачественной элементной базе, - загадка. Но после обращения к производителю GATE-8000, мы получили рекомендацию на более дорогой (в 10 раз) и громоздкий (но аккуратный и корпусированный) переходник Z-397, который заработал тут же как надо.

Программная часть

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

  1. Что нужно - взаимодействие с GATE-8000 для отправки команд и получения данных.

    Как решим - изучим протокол GATE, напишем сериализатор и десериализатор данных, подключим библиотеку для работы с последовательным портом.

  2. Что нужно - взаимодействие с платформой для получения команд и отправки данных.

    Как решим - выберем для общения протокол MQTT, в коде воспользуемся готовой библиотекой Paho MQTT.

Итак, мы приступили к изучению протокола GATE-8000, который является закрытым, поэтому ниже рассказано только о некоторых его особенностях. Он достаточно низкоуровневый, и необходимо обращаться напрямую к регистрам памяти устройства. В документе по этому протоколу описаны кадры запросов от компьютера контроллеру и кадры ответов контроллера компьютеру. Меняя поля в кадре запроса, можно отправлять на устройство различные команды и получать информацию из регистров.

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

1) задавать всю логику работы в агенте;

2) использовать внешние запросы (от платформы).

Мы выбрали второй вариант и вынесли логику с конечного устройства на платформу (подробнее про сервис сценариев автоматизации >>>). Так ее легко адаптировать и подстроить, при этом код программы остается компактным и позволяет просто формировать команды для устройства, а платформа в свою очередь координирует отправку команд и их периодичность.

Всегда ли нужно выносить логику работы с устройства?

Такое решение, конечно, не подойдет, если от устройства требуется предпринять действия мгновенно (например, если идет речь о жизни человека), но даже в таком случае часть логики можно вынести на платформу. Как вариант, для выбора заранее запрограммированных шаблонов поведения.

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

Карта памяти контроллера? WTF?

Под картой памяти контроллера (термин из протокола) имеется в виду таблица с описанием заполнения регистров памяти, а не микрофлешка =).

Следующая особенность работы с контроллером в том, что за один цикл чтения можно получить только 12 событий, по 8 байт на каждое. А на каждый проход человека в офис генерируется уже два события:

1) найден ключ в банке ключей (банк ключей - еще один блок в распределенной памяти контроллера);

2) состоялся проход (если он, конечно, состоялся).

Ниже представлен фрагмент кода на С++, реализующий метод одного цикла чтения буфера.

bool SerialPortInlet::readBufferCycle(unsigned short& bottom, unsigned short const& top, unsigned char& u_lowerBound,    unsigned char& l_lowerBound, std::vector<unsigned char>& readBuffer, std::string& result){// Подсчет байтов, которые необходимо считатьunsigned short byteCountTmp = top - bottom;BOOST_LOG_SEV(log_, logging::info) << "Need read " << byteCountTmp << " byte";unsigned char byteCount;// За один цикл нельзя прочитать более 12 событий (96 байт)byteCount = byteCountTmp > 0x60 ? 0x60 : (unsigned char)byteCountTmp;BOOST_LOG_SEV(log_, logging::info) << "Read " << +byteCount << " byte";// Описываем тело командыstd::vector<unsigned char> body = {0x02, 0xA0, byteCount, u_lowerBound, l_lowerBound};std::vector<unsigned char> command;// Получаем полный текст командыgenerateComplexCommand(command, Command::BYTE_CODE_READ, body);// Если не удалось по каким-то причинам отправить команду (например, конечное устройство не подключено), возвращается falseif (!sendCommand(command, result)){    return false;}// Иначе отправляем ответ с устройства на парсинг по событиямSerialPortType::Answer answerEvents;if(!Parsers::parserAnswer(log_, result, answerEvents, Command::BYTE_CODE_READ)){    BOOST_LOG_SEV(log_, logging::error) << "Failed parse buffer reading";    return false;}readBuffer.insert(readBuffer.end(), answerEvents.body.begin(), answerEvents.body.end());// Сдвигаем нижнюю границу буфера для чтения следующих событийbottom = bottom + byteCount;u_lowerBound = (unsigned char)(bottom >> 8) ;l_lowerBound = (unsigned char)bottom;return true;}

Немного добавило хлопот то, что, наконец вытащив нужные байты, на месте информации о карте, мы увидели не номер карты, а адрес, по которому он находится. Поэтому потом каждый номер ключа приходится отдельно считывать по адресу. Также не сразу заметили наличие байтстаффинга, его обработку мы ввели уже после первого тестирования с платой.

Байтстаффинг?

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

Пример байтстаффинга из документацииПример байтстаффинга из документации

Полная структурная схема разработанной системы выглядит так.

Работоспособность всех устройств было очень удобно проверять с помощью графического последовательного терминала СuteCom. После успешного тестирования программа была поставлена на автозапуск, а Raspberry отправилась жить на потолке рядом с платой СКУДа.

Один делает, другой смотрит, третий фотографирует, огнетушитель придерживает дверь - настоящая командная работа =)Один делает, другой смотрит, третий фотографирует, огнетушитель придерживает дверь - настоящая командная работа =)

Работа на платформе Rightech IoT Cloud

Модель

Основные данные с контроллера - это события, на платформу они приходит в формате JSON и включают в себя поля

  • eventTime - время наступления события;

  • eventCode - код события;

  • keyNumber - номер карты сотрудника (поле может быть пустым, если событие вызвано не картой).

Модель устройства выглядит следующим образом.

Посмотреть оригинал >>>

Возможные события:

  • нажата кнопка звонка;

  • неопознанный ключ на входе;

  • неопознанный ключ на выходе;

  • ключ найден в банке ключей при входе;

  • ключ найден в банке ключей при выходе;

  • открывание оператором по сети;

  • дверь заблокирована оператором;

  • дверь оставлена открытой после входа;

  • дверь оставлена открытой после выхода;

  • проход состоялся на вход;

  • проход состоялся на выход;

  • перезагрузка контроллера.

Объект

Интерфейс объекта полностью формируется согласно разработанной модели.

Интерфейс истории журнала объектаИнтерфейс истории журнала объекта

Посмотреть оригинал >>>

Интерфейс командИнтерфейс команд

Ура, теперь, собравшись на кухне офиса в ожидании пиццы на праздник, можно никуда не идти, а просто открыть мобильное приложение и нажать кнопку открытия двери для курьера!

Автомат

Можно заметить, что есть команда не только на чтение буфера событий, но и на запись новых границ. В памяти контроллера хранятся границы буфера - начало и конец. Когда на устройство приходит команда чтения, из памяти берутся эти границы и в их пределах происходит чтение из буфера событий. Граница конца буфера сдвигается автоматически на контроллере при получении новых событий. А вот начальную границу буфера нужно перезаписать (указав конечную границу после прошедшего чтения), чтобы не прочитать одни и те же данные повторно. Но это необходимо сделать только после того, как данные о событиях успешно отправлены на платформу.

Зафиксировать успешное получение данных и затем отправить команду на перезапись начальной границы удобно в автомате.


Посмотреть оригинал >>>

Здесь виден цикл <чтение>-<запись новой границы буфера>-<ожидание таймера> (сейчас события считываются каждые 30 секунд).

  1. В состоянии Read events читаем новые события.

  2. В состоянии Clear buffer записываем новую границу.

  3. В состоянии Await timer ожидаем начала нового цикла.

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

Дальнейшее использование собранных данных

Данный проект нашел свое продолжение в интеграции с нашей внутренней CRM системой, в которой на вкладке информации о сотрудниках всегда видны актуальные сведения о том, кто находится или отсутствует в офисе.

Также отображается время входа/выхода из офиса, считается суммарное количество часов в месяц.

Посмотреть оригинал >>>

В мессенджер Slack каждый день пишется о том, что офис открыт, когда приходит первый человек, взявший ключи на ресепшене.

Забор данных из платформы производится по REST API. API платформы предоставляет возможность работы, взаимодействия и использования сущностей платформы и их данных в таких внешних системах, как веб-порталы, мобильные и веб-приложения или, как в нашем случае, - CRM системах.

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


Теперь мы знаем немного больше о том, как может работать СКУД в IoT-проектах. В следующих материалах рассмотрим, как рассчитать на базе полученной информации количество человек в офисе и какие практические применения есть у этой идеи.

Подробнее..

Создание своей оценочной платы для микроконтроллеров

16.04.2021 02:15:22 | Автор: admin

Заказывая много оценочных плат из Китая, я и подумать не мог что всюду будет брак, недоработки и подделка. Всё это ужасно путало в изучении и порой было тяжело понять то ли мой код кривой, то ли контроллер. Примерно в это же время я нашёл микроконтроллеры и другую рассыпуху дешевле чем в Китае при это локально в России. Я сразу загорелся тем, что бы сделать себе платы и забыть о китайских корявых blue pill.

Брак или странная задумка инженеров

Земля на ножках для прошивки висела в воздухе, после доработки всё окей.

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

Первые наброски выглядели примерно так:
v1v1

Тут я ещё не знал, что для нормальной прошивки мк нужен pull-up резистор на ногу сброса.

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

Когда приехали платы качество меня порадовало, но был и косяк с моей стороны текст настолько мелкий что кое где не читается.

Детальное фото печатной платы

В итоге у меня было куча плат, с пяток контроллеров и разных вторичных компонентов, выпаянных из разных плат. Всё это вылилось в 3 рабочих прототипа.

В итоге у меня было куча плат, с пяток контроллеров и разных вторичных компонентов, выпаянных из разных плат. Всё это вылилось в 3 рабочих прототипа:

Фото ужасное, но переснять не могу уже раздал их)Фото ужасное, но переснять не могу уже раздал их)

Немного о платах

Остановился на 6 светодиодах. Всего 3 группы: питание, 4 GPIO, 1 GPIO(ШИМ) на обратной стороне. У каждой группы есть маленькая напаиваемая перемычка.

USB только питание, по входу стоит диод, защита usb выхода от обратного напряжения которое может пойти если запитать схему >5в напряжением. Стабилизатор выдерживает пиковые 16в, штатное до 14в.

Контроллер может без проблем работать и от 5в, но расчёт резисторов для светодиодов выполнял для 3.3, да и базово считаю что лучше работать с 3.3, ибо потом по привычке можно что-нибудь спалить.

Продолжаем вакханалию

Это была только половина пути, я ведь хотел много плат и очень не хотел делать их вручную.

Для информации из паяльного инструмента у меня был только паяльник, не было даже фена (оставил там откуда уехал). Зато в новой квартире обнаружилась духовка с очень чётким контролем температуры, я думаю дальше понятно что будет, особо впечатлительные не принимайте близко к сердцу.

И так, надо было решать как спаять всё быстро и с минимумом косяков. Трафарета у меня не было и я решил попробовать просто намазать тонким слоем паяльную пасту (благо она была).

Сказано сделано, вот что из этого вышло:

Мелкие капельки припоя что никуда не стекли прилипли прилично, далеко не с первого раза я их смог убрать, так же видно что 2 контроллера немного поплыли и встали криво. Выглядит жуть, но в целом получилось неплохо. Я делал несколько прогонов, первый мк и обвязка, остальное вторым. И по выходу получилось около 70% годных и готовых сразу без танцев плат.

Финальный результат, usb портов к этому времени не подвезли, так что без них.

Пока остановился на этом, с новой партией плат должен прийти трафарет, там уже будут другие танцы и другие бубны.

Планы у меня наполеоновские, уже нарисовал и под stm32f0 и под f1 платы, ещё есть идея создать плату на stm32f4(7) с интегрированных ethernet.

Для тех кто дочитал, спойлер след платы!

В следующей статье затрону контроллер и среды, в которых пишу. Ни пуха ни пера и не болейте!

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru