Skip to content

Instantly share code, notes, and snippets.

@rat
Created August 24, 2013 06:07
Show Gist options
  • Save rat/3d746c449b458210c07a to your computer and use it in GitHub Desktop.
Save rat/3d746c449b458210c07a to your computer and use it in GitHub Desktop.
#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