Arduino y peticiones GET HTTP con el SIM900
En la entrada anterior explicamos como preparar el módulo GSM MMsmartGSM de PROPOX para poder utilizarlo junto con Arduino.
En esta entrada voy a tratar de explicar un tema que muchos consideran casi "magia negra" y esa es el realizar peticiones a servidores web con un módulo GSM a través de una conexión GPRS.
El objetivo de esta entrada es sencillo: Enviar datos a un servidor web a través de una petición GET utilizando únicamente los comandos AT del SIM900 y funciones de lectura de datos del puerto serial.
Para esta entrada no vamos a utilizar ningún tipo de bibliotecas extra. La dinámica que seguiremos será sencilla: Primero vamos a realizar una conexión con el módem desde la propia consola de comandos y una vez la logremos hacer funcionar de manera adecuada, vamos a desarrollar un código para Arduino que nos permita realizar esta misma acción de forma programática.
De nuevo advierto que esta entrada podría resultar un poco larga ya que explicaremos los conceptos básicos antes de entrar al detalle de la programación con Arduino. Pero de nuevo, les recomiendo que la lean completa para que tengan una mejor comprensión de como funcionan las conexiones en Internet, el protocolo HTTP y como podemos enviar datos fácilmente desde nuestro dispositivo hacia cualquier prácticamente cualquier servidor en Internet.
Un pequeño video para que se hagan una idea de lo que vamos a lograr hacer al final de esta entrada:
Un pequeño video para que se hagan una idea de lo que vamos a lograr hacer al final de esta entrada:
Habiendo dicho lo anterior... ¡Comencemos!
¿Qué es el Internet?
El Internet es la red global de comunicaciones que posee un sin fín de computadores y dispositivos interconectados entre sí a través de diferentes tecnologías de red pero que tienen algo en común: utilizan un protocolo estándar de comunicaciones conocido como TCP/IP.
El TCP/IP es un conjunto de especificaciones de protocolos que deben seguir los dispositivos (a diferentes niveles) para poder comunicarse entre sí.
Podría escribir mucho acerca del protocolo de Internet pero para no aburrirnos mejor les dejo la entrada de la Wikipedia que tiene un bonito resumen al respecto.
Resumiendo el artículo de la Wikipedia: cada dispositivo conectado a Internet utiliza una dirección numérica conocida como dirección IP, para comunicarnos con un dispositivo remoto debemos de conocer el número que ha sido asignado al mismo.
Las direcciones IP se representan como 4 cifras entre 0 y 255 separadas por puntos, por ejemplo "33.24.35.66". Esto debería cambiar gradualmente en el futuro con la implementación del Protocolo de Internet versión 6 en donde las direcciones son considerablemente más largas por lo que se representan utilizando códigos hexadecimales.
Las direcciones IP se representan como 4 cifras entre 0 y 255 separadas por puntos, por ejemplo "33.24.35.66". Esto debería cambiar gradualmente en el futuro con la implementación del Protocolo de Internet versión 6 en donde las direcciones son considerablemente más largas por lo que se representan utilizando códigos hexadecimales.
En el día a día, rara vez observamos estas direcciones porque mayormente hacemos uso de un servicio de ayuda llamado DNS o en español "Servicio de Nombres de Dominio". Este servicio se encarga de traducir una dirección como la de este blog "fuenteabierta.teubi.co" a la dirección IP correspondiente al servidor donde está alojado.
Esta resolución de nombres se realiza de manera completamente transparente al usuario de tal manera que nadie (en su sano juicio) debería de tener la necesidad de estar memorizando los números de las direcciones IP de los servidores con los que se comunica.
El Internet y las páginas web
Algo que confunde a mucha gente es el hecho de que los sitios web o son Internet. Las páginas web representan solo la parte "visible" de la Internet, existen muchos servicios que se encargan de proporcionar información haciendo uso de diferentes protocolos, las páginas web se transmiten haciendo uso del protocolo de transferencia de hipertexto (Mejor conocido como HTTP por sus siglas en inglés).
Existen muchos otros protocolos que nunca vez has utilizado directamente, por ejemplo tu e-Mail es entregado a tu buzon de correo haciendo uso del protocolo SMTP; Accedes a tu buzón de correo desde tu iPhone haciendo uso de ya sea el protocolo IMAP o POP; Puedes transferir archivos haciendo uso del protocolo FTP o Bittorrent; Y así, existen un sin fin de protocolos para transferir diferentes tipos de datos de distintas formas a través de Internet.
Para resumir digamos que los protocolos son "convenciones" de como se debe transmitir los datos a través de una conexión en Internet.
Tipos de conexiones
A pesar del sin fin de protocolos que existen, podemos decir que todos los protocolos hacen uso mayormente de los siguientes dos tipos de conexiones:
- Conexiones TCP: Orientadas a la transmisión "continua" de datos a través de flujos o "streams". Esto significa que resultan más útiles cuando queremos mantener una conexión activa o vamos a transmitir datos de manera continua. Poseen la ventaja que el protocolo se encarga de verificar que los datos sean enviados de manera correcta y de no ser así genera un error. El protocolo HTTP utiliza conexiones del tipo TCP.
- Conexiones UDP: Este tipo de conexiones envía "datagramas". Un datagrama es un pequeño bloque de datos. Son utilizadas cuando no nos interesa enviar información de manera continua y solo queremos transferir pequeños "bloques" de datos. El problema es que el protocolo no garantiza ni siquiera que los datos lleguen a su destino o que estos lleguen en orden, así que debemos de manejar eso directamente desde nuestro software. El protocolo DNS utiliza conexiones del tipo UDP. Hay formatos de video tipo "stream" que utilizan códecs de video especialmente diseñados para funcionar con pérdida de datos, por ello pueden ocupar fácilmente conexiones UDP.
Los números de puerto
Así como las máquinas que se conectan a Internet utilizan una dirección numérica para identificarse entre sí, cada conexión realizada en la computadora utiliza un número de puerto.
Los números de puerto van desde 0 hasta 65,535. El protocolo HTTP utiliza por convención el puerto 80. Así como sucede con el servicio DNS usualmente tu no verás estos números ya que por conveniencia se han definido algunos formatos textuales para acceder a los diferentes servicios.
Por ejemplo al escribir http://fuenteabiera.teubi.co/ realmente queremos decir que nos queremos conectar a la IP 74.125.196.121 al puerto 80.
El protocolo HTTP
Luego haber explicado lo anterior es momento de entrar en calor. El protocolo HTTP es tal vez el protocolo más difundido y más conocido por los usuarios de Internet, a través de el se transmiten las páginas web que observas a través de tu navegador.
El protocolo HTTP tiene la característica de transmitir únicamente "texto" o datos binarios codificados como texto, el formato más utilizado es el HTML o lenguaje de marcado de hipertexto.
¿Qué te parece si te digo que podemos hacer una conexión a un servidor web sin necesidad de abrir un navegador?
Si estás en windows o linux abre una consola de comandos y escribe lo siguiente:
$ telnet dev.teubi.co 80
Una vez aparezca el mensaje (en Linux, una pantalla negra en Windows):
Trying 67.23.250.27... Connected to dev.teubi.co. Escape character is '^]'.
Escribe lo siguiente (Presiona la tecla [Enter] cada vez que veas [entrar]):
GET /hola.php HTTP1.1[entrar] Host: dev.teubi.co[entrar] [entrar]
Luego de unos segundos verás algo como lo siguiente:
HTTP/1.1 200 OK Date: Fri, 01 Nov 2013 02:38:24 GMT Server: Apache/2.2.19 (Unix) mod_ssl/2.2.19 OpenSSL/0.9.8e-fips-rhel5 mod_auth_passthrough/2.1 mod_bwlimited/1.4 FrontPage/5.0.2.2635 X-Powered-By: PHP/5.2.17 Transfer-Encoding: chunked Content-Type: text/plain 37 Bienvenido a tu primera conexion HTTP sin un navegador! 0 Connection closed by foreign host.
¡Listo! Acabas de realizar tu primera conexión HTTP sin necesidad de abrir un navegador.
Examinando la petición (request)
GET /hola.php HTTP1.1
En esta línea estás indicando al servidor web que estás realizando un request del tipo GET. Este es el tipo más común de peticiones y significa que todos la información que requerimos está contenida en la petición. Lo más importante que tienes que tomar en cuenta es que solo colocamos la dirección al recurso y no la dirección completa.
Por ejemplo si queremos hacer una petición a "http://www.algunlugar.com/directorio/paginaweb/contenido.html", luego de "GET" solo debemos colocar "/directorio/paginaweb/contenido.html".
Host: dev.teubi.co[entrar]
Esta línea es conocida como "encabezado de la petición". Los encabezados puedes reconocerlos porque siempre tienen la forma "<nombre encabezado>:<valor>". El encabezado "Host:" es necesario ya que el protocolo HTTP es capaz de servir contenido de diferentes sitios web bajo la misma dirección IP. Así que debemos especificar cual es el sitio web del cual requerimos información.
Examinando la respuesta
HTTP/1.1 200 OK
La primera línea corresponde al "código" de respuesta del servidor web. Cada código tiene un significado diferente puedes encontrar una lista de códigos y sus significados en la Wikipedia.
El Código 200 nos indica que el recurso que solicitamos fue encontrado en el servidor y nos será enviado.
Date: Fri, 01 Nov 2013 02:38:24 GMT Server: Apache/2.2.19 (Unix) mod_ssl/2.2.19 OpenSSL/0.9.8e-fips-rhel5 mod_auth_passthrough/2.1 mod_bwlimited/1.4 FrontPage/5.0.2.2635 X-Powered-By: PHP/5.2.17 Transfer-Encoding: chunked Content-Type: text/plain
Al igual que con los encabezados de la petición, los encabezados de la respuesta nos sirven para conocer las características del servidor. En este caso el servidor nos responde con la fecha, información del servidor, información extra, la codificación del contenido y el tipo de contenido. En este caso la página de prueba no responde con HTML sino con texto plano, identificado con el tipo "text/plain".
37 Bienvenido a tu primera conexion HTTP sin un navegador! 0
Las últimas líneas son los datos de la respuesta. El primer número indica el "tamaño" de los datos que el servidor enviará. Luego sigue el contenido y por último un "0" que nos indica el final de los datos.
A pesar de ser un estándar, cada servidor web implementa de maneras diferentes el protocolo HTTP, por eso es que dejamos el trabajo de desarrollar navegadores web a empresas como Mozilla o Google.
Por último abre tu navegador y accede a la siguiente dirección:
Verás que el contenido es el mismo, pero en navegador se encarga de mostrarte únicamente los datos recibidos en vez de toda la información de encabezados y comandos de conexión.
Realizando conexiones HTTP con el SIM900
Conectando nuestro Arduino
Primero, antes de continuar, vamos a conectar el módulo al Arduino Micro, de la misma manera que lo hicimos con la entrada de envío de SMS:
En este ejemplo vamos a utilizar la interrupción de la línea 2 para realizar el envío de datos y la interrupción de la línea 3 para enviar la señal de apagado.
Los comandos AT para realizar conexiones
El SIM900 posee ciertos comandos que facilitan enormemente el establecimiento de conexiones TCP o UDP. Obviamente no posee funcionalidad específica para realizar conexiones haciendo uso del protocolo HTTP así que tendremos que hacer algo similar a lo que hicimos con el comando telnet solo que sobre la línea serial.
Para el caso del módulo GSM la conexión GPRS se realiza siguiendo el siguiente algoritmo:
- Iniciamos la conexión GPRS (AT+CGATT).
- Definimos el APN, usuario y clave a utilizar (AT+CSTT).
- Activamos el perfil de datos inalámbrico (AT+CIICR).
- Verificamos que se obtenga una dirección IP para el módulo (AT+CIFSR).
- Cerramos la conexión cuando no se utilice (AT+CIPSHUT)
- Desactivamos la conexión GPRS (AT+CGATT)
Idealmente no debería ser necesario que realicemos 5 y 6 si necesitamos que el equipo esté conectado siempre. Sin embargo en algunas aplicaciones que requiramos bajo consumo es posible que nos interese desactivar el GPRS cuando no tengamos información que enviar. Por ejemplo si es un módulo que debe reportar datos cada seis horas posiblemente obtengamos mayor autonomía de batería activando el GPRS únicamente cuando lo vayamos a enviar información.
Una vez el módulo se ha conectado a la red de datos el envío de datos se realiza mediante el siguiente algoritmo:
- Inicializamos una conexión TCP o UDP (AT+CIPSTART)
- Enviamos los datos. (AT+CIPSEND)
- Leemos los datos de respuesta del servidor.
- Cerramos la conexión. (AT+CIPCLOSE)
Algunas funciones de ayuda
Vamos a reutilizar gran parte del código que desarrollamos para el envío de SMS, pero vamos a hacer algunas modificaciones. Primero vamos a crear una función llamada waitForString(), esta función se encargará de leer el puerto serial hasta que reciba cierto comando. Esto es muy útil para crear una especie de "chat" donde enviamos un comando y recibimos una respuesta.
Esta función deberá tener también un "timeout" o tiempo de vencimiento, esto es para que luego de pasado cierto tiempo asumamos que el comando falló y permita que las demas funciones sigan trabajando adecuadamente.
Adicionalmente retornará un valor "verdadero" o "falso". Esto nos servirá para conocer si la respuesta que esperábamos fue encontrada o de no ser así cancelar la ejecución de la secuencia de comandos.
Adicionalmente retornará un valor "verdadero" o "falso". Esto nos servirá para conocer si la respuesta que esperábamos fue encontrada o de no ser así cancelar la ejecución de la secuencia de comandos.
bool waitForString(char* string, long waitForMilliseconds=5000) { clearBuffer(); long startTime = millis(); boolean found = false; Serial.print("Waiting for string: \""); Serial.print(string); Serial.print("\"\r\n"); while((millis()-startTime)<waitForMilliseconds) { if (mySerial.available()) { chr = mySerial.read(); Serial.write((char)chr); appendToBuffer((char)chr); if((char)chr=='\n') { if(strstr(buffer,string)!=NULL) { found = true; break; } else if(strstr(buffer,"ERROR")!=NULL) { found = false; break; } clearBuffer(); } } if (Serial.available()) mySerial.write(Serial.read()); } return found; }
Vamos a crear otra función similar a la anterior pero que utilizaremos cuando simplemente queremos escuchar datos por cierta cantidad de tiempo pero no nos interesa que datos sean recibidos, la usaremos simplemente cuando nos interese asegurarnos que el "buffer" esté limpio y queremos leer más datos.
void waitForData(int wait_delay) { long startTime = millis(); while((millis()-startTime)<wait_delay) { if (mySerial.available()) Serial.write(mySerial.read()); if (Serial.available()) { mySerial.write(Serial.read()); } } }
Todas las funciones de ayuda las colocaremos en el archivo "utils.ino", adicionalmente crearemos un archivo "utils.h", este último solo contendrá las definiciones de las funciones para evitar que Arduino genere errores de compilación.
Definiendo variables globales
Es necesario definir algunas variables. Vamos a comenzar definiendo en un archivo aparte "enums.h" un par de enumeradores que nos serán útiles para identificar el estado actual de conexión del módulo.
Archivo "enums.h":
// Enumerador para deteccion de conexion de modulo GSM. typedef enum { OFFLINE, ONLINE } gsmStatus; // Enumerador para deteccion de conexion GPRS. typedef enum { DISCONNECTED, CONNECTED } gprsStatus;
Al incio de nuestro proyecto de Arduino nos aseguramos de colocar todas estas variables:
#define BUFFSIZE 1024 #include#include #include "enums.h" #include "utils.h" // Buffer de datos serial char buffer[BUFFSIZE]; int buffSize = 0; volatile byte chr; // Eliminador de rebote por software volatile long lastInt = 0; // Definimos un SoftSerial donde conectaremos // el modulo GSM SoftwareSerial mySerial(10, 11); // RX, TX // Estas enumeraciones serviran para detectar // Si el modulo esta conectado y si esta activa // La red de datos gsmStatus currentStatus = OFFLINE; gprsStatus currentGPRS = DISCONNECTED; // Banderas para las interrupciones // Estas variables indicaran al loop // principal que debera de realizar una accion volatile boolean sendMessage = false; volatile boolean startShutDown = false;
Código de inicialización
Al igual que el código de inicialización para envío de SMS asociaremos las líneas de interrupción 0 y 1, correspondientes a las líneas 3 y 2 de Arduino, también se inicializará el puerto Serial:
void setup() { // Abrir el puerto serie Serial.begin(9600); while (!Serial) { ; // wait for serial port to connect. Needed for Leonardo only } // Inicializar el SoftSerial mySerial.begin(9600); // Inicializamos la ultima interrupcion para evitar que // se activen al encender lastInt = millis(); // Asignamos las interrupciones 0 y 1 pinMode(3,INPUT_PULLUP); // Maneja el apagado del modulo GSM attachInterrupt(0, pin3OnFalling, FALLING); pinMode(2,INPUT_PULLUP); // Maneja la conexion al GPRS y envio de datos attachInterrupt(1, pin2OnFalling, FALLING); Serial.print("Arduino: Setup finished.\r\n"); }
Manejo de Interrupciones
Como habíamos mencionado en artículos anteriores, lo importante del manejo de interrupciones es que sea rápido. Esto significa que el código únicamente se encargará de establecer una variable bandera que luego procesaremos en el loop principal:
void pin3OnFalling() { if((millis()-lastInt)>500) { startShutDown = true; lastInt = millis(); } } void pin2OnFalling() { if((millis()-lastInt)>500) { sendMessage = true; lastInt = millis(); } }
El loop principal
Aquí es donde se realizará toda la acción. La lógica es muy sencilla ya que se sigue el siguiente algoritmo:
- Si la variable de estado interna está como OFFLINE, intentará detectar el módulo. Para que el módulo sea detectado simplemente lo encendemos.
- Si la variable de estado interna está como ONLINE entonces procesaremos el envío de datos. Si el módulo esta DISCONNECTED entonces intentará conectar el GPRS, caso contrario realizará la petición GET.
- La línea de apagado siempre se procesa, originalmente había pensado procesarla solo si el módulo se encontraba ONLINE, pero luego decidí procesarla siempre en caso de que el estado del módulo almacenado se "desincronizara" con el estado real.
void loop() // run over and over { if(currentStatus==OFFLINE) { // Si el estatus es OFFLINE intentar detectar // el modulo por dos maneras Serial.write("Trying to detect SIM900 module\r\n"); // Esperando a Call ready if(waitForString("Call Ready",5000)) { Serial.write("GSM Module detected. Current status: ONLINE\r\n"); currentStatus=ONLINE; // O verificando mediante comandos AT } else if(checkForSIM900()) { Serial.write("GSM Module already connected. Changing status to: ONLINE\r\n"); currentStatus=ONLINE; } } if(currentStatus==ONLINE) { // Si esta ONLINE procesara el comando de la interrupcion if(sendMessage) { // La primera vez que reciba la interrupcion intentara conectar // Este codigo ignorara el envio del mensaje if(currentGPRS==DISCONNECTED) { Serial.print("GPRS is disconnected. Starting up GPRS data.\r\n"); Serial.print("Current request is going to be ignored.\r\n"); // try to SETUP GPRS before connect setupGPRS(); sendMessage = false; // Una vez este conectado // Intentara realizar la conexion } else if(currentGPRS==CONNECTED) { Serial.print("DATA Interrupt received\r\n"); GET(); sendMessage = false; } } bridge(); } if(startShutDown) { Serial.print("Shutdown interrupt received\r\n"); shutDown(); startShutDown = false; currentStatus = OFFLINE; currentGPRS = DISCONNECTED; } }
Ahora revisaremos sección por sección para comprender mejor el funcionamiento del código y su interacción con las funciones del módulo de GSM.
1 - Código de detección del módulo GSM
Aquí es donde podemos observar la gran utilidad de las funciones de ayuda, lo que realizamos es una especie de "chat", enviamos un comando y esperamos por la respuesta. Debido a que los comandos se ejecutan de manera secuencial, esperamos que las respuestas sean todas las adecuadas.
Primero esperamos por "Call Ready" este texto es enviado cuando encendemos por primera vez el módulo SIM900.
if(waitForString("Call Ready",5000)) { Serial.write("GSM Module detected. Current status: ONLINE\r\n"); currentStatus=ONLINE; }
Si el módulo ya estuviera encendido la función checkForSIM900() nos ayudará a detectarlo. Esta función ejecuta los siguientes comandos:
AT\r\n AT+CPIN?\r\n AT+CFUN?\r\n AT+CCALR?\r\n
Si toda la secuencia se ejecuta correctamente entonces se marca el módulo como detectado.
boolean checkForSIM900() { // AT revisa que el modulo este conectado y responda pushSlow("AT\r\n"); if(!waitForString("OK",5000)) return false; // Chequea que la SIMCARD no requira PIN pushSlow("AT+CPIN?\r\n"); if(!waitForString("+CPIN: READY",5000)) return false; // CFUN verifica que toda la funcionalidad // esté disponible pushSlow("AT+CFUN?\r\n"); if(!waitForString("+CFUN: 1",5000)) return false; // CCALR revisa que se puedan // realizar llamadas pushSlow("AT+CCALR?\r\n"); if(!waitForString("+CCALR: 1",5000)) return false; return true; }
2.1 Código de configuración de la conexión GPRS
Este código se encarga de configurar la conexión GPRS. Antes de intentar conectarnos deshabilitamos la conexión actual. Por alguna razón (supongo causado por el proveedor) algunas veces el módulo se conectaba automáticamente y otras no. Así que para garantizar que siempre siguiera la misma secuencia lo más sencillo de realizar era forzar una desconexión y conectarla nuevamente por medio de los siguientes comandos:
AT+CGATT=1\r\n AT+CSTT="internet.tigo.sv","",""\r\n AT+CIICR\r\n AT+CIFSR\r\n
Al igual que la detección del módulo solo si todos los comandos se ejecutan se considera que la conexión ha sido exitosa.
void setupGPRS() { // Enviamos [Enter] para limpiar cualquier // comando previo pushSlow("\r\n"); waitForData(1000); // Desconectamos el GPRS // para evitar conflictos. shutdownGRPS(); // Conectamos nuevamente pushSlow("AT+CGATT=1\r\n"); if(!waitForString("OK",10000)) { shutdownGRPS(); return; } pushSlow("AT+CSTT=\"internet.tigo.sv\",\"\",\"\"\r\n"); if(!waitForString("OK",10000)) { shutdownGRPS(); return; } pushSlow("AT+CIICR\r\n"); // Habilitar conexiones Wireless if(!waitForString("OK",10000)) { shutdownGRPS(); return; } pushSlow("AT+CIFSR\r\n"); // Obtener IP local waitForData(1000); currentGPRS = CONNECTED; }
En mi caso estoy utilizando un chip de Tigo El Salvador y el APN corresponde a "internet.tigo.sv", si deseas utilizar otro proveedor solo debes averiguar el APN correspondiente y modificarlo en la línea correspondiente.
Si la conexión falla por cualquier motivo, entonces deshabilitamos el GPRS mediante los siguientes comandos:
AT+CIPSHUT\r\n AT+CGATT=0\r\n
Y el código que maneja la desconexión:
void shutdownGRPS() { // Desactiva las conexiones del modulo pushSlow("AT+CIPSHUT\r\n"); waitForData(3000); // Desactiva el GPRS pushSlow("AT+CGATT=0\r\n"); waitForData(3000); currentGPRS = DISCONNECTED; }
2.2 Código de petición GET
Una vez el módulo se encuentra conectado a la red de datos y tiene su dirección IP asignada podemos comenzar a realizar conexiones a servidores.
Aquí nos detendremos un momento a revisar cada uno de los comandos que enviamos, comenzamos con establecer una conexión con:
AT+CIPSTART="TCP","dev.teubi.co",80\r\n
Nota: \r\n equivale a [Enter] en C.
El comando anterior equivale a decir "Quiero crear una nueva conexión, de tipo TCP al servidor cuyo nombre es dev.teubi.co al puerto HTTP correspondiente al número 80".
Este comando nos responderá con "CONNECT OK" una vez la conexión haya sido establecida. Como es una conexión "TCP" se mantendrá abierta en tanto nosotros enviemos datos.
Para enviar datos utilizaremos el comando:
AT+CIPSEND\r\n
El modem nos responderá con un "prompt" ">" indicando que podemos comenzar a escribir nuestros datos.
> GET /hola.php HTTP/1.1\r\n Host: dev.teubi.co\r\n \r\n \x1A
El comando anterior equivale a decir, ahora que estamos conectados al servidor "http://dev.teubi.co/" quiero la pagina web "/hola.php". El código "\x1A" es un carácter especial que le indica a módem que no enviaremos más datos. Una vez los datos hayan sido enviados responderá con "SEND OK".
Automáticamente el servidor cerrará la conexión y nos aparecerá la indicación "CLOSED". Pero enviaremos un AT+CIPCLOSE en caso de que por algun motivo la conexión quedara abierta.
Esto último es importante ya que el stack TCP/IP incluido en el módem solo es capaz de manejar una conexión a la vez.
El código que maneja todo lo anterior se muestra a continuación:
void GET() { // Enviamos [Enter] para limpiar cualquier // comando previo pushSlow("\r\n"); waitForData(1000); pushSlow("AT+CIPSTART=\"TCP\",\"dev.teubi.co\",80\r\n"); if(!waitForString("CONNECT OK",30000)) { return; } pushSlow("AT+CIPSEND\r\n"); waitForData(1000); pushSlow("GET /hola.php HTTP/1.1\r\n"); pushSlow("Host: dev.teubi.co\r\n"); pushSlow("Connection: Keep-Alive\r\n"); pushSlow("\r\n"); pushSlow("\x1A"); if(!waitForString("SEND OK",15000)) { return; } waitForData(15000); pushSlow("AT+CIPCLOSE\r\n"); if(!waitForString("CLOSE OK",5000)) { return; } }
Comandos de apagado
El comando de apagado ya lo habíamos revisado antes, solo que para esta versión lo hemos modificado de tal manera que guarda el estado de desconexión para esperar nuevamente a que el módem esté disponible:
void shutDown() { // Envia el comando de apagado pushSlow("\r\n"); pushSlow("AT+CPOWD=1\r\n"); }
Un pequeño video
Puede que lo hayas visto al principio pero te dejamos nuevamente el video
donde explicábamos en general el funcionamiento del módulo para que lo
tengas como referencia.
Código fuente
Puedes descargar el código fuente desde GitHub en la siguiente dirección:
Concluyendo
Si bien la configuración puede parecer complicada, ahora tienes la oportunidad de que tu dispositivo se comunique prácticamente con cualquier servidor de Internet o incluso con otros dispositivos.
El concepto del Internet of things se basa en dispositivos inteligentes que se comunican entre sí para facilitarte la vida. ¿En que proyecto estás pensando ahora que no tienes limitaciones para que tu dispositivo se conecte desde cualquier lugar a cualquier hora?
Comentarios
Tenemos un modulo Eledfreaks Efcom pro V1.1 conectado a un Arduino Mega.
El proyecto comenzado como hobby consiste en el desarrollo de una máquina de vending para provisión industrial conectada a un servidor. Si bien partimos de conocimiento cero de Arduino y programación, ahora con un año de trabajo tenemos desarrollado el programa que maneja los motores y genera las tablas de usuarios, consumo y disponibilidad, tablas que tenemos que subir y bajar del servidor (recién estamos epezando a estudiar PHP y Mysql).
Voy a la pregunta concreta:
1- Como profundizar el conocimiento de los comandos AT.
2- En el tutorial el comando GET está limitado por tiempo, ¿hay forma de cerrar la comunicación por algún parámetro de fin de archivo.(en realidad todos los comandos son manejados por tiempo el que nos preocupa es GET).
3- La idea es tratar de desarrollar que la comunicación sea opcional wifi y si no hay, que use el módulo Gprs.¿ podrás orientarnos donde estudiar esto?
Sabes que podría ser ?
Al llegar SEND OK deja de recibir la respueste del servidor
Gracias.
Es esto restringido por los proveedores de telefonía?
logica_Razon@hotmail.com
En primer lugar enhorabuena por el artículo, está muy bien explicado.
Aquí hemos visto como solicitar información vía TCP desde la SIM900 a un servidor, con el comando GET. ¿Sería posible hacerlo de forma inversa? Es decir, hacer una petición desde un terminal móvil para obtener los datos de un sensor (ejemplo: DameTemperatura()), o incluso pedirle desde un terminal móvil "Activar Pin3".
Un saludo.
Hemos realizado una instalación de una farola autónoma en Auckland (Nueva Zelanda) y tenemos un problema de comunicaciones, explico a continuación:
En la instalación autónoma de la farola de Auckland, utilizamos un módem Quectel M95 con una tarjeta de vodafone de Nueva Zelanda, el módem funciona bien en estos pasos:
1- Prueba de conexión GPRS y GSM: OK
2- Tome la hora local y cambiarlo: OK
3 - Obtener una dirección IP: OK
Pero cuando se está esperando la respuesta de ping, no recibe respuesta.
Necesitamos enviar un pequeño archivo (1,2 kb aprox) a un servidor FTP cada media hora, pero el módem se queda en espera de recibir respuesta abriendo el FTP.
Por otro lado, y en el caso del sistema vandálico, el módem envía un SMS al teléfono designado por el cliente; el SMS se envía pero el teléfono receptor recibe un SMS vacío, sin el texto definido como alarma en el módem.
Hemos probado el módem y funciona bien en España, y el fabricante del módem dice que el protocolo de comunicación está bien, ya no sabemos que hacer....
Creemos que es posible fallo dependiendo de los diferentes APN o restricción alguna con el servicio de vodafone.
Nuestro socio NZ nos envió una tarjeta de NZ SIM, hemos probado muchos APN, los siguientes APN funciona bien en España con la tarjeta de NZ (con roaming)
www.vodafone.net.nz
vodafone
Internet
... pero en Nueva Zelanda no funciona ninguno de estos APN, incluyendo: live.vodafone.com
Agradecería un poco de luz al respecto.... GRACIAS Y SALUDOS
Tengo un pequeño problema... Estoy usando el Arduino Mega y el Shield M95 de quectel (que se pone encima del arduino).. tengo entendido que igual el sim900 usa comandos AT, ya he realizado un par de pruebas distintas como envio de SMS y ha funcionado bien (el unico problema es que tengo que alimentar con una fuente externa) he revisado tu codigo y lo he cambiado un poco para probarlo en mi M95 pero al correrlo e intentar encerder el modulo este no da respuesta. No se si es por que no funcionan los comandos que estoy usando o se deba a otro problema, espero que me puedas ayudar a solucionar mi problema y muchas gracias.
si es asi, como lo hago por favor
Muchas gracias
Retirar el máximo de 5.000 dólares diarios por un máximo de 30
Días vía (wesleymarkhackers@gmail.com).
Estoy muy feliz por esto porque tengo la mía la semana pasada y la he usado para obtener $ 150,000. Wesley marca Hackers está dando
La tarjeta sólo para ayudar a los pobres y necesitados, aunque es ilegal, pero
Es algo agradable y no es como otro estafa fingiendo
Para tener las tarjetas de cajero automático en blanco. Y nadie es atrapado cuando
Utilizando la tarjeta. ¡Consiga el suyo de los hackers de la marca de wesley hoy! Solo envía un correo electrónico
A (wesleymarkhackers@gmail.com)
loans, student loans, debt consolidation loans, unsecured loans, risk
capital, etc. ... You are in the right place
Your loan solutions! I am a private lender who lends
Individuals and businesses at a low interest rate and affordable
Interest rate of 3%. Contact us by email: powerfinance7@gmail.com
LOAN APPLICATION FORM
**********************
Your full name:
Country/State:
Loan Amount:
Duration
Phone:
Monthly income:
Occupation:
Awaiting your swift response.
May Allah bless you.
IBRAHIM MUSA
power Financial Service Pvt.
Contact Us At :powerfinance7@gmail.com
WhatsApp Number +919717357946
Primero quiero felicitarte por excelente explicación. Y en segundo lugar tengo una duda.
Verás que estoy interesado en comprar un "Modulo Shield Sim808 Gsm Gps Gprs Con Antenas"
y quiero saber si este módulo soporta peticiones http get y post. En otras palabras quiero saber si todo dispositivo que soporte gprs puede hacer peticiones http get y post?
Muchas gracias con anticipación.
mi correo hugo_dw@outlook.es