В этой части делаем из Raspberry Pi VoIP устройство для осуществления видео вызовов по SIP протоколу.

Первоначальная задача осталась прежней — осуществление вызова по внешнему воздействию (нажатию кнопки). Но немного изменилась реализация идеи. Как и в предыдущей части, воспользуемся терминальным SIP клиентом Linphonec, но в целях упрощения настройки, я решил воспользоваться VoIP провайдером Zadarma.com с бесплатными внутрисетевыми звонками, в том числе c поддержкой видео. Для видео звонков я использовал бюджетную USB камеру.

Подробности, а также пошаговая инструкция под катом.

Первая часть
Системы развернута на базовом образе для RPI v3_40_int из коробки без установки чего либо дополнительного.

Ссылка базовые образы MajorDoMo для Raspberry

Вебкамера, которую я использовал — бюджетная (около 7 уе, в Минске) — Ritmix RVC-015M. Имеет возможность ручной настройки фокуса.

В процессе тестирования и для написания поста, я решил отказаться от использования своего VoIP сервера (Fresswitch). Установка своего VoIP сервера усложняет процесс настройки, но дает более гибкие возможности.

Для примера, воспользуемся представленным на Хабре VoIP оператором Zadarma.

Для осуществления звонков нам требуется две учетные записи на SIP сервере. Под одной будет работать Raspberry Pi и консольный клиент, вторая для смартфона (или же ПК). Процесс регистрации интуитивно понятен, и не нуждается в описании.

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

Установка и сборка Linphone


Подготовка к установке:


Останавливаем запущенные, но неиспользуемые сервисы:

Остановка служб
sudo systemctl stop freeswitch.service
sudo systemctl stop majordomo.service
sudo systemctl stop avahi-daemon.socket
sudo systemctl stop avahi-daemon.service
sudo systemctl stop mosquitto.service
sudo systemctl stop mysql
sudo systemctl stop mpd.service
sudo systemctl stop mpd.socket
sudo systemctl stop homebridge.service
sudo systemctl stop nginx.service
sudo systemctl stop bluetooth.target
sudo systemctl stop bluetooth.service


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

Поочередные команды: проверка, включен ли в нашей установке Raspbian (Debian) файл подкачки, если вывод пуст, это означает, что в системе отсутствует файла подкачки.
Добавляем 1G swap и создаем файл.

Устанавливаем правильные разрешения на этот файл, только пользователь root может читать и писать в файл подкачки.

Используем инструмент mkswap для настройки области подкачки Linux в файле и активируем его:

sudo swapon --show
sudo fallocate -l 1G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

Установка консольного SIP клиента Linphonec и утилиты управления Linphonecsh


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

sudo apt-get install cmake automake autoconf libtool intltool yasm libasound2-dev libpulse-dev libv4l-dev nasm git libglew-dev

Переходим в домашнюю директорию и скачиваем сам пакет Linphone, скачивание заняло минут 20:

cd /home/pi/
git clone git://git.linphone.org/linphone-desktop.git -recursive

Переходим в созданную директорию при скачивании пакета, подготавливаем к установке версию без графического интерфейса:

cd linphone-desktop
sudo ./prepare.py no-ui -DENABLE_OPENH264=ON -DENABLE_WEBRTC_AEC=OFF -DENABLE_UNIT_TESTS=OFF -DENABLE_MKV=OFF -DENABLE_FFMPEG=ON -DENABLE_CXX_WRAPPER=OFF -DENABLE_NON_FREE_CODECS=ON -DENABLE_VCARD=OFF -DENABLE_BV16=OFF -DENABLE_V4L=OFF 

Выполняем сборку используя атрибут –j4 (т.е. выполняет сборку в 4 потока одновременно:

sudo make -j4

Сборка занимает минут 30-40.

Собранные файлы программ появились в директории OUTPUT/no-ui/bin. Для запуска программы перейдём в неё, проверим версию программы:

cd OUTPUT/no-ui/bin
./linphonec -v 

Получаем результат: version: 3.12.0

Перегружаем наш Raspberry.

При перезапуске восстанавливаются все сервисы прописанные в автозагрузке, удаляется файл подкачки.

Настройка терминального SIP клиента Linphonec


Запустим Linphonec в режиме автоответа от текущего пользователя pi:

/home/pi/linphone-desktop/OUTPUT/no-ui/bin/linphonec 

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

Как в первой части cсоздаём директорию от текущего пользователя (pi)

mkdir /home/pi/.local
mkdir /home/pi/.local/share
mkdir /home/pi/.local/share/linphone

Т.к. в нашем случае мы не используем VoIP сервер, то используется стандартный порт для IP телефонии 5060.

Произведем регистрацию одного из аккаунтов выполнив в Linphonec следующую команду:

register sip:XXXXXX@sip.zadarma.com sip.zadarma.com YYYYYYY  

формат команды можно посмотреть набрав help register.

В нашем случае XXXXXX — номер (логин) учетной записи, YYYYY — пароль, выдаваемый при регистрации. Проверим регистрацию:

status register

ответ при успешной регистрации: registered, identity=sip:XXXXX@sip.zadarma.com duration=3600

Выход из клиента осуществляется по нажатию ctrl+c или командой quit.

После выхода в домашней директории /home/pi появился файл настройки консольного клиента: .linphonerc.

Подключение WEB видеокамеры


Подключаем к Raspberry камеру.

Проверяю, включена ли моя учетная запись в группу video

cat /etc/group | grep video

Ответ: video:x:44:pi

Посмотрим определилась ли веб-камера в вашей системе:

sudo ls -l /dev/ | grep video

Проверим определился ли микрофон камеры:

arecord -l

Ответ:

List of CAPTURE Hardware Devices
card 1: CAMERA [USB2.0 PC CAMERA], device 0: USB Audio [USB Audio]
Subdevices: 1/1
Subdevice #0: subdevice #0


Всё в порядке, микрофон тоже есть. Проверим его в алсемиксере

alsamixer

Сразу уточню, микрофон у меня по умолчанию включен, определился как основной и выкручен почти полностью, идет сильное переусиление.

Нажимаем F6 (выбор карты), выбираем USB PC Camera, дальше F4 — устройство Capture (микрофон на камере), опустим его уровень почти до нуля, курсорными клавишами вниз, заодно проверим и Capture.

<img src="" alt=«image»/>
В маркете приложений для Android устанавливаю приложение Linphone (перепробовал несколько, только у него завелась трансляция видео. На Windows все SIP клиенты, которыми я пользуюсь — работают без проблем. Так же без проблем заводится на моем SIP сервере (freeswitch, если использовать в локальной, да и не только сети, то наилучший вариант свой сервер + шлюз для звонков из своей локальной сети).

Инструкция по настройке приложения для Android Linphone приведена на сайте Zadarma.com.
Инструкция от SIP провайдера .

Производим регистрацию мобильного телефона на Zadarma, далее по желанию настраиваем опции видео, аудио и т.д.

Для тестирования запустим в RPI утилиту linphonec с функцией видео звонка и автоответа (добавив ключи -V -a):

/home/pi/linphone-desktop/OUTPUT/no-ui/bin/linphonec -V -a 

и произведём вызов в терминальном клиенте набрав:

call 576935

подстановка сервера VoIP (домена) производится автоматически, хотя можно и полностью набрать SIP адрес.

В итоге получим:


(более менее хорошее качество для этой камеры на расстоянии до метров 2-3-ех от объектива).

Можем проверить режим автоответа, набрав на смартфоне номер для RPI.

Для запуска и управления Linphonec в режиме демона, используется утилита Linphonecsh.

Первоначально при запуске необходима инициализация клиента linphonecsh -init. При выполнении этой команды происходит запуск консольного клиента, без загрузки конфигурационного файла.
Чтобы при запуске выполнялось чтение конфигурационного файла, возможность видео звонка и автоматического ответа на входящие вызовы запустим с флагами — с — V -a:

/home/pi/linphone-desktop/OUTPUT/no-ui/bin/linphonecsh init -c /home/pi/.linphonerc -V -a

Сейчас можем управлять консольным клиентом из командной строки ОС и MajorDoMo.

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

/home/pi/linphone-desktop/OUTPUT/no-ui/bin/linphonecsh dial XXXXX 

Первый шаг, можно сказать сделан.

Подключение кнопки и работа с GPIO




В Raspberry Pi имеется ряд портов GPIO (General Purpose Input/Output) это интерфейс. который содержит Входы и Выходы общего назначения, к которым можно подключать разнообразные исполнительные устройства, в нашем случае простую кнопку.

Почти любой контакт GPIO (есть несколько зарезервированных) можно установить в одно из двух состояний: «выход» (он же OUT или логическая 1) или «вход» (IN или логический 0). Напряжение на выходе составляет 3,3В.

Для своей кнопки я буду использовать два самых правых контакта в верхнем ряду. Разъём #38 (GPIO20) будет установлен на «выход» (OUT), а разъём #40 (GPIO21) — на «вход» (IN).

Для подключения к гребенки GPIO используются перемычки BBJ. Рекомендуется проводить подключение при отключенной малинки от сети.

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

Bash скрипт для инициализации портов GPIO:

sudo nano /usr/local/bin/gpio21.sh

и вставляем содержимое

gpio21.sh
#! /bin/bash
# Set up GPIO20 and set to output
echo «20» > /sys/class/gpio/export
echo «out» > /sys/class/gpio/gpio20/direction
echo «1» > /sys/class/gpio/gpio20/value
# Set up GPIO21 and set to input
echo «21» > /sys/class/gpio/export
echo «in» > /sys/class/gpio/gpio21/direction

Делаем файл исполняемым:

sudo chmod +x  /usr/local/bin/gpio21.sh

Второй скрипт для набора номера по нажатию кнопки, я решил сделать на PHP, для последующей интеграции с систему домашней автоматизации MajorDoMo. По нажатию кнопки, меняется состояние порта 21, система периодически считывает значение порта 21 и в случае его изменения отправляет команду набора номера утилите Linphonecsh.

sudo nano /usr/local/bin/dial.php

и вставляем содержимое:

dial.php
<?php
$old_state = 0;
while(true)
{
$state = file_get_contents('/sys/class/gpio/gpio21/value');
if ( $state != $old_state)
{
if ( $state == 1 )
{
//Making new call
echo «make »;
exec («sudo -u pi /home/pi/linphone-desktop/OUTPUT/no-ui/bin/linphonecsh dial sip: ХХХХХ@sip.zadarma.com»);
usleep(200000);
}
$old_state = $state;
}
usleep(20000);
}
?>

Делаем файл исполняемым.

Далее прописываем три строчки в самый конец файла автозагрузки:

  1. скрипт инициализации портов GPIO
  2. запуск утилиты управления в режиме автоответа и поддержкой передачи видео
  3. PHP скрипт набора номера.

crontab -e


@reboot sudo /usr/local/bin/gpio21.sh
@reboot sudo -u pi /home/pi/linphone-desktop/OUTPUT/no-ui/bin/linphonecsh init -c /home/pi/.linphonerc -V -a
@reboot sudo php /usr/local/bin/dial.php

Перегружаем наш Raspberry, sudo reboot. После перезапуска наш видеофон готов к использованию.

Дальше при желании и возможности — интеграции в систему домашней автоматизации, подключение к своему SIP серверу и т.д.

Нагрузка на RPI во время ожидания и при совершении видео звонка
Нагрузка на RPI во время ожидания и при совершении видео звонка:





Небольшое отступление в качестве заключения


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

При создании хотел бы, чтоб выполнялись следующие критерии, или хотя бы два из трёх:

  1. Доступность (возможность покупки комплектующих здесь и сейчас (в моей местности).
  2. Бюджетность (невысокая стоимость устройства на выходе).
  3. Простота исполнения или же, хотя бы полнота пошаговой инструкции (Возможность человеку, которому потребовалось его повторить, без особых познаний и временных затрат, сделать устройство и начать им пользоваться).

Комментарии (7)


  1. ermakovd
    13.12.2019 08:05

    Вот здесь описано создание похожей, но гораздо более законченной вызывной панели на Малине.


    1. udvnl Автор
      13.12.2019 08:20

      Спасибо, видел и читал. Хорошо и толково там написано. Первоначально шёл по параллельному пути.
      Основное отличие идеи (технические подробности в расчёт не беру) — в статье про SIP домофон, работает только в своей локальной сети со своим VoIP сервером Asterix (про его настройки написано совсем мало). В моем посте, доступ не зависит от месторасположения пользователя.
      Ну и мое имхо, чем больше будет описания идей и реализаций их, с пошаговыми действиями, тем лучше.


  1. udvnl Автор
    13.12.2019 10:16

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

    парочка фото







  1. psinetron
    13.12.2019 11:08

    Спасибо за статью, очень познавательно!
    Не погружался в VoIP, но у меня такой вопрос — имеет ли смысл повторить проект на каком-нибудь Esp32? Есть сразу наборы с камерой, качеством она точно не уступает средней вебке. Однозначно получится компактнее, дешевле и можно сделать автономное питание. Правда не знаю — потянет ли Esp? Если потянет — готов попробовать повторить


    1. udvnl Автор
      13.12.2019 11:22

      С ESP я не работал совсем, но насколько я думаю — навряд ли. Она ж вроде работает не под управлением Linux.


      1. psinetron
        13.12.2019 11:35
        -1

        Нет, не под линуксом. Еще раз повторюсь, с VoIP(мы же о нем говорим?) я особо не работал, поэтому поправьте меня, если я совсем чушь буду говорить или совсем не в разрезе статьи, просто мне интересно заглянуть дальше в ваш проект и разобраться как его можно удешевить. Esp32cam поддерживает стриминг видео. Если я правильно понимаю, то VoIP основан на http протоколе, значит по сути тот же самый стриминг можно вести на VoIP сервер.


        1. udvnl Автор
          13.12.2019 11:57

          Для проекта я вначале устанавливал консольного клиента, первая проблема — как его установить на ESP, вторая проблема, здесь я использовал сторонний сервер Zadarma, % на 99,9 уверен в него никто ничего не даст вносить.
          Ну и немного поправлю, VoIP основан на SIP протоколе, очень грубо два устройства клиентов и сервер как посредник обмениваются служебными сообщениями, в которых кроме прочего указывается на каком кодеке будут работать. Обычно используются кодеки H264, vp-8 (для видео). как то сумбурно получилось описать.
          Вот ESP для меня пока черный ящик. с контроллерами я не работал и их возмодностей не знаю.