![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
gsm
Dependencies: DebouncedIn mbed
Fork of CLASEDELGSM1 by
main.cpp@6:4cece0df6a3b, 2016-05-10 (annotated)
- Committer:
- tony63
- Date:
- Tue May 10 12:52:36 2016 +0000
- Revision:
- 6:4cece0df6a3b
- Parent:
- 5:dbb0384120e0
- Child:
- 7:08dac00ecff7
Esta actualizaci?n env?a acuse de recibo OK, si el mensaje se procesa de forma remota
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
tony63 | 6:4cece0df6a3b | 1 | /*************************Alarma Contra Robo*******ver:01.may 10 2016 ************************************************** |
tony63 | 6:4cece0df6a3b | 2 | Como modem usa un celular SIEMENS a56i (ver compatibilidad mandos AT otros modems) |
tony63 | 4:0b889f7a8eba | 3 | Envia el mensaje intruso y otras cosas (mire el codigo de abajo) |
tony63 | 4:0b889f7a8eba | 4 | Como modem GSM usa un celular SIEMENS A56i |
tony63 | 4:0b889f7a8eba | 5 | El conector se distingue asi: |
tony63 | 6:4cece0df6a3b | 6 | Cable verde es RX conectelo a PTE0 cable blanco es TX conectelo a PTE1 (placa FRDMKL25Z de NXP antes freescale) |
tony63 | 4:0b889f7a8eba | 7 | La alarma se dispara segun la señal digital de entrada de un sensor PIR que se le filtra el ruido por medio de |
tony63 | 4:0b889f7a8eba | 8 | una validacion por retardo |
tony63 | 4:0b889f7a8eba | 9 | La alarma puede hacer accionamientos como: |
tony63 | 4:0b889f7a8eba | 10 | Accionamiento Permanente de una sirena |
tony63 | 4:0b889f7a8eba | 11 | Accionaminto temporizado de una sirena |
tony63 | 4:0b889f7a8eba | 12 | Accionamiento de un Mensaje de voz reperido y temporizado con un modulo de voz parallax |
tony63 | 4:0b889f7a8eba | 13 | puede marcar un telefono fijo y uno de celular e inyectar audio, como voz robotizada a la linea de audio |
tony63 | 4:0b889f7a8eba | 14 | usando un modulo GSM/GPRS SIM900 para arduino con entradas y salidas de audio |
tony63 | 4:0b889f7a8eba | 15 | puede leer coordenadas de gps y enviarlas con el link de googlemaps. |
tony63 | 0:edc50cf04b46 | 16 | // OJO CON ESTO |
tony63 | 0:edc50cf04b46 | 17 | // conector del siemens cable verde es RX conectelo a PTE0 cable blanco es TX conectelo a PTE1 |
tony63 | 4:0b889f7a8eba | 18 | |
tony63 | 4:0b889f7a8eba | 19 | ESTA ALARMA SE PUEDE PROBAR DE LA SIGUIENTE FORMA |
tony63 | 4:0b889f7a8eba | 20 | LOS TELEFONOS ESTAN PREGRAVADOS O CON UN CAMBIO SIMPLE EN EL PROGRAMA EL SISTEMA PUEDE CONTESTAR |
tony63 | 4:0b889f7a8eba | 21 | CON EL TELEFONO QUE LO LLAMO |
tony63 | 4:0b889f7a8eba | 22 | EN EL CASO DE RASTREADORES |
tony63 | 4:0b889f7a8eba | 23 | HAY UN SUICHE QUE SE LLAMA PIR UBICADO EN PTA13..SI SE PULSA POR UN INSTANTE DE TIEMPO |
tony63 | 4:0b889f7a8eba | 24 | EL LED VERDE DESTELLA INDICANDO QUE SE ENVIO EL MENSAJE AL NUMERO CODIFICADO EN LA CADENA SEGUN LAS TRAMAS PDU |
tony63 | 4:0b889f7a8eba | 25 | ENVIA EL MENSAJE "HAY INTRUSOS EN LA FINCA...." |
tony63 | 4:0b889f7a8eba | 26 | |
tony63 | 4:0b889f7a8eba | 27 | EN EL CASO DE ENVIAR ORDENES SE DISEÑARON DOS |
tony63 | 4:0b889f7a8eba | 28 | SI SE ENVIA UN MENSAJE CON Alarma1 prende el led azul 5 segundos y retorna a verde |
tony63 | 4:0b889f7a8eba | 29 | SI se envia el mensaje con Alarma2 prende el led rojo 5 segundos y retorna a verde |
tony63 | 4:0b889f7a8eba | 30 | si el telefono falla da indicacion con rojo |
tony63 | 4:0b889f7a8eba | 31 | el sistema reintenta de forma infinita la configuracion hasta que lo logra |
tony63 | 4:0b889f7a8eba | 32 | *****se verifico que no se de bloqueo y asi resulto bajo intensas pruebas******** |
tony63 | 4:0b889f7a8eba | 33 | este sistema detecta el mensaje, el tamaño del mensaje y el numero telefonico de quien llama pero etos parametros no se estan usando |
tony63 | 4:0b889f7a8eba | 34 | se podrian usar en programas mas complejos como rastreadores satelitales o sistemas de monitoreo de variablees fisicas |
tony63 | 4:0b889f7a8eba | 35 | que se consultan por medio de ordenes previas segun algun Mensaje corto. |
tony63 | 4:0b889f7a8eba | 36 | |
tony63 | 4:0b889f7a8eba | 37 | */ |
tony63 | 0:edc50cf04b46 | 38 | #include "mbed.h" |
tony63 | 0:edc50cf04b46 | 39 | #include "DebouncedIn.h" |
tony63 | 0:edc50cf04b46 | 40 | #include "stdio.h" |
tony63 | 0:edc50cf04b46 | 41 | #include "string.h" |
tony63 | 0:edc50cf04b46 | 42 | Timer t; |
tony63 | 0:edc50cf04b46 | 43 | DigitalOut LedVerde(LED2); |
tony63 | 0:edc50cf04b46 | 44 | DigitalOut LedRojo(LED1); |
tony63 | 6:4cece0df6a3b | 45 | DigitalOut camara(PTE20 ); |
tony63 | 6:4cece0df6a3b | 46 | DigitalOut sirena(PTE21 ); |
tony63 | 6:4cece0df6a3b | 47 | DigitalOut luces(PTE22 ); |
tony63 | 6:4cece0df6a3b | 48 | DigitalOut audio(PTE23 ); |
tony63 | 0:edc50cf04b46 | 49 | DigitalOut LedAzul(LED3); |
tony63 | 4:0b889f7a8eba | 50 | DebouncedIn PIR(PTA13); //señal que inicia el envio del mensaje |
tony63 | 0:edc50cf04b46 | 51 | DebouncedIn button1(PTC12); //señal que inicia el envio del mensaje |
tony63 | 6:4cece0df6a3b | 52 | Serial GSM(PTE0,PTE1); //Configura puerto UART1 de la FRDMKL25Z |
tony63 | 6:4cece0df6a3b | 53 | Serial voz(PTA2,PTA1); //Configura puerto UART0 de la FRDMKL25Z |
tony63 | 0:edc50cf04b46 | 54 | Serial pc(USBTX,USBRX);//Configura puerto USB a la consola serial del PC conectado. |
tony63 | 0:edc50cf04b46 | 55 | void Rx_interrupt(); |
tony63 | 0:edc50cf04b46 | 56 | int position=0; |
tony63 | 2:0377af333c98 | 57 | int intentos=0; |
tony63 | 0:edc50cf04b46 | 58 | int lenpack=6; |
tony63 | 2:0377af333c98 | 59 | int ret=1; |
tony63 | 0:edc50cf04b46 | 60 | int longi=0; |
tony63 | 1:6b506dde0a6e | 61 | char tel[11]; |
tony63 | 0:edc50cf04b46 | 62 | char DE[50]; |
tony63 | 5:dbb0384120e0 | 63 | char buffer[200]; |
tony63 | 5:dbb0384120e0 | 64 | //char buffermsg[200]; |
tony63 | 5:dbb0384120e0 | 65 | //char buffer1[200]; |
tony63 | 5:dbb0384120e0 | 66 | //char datos[200]; |
tony63 | 2:0377af333c98 | 67 | char NUMBER[13]; |
tony63 | 2:0377af333c98 | 68 | char resp[6]; |
tony63 | 2:0377af333c98 | 69 | char CMT[]="+CMTI"; |
tony63 | 2:0377af333c98 | 70 | char tam[2]; |
tony63 | 0:edc50cf04b46 | 71 | int index; |
tony63 | 0:edc50cf04b46 | 72 | int count; |
tony63 | 0:edc50cf04b46 | 73 | int i = 0; |
tony63 | 1:6b506dde0a6e | 74 | int j = 0; |
tony63 | 0:edc50cf04b46 | 75 | int c=0; |
tony63 | 0:edc50cf04b46 | 76 | unsigned char CtrlZ = 0x1A; // comodin de emision controlZ |
tony63 | 0:edc50cf04b46 | 77 | bool Flag = false; // bandera |
tony63 | 0:edc50cf04b46 | 78 | char r[]=""; //Cadena de recepcion de la trama PDU si se usa!! |
tony63 | 5:dbb0384120e0 | 79 | char msg[50]; |
tony63 | 0:edc50cf04b46 | 80 | char char1; |
tony63 | 0:edc50cf04b46 | 81 | //Flush serial para el buffer |
tony63 | 0:edc50cf04b46 | 82 | void FlushGSM(void) { |
tony63 | 0:edc50cf04b46 | 83 | char1 = 0; |
tony63 | 0:edc50cf04b46 | 84 | while (GSM.readable()){ |
tony63 | 0:edc50cf04b46 | 85 | char1 = GSM.getc();} |
tony63 | 0:edc50cf04b46 | 86 | return;} |
tony63 | 0:edc50cf04b46 | 87 | |
tony63 | 0:edc50cf04b46 | 88 | void callback() { |
tony63 | 0:edc50cf04b46 | 89 | // Note: you need to actually read from the serial to clear the RX interrupt |
tony63 | 0:edc50cf04b46 | 90 | pc.printf("%c\n", GSM.getc()); |
tony63 | 0:edc50cf04b46 | 91 | |
tony63 | 0:edc50cf04b46 | 92 | } |
tony63 | 2:0377af333c98 | 93 | //**************************************************************************************************************** |
tony63 | 2:0377af333c98 | 94 | //esta funcion de abajo lee todo un bufer hasta encontrar CR o LF y el resto lo rellena de |
tony63 | 2:0377af333c98 | 95 | //$, count es lo que va a leer.Lo leido lo mete en buffer que es una cadena previamente definida |
tony63 | 2:0377af333c98 | 96 | //incorpora medida de tiempo si se demora mas de tres segundos retorna fracaso con -1 |
tony63 | 2:0377af333c98 | 97 | //**************************************************************************************************************** |
tony63 | 0:edc50cf04b46 | 98 | int readBuffer(char *buffer,int count) |
tony63 | 0:edc50cf04b46 | 99 | { |
tony63 | 0:edc50cf04b46 | 100 | int i=0; |
tony63 | 0:edc50cf04b46 | 101 | t.start(); // start timer |
tony63 | 0:edc50cf04b46 | 102 | while(1) { |
tony63 | 0:edc50cf04b46 | 103 | while (GSM.readable()) { |
tony63 | 0:edc50cf04b46 | 104 | char c = GSM.getc(); |
tony63 | 0:edc50cf04b46 | 105 | if (c == '\r' || c == '\n') c = '$'; |
tony63 | 0:edc50cf04b46 | 106 | buffer[i++] = c; |
tony63 | 0:edc50cf04b46 | 107 | if(i > count)break; |
tony63 | 0:edc50cf04b46 | 108 | } |
tony63 | 0:edc50cf04b46 | 109 | if(i > count)break; |
tony63 | 0:edc50cf04b46 | 110 | if(t.read() > 3) { |
tony63 | 0:edc50cf04b46 | 111 | t.stop(); |
tony63 | 0:edc50cf04b46 | 112 | t.reset(); |
tony63 | 0:edc50cf04b46 | 113 | break; |
tony63 | 0:edc50cf04b46 | 114 | } |
tony63 | 0:edc50cf04b46 | 115 | } |
tony63 | 0:edc50cf04b46 | 116 | wait(0.5); |
tony63 | 0:edc50cf04b46 | 117 | while(GSM.readable()) { // display the other thing.. |
tony63 | 0:edc50cf04b46 | 118 | char c = GSM.getc(); |
tony63 | 0:edc50cf04b46 | 119 | } |
tony63 | 0:edc50cf04b46 | 120 | return 0; |
tony63 | 0:edc50cf04b46 | 121 | } |
tony63 | 2:0377af333c98 | 122 | //******************************************************************************** |
tony63 | 0:edc50cf04b46 | 123 | /* esta funcion de abajo limpia o borra todo un "buffer" de tamaño "count" |
tony63 | 2:0377af333c98 | 124 | lo revisa elemento por elemento y le mete el caracter null que indica fin de cadena |
tony63 | 0:edc50cf04b46 | 125 | no retorna nada |
tony63 | 0:edc50cf04b46 | 126 | */ |
tony63 | 0:edc50cf04b46 | 127 | //*************************************************************************************** |
tony63 | 0:edc50cf04b46 | 128 | void cleanBuffer(char *buffer, int count) |
tony63 | 0:edc50cf04b46 | 129 | { |
tony63 | 0:edc50cf04b46 | 130 | for(int i=0; i < count; i++) { |
tony63 | 0:edc50cf04b46 | 131 | buffer[i] = '\0'; |
tony63 | 0:edc50cf04b46 | 132 | } |
tony63 | 0:edc50cf04b46 | 133 | } |
tony63 | 0:edc50cf04b46 | 134 | /* esta funcion de abajo envia un comando parametrizado como cadena |
tony63 | 2:0377af333c98 | 135 | puede ser un comando tipo AT |
tony63 | 0:edc50cf04b46 | 136 | */ |
tony63 | 0:edc50cf04b46 | 137 | //*************************************************************************************** |
tony63 | 0:edc50cf04b46 | 138 | void sendCmd(char *cmd) |
tony63 | 0:edc50cf04b46 | 139 | { |
tony63 | 0:edc50cf04b46 | 140 | GSM.puts(cmd); |
tony63 | 0:edc50cf04b46 | 141 | } |
tony63 | 2:0377af333c98 | 142 | //**************************************************************************************** |
tony63 | 0:edc50cf04b46 | 143 | /* esta funcion de abajo espera la respuesta de un comando que debe ser identica a la cadena "resp" y un tiempo timeout" |
tony63 | 0:edc50cf04b46 | 144 | si todo sale bien retorna un cero que en la programacion hay que validar |
tony63 | 0:edc50cf04b46 | 145 | si algo sale mal ( no se parece o se demora mucho )retorna -1 que debera validarse con alguna expresion logica |
tony63 | 0:edc50cf04b46 | 146 | */ |
tony63 | 0:edc50cf04b46 | 147 | //*************************************************************************************** |
tony63 | 0:edc50cf04b46 | 148 | int waitForResp(char *resp, int timeout) |
tony63 | 0:edc50cf04b46 | 149 | { |
tony63 | 0:edc50cf04b46 | 150 | int len = strlen(resp); |
tony63 | 0:edc50cf04b46 | 151 | int sum=0; |
tony63 | 0:edc50cf04b46 | 152 | t.start(); |
tony63 | 0:edc50cf04b46 | 153 | |
tony63 | 0:edc50cf04b46 | 154 | while(1) { |
tony63 | 0:edc50cf04b46 | 155 | if(GSM.readable()) { |
tony63 | 0:edc50cf04b46 | 156 | char c = GSM.getc(); |
tony63 | 0:edc50cf04b46 | 157 | sum = (c==resp[sum]) ? sum+1 : 0;// esta linea de C# sum se incrementa o se hace cero segun c |
tony63 | 0:edc50cf04b46 | 158 | if(sum == len)break; //ya acabo se sale |
tony63 | 0:edc50cf04b46 | 159 | } |
tony63 | 0:edc50cf04b46 | 160 | if(t.read() > timeout) { // time out chequea el tiempo minimo antes de salir perdiendo |
tony63 | 0:edc50cf04b46 | 161 | t.stop(); |
tony63 | 0:edc50cf04b46 | 162 | t.reset(); |
tony63 | 0:edc50cf04b46 | 163 | return -1; |
tony63 | 0:edc50cf04b46 | 164 | } |
tony63 | 0:edc50cf04b46 | 165 | } |
tony63 | 0:edc50cf04b46 | 166 | t.stop(); // stop timer antes de retornar |
tony63 | 0:edc50cf04b46 | 167 | t.reset(); // clear timer |
tony63 | 0:edc50cf04b46 | 168 | while(GSM.readable()) { // display the other thing.. |
tony63 | 0:edc50cf04b46 | 169 | char c = GSM.getc(); |
tony63 | 0:edc50cf04b46 | 170 | } |
tony63 | 0:edc50cf04b46 | 171 | |
tony63 | 0:edc50cf04b46 | 172 | return 0; |
tony63 | 0:edc50cf04b46 | 173 | } |
tony63 | 0:edc50cf04b46 | 174 | /* esta funcion de abajo es muy completa e util se encarga de enviar el comando y esperar la respuesta |
tony63 | 0:edc50cf04b46 | 175 | si todo sale bien retorna un cero(herencia de las funciones contenedoras) que en la programacion hay que validar |
tony63 | 0:edc50cf04b46 | 176 | con alguna expresion logica |
tony63 | 0:edc50cf04b46 | 177 | */ |
tony63 | 0:edc50cf04b46 | 178 | //*************************************************************************************** |
tony63 | 0:edc50cf04b46 | 179 | int sendCmdAndWaitForResp(char *cmd, char *resp, int timeout) |
tony63 | 0:edc50cf04b46 | 180 | { |
tony63 | 0:edc50cf04b46 | 181 | sendCmd(cmd); |
tony63 | 0:edc50cf04b46 | 182 | return waitForResp(resp,timeout); |
tony63 | 0:edc50cf04b46 | 183 | } |
tony63 | 0:edc50cf04b46 | 184 | /* esta funcion de abajo chequea que el modem este vivo envia AT y le contesta con OK y espera 2 segundos |
tony63 | 0:edc50cf04b46 | 185 | */ |
tony63 | 0:edc50cf04b46 | 186 | //*************************************************************************************** |
tony63 | 0:edc50cf04b46 | 187 | int powerCheck(void)// este comando se manda para verificar si el modem esta vivo o conectado |
tony63 | 0:edc50cf04b46 | 188 | { |
tony63 | 0:edc50cf04b46 | 189 | return sendCmdAndWaitForResp("AT\r\n", "OK", 2); |
tony63 | 0:edc50cf04b46 | 190 | } |
tony63 | 0:edc50cf04b46 | 191 | /* esta funcion de abajo chequea el estado de la sim card |
tony63 | 0:edc50cf04b46 | 192 | y si todo sale bien retorna un cero que en la programacion hay que validar |
tony63 | 0:edc50cf04b46 | 193 | con alguna expresion logica |
tony63 | 0:edc50cf04b46 | 194 | */ |
tony63 | 0:edc50cf04b46 | 195 | //*************************************************************************************** |
tony63 | 0:edc50cf04b46 | 196 | int checkSIMStatus(void) |
tony63 | 0:edc50cf04b46 | 197 | { |
tony63 | 0:edc50cf04b46 | 198 | char gprsBuffer[30]; |
tony63 | 0:edc50cf04b46 | 199 | int count = 0; |
tony63 | 0:edc50cf04b46 | 200 | cleanBuffer(gprsBuffer,30); |
tony63 | 0:edc50cf04b46 | 201 | while(count < 3) { |
tony63 | 0:edc50cf04b46 | 202 | sendCmd("AT+CPIN?\r\n"); |
tony63 | 0:edc50cf04b46 | 203 | readBuffer(gprsBuffer,30); |
tony63 | 0:edc50cf04b46 | 204 | if((NULL != strstr(gprsBuffer,"+CPIN: READY"))) { |
tony63 | 0:edc50cf04b46 | 205 | break; |
tony63 | 0:edc50cf04b46 | 206 | } |
tony63 | 0:edc50cf04b46 | 207 | count++; |
tony63 | 0:edc50cf04b46 | 208 | wait(1); |
tony63 | 0:edc50cf04b46 | 209 | } |
tony63 | 0:edc50cf04b46 | 210 | |
tony63 | 0:edc50cf04b46 | 211 | if(count == 3) { |
tony63 | 0:edc50cf04b46 | 212 | return -1; |
tony63 | 0:edc50cf04b46 | 213 | } |
tony63 | 0:edc50cf04b46 | 214 | return 0; |
tony63 | 0:edc50cf04b46 | 215 | } |
tony63 | 0:edc50cf04b46 | 216 | /* esta funcion de abajo chequea la calidad de la señal |
tony63 | 2:0377af333c98 | 217 | y si todo sale bien retorna con el valor de señal util o un -1 si no es aceptable, en la programacion hay que validar |
tony63 | 0:edc50cf04b46 | 218 | con alguna expresion logica |
tony63 | 0:edc50cf04b46 | 219 | */ |
tony63 | 0:edc50cf04b46 | 220 | //*************************************************************************************** |
tony63 | 0:edc50cf04b46 | 221 | int checkSignalStrength(void) |
tony63 | 0:edc50cf04b46 | 222 | { |
tony63 | 0:edc50cf04b46 | 223 | char gprsBuffer[100]; |
tony63 | 0:edc50cf04b46 | 224 | int index,count = 0; |
tony63 | 0:edc50cf04b46 | 225 | cleanBuffer(gprsBuffer,100); |
tony63 | 0:edc50cf04b46 | 226 | while(count < 3) { |
tony63 | 0:edc50cf04b46 | 227 | sendCmd("AT+CSQ\r\n"); |
tony63 | 0:edc50cf04b46 | 228 | readBuffer(gprsBuffer,25); |
tony63 | 0:edc50cf04b46 | 229 | if(sscanf(gprsBuffer, "AT+CSQ$$$$+CSQ: %d", &index)>0) { |
tony63 | 0:edc50cf04b46 | 230 | break; |
tony63 | 0:edc50cf04b46 | 231 | } |
tony63 | 0:edc50cf04b46 | 232 | count++; |
tony63 | 0:edc50cf04b46 | 233 | wait(1); |
tony63 | 0:edc50cf04b46 | 234 | } |
tony63 | 0:edc50cf04b46 | 235 | if(count == 3) { |
tony63 | 0:edc50cf04b46 | 236 | return -1; |
tony63 | 0:edc50cf04b46 | 237 | } |
tony63 | 0:edc50cf04b46 | 238 | return index; |
tony63 | 0:edc50cf04b46 | 239 | } |
tony63 | 0:edc50cf04b46 | 240 | |
tony63 | 0:edc50cf04b46 | 241 | /* esta funcion de abajo inicaliza el modem se compone de un grupo de subfunciones ya definidas previamente |
tony63 | 0:edc50cf04b46 | 242 | primero chequea que este vivo |
tony63 | 0:edc50cf04b46 | 243 | segundo chequea el estado de la simcard |
tony63 | 0:edc50cf04b46 | 244 | tercero chequea la intencidad de señal celular |
tony63 | 0:edc50cf04b46 | 245 | cuarto aplica la configuracion |
tony63 | 0:edc50cf04b46 | 246 | y si todo sale bien retorna un cero que en la programacion hay que validar |
tony63 | 0:edc50cf04b46 | 247 | con alguna expresion logica |
tony63 | 0:edc50cf04b46 | 248 | */ |
tony63 | 0:edc50cf04b46 | 249 | //*************************************************************************************** |
tony63 | 0:edc50cf04b46 | 250 | int init() |
tony63 | 0:edc50cf04b46 | 251 | { |
tony63 | 2:0377af333c98 | 252 | if (0 != sendCmdAndWaitForResp("AT\r\n", "OK", 3)){ |
tony63 | 2:0377af333c98 | 253 | return -1; |
tony63 | 2:0377af333c98 | 254 | } |
tony63 | 2:0377af333c98 | 255 | if (0 != sendCmdAndWaitForResp("AT+CNMI=1,1\r\n", "OK", 3)){ |
tony63 | 2:0377af333c98 | 256 | return -1; |
tony63 | 2:0377af333c98 | 257 | } |
tony63 | 2:0377af333c98 | 258 | if (0 != sendCmdAndWaitForResp("AT+CMGF=0\r\n", "OK", 3)){ |
tony63 | 0:edc50cf04b46 | 259 | return -1; |
tony63 | 2:0377af333c98 | 260 | } |
tony63 | 6:4cece0df6a3b | 261 | if (0 != sendCmdAndWaitForResp("AT+CBST=7,0,1\r\n", "OK", 3)){ //velocidad fija a 9600, modem asincronico no transparente |
tony63 | 0:edc50cf04b46 | 262 | return -1; |
tony63 | 2:0377af333c98 | 263 | } |
tony63 | 6:4cece0df6a3b | 264 | if (0 != sendCmdAndWaitForResp("ATE\r\n", "OK", 3)){ //se le quita el eco al modem GSM |
tony63 | 5:dbb0384120e0 | 265 | return -1; |
tony63 | 5:dbb0384120e0 | 266 | } |
tony63 | 2:0377af333c98 | 267 | LedVerde=0; |
tony63 | 2:0377af333c98 | 268 | return 0; |
tony63 | 2:0377af333c98 | 269 | } |
tony63 | 2:0377af333c98 | 270 | |
tony63 | 0:edc50cf04b46 | 271 | /* esta funcion de abajo intenta leer un mensaje de texto en formato PDU o HEX |
tony63 | 0:edc50cf04b46 | 272 | y si todo sale bien retorna un cero que en la programacion hay que validar |
tony63 | 0:edc50cf04b46 | 273 | con alguna expresion logica |
tony63 | 0:edc50cf04b46 | 274 | */ |
tony63 | 0:edc50cf04b46 | 275 | //*************************************************************************************** |
tony63 | 0:edc50cf04b46 | 276 | int readSMSpdu(char *message, int index) |
tony63 | 0:edc50cf04b46 | 277 | { |
tony63 | 0:edc50cf04b46 | 278 | int i = 0; |
tony63 | 0:edc50cf04b46 | 279 | char gprsBuffer[100]; |
tony63 | 0:edc50cf04b46 | 280 | char *p,*s; |
tony63 | 0:edc50cf04b46 | 281 | GSM.printf("AT+CMGR=%d\r\n",index); |
tony63 | 0:edc50cf04b46 | 282 | cleanBuffer(gprsBuffer,100); |
tony63 | 0:edc50cf04b46 | 283 | readBuffer(gprsBuffer,100); |
tony63 | 0:edc50cf04b46 | 284 | if(NULL == ( s = strstr(gprsBuffer,"+CMGR"))) { |
tony63 | 0:edc50cf04b46 | 285 | return -1; |
tony63 | 0:edc50cf04b46 | 286 | } |
tony63 | 0:edc50cf04b46 | 287 | if(NULL != ( s = strstr(gprsBuffer,"+32"))) { |
tony63 | 0:edc50cf04b46 | 288 | p = s + 6; |
tony63 | 0:edc50cf04b46 | 289 | while((*p != '$')&&(i < 5)) { |
tony63 | 0:edc50cf04b46 | 290 | message[i++] = *(p++); |
tony63 | 0:edc50cf04b46 | 291 | } |
tony63 | 0:edc50cf04b46 | 292 | message[i] = '\0'; |
tony63 | 0:edc50cf04b46 | 293 | } |
tony63 | 0:edc50cf04b46 | 294 | return 0; |
tony63 | 0:edc50cf04b46 | 295 | } |
tony63 | 0:edc50cf04b46 | 296 | /* esta funcion de abajo borra mensajes SMS del modem |
tony63 | 0:edc50cf04b46 | 297 | y si todo sale bien retorna un cero que en la programacion hay que validar |
tony63 | 0:edc50cf04b46 | 298 | con alguna expresion logica |
tony63 | 0:edc50cf04b46 | 299 | */ |
tony63 | 0:edc50cf04b46 | 300 | //*************************************************************************************** |
tony63 | 0:edc50cf04b46 | 301 | int deleteSMS(int index) |
tony63 | 0:edc50cf04b46 | 302 | { |
tony63 | 0:edc50cf04b46 | 303 | char cmd[32]; |
tony63 | 0:edc50cf04b46 | 304 | snprintf(cmd,sizeof(cmd),"AT+CMGD=%d\r\n",index); |
tony63 | 0:edc50cf04b46 | 305 | sendCmd(cmd); |
tony63 | 0:edc50cf04b46 | 306 | return 0; |
tony63 | 0:edc50cf04b46 | 307 | } |
tony63 | 6:4cece0df6a3b | 308 | //********Esta funcion devuelve la confirmacion del mensaje a quien lo envio************************** |
tony63 | 6:4cece0df6a3b | 309 | int recibe_ok(){ |
tony63 | 6:4cece0df6a3b | 310 | GSM.printf("AT+CMGS=32\n\r"); |
tony63 | 6:4cece0df6a3b | 311 | pc.printf("AT+CMGS=32\n\r"); |
tony63 | 6:4cece0df6a3b | 312 | wait_ms(200); |
tony63 | 6:4cece0df6a3b | 313 | GSM.printf("0011000A91%s0000AA15CDB27B1E569741F2F2382D4E93DFA0E7321402",tel); |
tony63 | 6:4cece0df6a3b | 314 | pc.printf("0011000A91%s0000AA15CDB27B1E569741F2F2382D4E93DFA0E7321402",tel); |
tony63 | 6:4cece0df6a3b | 315 | wait_ms(500); |
tony63 | 6:4cece0df6a3b | 316 | GSM.putc((char)0x1A); |
tony63 | 6:4cece0df6a3b | 317 | return 0; |
tony63 | 6:4cece0df6a3b | 318 | } |
tony63 | 2:0377af333c98 | 319 | //************************************************************************************ |
tony63 | 4:0b889f7a8eba | 320 | //*****************SE INICIA EL PROGRAMA PRINCIPAL******************************************************* |
tony63 | 4:0b889f7a8eba | 321 | int main() { |
tony63 | 4:0b889f7a8eba | 322 | //configuramos los puertos seriales |
tony63 | 4:0b889f7a8eba | 323 | GSM.baud(9600);//configura los baudios de la FRDMKL25Z en 9600 |
tony63 | 4:0b889f7a8eba | 324 | GSM.format(8,Serial::None,1); //configura el formato de los datos de la UART |
tony63 | 4:0b889f7a8eba | 325 | LedVerde=1; //APAGO LOS LEDS |
tony63 | 4:0b889f7a8eba | 326 | LedRojo=1; |
tony63 | 4:0b889f7a8eba | 327 | LedAzul=1; |
tony63 | 4:0b889f7a8eba | 328 | LedRojo=0; // PRENDO EL LED ROJO |
tony63 | 4:0b889f7a8eba | 329 | //quito el eco del modem |
tony63 | 4:0b889f7a8eba | 330 | |
tony63 | 4:0b889f7a8eba | 331 | //****************CONFIGURAMOS EL MODEM GSM (TELEFONO CELULAR SIEMENS A56i) |
tony63 | 4:0b889f7a8eba | 332 | inicio1: |
tony63 | 4:0b889f7a8eba | 333 | ret = init(); |
tony63 | 4:0b889f7a8eba | 334 | if(ret==0){ |
tony63 | 4:0b889f7a8eba | 335 | LedRojo=1; |
tony63 | 4:0b889f7a8eba | 336 | LedVerde=0; |
tony63 | 4:0b889f7a8eba | 337 | } |
tony63 | 4:0b889f7a8eba | 338 | else{ |
tony63 | 4:0b889f7a8eba | 339 | wait(5); |
tony63 | 4:0b889f7a8eba | 340 | goto inicio1; |
tony63 | 4:0b889f7a8eba | 341 | } |
tony63 | 0:edc50cf04b46 | 342 | |
tony63 | 2:0377af333c98 | 343 | //RUTINA PRINCIPAL******************************************************************************************* |
tony63 | 4:0b889f7a8eba | 344 | |
tony63 | 2:0377af333c98 | 345 | //********************************************************************************************************************* |
tony63 | 2:0377af333c98 | 346 | while(1){ |
tony63 | 4:0b889f7a8eba | 347 | //***************ALARMA POR ACTIVACION PIR*************************************************** |
tony63 | 4:0b889f7a8eba | 348 | if (PIR.falling()) |
tony63 | 2:0377af333c98 | 349 | { |
tony63 | 4:0b889f7a8eba | 350 | wait(1); |
tony63 | 4:0b889f7a8eba | 351 | if (!PIR) |
tony63 | 2:0377af333c98 | 352 | { |
tony63 | 4:0b889f7a8eba | 353 | |
tony63 | 4:0b889f7a8eba | 354 | //**********se envia la palabra "Hay Intrusos En La Finca de Rionegro" |
tony63 | 4:0b889f7a8eba | 355 | //******Gustavo |
tony63 | 4:0b889f7a8eba | 356 | GSM.printf("AT+CMGS=50\n\r"); |
tony63 | 4:0b889f7a8eba | 357 | wait_ms(200); |
tony63 | 4:0b889f7a8eba | 358 | GSM.printf("0011000A9113223717370000AA2A21970B19CE83926EBABC3E7FCF41453788190699D3EE7118442E83A4E9B7BB7C96BF5DAE10"); |
tony63 | 4:0b889f7a8eba | 359 | wait_ms(200); |
tony63 | 4:0b889f7a8eba | 360 | GSM.putc((char)0x1A); |
tony63 | 5:dbb0384120e0 | 361 | for(i=0;i<60;i++){ //por mas ruido se envia un mensaje cada minuto |
tony63 | 2:0377af333c98 | 362 | LedVerde=1; |
tony63 | 5:dbb0384120e0 | 363 | wait(0.5); |
tony63 | 2:0377af333c98 | 364 | LedVerde=0; |
tony63 | 5:dbb0384120e0 | 365 | wait(0.5); |
tony63 | 4:0b889f7a8eba | 366 | } |
tony63 | 4:0b889f7a8eba | 367 | } |
tony63 | 4:0b889f7a8eba | 368 | } |
tony63 | 4:0b889f7a8eba | 369 | // **************apartir de aca se pueden escribir mas alarmas o mensajes de salida activar leds salidas o generar respuestas |
tony63 | 4:0b889f7a8eba | 370 | |
tony63 | 4:0b889f7a8eba | 371 | |
tony63 | 2:0377af333c98 | 372 | |
tony63 | 2:0377af333c98 | 373 | |
tony63 | 4:0b889f7a8eba | 374 | //***************inicia la recepcion de un mensaje de texto********************************** |
tony63 | 4:0b889f7a8eba | 375 | //la comparacion de estos mensajes constituye generar accionamiento abrir o cerrar circuitos o contestar mensajes |
tony63 | 4:0b889f7a8eba | 376 | |
tony63 | 2:0377af333c98 | 377 | if (GSM.readable()) { |
tony63 | 5:dbb0384120e0 | 378 | readBuffer(buffer,110); |
tony63 | 2:0377af333c98 | 379 | pc.printf("%s\r\n",buffer); |
tony63 | 2:0377af333c98 | 380 | for(i=0;i<5;i++) |
tony63 | 2:0377af333c98 | 381 | { |
tony63 | 2:0377af333c98 | 382 | resp[i]=buffer[i]; |
tony63 | 2:0377af333c98 | 383 | } |
tony63 | 2:0377af333c98 | 384 | |
tony63 | 2:0377af333c98 | 385 | pc.printf("%s\r\n",resp); |
tony63 | 2:0377af333c98 | 386 | if(strcmp("$$+CM",resp) == 0){ //COMPARA resp con "+CMTI" |
tony63 | 2:0377af333c98 | 387 | pc.printf("llego MSG\r\n"); |
tony63 | 2:0377af333c98 | 388 | cleanBuffer(buffer,10); |
tony63 | 2:0377af333c98 | 389 | wait(0.5); |
tony63 | 2:0377af333c98 | 390 | GSM.printf("AT+CMGL=0\r\n");//envio comando para leer mensaje |
tony63 | 2:0377af333c98 | 391 | pc.printf("AT+CMGL=0\r\n"); |
tony63 | 2:0377af333c98 | 392 | //if (GSM.readable()) { |
tony63 | 2:0377af333c98 | 393 | GSM.printf("AT+CMGD=0\r\n"); |
tony63 | 2:0377af333c98 | 394 | readBuffer(buffer,100); |
tony63 | 2:0377af333c98 | 395 | pc.printf("%s\r\n",buffer); |
tony63 | 2:0377af333c98 | 396 | wait(5); |
tony63 | 2:0377af333c98 | 397 | //leer telefono |
tony63 | 2:0377af333c98 | 398 | for(i=0;i<10;i++){ |
tony63 | 2:0377af333c98 | 399 | tel[i]=buffer[i+40]; |
tony63 | 2:0377af333c98 | 400 | } |
tony63 | 2:0377af333c98 | 401 | pc.printf("%s-\r\n",tel); |
tony63 | 2:0377af333c98 | 402 | //leer tamaño |
tony63 | 2:0377af333c98 | 403 | for(i=0;i<2;i++){ |
tony63 | 2:0377af333c98 | 404 | tam[i]=buffer[i+68]; |
tony63 | 2:0377af333c98 | 405 | } |
tony63 | 2:0377af333c98 | 406 | pc.printf("%s-\r\n",tam); |
tony63 | 2:0377af333c98 | 407 | //leer mensaje |
tony63 | 5:dbb0384120e0 | 408 | for(i=0;i<20;i++){ |
tony63 | 5:dbb0384120e0 | 409 | msg[i]=buffer[i+70]; //OJO SE LEE EL MENSAJE APARTIR DE LA POSICION 70 14 caracteres |
tony63 | 2:0377af333c98 | 410 | } |
tony63 | 2:0377af333c98 | 411 | pc.printf("%s-\r\n",msg); |
tony63 | 2:0377af333c98 | 412 | //decodificar mensaje |
tony63 | 2:0377af333c98 | 413 | //comparar mensaje |
tony63 | 6:4cece0df6a3b | 414 | deleteSMS(1);//se borra los mensajes por medio de una funcion |
tony63 | 6:4cece0df6a3b | 415 | readBuffer(buffer,200); |
tony63 | 6:4cece0df6a3b | 416 | readBuffer(buffer,200); |
tony63 | 5:dbb0384120e0 | 417 | if(strncmp("417658DE0EC700",msg,14) == 0){ //COMPARA resp con "417658DE0EC700" que es Alarma1 |
tony63 | 6:4cece0df6a3b | 418 | recibe_ok(); |
tony63 | 2:0377af333c98 | 419 | LedVerde=1; |
tony63 | 2:0377af333c98 | 420 | LedAzul=0; |
tony63 | 2:0377af333c98 | 421 | wait(15); |
tony63 | 2:0377af333c98 | 422 | LedAzul=1; |
tony63 | 2:0377af333c98 | 423 | LedVerde=0; |
tony63 | 2:0377af333c98 | 424 | } |
tony63 | 5:dbb0384120e0 | 425 | if(strncmp("417658DE0ECB00",msg,14) == 0){ //COMPARA resp con "417658DE0ECB00" que es Alarma2 |
tony63 | 6:4cece0df6a3b | 426 | recibe_ok(); |
tony63 | 2:0377af333c98 | 427 | LedVerde=1; |
tony63 | 2:0377af333c98 | 428 | LedRojo=0; |
tony63 | 2:0377af333c98 | 429 | wait(15); |
tony63 | 2:0377af333c98 | 430 | LedRojo=1; |
tony63 | 2:0377af333c98 | 431 | LedVerde=0; |
tony63 | 2:0377af333c98 | 432 | } |
tony63 | 5:dbb0384120e0 | 433 | if(strncmp("C3703B2C0F83DE6E",msg,16) == 0){ //COMPARA resp con "417658DE0ECB00" que es Camara on |
tony63 | 6:4cece0df6a3b | 434 | recibe_ok(); |
tony63 | 5:dbb0384120e0 | 435 | camara=1; |
tony63 | 5:dbb0384120e0 | 436 | } |
tony63 | 5:dbb0384120e0 | 437 | if(strncmp("C3703B2C0F83DE66",msg,16) == 0){ //COMPARA resp con "417658DE0ECB00" que es Camara of |
tony63 | 6:4cece0df6a3b | 438 | recibe_ok(); |
tony63 | 5:dbb0384120e0 | 439 | camara=0; |
tony63 | 5:dbb0384120e0 | 440 | } |
tony63 | 5:dbb0384120e0 | 441 | if(strncmp("D3B4BCEC0E83DE6E",msg,16) == 0){ //COMPARA resp con "D3B4BCEC0E83DE6E" que es Sirena on |
tony63 | 6:4cece0df6a3b | 442 | recibe_ok(); |
tony63 | 6:4cece0df6a3b | 443 | sirena=1; |
tony63 | 6:4cece0df6a3b | 444 | wait(30); //prende la sirena 30 segundos |
tony63 | 6:4cece0df6a3b | 445 | sirena=0; |
tony63 | 6:4cece0df6a3b | 446 | } |
tony63 | 6:4cece0df6a3b | 447 | /* if(strncmp(" ",msg,16) == 0){ //COMPARA resp con " " que es luz on |
tony63 | 6:4cece0df6a3b | 448 | recibe_ok(); |
tony63 | 6:4cece0df6a3b | 449 | luces=1; |
tony63 | 6:4cece0df6a3b | 450 | wait(30); //prende la luz 30 segundos |
tony63 | 6:4cece0df6a3b | 451 | luces=0; |
tony63 | 5:dbb0384120e0 | 452 | } |
tony63 | 6:4cece0df6a3b | 453 | if(strncmp(" ",msg,16) == 0){ //COMPARA resp con "" que es Msg1 |
tony63 | 6:4cece0df6a3b | 454 | recibe_ok(); |
tony63 | 6:4cece0df6a3b | 455 | } |
tony63 | 6:4cece0df6a3b | 456 | if(strncmp(" ",msg,16) == 0){ //COMPARA resp con "" que es Msg2 |
tony63 | 6:4cece0df6a3b | 457 | recibe_ok(); |
tony63 | 6:4cece0df6a3b | 458 | } |
tony63 | 6:4cece0df6a3b | 459 | if(strncmp(" ",msg,16) == 0){ //COMPARA resp con "" que es Msg3 |
tony63 | 6:4cece0df6a3b | 460 | recibe_ok(); |
tony63 | 6:4cece0df6a3b | 461 | } |
tony63 | 6:4cece0df6a3b | 462 | if(strncmp(" ",msg,16) == 0){ //COMPARA resp con "" que es Msg123 |
tony63 | 6:4cece0df6a3b | 463 | recibe_ok(); |
tony63 | 6:4cece0df6a3b | 464 | } |
tony63 | 6:4cece0df6a3b | 465 | */ |
tony63 | 5:dbb0384120e0 | 466 | //strncmp(str1, str2, 6) compara hasta 6 caracteres |
tony63 | 6:4cece0df6a3b | 467 | //recibe_ok(); |
tony63 | 2:0377af333c98 | 468 | |
tony63 | 4:0b889f7a8eba | 469 | //ejecurar orden si esta es mas que prender leds |
tony63 | 2:0377af333c98 | 470 | cleanBuffer(buffer,100); |
tony63 | 2:0377af333c98 | 471 | |
tony63 | 2:0377af333c98 | 472 | } |
tony63 | 1:6b506dde0a6e | 473 | } |
tony63 | 2:0377af333c98 | 474 | |
tony63 | 2:0377af333c98 | 475 | |
tony63 | 2:0377af333c98 | 476 | } |
tony63 | 2:0377af333c98 | 477 | |
tony63 | 1:6b506dde0a6e | 478 | |
tony63 | 2:0377af333c98 | 479 | //********************************************************************************************************************** |
tony63 | 2:0377af333c98 | 480 | loop1: LedRojo=0; |
tony63 | 2:0377af333c98 | 481 | wait(0.3); |
tony63 | 2:0377af333c98 | 482 | LedRojo=1; |
tony63 | 2:0377af333c98 | 483 | wait(0.3); |
tony63 | 2:0377af333c98 | 484 | goto loop1; |
tony63 | 2:0377af333c98 | 485 | |
tony63 | 4:0b889f7a8eba | 486 | } |
tony63 | 4:0b889f7a8eba | 487 | |
tony63 | 4:0b889f7a8eba | 488 | /* |
tony63 | 4:0b889f7a8eba | 489 | si se manda para enviar mensaje |
tony63 | 4:0b889f7a8eba | 490 | AT+CMGS=20 |
tony63 | 4:0b889f7a8eba | 491 | //un salto de linea y el simbolo mayor |
tony63 | 4:0b889f7a8eba | 492 | > |
tony63 | 5:dbb0384120e0 | 493 | patrones de alarma y mensajes |
tony63 | 5:dbb0384120e0 | 494 | Camara on |
tony63 | 5:dbb0384120e0 | 495 | |
tony63 | 5:dbb0384120e0 | 496 | da esto |
tony63 | 5:dbb0384120e0 | 497 | +CMGL: 1,0,,26 |
tony63 | 5:dbb0384120e0 | 498 | 0791751330512411040AA1132237173700006150709060250A09C3703B2C0F83DE6E |
tony63 | 5:dbb0384120e0 | 499 | |
tony63 | 5:dbb0384120e0 | 500 | Camara of da esto |
tony63 | 5:dbb0384120e0 | 501 | +CMGL: 2,0,,26 |
tony63 | 5:dbb0384120e0 | 502 | 0791751330080089040AA1132237173700006150709001520A09C3703B2C0F83DE66 |
tony63 | 5:dbb0384120e0 | 503 | mensaje=C3703B2C0F83DE66 |
tony63 | 5:dbb0384120e0 | 504 | OK |
tony63 | 5:dbb0384120e0 | 505 | |
tony63 | 5:dbb0384120e0 | 506 | Sirena on |
tony63 | 5:dbb0384120e0 | 507 | da esto |
tony63 | 5:dbb0384120e0 | 508 | |
tony63 | 5:dbb0384120e0 | 509 | +CMGL: 3,0,,26 |
tony63 | 5:dbb0384120e0 | 510 | 0791751330512411040AA1132237173700006150709031540A09D3B4BCEC0E83DE6E |
tony63 | 5:dbb0384120e0 | 511 | mensaje=D3B4BCEC0E83DE6E |
tony63 | 5:dbb0384120e0 | 512 | OK |
tony63 | 5:dbb0384120e0 | 513 | |
tony63 | 5:dbb0384120e0 | 514 | Sirena of |
tony63 | 5:dbb0384120e0 | 515 | |
tony63 | 5:dbb0384120e0 | 516 | da esto |
tony63 | 5:dbb0384120e0 | 517 | +CMGL: 4,0,,26 |
tony63 | 5:dbb0384120e0 | 518 | 0791751330512411040AA1132237173700006150709051750A09D3B4BCEC0E83DE66 |
tony63 | 5:dbb0384120e0 | 519 | mensaje=D3B4BCEC0E83DE66 |
tony63 | 5:dbb0384120e0 | 520 | OK |
tony63 | 5:dbb0384120e0 | 521 | |
tony63 | 5:dbb0384120e0 | 522 | Alarma 1 |
tony63 | 5:dbb0384120e0 | 523 | |
tony63 | 5:dbb0384120e0 | 524 | +CMGL: 1,0,,25 |
tony63 | 5:dbb0384120e0 | 525 | 0791751330512411040AA1132237173700006150702153640A08417658DE0E8362 |
tony63 | 5:dbb0384120e0 | 526 | mensaje=417658DE0E8362 |
tony63 | 5:dbb0384120e0 | 527 | 5 |
tony63 | 4:0b889f7a8eba | 528 | |
tony63 | 6:4cece0df6a3b | 529 | Mensaje recibido ok! |
tony63 | 6:4cece0df6a3b | 530 | AT+CMGS=31 |
tony63 | 6:4cece0df6a3b | 531 | 0011000A9113223717370000AA14CDB27B1E569741F2F2382D4E93DFA0F73A04 |
tony63 | 6:4cece0df6a3b | 532 | |
tony63 | 6:4cece0df6a3b | 533 | AT+CMGS=32 |
tony63 | 6:4cece0df6a3b | 534 | 0011000A9113223717370000AA15CDB27B1E569741F2F2382D4E93DFA0E7321402 |
tony63 | 4:0b889f7a8eba | 535 | |
tony63 | 4:0b889f7a8eba | 536 | |
tony63 | 4:0b889f7a8eba | 537 | |
tony63 | 6:4cece0df6a3b | 538 | void recibe_ok(void){ |
tony63 | 6:4cece0df6a3b | 539 | GSM.printf("AT+CMGS=31\n\r"); |
tony63 | 6:4cece0df6a3b | 540 | wait_ms(200); |
tony63 | 6:4cece0df6a3b | 541 | GSM.printf("0011000A91"); |
tony63 | 6:4cece0df6a3b | 542 | GSM.printf("%str",tel); |
tony63 | 6:4cece0df6a3b | 543 | GSM.printf("0000AA14CDB27B1E569741F2F2382D4E93DFA0F73A04\n\r"); // Mensaje recibido ok! |
tony63 | 6:4cece0df6a3b | 544 | wait_ms(200); |
tony63 | 6:4cece0df6a3b | 545 | GSM.putc((char)0x1A); |
tony63 | 6:4cece0df6a3b | 546 | } |
tony63 | 6:4cece0df6a3b | 547 | |
tony63 | 4:0b889f7a8eba | 548 | */ |