Skip to content

Instantly share code, notes, and snippets.

@rat
Created August 5, 2013 10:43
Show Gist options
  • Save rat/6155004 to your computer and use it in GitHub Desktop.
Save rat/6155004 to your computer and use it in GitHub Desktop.
/*
* Arduino Gateway SMS
* Version 1.0 Jul, 2013
* Copyright 2013 Renato Tavares
*
* Modified by Renato Tavares <dr.renatotavares@gmail.com> to support ethernet shield and GPRS Shield.
*
* Complete Web Server to sending SMS with Arduino.
*/
// Incluindo bibliotecas necessárias
#include <SD.h>
#include <SPI.h>
#include <Ethernet.h>
#include <SoftwareSerial.h>
//Arduino Mega
//#define rxPin 50
//#define txPin 51
// 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);
// Inicia a biblioteca SoftwareSerial
// 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()
{
Serial.begin(19200);
mySerial.begin(19200);
Ethernet.begin(mac, ip);
pinMode(10, OUTPUT);
if (!SD.begin(4)) {
Serial.println("initialization failed!");
return;
}
Serial.println("SD iniciado");
}
/**
* 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)) {
Serial.println("Processando...");
get_sms_data();
Serial.println("Processado!!!!");
UpdateNoIP();
}
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();
Serial.println("Gravado com sucesso");
}
else {
Serial.println("error opening for save sms.txt");
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{
// Erro ao abrir o arquivo
Serial.println("Erro ao abrir o arquivo");
return;
}
}
else{
// Arquivo não existe
Serial.println("Arquino nao existe");
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;
while (client.connected()) {
if (client.available()) {
char c = client.read();
mensagem[pointer] = c;
pointer++;
mensagem[pointer] = '\0';
}
}
//desconecta o cliente
client.stop();
//recebeu a msg do PHP grava no SD
Serial.println(mensagem);
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;
}
}
void UpdateNoIP(){
EthernetClient client;
if(client.connect("dynupdate.no-ip.com", 80)){
Serial.println("Conectando com No-IP");
client.println("GET /nic/update?hostname=freesms2.hopto.org HTTP/1.0");
client.println("Host: dynupdate.no-ip.com");
client.println("Authorization: Basic Senha em Base64");
client.println("User-Agent: Arduino Client/1.0 dr.renatotavares@gmail.com");
client.println();
while(client.connected()){
// stay in this loop until the server closes the connection
while(client.available()){
// The server will not close the connection until it has sent the last packet
// and this buffer is empty
char read_char = client.read();
Serial.write(read_char);
}
}
// close your end after the server closes its end
client.stop();
Serial.println("Conexão com No-IP fechada");
}
else{
Serial.println("Falha na Conexão");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment