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

Обсуждаем сайт и форум.

Модератор: f0s

Аватара пользователя
Alex Keda
стреляли...
Сообщения: 35477
Зарегистрирован: 2004-10-18 14:25:19
Откуда: Made in USSR
Контактная информация:

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

Сообщение Alex Keda » 2025-07-06 18:53:22

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

как бы мало, поэтому в качестве номера я попросил записать номер 3G GSM модема на дачной точке доступа, под OpenWRT и за вечер набросал и отладил скрипт который принимает звонок, проверяет есть ли звонящий номер в локальной базе номеров, если есть - вешает трубку, и звонит на ворота.

модем с симкой в роутре так и так стоит, т.к. это альтернативный канал в интернет, поэтому из затрат - новый модем с поддержкой голоса (~300 рублей на авито можно найти, или чуть дороже) и вечер времени на написание основного тела скрипта.
+ пару вечеров на шлифовку, по мере наличия желания =)

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

Код: Выделить всё

root@SmartBox:~# cat  /root/scripts/listen.sh    
#!/bin/sh

door="+79251234567"
db="/root/scripts/numbers.db"
call_timeout=20
port="/dev/ttyUSB2"

mail_login="modem@lissyara.su"
mail_server="mx.lissyara.su"
mail_pass="super-mega-pass"
mail_rcpt="admin@lissyara.su"

script="`basename $0`"
pid_file="/tmp/$script.pid"
hostname="`uci get system.@system[0].hostname`"
response_all="/tmp/response.all.log"
response_clip="/tmp/response.clip.log"
response_tmp="/tmp/response.tmp.log"
response_call="/tmp/response.call.log"

# stub: detect port change
test -c /dev/ttyUSB3 && port="/dev/ttyUSB3"

# check process
if test -s $pid_file
then
        pid=`cat $pid_file`
        num_proc=`ps w | grep $pid | grep $script | wc -l`
        if [ $num_proc -gt 0 ]
        then
                exit 0
        fi
fi

# write PID
echo -n $$ > $pid_file

# log start
logger "start listen calls, callback to $door, using $port"

# clear log
echo -n > $response_all
echo -n > $response_clip

# set up modem device to translate outgoing \n into \r\n   
stty -F $port 9600 -echo icanon onlcr igncr
# Open modem for reading                                   
exec 5<$port
# and writing
exec 6>$port

#function
write2port(){
        echo "$1" >&6
}
mailsend(){
        /usr/bin/mailsend -f $mail_login -smtp $mail_server -auth -user $mail_login \
                -pass $mail_pass -t $mail_rcpt -sub "$1" -M "`date +%Y-%m-%d` in `date +%H:%M:%S` $1" &
}


# https://habr.com/ru/articles/845034/
write2port AAAAAAAT
# allow RING message
write2port "AT+CRC=1"
# number detect (AON)
write2port "AT+CLIP=1"
# allow end call by ATH command
write2port "AT+CVHU=0"
# no last call list
#write2port "AT+CLCC=0"
#write2port "AT+CMGD=ALL"
# disable ^RSSI: in log
#write2port "AT^CURC=0" >&6

# read port in cycle
while true
do
        # timeout
        sleep 0.3
        # check port
        test -e $port || exit
        # read port
        read -t 1 RESPONSE <&5
        echo $RESPONSE > $response_tmp
        echo $RESPONSE >> $response_all

        # save call. count call, if 2 or more - open door
        if grep CLIP: $response_tmp
        then
                echo $RESPONSE >> $response_clip
                if [ `grep CLIP: $response_clip | wc -l` -lt 2 ]
                then
                        continue
                fi

                # extract last line
                AT=`grep CLIP: $response_clip | tail -1`
                # log call
                echo `date +%Y-%m-%d` in `date +%H:%M:%S`: $AT >> /tmp/$script.call.log
                # extract caller number from line
                number=`echo $AT | awk -F '"' '{print $2}'`
                # drop call
                sleep 1
                write2port "ATH"
                # log call
                logger "call from $number"
                # send info
                mailsend "$hostname: Call from `grep $number $db`"
                # callback
                if grep $number $db
                then                                                                   
                        sleep 1
                        # send mail to me
                        mailsend "$hostname: open door, by `grep $number $db`"
                        # log open door
                        logger "call to $door, open by $number"
                        # call to doors
                        write2port "ATD$door;"

                        sleep 2

                        # clear callback log
                        echo -n > $response_call

                        # wait ~8 seconds and drop call, if no response
                        start=`date +%s`
                        while true
                        do
                                # read and save answer
                                read -t 1 RESPONSE <&5
                                echo $RESPONSE >> $response_call
                                echo $RESPONSE >> $response_all
                                # check answer
                                if grep "CONN:1,0" $response_call
                                then
                                        # log end call by answer
                                        logger "call to $door end by answer"
                                        # end call by answer
                                        write2port "AT+CHUP"
                                        # start listener
                                        sleep 2 && sh /root/scripts/listen.sh &
                                        exit
                                fi
                                # time in seconds
                                end=`date +%s`
                                # diff between start and end time
                                diff=`expr $end - $start`
                                # check run time
                                if [ $diff -gt $call_timeout ]
                                then
                                        logger "call to $door end by timeout: $call_timeout seconds expired"
                                        # end call
                                        write2port "AT+CHUP"
                                        # reboot modem
                                        #sleep 2
                                        #write2port "AT+CFUN=1"
                                        # start listener
                                        sleep 2 && sh /root/scripts/listen.sh &
                                        exit
                                fi
                        done
                else
                        # log unknown number
                        logger "number not found: $number"
                        mailsend "$hostname: number not found: $number"
                        echo -n > $response_call
                        echo -n > $response_clip
                        # reboot modem
                        #sleep 2
                        #write2port "AT+CFUN=1"
                fi
        fi
done

# delete pid
rm -f $pid_file

sh /root/scripts/listen.sh &
ну и раз в минуту в планировщик его

Код: Выделить всё

root@SmartBox:~# crontab -l
#
MAILTO=""

4       4       *       *       *       sh /root/scripts/backup.sh
1,21,41 *       *       *       *       sh /root/scripts/ping.and.reboot.sh
*       *       *       *       *       sh /root/scripts/listen.sh
база номеров в формате номер - примечание

Код: Выделить всё

root@SmartBox:~# cat /root/scripts/numbers.db
+79261112233    lissyara
+79264445566    nikita small
дополнительный софт: sleep, stty, mailsend
(штатный sleep не умеет интервалы менее 1 секунды)

собственно, известные баги.
1. некорректно работает pgrep, поэтому процесс приходится искать через ps. возможно свзяано с тем что замучал саму OpenWRT, надо переустанавливать, и проверять на чистую - но - лень =)
2. иногда модем отваливается. зависит от модема (я тестил на паре huawei, остановился на E3131, более стабильно работает, пока отваливался один раз за две недели, к сожалению разбираться возможности не было, ребутнул удалённо точку и поехал)
3. периодически, на первый гудок детектитстя предыдущий звонивший номер. поэтому трубку вешаем по второму гудку. не разобрался, вроде народ в инетах жаловался на подобную проблему но у меня никакими АТ командами это исправить не удалось. костыль, ждём второй гудок, второй детект - там номер 100% верный.

и, да, интернет по 3G нормально работает через этот же модем на порту ttyUSB0
Убей их всех! Бог потом рассортирует...

Хостинговая компания Host-Food.ru
Хостинг HostFood.ru
 

Услуги хостинговой компании Host-Food.ru

Хостинг HostFood.ru

Тарифы на хостинг в России, от 12 рублей: https://www.host-food.ru/tariffs/hosting/
Тарифы на виртуальные сервера (VPS/VDS/KVM) в РФ, от 189 руб.: https://www.host-food.ru/tariffs/virtualny-server-vps/
Выделенные сервера, Россия, Москва, от 2000 рублей (HP Proliant G5, Intel Xeon E5430 (2.66GHz, Quad-Core, 12Mb), 8Gb RAM, 2x300Gb SAS HDD, P400i, 512Mb, BBU):
https://www.host-food.ru/tariffs/vydelennyi-server-ds/
Недорогие домены в популярных зонах: https://www.host-food.ru/domains/

Аватара пользователя
Neus
майор
Сообщения: 2013
Зарегистрирован: 2008-09-08 21:59:56

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

Сообщение Neus » 2025-07-07 8:14:46

👍👍👍
Physics is mathematics with the constraint of reality.
Engineering is physics with the constraint of money.