[freeside-commits] branch FREESIDE_4_BRANCH updated. f4d3ad765d2309020bed99ef25a4916b8c63ba07

Mitch Jackson mitch at freeside.biz
Fri Feb 2 14:50:29 PST 2018


The branch, FREESIDE_4_BRANCH has been updated
       via  f4d3ad765d2309020bed99ef25a4916b8c63ba07 (commit)
       via  f2d06c14cb92b2ec00147dbdaf73d6cf0d70d85f (commit)
      from  fe2598be4bbc940f69797334e3d5f848af55db1b (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit f4d3ad765d2309020bed99ef25a4916b8c63ba07
Author: Mitch Jackson <mitch at freeside.biz>
Date:   Fri Feb 2 22:48:12 2018 +0000

    RT# 78952 CDR Import for Acme Packet Improved caller-id parsing

diff --git a/FS/FS/cdr/acmepacket.pm b/FS/FS/cdr/acmepacket.pm
index e0e80cdd6..1f00e4086 100644
--- a/FS/FS/cdr/acmepacket.pm
+++ b/FS/FS/cdr/acmepacket.pm
@@ -130,17 +130,28 @@ our %info = (
     # clid, dst, src CDR field formatted as one of the following:
     #   'WIRELESS CALLER'<sip:12513001300 at 4.2.2.2:5060;user=phone>;tag=SDepng302
     #   <sip:12513001300 at 4.2.2.2:5060;user=phone>;tag=SDepng302
+    #   '12513001300'<sip:4.2.2.2:5060;user=phone>;tag=SDepng302
 
     # clid
     $out[0] = $out[0] =~ /^\'(.+)\'/ ? $1 : "";
 
     # src, dst
-    # All of the sample data given shows sip connections.  In case the same
-    # switch is hooked into another circuit type in the future, we'll just
-    # tease out a length 7+ number not contained in the caller-id-text field
+    # Use the 7+ digit number as the src/dst phone number.
+    # Prefer using the number within <sip> label.  If there is not one,
+    # allow using number from caller-id text field.
     for (1,2) {
+      my $f = $out[$_];
       $out[$_] =~ s/^\'.+\'//g; # strip caller id label portion
-      $out[$_] = $out[$_] =~ /(\d{7,})/ ? $1 : undef;
+      if ($out[$_] =~ /(\d{7,})/) {
+        # Using number from <sip>
+        $out[$_] = $1;
+      } elsif ($f =~ /(\d{7,})/) {
+        # Using number from caller-id text
+        $out[$_] = $1;
+      } else {
+        # No phone number, perhaps an IP only call
+        $out[$_] = undef;
+      }
     }
 
     if ($DEBUG) {

commit f2d06c14cb92b2ec00147dbdaf73d6cf0d70d85f
Author: Mitch Jackson <mitch at freeside.biz>
Date:   Fri Feb 2 01:31:50 2018 -0600

    RT# 78592 CDR Import for Acme Packet VOIP Switches

diff --git a/FS/FS/cdr.pm b/FS/FS/cdr.pm
index c4e9c47a3..331ac0f2f 100644
--- a/FS/FS/cdr.pm
+++ b/FS/FS/cdr.pm
@@ -1733,6 +1733,14 @@ sub _cdr_date_parse {
     # Telos 2014-10-10T05:30:33Z
     ($year, $mon, $day, $hour, $min, $sec) = ( $1, $2, $3, $4, $5, $6 );
     $options{gmt} = 1;
+  } elsif ( $date =~ /^(\d+):(\d+):(\d+)\.\d+ \w+ (\w+) (\d+) (\d+)$/ ) {
+    ($hour, $min, $sec, $mon, $day, $year) = ( $1, $2, $3, $4, $5, $6 );
+    $mon = { # Acme Packet: 15:54:56.868 PST DEC 18 2017
+      # My best guess of month abbv they may use
+      JAN => '01', FEB => '02', MAR => '03', APR => '04',
+      MAY => '05', JUN => '06', JUL => '07', AUG => '08',
+      SEP => '09', OCT => '10', NOV => '11', DEC => '12'
+    }->{$mon};
   } else {
      die "unparsable date: $date"; #maybe we shouldn't die...
   }
@@ -1932,4 +1940,3 @@ L<FS::Record>, schema.html from the base documentation.
 =cut
 
 1;
-
diff --git a/FS/FS/cdr/acmepacket.pm b/FS/FS/cdr/acmepacket.pm
new file mode 100644
index 000000000..e0e80cdd6
--- /dev/null
+++ b/FS/FS/cdr/acmepacket.pm
@@ -0,0 +1,157 @@
+package FS::cdr::acmepacket;
+
+=head1 NAME
+
+FS:cdr::acmepacket - CDR import definition based on Acme Packet Net-Net 4000
+
+=head1 DESCRIPTION
+
+The Acme Packet NetNet 4000 S-CX6.4.0 generates an odd cdr log format:
+
+ - Each row in the CSV may be in one of many various formats, some of
+   them undocumented.
+ - Columns are inconsistently enclosed with " characters
+ - Quoted column values may, themselves, contain unescaped quote marks.
+   This breaks Text::CSV (well technically the FORMAT is broken, not
+   Text::CSV).
+ - A single call can generate multiple CDR records.  The only records we're
+   interested in are billable calls:
+   - These are called "Stop Record CSV Placement" in Acme Packet documentation
+   - These will always contain a "2" as the first column value
+   - These rows may be 175 or 269 fields in length.  It's unclear if the
+     undocumented 269 column rows are an intentional Acme Packet format, or
+     a bug in their switch.  The extra columns are inserted at idx 115,
+     and can safely be disregarded.
+
+NOTE ON DATE PARSING:
+
+  The Acme Packet manual doesn't describe it's date format in detail.  The sample
+  we were given contains only records from December.  Dates are formatted like
+  so: 15:54:56.868 PST DEC 18 2017
+
+  I gave my best guess how they will format the month text in the parser
+  FS::cdr::_cdr_date_parse().  If this format doesn't import records on a
+  particular month, check there.
+
+=cut
+
+use strict;
+use warnings;
+use vars qw(%info);
+use base qw(FS::cdr);
+use FS::cdr qw(_cdr_date_parse);
+use Text::CSV;
+
+my $DEBUG = 0;
+
+my $cbcsv = Text::CSV->new({binary => 1})
+  or die "Error loading Text::CSV - ".Text::CSV->error_diag();
+
+# Used to map source format into the contrived format created for import_fields
+# $cdr_premap[ IMPORT_FIELDS_IDX ] = SOURCE_FORMAT_IDX
+my @cdr_premap = (
+  9,  # clid
+  9,  # src
+  10, # dst
+  22, # channel
+  21, # dstchannel
+  26, # src_ip_addr
+  28, # dst_ip_addr
+  13, # startdate
+  14, # answerdate
+  15, # enddate
+  12, # duration
+  12, # billsec
+  3,  # userfield
+);
+
+our %info = (
+  name   => 'Acme Packet',
+  weight => 600,
+  header => 0,
+  type   => 'csv',
+
+  import_fields => [
+    # freeside      # [idx] acmepacket
+    'clid',         # 9  Calling-Station-Id
+    'src',          # 9  Calling-Station-Id
+    'dst',          # 10 Called-Station-Id
+    'channel',      # 22 Acme-Session-Ingress-Realm
+    'dstchannel',   # 23 Acme-Session-Egress-Realm
+    'src_ip_addr',  # 26 Acme-Flow-In-Src-Adr_FS1_f
+    'dst_ip_addr',  # 28 Acme-Flow-In-Dst-Addr_FS1_f
+    'startdate',    # 13 h323-setup-time
+    'answerdate',   # 14 h323-connect-time
+    'enddate',      # 15 h323-disconnect-time
+    'duration',     # 12 Acct-Session-Time
+    'billsec',      # 12 Acct-Session-Time
+    'userfield',    # 3 Acct-Session-Id
+  ],
+
+  row_callback => sub {
+    my $line = shift;
+
+    # Only process records whose first column contains a 2
+    return undef unless $line =~ /^2\,/;
+
+    # Replace unescaped quote characters within quote-enclosed text cols
+    $line =~ s/(?<!\,)\"(?!\,)/\'/g;
+
+    unless( $cbcsv->parse($line) ) {
+      warn "Text::CSV Error parsing Acme Packet CDR: ".$cbcsv->error_diag();
+      return undef;
+    }
+
+    my @row = $cbcsv->fields();
+    if (@row == 269) {
+      # Splice out the extra columns
+      @row = (@row[0..114], @row[209.. at row-1]);
+    } elsif (@row != 175) {
+      warn "Unknown row format parsing Acme Packet CDR";
+      return undef;
+    }
+
+    my @out = map{ $row[$_] } @cdr_premap;
+
+    if ($DEBUG) {
+      warn "~~~~~~~~~~pre-processed~~~~~~~~~~~~~~~~ \n";
+      warn "$_ $out[$_] \n" for (0.. at out-1);
+    }
+
+    # answerdate, enddate, startdate
+    for (7,8,9) {
+      $out[$_] = _cdr_date_parse($out[$_]);
+      if ($out[$_] =~ /\D/) {
+        warn "Unparsable date in Acme Packet CDR: ($out[$_])";
+        return undef;
+      }
+    }
+
+    # clid, dst, src CDR field formatted as one of the following:
+    #   'WIRELESS CALLER'<sip:12513001300 at 4.2.2.2:5060;user=phone>;tag=SDepng302
+    #   <sip:12513001300 at 4.2.2.2:5060;user=phone>;tag=SDepng302
+
+    # clid
+    $out[0] = $out[0] =~ /^\'(.+)\'/ ? $1 : "";
+
+    # src, dst
+    # All of the sample data given shows sip connections.  In case the same
+    # switch is hooked into another circuit type in the future, we'll just
+    # tease out a length 7+ number not contained in the caller-id-text field
+    for (1,2) {
+      $out[$_] =~ s/^\'.+\'//g; # strip caller id label portion
+      $out[$_] = $out[$_] =~ /(\d{7,})/ ? $1 : undef;
+    }
+
+    if ($DEBUG) {
+      warn "~~~~~~~~~~post-processed~~~~~~~~~~~~~~~~ \n";
+      warn "$_ $out[$_] \n" for (0.. at out-1);
+    }
+
+    # I haven't seen commas in sample data text fields.  Extra caution,
+    # mangle commas into periods as we pass back to importer
+    join ',', map{ $_ =~ s/\,/\./g; $_ } @out;
+  },
+);
+
+1;

-----------------------------------------------------------------------

Summary of changes:
 FS/FS/cdr.pm            |   9 ++-
 FS/FS/cdr/acmepacket.pm | 168 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 176 insertions(+), 1 deletion(-)
 create mode 100644 FS/FS/cdr/acmepacket.pm




More information about the freeside-commits mailing list