HylaFax
About
Hylafax is "The world's most advanced open source fax server".
Click here to expand Table of Contents
- 1 Download
 - 2 Dependencies
 - 3 Installation
 - 4 mod_spandsp
 - 5 Configuration
 - 6 Stop/ Start Hylafax
 - 7 Minicom testing for CallerID
 - 8 Incoming  
- 8.1 Dialplan
 - 8.2 ESL
 - 8.3 File name based on UUID
 
 - 9 Outgoing
 - 10 Logs
 - 11 Modem devices permissions issue
 
Download
http://www.hylafax.org/content/Download#Source%5FCode
Dependencies
apt-get update
apt-get install libtiff4-dev
Installation
cd hylafax-version
./configure (uses default values)
make
make install (must be root or equivalent)
mod_spandsp
The recommended way to integrate HylaFax with FreeSWITCH is to use emulated soft modem via mod_spandsp. Edit conf/autoload_configs/spandsp.conf.xml to include the following
<modem-settings> 
  <param name="total-modems" value="30"/> 
</modem-settings>
After reloading mod_spandsp on fs_cli
 fs> reload mod_spandsp
You will see new soft modems being created with relevant pointers to modem devices.
 # ls -l /dev/FS*
 lrwxrwxrwx 1 root root 10 2012-05-31 18:31 /dev/FS0 -> /dev/pts/4
 lrwxrwxrwx 1 root root 10 2012-05-31 18:31 /dev/FS1 -> /dev/pts/5
 lrwxrwxrwx 1 root root 11 2012-05-31 18:31 /dev/FS10 -> /dev/pts/14
 lrwxrwxrwx 1 root root 11 2012-05-31 18:31 /dev/FS11 -> /dev/pts/15
 lrwxrwxrwx 1 root root 11 2012-05-31 18:31 /dev/FS12 -> /dev/pts/16
 lrwxrwxrwx 1 root root 11 2012-05-31 18:31 /dev/FS13 -> /dev/pts/17
 lrwxrwxrwx 1 root root 11 2012-05-31 18:31 /dev/FS14 -> /dev/pts/18
 lrwxrwxrwx 1 root root 11 2012-05-31 18:31 /dev/FS15 -> /dev/pts/19
 lrwxrwxrwx 1 root root 11 2012-05-31 18:31 /dev/FS16 -> /dev/pts/20
 lrwxrwxrwx 1 root root 11 2012-05-31 18:31 /dev/FS17 -> /dev/pts/21
 lrwxrwxrwx 1 root root 11 2012-05-31 18:31 /dev/FS18 -> /dev/pts/22
 lrwxrwxrwx 1 root root 11 2012-05-31 18:31 /dev/FS19 -> /dev/pts/23
 lrwxrwxrwx 1 root root 10 2012-05-31 18:31 /dev/FS2 -> /dev/pts/6
 lrwxrwxrwx 1 root root 11 2012-05-31 18:31 /dev/FS20 -> /dev/pts/24
 lrwxrwxrwx 1 root root 11 2012-05-31 18:31 /dev/FS21 -> /dev/pts/25
 lrwxrwxrwx 1 root root 11 2012-05-31 18:31 /dev/FS22 -> /dev/pts/26
 lrwxrwxrwx 1 root root 11 2012-05-31 18:31 /dev/FS23 -> /dev/pts/27
 lrwxrwxrwx 1 root root 11 2012-05-31 18:31 /dev/FS24 -> /dev/pts/28
 lrwxrwxrwx 1 root root 11 2012-05-31 18:31 /dev/FS25 -> /dev/pts/29
 lrwxrwxrwx 1 root root 11 2012-05-31 18:31 /dev/FS26 -> /dev/pts/30
 lrwxrwxrwx 1 root root 11 2012-05-31 18:31 /dev/FS27 -> /dev/pts/31
 lrwxrwxrwx 1 root root 11 2012-05-31 18:31 /dev/FS28 -> /dev/pts/32
 lrwxrwxrwx 1 root root 11 2012-05-31 18:31 /dev/FS29 -> /dev/pts/33
 lrwxrwxrwx 1 root root 10 2012-05-31 18:31 /dev/FS3 -> /dev/pts/7
 lrwxrwxrwx 1 root root 10 2012-05-31 18:31 /dev/FS4 -> /dev/pts/8
 lrwxrwxrwx 1 root root 10 2012-05-31 18:31 /dev/FS5 -> /dev/pts/9
 lrwxrwxrwx 1 root root 11 2012-05-31 18:31 /dev/FS6 -> /dev/pts/10
 lrwxrwxrwx 1 root root 11 2012-05-31 18:31 /dev/FS7 -> /dev/pts/11
 lrwxrwxrwx 1 root root 11 2012-05-31 18:31 /dev/FS8 -> /dev/pts/12
 lrwxrwxrwx 1 root root 11 2012-05-31 18:31 /dev/FS9 -> /dev/pts/13
To test if the newly created soft modems are okay and respond to AT commands, you can find their support class by using cu command.
 # apt-get install cu
 # cu -l FS0
 Connected
 at+fclass=?
 0,1,1.0
 OK
Configuration
 faxsetup (with default settings)
 faxaddmodem FS0
 faxaddmodem FS1
 .
 .
 .
 faxaddmodem FS29
Edit /etc/rc.local to start hfaxd, faxq and faxgetty at boot
 # Starting the HylaFAX hfaxd and faxq Daemons at Boot.
 /usr/local/sbin/hylafax start
 # Starting faxgetty for incoming Fax
 m0:2345:respawn:/usr/local/sbin/faxgetty FS0
 m1:2345:respawn:/usr/local/sbin/faxgetty FS1
 m2:2345:respawn:/usr/local/sbin/faxgetty FS2
 m3:2345:respawn:/usr/local/sbin/faxgetty FS3
 m4:2345:respawn:/usr/local/sbin/faxgetty FS4
 m5:2345:respawn:/usr/local/sbin/faxgetty FS5
 m6:2345:respawn:/usr/local/sbin/faxgetty FS6
 m7:2345:respawn:/usr/local/sbin/faxgetty FS7
 m8:2345:respawn:/usr/local/sbin/faxgetty FS8
 m9:2345:respawn:/usr/local/sbin/faxgetty FS9
 m10:2345:respawn:/usr/local/sbin/faxgetty FS10
 m11:2345:respawn:/usr/local/sbin/faxgetty FS11
 m12:2345:respawn:/usr/local/sbin/faxgetty FS12
 m13:2345:respawn:/usr/local/sbin/faxgetty FS13
 m14:2345:respawn:/usr/local/sbin/faxgetty FS14
 m15:2345:respawn:/usr/local/sbin/faxgetty FS15
 m16:2345:respawn:/usr/local/sbin/faxgetty FS16
 m17:2345:respawn:/usr/local/sbin/faxgetty FS17
 m18:2345:respawn:/usr/local/sbin/faxgetty FS18
 m19:2345:respawn:/usr/local/sbin/faxgetty FS19
 m20:2345:respawn:/usr/local/sbin/faxgetty FS20
 m21:2345:respawn:/usr/local/sbin/faxgetty FS21
 m22:2345:respawn:/usr/local/sbin/faxgetty FS22
 m23:2345:respawn:/usr/local/sbin/faxgetty FS23
 m24:2345:respawn:/usr/local/sbin/faxgetty FS24
 m25:2345:respawn:/usr/local/sbin/faxgetty FS25
 m26:2345:respawn:/usr/local/sbin/faxgetty FS26
 m27:2345:respawn:/usr/local/sbin/faxgetty FS27
 m28:2345:respawn:/usr/local/sbin/faxgetty FS28
 m29:2345:respawn:/usr/local/sbin/faxgetty FS29
The directories are located in
 /var/spool/hylafax
Configuration files for individual soft modems created by mod_spandsp are in /var/spool/hylafax/etc/config.FS*
Stop/ Start Hylafax
To start/stop hfaxd, the HylaFax Daemon and faxq, the HylaFax queue manager.
 /etc/init.d/hylafax {stop|start|restart}
Minicom testing for CallerID
Use minicom on the tty (instead of faxgetty). And then do the following:
 ATZ
 AT+VCID=1
 ATI
 ATI3
And then send a call to that modem. Check what the CallerID display says.
Incoming
For incoming Fax sessions, the call should be bridged to modem/x/y where x is the slot and y is the dialed number. Use a to get the next available slot and number.
Dialplan
Edit the dialplan conf/dialplan/default.xml to include the following snippet or similar commands over ESL.
 <extension name="fax_receive">
   <condition field="destination_number" expression="^(.*)$">
     <action application="answer" />
     <action application="playback" data="silence_stream://2000"/>
     <action application="bridge" data="modem/a/a"/>
     <action application="hangup"/>
   </condition>
 </extension>
ESL
#!/usr/bin/env python
 
 import SocketServer
 from ESL import *
 
 class ESLRequestHandler(SocketServer.BaseRequestHandler ):
     def setup(self):
         print self.client_address, 'connected!'
 
         fd = self.request.fileno()
         print fd
 
         con = ESLconnection(fd)
         print "Connected: " 
         print  con.connected()
         if con.connected():
 
             info = con.getInfo()
 
             uuid = info.getHeader("unique-id")
             print uuid
             con.execute("answer", "", uuid)
             con.executeAsync("bridge", "modem/1/a/a", uuid)
 
 
 #server host is a tuple ('host', port)
 server = SocketServer.ThreadingTCPServer(('localhost', 8888), ESLRequestHandler)
 server.serve_forever()
File name based on UUID
Bridge call to modem/1/a/uuid, where uuid is a variable with value equal to the uuid of the call
Edit /var/spool/hylafax/etc/config.FS0, config.FS1 etc to include the following
RingsBeforeAnswer: 2  (you probably already have this configured, but check)
ModemResetCmds:  AT+VCID=1
CallIDPattern: "NMBR="
CallIDPattern: "NDID="
Restart faxgetty. Then in your bin/faxrcvd $CALLID1 will refer to the CallerID, and $CALLID2 will refer to the DID. Edit bin/faxrcvd to include the following
 DID=$CALLID1
 UUID=`echo $CALLID2 | cut -d "/" -f 2-`
 NEWFILE=$UUID
 mv -f $FILE $NEWFILE
Outgoing
Use sendfax for putting your outgoing Faxes in the queue.
sendfax -n -vv -d <destination_number> <filename.ps>
Edit the dialplan to include a bridge to the called number.
 <extension name="fax_transmit">
   <condition field="destination_number" expression="^(.*)$">
     <action application="bridge" data="freetdm/1/a/$1"/>
     <action application="hangup"/>
   </condition>
 </extension>
Logs
The log files with detailed message transaction between modem and hylafax are in directory /var/spool/hylafax/log
The transfer status of each received or sent fax is stored in /var/spool/hylafax/etc/xferfaxlog in tab separated format with the following parameters
 date - The date and time of the transaction in the format MM/DD/YY HH:MM , where MM is the numeric month, DD the numeric day, YY the last two digits of the year, and HH:MM is the time in 24-hour format.
 commid - The communication identifier for the call.
 modem - The device identifier for the modem that was used to do the send or receive.
 jobid - The job number for outbound calls.
 jobtag - The client-specified job tag for outbound calls.
 fax.tif - The associated recvq fax TIFF file for the event.
 sender - The sender/receiver’s electronic mailing address (facsimile receptions are always attributed to the ‘‘fax’’ user).
 dest-number - The phone number dialed for outgoing calls.
 TSI - The Transmitter Subscriber Identification string (as received) for incoming calls.
 CSI - The Caller Subscriber Identification string of the remote machine (as reported) for outgoing calls.
 local-number - The local phone number on which the data was received.
 params - The negotiated facsimile session parameters used for transferring data encoded as described below.
 #pages - The total number of pages transferred.
 jobtime - The duration of the session; in the format HH:MM:SS . This time includes setup overhead and any time spent cleaning up after a call.
 conntime - The time spent on the phone; in the format HH:MM:SS . This should be the time used by the Telco/PTT (see https://freeswitch.org/confluence/display/FREESWITCH/Glossary#Glossary-Telco) to calculate usage charges.
 reason - A string that indicates if any problem occurred during the session.
 CIDName - The received CIDName value for the session.
 CIDNumber - The received CIDNumber value for the session.
 owner - The login name of the job owner.
 dcs - The T.30 DCS string that was used in the facsimile communication.
Modem devices permissions issue
If running FS as a non-root user, mod_spandsp will fail when trying to create the /dev/FS devices (the /dev/pts are a non issue). The solution for this is to edit conf/autoload_configs/spandsp.conf.xml to include the undocumented "directory" parameter:
<modem-settings>
  <param name="total-modems" value="30"/>
  <param name="directory" value="/dev/FS"/>
</modem-settings>
Then modify the init.d script of FS to include the creation of /dev/FS and its correct permission and ownership settings.
In the SET section
 FS_USER=freeswitch
 FS_GROUP=freeswitch
 FS_DEVDIR=/dev/FS
inside do_start()
 # Create /dev/FS for mod_spandsp soft modems
 if [ $FS_DEVDIR ] ; then
    mkdir $FS_DEVDIR
    chown $FS_USER:$FS_GROUP $FS_DEVDIR
    chmod -R 0775 $FS_DEVDIR
 fi