<% -- 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 } 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 } -- Assuming that services will not be nil services = { callhistoryenable = boolean callwaitingenable = boolean forwarding = boolean hotlinedestination = string hotlineenable = boolean speeddialenable = boolean } --]] %> <% --TODO: Do we want to enable locking? %> <% --phoneLock.enabled="1" %> <% --feature.autoLocalHold="1" -- trying default for now%> feature.callPark.enabled="1" feature.directedCallPickup.enabled="1" feature.enhancedFeatureKeys.enabled="1" feature.groupCallPickup.enabled="1" feature.messaging.enabled="1" <% -- Management of buddies, and own status %> feature.presence.enabled="1" <% -- Run-time downloading of ringers %> feature.ringDownload.enabled="1" <% --- From sip-interop.cfg %> <% -- Allow user to set Do Not Disturb (DND) per-registration %> call.donotdisturb.perReg="1" <% -- When a conference is put on hold, other parties continue to talk %> call.localConferenceCallHold="1" <% -- Disallow transfers during the proceeding state of a consultation call %> voIpProt.SIP.allowTransferOnProceeding="0" <% -- TODO needed???%> <% --voIpProt.SIP.CID.sourcePreference="" %> <% -- Send 486 (SIP Busy Here) when 'Reject' is pressed during a ringing call %> voIpProt.SIP.use486forReject="1" <% -- Set phone's requested registration period in seconds %> voIpProt.server.1.expires="60" voIpProt.server.2.expires="60" <% --- From site.cfg %> <% -- Allow the use of device.xxx options (Admin Guide A-30) %> device.set="1" <% -- Override default user password of '123' see Admin Guide 4-103 %> <% -- only used for phone locking and to protect redundant 'Reboot' option %> device.auth.localUserPassword="" device.auth.localUserPassword.set="1" <% -- Attempt to determine VLAN ID and negotiate power through LLDP %> device.net.lldpEnabled="1" <% -- Apply option configured in device.net.lldpEnabled (Admin Guide A-30) %> device.net.lldpEnabled.set="1" <% -- Automatic periodic polling of provisioning server for upgrades %> prov.polling.enabled="1" <% -- Polling time of day hh:mm. %> prov.polling.time="02:00" <% -- Do not reject RTP packets arriving from a non-SDP-negotiated IP address %> <% -- Needed for some ATAs that do provide bad SDP in transfers to MOH %> tcpIpApp.port.rtp.filterByIp="0" <% -- Reject RTP packets arriving from a non-SDP-negotiated port %> <% -- To provide some security despite disabling filterByIp above.t %> tcpIpApp.port.rtp.filterByPort="1" <% -- Headset preferred over speakerphone after first use, until disabled %> up.headsetMode="1" <% -- Intensity of LCD backlight when phone is idle. 0 = off. %> up.backlight.idleIntensity="0" <% -- Receive volume of handset remembered between calls %> voice.volume.persist.handset="1" <% -- Receive volume of headset remembered between calls %> voice.volume.persist.headset="1" <% local values = ... %> <% local function xml_attr (t, v) if v ~= nil then -- v could be a string, boolean, or a number io.write(table.concat(t, '.') .. '="' .. tostring(v) .. '"\n') end end %> <% 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' }, values.device.digitmap) 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 -- 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' -- we can assume that values.device is not nil -- since values.device.template is this file if values.device.sntpserver then xml_attr({ 'tcpIpApp.sntp.address' }, values.device.sntpserver) end -- Parse time zone variable 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 = {} enable.forwarding = false enable.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.callList.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 then enable.hotline = true end -- set local contact directory to be readonly or readwrite xml_attr({ 'dir.local.readonly' }, values.services.speeddialenable) 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) -- 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) xml_attr({ 'reg', num, 'fwd.noanswer.ringCount' }, '3') -- set time in seconds before diversion -- (this option sets the ringCount when forwarding is disabled) xml_attr({ 'divert.noanswer', num, 'timeout' }, '20') -- 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 %> /> <% -- DEBUGGING --require("session") --local log, err = io.open("/root/polycom-template.log", "a") --log:write(session.serialize("values", values)) %>