In this section, I'll show you how to code your own incoming script step by step. We begin with simply accepting every incoming call, playing a beep. The last example is a very simple but useful answering machine with fax recognition and receiving.
Let's start with a very simple case: accept all incoming calls, beep and record something so we have an audio file to play with later. First of all, create a new directory somewhere which must be writable to root. We also need some test audio file for sending it. Let's take the beep which is distributed with CapiSuite.
mkdir capisuite-examples chmod 777 capisuite-examples # make it world-writeable cd capisuite-examples cp /usr/local/share/capisuite/beep.la .
Perhaps you must change the path in the last line to reflect your installation.
Now copy and paste the example shown here to a file called example.py in this directory. Don't forget to change the my_path-setting.
Example 2.1. example.py
import capisuitemy_path="/path/to/the/just/created/capisuite-examples/"
def callIncoming(call,service,call_from,call_to):
capisuite.connect_voice(call,10)
capisuite.audio_send(call,my_path+"beep.la")
capisuite.audio_receive(call,my_path+"recorded.la",20,3)
capisuite.disconnect(call)
Let's walk through the script line by line:
![]() | Import the capisuite module which holds all CapiSuite specific functions. All CapiSuite objects (functions, constants) in this module can be referenced by capisuite.objectname now. You could also do a "from capisuite import *", which will insert all objects in the current namespace - but this isn't recommended as they may collide with other global objects. NoteThe imported module capisuite isn't available as extra module, so you can't do this in an interactive Python session. It's included in the CapiSuite binary and only available in scripts interpreted by CapiSuite. |
![]() | Please change this to the real path you use for running these examples. |
![]() | Define the necessary function as explained in the section called “The incoming script” |
![]() | That's the first CapiSuite function we use: it accepts the pending call. The first parameter tells CapiSuite which call you mean. This parameter is necessary for nearly all CapiSuite functions. Ok, we only have one call now - but please think about an incoming script which also wants to place an outgoing call at the same time (for example to transfer a call). In this case CapiSuite wouldn't know which call you mean - so you must pass the reference you got to all connection related functions. You can also tell CapiSuite to wait for an arbitrary time before accepting a call - that's what the second parameter is used for. So this script will wait 10 seconds before connecting with the caller. Don't think this parameter is useless and you could call a Python function (like time.sleep()) to wait instead. This won't work for any delay longer than 4 (or 8, depending on your ISDN setup) seconds as the call will timeout if an ISDN device doesn't "pre-accept" it by telling your network provider that it's ringing. CapiSuite will do so if necessary - so please just use this parameter. |
![]() | This call should be fairly self-explainig. Send the audio file stored in beep.la. |
![]() | Record an audio file for maximal 20 seconds - stopping earlier if more than 3 seconds of silence are recognized. |
![]() | Last, but not least - disconnect. Hang up. Finish. It's over. |
CapiSuite configuration must be changed to use the just created script. Do this by editing your capisuite.conf and replacing the incoming_script value by the path to the file you just created (see the section called “Configuration of CapiSuite”) and restart CapiSuite.
Now test it: call any number which ends up at your ISDN card - if you have connected it to your ISDN interface, than any number (MSN) will do - if it's connected to a PBX, then you must call a number which was configured for the card in your PBX.
You should hear a beep and then you can speak something into this primitive answering machine. Please don't hangup before the script does as this case isn't handled yet. Just wait 3 seconds after saying something - it should disconnect after this period of silence.
If it doesn't work, you perhaps made an error when copying the script. In this case, please have a look at the CapiSuite log and error log, which you'll find in /var/log/capisuite or /usr/local/var/log/capisuite if you haven't changed the path.
A good trick to check for syntax errors is also to run your script through the normal Python interpreter. Do this by calling python /path/to/your/example.py. Naturally, it will complain about the import capisuite as this is no standard Python module. But before it does this, it will check the syntax of your script - so if you get any other error, please fix it and try again. If you only get
Traceback (most recent call last): File "../scripts/incoming.py", line 16, in ? import capisuite,cs_helpers ImportError: No module named capisuite
then your script has a correct syntax.
I hope you got your script working by now - if not, don't hesitate to ask on the CapiSuite mailing lists if you have read a Python tutorial before.
In the next section we want to use an announcement, so please record some words with this simple script and move the created file recorded.la to announce.la.
Well, it's really not nice that the caller mustn't hangup - and it's even worse that we do accept all incoming calls - perhaps by taking away your mothers important calls?
Let's quickly improve this.
Example 2.2. example.py, improved
import capisuite my_path="/path/to/the/just/created/capisuite-examples/" def callIncoming(call,service,call_from,call_to): try:if (call_to=="123"):
capisuite.connect_voice(call,10) capisuite.audio_send(call,my_path+"announce.la")
capisuite.audio_send(call,my_path+"beep.la") capisuite.audio_receive(call,my_path+"recorded.la",20,3) capisuite.disconnect(call) else: capisuite.reject(call,1)
capisuite.disconnect(call)
except capisuite.CallGoneError: capisuite.disconnect(call)
![]() | CapiSuite will tell the script that the other party has disconnected by raising an exception named CallGoneError. So you should always put your code in a try statement and catch the raised exception at the end of your script (or perhaps earlier if needed). This exception can be raised by call to a CapiSuite command. |
![]() | Have a look at the called number (please replace 123 with the number CapiSuite should accept)... |
![]() | Play the announcement we recorded in the last section. If you don't like it, simply record a new one and move the recorded.la again to announce.la. |
![]() | Ignore the call. The second parameter tells the exact reason for the reject - you can ignore a call (any other ISDN device or phone will still be ringing for that number) by using 1, actively disconnect by using 2 or any error condition which is available in the ISDN specification (see the section called “ISDN error codes” for available codes). |
![]() | You always have to call disconnect at the end of your script, as this will wait for the end of the call, while reject only initiates the call reject. Otherwise you'll get a warning in the error log. |
![]() | This is the exception handler for CallGoneError - the exception CapiSuite raises when the call is disconnected by the other party. You should also call disconnect here to wait until the call is completely disconnected. |
Save this to example.py again and test it. It's not necessary to restart CapiSuite as all scripts will be read at each time they're executed. Now you're allowed to hang up, too ;-).
We always used the same name to save the recorded message to which clearly isn't reasonable. We should really choose a new name for every new call. This isn't as simple as it may sound - you must assure that the used algorithm will also work for multiple calls arriving at the same time. Fortunately, the helpful programmer of CapiSuite had the same problem and so we can use the code he (hmmm... I?) has written.
The Python module cs_helpers.py contains some useful functions which are needed by the default scripts provided with CapiSuite but may be also helpful for the use in your own scripts. It contains the function uniqueName which does exactly what we need here. The syntax is:
filename=cs_helpers.uniqueName(directory,prefix,sufix)
The function will find a new unique filename in the given directory. The created filename will be "prefix-XXX.suffix" where XXX is the next free number started at 0. The next free number is remembered in a file prefix-nextnr and the created name is returned.
We can simply add this call to our script:
Example 2.3. using unique filenames
import capisuite,cs_helpers my_path="/path/to/the/just/created/capisuite-examples/" def callIncoming(call,service,call_from,call_to): try: if (call_to=="123"): filename=cs_helpers.uniqueName(my_path,"voice","la") capisuite.connect_voice(call,10) capisuite.audio_send(call,my_path+"announce.la") capisuite.audio_send(call,my_path+"beep.la") capisuite.audio_receive(call,filename,20,3) capisuite.disconnect(call) else: capisuite.reject(call,1) except capisuite.CallGoneError: capisuite.disconnect(call)
If you're interested in other functions which cs_helpers.py defines, just have a look at the reference at the section called “cs_helpers.py”.
As last step, I want to show you how fax recognition and receiving works and how to switch from voice to fax mode.
Here's the last and most complicated example of this section. It'll introduce four new CapiSuite functions and shows how to split up the functionality in another function which is used by callIncoming. There are much changes which are described below - but most of them should be nearly self-explanatory. So I don't think this last step is too big. And you don't want to read 10 more steps here, do you? ;-)
Example 2.4. Adding fax functions
import capisuite,cs_helpers,osmy_path="/path/to/the/just/created/capisuite-examples/" def callIncoming(call,service,call_from,call_to): try: if (call_to=="123"): filename=cs_helpers.uniqueName(my_path,"voice","la") capisuite.connect_voice(call,10) capisuite.enable_DTMF(call)
capisuite.audio_send(call,my_path+"announce.la",1)
capisuite.audio_send(call,my_path+"beep.la",1) capisuite.audio_receive(call,filename,20,3,1) dtmf=capisuite.read_DTMF(call,0)
if (dtmf=="X"):
if (os.access(filename,os.R_OK)):
os.unlink(filename) faxIncoming(call)
capisuite.disconnect(call) else: capisuite.reject(call,1) except capisuite.CallGoneError: capisuite.disconnect(call) def faxIncoming(call): capisuite.switch_to_faxG3(call,"+49 123 45678","Test headline")
filename=cs_helpers.uniqueName(my_path,"fax","sff") capisuite.fax_receive(call,filename)
Congrats. You've finished my small tutorial. Now it's up to you - you can play with the created script and try to make it more complete. There's still much to do - sending received calls to a user via e-mail, log connections, ... If you want to complete this script, the section called “CapiSuite command reference” will be helpful. You can also read on here to have a short look on the idle scripts, followed by a quick overview of the structure of the default scripts shipped with CapiSuite.