¿cuanta gente a visto el blog?

Enviar datos a la Base de datos con una llamada

 /etc/asterisk/pjsip.conf


[1001] type=endpoint context=odbc_test ; Asegúrate de usar el contexto definido en extensions.conf


sudo systemctl restart asterisk


sudo nano /etc/asterisk/extensions.conf


[odbc_test]

exten => 100,1,NoOp(Leyendo valor desde la base de datos)

 same => n,Set(ODBC_RESULT=${ODBC_IVAST(SELECT numero FROM ultnum WHERE id=1)})

 same => n,NoOp(Valor obtenido: ${ODBC_RESULT})

 same => n,Hangup()


exten => 101,1,NoOp(Insertando un nuevo valor en la base de datos)

 same => n,Set(ODBC_INSERT=${ODBC_IVAST(INSERT INTO ultnum (numero) VALUES (42))})

 same => n,NoOp(Valor insertado con éxito)

 same => n,Hangup()



sudo asterisk -rx "dialplan reload"

con menu

sudo nano /etc/asterisk/extensions.conf

[ivr_menu]
exten => s,1,Answer()
 same => n,Background(welcome) ; Reproduce un audio inicial (reemplaza 'welcome' con tu archivo .wav)
 same => n,WaitExten(10) ; Espera 10 segundos para recibir una entrada del usuario
 same => n,Hangup()

; Opción 1 - Establecer número en la base de datos a 1
exten => 1,1,NoOp(Opción 1 seleccionada)
 same => n,Set(ODBC_INSERT=${ODBC_IVAST(UPDATE ultnum SET numero=1 WHERE id=1)})
 same => n,Playback(option-1) ; Reproduce un mensaje indicando que se seleccionó la opción 1
 same => n,Hangup()

; Opción 2 - Establecer número en la base de datos a 2
exten => 2,1,NoOp(Opción 2 seleccionada)
 same => n,Set(ODBC_INSERT=${ODBC_IVAST(UPDATE ultnum SET numero=2 WHERE id=1)})
 same => n,Playback(option-2) ; Reproduce un mensaje indicando que se seleccionó la opción 2
 same => n,Hangup()

; Opción 3 - Establecer número en la base de datos a 3
exten => 3,1,NoOp(Opción 3 seleccionada)
 same => n,Set(ODBC_INSERT=${ODBC_IVAST(UPDATE ultnum SET numero=3 WHERE id=1)})
 same => n,Playback(option-3) ; Reproduce un mensaje indicando que se seleccionó la opción 3
 same => n,Hangup()

; Manejo de entradas inválidas
exten => i,1,Playback(invalid) ; Reproduce un mensaje de opción inválida
 same => n,Goto(ivr_menu,s,2) ; Regresa al inicio del menú

; Manejo de tiempo agotado sin respuesta
exten => t,1,Playback(goodbye) ; Reproduce un mensaje de despedida
 same => n,Hangup()


 


sudo nano /etc/asterisk/pjsip.conf


[1001]
type=endpoint
context=ivr_menu ; Cambia al contexto del menú IVR

que solo funcione el celular para eso

[ivr_menu]
exten => s,1,Answer()
 same => n,Background(vm-intro) ; Reproduce la introducción del correo de voz
 same => n,WaitExten(10) ; Espera 10 segundos para recibir entrada del usuario
 same => n,Hangup()

; Opción 1
exten => 1,1,NoOp(Opción 1 seleccionada)
 same => n,Set(ODBC_INSERT=${ODBC_IVAST(UPDATE ultnum SET numero=1 WHERE id=1)})
 same => n,Playback(demo-thanks) ; Agradece por seleccionar la opción 1
 same => n,Hangup()

; Opción inválida
exten => i,1,Playback(invalid) ; Reproduce mensaje de opción inválida
 same => n,Goto(ivr_menu,s,1) ; Regresa al menú

; Tiempo agotado
exten => t,1,Playback(vm-intro) ; Reproduce el mismo mensaje inicial
 same => n,Hangup()


sudo asterisk -rx "dialplan reload"

menu 774

sudo nano /etc/asterisk/extensions.conf

[default]
exten => 774,1,Answer()
 same => n,Playback(demo-thanks) ; Reproduce un audio corto por defecto
 same => n,Goto(ivr_menu,s,1) ; Entra al menú IVR

[ivr_menu]
exten => s,1,NoOp(Ingreso al menú IVR)
 same => n,Background(vm-intro) ; Reproduce un mensaje (puedes usar cualquier archivo por defecto)
 same => n,WaitExten(10) ; Espera 10 segundos para recibir entrada del usuario

; Opción 1: Establecer el último número de la tabla como 1
exten => 1,1,NoOp(Opción 1 seleccionada)
 same => n,Set(ODBC_INSERT=${ODBC_IVAST(UPDATE ultnum SET numero=1 WHERE id=1)})
 same => n,Playback(demo-thanks) ; Agradece al usuario
 same => n,Goto(ivr_menu,s,1) ; Regresa al menú

; Opción 2: Establecer el último número de la tabla como 0
exten => 2,1,NoOp(Opción 2 seleccionada)
 same => n,Set(ODBC_INSERT=${ODBC_IVAST(UPDATE ultnum SET numero=0 WHERE id=1)})
 same => n,Playback(demo-thanks) ; Agradece al usuario
 same => n,Goto(ivr_menu,s,1) ; Regresa al menú

; Opciones no válidas: Volver al menú
exten => i,1,Playback(invalid) ; Reproduce un mensaje indicando que la opción no es válida
 same => n,Goto(ivr_menu,s,1) ; Regresa al menú

; Tiempo agotado: Reproduce un mensaje y vuelve al menú
exten => t,1,Playback(vm-intro) ; Reproduce un mensaje
 same => n,Goto(ivr_menu,s,1) ; Regresa al menú

sudo nano /etc/asterisk/pjsip.conf


[1001]
type=endpoint
context=default
disallow=all
allow=ulaw
auth=auth1001
aors=1001





llamada condicional por tabla 

isql -v ivast
 
CREATE TABLE ultemp (
    id INT AUTO_INCREMENT PRIMARY KEY,
    valor INT NOT NULL
);

INSERT INTO ultemp (valor) VALUES (0);
SELECT * FROM ultemp;



sudo nano /etc/asterisk/extensions.conf

[check_ultemp]
exten => s,1,NoOp(Comprobando el valor de ultemp)
 same => n,Set(ULTEMP=${ODBC_READ(SELECT valor FROM ultemp WHERE id=1)})
 same => n,NoOp(Valor actual de ultemp: ${ULTEMP})

; Si el valor es mayor a 1000, llama al 1002
 same => n,GotoIf($[${ULTEMP} > 1000]?call_1002,1)

; Si el valor es menor o igual a 1000, cuelga cualquier llamada activa
 same => n,Hangup()

[call_1002]
exten => 1,1,NoOp(Llamando al 1002 porque ultemp es mayor a 1000)
 same => n,Dial(PJSIP/1002,10) ; Llama al 1002 durante 10 segundos
 same => n,Hangup()

sudo nano /root/check_ultemp.sh
#!/bin/bash

while true; do
    # Ejecuta la comprobación en Asterisk
    asterisk -rx "channel originate Local/s@check_ultemp extension s@check_ultemp"
    sleep 5 # Espera 5 segundos antes de volver a comprobar
done


chmod +x /root/check_ultemp.sh 

./root/check_ultemp.sh



isql -v ivast


UPDATE ultemp SET valor=1500 WHERE id=1;

 sudo nano llamadacontinua1001.py 

import socket
import time

# Configuración de Asterisk Manager Interface (AMI)
ASTERISK_HOST = '127.0.0.1'  # Dirección IP del servidor Asterisk
ASTERISK_PORT = 5038         # Puerto de AMI
ASTERISK_USER = 'admin'      # Usuario definido en manager.conf
ASTERISK_SECRET = 'admin'    # Contraseña definida en manager.conf

def iniciar_llamada():
    try:
        # Crear socket para conexión AMI
        ami_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        ami_socket.connect((ASTERISK_HOST, ASTERISK_PORT))

        # Login en AMI
        login = (
            f"Action: Login\r\n"
            f"Username: {ASTERISK_USER}\r\n"
            f"Secret: {ASTERISK_SECRET}\r\n"
            f"\r\n"
        )
        ami_socket.sendall(login.encode())
        time.sleep(1)

        # Comando Originate para iniciar llamada
        originate = (
            f"Action: Originate\r\n"
            f"Channel: PJSIP/1001\r\n"
            f"Context: default\r\n"  # Cambia si usas otro contexto
            f"Exten: 1001\r\n"       # Extensión destino
            f"Priority: 1\r\n"       # Prioridad definida en extensions.conf
            f"CallerID: Modo Continuo <1003>\r\n"
            f"\r\n"
        )
        ami_socket.sendall(originate.encode())
        print("Llamada enviada a 1001. Esperando respuesta...")

        # Leer la respuesta de Asterisk
        while True:
            data = ami_socket.recv(1024).decode()
            print(data)
            if "Hangup" in data or "answered" in data.lower():
                print("La llamada fue contestada o finalizada.")
                break

        ami_socket.close()
    except Exception as e:
        print(f"Error: {e}")

if __name__ == "__main__":
    try:
        while True:
            iniciar_llamada()
            time.sleep(1)  # Espera un segundo antes de intentar otra llamada
    except KeyboardInterrupt:
        print("\nModo continuo finalizado. No se realizarán más llamadas.")

  • Revisa manager.conf:

    Asegúrate de que manager.conf contenga algo similar a esto: 

    [admin] secret = admin read = system,call,log,verbose,command,agent,user write = system,call,log,verbose,command,agent,user

    Reinicia Asterisk después de cualquier cambio: 

    sudo systemctl restart asterisk
  • Verifica el canal PJSIP:

    Comprueba que el canal PJSIP/1001 esté registrado: 

    sudo asterisk -rx "pjsip show endpoints"

  • python3 llamadacontinua1001.py

    pip3 install pymysql

    sudo nano check_ultemp.py

    import socket
    import pymysql
    import time

    # Configuración de Asterisk Manager Interface (AMI)
    ASTERISK_HOST = '127.0.0.1'  # Dirección IP del servidor Asterisk
    ASTERISK_PORT = 5038         # Puerto de AMI
    ASTERISK_USER = 'admin'      # Usuario definido en manager.conf
    ASTERISK_SECRET = 'admin'    # Contraseña definida en manager.conf

    # Configuración de la base de datos
    DB_HOST = 'localhost'
    DB_USER = 'root'
    DB_PASSWORD = 'admin'
    DB_NAME = 'ivast'
    DB_TABLE = 'ultemp'

    # Variable para rastrear el estado de la llamada
    llamada_activa = False

    def iniciar_llamada():
        try:
            global llamada_activa
            # Crear socket para conexión AMI
            ami_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            ami_socket.connect((ASTERISK_HOST, ASTERISK_PORT))

            # Login en AMI
            login = (
                f"Action: Login\r\n"
                f"Username: {ASTERISK_USER}\r\n"
                f"Secret: {ASTERISK_SECRET}\r\n"
                f"\r\n"
            )
            ami_socket.sendall(login.encode())
            time.sleep(1)

            # Comando Originate para iniciar llamada
            originate = (
                f"Action: Originate\r\n"
                f"Channel: PJSIP/1001\r\n"
                f"Context: default\r\n"  # Cambia si usas otro contexto
                f"Exten: 1001\r\n"       # Extensión destino
                f"Priority: 1\r\n"       # Prioridad definida en extensions.conf
                f"CallerID: Alerta <1003>\r\n"
                f"\r\n"
            )
            ami_socket.sendall(originate.encode())
            print("Llamada iniciada a 1001.")
            llamada_activa = True

            ami_socket.close()
        except Exception as e:
            print(f"Error al iniciar la llamada: {e}")

    def finalizar_llamada():
        try:
            global llamada_activa
            # Crear socket para conexión AMI
            ami_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            ami_socket.connect((ASTERISK_HOST, ASTERISK_PORT))

            # Login en AMI
            login = (
                f"Action: Login\r\n"
                f"Username: {ASTERISK_USER}\r\n"
                f"Secret: {ASTERISK_SECRET}\r\n"
                f"\r\n"
            )
            ami_socket.sendall(login.encode())
            time.sleep(1)

            # Comando Hangup para finalizar la llamada
            hangup = (
                f"Action: Hangup\r\n"
                f"Channel: PJSIP/1001\r\n"
                f"\r\n"
            )
            ami_socket.sendall(hangup.encode())
            print("Llamada finalizada.")
            llamada_activa = False

            ami_socket.close()
        except Exception as e:
            print(f"Error al finalizar la llamada: {e}")

    def verificar_valor():
        try:
            global llamada_activa
            # Conexión a la base de datos
            conexion = pymysql.connect(
                host=DB_HOST,
                user=DB_USER,
                password=DB_PASSWORD,
                database=DB_NAME
            )
            cursor = conexion.cursor()

            # Consultar el valor actual de la tabla ultemp
            cursor.execute(f"SELECT valor FROM {DB_TABLE} ORDER BY id DESC LIMIT 1;")
            resultado = cursor.fetchone()

            if resultado:
                valor = resultado[0]
                print(f"Valor actual: {valor}")
                if valor > 1000 and not llamada_activa:
                    iniciar_llamada()
                elif valor <= 1000 and llamada_activa:
                    finalizar_llamada()
            else:
                print("No se encontró ningún dato en la tabla.")

            cursor.close()
            conexion.close()
        except Exception as e:
            print(f"Error al verificar el valor: {e}")

    if __name__ == "__main__":
        try:
            while True:
                verificar_valor()
                time.sleep(2)  # Intervalo de verificación en segundos
        except KeyboardInterrupt:
            print("\nScript detenido por el usuario.")



    python3 check_ultemp.py



    isql -v ivast

    UPDATE ultemp SET valor = 1500 WHERE id = 1;

    UPDATE ultemp SET valor = 900 WHERE id = 1;




    Consultar de la base de datos con ESP32

    ip a


    #include <WiFi.h>
    #include <HTTPClient.h>

    const char* ssid = "RED";  
    const char* password = "clave";

    // http://192.168.0.104/consulta_ultnum.php
    // Definir el pin para el LED
    #define LED_PIN 2  // Pin GPIO2 del ESP32 (G2)

    void setup() {
      // Inicializar el LED como salida
      pinMode(LED_PIN, OUTPUT);
      digitalWrite(LED_PIN, LOW); // Apagar el LED inicialmente
     
      Serial.begin(115200);
     
      // Conexión a la red WiFi
      Serial.println("Conectando a WiFi...");
      WiFi.begin(ssid, password);
     
      while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
      }
     
      Serial.println("\nConexión establecida!");
      Serial.print("IP asignada: ");
      Serial.println(WiFi.localIP());
    }

    void loop() {
      if (WiFi.status() == WL_CONNECTED) {
        HTTPClient http;
        String serverUrl = "http://192.168.0.104/consulta_ultnum.php";
       
        Serial.println("Conectando al servidor...");
        http.begin(serverUrl);
        int httpCode = http.GET();

        if (httpCode > 0) { // Si el servidor responde
          String payload = http.getString();
          Serial.print("Respuesta recibida: ");
          Serial.println(payload);
         
          // Convertir la respuesta a entero
          int valor = payload.toInt();
         
          // Controlar el LED según el valor
          if (valor == 1) {
            Serial.println("Encendiendo el LED...");
            digitalWrite(LED_PIN, HIGH); // Encender LED
          } else if (valor == 0) {
            Serial.println("Apagando el LED...");
            digitalWrite(LED_PIN, LOW); // Apagar LED
          } else {
            Serial.println("Valor desconocido recibido.");
          }
        } else {
          Serial.print("Error en la conexión HTTP: ");
          Serial.println(httpCode);
        }

        http.end();
      } else {
        Serial.println("WiFi desconectado!");
      }
     
      delay(500); // Esperar 5 segundos antes de realizar otra consulta
    }

    sudo nano /var/www/html/consulta_ultnum.php
    <?php
    $servername = "localhost"; // Cambia si no usas localhost
    $username = "root";
    $password = "admin";
    $dbname = "ivast";

    // Crear conexión
    $conn = new mysqli($servername, $username, $password, $dbname);

    // Verificar conexión
    if ($conn->connect_error) {
        die("Conexión fallida: " . $conn->connect_error);
    }

    // Consulta SQL
    $sql = "SELECT numero FROM ultnum WHERE id = 1";
    $result = $conn->query($sql);

    if ($result->num_rows > 0) {
        // Obtener el valor
        $row = $result->fetch_assoc();
        echo $row['numero'];
    } else {
        echo "No se encontraron resultados.";
    }

    $conn->close();
    ?>


    http://10.10.10.138/consulta_ultnum.php



    Subir datos desde la esp 

    sudo nano envia_valor.php
    <?php
    $servername = "localhost";
    $username = "root";
    $password = "admin";
    $dbname = "ivast";

    // Conexión a la base de datos
    $conn = new mysqli($servername, $username, $password, $dbname);
    if ($conn->connect_error) {
        die("Conexión fallida: " . $conn->connect_error);
    }

    // Obtener los datos enviados por la ESP32
    $id = $_POST['id'];
    $valor = $_POST['valor'];

    // Actualizar el valor en la tabla ultemp
    $sql = "UPDATE ultemp SET valor = $valor WHERE id = $id";

    if ($conn->query($sql) === TRUE) {
        echo "Valor actualizado con éxito";
    } else {
        echo "Error al actualizar: " . $conn->error;
    }

    $conn->close();
    ?>



     

    Extender disco duro de alma linux

    sudo du -ah / 2>/dev/null | sort -rh | head -n 20




    ps aux

     lsblk

    sudo fdisk /dev/nvme0n2

  • Presiona n para crear una nueva partición.
  • Selecciona la opción por defecto (primary).
  • Acepta los valores predeterminados para el inicio y final de la partición.
  • Presiona w para escribir los cambios y salir.


  • sudo partprobe /dev/nvme0n2
    lsblk

    sudo pvcreate /dev/nvme0n2p1

    sudo vgextend almalinux /dev/nvme0n2p1

    sudo vgdisplay

    sudo lvextend -l +100%FREE /dev/almalinux/root

    sudo resize2fs /dev/almalinux/root

    sudo blkid /dev/mapper/almalinux-root

    sudo xfs_growfs /
    sudo umount /dev/mapper/almalinux-root

    sudo resize2fs /dev/mapper/almalinux-root
    sudo mount /dev/mapper/almalinux-root /
    df -h

    wget http://enlace-al-paquete/unixODBC-devel-*.rpm

    sudo rpm -ivh unixODBC-devel-*.rpm




    Conectar Asterist con Base de Datos

     sudo nano /etc/odbc.ini

    [ivast]
    Driver = MySQL
    Server = localhost
    Database = ivast
    User = root
    Password = admin
    Port = 3306



    sudo nano /etc/asterisk/res_odbc.conf
     
    [ENV]
     
    [asterisk]
     
    enabled => no
     
    dsn => asterisk
     
    pre-connect => yes
     

    [mysql2]
    enabled => no
    dsn => MySQL-asterisk
    username => myuser
    password => mypass
    pre-connect => yes
     
    [sqlserver]
    enabled => no
    dsn => mickeysoft
    max_connections => 5
    username => oscar
    password => thegrouch
    pre-connect => yes
    sanitysql => select count(*) from systables
     
    backslash_is_escape => no

    [ivast]
    enabled => yes
    dsn => ivast
    username => root
    password => admin
    pre-connect => yes


    sudo nano /etc/asterisk/func_odbc.conf
     
    [general]
     
    [SQL]
    writehandle=mysql1
    readsql=${ARG1}

     
    [ANTISOLICIT]
    dsn=mysql1,mysql2   ; Use mysql1 as the primary handle, but fall back to mysql2
                       
    readsql=SELECT COUNT(*) FROM known_solicitors WHERE callerid='${SQL_ESC(${ARG1})}'
    syntax=<callerid>
    synopsis=Check if a specified callerid is contained in the known solicitors database

     
    [PRESENCE]
    writehandle=mysql1
    readsql=SELECT location FROM presence WHERE id='${SQL_ESC(${ARG1})}'
    writesql=UPDATE presence SET location='${SQL_ESC(${VAL1})}' WHERE id='${SQL_ESC(${ARG1})}'

    [ULTNUM_READ]
    dsn=ivast
    readsql=SELECT numero FROM ultnum LIMIT 1

    [ULTNUM_WRITE]
    dsn=ivast
    writesql=UPDATE ultnum SET numero=${SQL_ESC(${ARG1})} LIMIT 1
      


    /extension.conf 

     
    [general]
     
    static=yes
     
    writeprotect=no
     
    clearglobalvars=no
     
    [globals]
    CONSOLE=Console/dsp ; Console interface for demo
     
    TRUNK=DAHDI/G2 ; Trunk interface
     
    TRUNKMSD=1 ; MSD digits to strip (usually 1 or 0)
     
    [dundi-e164-canonical]
     
    [dundi-e164-customers]
     
    [dundi-e164-via-pstn]
     
    [dundi-e164-local]
     
    include => dundi-e164-canonical
    include => dundi-e164-customers
    include => dundi-e164-via-pstn

    [dundi-e164-switch]
     
    switch => DUNDi/e164

    [dundi-e164-lookup]
     
    include => dundi-e164-local
    include => dundi-e164-switch
     
    [dundi-e164]
     
    exten => s,1,Goto(${ARG1},1)
    include => dundi-e164-lookup

     
    [iax2-trunk]
    exten => _555XXXX,1,Dial(IAX2/username:secret@example.com/${EXTEN}@some-dialplan-context)
     
    [iaxprovider] 

    [trunkint]
     
    exten => _9011.,1,Gosub(dundi-e164,s,1(${EXTEN:4}))

    exten => _9011.,n,Dial(${GLOBAL(TRUNK)}/${FILTER(0-9,${EXTEN:${GLOBAL(TRUNKMSD)}})})

    [trunkld]

    exten => _91NXXNXXXXXX,1,Gosub(dundi-e164,s,1(${EXTEN:1}))
    exten => _91NXXNXXXXXX,n,Dial(${GLOBAL(TRUNK)}/${EXTEN:${GLOBAL(TRUNKMSD)}})

    [trunklocal]

    exten => _9NXXXXXX,1,Dial(${GLOBAL(TRUNK)}/${EXTEN:${GLOBAL(TRUNKMSD)}})

    [trunktollfree]
    exten => _91800NXXXXXX,1,Dial(${GLOBAL(TRUNK)}/${EXTEN:${GLOBAL(TRUNKMSD)}})
    exten => _91888NXXXXXX,1,Dial(${GLOBAL(TRUNK)}/${EXTEN:${GLOBAL(TRUNKMSD)}})
    exten => _91877NXXXXXX,1,Dial(${GLOBAL(TRUNK)}/${EXTEN:${GLOBAL(TRUNKMSD)}})
    exten => _91866NXXXXXX,1,Dial(${GLOBAL(TRUNK)}/${EXTEN:${GLOBAL(TRUNKMSD)}})

    [international]

    ignorepat => 9
    include => longdistance
    include => trunkint

    [longdistance]

    ignorepat => 9
    include => local
    include => trunkld

    [local]

    ignorepat => 9
    include => default
    include => trunklocal
    include => iax2-trunk
    include => trunktollfree
    include => iaxprovider



    [outbound-freenum]

    exten => _X*X!,1,Goto(outbound-freenum2,${EXTEN},1)
    exten => _XX*X!,1,Goto(outbound-freenum2,${EXTEN},1)
    exten => _XXX*X!,1,Goto(outbound-freenum2,${EXTEN},1)
    exten => _XXXX*X!,1,Goto(outbound-freenum2,${EXTEN},1)
    exten => _XXXXX*X!,1,Goto(outbound-freenum2,${EXTEN},1)
    exten => _XXXXXX*X!,1,Goto(outbound-freenum2,${EXTEN},1)

    [outbound-freenum2]

    exten => _X!,1,Verbose(2,Performing ISN lookup for ${EXTEN})
    same => n,Set(SUFFIX=${CUT(EXTEN,*,2-)})                                ; make sure the suffix is all digits as well
    same => n,GotoIf($["${FILTER(0-9,${SUFFIX})}" != "${SUFFIX}"]?fn-CONGESTION,1)
                                                                            ; filter out bad characters per the README-SERIOUSLY.best-practices.txt document
    same => n,Set(TIMEOUT(absolute)=10800)
    same => n,Set(isnresult=${ENUMLOOKUP(${EXTEN},sip,,1,freenum.org)})     ; perform our lookup with freenum.org
    same => n,GotoIf($["${isnresult}" != ""]?from)
    same => n,Set(DIALSTATUS=CONGESTION)
    same => n,Goto(fn-CONGESTION,1)
    same => n(from),Set(__SIPFROMUSER=${CALLERID(num)})
    same => n,GotoIf($["${GLOBAL(FREENUMDOMAIN)}" = ""]?dial)               ; check if we set the FREENUMDOMAIN global variable in [global]
    same => n,Set(__SIPFROMDOMAIN=${GLOBAL(FREENUMDOMAIN)})                 ;    if we did set it, then we'll use it for our outbound dialing domain
    same => n(dial),Dial(SIP/${isnresult},40)
    same => n,Goto(fn-${DIALSTATUS},1)

    exten => fn-BUSY,1,Busy()

    exten => _f[n]-.,1,NoOp(ISN: ${DIALSTATUS})
    same => n,Congestion()

    [trunkdial]

    exten => s,1,StackPop()
    same => n,Dial(${ARG1})
    exten => s,n,Goto(s-${DIALSTATUS},1)
    exten => s-NOANSWER,1,Hangup()
    exten => s-BUSY,1,PlayTones(busy)
    same => n,Wait(60)
    same => n,Hangup()
    exten => s-CHANUNAVAIL,1,PlayTones(congestion)
    same => n,Wait(60)
    same => n,Hangup()
    exten => s-CONGESTION,1,PlayTones(congestion)
    same => n,Wait(60)
    same => n,Hangup()
    exten => _s-.,1,NoOp(${DIALSTATUS})
    same => n,Hangup()

    [stdexten]

    exten => _X.,50000(stdexten),NoOp(Start stdexten)
    same => n,Set(LOCAL(ext)=${EXTEN})
    same => n,Set(LOCAL(dev)=${ARG1})
    same => n,Set(LOCAL(cntx)=${ARG2})
    same => n,Set(LOCAL(mbx)=${ext}${IF($[!${ISNULL(${cntx})}]?@${cntx})})
    same => n,Dial(${dev},20) ; Ring the interface, 20 seconds maximum
    same => n,Goto(stdexten-${DIALSTATUS},1) ; Jump based on status (NOANSWER,BUSY,CHANUNAVAIL,CONGESTION,ANSWER)

    exten => stdexten-NOANSWER,1,VoiceMail(${mbx},u) ; If unavailable, send to voicemail w/ unavail announce
    same => n,Return() ; If they press #, return to start

    exten => stdexten-BUSY,1,VoiceMail(${mbx},b) ; If busy, send to voicemail w/ busy announce
    same => n,Return() ; If they press #, return to start

    exten => _stde[x]te[n]-.,1,Goto(stdexten-NOANSWER,1) ; Treat anything else as no answer

    exten => a,1,VoiceMailMain(${mbx}) ; If they press *, send the user into VoicemailMain
    exten => a,n,Return()

    [stdPrivacyexten]

    exten => _X.,60000(stdPrivacyexten),NoOp(Start stdPrivacyexten)
    same => n,Set(LOCAL(ext)=${ARG1})
    same => n,Set(LOCAL(dev)=${ARG2})
    same => n,Set(LOCAL(dontcntx)=${ARG3})
    same => n,Set(LOCAL(tortcntx)=${ARG4})
    same => n,Set(LOCAL(cntx)=${ARG5})

    exten => _X.,n,Set(LOCAL(mbx)="${ext}"$["${cntx}" ? "@${cntx}" :: ""])
    same => n,Dial(${dev},20,p) ; Ring the interface, 20 seconds maximum, call screening
    ; option (or use P for databased call _X.screening)
    same => n,Goto(stdexten-${DIALSTATUS},1) ; Jump based on status (NOANSWER,BUSY,CHANUNAVAIL,CONGESTION,ANSWER)

    exten => stdexten-NOANSWER,1,VoiceMail(${mbx},u) ; If unavailable, send to voicemail w/ unavail announce
    same => n,NoOp(Finish stdPrivacyexten NOANSWER)
    same => n,Return() ; If they press #, return to start

    exten => stdexten-BUSY,1,VoiceMail(${mbx},b) ; If busy, send to voicemail w/ busy announce
    same => n,NoOp(Finish stdPrivacyexten BUSY)
    same => n,Return() ; If they press #, return to start

    exten => stdexten-DONTCALL,1,Goto(${dontcntx},s,1) ; Callee chose to send this call to a polite "Don't call again" script.

    exten => stdexten-TORTURE,1,Goto(${tortcntx},s,1) ; Callee chose to send this call to a telemarketer torture script.

    exten => _stde[x]te[n]-.,1,Goto(stdexten-NOANSWER,1) ; Treat anything else as no answer

    exten => a,1,VoiceMailMain(${mbx}) ; If they press *, send the user into VoicemailMain
    same => n,Return()

    [sub-page]

    exten => s,1,ChanIsAvail(${ARG1},s) ; s is for ANY call
    same => n,GotoIf($["${AVAILSTATUS}" = "1"]?autoanswer:fail)
    same => n(autoanswer),Set(_ALERT_INFO="RA") ; This is for the PolyComs
    same => n,SIPAddHeader(Call-Info: Answer-After=0) ; This is for the Grandstream, Snoms, and Others
    same => n,NoOp() ; Add others here and Post on the Wiki!!!!
    same => n,Dial(${ARG1})
    same => n(fail),Hangup()

    [demo]
    include => stdexten

    exten => s,1,Wait(1) ; Wait a second, just for fun
    same => n,Answer() ; Answer the line
    same => n,Set(TIMEOUT(digit)=5) ; Set Digit Timeout to 5 seconds
    same => n,Set(TIMEOUT(response)=10) ; Set Response Timeout to 10 seconds
    same => n(restart),BackGround(demo-congrats) ; Play a congratulatory message
    same => n(instruct),BackGround(demo-instruct) ; Play some instructions
    same => n,WaitExten() ; Wait for an extension to be dialed.

    exten => 2,1,BackGround(demo-moreinfo) ; Give some more information.
    exten => 2,n,Goto(s,instruct)

    exten => 3,1,Set(CHANNEL(language)=fr) ; Set language to french
    same => n,Goto(s,restart) ; Start with the congratulations

    exten => 1000,1,Goto(default,s,1)

    exten => 1234,1,Playback(transfer,skip) ; "Please hold while..."
    ; (but skip if channel is not up)
    same => n,Gosub(${EXTEN},stdexten(${GLOBAL(CONSOLE)}))
    same => n,Goto(default,s,1) ; exited Voicemail

    exten => 1235,1,VoiceMail(1234,u) ; Right to voicemail

    exten => 1236,1,Dial(Console/dsp) ; Ring forever
    same => n,VoiceMail(1234,b) ; Unless busy


    exten => #,1,Playback(demo-thanks) ; "Thanks for trying the demo"
    same => n,Hangup() ; Hang them up.


    exten => t,1,Goto(#,1) ; If they take too long, give up
    exten => i,1,Playback(invalid) ; "That's not valid, try again"


    exten => 600,1,Playback(demo-echotest) ; Let them know what's going on
    same => n,Echo() ; Do the echo test
    same => n,Playback(demo-echodone) ; Let them know it's over
    same => n,Goto(s,6) ; Start over

    exten => 76245,1,Gosub(page,s,1(SIP/Grandstream1))

    exten => _7XXX,1,Gosub(page,s,1(SIP/${EXTEN}))

    exten => 7999,1,Set(TIMEOUT(absolute)=60)
    same => n,Page(Local/Grandstream1@page&Local/Xlite1@page&Local/1234@page/n,d)


    exten => 8500,1,VoiceMailMain()
    same => n,Goto(s,6)

    [page]
    exten => _X.,1,Gosub(sub-page,s,1(SIP/${EXTEN}))
    same => n,Hangup()



    [public]

    include => demo

    [default]
    ; Extensión para unirse a la conferencia
    exten => 7,1,Answer()
    same => n,ConfBridge(7,pc1,pu1) ; Asocia la conferencia "7" con los perfiles definidos en confbridge.conf
    same => n,Hangup()
    ; Extensión para grabar el audio "bienvenido"
    exten => 600,1,Answer()
    same => n,Playback(vm-intro)                 ; Mensaje opcional: "Empiece a grabar después del tono"
    same => n,Record(/var/lib/asterisk/sounds/bienvenido.gsm) ; Graba el archivo "bienvenido.gsm"
    same => n,Playback(vm-saved)                 ; Mensaje: "Su grabación ha sido guardada"
    same => n,Hangup()

    ; Extensión para grabar el audio "invalido"
    exten => 601,1,Answer()
    same => n,Playback(vm-intro)                 ; Mensaje opcional: "Empiece a grabar después del tono"
    same => n,Record(/var/lib/asterisk/sounds/invalido.gsm)   ; Graba el archivo "invalido.gsm"
    same => n,Playback(vm-saved)                 ; Mensaje: "Su grabación ha sido guardada"
    same => n,Hangup()

    ; Extensión para grabar el audio "prueba"
    exten => 602,1,Answer()
    same => n,Playback(vm-intro)                 ; Mensaje: "Empiece a grabar después del tono"
    same => n,Record(/var/lib/asterisk/sounds/prueba.gsm) ; Graba el archivo "prueba.gsm"
    same => n,Playback(vm-saved)                 ; Mensaje: "Su grabación ha sido guardada"
    same => n,Hangup()


    ; Extensión para iniciar el menú interactivo
    exten => 505,1,Answer()
    same => n,Goto(menu,inicio,1)
    exten => 1001,1,Dial(PJSIP/1001)
    exten => 1001,n,Hangup()

    exten => 1002,1,Dial(PJSIP/1002)
    exten => 1002,n,Hangup()

    exten => 1003,1,Dial(PJSIP/1003)
    exten => 1003,n,Hangup()
    [menu]
    ; Inicio del menú interactivo
    exten => inicio,1,Background(prueba)         ; Reproduce el audio "Bienvenido a comunicaciones avanzadas"
    same => n,WaitExten(15)                      ; Espera 15 segundos para que el usuario pulse una opción

    ; Opción 1 - Llama a asistencia técnica
    exten => 1,1,Playback(bienvenido)            ; Reproduce el mensaje "Gracias, lo estamos comunicando"
    same => n,Dial(SIP/500,10)                   ; Llama a la extensión SIP 500
    same => n,Hangup()

    ; Opción 2 - Reproduce un mensaje
    exten => 2,1,Playback(hello-world)           ; Reproduce el mensaje "Hello world"
    same => n,Hangup()

    ; Manejo de entradas inválidas
    exten => i,1,Playback(invalido)              ; Reproduce el mensaje "Opción incorrecta"
    same => n,Goto(menu,inicio,1)                ; Regresa al inicio del menú

    ; Tiempo de espera (15 segundos sin entrada)
    exten => t,1,Playback(goodbye)               ; Reproduce el mensaje de despedida
    same => n,Hangup()



    include => demo


    [time]
    exten => _X.,30000(time),NoOp(Time: ${EXTEN} ${timezone})
    same => n,Wait(0.25)
    same => n,Answer()
    ; the amount of delay is set for English; you may need to adjust this time
    ; for other languages if there's no pause before the synchronizing beep.
    same => n,Set(FUTURETIME=$[${EPOCH} + 12])
    same => n,SayUnixTime(${FUTURETIME},Zulu,HNS)
    same => n,SayPhonetic(z)
    ; use the timezone associated with the extension (sip only), or system-wide
    ; default if one hasn't been set.
    same => n,SayUnixTime(${FUTURETIME},${timezone},HNS)
    same => n,Playback(spy-local)
    same => n,WaitUntil(${FUTURETIME})
    same => n,Playback(beep)
    same => n,Return()


    [ani]
    exten => _X.,40000(ani),NoOp(ANI: ${EXTEN})
    same => n,Wait(0.25)
    same => n,Answer()
    same => n,Playback(vm-from)
    same => n,SayDigits(${CALLERID(ani)})
    same => n,Wait(1.25)
    same => n,SayDigits(${CALLERID(ani)}) ; playback again in case of missed digit
    same => n,Return()

    asterist.conf
     [directories](!)
    astcachedir => /tmp
    astetcdir => /etc/asterisk
    astmoddir => /usr/lib/asterisk/modules
    astvarlibdir => /var/lib/asterisk
    astdbdir => /var/lib/asterisk
    astkeydir => /var/lib/asterisk
    astdatadir => /var/lib/asterisk
    astagidir => /var/lib/asterisk/agi-bin
    astspooldir => /var/spool/asterisk
    astrundir => /var/run/asterisk
    astlogdir => /var/log/asterisk
    astsbindir => /usr/sbin

    [options]
     


    pjsip.conf
     
    [transport-udp]
    type=transport
    protocol=udp    ;udp,tcp,tls,ws,wss,flow
    bind=0.0.0.0
    [1001]
    type=endpoint
    transport=transport-udp
    context=default
    disallow=all
    allow=ulaw
    auth=auth1001
    aors=1001

    [auth1001]
    type=auth
    auth_type=userpass
    password=admin
    username=1001

    [1001]
    type=aor
    max_contacts=1

    [1002]
    type=endpoint
    transport=transport-udp
    context=default
    disallow=all
    allow=ulaw
    auth=auth1002
    aors=1002

    [auth1002]
    type=auth
    auth_type=userpass
    username=1002
    password=admin

    [1002]
    type=aor
    max_contacts=1

    [1003]
    type=endpoint
    transport=transport-udp
    context=default
    disallow=all
    allow=ulaw
    auth=auth1003
    aors=1003

    [auth1003]
    type=auth
    auth_type=userpass
    username=1003
    password=admin

    [1003]
    type=aor
    max_contacts=1


    [zoiper_auth]
    type=auth
    auth_type=userpass
    password=admin
    username=zoiper_ivan

    [zoiper_aor]
    type=aor
    max_contacts=1

     /etc/asterisk/manager.conf
     
    [admin]
    secret = admin
    read = all
    write = all

    [general]
    enabled = yes
    ;webenabled = yes

    port = 5038
    bindaddr = 0.0.0.0

     

    Como instalar odbc para Asterist

     ANTES DE INSTALAR ES NECESARIO AUMENTAR EL ESPACIO DE /ROOT  QUE ES DONDE SE INTALARA


    sudo dnf install epel-release -y
    sudo dnf config-manager --set-enabled crb

    sudo dnf update -y




    sudo dnf install unixODBC-devel -y


    sudo dnf install unixODBC unixODBC-devel mariadb-connector-odbc -y

    rpm -qa | grep unixODBC
    sudo nano /etc/odbcinst.ini

    [MySQL]
    Description = ODBC for MariaDB
    Driver = /usr/lib64/libmaodbc.so
    Setup = /usr/lib64/libodbcmyS.so
    FileUsage = 1

    sudo nano /etc/odbc.ini

    [asterisk-connector]
    Description = MariaDB connection for Asterisk
    Driver = MySQL
    Server = localhost
    Database = asterisk
    User = root
    Password = admin
    Port = 3306
    isql -v asterisk-connector

    sudo dnf install unixODBC unixODBC-devel mariadb-connector-odbc -y


    rpm -qa | grep mariadb-connector-odbc

    rpm -qa | grep mariadb-connector-odbc
    sudo nano /etc/odbcinst.ini


    [MySQL]
    Description = ODBC for MariaDB
    Driver = /usr/lib64/libmaodbc.so

    sudo nano /etc/odbc.ini

    [asterisk-connector]
    Description = MariaDB connection for Asterisk
    Driver = MySQL
    Server = localhost
    Database = asterisk
    User = tu_usuario
    Password = admin
    Port = 3306

    mysql -u root -p
    CREATE DATABASE ivast;
    USE ivast;

    CREATE TABLE ultnum (
        id INT AUTO_INCREMENT PRIMARY KEY,
        numero INT NOT NULL
    );

    INSERT INTO ultnum (numero) VALUES (0);

    SHOW DATABASES;
    USE ivast;
    SHOW TABLES;
    SELECT * FROM ultnum;



    exit;

    sudo nano /etc/odbc.ini

    [ivast-connector]
    Description = MariaDB connection for ivast
    Driver = MySQL
    Server = localhost
    Database = ivast
    User = root
    Password = admin
    Port = 3306

    isql -v ivast-connector

    SELECT * FROM ultnum;

    INSERT INTO ultnum (numero) VALUES (42);

    UPDATE ultnum SET numero = 100 WHERE id = 1;