<% -- Polycom Configuration File Template -- We use single quotes to avoid escaping XML's double quotes -- It is important that the first line be the XML declaration --[[ Implemented parameters: values = { device = { adminpassword digitmap digitmaptimeout homepage musiconhold pcportenable registrar sntpserver timezone urldialingenable militarytimeenable displaylang } regX (where X is a number 1-34) = { extension = EXTEN password = string forwardall = EXTEN forwardallenable = boolean forwardbusy = EXTEN (allow URI?) forwardbusyenable = boolean forwardnoanswer = EXTEN forwardnoanswerenable = boolean polycomringtone = select callwaitingenable = boolean scaenable = boolean } -- Assuming that services will not be nil services = { callhistoryenable = boolean callwaitingenable = boolean forwarding = boolean hotlinedestination = string hotlineenable = boolean mailbox = string mailcallback = string speeddialenable = boolean provpollingtime = string dndenable = boolean softkey1 = boolean softkey2 = boolean softkey3 = boolean softkey4 = boolean softkey5 = boolean softkey6 = boolean softkey7 = boolean softkey8 = boolean softkey9 = boolean softkey10 = boolean } --]] %> device.set="1" <% local values = ... %> <% local function xml_attr (t, v) if v ~= nil then -- Check for -0, which is invalid for Polycom but fine for Lua if (v == 0) then v = "0" end -- v could be a string, boolean, or a number io.write(table.concat(t, '.') .. '="' .. tostring(v) .. '"\n') end end %> <% -- we can assume that values.device is not nil since values.device.template is this file xml_attr({ 'voIpProt.server.1.address' }, values.device.registrar) xml_attr({ 'mb.main.home' }, values.device.homepage) xml_attr({ 'voIpProt.SIP.musicOnHold.uri' }, values.device.musiconhold) xml_attr({ 'dialplan.digitmap.timeOut' }, values.device.digitmaptimeout) xml_attr({ 'feature.urlDialing.enabled' }, values.device.urldialingenable) if not values.device.pcportenable then -- set mode to '-1' which disables it xml_attr({ 'device.net.etherModePC' }, '-1') -- apply settings in 'device' parameter above xml_attr({ 'device.net.etherModePC.set' }, '1') end -- Enable 24-hour Clock Mode if values.device.militarytimeenable then xml_attr({'lcl.datetime.time.24HourClock'}, true) for langid=19,1,-1 do xml_attr({'lcl.ml.lang.clock.'..langid..'.24HourClock'}, true) end else xml_attr({'lcl.datetime.time.24HourClock'}, false) for langid=19,1,-1 do xml_attr({'lcl.ml.lang.clock.'..langid..'.24HourClock'}, false) end end -- Set the Display screen language if values.device.displaylang then xml_attr({'lcl.ml.lang'}, values.device.displaylang) end -- Override the default admin password of '456' if values.device.adminpassword then xml_attr({ 'device.auth.localAdminPassword' }, values.device.adminpassword) xml_attr({ 'device.auth.localAdminPassword.set' }, true) end -- Handle SNTP and Time Zone parameters -- See http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html -- TZ variable, with no leading colon -- Syntax: stdoffset[dst[offset][,start[/time],end[/time]]] -- Examples: 'GMT0' 'EST5EDT,M3.2.0,M11.1.0' '5' if values.device.sntpserver then xml_attr({ 'tcpIpApp.sntp.address' }, values.device.sntpserver) end -- Parse time zone variable posixtz = require('posixtz') local tz = posixtz.parse(values.device.timezone) if tz then -- convert POSIX sign (W of GMT is '+') to Polycom (E of GMT is '+') xml_attr({'tcpIpApp.sntp.gmtOffset'}, -1 * tz.offset.total) local function dstrule ( pos ) local dstprefix = 'tcpIpApp.sntp.daylightSavings' local t = tz.dst[pos] -- Handle explicit hour for DST change -- (Polycom doesn't implement explicit min or sec) -- (Polycom DST implementation assumes DST change is 1 hour) if t.hour then xml_attr({ dstprefix, pos, 'time' }, t.hour) end if t.day then -- there may be two of next line, Polycom uses first xml_attr({ dstprefix, 'fixedDayEnable' }, true) xml_attr({ dstprefix, pos, 'month' }, t.month) xml_attr({ dstprefix, pos, 'date' }, t.day) else -- there may be two of next line, Polycom uses first xml_attr({ dstprefix, 'fixedDayEnable' }, false) xml_attr({ dstprefix, pos, 'month' }, t.month) -- POSIX weekday is between 0 (Sun) and 6 (Sat) -- Polycom dayOfWeek is 1=Sun, 7=Sat xml_attr({ dstprefix, pos, 'dayOfWeek' }, tonumber(t.weekday) + 1) -- POSIX week from 1 to 5, where 1st,2nd..4th, and 5=last if t.week == '5' then xml_attr({ dstprefix, pos, 'dayOfWeek.lastInMonth' }, true) else -- Polycom uses 1, 8, 15, 22 for 1st, 2nd... 4th local d = 7 * ( tonumber(t.week) - 1 ) + 1 xml_attr({ dstprefix, pos, 'date' }, d) end end end if tz.dst then xml_attr({'tcpIpApp.sntp.daylightSavings.enable'}, true) dstrule('start') dstrule('stop') else xml_attr({'tcpIpApp.sntp.daylightSavings.enable'}, false) end end -- Check 'services' params local enable = {forwarding = false, hotline = false} if values.services then -- set variables so that we don't have to test values.services again if not values.services.callhistoryenable then xml_attr({ 'feature.callListPlaced.enabled' }, '0') end if not values.services.callwaitingenable then -- only allow one call per line key xml_attr({ 'call.callsPerLineKey' }, '1' ) end if values.services.forwarding then enable.forwarding = true end if values.services.hotlineenable and values.services.hotlinedestination then enable.hotline = true -- Set phone to replace any dialed digits with the hotline destination instead xml_attr({ 'dialplan.digitmap' }, 'R[#*0123456789].R'..values.services.hotlinedestination..'R') xml_attr({ 'dialplan.applyToUserDial' }, '1') xml_attr({ 'dialplan.applyToUserSend' }, '1') else xml_attr({ 'dialplan.digitmap' }, values.device.digitmap) end if values.services.mailbox then xml_attr({ 'msg.mwi.1.subscribe' }, values.services.mailbox) xml_attr({ 'msg.mwi.1.callBackMode' }, "contact") if values.services.mailcallback and values.services.mailcallback ~= "" then xml_attr({ 'msg.mwi.1.callBack' }, values.services.mailcallback) else xml_attr({ 'msg.mwi.1.callBack' }, string.gsub(values.services.mailbox, "@.*", "")) end end -- set local contact directory to be readonly or readwrite if not values.services.speeddialenable then xml_attr({ 'dir.local.contacts.maxNum' }, 0) end -- Set Provisioning Polling to enable as random starting at the time configured in the provpollingtime param and stopping 59 minutes later if values.services.provpollingtime then xml_attr({ 'prov.polling.enabled' }, 1) xml_attr({ 'prov.polling.mode' }, "random") xml_attr({ 'prov.polling.time' }, values.services.provpollingtime) xml_attr({ 'prov.polling.timeRandomEnd' }, string.gsub(values.services.provpollingtime, "(%d%d):(%d%d)", "%1:59")) end -- Set DND on the server-side only, the phone does not perform local DND if not values.services.dndenable then xml_attr({ 'voIpProt.SIP.serverFeatureControl.dnd' }, '1') xml_attr({ 'voIpProt.SIP.serverFeatureControl.localProcessing.dnd' }, '0') -- For VVXs DND soft key does not display and the option is removed from the phone menu system at Menu > Settings > Features xml_attr({ 'feature.doNotDisturb.enable' }, '0') end -- Loop through Services Parameter Groups looking for 'softkeyX' params for sfkey,sfkey_v in pairs(values.services) do local sknum = string.match(sfkey, 'softkey(%d+)') if sknum then if sfkey_v then -- Set this softkey to enable xml_attr({ 'softkey', sknum, 'enable' }, '1') else -- Set this softkey to disable xml_attr({ 'softkey', sknum, 'enable' }, '0') end end end end -- Loop through Parameter Groups looking for 'reg' params for pg, pg_t in pairs(values) do -- Is it of the form regX ? local num = string.match(pg, 'reg(%d+)') if num then -- set Hotline on all possible registrations if it is configured if enable.hotline then local d = values.services.hotlinedestination if d then xml_attr({ 'call.autoOffHook', num, 'enabled' }, '1') xml_attr({ 'call.autoOffHook', num, 'protocol' }, 'SIP') xml_attr({ 'call.autoOffHook', num, 'contact' }, d) end end -- user part of From URI xml_attr({ 'reg', num, 'address' }, pg_t.extension) -- SIP authentication parameters xml_attr({ 'reg', num, 'auth.userId' }, pg_t.extension) xml_attr({ 'reg', num, 'auth.password' }, pg_t.password) -- Caller ID string xml_attr({ 'reg', num, 'displayName' }, pg_t.callerid) -- Ringtone if pg_t.polycomringtone then xml_attr({ 'reg', num, 'ringType'}, 'ringer'..pg_t.polycomringtone) end -- Only allow one call in this line key if not pg_t.callwaitingenable then xml_attr({ 'reg', num, 'callsPerLineKey'}, '1' ) end -- Configure Shared Call Appearance for this line if pg_t.scaenable then xml_attr({ 'reg', num, 'type'}, 'shared') end -- From Admin_Guide_UCS_v3.3.0: -- "The phone has a flexible call forward/diversion feature for each registration. In all cases, a call will only be diverted if a non-Null contact has been configured." if enable.forwarding then -- Although not documented, -- Polycom phones send special options for -- 'forward all calls', namely: -- reg.x.fwdContact and reg.x.fwdStatus -- set forwardall as defined xml_attr({ 'reg', num, 'fwdStatus' }, pg_t.forwardallenable) xml_attr({ 'reg', num, 'fwdContact' }, pg_t.forwardall) -- set forwardnoanswer as defined xml_attr({ 'reg', num, 'fwd.noanswer.status' }, pg_t.forwardnoanswerenable) xml_attr({ 'reg', num, 'fwd.noanswer.contact' }, pg_t.forwardnoanswer) -- we do not use 'divert.noanswer.x.timeout', -- because it limits maximum rings *even when* forward-on-noanswer disabled -- set forwardbusy on DND and on busy, as defined xml_attr({ 'reg', num, 'fwd.busy.status' }, pg_t.forwardbusyenable) xml_attr({ 'divert.dnd', num, 'enabled' }, pg_t.forwardbusyenable) xml_attr({ 'reg', num, 'fwd.busy.contact' }, pg_t.forwardbusy) xml_attr({ 'divert.dnd', num, 'contact' }, pg_t.forwardbusy) else -- forwarding is not enabled -- disable the soft-key menu for forwarding xml_attr({ 'divert.fwd', num, 'enabled' }, '0') end end end %> />