In this implementation, I'm trying to do call patching between an inbound call and a outbound call via the session.bridge()
command.
I have already received the inbound call and my Python script is playing. In this script I'm trying to patch the running call with the numbers in the number_list(list of numbers)
one by one until the list is exhausted or till the call is patched and answered.
My Code:
for cp_num in connObj.cp_list:
ivr_log.debug("Attempting to dial Call Patch Number:%s"%(cp_num['cp_no']))
connObj.patch_uuid = uuid.uuid1()
cmd_str = """{ignore_early_media=true,execute_on_answer=record_session %s/%s_%s.wav,origination_uuid=%s,originate_timeout=45,script_name=gaadi_test}freetdm/wp4/a/%s"""%(connObj.recording_path,connObj.uuid,connObj.caller_id,connObj.patch_uuid,cp_num['cp_no'])
connObj.bridge(cmd_str) #BRIDGE
connObj.hangup_cause = connObj.getVar("last_bridge_hangup_cause")
if connObj.hangup_cause in ['NORMAL_CLEARING', '']:
connObj.cp_status = "SUCCESS"
return True
connObj.cp_status = "FAILED"
connObj.playback(connObj.path_sound + 'all_reps_busy.wav')
return False
Multiple numbers to the bridge command for sequential dialing. From freeswitch documentation: Multiple endpoints sequential -- no limit to failover number
bridge <target_endpoint>[|<target_endpoint>]
My Implementation
cmd1 = """{ignore_early_media=true,originate_timeout=45}[origination_uuid=%s,script_name=gaadi_test]freetdm/wp4/a/%s"""%(connObj.patch_uuid1,connObj.cp_list[0]['cp_no'])
cmd2 = """[origination_uuid=%s,script_name=gaadi_test]freetdm/wp4/a/%s"""%(connObj.patch_uuid2,connObj.cp_list[1]['cp_no'])
cmd = "%s[|%s]"%(cmd3,cmd4)
ivr_log.debug("CMD=%s"%(cmd))
connObj.call_patch_start_time = int(time.time())
connObj.patch_start_datetime = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
connObj.bridge(cmd)
P.S.: ConnObj.bridge(cmd) is working perfect for only one target point.
Sequential Dialing solution: just a little changes in cmd1 and cmd2. I have not confirmed if the origination uuid will be different for both the calls.
cmd1 = """{ignore_early_media=true,originate_timeout=45,script_name=gaadi_test}[origination_uuid=%s]freetdm/wp4/a/%s"""%(connObj.patch_uuid1,connObj.cp_list[0]['cp_no'])
cmd2 = """[origination_uuid=%s]freetdm/wp4/a/%s"""%(connObj.patch_uuid2,connObj.cp_list[1]['cp_no'])
cmd="%s|%s" #removed the brackets and its working now.
connObj.bridge(cmd)
EDIT:
Finally I solved the problem with Stanislav's approach. I used api_on_answer. On answer I wrote a file on the disk and then checked whether the file was present or not. If the file was present then the call was answered.
You can set execute_on_answer
variable to execute a hangup, but in general, mod_python
is not the right place for such tasks: the script is executed as a thread inside FreeSWITCH process, and you don't have any control while a FreeSWITCH application is being executed (bridge in your case).
A much better option is to use the Event Socket Library (ESL)†, and then you can control the call flow asynchronously and receive events that are relevant to call state changes.
† The FreeSWITCH docs are not very consistent and haven't been updated in a long while, so reading the following entries will give the best overview when starting out:
Event Socket Library
Starts with a very high level overview then abruptly jumps into the nitty gritty.
Documents the modes of operation (inbound & outbound) and available commands to send to the FreeSWITCH instances event loop. See mod_erlang_event
's section 6. (inbound mode) and 7. (outbound mode) for more details.
Event Socket Outbound
A short, hard to miss entry that may add more to the previous.
Event List
Gives an overview of the available events with some examples.
See the fs_cli "slash" (/) commands
to monitor events in realtime.
Unfortunately, none of these articles have been updated since at least 2020, so if something is off, then you'll have to drop down to the FreeSWITCH source.