Is it possible that an extension does not execute the hangup handler when the call on that extension is redirected to another local channel?
Example:
[context]
exten => 1000,1,Answer()
same => n,Dial(2000@myprovider,,g)
same => n,Hangup()
exten => h,1,NoOp()
same => n,System(path/to/myscript.sh)
The problem is: when I perform an “Action: Redirect” via Asterisk AMI, the hangup handler of 1000@context is executed—and unfortunately, this also triggers myscript.sh
Thank you for your response.
Unfortunately, that didn’t work. Let me show you how I’m currently trying it — at least I’m getting “0” back, which means “false”:
[context]
exten => 1000,1,Answer()
same => n,Dial(2000@myprovider,g)
same => n,Hangup()
exten => h,1,NoOp()
same => n,ExecIf($["${REDIRECT_ACTIVE}" = "TRUE"]?skip_hangup_handler)
same => n,System(/etc/asterisk/scripts/hangup-request-livekit-outbound.sh)
same => n(skip_hangup_handler),NoOp(Hangup-Handler übersprungen, da Redirect.)
same => n,Hangup()
myscript.py
async def find_and_redirect_unhold_channel(writer, reader):
if DEBUG_MODE:
print("...")
else:
print("...")
await send_ami_command(writer, "Action: Status\r\n\r\n")
status_response_str = await get_ami_response_until_complete(reader)
channels_list = parse_channels_from_status_response(status_response_str)
if not channels_list:
print_if_debug("...")
return
found_channel = None
debug_data = None
for channel_data in channels_list:
if (channel_data.get('Exten') == '1197_hold'):
found_channel = channel_data.get('Channel')
print_if_debug("...")
print_if_debug("\n".join([f"{k}: {v}" for k, v in channel_data.items()]))
print_if_debug("---")
redirect = True
if DEBUG_MODE:
user_input = input(f"Want to transfer? (Y/n): ").strip().lower()
if user_input != 'y':
redirect = False
if redirect:
print_if_debug(f"...")
set_global_var_command = (
f"Action: SetGlobalVar\r\n"
f"GlobalVariable: REDIRECT_ACTIVE\r\n"
f"Value: TRUE\r\n"
f"\r\n"
)
await send_ami_command(writer, set_global_var_command)
await reader.readuntil(b'\r\n\r\n')
redirect_command = (
f"Action: Redirect\r\n"
f"Channel: {found_channel}\r\n"
f"Context: incoming\r\n"
f"Exten: 1197_unhold\r\n"
f"Priority: 1\r\n"
f"\r\n"
)
await send_ami_command(writer, redirect_command)
redirect_response = await reader.readuntil(b'\r\n\r\n')
redirect_response_str = redirect_response.decode('utf-8').strip()
print_if_debug("\n--- AMI Redirect Debug-Ausgabe ---")
print_if_debug(redirect_response_str)
print_if_debug("--- Ende Redirect Debug-Ausgabe ---")
reset_global_var_command = (
f"Action: SetGlobalVar\r\n"
f"GlobalVariable: REDIRECT_ACTIVE\r\n"
f"Value: FALSE\r\n"
f"\r\n"
)
await send_ami_command(writer, reset_global_var_command)
await reader.readuntil(b'\r\n\r\n')
print_if_debug("...")
return
else:
print("...")
else:
print_if_debug("...")
I tried adding a 2-second delay in AMI before the redirect, but that also results in:
Executing [h@1000:2] ExecIf("SIP/ge89r6ea677786", "0?skip_hangup_handler") in new stack
EDIT:
I think it’s better if I write a value to the AstDB under 1197_hold and check in the [context] hangup handler whether the value in the AstDB is true or false. This is the only way it worked for me!
There will be no channel technology driver attached after the redirect. You might be able to devise a test for that, although it may produce warning messages.
Also the channel name should have had a suffix added.
This is about using Krisp via Livekit. Krisp also suppresses the MOH (Music on Hold) when I put a call on hold, which means:
I need to immediately intercept the held call on extension 1000 via AMI and redirect it to another local channel, e.g., extension 1000_hold, so that the dial to Livekit is terminated.
When I take the call back, I have to intercept the call from 1000_hold via AMI and redirect it back to extension 1000, which will then dial Livekit again.
Now comes the more complex scenario, which I was able to fully solve through the dialplan:
a)
Call 1 is placed on hold and Call 2 is started. Now I want to perform an attended transfer from Call 1 to Call 2. Before dialing Call 2, I need to check whether callstatus = HOLD is set in the AstDB. If that’s the case, then Call 1 is redirected differently using a GotoIf condition — specifically, directly into a ConfBridge. Call 2 was already redirected to the ConfBridge during the dial because callstatus = HOLD was detected.
b)
Call 1 is placed on hold and Call 2 is started. Now I hang up Call 2 instead of connecting it with Call 1. If I want to retrieve Call 1, we need to check whether the callstatus is HOLD or UNHOLD. The hangup handler of Call 2 has already set callstatus = UNHOLD in the AstDB upon hanging up. When Call 1 is retrieved, it is redirected via the corresponding GotoIf condition and dials extension 1000 again, triggering the dial to Livekit.
im late to the game here.. I use dialplan function REDIRECTING to grab a lot of data about redirected calls.. I use it specifically to detect when users call forward their phones at the phone itself vs using the forward functions we have system wide.. specifically we grab the data so we can alter the caller ID before the call goes out… maybe that helps?
Thank you for your response. That might be worth a try. I’ll test it soon and I might have a few more questions for you. In the meantime, can you give me an example of a Dialplan code line?