HOWTO Setup an Asterisk Fax-Server with CAPI

From RADION OpenLAB

Jump to: navigation, search


Contents

[edit] Introduction

This currently is a work in progress and is aimed to be an easy yet comfortable solution for chan_capi users with ACTIVE ISDN Cards like Eicon Diva.

There are no Asterisk means to get the native Fax features of the card to work.

What we wanted to achieve was an easy way to use already existing HylaFax clients like WinPrint Hylafax to "print" faxes out of any application into the outgoing fax queue.

Receiving faxes is also covered to a certain extent but we would like enhance the inbound features as well.

First of all you'll need a running Asterisk of course.

[edit] Requirements

For this setup we have used the following :

  • Asterisk 1.2.18
  • Cytronics & Melware divas4linux-melware-3.0.9-107.775-1
  • Cytronics & Melware chan_capi-1.0.1
  • AFAXD 0.3.0-radion-chan-capi


AFAXD is a perl script that emulates the socket behaviour of Hylafax so that the whole available range of Hylafax clients can connect to AFAXD. The most convenient client from our point of view is WinPrint Hylafax which prints a PostScript file to AFAXD, along with the destination fax number and a notification email adress to send the fax-sent status report to.

[edit] Definitions

All scripts that are going to be executed will reside in /var/lib/asterisk/bin/
Incoming fax files are going to be stored in /var/spool/asterisk/fax/in/
Outgoing fax files will be stored in /var/spool/asterisk/fax/out/
The path to asterisk callfiles is /var/spool/asterisk/outgoing/

Asterisk itself is running as user asterisk with group asterisk. That is the recommended way of running asterisk. Make sure that all paths have the right permissions.

[edit] Receiving Faxes

Right now receiving faxes is limited to ONE email address but can easily be extended to query email addresses out of almost anything like flatfiles, databases, AD/LDAP or basically anything you can access with PHP based on the DID.

[edit] extensions.conf

We need some custom contexts in the dialplan to receive faxes:

 
[custom-answerfax]
exten => s,1,Set(FAXFILE=/var/spool/asterisk/fax/in/${UNIQUEID}.sff)
exten => s,2,capicommand(receivefax|${FAXFILE})
exten => s,3,Hangup()
exten => h,1,System(/var/lib/asterisk/bin/faxprocess.php "${UNIQUEID}" "${FAXID}" "${CALLERID(number)}" "${FAXPAGES}" "${FAXRATE}" "${FAXRESOLUTION}" "your@email.tld")


For FreePBX / TrixBox:

With freepbx/trixbox you now create a new inbound route with your desired Fax DID, Disable the Fax Extension and set the following Destination:

Custom App: custom-answerfax,s,1

For vanilla Asterisk:

If you're just using asterisk you'll need an inbound extension that calls the above context with extension s priority 1

[edit] faxprocess.php

As you may have noticed there is a script called faxprocess.php that is called by our previously defined context. The faxprocess.php script is a wrapper script for fax-process.pl

This is working but is nevertheless very ugly. Armin and I will try to move any code regarding this project from perl to PHP in order to simplify things.

It takes the parameters passed on by asterisk and converts the sff file to a tiff file in order for fax-process.pl to work.

 
#!/usr/local/bin/php
 
<?php
 
  $fpath                =               "/var/spool/asterisk/fax/in"                            ;
 
  $strFaxID             =               $argv[1]                                                ;
  $strSenderID          =               $argv[2]                                                ;
  $strCallerID          =               $argv[3]                                                ;
  $strEmail             =               $argv[7]                                                ;
  $intPage              =               $argv[4]                                                ;
  $intFRate             =               $argv[5]                                                ;
  $intFRes              =               $argv[6]                                                ;
 
  $strSenderID          = trim         ($strSenderID)." (".trim($strCallerID).")"          ;
 
  $strTifConvCmd        =               "/usr/bin/sfftobmp "
                        .               "-ft $fpath/$strFaxID.sff -o $fpath/$strFaxID.tif"      ;
 
  $strFProcCmd          =               "/var/lib/asterisk/bin/fax-process.pl "
                        .               "--file $fpath/$strFaxID.tif --senderid '$strSenderID' "
                        .               "--numpages $intPages --frate $intFRate --fres $intFRes "
                                        "--to $strEmail --attachment $strFaxID.pdf"             ;
 
  exec                                  ($strTifConvCmd)                                        ;
  exec                                  ($strFProcCmd)                                          ;
 
?>

[edit] Sending Faxes

To send Faxes we would like to use multiple possibilities. What follows only describes how to send faxes with AFAXD and a HylaFax Client like WinPrint Hylafax for the sake of user comfort.

If someone comes up with a great email2fax gateway solution which can be integrated easily in conjunction with the AFAXD setup any hint would be greatly appreciated.

[edit] Required Software

  • GhostScript >= 8.54
  • Perl >= 5.8.8
  • PHP >= 4.0

[edit] About ghostscript

In order to use sendfax from chan_capi one has to have SFF (structured fax format) files It seems that as of right now using ghostscript is the only way to convert postscript files to sff files. After testing almost every possible ghostscript parameter for almost 24 hours my PS to SFF conversion string looks a little bit different than it was originally in AFAXD. From my point of view it gives the best results:

Old convert string:

 
/usr/bin/gs -dNOPAUSE -dBATCH -sDEVICE=cfax -$resolution -sOutputFile$tiffFile $psFile

New convert string:

 
/usr/bin/gs -dSAFER -dNOPAUSE -dBATCH -sDEVICE=cfax -r204 -sPAPERSIZE=a4 -dTextAlphaBits=1 -sOutputFile=$tiffFile $psFile

[edit] AFAXD

Since AFAXD isn't aware of capicommand(sendfax) but was written by Jan Schneider (skyder on ip-phone-forum.de - the maintainer of AFAXD) for txfax and spandsp. The biggest issue is the difference in file format. AFAXD receives the PostScript file from Winprint-Hylafax and converts it to TIF. Since sendfax needs an SFF file AFAXD was tweaked to create SFF files instead of TIF.

Also, the callfile AFAXD generates to intiate the call doesn't do well in a chan_capi kind of setup.

The following downloadable package is a "patched" AFAXD that takes the above considerations into account and generates SFF files (instead of TIF) as well as altered callfiles.

IMPORTANT NOTE: Most problems with AFAXD occured due to wrong permissions. If your Asterisk is running as user asterisk make sure AFAXD is running as asterisk as well. Otherwise Asterisk ignored the callfiles.

[edit] Download

Aktuelle Version Homepage Download URL
afaxd-0.30-radion-chan-capi --- afaxd-0.30-radion-chan-capi.tar.bz2

[edit] Installation

Just unpack the package, for instance to /usr/local/src/

 
cd /usr/local/src/
wget http://openlab.radion.org/downloads/afaxd-0.30-radion-chan-capi.tar.bz2
tar xvjpf afaxd-0.30-radion-chan-capi.tar.bz2

[edit] Configuration

Before you start copying anything edit the packaged afaxd.conf from the package, and change the uncommented lines to your needs.


Have a look at hosts.afaxd (this file is basically the same as hosts.hfaxd which does all access controls on hylafax). If you need help with the Syntax have a look at the HylaFax documentation. Copy the hosts.afaxd to the place you defined in afaxd.conf.

[edit] extensions.conf

[custom-sendfax]
exten => s,1,Set(CALLERID(num)=9)
exten => s,2,Set(TIMESTART=${STRFTIME(${EPOCH},,%s)})
exten => s,3,capicommand(sendfax|${FAXFILE}|+49 89 45220589|${STRFTIME(${EPOCH},,%d.%m.%Y %H:%M:%S)}           +49 89 4522058-9             RADION Imaginery UMS)
exten => s,4,Hangup()
exten => h,1,System(/var/lib/asterisk/bin/faxsendstatus.php "${STATUSMAIL}" "${FAXSTATUS}" "${FAXREASON}" "${FAXREASONTEXT}" "${FAXRATE}" "${FAXRESOLUTION}" "${FAXPAGES}" "${FAXID}" "${FAXCID}" "{JOBID}" "${TIMESTART}")



[edit] faxsendstatus.php

#!/usr/local/bin/php
 
<?php
 
  global $GlobalCNF;
 
  include_once                                          ("anyfunc.inc.php")                                     ;
 
  $strStatusMail                =                       $argv[1]                                                ;
  $intFaxStatus                 =                       $argv[2]                                                ;
  $intErrCode                   =                       $argv[3]                                                ;
  $strErrDescr                  =                       $argv[4]                                                ;
  $intFaxRate                   =                       $argv[5]                                                ;
  $intFaxRes                    =                       $argv[6]                                                ;
  $intFaxPages                  =                       $argv[7]                                                ;
  $intFaxID                     = trim                  ($argv[8])                                              ;
  $strRecCallerID               =                       $argv[9]                                                ;
  $intJobID                     =                       $argv[10]                                               ;
  $TIMESTART                    =                       $argv[11]                                               ;
 
  /// Calculate sending time needed /////////////////////////////////////////////////////////////////////////////
 
  $TIMESTOP                     = mktime                ()                                                      ;
 
  $intCLen                      =                       $TIMESTOP-$TIMESTART                                    ;
 
  $faxtime                      = date                  ("H:i:s", $TIMESTART )                                  ;
  $faxdate                      = date                  ("D, d M Y H:i:s")                                      ;
 
  $report[status][0]            =                       "OK"                                                    ;
  $report[status][1]            =                       "FEHLER"                                                ;
  $report[res][0]               =                       "Normal"                                                ;
  $report[res][1]               =                       "Fein"                                                  ;
 
  if                                                    ($intFaxStatus != 0)
  {
    $strErrDesc                 =                       "($strErrDescr)"                                        ;
  }
 
  $toArray[0][name]             =                       $strStatusMail;
  $toArray[0][email]            =                       $strStatusMail;
 
  $txtMessage = "
 
=========================================================================
   UMS Report for FAX JobID $intJobID : ".$report[status][$intFaxStatus]."
=========================================================================
 
   Zielnummer : $strRecCallerID
   Remote-ID  : $intFaxID
 
   Datenrate  : $intFaxRate
   Aufloesung : ".$report[res][$intFaxRes]."
 
   Seiten     : $intFaxPages
 
   Sendezeit  : $faxtime
   Sendedauer : $intCLen Sekunden
   Datum      : $faxdate
 
   Status     : ".$report[status][$intFaxStatus]." $strErrDesc
 
=========================================================================
 
  ";
 
  socketmail ($toArray, "Sendebericht für FAX: $strRecCallerID (".$report[status][$intFaxStatus].")", $txtMessage);
 
  exit                                                  (0)                                                     ;
 
?>

[edit] Tested Clients

[edit] Winprint HylaFAX

Getestet mit Version Homepage Download URL
WinprintHylaFAX-1.2.8 http://winprinthylafax.sourceforge.net/ DOWNLOAD WinprintHylaFAX-1.2.8.exe


Winprint HylaFAX is a Windows print monitor designed to send its output directly to a HylaFAX Server. Once installed, you can print to a HylaFAX Server from any application, and it will pop up a simple dialog box, allowing you to enter the destination FAX number. It's not intended to be fancy or all encompassing, just a quick and easy way to send FAXes from any Windows application.

Now, since AFAXD acts like a HylaFax Server from Winprint's point of view we have a perfect client.

[edit] Next Steps

Writing two handler scripts:

postsendfax.php postreceivefax.php

These script are supposed to handle all tasks currently performed by perl scripts in order to make things simpler and php based.

Bookmark this article on your favourite social bookmarking site
Add to BlogMarks
Add to del.icio.us
Add to digg
Add to Fark
Add to Furl
Add to Newsvine
Add to reddit
Add to Segnalo
Add to Simpy
Add to Slashdot
Add to smarking
Add to Spurl
Add to Wists
Your opinion counts. Please rate the quality of this article because we always want to improve our content. We would also love to hear from your experiences, so feel free to share them in this articles Discussion

Article Rating: 10.0/10 (1 vote)