Хабрахабр

Доработка модуля шлагбаума Doorhan GSM для управления через интернет

Причины и необходимость этого решения остаются за рамками статьи, я же хочу написать про то, как «на коленке» сделал интерфейс для управления модулем через Интернет. Недавно было решено установить в многоквартирном доме шлагбаум с управлением через GSM. Возможно кто-то захочет внедрить у себя. И даже немного с блэкджеком, управлением базой автомобилей с мобильного телефона и фотографиями моментов въезда с уличной камеры.

Предупрежу, что в статье не описано готовое решение «из коробки», а скорее proof of concept.

Часть 1. Почему такой контроллер

Перед тем, как ставить GSM-модуль был проведен некоторый обзор рынка таких систем. Хотелось получить недорогое, надежное и отработанное решение. Ну и чтобы «в наличии» было у установщиков, имелся какой-то опыт работы с ним и т.д.

Установщики на выбор предлагали либо ESIM 110/120 за ~12000р с доступом в интернет, либо Doorhan GSM за ~6000р с управлением через SMS или настройкой через USB-шнурок.

Представьте, кто-то не смог заехать домой? Вариант «сделать свой девайс из arduino + gsm модуль за $3» не рассматривался, так решение должно быть точно надежным и обкатанным. Потом неприятностей получишь по полной.

Хотя цены начинаются от 1500р. Так же не хотелось лотереи с покупкой устройства в Китае на Али, опять же во избежание проблем с надежностью.

Для кого-то может это и плюс, но в нашем случае тянет за собой расходы на мобильную связь — придется брать тариф с интернетом. Минусом ESIM120, кроме стоимости х2 было то, что для выхода в интернет использовался GPRS-интернет. Например «погоду», «анекдоты» или что там еще полезно для шлагбаума ) Сейчас же на сим-карте подключен тариф без абонентской платы, и для того, чтобы номер не заблокировался, раз в 2-3 месяца планирую подключать из личного кабинета оператора какую нибудь платную подписку за 2-3 рубля в сутки, на одни сутки.

Про Doorhan GSM я знал, что помимо управления через SMS (мало интересно) он подключается по USB к компьютеру и через собственное ПО позволяет управлять базой номеров.

Часть 2. Проброс управления

Так как блок управления шлагбаумом планировалось ставить в 20 метрах от помещения, где расположен домовой IP-видеорегистратор и узел связи местного интернет-провайдера, то было решено взять Doorhan и «нарастить» USB через роутер вроде TP-Link MR3020 стоимостью 1200р, OpenWRT и программ из проекта USBIP

Его и использовал. С роутером получилось даже несколько проще — нашел в закромах старый ASUS WL500gP, который для интернета не очень годится по нынешним меркам, зато имеет 2 USB порта.

09, потому как на новых не работает этот модуль ядра. Для usbip пришлось поставить старую версию OpenWRT, 12. Если у кого-то он будет не в локальной сети, возможны варианты с пробросом портов, UPNP или настройкой VPN, на ваш вкус. Подключение роутера к сети описывать не буду.

Устанавливаем kmod-usbip-server и проверяем, что у нас можно экспортировать

root@OpenWrt:~# opkg install kmod-usbip-server
root@OpenWrt:~# usbip list -l
Local USB devices
================= - busid 1-1 (0424:2502) 1-1:1.0 -> hub - busid 1-1.1 (1a86:7523) 1-1.1:1.0 -> ch341

Нам нужен busid устройства, 1-1.1 на котором располагается наш подключенный контроллер GSM. Забегая вперед, оказалось что это банальный COM->USB конвертер на чипе CH341

Выполняем:

root@OpenWrt:~#usbipd -D
root@OpenWrt:~#usbip bind -b 1-1.1
bind device on busid 1-1.1: complete

и в dmesg

usbip-host 1-1.1:1.0: usbip-host: register new device (bus 1 dev 57 ifn 0)

На компьютере с Windows устанавливаем драйвера USBIP и запускаем

usbip -a 10.16.19.19 1-1.1

где 10.16.19.19 IP-адрес нашего роутера с OpenWRT. Разумеется, для начала нужно отрыть доступ либо с вашего IP к роутеру в firewall, либо подключаться с локальной сети, либо любой из 1000 других вариантов от VPN до P2P.

Если все прошло успешно, то Windows радостно заявляет, что обнаружено новое устройство USB-to-Serial Converter CH340, даем ей драйвера и в системе появляется COM-порт.

Теперь можем запустить программку из комплекта с контроллером и управлять номерами в базе сидя дома на диване

Часть 3. Контроль въездов

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

Управлять модулем AT командами не получилось, видимо они не транслируются от модуля контроллера в модуль модема. Оказывается, GSM-модуль контроллера периодически шлет AT команды с уровнем сигнала в консоль, а так же при звонке пишет номер телефона, с которого поступает звонок.

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

1 и делаем insmod ch341. Для этого на OpenWRT устанавливаем kmod-usb-serial-ch341, отключаем трансляцию USBIP командой usbip unbind -b 1-1.

После чего прямо на роутере можно подключиться к /dev/ttyUSB0 и смотреть что там происходит со звонками в контроллере.

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

#!/bin/sh
cat /dev/ttyUSB0 | while read DATA; do if echo $DATA | grep CLIP 2>/dev/null >/dev/null; then curl --silent --output /dev/null --data "data=$DATA" http://1.2.3.4:8081/border.php; >/dev/null 2>/dev/null fi
done

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

Дело в том, как я упоминал выше, вокруг дома стоят AHD камеры, которые пишут на регистратор с доступом к потоку по IP. Вторая идея, которая пришла мне в голову — сделать связку между событием открывания шлагбаума и фото этого события. Причем одну из камер специально повернули на шлагбаум, в ожидании что его будут ломать.

Поэтому пошел в лоб — в момент звонка получаю RTSP и делаю из него JPG. Как снять jpeg с нашего китайского регистратора мне найти не удалось, хотя во многих камерах есть Preview URL.

ffmpeg -i "rtsp://2.3.4.5:554/user=user&password=password&channel=1&stream=0.sdp?" -y -f image2 -t 0.001 -ss 00:00:3 -s 1280*720 /tmp/screenshot.jpg

С таким же успехом можно было писать маленькие ролики в mp4, но я посчитал это лишним.
Фотографии решил хранить блобами в MySQL. Решение по производительности так себе, зато «таскать» проектик будет проще, не нужно копировать и базу и файлы, все в базе. А нагрузка на него никакая по сути.

В результате лог въездов выглядит как-то так:

Часть 4. Загрузка номеров из SQL базы на сайте в контроллер

Если вы внимательно читали, то наверное заметили — для регистрации въездов USB порт роутера работал в режиме Serial-to-USB преобразователя, а для работы с базой номеров внутри контроллера приходилось «прокидывать» его через USBIP на домашний компьютер и там через программу для Windows вносить изменения. Это не совсем удобно, нужно было делать unbind/bind да еще на домашнем компьютере запускать usbip консольный. Ну и делать это можно было только из дома (ну либо опять RDP/VPN и проч и проч), и тем более не с телефона мобильного. Вдвойне накаляло то, что базу номеров надо было вести и в mdb-формате (программа для контролера может выгружать данные в Access) и в веб-версии.

Не исключаю, что это какая-то китайская девайсина под маркой Doorhan, тем не менее. Беглый гуглеж протокола работы Doorhan GSM ничего не дал. Поэтому вооружился монитором (сниффером) для COM-порта и снял несколько дампов при работе из оригинального приложения.

Получил что-то вроде:
Команда на очистку памяти aa 02 09 00 00 03 e8 01 00 00 00 00 ee
Ответ что все прошло хорошо aa 20 00 ee
Команда на запись одного номера +79999999999
aa 03 10 00 01 2b 37 39 39 39 39 39 39 39 39 39 39 00 00 ee

Потом идет количество номеров в посылке. Из чего сделал такие выводы:
начало посылки АА, конец посылки ЕЕ
Ответ, что команда принята 20 00
Команда на начало записи номера 03. Может быть от 1 до 5, то есть за одну посылку можно отправить сразу несколько номеров подряд, закончив посылку командой ЕЕ, и получить одно подтверждение на блок.

То есть если писать в пустую память, то сначала это 1, потом 2 и так далее. После команды начала записи идет 2 байта (второй точно, первый возможно будет использоваться при количестве номеров больше 256 но не проверял), указывающие порядковый номер записи в ячейке. Так как наши номера«входят» в 12 байт (+79999999999) то последние 2 байта заняты нулями. После чего идет 14 байт номера телефона. Это не точно, сильно не вникал, потому что хватило этих данных. Вероятно для всяких международных форматов типа +10.

Завершается посылка байтом ЕЕ.

Допустим, в контроллер записано 10 номеров, память не очищали. С порядковым номером ячейки не совсем понятная ситуация. А если дать команду «записать номер в ячейку 11», то он запишется в нее. Если отправить команду «записать номер в ячейку 5», то номер в этой ячейке после контрольной вычитки не изменится, но в контроллере будет записано 11 номеров, причем 11-й будет пустой. Но так как оригинальное приложение делает только полное стирание и последующую перезапись списка, проверить гипотезу не получается. Вероятно это связано с командами ADD и REPLACE (добавить и изменить), которые можно слать через SMS. Поэтому свой вариант делал тоже отправкой команды стирания и последовательной записи по одному номеру (для простоты).

Но порт в роутере, а база с пользователями на внешнем сервере. Итак, мы подошли к тому, чтобы писать в контроллер через последовательный порт команды на управление списком абонентов. Пошел другим путем — прокинул /dev/ttyUSB0 по tcp с помощью пакета ser2net, который есть в поставке openwrt. Переносить ее на роутер конечно можно (получится законченное решение «из коробки») но мне было лень.

Конфиг /etc/ser2net.conf простой для неприличия

3333:raw:0:/dev/ttyUSB0:9600,remctl

После запуска ser2net можно подключиться к роутеру telnet-ом на 3333 порт и проверить результат.

То есть конечно работал, но в консоль писал мусор. Хочется сделать оговорку: после перезапуска роутера внезапно не работал cat /dev/ttyUSB0. Просто установив режим 9600 8n1 результата не дало, поэтому я посмотрел с помощью stty какие настройки порта стоят в «рабочем» состоянии и вписал в rc.local инициализацию Вспомнил, что во время экспериментов на роутере я запускал minicom, который вероятно сделал инициализацию порта.

stty -F /dev/ttyUSB0 9600 ignbrk -brkint -icrnl -imaxbel -opost -onlcr -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke

Наверняка что-то лишнее, читатели поправят возможно. Ну и если параметры порта указать в ser2net.conf то можно не ставить на роутер пакет stty.

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

$re = '/CLIP: ".(7\d)"/m'; //регэксп на входящий звонок while (1) { $f=@fsockopen('tcp://10.16.19.19',3333, $errno, $errstr); //подключимся к роутеру while ($f && $str=fread($f, 100)) { $test=preg_match($re, $str, $matches); if ($test) process_call($matches[1]); //пришел звонок, запишем в базу и сделаем фото
//проверим нужно ли записать телефоны из базы в контроллер и сделаем это, если нужно, используя дескриптор $f sync_phones($f); } if ($f) fclose($f); //что-то пошло не так sleep(5); //подождем 5 сек и сделаем реконнект }

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

И да, рукалицо, я использовал mysql вместо pdo или mysqli. На sync_phones остановлюсь чуть подробнее, потому как там реализован тот самый «не публичный» алгоритм работы GSM-контроллера Doorhan.

function sync_phones($f) { /* В таблице config хранится переменная update. Если в веб-интерфейсе сделать val=1, то должен запуститься процесс обновления номеров в контроллере. Можно сделать семафор через файл, но раз я все равно использую mysql, то решил сделать так */ $result=mysql_query("SELECT * FROM config WHERE name='update' AND val=1"); if (mysql_num_rows($result)==0) return; $init = pack('H*','aa1100ee'); //какой-то пакет инициализации при подключении программы к контроллеру $clear = pack('H*','aa0209000003e80100000000ee'); //команда на стирание данных (выдрано с дампа СОМ-порта) $logfile=fopen("/tmp/border.log","a"); fwrite($logfile,"Update started at ".date('Y-m-d H:i:s')."\n"); fwrite($f,$init); sleep(1); $ans=fread($f, 40); fwrite($logfile,"Send init. Answer ".bin2hex ( $ans )."\n"); fwrite($f,$clear); sleep(1); $ans=fread($f, 40); fwrite($logfile,"Send clear. Answer ".bin2hex ( $ans )."\n"); $result=mysql_query("SELECT * FROM phones ORDER BY pid"); //тут все ясно, select всех номеров из базы пользователей, чтобы записать их в контроллер $n=1; while($row=mysql_fetch_array($result)) { $start = 'aa0310'; $pos = sprintf("%04x",$n); $phone = bin2hex('+'.$row['phone']).'0000'; $end = 'ee'; //собираем "посылку" $send=$start.$pos.$phone.$end; $bin=pack('H*',$send); fwrite($f,$bin); $ans=fread($f, 40); fwrite($logfile,"Write {$n} phone {$row['phone']}. Answer ".bin2hex ( $ans )."\n"); $n++; } fwrite($logfile,"End update\n"); fclose($logfile); //запишем в наш "семафор" время, когда обновление завершено, полезная информация. И сам флажок, что обновление не требуется mysql_query("UPDATE config SET val=0,result='".bin2hex ( $ans )."',updated=NOW() WHERE name='update'");
}
?>

Часть 5. Заключение

В результате я получил (написал) WEB-интерфейс для шлагбаума, куда могу заходить через мобильный браузер, добавлять/удалять/изменять там номера жильцов нашего дома, делать пометки, с привязкой к квартире, ФИО, номеру телефона, номеру авто. Есть фотографии авто, лог въездов через шлагбаум с фото. В будущем, по логам посмотрю кто создает наибольшую нагрузку на шлагбаум — тот и будет оплачивать ремонт 🙂

Ну и бонусом получил WIFI-точку на парковке возле дома.

Цена вопроса — 0 рублей и выходной за компом.

Показать больше

Похожие публикации

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»