Asterisk + arduino = domotica???

buenas amig@s

soy nuevo en este foro soy estudiante de ing electronica.

para resumir un poco, trabajo con asterisk en la empresa donde estoy, el proyecto que me llamo la atencion surgio desde un amigo en la comunidad cuyo proyecto publico en una pagina el amigo se llama Jorge Montero todo el credito para el dicho proyecto es un portero automatico con asterisk, pero yo quiero agregarle mas cosas los datos extraidos textualmente del comentario del señor Jorge son los siguientes:

al chiste del proyecto es usar asterisk para realizar llamadas telefonicas al arduino y luego digitar X numero y poder encender o apagar una carga, (entienda por carga un bombillo, un motor, aire acondicionado y lo que tu inventiva necesite)

Pongo un adelanto del ejemplo, antes de publicarlo, pero esta todo el código necesario para arrancar.

Por una lado tenemos tres actores en este ejemplo:

Actor Principal : Asterisk

Actor Secundario: Arduino + EtherShield ( el arduino que yo estoy usando es un arduino mega por la cantidad de salidas digitales que me ofrece)

Actor Invitado: Un poco de código de ejemplo

En el DialPlan del Asterisk (/etc/asteriks/extensions.conf) ponemos algo como esto:

; Extension del portero automatico
//(en esta parte realice una modificacion y fue darle autenticacion para el usuario que realiza la llamada entrante)

; Extension del portero automatico 

exten => 300,1,Authenticate(0000)
exten => 300,2,Answer 
exten => 300,3,AGI(ConexionArduino.php) 
exten => 300,4,Hangup

el codigo anterior solo tiene como finalidad crear la extensión del arduino explico:
exten => 300,1,Authenticate(0000) la extencion que tiene mi arduino es la 300 paso (1) se autentifica la llamada con el 0000
exten => 300,2,Answer paso (2) la llamada es contestada
exten => 300,3,AGI(ConexionArduino.php) paso (3) se envia la llamada al script en php
exten => 300,4,Hangup paso (4) una ves terminada la llamada luego de toda la comunicacion se cuelga la llamada

En el directorio /var/lib/asterisk/agi-bin un fichero llamado "ConexionArduino.php" (sin las comillas y atentos a los permisos de ejecución), con el siguiente contenido:

#!/usr/bin/php -q

<?php

require("phpagi.php");
$agi = new AGI();

                                                                                 // Cambie los siguientes valores para reflejar su puesta en marcha
$arduino_ip = "tcp://192.168.0.130";                   //la ip que le asigne a mi arduino
$arduino_port = 23;                                                // abrir un socket a la dirección IP del Arduino y el puerto

$fp = fsockopen($arduino_ip, $arduino_port, $errno, $errstr);

if (!$fp) {
   exit();
}

$continue = true;
while($continue){
   $return = $agi->get_data('beep', 10000, 1);
   if (($return['result'] >= 0) and ($return['result'] <= 9)){
      $ascii = chr($return['result']);                                                           //convert that # to ASCII
      fwrite($fp, $ascii);                                                                            //La tecla pulsada se envia al Arduino
   }

}

fclose($fp);

?>

el codigo que yo estoy usando con la ayuda de mi amigo Luis Guevara, la version del ide que estoy usando es la 1.0.1

#include <SPI.h>

#include <Dhcp.h>
#include <Dns.h>
#include <EthernetUdp.h>                                                //librerias usadas por la  version que estoy usando 
#include <Ethernet.h>
#include <EthernetClient.h>
#include <EthernetServer.h>
#include <util.h>

#include <HashMap.h>

const int t = 15;
HashMap<int, int, t> tabla = HashMap<int, int,t>();


byte mac[] = {0x90, 0xA2, 0xDA, 0x00, 0x9B, 0x00 };           //mac que trae el modulo arduino Ethernet Shield           
byte ip[] = { 192, 168, 0, 130 };                                             // ip que tiene asignado mi arduino

EthernetServer server = EthernetServer(23);                       //puerto por el cual se comunican con el arduino                                  


void setup(){
  Ethernet.begin(mac, ip); 
  server.begin(); 

  Serial.begin(9600); 

  pinMode(24, OUTPUT);                                                     //declaracion de los pines como salida
  pinMode(25, OUTPUT); 
  pinMode(26, OUTPUT); 
  pinMode(27, OUTPUT); 
  pinMode(28, OUTPUT); 
  pinMode(29, OUTPUT); 
  pinMode(30, OUTPUT); 
  pinMode(31, OUTPUT); 
  pinMode(32, OUTPUT); 
  pinMode(33, OUTPUT); 
  pinMode(34, OUTPUT); 
  pinMode(35, OUTPUT); 
  pinMode(36, OUTPUT); 
  pinMode(37, OUTPUT); 
  pinMode(38, OUTPUT); 
  pinMode(39, OUTPUT);   
  
  tabla[1]  = 24;                                                           //tabla que indica cada numero del teclado del telefono asociado a un pin de arduino
  tabla[2]  = 25;
  tabla[3]  = 26;
  tabla[4]  = 27;
  tabla[5]  = 28;
  tabla[6]  = 29;
  tabla[7]  = 30;
  tabla[8]  = 31;
  tabla[9]  = 32;
  tabla[10] = 33;
  tabla[11] = 34;
  tabla[12] = 35;
  tabla[12] = 36;
  tabla[13] = 37;
  tabla[14] = 38;
  tabla[15] = 39;
}


void accion(int x)
{
  
    Serial.print(x); 

    Serial.println("activo"); 
    
    digitalWrite(tabla[x],1);                                                //x representa el pin en esta caso se activa (1) y tiene una duracion de 1000ms
    delay(1000); 
    
    digitalWrite(tabla[x],0);                                              //x representa el pin en esta caso se desactiva (0) y tiene una duracion de 1000ms
    delay(1000); 
    
    digitalWrite(tabla[x],1); 
    delay(1000); 
    
    digitalWrite(tabla[x],0); 
    
    //x  = 0;    
      
}

void loop(){
  
  EthernetClient client = server.available(); 

  if (client){ 
    accion(client.read()); 
    
    Serial.print("conectado"); 
    
    //Serial.println(x); 
    
  } 

}


--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------



ahora bien cuales son los problemas que tengo, son los siguientes:

en los códigos anteriores puedo solo controlar 9 cargas que son las teclas del telefono 1,2,3,4,5,6,7,8,9, pero necesito controlar aproximadamente 25 cargas es decir que yo pueda ingresar en el teclado del telefono el numero 25 y se active el pin 25 de mi arduino y de hay para adelante hacer lo que necesite.

solicito ayuda de ustedes para poder realizar este proyecto. 

gracias por los aportes que me puedan dar

¿Podrías poder cada código entre etiquetas "code"? Están justo encima del smiley ;), el botón '#'. Favorecerás muuuucho la lectura de tu post.

Podrías explicar también qué es lo que hace cada código. ¿Por qué pones dos códigos de arduino?

Dices que controlas solo 9 cargas porque envías/recibes los carácteres '1' a '9' (¿no serían 10 con el '0'?). ¿Por qué no trabajas con valores en lugar de carácteres ascii? Eso te facilitaría el uso hasta 255 cargas.

el 0 no lo puedo usar ya que si lo hago el pin quedara activo todo el tiempo

que puedo hacer para ingresarle dos digitos y lograr activar mas de 9 cargas??

leztad:
el 0 no lo puedo usar ya que si lo hago el pin quedara activo todo el tiempo

No entiendo porque no puedes usar el 0.

Si envías un cero, available() te devolverá true, es decir, dirá que has recibido un dato (con valor=0, pero un dato). Cuando lo leas con read, el valor será cero y pasarás el parámetro con valor 0 a la función acción().

Si no envías nada, available te devolverá false y no ejecutará nada del if.

En cuanto a pasar 2 dígitos, la solución más sencilla es que envíes un byte en lugar de un carácter ASCII, podrás enviar desde 0 hasta 255 como ya te había dicho.

gracias por contestar amigo digamos que lo del cero no es tan necesario en este momento para mi lo importante es poder usar dos digitos y disculpa mi ignorancia en temas de programación pero me podrías dar un ejemplo de como lo puedo lograr hacer?

Lo primero de todo sería modificar el código php. Yo de php....ni idea, pero el código que has puesto parece sencillo y la modificación sería algo así como:

#!/usr/bin/php -q

<?php

require("phpagi.php");
$agi = new AGI();

                                                                                 // Cambie los siguientes valores para reflejar su puesta en marcha
$arduino_ip = "tcp://192.168.0.130";                   //la ip que le asigne a mi arduino
$arduino_port = 23;                                                // abrir un socket a la dirección IP del Arduino y el puerto

$fp = fsockopen($arduino_ip, $arduino_port, $errno, $errstr);

if (!$fp) {
   exit();
}

$continue = true;
while($continue){
   $return = $agi->get_data('beep', 10000, 1);
   if (($return['result'] >= 0) and ($return['result'] <= 255)){
      fwrite($fp, $result);                                                                            //No se convierte a ASCII, se pasa directamente el valor de 8 bits
   }

}

fclose($fp);

?>

La idea es que en lugar de enviar los carácteres ASCII del '0' al '9', envíes un byte con el valor correspondiente (de 0 a 255)

En cuanto al código en el arduino, no haría falta modificarlo. Cuando recibes un dato, lo lees y lo pasas a la aplicación.

Con respecto a lo del '0', te vuelvo a repetir, que no tienes más que probalo para ver que funciona tan bien como el '1 o el '7', por ejemplo, con el mismo código que tienes. Solo tienes que añadir la entrada en la tabla correspondiente.

mi amigo vuelvo de nuevo despues de algunos dias de trabajo, realice las pruebas cambiando el 9 por el 255 y no hace nada todo queda igual.

alguna otra idea?

buenas mis amigos ya tengo buenas noticias ya logre que el proyecto funcione con dos digitos de manera sencilla adjunto el codigo

#!/usr/bin/php -q

<?php

require("phpagi.php");
$agi = new AGI();

// Cambie los siguientes valores para reflejar su puesta en marcha
$arduino_ip = "tcp://192.168.0.130"; //la ip que le asigne a mi arduino
$arduino_port = 23; // abrir un socket a la dirección IP del Arduino y el puerto

$fp = fsockopen($arduino_ip, $arduino_port, $errno, $errstr);

if (!$fp) {
exit();
}

$continue = true;
while($continue){

//archivo, timeout, numero de caracteres
$return = $agi->get_data('beep', 3000, 2);                            //el cambio fue que se dejo una pausa de 3000 ms, y para usar dos (2)                                                                                          // digitos
//rango de valores de los numero validos 
if (($return['result'] >= 0) and ($return['result'] <= 40)){
$ascii = chr($return['result']); //convert that # to ASCII
fwrite($fp, $ascii); //La tecla pulsada se envia al Arduino
}

}

fclose($fp);

?>

cualquier duda me avisan

HOLA UNA PREGUNTA CUANDO COMPILO ME DICE QUE "TABLA" NO ESTA DECLARADO EN EL SCOPE, NO ENTIENDO MUY BIEN SOY NOVATO ME PUEDES AYUDAR QUIERO CONTROLAR CUATRO RELAYS CON DIFERENTES EXTENSIONES ALGO ASI COMO SI MARCO 664 SE ACTIVE UN RELAY O 665 OTRO RELAY ETC ETC SALUDOS

MIRA ESTO ES LO QUE ME SALE

sketch_dec28b:14: error: expected constructor, destructor, or type conversion before '<' token
sketch_dec28b.ino: In function 'void setup()':
sketch_dec28b:46: error: 'tabla' was not declared in this scope
sketch_dec28b.ino: In function 'void accion(int)':
sketch_dec28b:72: error: 'tabla' was not declared in this scope

primero debes verificar ti tienes las siguientes librerias en tu compilador de arduino
#include <SPI.h>

#include <Dhcp.h>
#include <Dns.h>
#include <EthernetUdp.h> //librerias usadas por la version que estoy usando
#include <Ethernet.h>
#include <EthernetClient.h>
#include <EthernetServer.h>
#include <util.h>

#include <HashMap.h>

sobre todo la ultima que es para las tablas

revisa y me avisas

hola leztad oye puedo ponerme en contacto contigo directamente saludos

Mi correo es aszaps53@gmail.com podemos conversar por gtalk

y como es que haces la marcacion al arduino ?

la marcacion al arduino se realiza desde un teléfono ip el cual debe de estar logeado en una central telefónica asterisk o elastix según tu preferencia.

es decir si tengo un teléfono ip con la ext 500 y el arduino tiene la extensión 400 la comunicación seria de la siguiente manera

ext 500-----> elastix--------> ext400-------> autenticacion --------> arduino