# Конференция с постоянным внешним абонентом

* Допустим на АТС настроена конференц-комната с номером «**354233**».
* При звонке сотрудника(ов) в конференцию необходимо всегда подключать внешнего абонента.
* При отключении сотрудников от конференции внешнего абонента необходимо отключать

Это может потребоваться для организации связи с внешней (относительно MIKOPBX) конференцией. Позволит сэкономить на исходящих звонках (будет занята только одна линия).

1. В разделе «**Телефония**» - «**Конференция**» создаем новую конференцию

<figure><img src="https://3704471835-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPK4TuzRBnP7rt8htho-887967055%2Fuploads%2FdFqBPiC7FObKbVZmCCL3%2F1.png?alt=media&#x26;token=45c33adc-68c9-4699-b7ed-98311b225031" alt=""><figcaption><p>Раздел "Конференция"</p></figcaption></figure>

2. Укажем название комнаты «**Z-CONF-354233**»

<figure><img src="https://3704471835-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPK4TuzRBnP7rt8htho-887967055%2Fuploads%2FgrWGXCwMXJqycn242Tvp%2F2.png?alt=media&#x26;token=c6d1044e-6bcd-4af8-b6eb-9b303f090b5d" alt=""><figcaption><p>Окно создания новой конференции</p></figcaption></figure>

3. Укажем внутренний номер «**354233**»

<figure><img src="https://3704471835-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPK4TuzRBnP7rt8htho-887967055%2Fuploads%2Fmhk6x9rsE33xdtaeYYBf%2F3.png?alt=media&#x26;token=4a8ae8cd-951e-4daa-854b-bf3c6ae6c34f" alt=""><figcaption><p>Внутренний номер</p></figcaption></figure>

4. Опишем «**Приложение Dialplan**» (см. [Приложения диалпланов](https://docs.mikopbx.com/mikopbx/manual/modules/dialplan-applications))

<figure><img src="https://3704471835-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPK4TuzRBnP7rt8htho-887967055%2Fuploads%2Fj69f50FdFp2iVKEW3mrd%2F4.png?alt=media&#x26;token=42d11e02-e0d1-491a-866f-91b2adf57b51" alt=""><figcaption><p>Раздел Приложения диалпланов</p></figcaption></figure>

5. Название «**Z-Worker-CONF**»

<figure><img src="https://3704471835-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPK4TuzRBnP7rt8htho-887967055%2Fuploads%2FR3mwf5wG9OkBDXe51Jsj%2F5.png?alt=media&#x26;token=35b7fe00-5fbd-4369-8c68-d385490a8329" alt=""><figcaption><p>Указание названия в меню создания диалплана</p></figcaption></figure>

6. Номер для вызова «**2200103**» (может быть произвольным)

<figure><img src="https://3704471835-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPK4TuzRBnP7rt8htho-887967055%2Fuploads%2F4mTbjjJBCMaKNWbm4LQO%2F6.png?alt=media&#x26;token=2308e1b3-b108-45ad-9c5c-e8bb60f3db01" alt=""><figcaption><p>Указание номера для вызова приложения в меню создания диалплана</p></figcaption></figure>

7. Укажите тип кода «**PHP-AGI скрипт**»

<figure><img src="https://3704471835-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPK4TuzRBnP7rt8htho-887967055%2Fuploads%2Fe72Mr4vu4tIwESNMa4Oh%2F7.png?alt=media&#x26;token=b5d0d999-397b-41dd-b568-5d2edd48bd4d" alt=""><figcaption><p>Указание типа кода в меню создания диалплана</p></figcaption></figure>

8. Код

<figure><img src="https://3704471835-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPK4TuzRBnP7rt8htho-887967055%2Fuploads%2Fz2hA1g8zOOArtc5WDdyS%2F8.png?alt=media&#x26;token=ad8d35ad-b423-4215-9679-52c39423e0dc" alt=""><figcaption><p>Код в меню создания диалплана</p></figcaption></figure>

```php
<?php

require_once 'Globals.php';

use MikoPBX\Core\System\Util;
use \MikoPBX\Core\Asterisk\AGI;
use \MikoPBX\Core\Asterisk\AsteriskManager;

function checkStartConf(){
    $Z_DTMF         = '354233';
    $Z_PROVIDER_ID  = 'SIP-1601534775';
    $Z_DST          = '84957776675';

    $am = new AsteriskManager();
    $am->connect();

    $confEmpty = true;
    $confChannelFound = false;
    $data = $am->meetMeCollectInfo($Z_DTMF);
    foreach ($data as $channelData){
        $value = $am->GetVar($channelData['Channel'], 'ZDTMF', null, false);
        if(!empty($value)){
            // Это канал конференции.
            $confChannelFound = true;
        }else{
            // Есть канал конечного пользователя.
            $confEmpty = false;
        }
    }

    if($confChannelFound === false && $confEmpty === false){
        // Необходимо соединить с внешней конференцией.
        $am->Originate(
            'Local/'.$Z_DTMF.'@z-meetme',
            $Z_DST,
            'z-outgoing',
            '1',
            null,
            null,
            null,
            null,
            "__ZDTMF={$Z_DTMF},__ZPROVIDERID={$Z_PROVIDER_ID},__ZDST={$Z_DST}}",
            '0');

    }elseif ($confChannelFound === true && $confEmpty === true){
        $asteriskCmd = Util::which('asterisk');
        Util::mwExec("{$asteriskCmd} -rx 'meetme kick {$Z_DTMF} all'");
    }
}

$action = $argv[1]??'';
if($action === 'start'){
    $pid = Util::getPidOfProcess(basename($argv[0])." start$", getmypid());
    var_dump($pid);
    if(!empty($pid)){
        $killCmd = Util::which('kill');
        Util::mwExec("{$killCmd} {$pid}");
    }
    while (true){
        checkStartConf();
        sleep(3);
    }
}else{
    $agi = new AGI();
    $agi->answer();
    checkStartConf();
    $agi->hangup();
}
```

9. Правим файл «**/var/spool/cron/crontabs/root**» через меню [Кастомизация системных файлов](https://docs.mikopbx.com/mikopbx/manual/system/custom-files)

<figure><img src="https://3704471835-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPK4TuzRBnP7rt8htho-887967055%2Fuploads%2FEUa57geIn3cwhAo2mDxw%2F9.png?alt=media&#x26;token=381d95b9-46f2-4e95-bacc-58154a1d42c8" alt=""><figcaption><p>Файл "<strong>/var/spool/cron/crontabs/root"</strong> в меню кастомизация системных файлов </p></figcaption></figure>

10. &#x20;Добавляем задачу в конец файла:

<figure><img src="https://3704471835-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPK4TuzRBnP7rt8htho-887967055%2Fuploads%2FBZonuZo2chdVp32zGavf%2Fnewform.png?alt=media&#x26;token=1d4b7002-a342-44cd-ada9-766e7e6273ff" alt=""><figcaption><p>Добавление задачи в конец файла </p></figcaption></figure>

```php
*/1 * * * * /usr/bin/php -f /var/lib/asterisk/agi-bin/DIALPLAN-APP-EC12CFAE6783FE82FD34F16E40C7386B.php start > /dev/null 2> /dev/null
```

11. В данном примере «**DIALPLAN-APP-EC12CFAE6783FE82FD34F16E40C7386B**» - Это идентификатор созданного ранее приложения. ID можно подсмотреть в адресной строке браузера при редактировании приложения.
12. Опишем дополнительные контексты через меню [Кастомизация системных файлов](https://docs.mikopbx.com/mikopbx/manual/system/custom-files). Править будем файл **extensions.conf**.&#x20;

<figure><img src="https://3704471835-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPK4TuzRBnP7rt8htho-887967055%2Fuploads%2F3qw307uzhfTFhQplo7gF%2F11.png?alt=media&#x26;token=abc0b714-d654-4472-8609-d78be7b9e774" alt=""><figcaption><p>Правка файла "extensions.conf" в меню "Кастомизация системных файлов"</p></figcaption></figure>

13. Добавьте в конец файла следующий код:

```php
[z-outgoing]
exten => _X!,1,Ringing()
  same => n,Gosub(${ISTRANSFER}dial,${EXTEN},1)
  same => n,Dial(PJSIP/${EXTEN}@${ZPROVIDERID},600,${DOPTIONS}TKU(z-dial-answer)b(dial_create_chan,s,1))
  same => n,ExecIf($["${ISTRANSFER}x" != "x"]?Gosub(${ISTRANSFER}dial_hangup,${EXTEN},1))
  same => n,Set(pt1c_UNIQUEID=${EMPTY_VALUE})
  same => n,ExecIf($["${BLINDTRANSFER}x" != "x"]?AGI(check_redirect.php,${BLINDTRANSFER}))
  same => n,Hangup()

[z-dial-answer]
exten => s,1,NoOp(Answered send DTMF...)
  same => n,Gosub(dial_answer,${EXTEN},1)
  same => n,SendDTMF(${ZDTMF})
  same => n,return
	
[z-meetme]
exten => _X!,1,Answer()
  same => n,Meetme(${EXTEN},qdMTr)
  same => n,Hangup()
```

<figure><img src="broken-reference" alt=""><figcaption><p>Добавление кода в конец файла "extensions.conf" </p></figcaption></figure>

{% hint style="info" %}
При звонке в конференцию по номеру **354233** автоматически будет подключаться внешний абонент с номером **84957776675**. Как только абонент ответи, будет произведен набор добавочного номера **354233**. Как только все «внутренние» участники покинули конференцию, внешний абонент будет отключен.
{% endhint %}

{% hint style="info" %}
Задача в крон нужна лишь для дополнительной «защиты», по сути это рестарт php скрипта каждую минуту
{% endhint %}
