diff options
21 files changed, 590 insertions, 23 deletions
@@ -48,6 +48,8 @@ group :development do # Debugging http://railscasts.com/episodes/402-better-errors-railspanel gem 'better_errors' gem 'binding_of_caller' + + gem 'rails-erd' end group :test do diff --git a/Gemfile.lock b/Gemfile.lock index 010c3d1..902e551 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -51,6 +51,7 @@ GEM carrierwave (0.8.0) activemodel (>= 3.2.0) activesupport (>= 3.2.0) + choice (0.1.6) chronic (0.9.1) chunky_png (1.2.7) coderay (1.0.9) @@ -150,6 +151,11 @@ GEM activesupport (= 3.2.13) bundler (~> 1.0) railties (= 3.2.13) + rails-erd (1.1.0) + activerecord (>= 3.0) + activesupport (>= 3.0) + choice (~> 0.1.6) + ruby-graphviz (~> 1.0.4) railties (3.2.13) actionpack (= 3.2.13) activesupport (= 3.2.13) @@ -161,6 +167,7 @@ GEM rake (10.0.3) rdoc (3.12.2) json (~> 1.4) + ruby-graphviz (1.0.9) sass (3.2.7) sass-rails (3.2.6) railties (~> 3.2.0) @@ -246,6 +253,7 @@ DEPENDENCIES private_pub quiet_assets rails (= 3.2.13) + rails-erd sass-rails sextant simple_form (~> 2.1.0) diff --git a/app/controllers/config_snom_controller.rb b/app/controllers/config_snom_controller.rb index 1cac4b2..5b31064 100644 --- a/app/controllers/config_snom_controller.rb +++ b/app/controllers/config_snom_controller.rb @@ -63,7 +63,10 @@ class ConfigSnomController < ApplicationController if !params[:phone].blank? @phone = Phone.where({ :id => params[:phone].to_i }).first if !params[:sip_account].blank? - @sip_account = @phone.sip_accounts.where({ :id => params[:sip_account].to_i }).first + @sip_account = @phone.sip_accounts.where({ :id => params[:sip_account].to_i }).first || + if !@sip_account && @phone.fallback_sip_account && @phone.fallback_sip_account.id == params[:sip_account].to_i + @sip_account = @phone.fallback_sip_account + end end end diff --git a/app/controllers/config_yealink_controller.rb b/app/controllers/config_yealink_controller.rb new file mode 100644 index 0000000..0efcec0 --- /dev/null +++ b/app/controllers/config_yealink_controller.rb @@ -0,0 +1,310 @@ +class ConfigYealinkController < ApplicationController + + MAX_SIP_ACCOUNTS = 5 + MAX_HANDSETS = 5 + MAX_PHONEBOOK_ENTRIES = 1000 + IGNORE_PHONEBOOK_EXCEEDING = 500 + SIP_DEFAULT_PORT = 5060 + + before_filter { + @mac_address = params[:mac_address].to_s.upcase.gsub(/[^0-9A-F]/,'') + } + + def show + if @mac_address + @phone = Phone.where(:mac_address => @mac_address).first + end + + if ! @phone && GsParameter.get('PROVISIONING_AUTO_ADD_PHONE') + tenant = Tenant.where(:id => GsParameter.get('PROVISIONING_AUTO_TENANT_ID')).first + if ! tenant + render( + :status => 404, + :layout => false, + :content_type => 'text/plain', + :text => "<!-- Tenant not found -->", + ) + return + end + + @phone = tenant.phones.build + @phone.mac_address = @mac_address + @phone.hot_deskable = true + @phone.tenant = tenant + @phone.http_user = 'admin' + + if !GsParameter.get('PROVISIONING_SET_HTTP_PASSWORD').nil? && @phone.http_password.blank? + if GsParameter.get('PROVISIONING_SET_HTTP_PASSWORD').class == Fixnum + @phone.update_attributes({ :http_password => SecureRandom.hex(GsParameter.get('PROVISIONING_SET_HTTP_PASSWORD')) }) + elsif GsParameter.get('PROVISIONING_SET_HTTP_PASSWORD').class == String + @phone.update_attributes({ :http_password => GsParameter.get('PROVISIONING_SET_HTTP_PASSWORD') }) + end + end + + phone_model = nil + if request.env['HTTP_USER_AGENT'].index('W52P') + phone_model = PhoneModel.where(:name => 'Yealink W52P').first + end + + if ! phone_model + render( + :status => 404, + :layout => false, + :content_type => 'text/plain', + :text => "<!-- Phone Model not found in: \"#{request.env['HTTP_USER_AGENT']}\" -->", + ) + return + end + + @phone.phone_model = phone_model + if ! @phone.save + render( + :status => 500, + :layout => false, + :content_type => 'text/plain', + :text => "<!-- #{@phone.errors.messages.inspect} -->", + ) + return + end + + if ! GsParameter.get('PROVISIONING_AUTO_ADD_SIP_ACCOUNT') + return + end + + caller_name_index = 0 + sip_account_last = tenant.sip_accounts.where('caller_name LIKE ?', "#{GsParameter.get('PROVISIONING_AUTO_SIP_ACCOUNT_CALLER_PREFIX')}%").sort { |item1, item2| + item1.caller_name.gsub(/[^0-9]/, '').to_i <=> item2.caller_name.gsub(/[^0-9]/, '').to_i + }.last + + if sip_account_last + caller_name_index = sip_account_last.caller_name.gsub(/[^0-9]/, '').to_i + end + caller_name_index = caller_name_index + 1 + + @sip_account = tenant.sip_accounts.build + @sip_account.caller_name = "#{GsParameter.get('PROVISIONING_AUTO_SIP_ACCOUNT_CALLER_PREFIX')}#{caller_name_index}" + @sip_account.call_waiting = GsParameter.get('CALL_WAITING') + @sip_account.clir = GsParameter.get('DEFAULT_CLIR_SETTING') + @sip_account.clip = GsParameter.get('DEFAULT_CLIP_SETTING') + @sip_account.voicemail_pin = random_pin + @sip_account.hotdeskable = false + loop do + @sip_account.auth_name = SecureRandom.hex(GsParameter.get('DEFAULT_LENGTH_SIP_AUTH_NAME')) + break unless SipAccount.exists?(:auth_name => @sip_account.auth_name) + end + @sip_account.password = SecureRandom.hex(GsParameter.get('DEFAULT_LENGTH_SIP_PASSWORD')) + + if ! @sip_account.save + render( + :status => 500, + :layout => false, + :content_type => 'text/plain', + :text => "<!-- #{@sip_account.errors.messages.inspect} -->", + ) + return + end + + @phone.fallback_sip_account = @sip_account + if ! @phone.save + render( + :status => 500, + :layout => false, + :content_type => 'text/plain', + :text => "<!-- #{@phone.errors.messages.inspect} -->", + ) + return + end + end + + if ! @phone + render( + :status => 404, + :layout => false, + :content_type => 'text/plain', + :text => "<!-- Phone not found -->", + ) + return false + end + + if @phone.sip_accounts.any? + sip_accounts = @phone.sip_accounts + else + sip_accounts = [@phone.fallback_sip_account] + end + + base_url = "#{request.protocol}#{request.host_with_port}/config_yealink/#{@phone.id}/#{sip_accounts.first.id}/" + @phonebook_url = base_url + 'phone_book.xml' + + @sip_accounts = Array.new(MAX_SIP_ACCOUNTS) {|index| + sip_account = sip_accounts[index] + sip_account_entry = sip_account_defaults + + if sip_account + sip_account_entry['enable'] = '1' + sip_account_entry['label'] = sip_account.caller_name + sip_account_entry['auth_name'] = sip_account.auth_name + sip_account_entry['password'] = sip_account.password + sip_account_entry['user_name'] = sip_account.auth_name + sip_account_entry['sip_server_host'] = sip_account.sip_domain + sip_account_entry['outbound_host'] = sip_account.sip_domain + sip_account_entry['sip_listen_port'] = 5060 + (index*2) + end + + sip_account_entry + } + + @handsets = Array.new(MAX_HANDSETS) {|index| + handset = {} + sip_account = sip_accounts[index] + if sip_account + handset['name'] = sip_account.caller_name + else + handset['name'] = "Handset #{index+1}" + end + + handset + } + + @provisioning_url = "#{request.protocol}#{request.host_with_port}" + + if ! request.env['HTTP_USER_AGENT'].index('Yealink') + Rails.logger.info "---> User-Agent indicates not a Yealink phone (#{request.env['HTTP_USER_AGENT'].inspect})" + else + Rails.logger.info "---> Phone #{@mac_address.inspect}, IP address #{request_remote_ip.inspect}" + @phone.update_attributes({ :ip_address => request_remote_ip }) + end + end + + def phone_book + @phone = Phone.where({ :id => params[:phone].to_i }).first + if ! @phone + render( + :status => 404, + :layout => false, + :content_type => 'text/plain', + :text => "<!-- Phone not found -->", + ) + return false + end + + if @phone.sip_accounts.any? + sip_accounts = @phone.sip_accounts + else + sip_accounts = [@phone.fallback_sip_account] + end + + base_url = "#{request.protocol}#{request.host_with_port}/config_yealink/#{@phone.id}/#{sip_accounts.first.id}" + @phonebook_url = "#{base_url}/phone_book.xml" + + @phone_books = Array.new() + tenant = nil + phone_book_ids = {} + if @phone.phoneable.class == User + @phone.phoneable.phone_books.each do |phone_book| + if @phone_books.count >= MAX_PHONEBOOK_ENTRIES + break + end + if phone_book.phone_book_entries.count > IGNORE_PHONEBOOK_EXCEEDING + next + end + + @phone_books << {:name => phone_book.name, :url => "#{base_url}/#{phone_book.id}/phone_book.xml"} + phone_book_ids[phone_book.id] + end + tenant = @phone.phoneable.current_tenant + elsif @phone.phoneable.class == Tenant + tenant = @phone.phoneable + end + + if tenant + tenant.phone_books.each do |phone_book| + if @phone_books.count >= MAX_PHONEBOOK_ENTRIES + break + end + if phone_book.phone_book_entries.count > IGNORE_PHONEBOOK_EXCEEDING + next + end + + @phone_books << {:name => phone_book.name, :url => "#{base_url}/#{phone_book.id}/phone_book.xml"} + phone_book_ids[phone_book.id] + end + end + + phone_book_id = params[:phone_book].to_i + if @phone_books.any? && phone_book_ids[phone_book_id] + @phone_book = PhoneBook.where(:id => phone_book_id).first + end + + @phone_book = PhoneBook.where(:id => phone_book_id).first + + if @phone_book + respond_to { |format| + format.any { + self.formats = [ :xml ] + render :action => '_phone_directory' + } + } + else + respond_to { |format| + format.any { + self.formats = [ :xml ] + render :action => '_phone_menu' + } + } + end + + end + + private + def sip_account_defaults + sip_account_entry = { + 'enable' => '0', + 'label' => '', + 'display_name' => 'Call', + 'auth_name' => '', + 'password' => '', + 'user_name' => '', + 'sip_server_host' => '', + 'sip_server_port' => SIP_DEFAULT_PORT, + 'outbound_proxy_enable' => '1', + 'outbound_host' => '', + 'outbound_port' => SIP_DEFAULT_PORT, + 'transport' => '0', + 'backup_outbound_host' => '', + 'backup_outbound_port' => '', + 'anonymous_call' => '0', + 'anonymous_call_oncode' => '', + 'anonymous_call_offcode' => '', + 'reject_anonymous_call' => '0', + 'anonymous_reject_oncode' => '', + 'anonymous_reject_offcode' => '', + 'sip_listen_port' => '', + 'expires' => '', + '100rel_enable' => '', + 'precondition' => '', + 'subscribe_register' => '', + 'subscribe_mwi' => '1', + 'subscribe_mwi_expires' => '', + 'cid_source' => '', + 'session_timer.enable' => '', + 'session_timer.expires' => '', + 'session_timer.refresher' => '', + 'enable_user_equal_phone' => '', + 'srtp_encryption' => '', + 'ptime' => '', + 'subscribe_mwi_to_vm' => '1', + 'register_mac' => '', + 'register_line' => '', + 'reg_fail_retry_interval' => '', + 'enable_signal_encode' => '', + 'signal_encode_key' => '', + 'dtmf.type' => '1', + 'dtmf.dtmf_payload' => '', + 'dtmf.info_type' => '', + 'dnd.enable' => '0', + 'dnd.on_code' => '', + 'dnd.off_code' => '', + } + end + +end diff --git a/app/models/phone.rb b/app/models/phone.rb index 93553a2..a11a400 100644 --- a/app/models/phone.rb +++ b/app/models/phone.rb @@ -113,6 +113,57 @@ class Phone < ActiveRecord::Base rescue return false end + elsif self.phone_model.manufacturer.ieee_name == 'XIAMEN YEALINK NETWORK TECHNOLOGY CO.,LTD' + if !sip_account + self.sip_accounts.where(:sip_accountable_type => self.phoneable_type).each do |sip_account_associated| + if sip_account_associated.registration + sip_account = sip_account_associated + break + end + end + end + + if ! sip_account or ! sip_account.registration + require 'open-uri' + begin + if open("http://#{self.ip_address}/cgi-bin/ConfigManApp.com?key=Reboot", :http_basic_authentication=>['admin', self.http_password], :proxy => nil) + return true + end + rescue + return false + end + end + + require 'freeswitch_event' + event = FreeswitchEvent.new("NOTIFY") + event.add_header("profile", "gemeinschaft") + event.add_header("event-string", "check-sync;reboot=#{reboot.to_s}") + event.add_header("user", sip_account.auth_name) + event.add_header("host", sip_account.sip_domain.host) + event.add_header("content-type", "application/simple-message-summary") + return event.fire() + elsif self.phone_model.manufacturer.ieee_name == 'Polycom' + if !sip_account + self.sip_accounts.where(:sip_accountable_type => self.phoneable_type).each do |sip_account_associated| + if sip_account_associated.registration + sip_account = sip_account_associated + break + end + end + end + + if ! sip_account or ! sip_account.registration + return false + end + + require 'freeswitch_event' + event = FreeswitchEvent.new("NOTIFY") + event.add_header("profile", "gemeinschaft") + event.add_header("event-string", "check-sync;reboot=#{reboot.to_s}") + event.add_header("user", sip_account.auth_name) + event.add_header("host", sip_account.sip_domain.host) + event.add_header("content-type", "application/simple-message-summary") + return event.fire() end return false diff --git a/app/views/config_snom/_snom_phone_directory.xml.haml b/app/views/config_snom/_snom_phone_directory.xml.haml index 698f2e5..776e504 100644 --- a/app/views/config_snom/_snom_phone_directory.xml.haml +++ b/app/views/config_snom/_snom_phone_directory.xml.haml @@ -1,19 +1,22 @@ !!! XML -%SnomIPPhoneDirectory{:speedselect => 'off'} - %Title= @phone_xml_object[:title] - %Prompt= @phone_xml_object[:prompt] - - @phone_xml_object[:entries].each do |entry| - %DirectoryEntry{:sel => entry[:selected].to_s} - %Name= entry[:text] - %Telephone= entry[:number] +- cache(['snom_phone_directory', @sip_account.id, @phone_xml_object]) do + %SnomIPPhoneDirectory{:speedselect => 'off'} + %Title= @phone_xml_object[:title] + %Prompt= @phone_xml_object[:prompt] + - cache(['snom_phone_directory_table', @sip_account.id, @phone_xml_object[:entries]]) do + - @phone_xml_object[:entries].each do |entry| + - cache(['yealink_phone_directory_table_tr', @sip_account.id, entry]) do + %DirectoryEntry{:sel => entry[:selected].to_s} + %Name= entry[:text] + %Telephone= entry[:number] - - if @phone_xml_object[:softkeys] - - @phone_xml_object[:softkeys].each do |softkey| - %SoftKeyItem - %Name= softkey[:name] - - if ! softkey[:label].blank? - %Label= softkey[:label] - - if ! softkey[:url].blank? - %URL= softkey[:url] - - if ! softkey[:softkey].blank? - %URL= softkey[:softkey] + - if @phone_xml_object[:softkeys] + - @phone_xml_object[:softkeys].each do |softkey| + %SoftKeyItem + %Name= softkey[:name] + - if ! softkey[:label].blank? + %Label= softkey[:label] + - if ! softkey[:url].blank? + %URL= softkey[:url] + - if ! softkey[:softkey].blank? + %URL= softkey[:softkey] diff --git a/app/views/config_yealink/_phone_directory.xml.haml b/app/views/config_yealink/_phone_directory.xml.haml new file mode 100644 index 0000000..50d6561 --- /dev/null +++ b/app/views/config_yealink/_phone_directory.xml.haml @@ -0,0 +1,14 @@ +%YealinkIPPhoneDirectory + - cache(['yealink_phone_directory_table', @phone_book.id, @phone_book.phone_book_entries]) do + - @phone_book.phone_book_entries.each do |phone_book_entry| + - cache(['yealink_phone_directory_table_tr', @phone_book.id, phone_book_entry]) do + - phone_numbers = phone_book_entry.phone_numbers + - if !phone_book_entry.to_s.blank? && phone_numbers.any? + - mobile_phone = phone_numbers.where(:name => 'mobile').first + - phone = (phone_numbers - [mobile_phone]).first + %DirectoryEntry + %Name= phone_book_entry.to_s + - if phone + %Telephone= phone.number + - if mobile_phone + %Telephone= mobile_phone.number diff --git a/app/views/config_yealink/_phone_menu.xml.haml b/app/views/config_yealink/_phone_menu.xml.haml new file mode 100644 index 0000000..4ed41ec --- /dev/null +++ b/app/views/config_yealink/_phone_menu.xml.haml @@ -0,0 +1,6 @@ +%YealinkIPPhoneMenu + %Title Gemeinschaft + - @phone_books.each do |phone_book| + %MenuItem + %Name= phone_book[:name] + %URL= phone_book[:url] diff --git a/app/views/config_yealink/show.text.haml b/app/views/config_yealink/show.text.haml new file mode 100644 index 0000000..a654e19 --- /dev/null +++ b/app/views/config_yealink/show.text.haml @@ -0,0 +1,41 @@ += '#!version:1.0.0.1' + += 'lang.wui = English' += 'call_waiting.enable = 1' += 'voice.tone.country = Germany' += 'auto_provision.pnp_enable = 1' += 'auto_provision.mode = 1' += 'auto_provision.repeat.enable = 0' += 'auto_provision.repeat.minutes = 3600' += 'auto_provision.weekly.enalbe = 0' += 'auto_provision.weekly.mask = 0123456' += 'auto_provision.weekly.begin_time = 00:00' += 'auto_provision.weekly.end_time = 00:00' += 'auto_provision.server.url = ' + @provisioning_url += 'auto_provision.server.username = ' += 'auto_provision.server.password = ' += 'local_time.time_zone = +1' += 'local_time.time_zone_name = Germany(Berlin)' += 'local_time.summer_time = 2' += 'local_time.dst_time_type = 1' += 'local_time.start_time = ' += 'local_time.end_time = ' += 'local_time.offset_time = 60' + += 'local_time.ntp_server1 = ' += 'local_time.ntp_server2 = ' += 'security.user_password = admin:' + (@phone.http_password.blank? ? '0000' : @phone.http_password.to_s) + + +- @sip_accounts.each_with_index do |sip_account, index| + - i = index + 1 + - sip_account.each_pair do |key, value| + = "account.#{i}.#{key} = #{value}" + +- @handsets.each_with_index do |handset, index| + - i = index + 1 + - handset.each_pair do |key, value| + = "handset.#{i}.#{key} = #{value}" + += "remote_phonebook.data.1.url = #{@phonebook_url}" += 'remote_phonebook.data.1.name = Gemeinschaft' diff --git a/app/views/gateways/show.xml.haml b/app/views/gateways/show.xml.haml index e0ff21a..1642ccc 100644 --- a/app/views/gateways/show.xml.haml +++ b/app/views/gateways/show.xml.haml @@ -5,6 +5,10 @@ - @gateway.gateway_settings.each do |setting| %setting{ :name => setting.name, :value => setting.value, :class_type => setting.class_type, :description => setting.description } + %gateway_headers{ :count => @gateway.gateway_headers.count } + - @gateway.gateway_headers.each do |header| + %header{ :header_type => header.header_type, :constraint => header.constraint_value, :name => header.name, :value => header.value, :description => header.description } + %gateway_parameters{ :count => @gateway.gateway_parameters.count } - @gateway.gateway_parameters.each do |parameter| %parameter{ :name => parameter.name, :value => parameter.value, :class_type => parameter.class_type, :description => parameter.description } diff --git a/config/routes.rb b/config/routes.rb index d958c87..abe8c25 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -203,6 +203,10 @@ Gemeinschaft42c::Application.routes.draw do get "config_polycom/:phone/:sip_account/phone_book" => "config_polycom#phone_book" get "config_polycom/:phone/:sip_account/call_history" => "config_polycom#call_history" get "config_polycom/:phone/:sip_account/idle_screen" => "config_polycom#idle_screen" + + #Yealink + get "config_yealink/:phone/:sip_account/phone_book" => "config_yealink#phone_book" + get "config_yealink/:phone/:sip_account/:phone_book/phone_book" => "config_yealink#phone_book" # Unified path for Snom phones. # Enter e.g. "http://192.168.1.105:3000/settings" @@ -218,6 +222,10 @@ Gemeinschaft42c::Application.routes.draw do :constraints => { :mac_address => /000413[0-9A-F]{6}/i }, :via => [:get], :format => 'xml' + match 'settings-:mac_address' => 'config_yealink#show', + :constraints => { :mac_address => /001565[0-9A-F]{6}/i }, + :via => [:get], + :format => 'text' match 'snom_vision-:provisioning_key' => 'config_snom#snom_vision', :via => [:get], :format => 'xml' @@ -232,6 +240,10 @@ Gemeinschaft42c::Application.routes.draw do :constraints => { :mac_address => /0004f2[0-9A-F]{6}/i }, :via => [:get], :format => 'xml' + match ':mac_address.cfg' => 'config_yealink#show', + :constraints => { :mac_address => /001565[0-9A-F]{6}/i }, + :via => [:get], + :format => 'text' match 'settings-:mac_address.cfg' => 'config_polycom#settings', :constraints => { :mac_address => /0004f2[0-9A-F]{6}/i }, :via => [:get], diff --git a/db/migrate/20130812093300_add_yealink_phone.rb b/db/migrate/20130812093300_add_yealink_phone.rb new file mode 100644 index 0000000..cf4bd09 --- /dev/null +++ b/db/migrate/20130812093300_add_yealink_phone.rb @@ -0,0 +1,14 @@ +class AddYealinkPhone < ActiveRecord::Migration + def up + Manufacturer.create(:name => 'Yealink', :ieee_name => 'XIAMEN YEALINK NETWORK TECHNOLOGY CO.,LTD', :homepage_url => 'http://www.yealink.com') + yealink = Manufacturer.where(:name => 'Yealink').first + if yealink + yealink.phone_models.create(:name => 'Yealink W52P', :product_manual_homepage_url => 'http://www.yealink.com/Upload/W52P/V30/Yealink%20W52P_User_Guide_V30.pdf', :product_homepage_url => 'http://www.yealink.com/product_info.aspx?ProductsCateID=308') + end + end + + def down + Manufacturer.where(:name => 'Yealink').destroy_all + PhoneModel.where(:name => 'Yealink W52P').destroy_all + end +end diff --git a/db/migrate/20130813051500_add_polycom_phone.rb b/db/migrate/20130813051500_add_polycom_phone.rb new file mode 100644 index 0000000..a560fee --- /dev/null +++ b/db/migrate/20130813051500_add_polycom_phone.rb @@ -0,0 +1,14 @@ +class AddPolycomPhone < ActiveRecord::Migration + def up + Manufacturer.create(:name => 'Polycom', :ieee_name => 'Polycom', :homepage_url => 'http://www.polycom.com') + polycom = Manufacturer.where(:name => 'Polycom').first + if polycom + polycom.phone_models.create(:name => 'Polycom SoundPoint IP 670', :product_manual_homepage_url => 'http://www.polycom.com/global/documents/support/user/products/voice/SoundPoint_IP_670_User_Guide_SIP_v3_2.pdf', :product_homepage_url => 'http://www.polycom.com/products-services/voice/desktop-solutions/soundpont-ip-series/soundpoint-ip-670.html') + end + end + + def down + Manufacturer.where(:name => 'Polycom').destroy_all + PhoneModel.where(:name => 'Polycom SoundPoint IP 670').destroy_all + end +end diff --git a/db/migrate/20130814103800_change_perimeter_blacklist_entry.rb b/db/migrate/20130814103800_change_perimeter_blacklist_entry.rb new file mode 100644 index 0000000..597613f --- /dev/null +++ b/db/migrate/20130814103800_change_perimeter_blacklist_entry.rb @@ -0,0 +1,15 @@ +class ChangePerimeterBlacklistEntry < ActiveRecord::Migration + def up + blacklist_file_entry = GsParameter.where(:entity => 'perimeter', :section => 'general', :name => 'blacklist_file_entry').first + if blacklist_file_entry + blacklist_file_entry.update_attributes(:value => 'DROP net:{received_ip} all udp 5060', :class_type => 'String') + end + end + + def down + blacklist_file_entry = GsParameter.where(:entity => 'perimeter', :section => 'general', :name => 'blacklist_file_entry').first + if blacklist_file_entry + blacklist_file_entry.update_attributes(:value => '{received_ip} udp 5060', :class_type => 'String') + end + end +end diff --git a/lib/tasks/originate.rake b/lib/tasks/originate.rake index 5e7dfe3..b89b11b 100644 --- a/lib/tasks/originate.rake +++ b/lib/tasks/originate.rake @@ -9,5 +9,5 @@ task :originate, [ sip_account = SipAccount.where(:id => a.sip_account_id.to_i).first print "Originate #{sip_account} -> #{extension} ... " - puts sip_account.call(extension) -end
\ No newline at end of file + puts sip_account.call(extension, nil, nil, true) +end diff --git a/misc/freeswitch/scripts/dialplan/dialplan.lua b/misc/freeswitch/scripts/dialplan/dialplan.lua index 1133f58..b39acff 100644 --- a/misc/freeswitch/scripts/dialplan/dialplan.lua +++ b/misc/freeswitch/scripts/dialplan/dialplan.lua @@ -18,6 +18,7 @@ local CALL_FORWARDING_SERVICES = { HUNT_GROUP_EMPTY = 'offline', ACD_NO_AGENTS = 'offline', ACD_TIMEOUT = 'noanswer', + NO_USER_RESPONSE = 'offline', } -- create dialplan object diff --git a/misc/freeswitch/scripts/dialplan/presence.lua b/misc/freeswitch/scripts/dialplan/presence.lua index 0f63ce9..af05756 100644 --- a/misc/freeswitch/scripts/dialplan/presence.lua +++ b/misc/freeswitch/scripts/dialplan/presence.lua @@ -53,6 +53,7 @@ function Presence.set(self, state, caller_number) event:addHeader('presence-call-direction', direction); event:addHeader('answer-state', state); event:addHeader('unique-id', self.uuid); + event:addHeader('event_origin', 'gemeinschaft'); if caller_number then if self.inbound then event:addHeader('Caller-Destination-Number', caller_number); diff --git a/misc/freeswitch/scripts/event/presence_update.lua b/misc/freeswitch/scripts/event/presence_update.lua index cf29ca9..24b19d5 100644 --- a/misc/freeswitch/scripts/event/presence_update.lua +++ b/misc/freeswitch/scripts/event/presence_update.lua @@ -128,7 +128,9 @@ function PresenceUpdate.presence_in(self, event) direction = false; end - if protocol == 'conf' then + if tostring(event:getHeader('event_origin')) == 'gemeinschaft' then + self.log:debug('[', uuid,'] PRESENCE_', call_direction:upper(),'_LOOP ignored - protocol: ', protocol, ', account: ', account, ', state: ', state); + elseif protocol == 'conf' then state = event:getHeader('answer-state'); local login = tostring(event:getHeader('proto')); self.log:info('[', uuid,'] PRESENCE_CONFERENCE_', call_direction:upper(), ' ', common.str.to_i(account), ' - identifier: ', account, ', state: ', state); diff --git a/misc/freeswitch/scripts/phones/phone.lua b/misc/freeswitch/scripts/phones/phone.lua index 6219eb1..174503b 100644 --- a/misc/freeswitch/scripts/phones/phone.lua +++ b/misc/freeswitch/scripts/phones/phone.lua @@ -27,11 +27,14 @@ function Phone.list_by_sql(self, sql_query) phone.record.ieee_name = common.str.downcase(account_entry.ieee_name); if phone.record.ieee_name == 'snom technology ag' then - require 'phones.snom' + require 'phones.snom'; phone.model = phones.snom.Snom:new{ log = self.log }; elseif account_entry.ieee_name == 'siemens enterprise communicationsgmbh & co. kg' then - require 'phones.siemens' + require 'phones.siemens'; phone.model = phones.siemens.Siemens:new{ log = self.log }; + elseif phone.record.ieee_name == 'xiamen yealink network technology co.,ltd' then + require 'phones.yealink'; + phone.model = phones.yealink.Yealink:new{ log = self.log }; end table.insert(account_phones, phone); end) diff --git a/misc/freeswitch/scripts/phones/yealink.lua b/misc/freeswitch/scripts/phones/yealink.lua new file mode 100644 index 0000000..2794ed6 --- /dev/null +++ b/misc/freeswitch/scripts/phones/yealink.lua @@ -0,0 +1,60 @@ +-- Gemeinschaft 5 module: general yealink model class +-- (c) AMOOMA GmbH 2013 +-- + +module(...,package.seeall) + +Yealink = {} + +-- Create Yealink object +function Yealink.new(self, arg) + arg = arg or {} + object = arg.object or {} + setmetatable(object, self); + self.__index = self; + self.log = arg.log; + self.reboot = arg.reboot or true; + return object; +end + +-- send reload message to phone +function Yealink.resync(self, arg) + if arg.reboot == nil then + arg.reboot = self.reboot; + end + + local success = nil; + if arg.auth_name and arg.domain then + success = self:resync_sip(arg.auth_name, arg.domain, arg.reboot); + end + + if arg.ip_address and arg.reboot then + success = self:resync_http(arg.ip_address, arg.http_user, arg.http_password, arg.http_port); + end + + return success; +end + +-- send reload message to sip_account +function Yealink.resync_sip(self, sip_account, domain, reboot) + local event = freeswitch.Event('NOTIFY'); + event:addHeader('profile', 'gemeinschaft'); + event:addHeader('event-string', 'check-sync;reboot=' .. tostring(reboot)); + event:addHeader('user', sip_account); + event:addHeader('host', domain); + event:addHeader('content-type', 'application/simple-message-summary'); + return event:fire(); +end + +-- send reload message to ip +function Yealink.resync_http(self, ip_address, http_user, http_password, http_port) + local port_str = ''; + if tonumber(http_port) then + port_str = ':' .. http_port; + end + + local command = 'http_request.lua yealink_resync http://' .. tostring(ip_address):gsub('[^0-9%.]', '') .. port_str .. '/cgi-bin/ConfigManApp.com?key=Reboot ' .. (http_user or '') .. ' ' .. (http_password or ''); + + require 'common.fapi' + return common.fapi.FApi:new():execute('luarun', command); +end diff --git a/public/y000000000025.cfg b/public/y000000000025.cfg new file mode 100644 index 0000000..985bc8a --- /dev/null +++ b/public/y000000000025.cfg @@ -0,0 +1,3 @@ +#!version:1.0.0.1
+
+# general Yealink configuration
|