gs_phone 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES.txt +9 -0
- data/TODO.txt +5 -2
- data/lib/gs_phone/version.rb +1 -1
- data/lib/gs_phone.rb +354 -37
- metadata +2 -2
data/CHANGES.txt
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
Version 0.0.2
|
2
|
+
(23 March 2007)
|
3
|
+
|
4
|
+
* Changed the option parsing to use Subverion style commands
|
5
|
+
* Added context based help to each command
|
6
|
+
* Setup a hidden folder in the HOME to store our configuration files
|
7
|
+
* Added a basic generated template file used by gsutil
|
8
|
+
|
9
|
+
|
1
10
|
Version 0.0.1
|
2
11
|
(05 March 2007)
|
3
12
|
|
data/TODO.txt
CHANGED
@@ -10,8 +10,8 @@ This is the list of tasks that need to be done or have been completed.
|
|
10
10
|
* Get a list of the ip addresses currently assigned (Currently this works: grep -i '^ip' users.yml | awk '// {print $2}' | sort)
|
11
11
|
* Cleanup the option parser
|
12
12
|
* Cleanup the output from the program (e.g. remove "GS >")
|
13
|
-
*
|
14
|
-
*
|
13
|
+
* Allow asterisk intregration
|
14
|
+
* Read user list from extensions.conf and/or sip.conf
|
15
15
|
|
16
16
|
= FUTURE
|
17
17
|
|
@@ -23,3 +23,6 @@ This is the list of tasks that need to be done or have been completed.
|
|
23
23
|
* Add a MAINTAINER file
|
24
24
|
* Add a LICENSE file
|
25
25
|
* Add a README file
|
26
|
+
* Create a RubyForge Project
|
27
|
+
* Rework commandline passing to be like Subversion (svn command options)
|
28
|
+
* Make --help the default command if no option is given
|
data/lib/gs_phone/version.rb
CHANGED
data/lib/gs_phone.rb
CHANGED
@@ -21,73 +21,82 @@
|
|
21
21
|
|
22
22
|
|
23
23
|
require 'yaml'
|
24
|
-
require 'optparse'
|
25
24
|
|
26
25
|
class GrandStream
|
27
26
|
|
28
27
|
# Default configurations
|
29
|
-
@user_file = "users.yml"
|
28
|
+
@user_file = "#{ENV["HOME"]}/.gs_phone/users.yml"
|
30
29
|
@admin_password = "admin"
|
31
|
-
@gsutil = "gsutil"
|
32
|
-
@
|
33
|
-
|
30
|
+
@gsutil = "#{ENV["HOME"]}/.gs_phone/gsutil"
|
31
|
+
@config_file = "#{ENV["HOME"]}/.gs_phone/settings.yml"
|
32
|
+
@template_files = "#{ENV["HOME"]}/.gs_phone/templates/"
|
34
33
|
|
35
34
|
# Setup the help messages with the optparse library
|
36
35
|
def initialize(args)
|
37
36
|
read_configuration
|
37
|
+
@command = args[0]
|
38
38
|
@ip = args[1]
|
39
39
|
@current_ip = args[2]
|
40
40
|
@admin = args[3]
|
41
|
-
opts = OptionParser.new do |opts|
|
42
|
-
opts.banner = "Usage: #$0 COMMANDS [options]\n\n" +
|
43
|
-
" 'IP' is the ip address you want the phone to use\n" +
|
44
|
-
" 'crtIP' is the ip address the phone currently has\n" +
|
45
|
-
" 'pass' is the current phone password\n\n"
|
46
|
-
|
47
|
-
opts.on("--new 'IP' ['crtIP'|'pass']", "Add new user and setup their phone ") do
|
48
|
-
self.add_user(@ip)
|
49
|
-
self.make(@ip)
|
50
|
-
self.update_config(@ip, @current_ip, @admin)
|
51
|
-
self.reboot_phone(@current_ip)
|
52
|
-
end
|
53
|
-
opts.on('-A', "--add-user", 'Adds a user to the phone database') { self.add_user(@ip) }
|
54
|
-
opts.on('-M', "--make 'IP", 'Generates a config file from the template') { self.make(@ip) }
|
55
|
-
opts.on('--make-all', 'Reboots all phones') { self.make_all }
|
56
|
-
opts.on('-U', "--update 'IP' ['crtIP'|'pass']", "Update the configuration file to the phone") { self.update_config(@ip, @current_ip, @admin) }
|
57
|
-
opts.on('--update-all', 'Updates the configs on all phones') { self.update_all }
|
58
|
-
opts.on('-R', "--reboot 'IP'", 'Reboots a phone') { self.reboot_phone(@ip) }
|
59
|
-
opts.on('--reboot-all', 'Reboots all phones') { self.reboot_all_phones }
|
60
|
-
opts.on('-F', '--find-ip', "Find the ip address in the configuration file") { self.find_ip }
|
61
41
|
|
42
|
+
case @command
|
43
|
+
when "help"
|
44
|
+
help_command = args[1]
|
45
|
+
puts usage_summary(help_command)
|
46
|
+
when "new"
|
47
|
+
self.add_user(@ip)
|
48
|
+
self.make(@ip)
|
49
|
+
self.update_config(@ip, @current_ip, @admin)
|
50
|
+
self.reboot_phone(@ip)
|
51
|
+
when "add"
|
52
|
+
self.add_user(@ip)
|
53
|
+
when "make"
|
54
|
+
self.make(@ip)
|
55
|
+
when "update"
|
56
|
+
self.update_config(@ip, @current_ip, @admin)
|
57
|
+
when "reboot"
|
58
|
+
self.reboot_phone(@ip)
|
59
|
+
when "find"
|
60
|
+
self.find_ip
|
61
|
+
else
|
62
|
+
|
62
63
|
end
|
63
|
-
opts.parse!(args)
|
64
64
|
end
|
65
65
|
|
66
|
+
|
66
67
|
# Read the gs_phone configuration file to get the settings
|
67
68
|
def read_configuration
|
68
69
|
|
69
|
-
if File.exists?("#{ENV["HOME"]}/.gs_phone")
|
70
|
+
if File.exists?("#{ENV["HOME"]}/.gs_phone/settings.yml")
|
70
71
|
settings = Hash.new
|
71
|
-
settings = YAML::load(File.open("#{ENV["HOME"]}/.gs_phone"))
|
72
|
+
settings = YAML::load(File.open("#{ENV["HOME"]}/.gs_phone/settings.yml"))
|
72
73
|
|
73
74
|
@user_file = settings["user_file"] if settings.include?("user_file")
|
74
75
|
@admin_password = settings["admin_password"]
|
75
76
|
@gsutil = settings["gsutil"]
|
76
|
-
@
|
77
|
+
@config_file = settings["config_file"]
|
78
|
+
@template_files = settings["template_files"]
|
77
79
|
else
|
78
80
|
puts "You have no default configuration file. We will create one for you"
|
79
81
|
settings = {
|
80
82
|
"admin_password" => "admin",
|
81
|
-
"user_file" => "users.yml",
|
82
|
-
"gsutil" => "gsutil",
|
83
|
-
"
|
83
|
+
"user_file" => "#{ENV["HOME"]}/.gs_phone/users.yml",
|
84
|
+
"gsutil" => "#{ENV["HOME"]}/.gs_phone/gsutil",
|
85
|
+
"config_file" => "#{ENV["HOME"]}/.gs_phone/settings.yml",
|
86
|
+
"template_files" => "#{ENV["HOME"]}/.gs_phone/templates/"
|
84
87
|
}
|
85
88
|
|
86
|
-
|
89
|
+
Dir.mkdir("#{ENV["HOME"]}/.gs_phone")
|
90
|
+
Dir.mkdir("#{ENV["HOME"]}/.gs_phone/templates")
|
91
|
+
cfg_template = File.new("#{ENV["HOME"]}/.gs_phone/templates/template.cfg", "w")
|
92
|
+
cfg_template.puts add_template
|
93
|
+
cfg_template.close
|
94
|
+
|
95
|
+
file = File.new("#{ENV["HOME"]}/.gs_phone/settings.yml","w")
|
87
96
|
file.puts settings.to_yaml
|
88
97
|
file.close
|
89
98
|
|
90
|
-
puts "File #{ENV["HOME"]}/.gs_phone has been created. Please make sure the"
|
99
|
+
puts "File #{ENV["HOME"]}/.gs_phone/ has been created. Please make sure the"
|
91
100
|
puts " settings are correct."
|
92
101
|
exit
|
93
102
|
|
@@ -147,7 +156,7 @@ class GrandStream
|
|
147
156
|
# needs it this way
|
148
157
|
ip1, ip2, ip3, ip4 = ip.split('.')
|
149
158
|
|
150
|
-
templated = IO.readlines(@
|
159
|
+
templated = IO.readlines(@template_files + "template.cfg")
|
151
160
|
phone_config = ""
|
152
161
|
|
153
162
|
# Substitue in the user fields into their config
|
@@ -156,7 +165,7 @@ class GrandStream
|
|
156
165
|
phone_config << line.gsub(/<<ext>>/, exten).gsub(/<<name>>/, name).gsub(/<<password>>/, password).gsub(/<<ip1>>/, ip1).gsub(/<<ip2>>/, ip2).gsub(/<<ip3>>/, ip3).gsub(/<<ip4>>/, ip4)
|
157
166
|
end
|
158
167
|
# Write out the string to a file now
|
159
|
-
File.open("#{@
|
168
|
+
File.open("#{@template_files}#{ip}.cfg", "w+") do |file|
|
160
169
|
file.puts phone_config
|
161
170
|
end
|
162
171
|
puts "GS< Made config for extension #{exten.to_s}"
|
@@ -194,7 +203,7 @@ class GrandStream
|
|
194
203
|
current_ip = ip_address
|
195
204
|
end
|
196
205
|
# Setup the string to shell out to the gsutil script to scrape the webforms
|
197
|
-
cmd = "#{@gsutil} -p '#{admin}' -r '#{current_ip}' < #{@
|
206
|
+
cmd = "#{@gsutil} -p '#{admin}' -r '#{current_ip}' < #{@template_files}#{ip_address}.cfg"
|
198
207
|
`#{cmd}`.to_s # Evil eval().
|
199
208
|
puts "GS< Config sent to phone"
|
200
209
|
end
|
@@ -270,5 +279,313 @@ class GrandStream
|
|
270
279
|
end
|
271
280
|
end
|
272
281
|
end
|
282
|
+
|
283
|
+
def usage_summary(command)
|
284
|
+
usage = ""
|
285
|
+
case command
|
286
|
+
when "new"
|
287
|
+
usage =<<EONEW
|
288
|
+
Usage: new
|
289
|
+
|
290
|
+
Goes through all the steps to setup a new phone:
|
291
|
+
"add", "make", "update", "reboot"
|
292
|
+
|
293
|
+
EONEW
|
294
|
+
|
295
|
+
when "add"
|
296
|
+
usage =<<EOADD
|
297
|
+
Usage: add IP_ADDRESS
|
298
|
+
|
299
|
+
Adds a user who has a phone at IP_ADDRESS
|
300
|
+
|
301
|
+
Ex:
|
302
|
+
add 192.168.1.200
|
303
|
+
|
304
|
+
EOADD
|
305
|
+
|
306
|
+
when "make"
|
307
|
+
usage =<<EOMAKE
|
308
|
+
Usage: make IP_ADDRESS
|
309
|
+
|
310
|
+
Creates the configuration file for the phone at IP_ADDRESS
|
311
|
+
|
312
|
+
Ex:
|
313
|
+
make 192.168.1.200
|
314
|
+
|
315
|
+
EOMAKE
|
316
|
+
|
317
|
+
when "update"
|
318
|
+
usage =<<EOUPDATE
|
319
|
+
Usage: update IP_ADDRESS [CURRENT_ADDRESS] [ADMIN_PASSWORD]
|
320
|
+
|
321
|
+
Sends the updated configuration file for IP_ADDRESS to the phone.
|
322
|
+
|
323
|
+
Optionaly, a phone configuration can be sent to a phone that currently has
|
324
|
+
a different ip address by using CURRENT_ADDRESS
|
325
|
+
|
326
|
+
The admin password from the configuration file can also be overridden
|
327
|
+
|
328
|
+
Ex:
|
329
|
+
update 192.168.1.200
|
330
|
+
update 192.168.1.200 192.168.1.10 <= Send '200's update to the phone at '10'
|
331
|
+
update 192.168.1.200 192.168.1.10 admin <= Also uses the factory password
|
332
|
+
|
333
|
+
|
334
|
+
EOUPDATE
|
335
|
+
|
336
|
+
when "reboot"
|
337
|
+
usage =<<EOREBOOT
|
338
|
+
Usage: reboot COMMAND IP_ADDRESS
|
339
|
+
|
340
|
+
Reboots the phone at IP_ADDRESS.
|
341
|
+
|
342
|
+
CAUTION: Some firmware will allow the phone to be rebooted while it is in use!
|
343
|
+
|
344
|
+
Ex:
|
345
|
+
reboot 192.168.1.200
|
346
|
+
|
347
|
+
EOREBOOT
|
348
|
+
|
349
|
+
when "find"
|
350
|
+
usage =<<EOFIND
|
351
|
+
Usage: find
|
352
|
+
|
353
|
+
Searches the user.yml file to get the ipaddress of an extension.
|
354
|
+
|
355
|
+
EOFIND
|
356
|
+
|
357
|
+
else
|
358
|
+
usage =<<EOHELP
|
359
|
+
Usage: COMMAND [options]
|
360
|
+
|
361
|
+
IP is the ip address you want the phone to use crtIP is the ip address
|
362
|
+
the phone currently has pass is the current phone password
|
363
|
+
|
364
|
+
COMMANDS DESCRIPTION
|
365
|
+
new Add new user and setup their phone
|
366
|
+
add Adds a user to the phone database
|
367
|
+
make Generates a config file from the template
|
368
|
+
update Uploads the configuration file to the phone
|
369
|
+
reboot Reboots a phone
|
370
|
+
find Find the ip address in the configuration file
|
371
|
+
|
372
|
+
EOHELP
|
373
|
+
end
|
374
|
+
return usage
|
375
|
+
end
|
376
|
+
|
377
|
+
|
378
|
+
def add_template
|
379
|
+
template = <<TEMPLATE
|
380
|
+
admin_password = admin
|
381
|
+
end_user_password = \<<ext>>
|
382
|
+
account_active_1 = 1
|
383
|
+
account_name_1 = <<name>>
|
384
|
+
sip_server = 192.168.1.1
|
385
|
+
outbound_proxy = 192.168.1.1
|
386
|
+
sip_userid = <<ext>>
|
387
|
+
authenticate_id = <<ext>>
|
388
|
+
authenticate_password = <<password>>
|
389
|
+
name = <<name>>
|
390
|
+
static_ipaddress_true = 1
|
391
|
+
static_ipaddress_1 = <<ip1>>
|
392
|
+
static_ipaddress_2 = <<ip2>>
|
393
|
+
static_ipaddress_3 = <<ip3>>
|
394
|
+
static_ipaddress_4 = <<ip4>>
|
395
|
+
static_subnet_1 = 255
|
396
|
+
static_subnet_2 = 255
|
397
|
+
static_subnet_3 = 255
|
398
|
+
static_subnet_4 = 0
|
399
|
+
static_router_1 = 192
|
400
|
+
static_router_2 = 168
|
401
|
+
static_router_3 = 1
|
402
|
+
static_router_4 = 1
|
403
|
+
static_dns1_1 = 192
|
404
|
+
static_dns1_2 = 168
|
405
|
+
static_dns1_3 = 1
|
406
|
+
static_dns1_4 = 1
|
407
|
+
static_dns2_1 = 0
|
408
|
+
static_dns2_2 = 0
|
409
|
+
static_dns2_3 = 0
|
410
|
+
static_dns2_4 = 0
|
411
|
+
silence_suppression = 0
|
412
|
+
voice_frames_per_tx = 2
|
413
|
+
layer3_QoS = 48
|
414
|
+
layer2_QoS_vlan_tag = 0
|
415
|
+
layer2_QoS_priority_value = 0
|
416
|
+
no_key_entry_timeout = 4
|
417
|
+
use_hash_as_dial_key = 1
|
418
|
+
local_rtp_port = 5004
|
419
|
+
use_random_port = 0
|
420
|
+
keepalive_interval = 20
|
421
|
+
use_nat_ip =
|
422
|
+
nat_traversal_stun_server =
|
423
|
+
firmware_upgrade = 0
|
424
|
+
http_upgrade_url =
|
425
|
+
config_server_path =
|
426
|
+
firmware_file_prefix =
|
427
|
+
firmware_file_postfix =
|
428
|
+
config_file_prefix =
|
429
|
+
config_file_postfix =
|
430
|
+
dhcp_option_66_bootserver = 0
|
431
|
+
automatic_http_upgrade = 1
|
432
|
+
automatic_http_upgrade_days = 10080
|
433
|
+
always_check_for_new_firmware = 0
|
434
|
+
auth_config_file = 0
|
435
|
+
dtmf_payload_type = 101
|
436
|
+
syslog_server =
|
437
|
+
syslog_level = 0
|
438
|
+
ntp_server = 192.168.1.1
|
439
|
+
dhcp_option_42_timeserver_override = 0
|
440
|
+
custom_ring_tone_1_caller_id =
|
441
|
+
custom_ring_tone_2_caller_id =
|
442
|
+
custom_ring_tone_3_caller_id =
|
443
|
+
disable_call_waiting = 0
|
444
|
+
lock_keypad_update = 0
|
445
|
+
PPPoE_id =
|
446
|
+
PPPoE_password =
|
447
|
+
dhcp_option_12_hostname =
|
448
|
+
dhcp_option_15_domain =
|
449
|
+
dhcp_dns_server_1 = 0
|
450
|
+
dhcp_dns_server_2 = 0
|
451
|
+
dhcp_dns_server_3 = 0
|
452
|
+
dhcp_dns_server_4 = 0
|
453
|
+
static_dns2_4 = 0
|
454
|
+
time_zone = 240
|
455
|
+
dhcp_option_2_timezone_override = 1
|
456
|
+
daylight_savings_time = 0
|
457
|
+
date_display_format = 1
|
458
|
+
device_mode = 0
|
459
|
+
wan_side_http_access = 0
|
460
|
+
replay_to_icmp_in_wan = 0
|
461
|
+
cloned_wan_mac_addr_1 =
|
462
|
+
cloned_wan_mac_addr_2 =
|
463
|
+
cloned_wan_mac_addr_3 =
|
464
|
+
cloned_wan_mac_addr_4 =
|
465
|
+
cloned_wan_mac_addr_5 =
|
466
|
+
cloned_wan_mac_addr_6 =
|
467
|
+
lan_subnet_mask =
|
468
|
+
lan_dhcp_base_ip =
|
469
|
+
dhcp_ip_lease_time = 24
|
470
|
+
dmz_ip =
|
471
|
+
port_fw_port_num_1 = 0
|
472
|
+
port_fw_lan_ip_1 =
|
473
|
+
port_fw_lan_port_1 = 0
|
474
|
+
port_fw_lan_proto_1 = 0
|
475
|
+
port_fw_port_num_2 = 0
|
476
|
+
port_fw_lan_ip_2 =
|
477
|
+
port_fw_lan_port_2 = 0
|
478
|
+
port_fw_lan_proto_2 = 0
|
479
|
+
port_fw_port_num_3 = 0
|
480
|
+
port_fw_lan_ip_3 =
|
481
|
+
port_fw_lan_port_3 = 0
|
482
|
+
port_fw_lan_proto_3 = 0
|
483
|
+
port_fw_port_num_4 = 0
|
484
|
+
port_fw_lan_ip_4 =
|
485
|
+
port_fw_lan_port_4 = 0
|
486
|
+
port_fw_lan_proto_4 = 0
|
487
|
+
port_fw_port_num_5 = 0
|
488
|
+
port_fw_lan_ip_5 =
|
489
|
+
port_fw_lan_port_5 = 0
|
490
|
+
port_fw_lan_proto_5 = 0
|
491
|
+
port_fw_port_num_6 = 0
|
492
|
+
port_fw_lan_ip_6 =
|
493
|
+
port_fw_lan_port_6 = 0
|
494
|
+
port_fw_lan_proto_6 = 0
|
495
|
+
port_fw_port_num_7 = 0
|
496
|
+
port_fw_lan_ip_7 =
|
497
|
+
port_fw_lan_port_7 = 0
|
498
|
+
port_fw_lan_proto_7 = 0
|
499
|
+
port_fw_port_num_8 = 8888
|
500
|
+
port_fw_lan_ip_9 = 10.10.10.8
|
501
|
+
port_fw_lan_port_8 = 80
|
502
|
+
port_fw_lan_proto_8 = 1
|
503
|
+
use_dns_srv = 0
|
504
|
+
userid_is_phone_number = 0
|
505
|
+
sip_registration = 1
|
506
|
+
unregister_on_reboot = 0
|
507
|
+
register_expiration = 60
|
508
|
+
local_sip_port = 5060
|
509
|
+
sip_t1_timeout = 100
|
510
|
+
sip_t2_interval = 400
|
511
|
+
nat_traversal_true = 1
|
512
|
+
subscribe_for_mwi = 1
|
513
|
+
proxy_require =
|
514
|
+
voicemail_userid = *97
|
515
|
+
send_dtmf_mode = 0
|
516
|
+
early_dial = 0
|
517
|
+
dial_plan_prefix =
|
518
|
+
enable_call_features = 1
|
519
|
+
session_expiration_1 = 180
|
520
|
+
min_session_expiration_1 = 90
|
521
|
+
caller_request_timer_1 = 0
|
522
|
+
callee_request_timer_1 = 0
|
523
|
+
force_timer_1 = 0
|
524
|
+
uac_specify_refresher_1 = 0
|
525
|
+
uas_specify_refresher_1 = 1
|
526
|
+
force_invite_1 = 0
|
527
|
+
enable_100rel_1 = 0
|
528
|
+
default_ring_tone = 0
|
529
|
+
send_anonymous = 0
|
530
|
+
auto_answer = 0
|
531
|
+
allow_auto_answer_by_call_info = 0
|
532
|
+
turn_off_speaker_on_remote_disconnect = 0
|
533
|
+
special_feature_1 = 100
|
534
|
+
account_active_2 = 1
|
535
|
+
account_name_2 =
|
536
|
+
sip_server_2 =
|
537
|
+
outbound_proxy_2 =
|
538
|
+
sip_userid_2 =
|
539
|
+
authenticate_id_2 =
|
540
|
+
authenticate_password_2 =
|
541
|
+
name_2 =
|
542
|
+
use_dns_srv_2 = 0
|
543
|
+
userid_is_phone_number_2 = 0
|
544
|
+
sip_registration_2 = 1
|
545
|
+
unregister_on_reboot_2 = 0
|
546
|
+
register_expiration_2 = 60
|
547
|
+
local_sip_port_2 = 5062
|
548
|
+
sip_t1_imeout = 100
|
549
|
+
sip_t2_interval = 400
|
550
|
+
nat_traversal_true_2 = 1
|
551
|
+
subscribe_for_mwi_2 = 0
|
552
|
+
proxy_require_2 =
|
553
|
+
voicemail_userid_2 =
|
554
|
+
send_dtmf_2 = 0
|
555
|
+
early_dial_2 = 0
|
556
|
+
dial_plan_prefix_2 =
|
557
|
+
enable_call_features_2 = 1
|
558
|
+
session_expiration_2 = 180
|
559
|
+
min_session_expiration_2 = 90
|
560
|
+
caller_request_timer_2 = 0
|
561
|
+
callee_request_timer_2 = 0
|
562
|
+
force_timer_2 = 0
|
563
|
+
uac_specify_refresher_2 = 0
|
564
|
+
uas_specify_refresher_2 = 1
|
565
|
+
force_invite_2 = 0
|
566
|
+
enable_100rel_2 = 0
|
567
|
+
account_ring_tone_2 = 0
|
568
|
+
send_anonymous_2 = 0
|
569
|
+
auto_answer_2 = 0
|
570
|
+
allow_auto_answer_by_caller_info = 0
|
571
|
+
turn_off_speaker_on_remote_disconnect = 0
|
572
|
+
vocoder_1_2 = 0
|
573
|
+
vocoder_2_2 = 8
|
574
|
+
vocoder_3_2 = 4
|
575
|
+
vocoder_4_2 = 18
|
576
|
+
vocoder_5_2 = 3
|
577
|
+
vocoder_6_2 = 0
|
578
|
+
vocoder_7_2 = 0
|
579
|
+
vocoder_8_2 = 0
|
580
|
+
special_feature_2 = 100
|
581
|
+
|
582
|
+
TEMPLATE
|
583
|
+
|
584
|
+
|
585
|
+
end
|
586
|
+
|
587
|
+
|
588
|
+
|
273
589
|
end # Class
|
274
590
|
|
591
|
+
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.0
|
|
3
3
|
specification_version: 1
|
4
4
|
name: gs_phone
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.0.
|
7
|
-
date: 2007-03-
|
6
|
+
version: 0.0.2
|
7
|
+
date: 2007-03-23 00:00:00 -07:00
|
8
8
|
summary: Application to mange and configure a group of Grandstream Voip phones
|
9
9
|
require_paths:
|
10
10
|
- lib
|