ettoreleandrotognoli / python-ami

Python AMI Client
BSD 3-Clause "New" or "Revised" License
107 stars 66 forks source link

Fix EventList events handling #27

Open soloma83 opened 5 years ago

soloma83 commented 5 years ago

Hello. I've added fix to to the bug https://github.com/ettoreleandrotognoli/python-ami/issues/26.

Thank you.

romkazor commented 5 years ago

@soloma83 this fix makes some trouble. Try this code (and make some call) before fix and after

import time
from settings import login, connection
from asterisk.ami import AMIClient, SimpleAction

def send_action(event):
    print(1, event.status)
    print(2, event.keys)
    print(3, event.follows)

def event_listener(event, **kwargs):
    if event.name == 'Newchannel':
        action = SimpleAction('Status')
        client.send_action(action, callback=send_action)

    if event.name == 'Status':
        print(4, event)

client = AMIClient(**connection)
future = client.login(**login)
client.add_event_listener(event_listener)

try:
    while True:
        time.sleep(10)
except (KeyboardInterrupt, SystemExit):
    client.logoff()

Output before fix

1 Success
2 {'ActionID': '1', 'EventList': 'start', 'Message': 'Channel status will follow'}
3 None
4 Event : Status -> {'Privilege': 'Call', 'Channel': 'SIP/100-00000011'}

Output after fix

1 Success
2 {'ActionID': '1', 'EventList': 'start', 'Message': 'Channel status will follow'}
3 None
soloma83 commented 5 years ago

Hello. It is right fix. Your response is handled within request "synchronously", it has been pulled out of the event queue, and event listener must not get it. Here is my output after fix.

tests/integration/test_eventlist.py
1 Success
2 {'ActionID': '1', 'EventList': 'start', 'Message': 'Channel status will follow'}
3 ['', 'Event: Status', 'Privilege: Call', 'Channel: SIP/3030-00000000', 'ChannelState: 4', 'ChannelStateDesc: Ring', 'CallerIDNum: 3030', 'CallerIDName: 3030', 'ConnectedLineNum: <unknown>', 'ConnectedLineName: <unknown>', 'Accountcode: ', 'Context: from-users', 'Exten: 2020', 'Priority: 1', 'Uniqueid: 1544125642.0', 'Type: SIP', 'DNID: 2020', 'EffectiveConnectedLineNum: <unknown>', 'EffectiveConnectedLineName: <unknown>', 'TimeToHangup: 0', 'BridgeID: ', 'Linkedid: 1544125642.0', 'Application: (null)', 'Data: (null)', 'Nativeformats: (ulaw)', 'Readformat: ulaw', 'Readtrans: ', 'Writeformat: ulaw', 'Writetrans: ', 'Callgroup: 0', 'Pickupgroup: 0', 'Seconds: 0', 'ActionID: 1', '', 'Event: StatusComplete', 'ActionID: 1', 'EventList: Complete', 'ListItems: 1', 'Items: 1', '']

Process finished with exit code 0

I do not think that handling event list via callback is the right choice. It detaches output and to get response you need a lot supplementary things to do such as resolving resquest/response ID, sending data to reqesting process, etc...

Usualy, event lists are produced on bsic response without exact query e.g. "status', "queuestatus"

Thank you.

romkazor commented 5 years ago

I do not think that handling event list via callback is the right choice. It detaches output and to get response you need a lot supplementary things to do such as resolving resquest/response ID, sending data to reqesting process, etc...

@soloma83 Yeah, but how can i listen all events and send some action with response if some conditions is matches for me from events?

soloma83 commented 5 years ago

Yeah, but how can i listen all events and send some action with response if some conditions is matches for me from events?

@romkazor It won't break events listening. This patch added handling for actions reqponses It is triggered by sequence Response: Success EventList: start Regular events do not satisfy this statement.

Thank you.

romkazor commented 5 years ago

@soloma83 I finally found whats wrong! Your fix works, but regex for asterisk_end_list_regex will be: re.compile(b'EventList: Complete\r\n, re.IGNORECASE | re.MULTILINE) It works on asterisk 13+

Thank you.

alexis-via commented 2 years ago

Having EventList work correctly is essential. I wanted to use python-ami to get the list of PJSIP outbound registrations, but I find it really difficult and, from my experience, "OutboundRegistrationDetail" events are often not catched. I guess it is related to bug #26 and this PR tries to solve it. What is the problem with this PR?

ettoreleandrotognoli commented 2 years ago

Hello @alexis-via There is a lot of time that I'm not working with the asterisk, so I have no environment to test it at the moment. @romkazor suggested a fix for this PR, that makes sense for me, but I don't have an answer from @soloma83

Do you know if this PR fixes your issue? Or is it necessary to change what was suggested?

alexis-via commented 2 years ago

After more investigation on my code and reading the bug report again, my current conclusion is that there is no bug. The problem I had is that I was doing send_action() and then add_event_listener() to get the result via the EventList. To make it work correctly 100% of the time, you must do the add_event_listener() first and then call send_action().

My code is now the following (I post it here because I think it can help others). It works with Asterisk 18.6.0:

#! /usr/bin/python3

from asterisk.ami import AMIClient, SimpleAction, EventListener
import time 

def event_listener(event, **kwargs):
    print('START EVENT')
    if event.keys.get('Status') and event.keys.get('ServerUri'):
        status = event.keys['Status']
        server = event.keys['ServerUri']
        if status != 'Registered':
            print('%s NOT REGISTERED' % server)
        else:
            print('%s REGISTRATION OK' % server)
    print('END EVENT')

client = AMIClient(address='127.0.0.1', port=5038)
client.login(username='my_login', secret='xxxx')
client.add_event_listener(event_listener, white_list=['OutboundRegistrationDetail'])
action = SimpleAction('PJSIPShowRegistrationsOutbound')
future = client.send_action(action)
print('START SLEEP')
time.sleep(3)  # sleep 3 sec to receive all the events
client.logoff()

And, so far, this code works well with the last release, no need for the patch proposed in this PR.

soloma83 commented 2 years ago

I'm sorry.I had missed this conversation. But I remember that case. I found the same solution as proposed by @romkazor it was working fine.

Thank you, Kirilll

On Tue, Nov 23, 2021 at 11:12 PM Alexis de Lattre @.***> wrote:

After more investigation on my code and reading the bug report again, my current conclusion is that there is not bug. The problem I had is that I was doing send_action() and then add_event_listener() to get the result via the EventList. To make it work correctly 100% of the time, you must do the add_event_listener() first and then call send_action().

My code is now the following (I post it here because I think it can help others). It works with Asterisk 18.6.0:

! /usr/bin/python3

from asterisk.ami import AMIClient, SimpleAction, EventListener import time

def event_listener(event, **kwargs): print('START EVENT') if event.keys.get('Status') and event.keys.get('ServerUri'): status = event.keys['Status'] server = event.keys['ServerUri'] if status != 'Registered': print('%s NOT REGISTERED' % server) else: print('%s REGISTRATION OK' % server) print('END EVENT')

client = AMIClient(address='127.0.0.1', port=5038) client.login(username='my_login', secret='xxxx') client.add_event_listener(event_listener, white_list=['OutboundRegistrationDetail']) action = SimpleAction('PJSIPShowRegistrationsOutbound') future = client.send_action(action) print('START SLEEP') time.sleep(3) # sleep 3 sec to receive all the events client.logoff()

And, so far, this code works well with the last release, no need for the patch proposed in this PR.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/ettoreleandrotognoli/python-ami/pull/27#issuecomment-977037985, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADBOSAKHO5RETCAZFGEWZQ3UNPRQTANCNFSM4GGOSJ6A . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

alexis-via commented 2 years ago

@ettoreleandrotognoli Maybe we could write an example of such a code at the end of the README of the projet... what do you think ?