0
# CLI Tools and Utilities
1
2
Command-line interface tools for interactive Asterisk management, plus utility classes for event handling, data structures, and debugging support.
3
4
## Capabilities
5
6
### Command-Line Interface
7
8
#### CLI Functions
9
10
```python { .api }
11
def usage(argv0: str, out_file):
12
"""Print command-line program usage information."""
13
14
def show_actions(action: str = None):
15
"""
16
Show available Manager API actions and their arguments.
17
If action is specified, show detailed help for that action.
18
"""
19
20
def execute_action(manager: Manager, argv: list):
21
"""
22
Execute specified Manager API action with given arguments.
23
Supports both positional and named arguments (--name=value).
24
"""
25
26
def command_line(argv: list):
27
"""
28
Main command-line interface entry point.
29
Handles argument parsing and command dispatch.
30
"""
31
```
32
33
#### CLI Exception Classes
34
35
```python { .api }
36
class ArgumentsError(BaseException):
37
"""Raised for bad command-line arguments."""
38
```
39
40
### Utility Classes
41
42
#### AttributeDict
43
44
```python { .api }
45
class AttributeDict(dict):
46
"""
47
Dictionary subclass with special handling for multi-value fields.
48
Used for Manager API responses and events.
49
"""
50
51
MULTI_VALUE_FIELD: tuple = ('ChanVariable', 'DestChanVariable')
52
"""Fields that can have multiple occurrences in Manager responses."""
53
54
def __setitem__(key: str, value: str):
55
"""Set item with special handling for multi-value fields."""
56
```
57
58
#### EventCollection
59
60
```python { .api }
61
class EventCollection:
62
"""
63
Collection for managing Asterisk event subscriptions and dispatching.
64
Provides event filtering, subscription management, and callback handling.
65
"""
66
67
def __init__(initial: dict = None):
68
"""Initialize with optional initial event handlers."""
69
70
def subscribe(event_type: str, handler: callable):
71
"""Subscribe handler function to specific event type."""
72
73
def unsubscribe(event_type: str, handler: callable):
74
"""Unsubscribe handler from event type."""
75
76
def clear():
77
"""Remove all event subscriptions."""
78
79
def fire(name: str, *args, **kwargs):
80
"""Fire event with given name and arguments to all subscribed handlers."""
81
82
def copy() -> 'EventCollection':
83
"""Return a copy of this event collection."""
84
85
def __iadd__(collection: 'EventCollection') -> 'EventCollection':
86
"""Add events from another collection to this one."""
87
88
def __isub__(collection: 'EventCollection') -> 'EventCollection':
89
"""Remove events from another collection from this one."""
90
```
91
92
#### Unspecified
93
94
```python { .api }
95
class Unspecified:
96
"""
97
Represents an unspecified value that cannot be None.
98
Used where None may be a valid argument value.
99
"""
100
101
Unspecified: Unspecified
102
"""Singleton instance of Unspecified class."""
103
```
104
105
#### Utility Exceptions
106
107
```python { .api }
108
class SubscriptionError(BaseException):
109
"""
110
Raised when attempt to register the same (event, handler) tuple twice.
111
"""
112
```
113
114
### Debugging and Data Display
115
116
#### Debug Functions
117
118
```python { .api }
119
def dump_packet(packet: dict, file = sys.stdout):
120
"""
121
Dump packet data for debugging Manager API communication.
122
123
Args:
124
packet: Manager API packet/response dictionary
125
file: Output file object (default stdout)
126
"""
127
128
def dump_human(data: dict, file = sys.stdout, _indent: int = 0):
129
"""
130
Human-readable dump of structured data with indentation.
131
132
Args:
133
data: Data structure to dump
134
file: Output file object (default stdout)
135
_indent: Internal indentation level
136
"""
137
```
138
139
### Enhanced Logging
140
141
#### Custom Logger Classes
142
143
```python { .api }
144
class AsteriskLogger:
145
"""
146
Enhanced logger class with additional logging levels for Asterisk debugging.
147
"""
148
149
def state(msg: str, *args, **kwargs):
150
"""Log message with 'STATE' severity level."""
151
152
def packet(msg: str, *args, **kwargs):
153
"""Log message with 'PACKET' severity level."""
154
155
def io(msg: str, *args, **kwargs):
156
"""Log message with 'IO' severity level."""
157
158
class InstanceLogger:
159
"""
160
Provides instance-specific logging functionality.
161
"""
162
163
def getLogger() -> AsteriskLogger:
164
"""Get logger instance for the object."""
165
```
166
167
#### Custom Logging Levels
168
169
```python { .api }
170
logging.STATE: int
171
"""Custom logging level (INFO - 1) for state changes."""
172
173
logging.PACKET: int
174
"""Custom logging level (DEBUG - 1) for packet tracing."""
175
176
logging.IO: int
177
"""Custom logging level (PACKET - 1) for I/O operations."""
178
```
179
180
### Command-Line Utilities
181
182
#### Executable Scripts
183
184
```python { .api }
185
# asterisk-dump script
186
def main(argv: list):
187
"""Event dumping utility with auto-reconnect functionality."""
188
189
# asterisk-recover script
190
def main(argv: list):
191
"""Interactive channel recovery utility for troubleshooting."""
192
```
193
194
## Usage Examples
195
196
### Command-Line Usage
197
198
The `py-asterisk` command provides several operation modes:
199
200
```bash
201
# Show available actions
202
py-asterisk actions
203
204
# Execute specific action
205
py-asterisk action ShowChannels
206
207
# Execute action with arguments
208
py-asterisk action Originate SIP/1001 default 1002 1
209
210
# Execute action with named arguments
211
py-asterisk action Originate --channel=SIP/1001 --context=default --exten=1002
212
213
# Execute console command
214
py-asterisk command "core show channels"
215
216
# Show help for specific action
217
py-asterisk help Originate
218
```
219
220
### Event Monitoring Utilities
221
222
```bash
223
# Dump all Manager API events to console
224
asterisk-dump --host=127.0.0.1 --port=5038 --username=admin --secret=password
225
226
# Dump events with auto-reconnect
227
asterisk-dump --host=127.0.0.1 --port=5038 --username=admin --secret=password --reconnect
228
```
229
230
### Channel Recovery Tools
231
232
```bash
233
# Interactive channel recovery interface
234
asterisk-recover --host=127.0.0.1 --port=5038 --username=admin --secret=password
235
```
236
237
### Working with Events
238
239
```python
240
from Asterisk.Manager import Manager
241
from Asterisk.Util import EventCollection
242
243
manager = Manager(('127.0.0.1', 5038), 'admin', 'secret', listen_events=True)
244
245
# Event handler function
246
def handle_hangup(event):
247
print(f"Channel {event['Channel']} hung up")
248
print(f"Cause: {event.get('Cause', 'Unknown')}")
249
250
def handle_newchannel(event):
251
print(f"New channel: {event['Channel']}")
252
print(f"State: {event['ChannelState']}")
253
254
# Subscribe to events
255
manager.events.subscribe('Hangup', handle_hangup)
256
manager.events.subscribe('Newchannel', handle_newchannel)
257
258
# Events will be dispatched automatically while manager is connected
259
```
260
261
### Using Utility Classes
262
263
```python
264
from Asterisk.Util import AttributeDict, Unspecified
265
266
# AttributeDict handles multi-value fields specially
267
response = AttributeDict()
268
response['ChanVariable'] = 'var1=value1' # Creates nested dict
269
response['ChanVariable'] = 'var2=value2' # Adds to existing dict
270
271
# Unspecified for optional parameters
272
def my_function(required_param, optional_param=Unspecified):
273
if optional_param is not Unspecified:
274
# Parameter was provided
275
process_optional(optional_param)
276
```
277
278
### Debug Output
279
280
```python
281
from Asterisk.Util import dump_packet, dump_human
282
283
# Debug Manager API packets
284
response = manager.ShowChannels()
285
dump_packet(response)
286
287
# Human-readable data dump
288
dump_human({
289
'channels': 5,
290
'queues': {'support': {'calls': 2}, 'sales': {'calls': 0}}
291
})
292
```
293
294
### Enhanced Logging
295
296
```python
297
import logging
298
from Asterisk.Logging import AsteriskLogger
299
300
# The enhanced logger is automatically installed system-wide
301
logger = logging.getLogger('my_app')
302
303
# Use custom logging levels
304
logger.state("Manager connected and authenticated")
305
logger.packet("Sent action: ShowChannels")
306
logger.io("Reading response from socket")
307
308
# Standard levels still work
309
logger.info("Application started")
310
logger.error("Connection failed")
311
```