Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix EventList events handling #27

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

soloma83
Copy link

Hello.
I've added fix to to the bug #26.

Thank you.

@romkazor
Copy link
Contributor

romkazor commented Dec 6, 2018

@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
Copy link
Author

soloma83 commented Dec 6, 2018

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
Copy link
Contributor

romkazor commented Dec 8, 2018

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
Copy link
Author

soloma83 commented Dec 10, 2018

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
Copy link
Contributor

romkazor commented Dec 12, 2018

@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
Copy link

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
Copy link
Owner

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
Copy link

alexis-via commented Nov 23, 2021

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
Copy link
Author

soloma83 commented Nov 23, 2021 via email

@alexis-via
Copy link

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

mmaridev added a commit to mmaridev/python-ami that referenced this pull request Jan 4, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants