diff --git a/app/dialplan/resources/switch/conf/dialplan/500_call-forward.xml b/app/dialplan/resources/switch/conf/dialplan/500_call-forward.xml
index ddcad28397..5f29871ee3 100644
--- a/app/dialplan/resources/switch/conf/dialplan/500_call-forward.xml
+++ b/app/dialplan/resources/switch/conf/dialplan/500_call-forward.xml
@@ -13,5 +13,10 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/install/scripts/blf_subscribe.lua b/resources/install/scripts/blf_subscribe.lua
new file mode 100644
index 0000000000..a5050cca70
--- /dev/null
+++ b/resources/install/scripts/blf_subscribe.lua
@@ -0,0 +1,174 @@
+local proto = argv[1] or 'all'
+
+local service_name
+if proto == 'all' then
+ service_name = 'blf'
+else
+ service_name = proto
+end
+
+require "resources.functions.config"
+require "resources.functions.split"
+
+local log = require "resources.functions.log"[service_name]
+local presence_in = require "resources.functions.presence_in"
+local Database = require "resources.functions.database"
+local BasicEventService = require "resources.functions.basic_event_service"
+
+local find_call_flow do
+
+local find_call_flow_sql = [[select t1.call_flow_uuid, t1.call_flow_status
+from v_call_flows t1 inner join v_domains t2 on t1.domain_uuid = t2.domain_uuid
+where t2.domain_name = :domain_name and (t1.call_flow_feature_code = :feature_code
+or t1.call_flow_feature_code = :short_feature_code)
+]]
+
+function find_call_flow(user)
+ local ext, domain_name = split_first(user, '@', true)
+ local _, short = split_first(ext, '+', true)
+ if not domain_name then return end
+ local dbh = Database.new('system')
+ if not dbh then return end
+ local row = dbh:first_row(find_call_flow_sql, {
+ domain_name = domain_name, feature_code = ext, short_feature_code = short
+ })
+ dbh:release()
+ if not row then return end
+ return row.call_flow_uuid, row.call_flow_status
+end
+
+end
+
+local find_dnd do
+
+local find_dnd_sql = [[select t1.do_not_disturb
+from v_extensions t1 inner join v_domains t2 on t1.domain_uuid = t2.domain_uuid
+where t2.domain_name = :domain_name and (t1.extension = :extension or t1.number_alias=:extension)]]
+
+find_dnd = function(user)
+ local ext, domain_name = split_first(user, '@', true)
+ if not domain_name then return end
+ local dbh = Database.new('system')
+ if not dbh then return end
+ local dnd = dbh:first_value(find_dnd_sql, {domain_name = domain_name, extension = ext})
+ dbh:release()
+ return dnd
+end
+
+end
+
+local find_call_forward do
+
+local find_call_forward_sql = [[select t1.forward_all_destination, t1.forward_all_enabled
+from v_extensions t1 inner join v_domains t2 on t1.domain_uuid = t2.domain_uuid
+where t2.domain_name = :domain_name and (t1.extension = :extension or t1.number_alias=:extension)]]
+
+find_call_forward = function(user)
+ local ext, domain_name, number = split_first(user, '@', true)
+ if not domain_name then return end
+ ext, number = split_first(ext, '/', true)
+ local dbh = Database.new('system')
+ if not dbh then return end
+ local row = dbh:first_row(find_call_forward_sql, {domain_name = domain_name, extension = ext})
+ dbh:release()
+ if not (row and row.forward_all_enabled) then return end
+ if row.forward_all_enabled ~= 'true' then return 'false' end
+ if number then
+ return number == row.forward_all_destination and 'true' or 'false',
+ row.forward_all_destination
+ end
+ return 'true', row.forward_all_destination
+end
+
+end
+
+local protocols = {}
+
+protocols.flow = function(event)
+ local from, to = event:getHeader('from'), event:getHeader('to')
+ local expires = tonumber(event:getHeader('expires'))
+ if expires and expires > 0 then
+ local call_flow_uuid, call_flow_status = find_call_flow(to)
+ if call_flow_uuid then
+ log.noticef("Find call flow: %s staus: %s", to, tostring(call_flow_status))
+ presence_in.turn_lamp(call_flow_status == "false", to, call_flow_uuid)
+ else
+ log.warningf("Can not find call flow: %s", to)
+ end
+ else
+ log.noticef("%s UNSUBSCRIBE from %s", from, to)
+ end
+end
+
+protocols.dnd = function(event)
+ local from, to = event:getHeader('from'), event:getHeader('to')
+ local expires = tonumber(event:getHeader('expires'))
+ if expires and expires > 0 then
+ local proto, user = split_first(to, '+', true)
+ user = user or proto
+ local dnd_status = find_dnd(user)
+ if dnd_status then
+ log.noticef("Find DND: %s staus: %s", to, tostring(dnd_status))
+ presence_in.turn_lamp(dnd_status == "true", to)
+ else
+ log.warningf("Can not find DND: %s", to)
+ end
+ else
+ log.noticef("%s UNSUBSCRIBE from %s", from, to)
+ end
+end
+
+protocols.forward = function(event)
+ local from, to = event:getHeader('from'), event:getHeader('to')
+ local expires = tonumber(event:getHeader('expires'))
+ if expires and expires > 0 then
+ local proto, user = split_first(to, '+', true)
+ user = user or proto
+ local status, number = find_call_forward(user)
+ if status then
+ if status == 'true' then
+ log.noticef("CF: %s to number %s", to, tostring(number))
+ else
+ log.noticef("CF: %s disabled", to)
+ end
+ presence_in.turn_lamp(status == "true", to)
+ else
+ log.warningf("Can not find CF: %s", to)
+ end
+ else
+ log.noticef("%s UNSUBSCRIBE from %s", from, to)
+ end
+end
+
+if proto ~= 'all' then
+ for name in pairs(protocols) do
+ if proto ~= name then
+ protocols[name] = nil
+ end
+ end
+end
+
+if not next(protocols) then
+ log.errorf('Unknown subscribe protocol: %s', proto)
+ return
+end
+
+for name in pairs(protocols) do
+ log.noticef('add subscribe protocol: %s', name)
+end
+
+local service = BasicEventService.new(log, service_name)
+
+-- FS receive SUBSCRIBE to BLF from device
+service:bind("PRESENCE_PROBE", function(self, name, event)
+ local proto = event:getHeader('proto')
+ local handler = proto and protocols[proto]
+ if not handler then return end
+ return handler(event)
+end)
+
+log.notice("start")
+
+service:run()
+
+log.notice("stop")
diff --git a/resources/install/scripts/call_flow_subscribe.lua b/resources/install/scripts/call_flow_subscribe.lua
index b756200c16..12ea57ffa2 100644
--- a/resources/install/scripts/call_flow_subscribe.lua
+++ b/resources/install/scripts/call_flow_subscribe.lua
@@ -1,123 +1,4 @@
-require "resources.functions.config"
-require "resources.functions.split"
+-- For backward compatibility
+argv[1] = 'flow'
+require "blf_subscribe"
-local log = require "resources.functions.log".call_flow_subscribe
-local EventConsumer = require "resources.functions.event_consumer"
-local presence_in = require "resources.functions.presence_in"
-local Database = require "resources.functions.database"
-
-local find_call_flow do
-
-local find_call_flow_sql = [[select t1.call_flow_uuid, t1.call_flow_status
-from v_call_flows t1 inner join v_domains t2 on t1.domain_uuid = t2.domain_uuid
-where t2.domain_name = :domain_name and (t1.call_flow_feature_code = :feature_code
-or t1.call_flow_feature_code = :short_feature_code)
-]]
-
-function find_call_flow(user)
- local ext, domain_name = split_first(user, '@', true)
- local _, short = split_first(ext, '+', true)
- if not domain_name then return end
- local dbh = Database.new('system')
- if not dbh then return end
- local row = dbh:first_row(find_call_flow_sql, {
- domain_name = domain_name, feature_code = ext, short_feature_code = short
- })
- dbh:release()
- if not row then return end
- return row.call_flow_uuid, row.call_flow_status
-end
-
-end
-
-local find_dnd do
-
-local find_dnd_sql = [[select t1.do_not_disturb
-from v_extensions t1 inner join v_domains t2 on t1.domain_uuid = t2.domain_uuid
-where t2.domain_name = :domain_name and (t1.extension = :extension or t1.number_alias=:extension)]]
-
-find_dnd = function(user)
- local ext, domain_name = split_first(user, '@', true)
- if not domain_name then return end
- local dbh = Database.new('system')
- if not dbh then return end
- local dnd = dbh:first_value(find_dnd_sql, {domain_name = domain_name, extension = ext})
- dbh:release()
- return dnd
-end
-
-end
-
-local service_name = "call_flow"
-local pid_file = scripts_dir .. "/run/" .. service_name .. ".tmp"
-
-local events = EventConsumer.new(pid_file)
-
--- FS shutdown
-events:bind("SHUTDOWN", function(self, name, event)
- log.notice("shutdown")
- return self:stop()
-end)
-
--- Control commands from FusionPBX
-events:bind("CUSTOM::fusion::service::control", function(self, name, event)
- if service_name ~= event:getHeader('service-name') then return end
-
- local command = event:getHeader('service-command')
- if command == "stop" then
- log.notice("get stop command")
- return self:stop()
- end
-
- log.warningf('Unknown service command: %s', command or '')
-end)
-
-local protocols = {}
-
-protocols.flow = function(event)
- local from, to = event:getHeader('from'), event:getHeader('to')
- local expires = tonumber(event:getHeader('expires'))
- if expires and expires > 0 then
- local call_flow_uuid, call_flow_status = find_call_flow(to)
- if call_flow_uuid then
- log.noticef("Find call flow: %s staus: %s", to, tostring(call_flow_status))
- presence_in.turn_lamp(call_flow_status == "false", to, call_flow_uuid)
- else
- log.warningf("Can not find call flow: %s", to)
- end
- else
- log.noticef("%s UNSUBSCRIBE from %s", from, to)
- end
-end
-
-protocols.dnd = function(event)
- local from, to = event:getHeader('from'), event:getHeader('to')
- local expires = tonumber(event:getHeader('expires'))
- if expires and expires > 0 then
- local proto, user = split_first(to, '+', true)
- user = user or proto
- local dnd_status = find_dnd(user)
- if dnd_status then
- log.noticef("Find DND: %s staus: %s", to, tostring(dnd_status))
- presence_in.turn_lamp(dnd_status == "true", to)
- else
- log.warningf("Can not find DND: %s", to)
- end
- else
- log.noticef("%s UNSUBSCRIBE from %s", from, to)
- end
-end
-
--- FS receive SUBSCRIBE to BLF from device
-events:bind("PRESENCE_PROBE", function(self, name, event)
- local proto = event:getHeader('proto')
- local handler = proto and protocols[proto]
- if not handler then return end
- return handler(event)
-end)
-
-log.notice("start")
-
-events:run()
-
-log.notice("stop")
diff --git a/resources/install/scripts/call_forward.lua b/resources/install/scripts/call_forward.lua
index 3535218d5e..f8307321b8 100644
--- a/resources/install/scripts/call_forward.lua
+++ b/resources/install/scripts/call_forward.lua
@@ -44,6 +44,7 @@
local Database = require "resources.functions.database"
local Settings = require "resources.functions.lazy_settings"
local route_to_bridge = require "resources.functions.route_to_bridge"
+ local blf = require "resources.functions.blf"
--include json library
local json
@@ -69,6 +70,7 @@
local domain_name = session:getVariable("domain_name");
local extension_uuid = session:getVariable("extension_uuid");
local request_id = session:getVariable("request_id");
+ local forward_all_destination = session:getVariable("forward_all_destination") or '';
local extension, dial_string
--set the sounds path for the language, dialect and voice
@@ -144,14 +146,24 @@
local number_alias = row.number_alias or '';
local accountcode = row.accountcode;
local forward_all_enabled = row.forward_all_enabled;
- local forward_all_destination = row.forward_all_destination;
+ local last_forward_all_destination = row.forward_all_destination;
local follow_me_uuid = row.follow_me_uuid;
local toll_allow = row.toll_allow or '';
local forward_caller_id_uuid = row.forward_caller_id_uuid;
--toggle enabled
if enabled == "toggle" then
- enabled = (forward_all_enabled == "true") and "false" or "true";
+ -- if we toggle CF and specify new destination number then just enable it
+ if (#forward_all_destination == 0) or (forward_all_destination == row.forward_all_destination) then
+ enabled = (forward_all_enabled == "true") and "false" or "true";
+ else
+ enabled = 'true'
+ end
+ end
+
+-- get destination number form database if it not provided
+ if enabled == 'true' and #forward_all_enabled == 0 then
+ forward_all_destination = row.forward_all_destination
end
if not session:ready() then return end
@@ -373,3 +385,12 @@
--end the call
session:hangup();
end
+
+-- BLF for display CF status
+ blf.forward(enabled == 'true', extension, number_alias,
+ last_forward_all_destination, forward_all_destination, domain_name)
+
+-- turn off DND BLF
+ if enabled == 'true' then
+ blf.dnd(false, extension, number_alias, domain_name)
+ end
diff --git a/resources/install/scripts/do_not_disturb.lua b/resources/install/scripts/do_not_disturb.lua
index 2e64a56d20..b2ca95dc9c 100644
--- a/resources/install/scripts/do_not_disturb.lua
+++ b/resources/install/scripts/do_not_disturb.lua
@@ -43,7 +43,7 @@
--include config.lua
require "resources.functions.config";
- local presence_in = require "resources.functions.presence_in"
+ local blf = require "resources.functions.blf"
--check if the session is ready
if ( session:ready() ) then
@@ -96,6 +96,8 @@
accountcode = row.accountcode;
follow_me_uuid = row.follow_me_uuid;
do_not_disturb = row.do_not_disturb;
+ forward_all_destination = row.forward_all_destination
+ forward_all_enabled = row.forward_all_enabled
if toggle then
enabled = (do_not_disturb == 'true') and 'false' or 'true'
end
@@ -154,11 +156,11 @@
if (enabled == "true") then
sql = sql .. "dial_string = :dial_string, ";
sql = sql .. "do_not_disturb = 'true', ";
+ sql = sql .. "forward_all_enabled = 'false' ";
else
sql = sql .. "dial_string = null, ";
- sql = sql .. "do_not_disturb = 'false', ";
+ sql = sql .. "do_not_disturb = 'false' ";
end
- sql = sql .. "forward_all_enabled = 'false' ";
sql = sql .. "where domain_uuid = :domain_uuid ";
sql = sql .. "and extension_uuid = :extension_uuid ";
local params = {dial_string = dial_string, domain_uuid = domain_uuid, extension_uuid = extension_uuid};
@@ -217,13 +219,12 @@
session:hangup();
-- BLF for display DND status
- local function dnd_blf(enabled, id, domain)
- local user = string.format('dnd+%s@%s', id, domain)
- presence_in.turn_lamp(enabled, user)
- end
+ blf.dnd(enabled == "true", extension, number_alias, domain_name)
- dnd_blf(enabled == "true", extension, domain_name)
- if number_alias and #number_alias > 0 then
- dnd_blf(enabled == "true", number_alias, domain_name)
+ -- Turn off BLF for call forward
+ if forward_all_enabled == 'true' and enabled == 'true' then
+ blf.forward(false, extension, number_alias,
+ forward_all_destination, nil, domain_name
+ )
end
end
diff --git a/resources/install/scripts/resources/functions/basic_event_service.lua b/resources/install/scripts/resources/functions/basic_event_service.lua
new file mode 100644
index 0000000000..3d0a552e3b
--- /dev/null
+++ b/resources/install/scripts/resources/functions/basic_event_service.lua
@@ -0,0 +1,60 @@
+require "resources.functions.config"
+
+local EventConsumer = require "resources.functions.event_consumer".EventConsumer
+
+local function class(base)
+ local t = base and setmetatable({}, base) or {}
+ t.__index = t
+ t.__class = t
+ t.__base = base
+
+ function t.new(...)
+ local o = setmetatable({}, t)
+ if o.__init then
+ if t == ... then -- we call as Class:new()
+ return o:__init(select(2, ...))
+ else -- we call as Class.new()
+ return o:__init(...)
+ end
+ end
+ return o
+ end
+
+ return t
+end
+
+local BasicEventService = class(EventConsumer) do
+
+function BasicEventService:__init(log, service_name, timeout)
+ local pid_file = scripts_dir .. "/run/" .. service_name .. ".tmp"
+
+ self = BasicEventService.__base.__init(self, pid_file, timeout)
+
+ -- FS shutdown
+ self:bind("SHUTDOWN", function(self, name, event)
+ log.notice("shutdown")
+ return self:stop()
+ end)
+
+ -- Control commands from FusionPBX
+ self:bind("CUSTOM::fusion::service::control", function(self, name, event)
+ if service_name ~= event:getHeader('service-name') then return end
+
+ local command = event:getHeader('service-command')
+ if command == "stop" then
+ log.notice("get stop command")
+ return self:stop()
+ end
+
+ log.warningf('Unknown service command: %s', command or '')
+ end)
+
+ return self
+end
+
+end
+
+return {
+ BasicEventService = BasicEventService;
+ new = BasicEventService.new;
+}
\ No newline at end of file
diff --git a/resources/install/scripts/resources/functions/blf.lua b/resources/install/scripts/resources/functions/blf.lua
new file mode 100644
index 0000000000..b38b2405d4
--- /dev/null
+++ b/resources/install/scripts/resources/functions/blf.lua
@@ -0,0 +1,46 @@
+local presence_in = require "resources.functions.presence_in"
+
+local function blf(enabled, proto, id, domain)
+ local user = string.format('%s+%s@%s', proto, id, domain)
+ presence_in.turn_lamp(enabled, user)
+end
+
+local function dnd(enabled, extension, number_alias, domain)
+ blf(enabled, 'dnd', extension, domain)
+ if number_alias and #number_alias > 0 then
+ blf(enabled, 'dnd', number_alias, domain)
+ end
+end
+
+local function forward(enabled, extension, number_alias, number, domain)
+ if number then
+ extension = extension .. '/' .. number
+ if number_alias and #number_alias > 0 then
+ number_alias = number_alias .. '/' .. number
+ end
+ end
+ blf(enabled, 'forward', extension, domain)
+ if number_alias and #number_alias > 0 then
+ blf(enabled, 'forward', number_alias, domain)
+ end
+end
+
+local function forward_toggle(enabled, extension, number_alias, old_number, new_number, domain)
+ -- turn off previews BLF number
+ if old_number and #old_number > 0 and old_number ~= new_number then
+ forward(false, extension, number_alias, old_number, domain)
+ end
+
+ -- set common BLF status
+ forward(enabled, extension, number_alias, nil, domain)
+
+ -- set destination specifc status
+ if new_number and #new_number > 0 then
+ forward(enabled, extension, number_alias, new_number, domain)
+ end
+end
+
+return {
+ dnd = dnd;
+ forward = forward_toggle;
+}
diff --git a/resources/templates/conf/autoload_configs/lua.conf.xml b/resources/templates/conf/autoload_configs/lua.conf.xml
index a63de3ffee..4225ff6d2c 100644
--- a/resources/templates/conf/autoload_configs/lua.conf.xml
+++ b/resources/templates/conf/autoload_configs/lua.conf.xml
@@ -39,8 +39,14 @@
1 - Monitor - ignore SUBSCRIBE and just send NOTIFY each X seconds
2 - Event handler - handle each SUBSCRIBE request
-->
-
+
+
+
+
+
+
+