projekt7m / asterisk-ami

Communicate with an Asterisk server using the AMI interface
3 stars 0 forks source link

Can't get AMI Events #3

Open newtron123 opened 4 months ago

newtron123 commented 4 months ago

Hi,

I can't get Ami events, I'm using Asterisk 18.12.1.

use asterisk_ami::{AmiConnection, Tag};
use clap::clap_app;
use dotenv::dotenv;
use log::{error, info, trace, warn};
use simple_logger::SimpleLogger;
use std::error::Error;
use std::net::SocketAddr;
use tokio::io;
use tokio::io::{AsyncBufReadExt, BufReader};

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    dotenv().ok();  // Load environment variables from .env file

    SimpleLogger::new()
        .with_utc_timestamps()
        .with_colors(true)
        .with_level(log::LevelFilter::Trace)
        .init()
        .unwrap();

    let args = clap_app!(
        myapp =>
            (name: "asterisk-ami-example")
            (author: "Your Name <your.email@example.com>")
            (about: "Example application for the asterisk-ami crate")
            (@arg SERVER: -s --server +takes_value "Server to connect to")
            (@arg USER: -u --user +takes_value "Username to authenticate with")
            (@arg PASS: -p --pass +takes_value "Password to authenticate with")
            (@arg EVENTS: -e --events "Show all incoming events")
    )
    .get_matches();

    let all_events = args.is_present("EVENTS");

    let username = args
        .value_of("USER")
        .map(String::from)
        .or_else(|| dotenv::var("USERNAME").ok())
        .expect("No username given");
    let secret = args
        .value_of("PASS")
        .map(String::from)
        .or_else(|| dotenv::var("SECRET").ok())
        .expect("No password given");
    let server = args
        .value_of("SERVER")
        .map(String::from)
        .or_else(|| dotenv::var("SERVER").ok())
        .unwrap_or(String::from("127.0.0.1:5038"));
    let server_address: SocketAddr = server.parse()?;

    let mut stdin_reader = BufReader::new(io::stdin());

    'outer: loop {
        let ami_connection = AmiConnection::connect(server_address).await?;

        if all_events {
            let mut events = ami_connection.events();
                loop {
                    match events.recv().await {
                        Err(e) => warn!("Error on reading event: {:?}", e),
                        Ok(Some(evt)) => {
                            println!("Event: {:?}", evt);
                            info!("Event: {:?}", evt);
                        },
                        Ok(None) => {
                            trace!("Connection closed.");
                            break;
                        }
                    }
                }

        }

        let login = vec![
            Tag::from("Action", "Login"),
            Tag::from("Username", &username),
            Tag::from("Secret", &secret),
        ];
        match ami_connection.send(login).await {
            Some(resp) => info!("Login Response: {:?}", resp),
            None => {
                error!("Error on logging in ... maybe cannot connect to server?");
                break;
            }
        }

        let subscribe_events = vec![Tag::from("Action", "Events"), Tag::from("EventMask", "all")];
        match ami_connection.send(subscribe_events).await {
            Some(resp) => info!("Events Subscription Response: {:?}", resp),
            None => {
                error!("Error subscribing to events ... maybe cannot connect to server?");
                break;
            }
        };

        let mut line_buffer = String::new();
        loop {
            tokio::select! {
                bytes_read = stdin_reader.read_line(&mut line_buffer) => {
                    if bytes_read? == 0 {
                        trace!("Stdin closed");
                        break 'outer;
                    }

                    let cmd = line_buffer.trim();
                    if cmd == "" {
                        trace!("Good Bye");
                        break 'outer;
                    } else {
                        let pkt = vec![Tag::from("Action", cmd)];
                        match ami_connection.send(pkt).await {
                            Some(resp) => info!("Response: {:?}", resp),
                            None => {
                                info!("No response. Connection probably closed.");
                                break;
                            },
                        }
                    }
                    line_buffer.clear();
                }
            }
        }
    }

    Ok(())
}
mawis commented 4 months ago

It should work with that version of Asterisk. Have you configured (enabled) the AMI interface of Asterisk?

newtron123 commented 4 months ago

I have a PHP application working on the same manager account, it prints all the events

mawis commented 4 months ago

What’s the command line you are using (with X’ed username and password)?Is it only the events you don’t get? Can you give AMI-commands to the server after starting the program?Am 14.07.2024 um 12:27 schrieb newtron123 @.***>: I have a PHP application working on the same manager account, it prints all the events

—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you commented.Message ID: @.***>

newtron123 commented 4 months ago

So I have sent queue reset command, it works well, here is the result

2024-07-15T07:11:11.870Z TRACE [asterisk_ami] Connecting to 192.168.20.100:5038
2024-07-15T07:11:11.878Z INFO  [ami_rust_test] Login Response: [[Tag { key: "Response", value: "Success" }, Tag { key: "Message", value: "Authentication accepted" }]]
2024-07-15T07:11:11.881Z INFO  [ami_rust_test] Events Subscription Response: [[Tag { key: "Response", value: "Success" }, Tag { key: "Events", value: "On" }]]
Action: QueueReset
ActionID: 123
Queue: 905
2024-07-15T07:12:02.490Z INFO  [ami_rust_test] Response: [[Tag { key: "Response", value: "Success" }, Tag { key: "Message", value: "Queue stats reset successfully" }]]
use asterisk_ami::{AmiConnection, Tag};
use clap::clap_app;
use dotenv::dotenv;
use log::{error, info, trace, warn};
use simple_logger::SimpleLogger;
use std::error::Error;
use std::net::SocketAddr;
use tokio::io;
use tokio::io::{AsyncBufReadExt, BufReader};

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    dotenv().ok();  // Load environment variables from .env file

    SimpleLogger::new()
        .with_utc_timestamps()
        .with_colors(true)
        .with_level(log::LevelFilter::Trace)
        .init()
        .unwrap();

    let args = clap_app!(
        myapp =>
            (name: "asterisk-ami-example")
            (author: "Your Name <your.email@example.com>")
            (about: "Example application for the asterisk-ami crate")
            (@arg SERVER: -s --server +takes_value "Server to connect to")
            (@arg USER: -u --user +takes_value "Username to authenticate with")
            (@arg PASS: -p --pass +takes_value "Password to authenticate with")
            (@arg EVENTS: -e --events "Show all incoming events")
    )
    .get_matches();

    let all_events = args.is_present("EVENTS");

    let username = args
        .value_of("USER")
        .map(String::from)
        .or_else(|| dotenv::var("USERNAME").ok())
        .expect("No username given");
    let secret = args
        .value_of("PASS")
        .map(String::from)
        .or_else(|| dotenv::var("SECRET").ok())
        .expect("No password given");
    let server = args
        .value_of("SERVER")
        .map(String::from)
        .or_else(|| dotenv::var("SERVER").ok())
        .unwrap_or(String::from("127.0.0.1:5038"));
    let server_address: SocketAddr = server.parse()?;

    let mut stdin_reader = BufReader::new(io::stdin());

    'outer: loop {
        let ami_connection = AmiConnection::connect(server_address).await?;

        if all_events {
            let mut events = ami_connection.events();
            tokio::spawn(async move {
                while let Ok(evt) = events.recv().await {
                    match evt {
                        Some(evt) => {
                            println!("Event: {:?}", evt);
                            info!("Event: {:?}", evt);
                        },
                        None => {
                            trace!("Connection closed.");
                            break;
                        }
                    }
                }
            });
        }

        let login = vec![
            Tag::from("Action", "Login"),
            Tag::from("Username", &username),
            Tag::from("Secret", &secret),
        ];
        match ami_connection.send(login).await {
            Some(resp) => info!("Login Response: {:?}", resp),
            None => {
                error!("Error on logging in ... maybe cannot connect to server?");
                break;
            }
        }

        let subscribe_events = vec![Tag::from("Action", "Events"), Tag::from("EventMask", "all")];
        match ami_connection.send(subscribe_events).await {
            Some(resp) => info!("Events Subscription Response: {:?}", resp),
            None => {
                error!("Error subscribing to events ... maybe cannot connect to server?");
                break;
            }
        };

        let mut line_buffer = String::new();
        loop {
            tokio::select! {
                bytes_read = stdin_reader.read_line(&mut line_buffer) => {
                    if bytes_read? == 0 {
                        trace!("Stdin closed");
                        break 'outer;
                    }

                    let cmd = line_buffer.trim();
                    if cmd.is_empty() {
                        trace!("Good Bye");
                        break 'outer;
                    } else {
                        let mut tags = vec![];
                        for line in cmd.lines() {
                            let mut parts = line.splitn(2, ": ");
                            if let (Some(key), Some(value)) = (parts.next(), parts.next()) {
                                tags.push(Tag::from(key, value));
                            }
                        }

                        if !tags.is_empty() {
                            match ami_connection.send(tags).await {
                                Some(resp) => info!("Response: {:?}", resp),
                                None => {
                                    info!("No response. Connection probably closed.");
                                    break;
                                },
                            }
                        }
                    }
                    line_buffer.clear();
                }
            }
        }
    }

    Ok(())
}
newtron123 commented 3 months ago

I think there is a problem regarding Event Subscription

newtron123 commented 2 months ago

any news?