SMS Scheduler that will automatically send and receive text messages using the Enfora 1308 GSM Modem. Please note that it uses a modified NetServices library and to set the baud rate for the GSM Modem to 19.2K.

Dependencies:   mbed

main.cpp

Committer:
mafischl
Date:
2011-10-13
Revision:
1:5a7cce9994a3
Parent:
0:d9266031f832

File content as of revision 1:5a7cce9994a3:

//Contest Winner using GSM Modem

#include "mbed.h"
#include "NetServices/if/eth/EthernetNetIf.h"
#include "NetServices/core/ipaddr.h"
#include "NetServices/services/http/server/HTTPServer.h"
#include "NetServices/services/ntp/NTPClient.h"
#include "TextLCD.h"
#include "MODSERIAL.h"
#include <math.h>
#include <iostream>
#include <string>
#define MESSAGE_BUFFER_SIZE 1024
using namespace std;

// OPTIONAL SETTINGS

int SMSinterval = 15;       //Send a SMS Vote once every n seconds
int TIMEZONE = 4;           //Number of hours behind UTC
int phoneNumber = 78527;    //Phone Number to send SMS Votes
string bodyText = "Buzz";    //Message to send in vote

//END OF OPTIONAL SETTINGS


MODSERIAL gsm(p28,p27);
EthernetNetIf eth;
HTTPServer svr;
NTPClient ntp;
Serial pc(USBTX, USBRX); // PC Virtual Serial Port over USB
TextLCD lcd(p15, p16, p17, p11, p12, p20); // rs, e, d4-d7
DigitalOut heartBeat(LED1); //Heartbeat
DigitalOut wdtLED(LED4); //WatchDog Indicator
Timer t, timeOrDateTimer, clockSyncTimer, statusMessageInterruptTimer, send_SMS_Timer, GSM_Buffer_Timer;
int SMScount = 0;
int timeCount;
int statusMessage = 0;
int compareResult = 0;
int messageResponse = 0;
int mpResult = 0;
bool timeOrDate = 0;
bool statusMessageAlert = 0;
bool statusMessageInterrupt = 0;
char messageBufferIncoming[MESSAGE_BUFFER_SIZE];
char messageBufferOutgoing[MESSAGE_BUFFER_SIZE];
bool messageReceived;
LocalFileSystem local("local");


char buf[40];
char buf1[40];
char buf2= 0x1A;    //CTRL+Z, Substitute character

extern "C" void mbed_mac_address(char *mac);

class Watchdog {
public:
// Load timeout value in watchdog timer and enable
    void kick(float s) {
        LPC_WDT->WDCLKSEL = 0x1;                // Set CLK src to PCLK
        uint32_t clk = SystemCoreClock / 16;    // WD has a fixed /4 prescaler, PCLK default is /4
        LPC_WDT->WDTC = s * (float)clk;
        LPC_WDT->WDMOD = 0x3;                   // Enabled and Reset
        kick();
    }
// "kick" or "feed" the dog - reset the watchdog timer
// by writing this required bit pattern
    void kick() {
        LPC_WDT->WDFEED = 0xAA;
        LPC_WDT->WDFEED = 0x55;
    }
};

Watchdog wdt;


void messageReceive(MODSERIAL_IRQ_INFO *q) {
    MODSERIAL *sys = q->serial;
    sys->move(messageBufferIncoming, MESSAGE_BUFFER_SIZE);
    messageReceived = true;
    return;
}

int messageProcess(void) {
    if (!strncmp(messageBufferIncoming, "OK", sizeof("OK")-1)) mpResult = 1;
    else if (!strncmp(messageBufferIncoming, "ERROR", sizeof("ERROR")-1)) mpResult = 2;
    else mpResult = 1;
    pc.printf("%s\r\n", messageBufferIncoming);
    gsm.rxBufferFlush();                            //Flush the Buffer
    messageReceived = false;
    return mpResult;
}

void sync_time() {
    //Connect to NIST and get time
    time_t ctTime;
    ctTime = time(NULL);

    Host server(IpAddr(), 123, "nist1-atl.ustiming.org");
    ntp.setTime(server);

    ctTime = time(NULL);
}

void send_SMS() {
    //Send SMS Vote

    gsm.printf("AT+CMGS=\"%d\"\r\n", phoneNumber);

    gsm.printf("%s%c\r\n", bodyText, buf2);
    if (messageProcess()==1) {
        statusMessageAlert = 1;
        statusMessage = 5;
        SMScount = SMScount + 1;
        pc.printf("SMS sent: %d\r\n", SMScount);
    } else {
        statusMessageAlert = 1;
        statusMessage = 7; //This value will also force a auto re-send
        pc.printf("SMS send failed\r\n");
    }
}

int main() {
    messageReceived = false;

    if ((LPC_WDT->WDMOD >> 2) & 1)
        wdtLED = 1;
    else wdtLED = 0;

// 30 second timeout on watchdog timer hardware
    wdt.kick(30.0);

    gsm.baud(19200);
    gsm.format(8, Serial::None, 1);
    gsm.attach(&messageReceive, MODSERIAL::RxAutoDetect);     //Attaches Interrupts
    gsm.autoDetectChar('\n');                                 //Set Detection to Line Feed
    pc.baud(19200);

    lcd.cls();
    lcd.locate(0,0);
    lcd.printf("----------------");
    lcd.locate(0,1);
    lcd.printf("----------------");
    lcd.cls();
    lcd.locate(0,0);
    lcd.printf(" Contest Winner");
    lcd.locate(0,1);
    lcd.printf("    Please Wait");
    wait(2);
    lcd.cls();
    lcd.locate(0,0);
    lcd.printf("Setting up...\n");
    pc.printf("Program Started, setting up Ethernet Connection...\r\n");
    EthernetErr ethErr = eth.setup();
    if (ethErr) {
        lcd.printf("Error %d in setup.\n", ethErr);
        pc.printf("Error %d in setup.\r\n", ethErr);
        return -1;
    }
    wdt.kick();

    // Set-UP GSM Modem

    pc.printf("Setting up GSM Modem\r\n");
    lcd.locate(0,0);
    lcd.printf("GSM Modem Setup");
    wait(1);

    gsm.printf("AT\r\n");                     //Check Connection
    wait(0.5);
    messageProcess();                         //Process incoming message

    gsm.printf("AT+CSMP=17,167,0,0\r\n");     //Set Text Parameters
    wait(0.5);
    messageProcess();                         //Process incoming message

    gsm.printf("AT+CSCA?\r\n");               //Check Service Center
    wait(0.5);
    messageProcess();                         //Process incoming message

    gsm.printf("AT+CMGF=1\r\n");              //Set format to Text Mode
    wait(0.5);
    messageProcess();                         //Process incoming message

    gsm.printf("AT+CNMI=1,1,0,0,0\r\n");      //Set the new messages indicator
    wait(0.5);
    messageProcess();                         //Process incoming message

    gsm.printf("AT+CSAS\r\n");                //Save the Current Setup, REGLED will light SOLID
    wait(3.0);
    messageProcess();                         //Process incoming message

    lcd.locate(0,0);
    lcd.printf("Setup OK        ");
    pc.printf("Setup Done\r\n");
    wait(1);
    wdt.kick();

    //Define RPC Controls
    //Base::add_rpc_class<DigitalOut>(p21);


    //Add RPC Handler
    svr.addHandler<SimpleHandler>("/");
    svr.addHandler<RPCHandler>("/rpc"); //Default handler
    pc.printf("Handlers installed\r\n");
    svr.bind(80);

    lcd.locate(0,0);
    lcd.printf("Listening...");
    pc.printf("Connection is live, listening on port 80\r\n");

    wdt.kick();
    //Connect to NIST and get time
    time_t ctTime;
    sync_time(); //sync time for the first time


    statusMessageAlert = 1;
    statusMessage = 1;


    pc.printf("Time was synced to NIST\r\n");
    wdt.kick();

    timeOrDateTimer.start();
    clockSyncTimer.start();
    Timer tm;
    t.start();
    tm.start();
    send_SMS_Timer.start();
    GSM_Buffer_Timer.start();

    while (true) {
        ctTime = time(NULL) - (TIMEZONE*60*60); //Update clock and adjust for timezone
        char buffer[32];

        if (statusMessageAlert) {
            statusMessageInterruptTimer.start();
            statusMessageAlert = 0;
            statusMessageInterrupt = 1;
        }

        if (statusMessageInterrupt) {   //Status Messages to be displayed where Date/Time
            lcd.locate(0,0);
            if (statusMessage==0) {
                lcd.printf("System is OK    ");
            } else if (statusMessage==1) {
                lcd.printf("Clock Sync..DONE");
            } else if (statusMessage==2) {
                lcd.printf("Clock Sync..FAIL");
            } else if (statusMessage==3) {
                lcd.printf("GSM Modem OK    ");
            } else if (statusMessage==4) {
                lcd.printf("GSM Modem Error ");
            } else if (statusMessage==5) {
                lcd.printf("Message Sent    ");
            } else if (statusMessage==6) {
                lcd.printf("Message Received");
            } else if (statusMessage==7) {           //SMS Send Failed, force auto re-send
                lcd.printf("Msg Send Error  ");
            } else if (statusMessage==8) {
                lcd.printf("Msg Recv Error  ");
            }
        }

        else {
            if (timeOrDate) {
                strftime(buffer, 32, "%X", localtime(&ctTime));
                lcd.locate(0,0);
                lcd.printf("%s (-%d:00)", buffer, TIMEZONE);
            } else {
                strftime(buffer, 32, "%a %b %d, %Y", localtime(&ctTime));
                lcd.locate(0,0);
                lcd.printf("%s", buffer);
            }
        }

        Net::poll();
        timeCount = t.read();

        //Timers

        if (timeCount > 0) {
            heartBeat = !heartBeat;
            t.stop();
            t.reset();
            t.start();
        }

        if (timeOrDateTimer > 3) {
            timeOrDate = !timeOrDate;
            timeOrDateTimer.stop();
            timeOrDateTimer.reset();
            timeOrDateTimer.start();
        }

        if (send_SMS_Timer > SMSinterval) {
            statusMessage = 0;
            send_SMS();
            send_SMS_Timer.stop();
            send_SMS_Timer.reset();
            send_SMS_Timer.start();
        }

        if (clockSyncTimer > 3600) {  //Re-Sync every hour
            sync_time();
            pc.printf("Time was synced to NIST\r\n");
            clockSyncTimer.stop();
            clockSyncTimer.reset();
            clockSyncTimer.start();
            statusMessageAlert = 1;
            statusMessage = 1;
        }

        if (GSM_Buffer_Timer > (25*SMSinterval)) {
            gsm.printf("AT+CMGD= 1, 1\r\n");                            //Clears out entire buffer
            pc.printf("GSM Buffer Cleared\r\n");
            GSM_Buffer_Timer.stop();
            GSM_Buffer_Timer.reset();
        }

        if (statusMessageInterruptTimer > 2) {
            statusMessageInterrupt = 0;
            statusMessageInterruptTimer.stop();
            statusMessageInterruptTimer.reset();
        }

        if (messageReceived) {      //Handle received messages
            messageProcess();
            statusMessageAlert = 1;
            statusMessage = 6;
        }

        wdt.kick();
    }

    return 0;
}