Система верификации пользователей посредством RFID карт с отправкой сообщений в Telegram
-
Сегодня речь пойдет о системе верификации пользователей, которая в будущем сможет стать (и станет, я надеюсь) полноценной системой двухфакторной верификации пользователей. В качестве первого фактора будем использовать RFID карту, в качестве второго - распознавание лица пользователя с помощью OpenCV. На данный момент второй фактор работает в ручной режиме и фото отправляется в Телеграм оператору. Но автор топика активно работает над адаптацией каскада Хаара для распознавания лиц. И, как знать, может скоро и выйдет еще одна статья. Не будем загадывать. Все равно в одну статью это все не уместить. Поэтому начнем. Кому интересно - добро пожаловать под кат.
1. Схемотехническое проектирование
1.1 Лирическое отступление
Я считаю, что наш ГОСТ вполне имеет право на жизнь. И, если следовать порядку проектирования, описанному в нем, то процесс разработки и поддержки любого реального проекта становится проще и понятнее любому члену команды. По крайней мере это точно касается маленьких проектов вроде этого, особенно если не заниматься занудством до невозможности и не пытаться соблюсти его кругом и всюду.
1.2 Непосредственно проектирование
Проектирование устройства было начато с разработки электрической структурной схемы, представленной ниже. Из схемы видно, что устройство состоит из трёх основных блоков: Raspberry Pi, модуля считывания RFID карт RFID-RC522 и WEB-камеры.
Монитор - не обязательная вещь. На него просто будут выводиться логи вроде "Карта №... Доступ разрешен".
Выбор считывателя ничем не обоснован. Взял тот, что был под рукой.
Процесс работы устройства выглядит следующим образом: пользователь прикладывает RFID карту к считывателю, Raspberry Pi проверяет разрешен ли доступ для владельца карты, если доступ разрешен, то делается фотография web-камерой. Информация о владельце карты (для примера, у нас будет ID карты) и фотография автоматически отправляются оператору устройства на заранее сконфигурированный номер в Telegram. Если пользователю данной карты доступ запрещен, то фотографирования не происходит, выдается сообщение «Доступ запрещен!» и сообщение не отправляется.
В качестве WEB-камеры может использоваться любая WEB-камера совместимая со стандартным классом USB устройств USB Image. Т.е. практически любая USB WEB-камера, за исключением совсем экзотики.
При отправке Telegram-боту сообщения вида /photo в ответ оператор получает последнее фото с камеры.
При отправке Telegram-боту сообщения вида /text в ответ, для примера, будем выводить информацию о том какой пользователь воспользовался системой последним (прошел через турникет, например).
2. Разработка ПО
2.1 Структура ПО
В начале я хотел написать свой модуль ядра для работы с SPI, но про это можно написать целую отдельную статью. Да и зачем?? Если есть готовый. Может когда-нибудь в академических целях...
Поэтому использовать мы будем стандартный драйвер spi_bcm2708.
По умолчанию он занесен в blacklist ввиду не использования его большинством пользователей. Поэтому комментируем соответствующую строчку в соответствующем файле. Это делается так:
sudo nano /etc/modprobe.d/raspi-blacklist.conf
в этом файле комментируем строку
blacklist spi-bcm2708
Модуль активировали.
Хотел написать библиотеку для работы с этим модулем. Но и тут не получилось выпендриться. Уже есть готовая.
Для взаимодействия будем использовать уже написанную библиотеку. Она требует для работы другую - SPI-Py
Следующий набор команд установит все, что нам потребуется (git, разумеется, уже должен быть установлен):
sudo apt-get install python-dev git clone https://github.com/lthiery/SPI-Py.git cd SPI-Py sudo python setup.py install git clone https://github.com/rasplay/MFRC522-python.git
Писать будем на языке python. Работать будем в директории MFRC522-python.
cd MFRC522-python
Структура нашего проекта представлена на рисунке ниже.
Взаимодействие со считывателем RFID карт осуществляется через стандартный модуль ядра spi_bcm2708. Основные функции работы с SPI из userspace реализованы в библиотеке SPI-Py. По средствам этой библиотеки модуль чтения запускает опрос считывателя. Конфигурация модуля чтения RFID меток (регистры, функции для работы) реализованы в модуле конфигурации. В нем же хранится конфигурация Telegram бота (token). После считывания RFID метки модуль чтения обращается к модулю фото. В ответ получает фото пользователя, которое направляется в модуль отправки сообщений для отправки оператору в Telegram вместе с информацией о пользователе.
Раз уж мы решили использовать OpenCV для распознавания лиц, то осуществлять захват изображения с камеры тоже будем с её помощью. OpenCV ставится на Raspberry Pi ровно также как и на любую другую Linux-машину. Описывать процесс её установки в рамках топика не вижу смысла. Мануал по установке есть на официальном сайте, просто повторяем шаги и всё.
Далее будет описана реализация основного функционала. А полный код проекта будет доступен по ссылке в конце статьи.
Опрос RFID считывателя происходит в бесконечном цикле вида:
while continue_reading: (status,TagType) = MIFAREReader.MFRC522_Request(MIFAREReader.PICC_REQIDL) # Опрашиваем RFID считыватель if status == MIFAREReader.MI_OK: # Если обнаружена карта print "Card detected" (status,backData) = MIFAREReader.MFRC522_Anticoll() if status == MIFAREReader.MI_OK: print "Card read UID: "+str(backData[0])+","+str(backData[1])+","+str(backData[2])+","+str(backData[3])+","+str(backData[4]) if (( backData == cardA ) or ( backData == cardB ) or ( backData == cardC )): # Сравниваем для примера с тремя захардкоженными идентификаторами трёх билетиков московского метро print "welcome" ### Получаем снимок с камеры через OpenCv ### capture = cv.CaptureFromCAM(0) frame = cv.QueryFrame(capture) cv.SaveImage("../../../Camera/telegram/image/ny.jpg", frame) del(capture) ### #### ### Запись файла с информацией о пользователе #### f1 = open("../../../Camera/telegram/text1.txt", 'wb') f1.write("The") if ( backData == cardB ): f1.write("User with cardB is comming") elif ( backData == cardA ): f1.write("User whith cardA is comming") ### #### # запуск отправки в Телеграм os.system('python3 telegram.py') else: print "wrong Card"
Я постарался максимально закомментировать код дабы исключить пояснения в основном тексте статьи. С остальными фрагментами кода буду поступать аналогично.
Теперь надо зарегистрировать Telegram-бота. Простейший мануал опять же есть на официальном сайте и пересказывать его шаги в этой статье я не буду. Ещё есть документация и примеры исходных кодов для интересующихся.
Требуемый нам функционал реализуем так:
### Отправка текcтовой информации ### def mes (): f = open('../../../Camera/telegram/text1.txt') bot.send_message(<тут ваш идентификатор>, f.read()) return 0 ### Отправка фото ### def photo (): photo = open('../../../Camera/telegram/image/ny.jpg', 'rb') bot.send_photo(<тут ваш идентификатор>, photo) return 0 mes() photo()
Вместо <тут ваш идентификатор> вписываем идентификатор абонента, которому отсылаем сообщение.
Осталось реализовать ответы бота на сообщения. Для этого надо создать обработчики соответствующих команд /photo и /text:
### Обработка команды /text ### @bot.message_handler(commands=['text']) def mes (message): f = open('../../../Camera/telegram/text1.txt') # файл с информацией, который сохраняли ранее bot.send_message(message.chat.id, f.read()) # отправка return 0 ### Обработка команды /photo ### @bot.message_handler(commands=['photo']) def photo (message): photo = open('../../../Camera/telegram/image/ny.jpg', 'rb') # фото, которое сохраняли ранее print(message.chat.id) bot.send_photo(message.chat.id, photo) # отправка
Реализацию основных частей рассмотрели.
3. Макет
На основании п.1 и п.2 был разработан макет устройства, представленный на фото ниже. В качестве RFID карт использовались билеты для проезда в Московском метрополитене.
К Raspberry Pi подключен RFID считыватель по интерфейсу SPI согласно таблице представленной ниже. WEB-камера подключается к USB-порту, расположенному на плате. Взаимодействие с сетью (API сервера Telegram) осуществляется через Ethernet порт.
Таблица подключения RFID считывателя RC522 к Raspberry Pi
RPi пин RC522 пин 1 Vcc 6 GND 19 MOSI 21 MISO 22 RST 23 SCK 24 NSS
На этом статья подходит в концу. Полный код проекта доступен в моем репозитории на github . Не забываем вписывать ваш токен для Telegram-бота в файле config.py, а также вписывать свой идентификатор абонента, которому надо посылать фото и информацию.
P.S.
Статья написана для участия в конкурсе т.к. своей Rasberry Pi не имею. Для реализации этого проекта взял у друга на пару месяцев первую Raspberry.
Да, разработка - процесс неспешный. Тем более, что проектом занимаюсь исключительно в свободное время.
-
Здравствуйте! Есть аналогичный вашему проект, может Вы сталкивались со следующей ситуацией:
Платформа – Raspberry
Pi 3 , OS Raspbian
с графической оболочкой.Скрипт написан на Python 2.7 – Read_sim_QQ.py (https://github.com/PaulLos/RPi-QQ.git)
Данная программа считывает данные с бесконтактной карты
через RFID считыватель
подключенный к GPIO через
SPI.Аналогично вот этому примеру - https://www.raspberrypi-spy.co.uk/2018/02/rc522-rfid-tag-read-raspberry-pi/
В чикле считывания программа передает данные карты на наш
сервер.Проблема в следующем:
При запуске скрипта командой из терминального окна запуск
программы происходит не всегда корректно, а именно программа стартует, но
считывание не всегда начинается.Было замечено, что если после включения или рестарта системы
проходит достаточно большое время более 5 минут, то скрипт работает стабильно,
но если запустить программу сразу после старта системы, например через минуту,
то скрипт работает не корректно, но если его прервать CTL>C и запустить заново, то все начинает
работать корректно. И далее можно неоднократно останавливать и запускать
данное ПО - все работает.Проблема обнаружилась, когда я добавил запуск в файл
автостарта при запуске системы.Спасибо.