Mostrando entradas con la etiqueta SMS. Mostrar todas las entradas
Mostrando entradas con la etiqueta SMS. Mostrar todas las entradas

Cómo enviar un SMS desde cero ( I )

En esta serie de posts os enseñaré cómo se envía un SMS desde cero. 


Para empezar tenemos que tener un hardware específico, que en mi caso es un módem modelo MC35i, tiene una salida para una antena con un imán en la base para fijarla firmemente a un soporte, en la parte de atrás tiene un conector DB9 que es el puerto COM del equipo, que tendremos que unir a la salida del puerto serie del PC, una ranura para insertar la tarjeta SIM que nos la proporcionará nuestro operador de telefonía y por último una salida para poder conectar un teléfono.

Aquí tenéis algunas fotos:





























Pues una vez que hemos conectado el módem al PC por el puerto serie y le hemos encendido (parpadeará un led verde), vamos a configurarlo:




En este caso he utilizado Delphi 7 y Turbo Power Async Pro (o cualquier otra utilidad que os permita enviar y recibir texto por un puerto serie)




Instalamos Turbo Power y ponemos el objeto ApdComPort1 en el Form de nuestra aplicación, con las siguientes propiedades:


AutoOpen=TRUE, para que se active cuando iniciamos el programa.

Baud=9600 se podría poner a 19200 con este módem, pero he visto que trabaja mejor a esta velocidad.

ComNumber=8 es el número de puerto COM

DataBits=8, StopBits=1, SWFlowOption=swfNone









El Form contendrá un botón (Caption=INICIO) y un Grid, donde mostraremos fila por fila los parámetros de inicialización del módem












La inicialización del módem se hace utilizando comandos AT .


Existen cuatro formatos de ejecución para cada  comando AT. Cada
formato se determina generalmente por la sintaxis según se presenta en la
siguiente tabla:





























Comandos de prueba


AT+CXXX=?


Devuelve una lista de los
posibles parámetros que se pueden introducir con el correspondiente parámetro
de escritura.



Comandos de lectura


AT+CXXX?


Devuelve el parámetro o
conjunto de parámetros actualmente establecidos.



Comandos de escritura


AT+CXXX=<...>


Establece el valor a los
parámetros introducido por el usuario.



Comandos de ejecución


AT+CXXX


Este comando utiliza
parámetros predefinidos en caso de que no hayan sido modificados con el
correspondiente comando de escritura.






La respuesta dada por el módem a cada comando es distinta dependiendo del formato, incluso a pesar de que el comando sea el mismo.




Al final de cada comando se debe incluir un retorno de carro.

Los comandos para el  MC35i son los siguientes:






 Comandos
generales.




































Comando


Sintaxis / Respuesta


Descripción


AT


AT


OK


Verifica que la
comunicación se ha establecido pero no realiza ninguna acción. La respuesta
del terminal es OK. De ahora en adelante se marcara en rojo la respuesta del
terminal.


AT+CPIN


AT+CPIN=


OK


CPIN=?


READY


Permite introducir
el código PIN para poder utilizar la tarjeta SIM.


Una vez lo hemos
introducido se puede comprobar si es correcto ejecutando el correspondiente
comando de lectura.


AT+CGMI


AT+CGMI


Identifica al
fabricante del terminal.


AT+CGMM


AT+CGMM


Identifica el
modelo del terminal.


AT+CVIB


AT+CVIB=1





OK


ERROR


Activa el modo
vibración. Sólo está disponible para terminales que tengan vibrador
incorporado.


Si el modo
vibrador se ha activado correctamente


Si el modo
vibrador no esta disponible







Comandos para
control de llamadas.































Comando


Sintaxis / Respuesta


Descripción


ATD


Ó


ATDT


ATD [;]








OK


NO DIALTONE


BUSY


Realiza una
llamada de teléfono al número dado por n. Es importante enviar ; al terminar, en
caso contrario la llamada será una llamada de datos. debe ser una
cadena de caracteres.


Siempre se recibe
esta respuesta.


Se recibe además
de la anterior sino hay tono.


Si el interlocutor
esta ocupado.


ATA


ATA


OK


CONNECT


NO CARRIER


Responder a una
llamada.


En el caso de
llamada de voz.


En el caso de
llamada de datos.


En el caso de que
lo haya fallo de conexión.


ATH


ATH


OK


Finalizar la
llamada en curso.


Llamada finalizada
con éxito.


ATDL


ATDL


ERROR


Rellamada.


No hay ningún
número como último número marcado.







                    Comandos para
gestión de la memoria.


























Comando


Sintaxis / Respuesta


Descripción


AT+CPBS


AT+CPBS=


OK


AT+CPBS=?





+CPBS: lista
posible


OK


Selecciona la memoria activa dada por storage. Storage es una cadena de
caracteres.


Consulta la lista de las posibles unidades
de almacenamiento.


Devuelve dicha lista.


AT+CPBR


AT+CPBR=


Lee de la memoria activa la entrada en
dicha agenda situada en la posición dada por el entero location. Si dicho entero
supera el límite de almacenamiento se devolverá un error.


AT^SDLD


AT^SDLD


OK


ERROR


Borra el número establecido como último
número marcado.







Comandos para el envío y recepción de SMS.








































Comando


Sintaxis / Respuesta


Descripción


AT+CMGF


AT+CMGF


OK


Activa/Desactiva
el modo texto.


Con el
correspondiente comando de prueba se puede consultar el estado: 1, activado,
0, desactivado


AT+CMGR


AT+CMGR=


OK


Lee el mensaje almacenado
en la posición de la memoria activa, dada por el entero n.


AT+CMGD


AT+CMGR=


OK


Borra el mensaje
almacenado en la posición de la memoria activa, dada por el entero n.


AT+CMSS


AT+CMSS=


OK


Reenvía el
mensaje, anteriormente enviado, almacenado en la posición de la memoria
activa dada por el entero n.


AT+CMGS


AT+CMGS=””[,]











> ^z


+CMGS: 149


OK


Envia un mensaje
SMS al numero de teléfono indicado en n. n es una cadena de caracteres. Si n
incluye el prefijo internacional el tipo de destino puede dejarse en blanco.
es un retorno de carro.


El
modem responde con > y enviamos el cuerpo del mensaje, texto, seguido de
^z (Ctrl z)











En siguientes posts veremos cómo preparar al módem para enviar y recibir SMS




Cómo enviar un SMS desde cero ( II )

Continuado con el post anterior aquí tienen cómo se inicializa el módem.









Para ello he puesto un Botón llamado "Conectar" dentro del Form con el siguiente procedimiento que lo que hace es:
Enviar un ATE0 para quitar el "eco" de los caracteres, después le decimos que queremos enviar un texto AT+CMGF=1,  y por último leemos varios parámetros:

- AT+CSQ (Potencia de la señal), posibles respuestas son:


0 113 dBm or menos
1 111 dBm
2...30 109... 53 dBm
31 51 dBm o más
99 desconocido o no detectable








ComandoPosibles respuestas
+CSQ+CSQ: , +CME ERROR: 
+CSQ=?+CSQ: (list of supporteds),(list of supporteds)



- AT+CMGF: Pone el módem en modo texto (=1)  o en modo PDU (=0), en nuestro caso será en texto.

- AT+CNMI : queremos preguntar al módem cómo serán tratados los nuevos SMS recibidos
Su respuesta es: AT+CNMI=,,,,




=1 Descarga los códigos de resultado no solicitados cuando el link TA-TE está reservado.






=1 Devuelve los SMS.






=0 no hay indicaciones CBM para rutar al TE.




=0 no SMS-STATUS-REPORTs son rutados.



=0 El buffer del TA de códigos de resultado no solicitados definidos con este comando son borrados del TE.

- AT+CPMS Almacenamiento preferido del mensaje.

- AT+CSCA  Informa del número del Centro de Servicio






PROCEDURE TForm1.BitBtn1Click(Sender: TObject);
VAR i: integer;
BEGIN
enviar('ATE0', Rdo, CodigoError);
IF CodigoError <> 0 THEN
BEGIN
showmessage('Se ha producido el error: ' + Rdo)
END
ELSE
BEGIN
enviar('AT+CMGF=1', rdo, CodigoError);
END;
//muestra en un Grid, fila a fila, distintos parámetros del modem
RellenarGrid(1, 'Calidad de señal', 'AT+CSQ');
RellenarGrid(2, 'PDU/TEXTO', 'AT+CMGF=?');
RellenarGrid(3, 'PDU/TEXTO Modo Activo', 'AT+CMGF?');
RellenarGrid(4, 'CNMI', 'AT+CNMI?');
RellenarGrid(5, 'CPMS', 'AT+CPMS?');
//El Centro de Servicio viene dado por el operador de telefonía
//Es el que se encargar de gestionar los envíos
RellenarGrid(6, 'Centro de servicio', 'AT+CSCA?');
Application.processmessages;
label8.visible := false;
END;

PROCEDURE tform1.RellenarGrid(Fila: integer; Texto, ComandoAT: ansistring);
BEGIN
Grid2.Cells[0, Fila] := Texto;
enviar(ComandoAT, Rdo, CodigoError);
IF CodigoError = 0 THEN
BEGIN
IF Ansipos(':', Rdo) > 0 THEN Rdo := Gettoken(Rdo, ':', 2);
Rdo := stringReplace(Rdo, 'AT+', '', [rfreplaceAll]);
Rdo := stringReplace(Rdo, OK, '', [rfreplaceAll]);
Rdo := stringReplace(Rdo, chr(13) + chr(10) + 'OK', '', [rfreplaceAll]);
Rdo := stringReplace(Rdo, chr(13), '', [rfreplaceAll]);
Rdo := stringReplace(Rdo, chr(10), '', [rfreplaceAll]);
Grid2.Cells[1, Fila] := Rdo;
END
ELSE Grid2.Cells[1, Fila] := 'Error';
END;


Procedimiento que envía el comando AT al módem





PROCEDURE tform1.enviar(at: ANSISTRING; VAR Rdo: ansistring; VAR CodigoError: integer);
BEGIN
CodigoError := 0;
Edit1.TExt := '';
rdo := '';
Terminado := False;
Segundos := 0;
IF (FStatusTrigger = 0) THEN
BEGIN
FStatusTrigger := ApdComPort1.AddStatusTrigger(stLine);
ApdComPort1.SetStatusTrigger(FStatusTrigger,
lsOverrun OR lsParity OR lsFraming OR lsBreak,
True);
END;
memo1.Lines.add('>>' + at + chr(13));
timer1.Enabled := true;
ApdComPort1.OutPut := at + chr(13);
REPEAT
delay(2000)
UNTIL Terminado;
END;



Es un objeto tTimer que se encarga de comprobar si el módem
ha respondido con un OK o con un ERROR








PROCEDURE TForm1.Timer1Timer(Sender: TObject);
BEGIN
IF (ansipos(chr(13) + chr(10) + 'OK' + chr(13) + chr(10), Rdo) > 0)
OR (Segundos > 15)
OR (ansipos(chr(13) + chr(10) + 'ERROR' + chr(13) + chr(10), Rdo) > 0)
OR (ansipos(chr(13) + chr(10) + '>', Rdo) > 0)
THEN
BEGIN
IF Segundos > 15 THEN CodigoError := 1; //Timeout
IF (ansipos(chr(13) + chr(10) + 'ERROR' + chr(13) + chr(10), Rdo) > 0)
THEN CodigoError := 2; //Se ha producido un error
terminado := true;
timer1.Enabled := false;
END
ELSE inc(Segundos);

END;





Procedimiento del objeto ApdComPort1 que se dispara para recoger los caracteres del buffer del puerto serie





PROCEDURE TForm1.ApdComPort1TriggerAvail(CP: TObject; Count: Word);

VAR
I: Word;
C: Char;
S, s1: STRING;
BEGIN
FOR I := 1 TO Count DO BEGIN
C := ApdComPort1.GetChar;
s1 := c;
Rdo := Rdo + s1;
END;

memo1.lines.add(Rdo);
IF ansipos(chr(13) + chr(10) + 'OK' + chr(13) + chr(10), Rdo) > 0
THEN
BEGIN
application.processmessages;
edit1.Text := Rdo;
END;
END;





Seguiremos con más procedimientos en próximos posts




Cómo enviar un SMS desde cero ( y III )

Continuando con la serie de posts, a continuación veremos cómo se envía un SMS.

Suponemos que en el Form tenemos:


- Una lista de números telefónicos almacenados en un grid con varias columnas (en la columna 3 está el número de teléfono donde hay que enviar el SMS), 


- Un TButton con el siguiente procedimiento asociado al evento OnClick, su función es ir leyendo fila a fila el grid obteniendo el número de teléfono y el texto a enviar, que en este caso he puesto un texto fijo, pero que si lo que queréis es enviar un texto diferente a cada número de teléfono, se almacenaría en la columna 1 para leerlo de esta forma TEXTO:= grid3.Cells[0, i];



PROCEDURE TForm1.Button6Click(Sender: TObject);
VAR
texto, CeldaX, Nombre,telefono: ansistring;
i: integer;
BEGIN
TRY
Application.processmessages;
Label1.caption := 'ENVIANDO SMS...';
FOR i := 1 TO grid3.rowcount - 1 DO
BEGIN
grid3.SetFocus;
grid3.Row := i;
BEGIN
TEXTO := 'Este es el texto del SMS';
Telefono:= grid3.Cells[2, i];
EnviarSMS(telefono,texto, Rdo, CodigoError);
IF ansipos(chr(13) + chr(10) + '+CMGS:', Rdo) > 0 THEN
BEGIN
// Si el envío es correcto pone en la columna 5 del grid un OK+Fecha
grid3.cells[4, i] := 'OK: ' + DateTostr(now);
END
ELSE grid3.cells[4, i] := '===ERROR==='
END;
END;
FINALLY
Application.processmessages;
Label1.caption := 'ENVÍO TERMINADO';
END;
END;



PROCEDURE tForm1.EnviarSMS(Telefono, texto: ansistring; VAR Rdo: ansistring; VAR CodigoError: Integer);
BEGIN
enviar('AT+CMGS="' + telefono + '"', Rdo, CodigoError);
//Después del comando at+cmgs el modem devuelve: >
IF ansipos('>', Rdo) > 0 THEN
BEGIN
enviar('"' + texto + '"' + ^Z, Rdo, CodigoError);
END;
END;




El procedimiento "enviar" es el mismo que anteriores posts, pero lo pongo para facilitar la comprensión del procedimiento anterior 





PROCEDURE tform1.enviar(at: ANSISTRING; VAR Rdo: ansistring; VAR CodigoError: integer);
BEGIN
CodigoError := 0;
Edit1.TExt := '';
rdo := '';
Terminado := False;
Segundos := 0;
IF (FStatusTrigger = 0) THEN
BEGIN
FStatusTrigger := ApdComPort1.AddStatusTrigger(stLine);
ApdComPort1.SetStatusTrigger(FStatusTrigger,
lsOverrun OR lsParity OR lsFraming OR lsBreak,
True);
END;
memo1.Lines.add('>>' + at + chr(13));
timer1.Enabled := true;
ApdComPort1.OutPut := at + chr(13);
REPEAT
delay(2000)
UNTIL Terminado;
END;


Procedimiento del objeto ApdComPort1, que se dispara para recoger los caracteres del buffer

PROCEDURE TForm1.ApdComPort1TriggerAvail(CP: TObject; Count: Word);
{Event OnTriggerAvail - Example how OnTriggerAvail works}
VAR
I: Word;
C: Char;
S, s1: STRING;
BEGIN
FOR I := 1 TO Count DO BEGIN
C := ApdComPort1.GetChar;
s1 := c;
Rdo := Rdo + s1;
END;

memo1.lines.add(Rdo);
IF ansipos(chr(13) + chr(10) + 'OK' + chr(13) + chr(10), Rdo) > 0
THEN
BEGIN
application.processmessages;
edit1.Text := Rdo;
END;
END;





Si queremos leer todos los mensajes almacenados en la SIM y copiarlos en el Grid1  tendremos que utilizar el comando AT+CMGL=all  de la siguiente forma:



PROCEDURE TForm1.Button2Click(Sender: TObject);
VAR
linea1, linea2: ansistring;
contador, contadorfila: integer;
HayParametros: boolean;
BEGIN
contador := 2; contadorfila := 1; HayParametros := false;
//Lee todos los mensajes de la SIM
enviar('AT+CMGL=all', Rdo, CodigoError);
REPEAT
//captura el token nº “contador” de la cadena RDO, separada por el carácter chr(13))
linea1 := gettoken(Rdo, chr(13), contador);
IF ansipos('+CMGL:', linea1) > 0 THEN
BEGIN
inc(contadorFila);
Grid1.Cells[0, contadorFila] := gettoken(linea1, ',', 1);
Grid1.Cells[1, contadorFila] := gettoken(linea1, ',', 2);
Grid1.Cells[2, contadorFila] := gettoken(linea1, ',', 3);
Grid1.Cells[4, contadorFila] := gettoken(linea1, ',', 4);
Grid1.Cells[5, contadorFila] := gettoken(linea1, ',', 5);
Grid1.Cells[6, contadorFila] := gettoken(linea1, ',', 6);
Grid1.Cells[7, contadorFila] := gettoken(linea1, ',', 7);
Grid1.Cells[8, contadorFila] := gettoken(linea1, ',', 8);
HayParametros := true;
END
ELSE
BEGIN
IF HayParametros THEN
BEGIN
Grid1.Cells[9, contadorFila] := linea1;
END;
HayParametros := false;
END;
inc(contador);
UNTIL (ansipos('OK', LINEA1) > 0) OR (ansipos('OK', LINEA2) > 0) OR (contador > 100);
END;





Para borrar todos los mensajes de la SIM tendremos que usar el comando AT+CMGD=numero del mensaje



PROCEDURE TForm1.Button1Click(Sender: TObject);
VAR
I: INTEGER;
BEGIN
FOR I := 0 TO Grid1.rowcount - 1 DO
BEGIN
application.processmessages;
label7.caption := 'Borrando mensaje: ' + inttostr(i);
application.processmessages;
enviar('AT+CMGD=' + inttoStr(i), Rdo, CodigoError);
END;
END;



Una vez que se muestran todos los mensajes en la rejilla podremos borrar un mensaje cualquiera haciendo doble clic sobre una fila , utilizando el siguiente procedimiento:





PROCEDURE TForm1.Grid1DblClick(Sender: TObject);
VAR
NumeroDeMensaje: ansistring;
i: integer;
BEGIN
IF MessageDlg('Eliminar mensaje ?' + grid1.Cells[0, FilaSeleccionada],
mtConfirmation, [mbYes, mbNo], 0) = mryes THEN
BEGIN
NumeroDeMensaje := gettoken(grid1.Cells[0, FilaSeleccionada], ':', 2);
enviar('AT+CMGD=' + NumeroDeMensaje, Rdo, CodigoError);
IF CodigoError = 0 THEN
BEGIN
FOR i := 0 TO grid1.ColCount - 1 DO grid1.Cells[i, FilaSeleccionada] := '';
END;
END;
END;




como enviar un sms con Delphi con zenvia


Zenvia es la empresa líder en movilidad corporativa de Brasil y ofrece a sus clientes la posibilidad de gestionar los envíos SMS desde aplicaciones externas. El método que presento es la forma de gestionar esos envíos desde una aplicación realizada en Delphi.






Ajuste el envío





Primer paso


Haga la  descarga de la biblioteca de integración  en ella se encuentran los  
siguientes archivos:. HumanApiClient 
   Indy _9_00_17_ src. Zip.





Paso 2


Añadir a la  ruta de búsqueda  de  Delphi  el directorio donde están las fuentes del paquete


Indy  y el paquete  HumanClient.





Paso 3


Para cualquier operación de  acceso a enviar  SMS, es necesario identificarse con su


cuenta y código de acceso. Vamos a trabajar con instancias de clases TSimpleSending   TMultipleSending  para el manejo de  SMS  (envío y consulta) 


a través de sus parámetros del constructor de su cuenta y código de acceso.  
Estos datos son transferidos por 
 Zenvia  junto con la negociación del contrato  
firmado con la empresa.





Ejemplo:





sms: = TMultipleSending.create ('Cuenta', 'contraseña');


Envío de  SMS  de forma individual


Primer paso


Utilizar una instancia de la clase  TSimpleSending con su cuenta y contraseña.


Ejemplo:





var


    ret: string;


    sms: TSimpleSending;


comenzar  


    sms: = TSimpleSending.create ('Cuenta', 'contraseña');








Paso 2


Agregue la información de  Para  (requerido)  Mensaje  (requerido)  De  (opcional), Id  (opcional) Horario  (opcional) y devolución de llamada  (opcional)
 


Ejemplo:





sms.From: = 'YourCo';


sms.ToNumber: = 'NumeroDeDestino';


sms.Msg: = 'SuaMensagem';











Paso 3


Llame al método  TSimpleSending.send



Ejemplo:





ret: sms.send = ();





Paso 4



El método de envío de retorno es una  cadena;el  texto que se puede ver en el código y la descripción de la solicitud y el estado 
 de SMS  enviados.


Ejemplo:





StatusBar1.Panels [0] .Text: = ret;    








Envío múltiple  de SMS


Primer paso


Instancia de la clase  TMultipleSending con su cuenta y contraseña.


Ejemplo:





var


    ret: TStrings;


    sms: TMultipleSending;


    Fecha: string;


    typeLayout: string;


comenzar


    sms: = TMultipleSending.create ('Cuenta', 'contraseña');


   


Paso 2





Llame al método  TMultipleSending.LoadList, para llenar una  cadena 
con la lista de  SMS  para ser enviados y el  tipo de diseño de la lista.
En nuestro ejemplo, vamos a elegir la 
 disposición  A, que consiste en
 
"numeroDeTelefone; textoDaMensagem".





Ejemplo:





fecha: = '555199990101; testen555199990102 mensaje; Mensaje de prueba ";


typeLayout: = 'A';


sms.LoadList (fecha, typeLayout);








Paso 3


Llame al método  TMultipleSending.send, a través de clases de parámetros ListResource.


Ejemplo:





ret: sms.send = ();








Paso 4


El método de envío de retorno es un  TStrings; texto que se puede incluir en el código junto con la descripción de la solicitud y el estado del  SMS  enviado a través  de devolución de llamada.


Ejemplo:





ShowMessage (ret.Text);


Fuente: 
programadordelphiatual.blogspot.com.es



Simulación del movimiento de los electrones en un campo electrico

Espectacular simulación realizada con OpenGL del movimiento de los electrones cuando atraviesan un campo eléctrico. Como muestra la image...