Class: AGI

Inherits:
Object
  • Object
show all
Defined in:
lib/AGI.rb

Overview

AGI is the Asterisk Gateway Interface, an interface for adding functionality to asterisk. This class implements an object that knows the AGI language and can therefore serve as a bridge between ruby and Asterisk. It can interact with any IO object it’s given, so can be used in a sockets based FastAGI or a simple STDIN/STDOUT based Fork-Exec’d AGI. Please see The Voip Info Asterisk AGI site for more details.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(params = {}) ⇒ AGI

Please note, everything else provided in the hash is available in the resulting object’s init_params accessor.



59
60
61
62
63
64
65
66
67
# File 'lib/AGI.rb', line 59

def initialize(params={})
  @input = params[:input]   || STDIN
  @output = params[:output] || STDOUT
  @logger = params[:logger] || Logger.new(STDERR)
  @init_params = params # To store other options for user
  @channel_params = {}
  @last_response  = nil
  @initialized = false
end

Instance Attribute Details

#channel_paramsObject (readonly)

Channel Parameters, populated by init



50
51
52
# File 'lib/AGI.rb', line 50

def channel_params
  @channel_params
end

#init_paramsObject (readonly)

Additional AGI parameters provided to new



52
53
54
# File 'lib/AGI.rb', line 52

def init_params
  @init_params
end

Instance Method Details

#answerObject

Causes Asterisk to answer the channel.

Returns an AGIResponse object.



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/AGI.rb', line 72

def answer
  response = AGIResponse.new
  command_str = "ANSWER"
  begin      
    response.native = execute(command_str)
  rescue AGITimeoutError, AGICommandError, AGIHangupError
    raise
  end
  if response.native == -1 then
    raise AGIChannelError.new(@last_response, "Channel Failure in (#{command_str})")
  elsif response.native == 0
    response.success = true
  end
  return response
end

#background(audio, digits = '') ⇒ Object

Signals Asterisk to stream the given audio file(s) to the channel. If digits are provided, allows the user to terminate the audio transmission by supplying DTMF. This differs from stream file because it does not accept an offset, and accepts an Array of sound files to play. It actually uses multiple calls to stream_file to accomplish this task.

Please see stream_file for Returns, as this is a wrapper for that method



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/AGI.rb', line 92

def background(audio, digits='')
  result = nil
  if audio.class == Array then
    audio.each do |file|
      begin
        result = stream_file(file, digits)
      rescue AGITimeoutError, AGICommandError, AGIHangupError, AGIChannelError
        raise
      end          
      return result unless result.success?
      return result if result.data
    end
    return result
  elsif audio.class == String then
    begin
      result = stream_file(audio, digits)
    rescue AGITimeoutError, AGICommandError, AGIHangupError, AGIChannelError
      raise
    end
  end
end

#background_digits(digit_string, digits = '', path = 'digits') ⇒ Object Also known as: background_say_digits

Is a combination of asterisks background functionality and say_digits. It says the designated digit_string. If digits are provided, allows the user to terminate the audio transmission by supplying DTMF. Allows an optional directory which contains digit-audio. (1.gsm, 2.gsm, …)

Please see background for returns, as this is a wrapper for that method



117
118
119
120
121
122
123
124
125
126
# File 'lib/AGI.rb', line 117

def background_digits(digit_string, digits='', path='digits')
  audio = []
  digit_string.to_s.scan(/./m) { |digit| audio << "#{path}/#{digit}" }
  begin
    response = background(audio, digits)
  rescue Exception
    raise
  end
  return response
end

#channel_status(channel = nil) ⇒ Object

Queries Asterisk for the status of the named channel. If no channel is named, defaults to the current channel.

Returns an AGIResponse object with data signifying the status of the channel:

  • 0, ‘DOWN, UNAVAILABLE’, Channel is down and available

  • 1, ‘DOWN, RESERVED’, Channel is down, but reserved

  • 2, ‘OFF HOOK’, Channel is off hook

  • 3, ‘DIGITS DIALED’, Digits (or equivalent) have been dialed

  • 4, ‘LINE RINGING’, Line is ringing

  • 5, ‘REMOTE RINGING’, Remote end is ringing

  • 6, ‘UP’, Line is up

  • 7, ‘BUSY’, Line is busy



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/AGI.rb', line 140

def channel_status(channel=nil)
  response = AGIResponse.new
  if channel.nil? then
    command_str = "CHANNEL STATUS"
  else
    command_str = "CHANNEL STATUS #{channel}"
  end
  begin      
    response.native = execute(command_str)
  rescue AGITimeoutError, AGICommandError, AGIHangupError
    raise
  end
  if response.native == -1 then
    raise AGIChannelError.new(@last_response, "Channel Failure in (#{command_str})")
  else
    response.success = true
  end
  if response.native == 0 then
    response.data = "DOWN, AVAILABLE"
  elsif response.native == 1 then
    response.data = "DOWN, RESERVED"
  elsif response.native == 2 then
    response.data = "OFF HOOK"
  elsif response.native == 3 then
    response.data = "DIGITS DIALED"
  elsif response.native == 4 then
    response.data = "LINE RINGING"
  elsif response.native == 5 then
    response.data = "REMOTE RINGING"
  elsif response.native == 6 then
    response.data = "UP"
  elsif response.native == 7 then
    response.data = "BUSY"
  end
  return response
end

#control_stream_file(file, digits = '""', skipms = 3000, ffchar = '*', rewchar = '#', pausechar = nil) ⇒ Object

Signals Asterisk to stream the given audio file to the channel starting at an optional offset until either the entire file has been streamed or the user provides one of a set of DTMF digits. Unlike stream_file, this allows the user on the channel to control playback using a fast-forward key, a rewind key, and a pause key.

Returns an AGIResponse including the DTMF digit provided by the channel.



180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/AGI.rb', line 180

def control_stream_file(file, digits='""', skipms=3000, ffchar='*', rewchar='#', pausechar=nil)
  response = AGIResponse.new
  if pausechar.nil?
    command_str = "CONTROL STREAM FILE file digits skipms ffchar rewchar"
  else
    command_str = "CONTROL STREAM FILE file digits skipms ffchar rewchar pausechar"  
  end
  begin
    response.native = execute(command_str)
  rescue AGITimeoutError, AGICommandError, AGIHangupError
    raise
  end
  if response.native == -1 then
    raise AGIChannelError.new(@last_response, "Channel Failure in (#{command_str})")
  elsif response.native == 0
    response.success = true
  else
    response.success = true
    response.data = response.native.chr
  end
  return response
end

#database_del(family, key) ⇒ Object

Signals Asterisk to delete the appropriate ASTDB database key/value.

Returns an AGIResponse object



206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/AGI.rb', line 206

def database_del(family, key)
  response = AGIResponse.new
  command_str = "DATABASE DEL #{family} #{key}"
  begin
    response.native = execute(command_str)
  rescue AGITimeoutError, AGICommandError, AGIHangupError
    raise
  end
  if response.native == -1 then
    raise AGIChannelError.new(@last_response, "Channel Failure in (#{command_str})")
  elsif response.native == 1 then
    response.success = true
  end
  return response
end

#database_deltree(family, keytree = nil) ⇒ Object

Signals Asterisk to delete the appropriate ASTDB database key/value family.

Returns an AGIResponse object



225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/AGI.rb', line 225

def database_deltree(family, keytree=nil)
  response = AGIResponse.new
  if keytree.nil? then
    command_str = "DATABASE DELTREE #{family}"
  else
    command_str = "DATABASE DELTREE #{family} #{keytree}"
  end
  begin
    response.native = execute(command_str)
  rescue AGITimeoutError, AGICommandError, AGIHangupError
    raise
  end
  if response.native == -1 then
    raise AGIChannelError.new(@last_response, "Channel Failure in (#{command_str})")
  elsif response.native == 1 then
    response.success = true
  end
  return response
end

#database_get(family, key) ⇒ Object

Signals Asterisk to return the appropriate ASTDB database key’s value

Returns an AGIResponse object with data including the value of the requested database key



248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
# File 'lib/AGI.rb', line 248

def database_get(family, key)
  response = AGIResponse.new
  command_str = "DATABASE GET #{family} #{key}"
  begin
    response.native = execute(command_str)
  rescue AGITimeoutError, AGICommandError, AGIHangupError
    raise
  end
  if response.native == -1 then
    raise AGIChannelError.new(@last_response, "Channel Failure in (#{command_str})")
  elsif response.native == 1 then
    response.success = true
    response.data = parse_response
  end
  return response
end

#database_put(family, key, value) ⇒ Object

Signals Asterisk to insert the given value into the ASTDB database

Returns an AGIResponse



268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
# File 'lib/AGI.rb', line 268

def database_put(family, key, value)
  response = AGIResponse.new
  command_str = "DATABASE PUT #{family} #{key} #{value}"
  begin
    response.native = execute(command_str)
  rescue AGITimeoutError, AGICommandError, AGIHangupError
    raise
  end    
  if response.native == -1 then
    raise AGIChannelError.new(@last_response, "Channel Failure in (#{command_str})")
  elsif response.native == 1 then
    response.success = true
  end
  return response
end

#exec(string) ⇒ Object

Signals Asterisk to execute the given Asterisk Application by sending the command “EXEC” to Asterisk using the AGI

Returns an AGIResponse.

Please note, the success? method to this AGIResponse indicates success of the EXEC command, not the underlying Asterisk Application. If Asterisk provides data in it’s standard format, it will be included as data in the AGIResponse object. If it does not, the native asterisk response will be.



289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
# File 'lib/AGI.rb', line 289

def exec(string)
  response = AGIResponse.new
  command_str = "EXEC #{string}"
  begin
    response.native = execute(command_str)
  rescue AGITimeoutError, AGICommandError, AGIHangupError
    raise
  end
  if response.native == -2 then
    raise AGICommandError.new(@last_response, "Application Not Found in (#{command_str})")
  elsif response.native == -1 then
    raise AGIChannelError.new(@last_response, "Channel Failure in (#{command_str})")
  else
    response.success = true
    response.data = parse_response
    response.data ||= response.native
  end
  return response
end

#get_data(file, timeout = nil, max_digits = nil) ⇒ Object

Signals Asterisk to collect DTMF digits from the channel while playing an audio file. Optionally accepts a timeout option (in seconds) and a maximum number of digits to collect.

Returns an AGIResponse with data available which denotes the DTMF digits provided by the channel.



312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
# File 'lib/AGI.rb', line 312

def get_data(file, timeout=nil, max_digits=nil)
  response = AGIResponse.new
  if timeout.nil? then
    command_str = "GET DATA #{file}"
  elsif max_digits.nil? then
    command_str = "GET DATA #{file} #{(timeout.to_i * 1000)}"
  else
    command_str = "GET DATA #{file} #{(timeout.to_i * 1000)} #{max_digits}"
  end
  begin      
    response.native = execute(command_str)
  rescue AGITimeoutError, AGICommandError, AGIHangupError
    raise
  end
  if response.native == -1 then
    raise AGIChannelError.new(@last_response,"Channel Failure in #{command_str}")
  else
    response.success = true
    response.data = response.native
  end
  return response
end

#get_full_variable(variablename, channel = nil) ⇒ Object

Signals Asterisk to return the contents of the requested (complex) channel variable

Returns an AGIResponse with the variable’s value



338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
# File 'lib/AGI.rb', line 338

def get_full_variable(variablename, channel=nil)
  response = AGIResponse.new
  if channel.nil?
    command_str = "GET FULL VARIABLE #{variablename}"
  else
    command_str = "GET FULL VARIABLE #{variablename} #{channel}"
  end
  begin
    response.native = execute(command_str)
  rescue AGITimeoutError, AGICommandError, AGIHangupError
    raise
  end
  if response.native == -1 then
    raise AGIChannelError.new(@last_response, "Channel Failure in (#{command_str})")
  elsif response.native == 1
    response.success = true
    response.data = parse_response
  end
  return response
end

#get_option(file, digits = '""', timeout = 0) ⇒ Object

Signals Asterisk to stream the given audio file to the channel starting at an optional offset until either the entire file has been streamed or the user provides one of a set of DTMF digits. Unlike stream_file, this accepts a timeout option.

Returns an AGIResponse including the DTMF digit provided by the channel.



362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
# File 'lib/AGI.rb', line 362

def get_option(file, digits='""', timeout=0)
  response = AGIResponse.new
  command_str = "GET OPTION #{file} #{digits} #{(timeout.to_i * 1000)}"
  begin
    response.native = execute(command_str)
  rescue AGITimeoutError, AGICommandError, AGIHangupError
    raise
  end
  if response.native == -1 then
    raise AGIChannelError.new(@last_response, "Channel Failure in (#{command_str})")
  elsif response.native == 0
    response.success = true
  else
    response.success = true
    response.data = response.native.chr
  end
  return response
end

#get_variable(variablename) ⇒ Object

Signals Asterisk to return the contents of the requested channel variable

Returns an AGIResponse with the variable’s value



385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
# File 'lib/AGI.rb', line 385

def get_variable(variablename)
  response = AGIResponse.new
  command_str = "GET VARIABLE #{variablename}"
  begin
    response.native = execute(command_str)
  rescue AGITimeoutError, AGICommandError, AGIHangupError
    raise
  end
  if response.native == -1 then
    raise AGIChannelError.new(@last_response, "Channel Failure in (#{command_str})")
  elsif response.native == 1
    response.success = true
    response.data = parse_response
  end
  return response
end

#hangup(channel = nil) ⇒ Object

Signals Asterisk to hangup the requested channel. If no channel is provided, defaults to the current channel.

Returns an AGIResponse.



405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
# File 'lib/AGI.rb', line 405

def hangup(channel=nil)
  response = AGIResponse.new
  if channel.nil? then
    command_str = "HANGUP"
  else
    command_str = "HANGUP #{channel}"
  end
  begin
    response.native = execute(command_str)
  rescue AGITimeoutError, AGICommandError, AGIHangupError
    raise
  end
  if response.native == -1 then
    raise AGIChannelError.new(@last_response, "Channel Failure in (#{command_str})")
  elsif response.native == 1
    response.success = true
  end
  return response
end

#initObject

Initializes the channel by getting all variables provided by Asterisk as it initiates the connection. These values are then stored in the instance variable @channel_params, a Hash object. While initializing the channel, the IO object(s) provided to new as :input and :output are set to operate synchronously.

Note, a channel can only be initialized once. If the AGI is being initialized a second time, this will throw an AGIInitializeError. If this is desired functionality, please see the reinit method.



428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
# File 'lib/AGI.rb', line 428

def init
  if @initialized
    raise AGIInitializeError.new(nil, "Tried to init previously initialized channel. If this is desired, use reinit()")      
  end
  begin
    @input.sync = true
    @output.sync = true
    while( line = @input.gets.chomp )
      if line =~ %r{^\s*$} then
        break
      elsif line =~ %r{^agi_(\w+)\:\s+(.+)$} then
        if @channel_params.has_key?($1) then
          @logger.warn{"AGI Got Duplicate Channel Parameter for #{$1} (was \"#{@channel_params[$1]}\" reset to \"#{$2})\""}
        end
        @channel_params[$1] = $2          
        @logger.debug{"AGI Got Channel Parameter #{$1} = #{$2}"}
      end
    end
  rescue NoMethodError => error
    if error.to_s =~ %r{chomp} then
      raise AGIHangupError.new(nil, "Channel Hungup during init")
    else
      raise
    end
  end
  @initialized = true
end

#noop(string = nil) ⇒ Object

Signals Asterisk to … do nothing

Returns an AGIResponse. (just in case you want to make sure asterisk successfully didnt do anything. Don’t ask me, I just implement them)



459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
# File 'lib/AGI.rb', line 459

def noop(string=nil)
  response = AGIResponse.new
  if string.nil? then
    command_str = "NOOP"
  else
    command_str = "NOOP #{string}"
  end
  begin
    response.native = execute(command_str)
  rescue AGITimeoutError, AGICommandError, AGIHangupError
    raise
  end
  if response.native == -1 then
    raise AGIChannelError.new(@last_response, "Channel Failure in (#{command_str})")
  else
    response.success = true
  end
  return response
end

#receive_char(timeout = 0) ⇒ Object

Signals Asterisk to query the channel to request a single text character from the channel

Returns an AGIResponse including the character received.



482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
# File 'lib/AGI.rb', line 482

def receive_char(timeout=0)
  response = AGIResponse.new
  command_str = "RECEIVE CHAR #{(timeout.to_i * 1000)}"
  begin
    response.native = execute(command_str)
  rescue AGITimeoutError, AGICommandError, AGIHangupError
    raise
  end
  if response.native == -1 then
    raise AGIChannelError.new(@last_response, "Channel Failure in (#{command_str})")
  elsif response.native == 0
    raise AGICommandError.new(@last_response, "Channel doesn't support TEXT in (#{command_str})")
  else
    response.success = true
    response.data = response.native.chr
  end
  return response
end

#record_file(filename, format, digits, timeout = -1,, beep = false, silence = nil) ⇒ Object

Signals Asterisk to query the channel to provide audio data to record into a file. Asterisk will record until certain digits are provided as DTMF, or the operation times out, or silence is detected for a second timeout. Can optionally cause asterisk to send a beep to the channel to signal the user the intention of recording sound. By default, there is no timeout,no silence detection, and no beep.

Returns an AGIResponse.



504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
# File 'lib/AGI.rb', line 504

def record_file(filename, format, digits, timeout=-1, beep=false, silence=nil)
  beep_str = ''
  if ( beep == true ) then
    beep_str = "BEEP"
  end
  silence_str = ''
  unless silence.nil?
    silence_str = "s=#{silence}"
  end
  response = AGIResponse.new
  command_str = "RECORD FILE #{filename} #{format} #{digits} #{(timeout.to_i * 1000)} #{beep_str} #{silence_str}"
  begin
    response.native = execute(command_str)
  rescue AGITimeoutError, AGICommandError, AGIHangupError
    raise
  end
  if response.native == -1 then
    raise AGIChannelError.new(@last_response, "Channel Failure in (#{command_str})")
  elsif response.native > 0
    response.success = true
    response.data = response.native.chr
  else
    response.success = true
  end
  return response
end

#reinitObject

Initializes the channel by getting all variables provided by Asterisk as it initiates the connection. These values are then stored in the instance variable @channel_params, a Hash object. While initializing the channel, the IO object(s) provided to new as :input and :output are set to operate synchronously.

Note, unlike the init method, this can be called on an AGI object multiple times. Realize, however, that each time you do, the channel will have to provide a set of initialization data, and all previously stored channel parameters will be forgotten.



535
536
537
538
539
540
# File 'lib/AGI.rb', line 535

def reinit
  @initialized = false
  @channel_params = {}
  @last_response  = nil
  init    
end

#say_alpha(string, digits = '""') ⇒ Object

Signals Asterisk to announce the string provided as a series of characters If digits are provided as well, will allow the user to terminate the announcement if one of the digits are provided by DTMF.

Returns an AGIResponse including the DTMF digit provided by the channel.



545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
# File 'lib/AGI.rb', line 545

def say_alpha(string, digits='""')
  response = AGIResponse.new
  command_str = "SAY ALPHA '#{string}' #{digits}"
  begin
    response.native = execute(command_str)
  rescue AGITimeoutError, AGICommandError, AGIHangupError
    raise
  end
  if response.native == -1 then
    raise AGIChannelError.new(@last_response, "Channel Failure in (#{command_str})")
  elsif response.native == 0
    response.success = true
  else
    response.success = true
    response.data = response.native.chr
  end
  return response
end

#say_date(time = Time.now, digits = '""') ⇒ Object

Signals Asterisk to announce the given date. If digits are provided as well, will allow the user to terminate the announcement if one of the digits are provided by DTMF. Can accept either a Time object or an integer designation of the number of seconds since 00:00:00 January 1, 1970, Coordinated Universal Time (UTC). Defaults to now.

Returns an AGIResponse including the DTMF digit provided by the channel, if any are.



567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
# File 'lib/AGI.rb', line 567

def say_date(time=Time.now, digits='""')
  response = AGIResponse.new
  command_str = "SAY DATE #{time.to_i} #{digits}"
  begin
    response.native = execute(command_str)
  rescue AGITimeoutError, AGICommandError, AGIHangupError
    raise
  end
  if response.native == -1 then
    raise AGIChannelError.new(@last_response, "Channel Failure in (#{command_str})")
  elsif response.native == 0
    response.success = true
  else
    response.success = true
    response.data = response.native.chr
  end
  return response
end

#say_datetime(time = Time.now, digits = '""', format = "ABdY", timezone = nil) ⇒ Object

Signals Asterisk to announce the given date and time. If digits are provided as well, will allow the user to terminate the announcement if one of the digits are provided by DTMF. Can accept either a Time object or an integer designation of the number of seconds since 00:00:00 January 1, 1970, Coordinated Universal Time (UTC). Defaults to now.

Returns an AGIResponse including the DTMF digit provided by the channel, if any are.



589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
# File 'lib/AGI.rb', line 589

def say_datetime(time=Time.now, digits='""', format="ABdY", timezone=nil)
  response = AGIResponse.new
  if timezone.nil?
    command_str = "SAY DATETIME #{time.to_i} #{digits} #{format}"
  else
    command_str = "SAY DATETIME #{time.to_i} #{digits} #{format} #{timezone}"
  end
  begin
    response.native = execute(command_str)
  rescue AGITimeoutError, AGICommandError, AGIHangupError
    raise
  end
  if response.native == -1 then
    raise AGIChannelError.new(@last_response, "Channel Failure in (#{command_str})")
  elsif response.native == 0
    response.success = true
  else
    response.success = true
    response.data = response.native.chr
  end
  return response
end

#say_digits(number, digits = '""') ⇒ Object

Signals Asterisk to announce the number provided as a series of digits. If digits are provided as well, will allow the user to terminate the announcement if one of the digits are provided by DTMF.

Returns an AGIResponse including the DTMF digit provided by the channel.



615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
# File 'lib/AGI.rb', line 615

def say_digits(number, digits='""')
  response = AGIResponse.new
  command_str = "SAY DIGITS #{number} #{digits}"
  begin
    response.native = execute(command_str)
  rescue AGITimeoutError, AGICommandError, AGIHangupError
    raise
  end
  if response.native == -1 then
    raise AGIChannelError.new(@last_response, "Channel Failure in (#{command_str})")
  elsif response.native == 0
    response.success = true
  else
    response.success = true
    response.data = response.native.chr
  end
  return response
end

#say_number(number, digits = '""') ⇒ Object

Signals Asterisk to announce the number provided as a single number. If digits are provided as well, will allow the user to terminate the announcement if one of the digits are provided by DTMF.

Returns an AGIResponse including the DTMF digit provided by the channel.



637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
# File 'lib/AGI.rb', line 637

def say_number(number, digits='""')
  response = AGIResponse.new
  command_str = "SAY NUMBER #{number} #{digits}"
  begin
    response.native = execute(command_str)
  rescue AGITimeoutError, AGICommandError, AGIHangupError
    raise
  end
  if response.native == -1 then
    raise AGIChannelError.new(@last_response, "Channel Failure in (#{command_str})")
  elsif response.native == 0
    response.success = true
  else
    response.success = true
    response.data = response.native.chr
  end
  return response
end

#say_phonetic(string, digits = '""') ⇒ Object

Signals Asterisk to announce the string provided as a series of characters. If digits are provided as well, will allow the user to terminate the announcement if one of the digits are provided by DTMF.

Returns an AGIResponse including the DTMF digit provided by the channel.



659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
# File 'lib/AGI.rb', line 659

def say_phonetic(string, digits='""')
  response = AGIResponse.new
  command_str = "SAY PHONETIC '#{string}' #{digits}"
  begin
    response.native = execute(command_str)
  rescue AGITimeoutError, AGICommandError, AGIHangupError
    raise
  end
  if response.native == -1 then
    raise AGIChannelError.new(@last_response, "Channel Failure in (#{command_str})")
  elsif response.native == 0
    response.success = true
  else
    response.success = true
    response.data = response.native.chr
  end
  return response
end

#say_time(time = Time.now, digits = '""') ⇒ Object

Signals Asterisk to announce the given time. If digits are provided as well, will allow the user to terminate the announcement if one of the digits are provided by DTMF. Can accept either a Time object or an integer designation of the number of seconds since 00:00:00 January 1, 1970, Coordinated Universal Time (UTC). Defaults to now.

Returns an AGIResponse including the DTMF digit provided by the channel, if any are.



681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
# File 'lib/AGI.rb', line 681

def say_time(time=Time.now, digits='""')
  response = AGIResponse.new
  command_str = "SAY TIME #{time.to_i} #{digits}"
  begin
    response.native = execute(command_str)
  rescue AGITimeoutError, AGICommandError, AGIHangupError
    raise
  end
  if response.native == -1 then
    raise AGIChannelError.new(@last_response, "Channel Failure in (#{command_str})")
  elsif response.native == 0
    response.success = true
  else
    response.success = true
    response.data = response.native.chr
  end
  return response
end

#send_image(image) ⇒ Object

Signals Asterisk to transfer an image across the channel.

Returns an AGIResponse.

Please note, at present Asterisk returns the same value to the AGI if the image is sent and if the channel does not support image transmission. The AGIResponse, therefore, reflects the same. AGIResponse.success? will be true for both successful transmission and for channel-doesn’t support.



705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
# File 'lib/AGI.rb', line 705

def send_image(image)
  response = AGIResponse.new
  command_str = "SEND IMAGE #{image}"
  begin
    response.native = execute(command_str)
  rescue AGITimeoutError, AGICommandError, AGIHangupError
    raise
  end
  if response.native == -1 then
    raise AGIChannelError.new(@last_response, "Channel Failure in (#{command_str})")
  elsif response.native == 0
    response.success = true
  end
  return response
end

#send_text(text) ⇒ Object

Signals Asterisk to transfer text across the channel.

Returns an AGIResponse.

Please note, at present Asterisk returns the same value to the AGI if the text is sent and if the channel does not support text transmission. The AGIResponse, therefore, reflects the same. AGIResponse.success? will be true for both successful transmission and for channel-doesn’t support.



726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
# File 'lib/AGI.rb', line 726

def send_text(text)
  response = AGIResponse.new
  command_str = "SEND TEXT '#{text}'"
  begin
    response.native = execute(command_str)
  rescue AGITimeoutError, AGICommandError, AGIHangupError
    raise
  end
  if response.native == -1 then
    raise AGIChannelError.new(@last_response, "Channel Failure in (#{command_str})")
  elsif response.native == 0
    response.success = true
  end
  return response
end

#set_autohangup(time) ⇒ Object

Signals Asterisk to hangup the channel after a given amount of time has elapsed.

Returns an AGIResponse.



745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
# File 'lib/AGI.rb', line 745

def set_autohangup(time)
  response = AGIResponse.new
  command_str = "SET AUTOHANGUP #{time}"
  begin
    response.native = execute(command_str)
  rescue AGITimeoutError, AGICommandError, AGIHangupError
    raise
  end
  if response.native == -1 then
    raise AGIChannelError.new(@last_response, "Channel Failure in (#{command_str})")
  elsif response.native == 0
    response.success = true
  end
  return response
end

#set_callerid(callerid) ⇒ Object

Signals Asterisk to set the callerid on the channel.

Returns an AGIResponse.



764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
# File 'lib/AGI.rb', line 764

def set_callerid(callerid)
  response = AGIResponse.new
  command_str = "SET CALLERID #{callerid}"
  begin
    response.native = execute(command_str)
  rescue AGITimeoutError, AGICommandError, AGIHangupError
    raise
  end
  if response.native == -1 then
    raise AGIChannelError.new(@last_response, "Channel Failure in (#{command_str})")
  elsif response.native == 1
    response.success = true
  end
  return response
end

#set_context(context) ⇒ Object

Signals Asterisk to set the context for the channel upon AGI completion.

Returns an AGIResponse.



783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
# File 'lib/AGI.rb', line 783

def set_context(context)
  response = AGIResponse.new
  command_str = "SET CONTEXT #{context}"
  begin
    response.native = execute(command_str)
  rescue AGITimeoutError, AGICommandError, AGIHangupError
    raise
  end
  if response.native == -1 then
    raise AGIChannelError.new(@last_response, "Channel Failure in (#{command_str})")
  elsif response.native == 0
    response.success = true
  end
  return response    
end

#set_extension(extension) ⇒ Object

Signals Asterisk to set the extension for the channel upon AGI completion.

Returns an AGIResponse.



802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
# File 'lib/AGI.rb', line 802

def set_extension(extension)
  response = AGIResponse.new
  command_str = "SET EXTENSION #{extension}"
  begin
    response.native = execute(command_str)
  rescue AGITimeoutError, AGICommandError, AGIHangupError
    raise
  end
  if response.native == -1 then
    raise AGIChannelError.new(@last_response, "Channel Failure in (#{command_str})")
  elsif response.native == 0
    response.success = true
  end
  return response    
end

#set_music(toggle, music_class = nil) ⇒ Object

Signals Asterisk to enable or disable music-on-hold for the channel. If music_class is provided, it will select music from the apropriate music class, if it is not provided, asterisk will use music from the default class. The toggle option can either be ‘on’ or ‘off’.

Returns an AGIResponse.



821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
# File 'lib/AGI.rb', line 821

def set_music(toggle, music_class=nil)
  unless ( toggle == 'on' || toggle == 'off')
    raise ArgumentError, "Argument 1 must be 'on' or 'off' to set music"
  end
  response = AGIResponse.new
  if music_class.nil? then
    command_str = "SET MUSIC #{toggle}"
  else
    command_str = "SET MUSIC #{toggle} #{music_class}"
  end
  begin
    response.native = execute(command_str)
  rescue AGITimeoutError, AGICommandError, AGIHangupError
    raise
  end
  if response.native == -1 then
    raise AGIChannelError.new(@last_response, "Channel Failure in (#{command_str})")
  elsif response.native == 0
    response.success = true
  end
  return response    
end

#set_priority(priority) ⇒ Object

Signals Asterisk to set the priority for the channel upon AGI completion.

Returns an AGIResponse.



847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
# File 'lib/AGI.rb', line 847

def set_priority(priority)
  response = AGIResponse.new
  command_str = "SET PRIORITY #{priority}"
  begin
    response.native = execute(command_str)
  rescue AGITimeoutError, AGICommandError, AGIHangupError
    raise
  end
  if response.native == -1 then
    raise AGIChannelError.new(@last_response, "Channel Failure in (#{command_str})")
  elsif response.native == 0
    response.success = true
  end
  return response    
end

#set_variable(variable, value) ⇒ Object

Signals Asterisk to set the contents of the requested channel variable.

Returns an AGIResponse



866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
# File 'lib/AGI.rb', line 866

def set_variable(variable, value)
  response = AGIResponse.new
  command_str = "SET VARIABLE #{variable} #{value}"
  begin
    response.native = execute(command_str)
  rescue AGITimeoutError, AGICommandError, AGIHangupError
    raise
  end
  if response.native == -1 then
    raise AGIChannelError.new(@last_response, "Channel Failure in (#{command_str})")
  elsif response.native == 1
    response.success = true
  end
  return response
end

#stream_file(file, digits = '', offset = nil) ⇒ Object

Signals Asterisk to stream the given audio file to the channel starting at an optional offset until either the entire file has been streamed or the user provides one of a set of DTMF digits.

Returns an AGIResponse including the DTMF digit provided by the channel.



885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
# File 'lib/AGI.rb', line 885

def stream_file(file, digits='', offset=nil)
  digits.gsub!(/['"]/, '')
  response = AGIResponse.new
  if offset.nil? then
    command_str = "STREAM FILE #{file} '#{digits}'"
  else
    command_Str = "STREAM FILE #{file} ''#{digits}' #{offset}"
  end
  begin
    response.native = execute(command_str)
  rescue AGITimeoutError, AGICommandError, AGIHangupError
    raise
  end
  if response.native == -1 then
    raise AGIChannelError.new(@last_response, "Channel Failure in (#{command_str})")
  elsif response.native == 0
    response.success = true
  else
    response.success = true
    response.data = response.native.chr
  end
  return response
end

#tdd_mode(toggle) ⇒ Object

Signals Asterisk to enable or disable tdd mode for the channel

Returns an AGIResponse.



912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
# File 'lib/AGI.rb', line 912

def tdd_mode(toggle)
  unless ( toggle == 'on' || toggle == 'off')
    raise ArgumentError, "Argument 1 must be 'on' or 'off' to set tdd mode"
  end
  command_str = "TDD MODE #{toggle}"
  response = AGIResponse.new
  begin
    response.native = execute(command_str)
  rescue AGITimeoutError, AGICommandError, AGIHangupError
    raise
  end
  if response.native == -1 then
    raise AGIChannelError.new(@last_response, "Channel Failure in (#{command_str})")
  elsif response.native == 0
    raise AGIChannelError.new(@last_response, "Channel is not TDD-Capable")
  elsif response.native == 1
    response.success = true
  end
  return response
end

#verbose(message, level) ⇒ Object

Signals Asterisk to log the given message using the given log level to asterisk’s verbose log.

Returns an AGIResponse.



936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
# File 'lib/AGI.rb', line 936

def verbose(message, level)
  response = AGIResponse.new
  command_str = "VERBOSE #{message} #{level}"
  begin
    response.native = execute(command_str)
  rescue AGITimeoutError, AGICommandError, AGIHangupError
    raise
  end
  if response.native == -1 then
    raise AGIChannelError.new(@last_response, "Channel Failure in (#{command_str})")
  elsif response.native == 1
    response.success = true
  end
  return response
end

#wait_for_digit(timeout = -1)) ⇒ Object

Signals Asterisk to collect a single DTMF digit from the channel while waiting for an optional timeout.

Returns an AGIResponse with data available which denotes the DTMF digits provided by the channel.



955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
# File 'lib/AGI.rb', line 955

def wait_for_digit(timeout=-1)
  response = AGIResponse.new
  command_str = "WAIT FOR DIGIT #{timeout}"
  begin
    response.native = execute(command_str)
  rescue AGITimeoutError, AGICommandError, AGIHangupError
    raise
  end
  if response.native == -1 then
    raise AGIChannelError.new(@last_response, "Channel Failure in (#{command_str})")
  elsif response.native == 0
    response.success = true
  else
    response.success = true
    response.data = response.native.chr
  end
  return response
end