mellowtigger: (penguin coder)
[personal profile] mellowtigger
phone operatorThe more I learn about phone system technology, the more I wonder how anything ever works (successfully).

Among the hodge-podge of responsibilities I have at my job, I also manage 6 PBX phone systems of the Mitel / Intertel CS-5000 family. Thanks to a useful hint that my boss found in a Perl script via Google, I was able to establish phone system logging using Powershell. My programming will save us over $10,000 that we would have been charged by our vendor. That's half my annual salary, so I've earned my keep for a while. :)

I've redacted some of the details from my code for security reasons, but I wanted to make the source code public so it's easier for the next person to find useful material through a web search engine.

# log-smdr.ps1
# This Powershell script connects to a Mitel/Intertel CS-5000 series phone system, 
# directs it to open its SMDR stream, then logs the results to a text file.
# Station Message Detail Recording (SMDR) is a system feature that provides 
# a detailed record of outgoing and incoming calls.
# This script is intended to be restarted at midnight each night.

# Turning on SMDR reporting is a two-step process in DbStudio Session Manager.
# 1) System / Maintenance / SMDR, set "SMDR Output Active" to yes
#    ("Output Port" should already be set to "NONE")
# 2) System / Sockets / SMDR, set "Enable" to yes
#    (System / Cabinet / Sockets / SMDR, in some older systems)

# (example perl script)

param ([string]$site='needparm', [string]$logdir='C:\script\log\', [boolean]$debug=$false)

# convert $site parameter into ip/port combination
switch ($site) {
    'S1' { $ip=''; $port=4000 }
    'S2' { $ip=''; $port=4000 }
    'S3' { $ip=''; $port=4000 }
    default { $ip=''; $port=4000 }

# find a new filename for logging this session
$scriptps1 = $MyInvocation.MyCommand.Name
$scriptname = $scriptps1.substring(0,($scriptps1.length - 4))
$datelog = get-date -f 'yyyyMMdd'
$version = 0
do {
    $version += 1
    $filelog = $logdir + $scriptname + '.' + $datelog + '.' + $site + '.' + $version + '.txt'
} while (test-path $filelog)
set-content $filelog $null
if ($debug) {write-host 'logfile:' $filelog}

# create a tcp socket and a destination
# fyi, the TcpClient object did not work with SMDR (perhaps some default values interfered?)
# so I took it down a layer to the Socket object which works nicely
$sockfam  = [System.Net.Sockets.AddressFamily]::InterNetwork
$socktype = [System.Net.Sockets.SocketType]::Stream
$sockpro  = [System.Net.Sockets.ProtocolType]::TCP
$socket   = New-Object System.Net.Sockets.Socket $sockfam, $socktype, $sockpro
$ipaddr   = [System.Net.IpAddress]::Parse($ip)
$ipdest    = New-Object System.Net.IPEndPoint $ipaddr, $port

# establish the connection
if ($debug) {write-host 'connecting:' $ip ':' $port}
if ($socket.Connected -eq $false) {
    if ($debug) {write-host 'connection: FAILED'}
if ($debug) {write-host 'connection: OPEN'}

# send the SMDR command ASCII character string (no password)
#     2  	002	02	00000010	STX	Start of Text
#     0  	000	00	00000000	NUL	Null char
#     132	204	84	10000100	„	Double low-9 quotation mark
$cmd = @([byte]2,[byte]0,[byte]0,[byte]0,[byte]132,[byte]0)
if ($debug) {write-host 'connection: CMD SENT'}

# the socket's .Receive() will Block, causing the program to freeze until bytes are received,
# so set up a stream which provides the useful .DataAvailable property instead
# incoming records are always 86 bytes long
$bytes = new-object System.Byte[] 86
$stream = new-object System.Net.Sockets.NetworkStream($socket)

do {
    start-sleep -m 1000
    if ($stream.DataAvailable) {
        $socket.Receive($bytes) | out-null  # script hangs here until bytes are received
        $result = [System.Text.Encoding]::ASCII.GetString($bytes[0..84]) # ignore trailing CR/LF
        if ($debug) {write-host $result}
        add-content $filelog $result # append data to text log file
    $datetest = get-date -f 'yyyyMMdd'
} while ($datetest -eq $datelog)

if ($debug) {write-host 'connection: CLOSING'}
if ($debug) {write-host 'connection: CLOSED'}
$socket = $null
You turn on SMDR by using the DbStudio Session Manager software that comes with your PBX system. That application directory also contains \DiagMon\Diagmon.exe, a program that can also be used to monitor (but not log, that I can tell) SMDR output from your phone panels. I intend to use DiagMon with packet sniffing software to reverse engineer the protocol for handling password-enabled SMDR. It's really hard to come by programmer-focused PBX documentation. I even contacted Mitel, but they defer to local vendors who have a financial disincentive to provide such documentation. :(

Here's a redacted version of the debug output from this script:
connecting to : 4000
connection: OPEN
connection: CMD SENT
Q   Station Message Detailed Recording                          17:01:24 04-07-2012
R   NET 1234  P0001 94567                        17:11 00:03:34 $00.00
R   NET 1234  P0001 95678                        17:16 00:00:09 $00.00
R   NET 2345  P0001 96789                        17:21 00:00:14 $00.00
R   IN  3456  90001                              17:19 00:04:56 $00.00
My next project will take these .TXT log files, parse them, and store the data fields in a SQL Server table. Then I can do lots of fun stuff like calculate the average length of time that people are spending in our phone tree before they reach a live person, or determine if people are hanging up in frustration before reaching any person.
Anonymous( )Anonymous This account has disabled anonymous posting.
OpenID( )OpenID You can comment on this post while signed in with an account from many other sites, once you have confirmed your email address. Sign in using OpenID.
Account name:
If you don't have an account you can create one now.
HTML doesn't work in the subject.


If you are unable to use this captcha for any reason, please contact us by email at

Notice: This account is set to log the IP addresses of everyone who comments.
Links will be displayed as unclickable URLs to help prevent spam.


mellowtigger: (Default)

June 2017

1112 1314151617

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jun. 27th, 2017 12:22 pm
Powered by Dreamwidth Studios