Asterisk AMI AJAM Parser php

Разбор сырых данных от Asterisk Manager Interface(AMI).
в примере команда AMI -> QueueStatus

Имеем на входе форматированную строку,
содержащую символы перевода каретки и новой строки.
Это и используем для разбора данных.
В итоге получим отдельный ассоциативный массив для каждой сущности (очередь и ее агенты)

Имеем на входе форматированную строку

Имеем на входе форматированную строку

Response: Success
EventList: start
Message: Queue status will follow

Event: QueueParams
Queue: 5050
Max: 0
Strategy: rrmemory
Calls: 0
Holdtime: 4
TalkTime: 56
Completed: 70
Abandoned: 7
ServiceLevel: 60
ServicelevelPerf: 98.6
Weight: 0

Event: QueueMember
Queue: 5050
Name: cc5001
Location: Local/5001@from-queue/n
StateInterface: hint:5001@ext-local
Membership: static
Penalty: 0
CallsTaken: 21
LastCall: 1535717186
LastPause: 1535714318
InCall: 0
Status: 1
Paused: 0
PausedReason: 

Event: QueueMember
Queue: 5050
Name: cc5005
Location: Local/5005@from-queue/n
StateInterface: hint:5005@ext-local
Membership: static
Penalty: 0
CallsTaken: 0
LastCall: 0
LastPause: 0
InCall: 0
Status: 5
Paused: 0
PausedReason: 

Event: QueueMember
Queue: 5050
Name: cc5002
Location: Local/5002@from-queue/n
StateInterface: hint:5002@ext-local
Membership: static
Penalty: 0
CallsTaken: 32
LastCall: 1535717176
LastPause: 1535711824
InCall: 0
Status: 1
Paused: 0
PausedReason: 

Event: QueueMember
Queue: 5050
Name: cc5003
Location: Local/5003@from-queue/n
StateInterface: hint:5003@ext-local
Membership: static
Penalty: 0
CallsTaken: 0
LastCall: 0
LastPause: 0
InCall: 0
Status: 5
Paused: 0
PausedReason: 

Event: QueueMember
Queue: 5050
Name: cc5000
Location: Local/5000@from-queue/n
StateInterface: hint:5000@ext-local
Membership: static
Penalty: 0
CallsTaken: 17
LastCall: 1535717120
LastPause: 1535710559
InCall: 0
Status: 1
Paused: 0
PausedReason: 

Event: QueueMember
Queue: 5050
Name: cc5004
Location: Local/5004@from-queue/n
StateInterface: hint:5004@ext-local
Membership: static
Penalty: 0
CallsTaken: 0
LastCall: 0
LastPause: 0
InCall: 0
Status: 5
Paused: 0
PausedReason: 

Event: QueueStatusComplete
EventList: Complete
ListItems: 7
 

PHP

Предположим, что raw данные в переменной result.
Подорвем (explode) через \r\n и получим единый массив:

Нажмите, чтобы отобразить

Нажмите, чтобы скрыть

Array
(
    [0] => Response: Success
    [1] => EventList: start
    [2] => Message: Queue status will follow
    [3] => 
    [4] => Event: QueueParams
    [5] => Queue: 5050
    [6] => Max: 0
    [7] => Strategy: rrmemory
    [8] => Calls: 0
    [9] => Holdtime: 6
    [10] => TalkTime: 65
    [11] => Completed: 66
    [12] => Abandoned: 7
    [13] => ServiceLevel: 60
    [14] => ServicelevelPerf: 98.5
    [15] => Weight: 0
    [16] => 
    [17] => Event: QueueMember
    [18] => Queue: 5050
    [19] => Name: cc5001
    [20] => Location: Local/5001@from-queue/n
    [21] => StateInterface: hint:5001@ext-local
    [22] => Membership: static
    [23] => Penalty: 0
    [24] => CallsTaken: 20
    [25] => LastCall: 1535713711
    [26] => LastPause: 1535714318
    [27] => InCall: 0
    [28] => Status: 1
    [29] => Paused: 1
    [30] => PausedReason: 
    [31] => 
    [32] => Event: QueueMember
    [33] => Queue: 5050
    [34] => Name: cc5005
    [35] => Location: Local/5005@from-queue/n
    [36] => StateInterface: hint:5005@ext-local
    [37] => Membership: static
    [38] => Penalty: 0
    [39] => CallsTaken: 0
    [40] => LastCall: 0
    [41] => LastPause: 0
    [42] => InCall: 0
    [43] => Status: 5
    [44] => Paused: 0
    [45] => PausedReason: 
    [46] => 
    [47] => Event: QueueMember
    [48] => Queue: 5050
    [49] => Name: cc5002
    [50] => Location: Local/5002@from-queue/n
    [51] => StateInterface: hint:5002@ext-local
    [52] => Membership: static
    [53] => Penalty: 0
    [54] => CallsTaken: 30
    [55] => LastCall: 1535717034
    [56] => LastPause: 1535711824
    [57] => InCall: 0
    [58] => Status: 1
    [59] => Paused: 0
    [60] => PausedReason: 
    [61] => 
    [62] => Event: QueueMember
    [63] => Queue: 5050
    [64] => Name: cc5003
    [65] => Location: Local/5003@from-queue/n
    [66] => StateInterface: hint:5003@ext-local
    [67] => Membership: static
    [68] => Penalty: 0
    [69] => CallsTaken: 0
    [70] => LastCall: 0
    [71] => LastPause: 0
    [72] => InCall: 0
    [73] => Status: 5
    [74] => Paused: 0
    [75] => PausedReason: 
    [76] => 
    [77] => Event: QueueMember
    [78] => Queue: 5050
    [79] => Name: cc5000
    [80] => Location: Local/5000@from-queue/n
    [81] => StateInterface: hint:5000@ext-local
    [82] => Membership: static
    [83] => Penalty: 0
    [84] => CallsTaken: 16
    [85] => LastCall: 1535716246
    [86] => LastPause: 1535710559
    [87] => InCall: 1
    [88] => Status: 2
    [89] => Paused: 0
    [90] => PausedReason: 
    [91] => 
    [92] => Event: QueueMember
    [93] => Queue: 5050
    [94] => Name: cc5004
    [95] => Location: Local/5004@from-queue/n
    [96] => StateInterface: hint:5004@ext-local
    [97] => Membership: static
    [98] => Penalty: 0
    [99] => CallsTaken: 0
    [100] => LastCall: 0
    [101] => LastPause: 0
    [102] => InCall: 0
    [103] => Status: 5
    [104] => Paused: 0
    [105] => PausedReason: 
    [106] => 
    [107] => Event: QueueStatusComplete
    [108] => EventList: Complete
    [109] => ListItems: 7
    [110] => 
    [111] => 
)

Ключи с пустыми значениями, это границы между сущностями. Они нам пригодятся.


При помощи implode сольем все опять в одну строку:

   Event: QueueParams,Queue: 5050,Max: 0,Strategy: rrmemory,Calls: 0,Holdtime: 4,TalkTime: 47,Completed: 73,Abandoned: 7,ServiceLevel: 60,ServicelevelPerf: 98.6,Weight: 0,,Event:....

Пустые ключи превратились в ,,, воспользуемся этим.

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

Нажмите, чтобы отобразить

Нажмите, чтобы скрыть

Array
(
    [0] => Event: QueueParams,Queue: 5050,Max: 0,Strategy: rrmemory,Calls: 0,Holdtime: 3,TalkTime: 51,Completed: 75,Abandoned: 7,ServiceLevel: 60,ServicelevelPerf: 98.7,Weight: 0
    [1] => Event: QueueMember,Queue: 5050,Name: cc5001,Location: Local/5001@from-queue/n,StateInterface: hint:5001@ext-local,Membership: static,Penalty: 0,CallsTaken: 24,LastCall: 1535718521,LastPause: 1535714318,InCall: 0,Status: 1,Paused: 0,PausedReason: 
    [2] => Event: QueueMember,Queue: 5050,Name: cc5005,Location: Local/5005@from-queue/n,StateInterface: hint:5005@ext-local,Membership: static,Penalty: 0,CallsTaken: 0,LastCall: 0,LastPause: 0,InCall: 0,Status: 5,Paused: 0,PausedReason: 
    [3] => Event: QueueMember,Queue: 5050,Name: cc5002,Location: Local/5002@from-queue/n,StateInterface: hint:5002@ext-local,Membership: static,Penalty: 0,CallsTaken: 34,LastCall: 1535718475,LastPause: 1535711824,InCall: 0,Status: 1,Paused: 0,PausedReason: 
    [4] => Event: QueueMember,Queue: 5050,Name: cc5003,Location: Local/5003@from-queue/n,StateInterface: hint:5003@ext-local,Membership: static,Penalty: 0,CallsTaken: 0,LastCall: 0,LastPause: 0,InCall: 0,Status: 5,Paused: 0,PausedReason: 
    [5] => Event: QueueMember,Queue: 5050,Name: cc5000,Location: Local/5000@from-queue/n,StateInterface: hint:5000@ext-local,Membership: static,Penalty: 0,CallsTaken: 17,LastCall: 1535717120,LastPause: 1535710559,InCall: 0,Status: 1,Paused: 0,PausedReason: 
    [6] => Event: QueueMember,Queue: 5050,Name: cc5004,Location: Local/5004@from-queue/n,StateInterface: hint:5004@ext-local,Membership: static,Penalty: 0,CallsTaken: 0,LastCall: 0,LastPause: 0,InCall: 0,Status: 5
)

Далее разберем каждое значение на отдельные массивы, при помощи foreach.

Полный код:

<?php
        $result = explode("\r\n", $result);
                end($result);
                $count1 =  key($result);
        $result = array_slice($result, 3, $count1);
        $result = array_slice($result, 0, $count1 - 8);
        array_shift($result);
 
        $result = implode(',',$result);
        $result = explode(',,',$result);
                end($result);
                $count2 =  key($result);
        for($i = 0; $i <= $count2; ++$i){
        $item = explode(',',$result[$i]);
        foreach($item as &$val) {
                list($k, $v) = array_pad(explode(': ', $val, 2), 2, null);
                $parse[$i][$k] = $v;
             }
        }

В итоге имеем разобранные на ассоциативные массивы сущности:

        echo "<pre>";
        print_r($parse);
        echo "</pre>";

массивы items

массивы items

Array
(
    [0] => Array
        (
            [Event] => QueueParams
            [Queue] => 5050
            [Max] => 0
            [Strategy] => rrmemory
            [Calls] => 0
            [Holdtime] => 3
            [TalkTime] => 41
            [Completed] => 63
            [Abandoned] => 6
            [ServiceLevel] => 60
            [ServicelevelPerf] => 98.4
            [Weight] => 0
        )
 
    [1] => Array
        (
            [Event] => QueueMember
            [Queue] => 5050
            [Name] => cc5001
            [Location] => Local/5001@from-queue/n
            [StateInterface] => hint:5001@ext-local
            [Membership] => static
            [Penalty] => 0
            [CallsTaken] => 20
            [LastCall] => 1535713711
            [LastPause] => 1535714318
            [InCall] => 0
            [Status] => 1
            [Paused] => 1
            [PausedReason] => 
        )
 
    [2] => Array
        (
            [Event] => QueueMember
            [Queue] => 5050
            [Name] => cc5005
            [Location] => Local/5005@from-queue/n
            [StateInterface] => hint:5005@ext-local
            [Membership] => static
            [Penalty] => 0
            [CallsTaken] => 0
            [LastCall] => 0
            [LastPause] => 0
            [InCall] => 0
            [Status] => 5
            [Paused] => 0
            [PausedReason] => 
        )
 
    [3] => Array
        (
            [Event] => QueueMember
            [Queue] => 5050
            [Name] => cc5002
            [Location] => Local/5002@from-queue/n
            [StateInterface] => hint:5002@ext-local
            [Membership] => static
            [Penalty] => 0
            [CallsTaken] => 27
            [LastCall] => 1535716491
            [LastPause] => 1535711824
            [InCall] => 0
            [Status] => 1
            [Paused] => 0
            [PausedReason] => 
        )
 
    [4] => Array
        (
            [Event] => QueueMember
            [Queue] => 5050
            [Name] => cc5003
            [Location] => Local/5003@from-queue/n
            [StateInterface] => hint:5003@ext-local
            [Membership] => static
            [Penalty] => 0
            [CallsTaken] => 0
            [LastCall] => 0
            [LastPause] => 0
            [InCall] => 0
            [Status] => 5
            [Paused] => 0
            [PausedReason] => 
        )
 
    [5] => Array
        (
            [Event] => QueueMember
            [Queue] => 5050
            [Name] => cc5000
            [Location] => Local/5000@from-queue/n
            [StateInterface] => hint:5000@ext-local
            [Membership] => static
            [Penalty] => 0
            [CallsTaken] => 16
            [LastCall] => 1535716246
            [LastPause] => 1535710559
            [InCall] => 0
            [Status] => 1
            [Paused] => 0
            [PausedReason] => 
        )
 
    [6] => Array
        (
            [Event] => QueueMember
            [Queue] => 5050
            [Name] => cc5004
            [Location] => Local/5004@from-queue/n
            [StateInterface] => hint:5004@ext-local
            [Membership] => static
            [Penalty] => 0
            [CallsTaken] => 0
            [LastCall] => 0
            [LastPause] => 0
            [InCall] => 0
            [Status] => 5
        )
 
)

В таком виде уже нормально использовать. Например скормить шаблонизатору в JSON:

JSON

JSON

[{"Event":"QueueParams","Queue":"5050","Max":"0","Strategy":"rrmemory","Calls":"0","Holdtime":"2","TalkTime":"40","Completed":"77","Abandoned":"7","ServiceLevel":"60","ServicelevelPerf":"98.7","Weight":"0"},
{"Event":"QueueMember","Queue":"5050","Name":"cc5001","Location":"Local\/5001@from-queue\/n","StateInterface":"hint:5001@ext-local","Membership":"static","Penalty":"0","CallsTaken":"25","LastCall":"1535718995","LastPause":"1535714318","InCall":"0","Status":"1","Paused":"0","PausedReason":""},
{"Event":"QueueMember","Queue":"5050","Name":"cc5005","Location":"Local\/5005@from-queue\/n","StateInterface":"hint:5005@ext-local","Membership":"static","Penalty":"0","CallsTaken":"0","LastCall":"0","LastPause":"0","InCall":"0","Status":"5","Paused":"0","PausedReason":""},
{"Event":"QueueMember","Queue":"5050","Name":"cc5002","Location":"Local\/5002@from-queue\/n","StateInterface":"hint:5002@ext-local","Membership":"static","Penalty":"0","CallsTaken":"35","LastCall":"1535718811","LastPause":"1535718878","InCall":"0","Status":"1","Paused":"1","PausedReason":""},
{"Event":"QueueMember","Queue":"5050","Name":"cc5003","Location":"Local\/5003@from-queue\/n","StateInterface":"hint:5003@ext-local","Membership":"static","Penalty":"0","CallsTaken":"0","LastCall":"0","LastPause":"0","InCall":"0","Status":"5","Paused":"0","PausedReason":""},
{"Event":"QueueMember","Queue":"5050","Name":"cc5000","Location":"Local\/5000@from-queue\/n","StateInterface":"hint:5000@ext-local","Membership":"static","Penalty":"0","CallsTaken":"17","LastCall":"1535717120","LastPause":"1535710559","InCall":"0","Status":"1","Paused":"0","PausedReason":""},
{"Event":"QueueMember","Queue":"5050","Name":"cc5004","Location":"Local\/5004@from-queue\/n","StateInterface":"hint:5004@ext-local","Membership":"static","Penalty":"0","CallsTaken":"0","LastCall":"0","LastPause":"0","InCall":"0","Status":"5"}]

Queue Status

Только авторизованные участники могут оставлять комментарии.
  • blog/asterisk_ajam_queuestatus.txt
  • Последние изменения: 2018/10/21