Created
August 24, 2013 06:07
-
-
Save rat/3d746c449b458210c07a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <SD.h> | |
#include <SPI.h> | |
#include <Ethernet.h> | |
#include <SoftwareSerial.h> | |
// Define as variáveis para simular o multitasking | |
unsigned long UpdateCycle = 30000; | |
unsigned long UpdateLastMillis = 0; | |
// Ponteiro para o meu arquivo no SD Card | |
File myFile; | |
// Define os dados da rede necessarios para o Ethernet Shield | |
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; | |
byte ip[] = {192,168,1,177}; | |
// Ethernet Server escutando na porta 80 | |
EthernetServer server(80); | |
// Jumpers no RX 3 e DX 2 | |
SoftwareSerial mySerial(2, 3); | |
//SoftwareSerial mySerial(rxPin, txPin); | |
/** | |
* Função de configuração do Arduino. | |
* | |
* Função obrigatória do Arduino que realiza a iniciação das | |
* variáveis e configurações que serão usadas no decorrer do código. | |
* | |
*/ | |
void setup() | |
{ | |
mySerial.begin(19200); | |
Ethernet.begin(mac, ip); | |
pinMode(10, OUTPUT); | |
if (!SD.begin(4)){ | |
return; | |
} | |
} | |
/** | |
* Loop principal do programa. | |
* | |
* Função obrigatória do Arduino, responsável pelo loop infinito | |
* que realiza o processamento dos dados. | |
* | |
*/ | |
void loop() | |
{ | |
if(cycleCheck(&UpdateLastMillis, UpdateCycle)) { | |
get_sms_data(); | |
} | |
client_request(); | |
} | |
/** | |
* Salva o pedido do cliente no SD Card. | |
* | |
* Toda vez que um pedido para envio de SMS chega ao Arduino | |
* ele primeiro é salvo no SD card e só posteriormente enviado | |
* de fato. Isso é útil para responder rapidamente vários pedidos | |
* e enviar as mensagens quando o Arduino está folgado. | |
* | |
*/ | |
void save_sms_data(char data[]) | |
{ | |
myFile = SD.open("sms.txt", FILE_WRITE); | |
if (myFile) { | |
myFile.print(data); | |
myFile.print("\n"); | |
myFile.close(); | |
} | |
else { | |
return; | |
} | |
} | |
/** | |
* Recupera o texto vindo do cartão SD e envia o SMS. | |
* | |
* Todas as mensagens são salvas no SD Carda antes de | |
* serem enviadas, isso garante (ou deveria) velocidade | |
* pois se um ou mais clientes solicitarem o envio do SMS | |
* o Arduino demora responder e a requisição fala. Já escrever | |
* no SD Carda é rápido, basta posteriomente eu ler os dados gravados | |
* e enviar os SMS's quando o Arduino não estiver atendendo um cliente. | |
* | |
* @TODO Criar algoritimo que impede receber novos pedidos enquando envia os SMS's. | |
* @TODO Criar um resposta HTTP para sucesso e outra para falha. (Se possível ;.;) | |
* @TODO Confirmar se o Arduino garante que o arquivo só possa ser escrito por um processo. | |
* | |
*/ | |
void get_sms_data() | |
{ | |
if(SD.exists("sms.txt")){ | |
myFile = SD.open("sms.txt"); | |
char mensagem[161]; | |
char numero[15]; | |
byte pointer = 0; | |
byte foundPipe = 0; | |
if (myFile) { | |
while (myFile.available()) { | |
char c = myFile.read(); | |
if(c != '|' && foundPipe == 0){ | |
mensagem[pointer] = c; | |
pointer++; | |
mensagem[pointer] = '\0'; | |
} | |
else if(c == '|' && foundPipe == 0){ | |
foundPipe = 1; | |
pointer = 0; | |
} | |
else if(foundPipe == 1 && c != '|' && c != '\n'){ | |
numero[pointer] = c; | |
pointer++; | |
numero[pointer] = '\0'; | |
} | |
else if(foundPipe == 1 && c == '\n'){ | |
pointer = 0; | |
foundPipe = 0; | |
send_sms(mensagem, numero); | |
} | |
} | |
myFile.close(); | |
SD.remove("sms.txt"); | |
} | |
else{ | |
return; | |
} | |
} | |
else{ | |
return; | |
} | |
} | |
/** | |
* Função para realizar o envio de SMS. | |
* | |
* A GPRS Shield utilizar AT commands para funcionar, a documentação | |
* da shield e os comendos podem ser encontrados na página do | |
* fornecedor: http://www.elecfreaks.com/wiki/index.php?title=EFCom_GPRS/GSM_Shield | |
* | |
* Realizei backup da documentação no Google Drive | |
*/ | |
void send_sms(char msg[], char phone[]) | |
{ | |
mySerial.print("\r\n"); | |
delay(1100); | |
mySerial.print("AT+CMGF=1\r\n"); | |
delay(1100); | |
mySerial.print("AT+CMGS=\""); | |
mySerial.print(phone); | |
mySerial.print("\"\r\n"); | |
delay(1100); | |
mySerial.print(msg); | |
mySerial.print("\r\n"); | |
delay(1100); | |
mySerial.write(26); | |
delay(1100); | |
} | |
/** | |
* Função para monitorar o pedido vindo do cliente. | |
* | |
* Recebe a requisição vinda do cliente sempre no formato: | |
* | |
* mensagem|telefone | |
* | |
* Caso não obedeça esse padrão, a mensagem não será enviada ao cliente. | |
*/ | |
void client_request() | |
{ | |
EthernetClient client = server.available(); | |
if (client) | |
{ | |
char mensagem[175]; | |
byte pointer = 0; | |
byte firstChar = 1; | |
byte myRequest = 0; | |
byte firstPipe = 0; | |
while (client.connected()) | |
{ | |
if (client.available()) | |
{ | |
char c = client.read(); | |
if(firstChar == 1 && c == '|') | |
{ | |
myRequest = 1; | |
firstChar = 0; | |
firstPipe = 1; | |
} | |
else if(firstChar == 1 && c != '|') | |
{ | |
myRequest = 0; | |
firstChar = 0; | |
} | |
if(myRequest && firstPipe == 0) | |
{ | |
mensagem[pointer] = c; | |
pointer++; | |
mensagem[pointer] = '\0'; | |
} | |
else if(myRequest && firstPipe == 1) | |
{ | |
firstPipe = 0; | |
} | |
} | |
} | |
client.stop(); | |
if(myRequest){ | |
save_sms_data(mensagem); | |
} | |
} | |
} | |
/** | |
* Função para simular o multitasking. | |
* | |
* Função que verifica a diferença entre o tempo atual | |
* e o tempo do último ciclo, se essa diferença for maior | |
* ou igual a constante de ciclo, realiza a tarefa desejada. | |
* | |
* Outras informações em http://arduino.cc/forum/index.php/topic,5686.msg44073.html | |
* | |
*/ | |
boolean cycleCheck(unsigned long *UpdateLastMillis, unsigned long UpdateCycle) { | |
unsigned long currentMillis = millis(); | |
if(currentMillis - *UpdateLastMillis >= UpdateCycle) { | |
*UpdateLastMillis = currentMillis; | |
return true; | |
} | |
else{ | |
return false; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment