Содержание статьи
Недавно я закончил сборку своего электровелосипеда. Теперь я могу не только колесить в близлежащих парках, но и использовать его в качестве полноценного средства передвижения. Скорость до 55 км/ч позволяет уверенно держаться в городском потоке машин, а бесшумность, отсутствие запаха бензина плюс небольшая масса — спокойно ездить по паркам и тротуарам, а также хранить транспорт дома. В общем, сплошные плюсы. Когда надо припарковаться и пойти по делам, на раме моего велосипеда защелкивается U-образный замок Kryptonite. Однако мотор и новенький аккумулятор уже не делают раму самой дорогой частью велосипеда. И поэтому остро встает вопрос защиты транспортного средства от тех, кто тоже следует за прогрессом, но не желает на него тратиться. Короче говоря, от воров.
Имеющиеся в продаже сигнализации для велосипедов просто отпугивают воришек громким звуком. Поэтому я решил сделать собственное устройство с обратной связью. Первое, что пришло в голову, — разработать сигнализацию на микроконтроллере. Но затем я подумал: почему бы не использовать старый смартфон, который лежит без дела? Ведь у него на борту уже есть все необходимое, чтобы решить поставленную задачу: мобильный интернет, GPS для определения местоположения, различные датчики для обнаружения внешних воздействий, камера и сенсорный экран. В общем, вопрос с железом был решен, осталось только реализовать программную часть. Чтобы лучше понять принцип работы описанного в статье устройства, можешь сразу посмотреть демонстрацию его работы.
Termux
Если ты еще не слышал про Termux, то срочно отправляйся изучать матчасть. «Хакер» уже писал на эту тему. Termux — это эмулятор терминала для операционной системы Android. Но пускай тебя не смущает слово «эмулятор», весь код выполняется нативно.
Как ты знаешь, в основе Android — ядро Linux. Termux добавляет к ядру минимальное окружение в виде набора утилит и интерпретатора Bash. Этот набор может быть легко расширен хорошо известной пользователям Linux командой apt
(или pkg
). При этом список пакетов достаточно обширный: от консольного редактора Vim до оконной системы X11 и среды рабочего стола Xfce. Все это работает без прав суперпользователя!
Кроме того, всегда есть возможность написать свою программу на С или даже языке ассемблера. Компилятор GCC также можно установить из пакетов. Если есть права root, все становится еще интереснее: можно подключить репозиторий root-repo и получить доступ к таким программам, как tcpdump или Aircrack-ng. Для наших же целей root-права не потребуются: все, что нам нужно, — это установить интерпретатор языка Python 3. К счастью, нужный пакет уже имеется в репозитории.
Termux я рекомендую установить из магазина софта с открытым исходным кодом F-Droid. Если у тебя в телефоне еще нет этого магазина, отправляйся на сайт f-droid.
и скачивай соответствующее приложение. Далее в самом F-Droid в строке поиска напиши Termux и установи следующие приложения: Termux, Termux:API и Termux:Widget. Если Android на твоем телефоне ниже седьмого, то тебе понадобится уже архивная версия. Ее ты можешь взять тут. После установки запускай Termux и инсталлируй необходимые пакеты и модули питона, которые нам понадобятся. Для этого в открывшемся терминале набери следующие команды:
pkg update
pkg install termux-api
pkg install openssh
pkg install qrencode
pkg install python
pkg install pip
pip install pystun3
Обрати внимание, что pystun3
в последней строке — это модуль питона, поэтому мы установили его командой pip
, а не pkg
.
Termux:API
Командой pkg
мы установили поддержку Termux-API, что позволяет взаимодействовать с системой Android из командной строки: делать фото, записывать и воспроизводить звук, подавать вибросигнал, получать информацию с датчиков телефона, выводить диалоговые окна и прочее. Чтобы изучить все возможности Termux-API, набери в командной строке termux-
, нажми два раза Tab, и увидишь все доступные утилиты. Функциональности вполне достаточно, чтобы организовать взаимодействие с пользователем с помощью всплывающих сообщений (termux-toast), диалоговых окон (termux-dialog) и уведомлений (termux-notification).
Для сигнализации нам понадобится информация с датчика ускорения — акселерометра. Для этого посмотрим сначала, какие датчики присутствуют в телефоне:
termux-sensor -l
В полученном списке датчиков ищи тот, в названии которого есть слово accelerometer. Например, в моем телефоне имеется BMI160 Accelerometer и Linear Acceleration. Теперь можно попробовать опросить датчик такой командой:
termux-sensor -s "BMI160 Accelerometer" -n 1
В моем случае вывод этой команды имеет следующий вид:
{ "BMI160 Accelerometer": { "values": [ 0.35223388671875, 0.20556640625, 9.873580932617188 ] }}
Обрати внимание на две вещи. Во‑первых, вывод информации по одному измерению занимает девять строк. В дальнейшем мы используем это для парсинга выходного потока с датчика ускорения. Во‑вторых, ускорение выводится в виде его компонентов по трем пространственным координатам. Если ты еще не забыл школьный курс физики, то уже сообразил, что сумма квадратов этих величин даст нам квадрат ускорения. Его‑то мы и будем вычислять для определения движения телефона.
Если в предыдущей команде опустить параметр -n
, то данные с датчика будут выводиться непрерывно с интервалом в одну секунду. Интервал, в свою очередь, можно изменить, добавив ключ -d <
. Этим мы и воспользуемся в программе. Датчик ускорения достаточно чувствительный, чтобы определить не только перемещение твоего девайса, но и вибрацию от легкого удара по столу, на котором лежит устройство.
Предварительная подготовка
Писать код можно прямо на телефоне, установив любой текстовый редактор, например Vim или Nano. Но проще делать это на компьютере, а затем отправить программу по SSH на телефон. Для этого в файл ~/.
нужно положить свой ключ SSH. После чего в консоли Termux запустить демон sshd, введя одноименную команду. Учти, что демон sshd слушает нестандартный порт 8022, поскольку у него нет привилегий суперпользователя.
Теперь можно с ПК получить доступ к телефону командой ssh <
. Обрати внимание, что имя пользователя можно не указывать, Termux примет любое. Узнать IP-адрес телефона в твоей локальной сети можно, введя команду ifconfig
в консоли Termux. Если ты пользователь Windows, то для подключения используй клиент Putty. Для пересылки файла программы из текущего каталога на компьютере в Termux достаточно в терминале на компе ввести такую команду:
cat program.py | ssh <IP-адрес телефона> -p 8022 "cat > program.py"
для Linux или такую для Windows:
set PATH=C:\путь\до\папки\putty;%PATH%pscp -P 8022 program.py <IP-адрес телефона>
Если телефон подключен к домашней сети Wi-Fi, Termux не очень отзывчив при соединении по SSH. По всей видимости, это связано с переходом передатчика в телефоне в энергосберегающий режим. Если ты тоже столкнешься с такой проблемой, ее можно решить командой iw
, выполненной от рута. А если таких прав нет, ты можешь подключиться к телефону либо по USB-кабелю, включив режим USB-модема, либо по Wi-Fi, переведя телефон в режим точки доступа.
Пишем код
Программа состоит из двух частей: клиентской и серверной. Клиент будет работать на телефоне, закрепленном на велосипеде, и периодически отправлять UDP-пакеты серверу — телефону, который находится рядом с тобой. В содержимом пакета может быть либо KNOCK, либо ALARM. Получив сообщение KNOCK, сервер будет знать, что клиент работает штатно и не имеет проблем с сетью. В случае сообщения ALARM будем проигрывать заранее подготовленный файл со звуком сирены.
Итак, приступаем к написанию клиентской части программы, которую назовем client_alarm.
. Сначала сделаем импорт необходимых модулей.
#!/data/data/com.termux/files/usr/bin/env python3import socketimport jsonfrom subprocess import Popen, PIPEimport osimport timefrom nat import nat_traversal
Первая строка — это шебанг. Чтобы каждый раз не писать такой длинный путь, можешь использовать стандартный для Linux /
, а потом вызвать утилиту termux-fix-shebang
. Она исправит путь до программы env
на подходящий для Termux. Далее зададим необходимые константы.
AVERAGE = 10KNOCK_DELAY = 5SENSOR_NAME = 'BMI160 Accelerometer'ACCELEROMETER_DELAY = 20ACCELERATION_THRESHOLD = 0.1DELAY_AFTER_ALARM = 1RPORT = 0RHOST = ''
Здесь AVERAGE
— число измерений ускорения, по которым мы будем вычислять среднее значение. Усреднение нужно для более стабильной работы, чтобы исключить ложные срабатывания сигнализации. KNOCK_DELAY
— задержка в секундах между «отстукиванием» на сервер. ACCELEROMETER_DELAY
— задержка в миллисекундах, которая будет передана команде termux-sensor
. ACCELERATION_THRESHOLD
— важный параметр, который определяет порог срабатывания сигнализации. Если сделать его слишком маленьким, то чувствительность возрастет, но при этом можно получить ложные срабатывания. Рекомендую подобрать этот параметр экспериментально так, чтобы добиться нужной тебе чувствительности. DELAY_AFTER_ALARM
— пауза после каждого срабатывания сигнализации. Она нужна, чтобы не «засыпать» сервер пакетами с сигналом ALARM. RHOST
и RPORT
— адрес, куда будем отправлять пакеты.
И тут возникает проблема: чтобы организовать коммуникацию двух устройств по сети, хотя бы одно из них должно иметь публичный (еще говорят «белый») IP-адрес. Для этого нужно либо арендовать VPS-сервер, либо заказать соответствующую услугу у твоего интернет‑провайдера. После чего можно обеспечить прямую видимость устройств, подключив их к собственному серверу, например через OpenVPN или Wireguard. Как это сделать, «Хакер» писал здесь. Именно так я и сделал. Но если у тебя еще нет арендованного сервера, то не спеши расстраиваться. Я расскажу, как соединить два находящихся за NAT устройства по сети напрямую.
Проходим сквозь стену
NAT (network address translation) — это механизм трансляции сетевых адресов, который позволяет нескольким устройствам подключаться к хостам в интернете, используя один общий IP-адрес. На сегодняшний день именно технология NAT дает возможность более чем 20 миллиардам устройств по всему миру иметь доступ в глобальную сеть, при том что «белых», то есть маршрутизируемых в интернете, IPv4-адресов всего чуть более четырех миллиардов.
У разных провайдеров NAT может быть настроен по‑разному. Для соединения устройств мы будем использовать STUN (Session Traversal Utilities for NAT) — специальный сетевой протокол, который позволяет клиенту за NAT узнать свой внешний IP-адрес, а также способ трансляции порта во внешней сети. В данном случае за нас все сделает функция get_ip_info(
модуля pystun3
, который мы установили ранее.
Продолжение доступно только участникам
Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее
Вариант 2. Открой один материал
Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.
Я уже участник «Xakep.ru»