Hi dear TEAM ,
the problem is that i am sending commands to asterisk from python and python is not waiting the response from asterisk and continues implementing python codes this is initial problem but now i have created a variable which assigns value of steps asterisk, current problem is after one loop asterisk did automaticly hangup
can you give us direction or any other information regarding the issue of ours
Thank you for your help
this is my code.
#!/opt/call_center/venv/bin/python3
import websockets
from utils import *
from endpoints import *
import time
import sys
from websockets.sync.client import connect
from asterisk.agi import AGI
agi = AGI()
KUTING = {
'uz': '/tmp/kuting',
'ru': '/tmp/kuting_ru'
}
GAPIRING = {
'uz': '/tmp/gapiring',
'ru': '/tmp/gapiring_ru'
}
JAVOB_TILI = {
"uz": "o'zbekcha javob ber",
"ru": "на русском языке"
}
RESPONSE_PLAY_END = 'response_play_end'
RECORD_END = 'record_end'
language = 'uz'
def wait_for(step):
print(f"VERBOSE \"{step} \ 1")
current_step = agi.get_variable('STEP')
while current_step != step:
current_step = agi.get_variable('STEP')
print(f"VERBOSE \"{current_step} \ 1")
return True
def websocket_client(caller_number):
uri = "ws://server_ip/chatbot/
"
print(f"VERBOSE \"{caller_number} phone\ 1")
with connect(uri) as websocket:
print(f"VERBOSE \"websocket connected\ 1")
# agi.answer()
language = 'uz'
agi.appexec('Playback', '/tmp/kirish_sozi_bank')
result = agi.get_result()
try:
while True:
print(f"VERBOSE \" gapiring \ 1")
agi.appexec('Playback', f'{GAPIRING[language]}')
agi.record_file(f'/tmp/{caller_number}', format='wav', silence=2)
result = agi.get_result()
print(f"VERBOSE \"yozib olish yakunlandi")
agi.set_variable("STEP", RECORD_END)
wait_for(RECORD_END)
language = detect_language(caller_number)
agi.appexec('Playback', f'{KUTING[language]}')
result = agi.get_result()
transcript = send_audio_to_stt(caller_number, language)
websocket.send(transcript + f"\n {JAVOB_TILI[language]}")
response = websocket.recv()
print(f"VERBOSE \"{response} socketdan \ 1")
save_log(caller_number, transcript, response)
send_to_tts(response, language, caller_number)
agi.appexec('Playback', f'/tmp/response_{caller_number}')
agi.set_variable("STEP", RESPONSE_PLAY_END)
wait_for(RESPONSE_PLAY_END)
except Exception as e:
print(f"VERBOSE \"{e}\ 1", file=sys.stderr)
caller_number = sys.argv[1]
websocket_client(caller_number)
Asteriks extensions
[websocketli]
exten => _X,1,NoOp()
same => n,AGI(/opt/call_center/agi.py,${CALLERID(num)})
Casual observation looks like you are violating the AGI protocol. Where do you read the response to the VERBOSE request? Does your library provide a .verbose method?
But it leaves an outstanding response, from the AGI server, in the input queue, so when you try to do the read, that response is matched up with the read request.
This kinda implies you’re doing something wrong. Maybe mismatching quotes? What is displayed (with AGI debug enabled) on the console? You should resolve this and only use library methods.
AGI is a very simple ‘plain text’ protocol. When Asterisk creates the process to execute your AGI, Asterisk communicates with that process via the STDIN and STDOUT of the created process. Thus, your AGI (via the library) make a request by ‘printing’ the request on STDOUT. The library method will read the response from STDIN. Many programmers miss the subtlety and add their own ‘debugging’ print statements, thus breaking the protocol.
For every request, there is a response that must be read. Lather, rinse, repeat.
In addition, when the process is created, Asterisk ‘prints’ a bunch of variables to the STDIN of the process. Some libraries automatically read this, some don’t. If your library does not, there is probably a method to read this ‘AGI environment.’ This ‘backlog’ needs to be ‘drained’ before making AGI requests.
AGI is a synchronous protocol. If you’re looking for events, listening for AMI events sounds like a better approach. Note that you can use AMI in an AGI.
The channel isn’t locked whilst the whole time AGI is running, and there is reference counting to ensure that it can’t be fully removed.
I’m not sure of the current internals, but the original implementation would cause the channel used by AGI to appear to hang up, if was forced to another place in the dialplan.