anders/ami-react

异步、事件驱动的 Asterisk 管理接口 (AMI) 访问

v0.3.1 2016-11-01 13:06 UTC

This package is auto-updated.

Last update: 2024-09-29 05:07:36 UTC


README

简单的异步、事件驱动的 Asterisk 管理接口 (AMI) 访问 自定义版本

Asterisk PBX 是一种流行的开源电话解决方案,提供了一系列电话功能。 Asterisk 管理接口 (AMI) 允许您控制并监控 PBX。其中之一,可以用来发起新的通话,执行 Asterisk 命令或监控订阅者、通道或队列的状态。

  • 异步执行动作 - 向 Asterisk 发送任意数量的动作(命令),并行处理它们的响应,一旦结果到来即可处理。基于 Promise 的设计提供了一种 合理的 接口来处理超界响应。
  • 事件驱动的核心 - 注册您的事件处理器回调以对传入的事件做出反应,例如传入的通话或订阅者状态的更改。
  • 轻量级、SOLID 设计 - 提供了一个薄薄的抽象层,它是 恰到好处 的,不会妨碍您。未来的或自定义的动作和事件无需更改即可支持。
  • 良好的测试覆盖率 - 附带自动测试套件,并定期测试与 Asterisk 1.8+ 版本兼容。

目录

快速入门示例

安装后,您可以使用以下代码访问您的本地 Asterisk 电话实例,并通过 AMI 发出一些简单命令

$loop = React\EventLoop\Factory::create();
$factory = new Factory($loop);

$factory->createClient('user:secret@localhost')->then(function (Client $client) {
    echo 'Client connected' . PHP_EOL;
    
    $sender = new ActionSender($client);
    $sender->listCommands()->then(function (Response $response) {
        echo 'Available commands:' . PHP_EOL;
        var_dump($response);
    });
});

$loop->run();

另请参阅 示例

用法

工厂

Factory 负责创建您的 Client 实例。它还将所有内容注册到主要的 EventLoop

$loop = \React\EventLoop\Factory::create();
$factory = new Factory($loop);

如果您需要自定义 DNS 或代理设置,可以显式传递一个自定义的 ConnectorInterface 实例

$factory = new Factory($loop, $connector);

createClient()

可以使用 createClient(string $amiUrl): PromiseInterface<Client> 方法创建一个新的 Client。它有助于建立到 AMI 的普通 TCP/IP 或安全的 SSL/TLS 连接,并发出初始 login 动作。

$factory->createClient('user:secret@localhost')->then(
    function (Client $client) {
        // client connected and authenticated
    },
    function (Exception $e) {
        // an error occured while trying to connect or authorize client
    }
);

注意:给定的 $amiUrl 必须 包含主机,它 应该 包含用户名和密码,它可以包含方案(tcp/ssl)和端口定义。

客户端

Client 负责与 Asterisk 管理接口交换消息,并跟踪挂起的动作。

如果您要发送外出动作,请参阅下面的 ActionSender 类。

on()

可以使用 on(string $eventName, callable $eventHandler): void 方法来注册新的事件处理器。传入的事件和错误将被转发到已注册的事件处理器回调中。

$client->on('event', function (Event $event) {
    // process an incoming AMI event (see below)
});
$client->on('close', function () {
    // the connection to the AMI just closed
});
$client->on('error', function (Exception $e) {
    // and error has just been detected, the connection will terminate...
});

close()

可以使用 close(): void 方法强制关闭 AMI 连接并拒绝所有挂起操作。

end()

可以使用 end(): void 方法在所有挂起操作完成后软关闭 AMI 连接。

高级

创建 Action 对象,通过 AMI 发送它们,并等待传入的 Response 对象通常隐藏在 ActionSender 接口中。

如果你需要自定义或不受支持的操作,你也可以手动进行。不过,考虑提交一个 PR 吧 :)

createAction()

可以使用 createAction(string $name, array $fields): Action 方法来构建自定义 AMI 操作。会自动添加一个唯一值到 "ActionID" 字段(用于匹配传入的响应)。

request()

可以使用 request(Action $action): PromiseInterface<Response> 方法将给定的消息排队通过 AMI 发送,并等待一个匹配其 "ActionID" 字段值的 Response 对象。

ActionSender

ActionSender 将一个给定的 Client 实例包装起来,提供一种简单的方式来执行常见操作。这个类代表执行操作和等待相应响应的主要接口。

$sender = new ActionSender($client);

动作

所有公共方法都与它们各自的 AMI 操作相对应。

$sender->ping()->then(function (Response $response) {
    // response received for ping action
});

在此处列出所有可用的操作超出了范围,请参阅 类概要

处理

发送操作是异步的(非阻塞的),因此你实际上可以并行发送多个操作请求。AMI 将对每个操作响应一个 Response 对象。顺序没有保证。发送操作使用基于 Promise 的接口,这使得在操作 fulfilled(即成功解决或因错误而拒绝)时做出反应变得容易。

$sender->ping()->then(
    function (Response $response) {
        // response received for ping action
    },
    function (Exception $e) {
        // an error occured while executing the action
        
        if ($e instanceof ErrorException) {
            // we received a valid error response (such as authorization error)
            $response = $e->getResponse();
        } else {
            // we did not receive a valid response (likely a transport issue)
        }
    }
});

自定义动作

虽然使用 ActionSender 不是强制性的,但它是执行常见操作的首选方式。

如果你需要新的或不受支持的操作,或额外的参数,你也可以手动进行。有关详细信息,请参阅上面的高级 Client 使用。非常感谢更新 ActionSender 的 PR :)

消息

MessageResponseActionEvent 值对象的抽象基类。它为这三种消息类型提供了一个通用接口。

每个 Message 由任意数量的字段组成,每个字段都有一个名称和一个或多个值。字段名称不区分大小写。值的解释是应用特定的。

getFieldValue()

可以使用 getFieldValue(string $key): ?string 方法来获取给定字段键的第一个值。如果没有找到值,则返回 null

getFieldValues()

可以使用 getFieldValues(string $key): string[] 方法来获取给定字段键的所有值的列表。如果没有找到值,则返回一个空的 array()

getFields()

可以使用 getFields(): array 方法来获取所有字段的数组。

getActionId()

可以使用 getActionId(): string 方法来获取此消息的唯一操作 ID。这是获取 "ActionID" 字段值的快捷方式。

响应

《Response》值对象表示从 AMI 收到的入站响应。它共享Message父类的所有属性。

getCommandOutput()

可以使用 getCommandOutput(): ?string 方法来获取 "command" Action 的输出结果。如果这个响应实际上是对 "command" 动作的响应,则此值可用;否则默认为 null

$sender->command('help')->then(function (Response $response) {
    echo $response->getCommandOutput();
});

动作

《Action》值对象表示要发送到 AMI 的出站动作消息。它共享Message父类的所有属性。

事件

《Event》值对象表示从 AMI 收到的入站事件。它共享Message父类的所有属性。

getName()

可以使用 getName(): ?string 方法来获取事件的名称。这是获取 "Event" 字段值的快捷方式。

安装

推荐通过 Composer 安装此库。 初次使用 Composer?

这将安装最新支持的版本

$ composer require clue/ami-react:^0.3

有关版本升级的详细信息,请参阅变更日志

测试

为了运行测试,您需要 PHPUnit

$ phpunit

测试套件包含单元测试和功能集成测试。功能测试需要访问正在运行的 Asterisk 服务器实例,并且默认会跳过。如果您还想运行功能测试,您需要提供类似以下的 您自己的 AMI 登录详情到环境变量中

$ LOGIN=username:password@localhost phpunit

许可

MIT