uses pushing box to publish to google spreadsheets with a state machine instead of a while loop
Fork of GSM_PUSHING_BOX_STATE_MACHINE by
Diff: GSMLibrary.cpp
- Revision:
- 32:424896b5adbe
- Parent:
- 30:421aae087064
- Child:
- 33:2ae9a4eb6433
--- a/GSMLibrary.cpp Tue Apr 28 03:03:19 2015 +0000 +++ b/GSMLibrary.cpp Wed Oct 21 19:44:15 2015 +0000 @@ -1,57 +1,44 @@ //Libraries #include "GSMLibrary.h" -#include "gsmqueue.h" +//#include "gsmqueue.h" #include <string.h> - +#include "GPRSInterface.h" +#include "gsmqueue.h" //Global defines #define TIMEOUTLIMIT SECONDS_TIMEOUT/TIME_CONST //Defines how many "ticks" of the GSM will constitute "timeout" of our "watchdog timer" - -//Extra defines for transmitter -#define START_SMS_TRANSMISSION "START" -#define STOP_SMS_TRANSMISSION "STOP" -#define GPS_SMS_TRANSMISSION "GPS" -#define RECEIVER_PHONE_NUMBER "\"+13853357314\"" -#define AT_CMGS "AT+CMGS=" RECEIVER_PHONE_NUMBER //Begin sending SMS with this send command and the phone number -#define NUM_SIZE 25 //Size of a temporary variable to help with concatenation of strings -#define BEGIN_SENSOR_DATA "$" //$ and % are parsed by using regex by the GUI for the receiver and indicate the start and end of data received -#define END_SENSOR_DATA "%" - -//Define AT commands to send -#define AT_OK "AT" //Ask GSM if everything is 'ok' -#define AT_CSQ "AT+CSQ" //Check signal strength -#define AT_CREG "AT+CREG?" //Check if GSM is registered on cellular network -#define AT_CNMI "AT+CNMI=2,0,0,0,0" //Turn off the notification that is normally received when text messages are received -#define AT_CMGF "AT+CMGF=1" //Turn on "text message mode" so we can characters (rather than PDU mode in which you send bytes) -#define AT_READ_MSG "AT+CMGL=\"REC UNREAD\"" //Read received messages that have not yet been read -#define AT_DEL_R_MSGS "AT+QMGDA=\"DEL READ\"" //Delete read messages - -//Define expected responses for AT commands -//Please notice that after ":" the gsm will usually send aditional information -#define AT_OK_RESPONSE "OK" //Response after sending "AT" message -#define AT_CSQ_RESPONSE "+CSQ:" //+CSQ: <arg1>,<arg2> where <arg1> is signal strength arg1 = 0-30 where a number below 10 means low signal strength and 99 is not knwn or detectable signal and arg2 is bit error rate form 0-7, 99 will represent error -#define AT_CREG_RESPONSE "+CREG:"//+CREG: <arg1>,<arg2> where <arg1> = 0-2(see AT command descriptions), <arg2> = 0-5, 0 not registered to nework and not looking for one. 1 is conected to network, 2 is not conected but searching -#define AT_CNMI_RESPONSE "OK" -#define AT_CMGF_RESPONSE "OK" -#define AT_CMGS_RESPONSE ">" //Received after you give the GSM the phone number. (We mistakenly thought it was received a second time after SMS was sent... this is not true!) -#define AT_SENDSMS_RESPONSE "+CMGS:" // +CMGS: <id> this will include the message id, or CMS ERROR for error. -#define AT_DEL_R_MSGS_RESPONSE "OK" +#define NUM_SIZE 250 //External variables extern Serial pc; //To print output to computer -extern Serial gsm; //To communicate with GSM +//extern Serial gsm; //To communicate with GSM extern uint8_t buffer[BUFFER_LENGTH]; //DMA queue +/************************************************** + ** GPRS ** + **************************************************/ +/** + * D1 - TX pin (RX on the WiFi side) + * D0 - RX pin (TX on the WiFi side) + * 19200 - Baud rate + * "apn" - APN name + * "username" - APN username + * "password" - APN passowrd + */ +GPRSInterface eth(D1,D0, 19200, "ndo","",""); //Internal variables gsm_states gsm_current_state = GSM_INITIALIZE; int timeout_count = 0; -char state_chars[] = "iosntmRPWD"; //For debugging - 1 char to represent each state: init, ok, signalstrength, network, turn off notifications, messagemode, read, phone, writesms, del +char state_chars[] = "iSJICS"; //For debugging - 1 char to represent each state: init, ok, signalstrength, network, turn off notifications, messagemode, read, phone, writesms, del +char* serverIP; +TCPSocketConnection sock; //Extras for transmitter +char gsm_msg[250]; //String storing SMS message that will be sent (add 250 length to give leeway) +char gsm_header[250]; //for the http header information +char num[NUM_SIZE]; //Temporary string storage to help with concatenation of strings char send = false; //if true => we will send something (only if send_enable is true) char send_enable = false; //Sending start and stop commands to GSM via SMS changes this variable. If true, we will send SMS messages of our data received -char undeleted_msgs = true; //At the beginning assume we have undeleted messages -char gsm_msg[MAX_SMS_LENGTH + 250]; //String storing SMS message that will be sent (add 250 length to give leeway) -char num[NUM_SIZE]; //Temporary string storage to help with concatenation of strings + //"Tick" of the GSM (i.e. this is a state machine) void gsm_tick() @@ -62,7 +49,7 @@ //gsm_printState(); //&debug //printQueue(); //&debug gsm_nextStateLogic(); //Next state - gsm_mealyOutputs(); //Mealy outputs. This state machine is a little different because Mealy outputs come after the next state logic + //gsm_mealyOutputs(); //Mealy outputs. This state machine is a little different because Mealy outputs come after the next state logic } } @@ -85,38 +72,60 @@ } //Have the GSM send data - L = long, S = short, hh/mm/ss for time, "lat ns" for latitute, "lon we" for longitude -void gsm_send_data(float L, float Lref, float S, float Sref, int hh, int mm, int ss, float lat, char ns, float lon, char we) +void gsm_send_data(float L, float Lref, int hh, int mm, int ss, float lat, char ns, float lon, char we) { - if (!gsm_ready()) //Don't send if gsm not ready - return; - //Concatenate data gsm_msg[0] = NULL; - strcat(gsm_msg, BEGIN_SENSOR_DATA); - snprintf(num, NUM_SIZE, "%f,", L); + gsm_header[0] = NULL; + int contentLength = 0; + snprintf(num, NUM_SIZE, "&phone=%s", "3852368101"); + contentLength += strlen(num); strcat(gsm_msg, num); - snprintf(num, NUM_SIZE, "%f,", Lref); + snprintf(num, NUM_SIZE, "&data=%f", L); + contentLength += strlen(num); strcat(gsm_msg, num); - snprintf(num, NUM_SIZE, "%f,", S); + snprintf(num, NUM_SIZE, "&dataRef=%f", Lref); + contentLength += strlen(num); strcat(gsm_msg, num); - snprintf(num, NUM_SIZE, "%f,", Sref); + snprintf(num, NUM_SIZE, "&dataRatio=%f", (Lref ? (L/Lref) : 0)); + contentLength += strlen(num); strcat(gsm_msg, num); - snprintf(num, NUM_SIZE, "%d:%d:%d,", hh, mm, ss); //If there is no data from GPS, the time will just be "0:0:0" (that is okay) + snprintf(num, NUM_SIZE, "&time=%02d:%02d:%02d", hh, mm, ss); //If there is no data from GPS, the time will just be "00:00:00" (that is okay) + contentLength += strlen(num); strcat(gsm_msg, num); if (ns != NULL) //If there is a gps fix (i.e. the gps has data on our location), ns will be set { - snprintf(num, NUM_SIZE, "%.4f,%.4f", (ns == 'N') ? lat : -lat, (we == 'E') ? lon : -lon); //Use + or - rather than N/S, E/W + snprintf(num, NUM_SIZE, "&latitude=%.4f&longitude=%.4f", (ns == 'N') ? lat : -lat, (we == 'E') ? lon : -lon); //Use + or - rather than N/S, E/W + contentLength += strlen(num); strcat(gsm_msg, num); } - else strcat(gsm_msg, "0,0"); //Otherwise just send 0's for latitude and longitude - strcat(gsm_msg, END_SENSOR_DATA); + else { + snprintf(num, NUM_SIZE,"&latitude=0&longitude=0"); + strcat(gsm_msg, num); //Otherwise just send 0's for latitude and longitude + contentLength += strlen(num); + } + + //header information + snprintf(num, NUM_SIZE, "%s", "POST /pushingbox?devid=v941C443DE0C7B14"); + strcat(gsm_header, num); + strcat(gsm_header, gsm_msg); + snprintf(num, NUM_SIZE, "%s"," HTTP/1.1\r\n"); + strcat(gsm_header, num); + snprintf(num, NUM_SIZE, "%s","Host: api.pushingbox.com\r\n"); + strcat(gsm_header, num); + snprintf(num, NUM_SIZE, "%s","Connection: close\r\n"); + strcat(gsm_header, num); + snprintf(num, NUM_SIZE, "%s","User-Agent: FRDM-KD64\r\n"); + strcat(gsm_header, num); + //must have two blank lines after so the server knows that this is the end of headers + snprintf(num, NUM_SIZE, "Content-Length: %d\r\n\r\n", contentLength); + strcat(gsm_header, num); send = true; //Mark that we are currently sending a message - strcat(gsm_msg, SMS_END_CHAR); //Add SMS end char } -//Return true if gsm is ready to send sms -//This only occurs if send = false (not currently sending a message) AND gsm received start sequence +//Return true if gsm is ready to send via tcp +//This only occurs if gsm received start sequence and responded appropriately bool gsm_ready() { return ((!send) && send_enable) ? true : false; @@ -126,12 +135,7 @@ //It does not reset send_enable void gsm_reset() { - //If we are in the middle of sending a text message, we need to "escape" out of this mode by sending the escape character - if (gsm_current_state == GSM_AT_CMGS) - sendCommand(SMS_ESCAPE_CHAR); - gsm_current_state = GSM_INITIALIZE; - undeleted_msgs = true; send = false; } @@ -146,127 +150,71 @@ { case GSM_INITIALIZE: timeout_count = 0; //No AT commands have been sent: this will send the first one - gsm_current_state = GSM_AT_OK; - break; - case GSM_AT_OK: - if (findInQueue(AT_OK_RESPONSE, true)) - gsm_current_state = GSM_AT_CSQ; - break; - case GSM_AT_CSQ: - if(findInQueue(AT_CSQ_RESPONSE, true)) - gsm_current_state = GSM_AT_CREG; - break; - case GSM_AT_CREG: - if(findInQueue(AT_CREG_RESPONSE, true)) - { - parseInt(); //After the CREG response we receive two integers. The second should be '1' (see AT_CREG_RESPONSE #define) - if(parseInt() == 1) - gsm_current_state = GSM_AT_CNMI; - } + printf(">>>INIT\r\n"); + if (eth.init() != NULL) { + printf(">>> Could not initialise. Halting!\n"); + exit(0); + } + gsm_current_state = GSM_CHECK_SIM; break; - case GSM_AT_CNMI: - if(findInQueue(AT_CNMI_RESPONSE, true)) - gsm_current_state = GSM_AT_CMGF; - break; - case GSM_AT_CMGF: - if(findInQueue(AT_CMGF_RESPONSE, true)) - gsm_current_state = GSM_READ_MSG; + case GSM_CHECK_SIM: + printf(">>>CHECK SIM\r\n"); + if (eth.preInit() == true){ + gsm_current_state = GSM_JOIN; + } break; - case GSM_READ_MSG: - if(send_enable) //If we are currently sending SMS, check if we need to stop transmission of SMS - { - if(findInQueue(STOP_SMS_TRANSMISSION, true)) //Always stop sending if stop sequence received by SMS - { - undeleted_msgs = true; - send_enable = false; //Set send_enable to indicate we will stop sending SMS - } - else if (send) //Only continue sending if we didn't find stop sequence AND user requested that we send sms - gsm_current_state = GSM_AT_CMGS; //Continue sending SMS (change state accordingly) - //Implicit: otherwise we will continue checking text messages in this state. + case GSM_JOIN: + printf(">>>JOIN\r\n"); + int join = eth.connect(); + if (join == false || join < 0){ + //stay here } - else //If we are not yet sending SMS, check if we need to start transmission of SMS - { - if(findInQueue(START_SMS_TRANSMISSION, true)) - { - undeleted_msgs = true; - send_enable = true; //Now we are in send SMS mode: whenever 'send' variable is set to true we will send an SMS - if (send) //Only begin sending a new SMS if user requested that we send SMS (i.e. there is data to send) - gsm_current_state = GSM_AT_CMGS; //Start sending SMS (change state accordingly) - } + else{ + //possibly send this sms to the main box at the lab + //eth.send_SMS("17066311506", eth.getIPAddress()); + gsm_current_state = GSM_SERVER_IP; } break; - case GSM_AT_CMGS: - if(findInQueue(AT_CMGS_RESPONSE, true)) - gsm_current_state = GSM_AT_SENDSMS; - break; - case GSM_AT_SENDSMS: - if(findInQueue(AT_SENDSMS_RESPONSE, true)) + case GSM_SERVER_IP: + printf(">>>SERVER IP\r\n"); + serverIP = "api.pushingbox.com"; + if(serverIP != NULL) { - //pc.printf("(Wid%i)",parseInt());//&debug - timeout_count = 0; //Reset timeout count - send = false; //Indicate we are done sending the text message - if (undeleted_msgs) //Check if we need to delete read messages - gsm_current_state = GSM_DEL_R_MSGS; //Only delete messages if there are unread messages - else - { - gsm_current_state = GSM_READ_MSG; //Otherwise skip the delete messages state; go read text messages again - //pc.printf("(Dnone)");//&debug - } + gsm_current_state = GSM_CONNECT; + } + else{ + gsm_current_state = GSM_JOIN; + } + break; + case GSM_CONNECT: + printf("\r\n>>>CONNECT TO: %s\r\n", serverIP); + //sock.set_blocking(true,5000); + if (sock.connect(serverIP,80) == true){ + gsm_current_state = GSM_SEND; + } + else{ + gsm_current_state = GSM_CONNECT; } - else - { - //pc.printf("(Werr)"); //&debug - gsm_current_state = GSM_AT_CMGS; //If failed, try resending the message (i.e. continue until timeout) + break; + case GSM_SEND: + printf(">>>READY TO SEND\r\n"); + if(send){ + if(sock.send_all(gsm_header, sizeof(gsm_header)-1)){ + printf("Data succesfully sent to server\r\n"); + //close the connection so others can send too + //wait(2); + //eth.disconnect(); + } + else{ + printf("Reconnecting to Server...\r\n"); + send = false; + gsm_current_state = GSM_CONNECT; + } } break; - case GSM_DEL_R_MSGS: - if (findInQueue(AT_DEL_R_MSGS_RESPONSE, true)) - { - undeleted_msgs = false; - //pc.printf("(Dsucc)"); //&debug - } - //else - //pc.printf("(Derr)"); //&debug - gsm_current_state = GSM_READ_MSG; - break; - default: - pc.printf("This is a state error\r\n"); - } -} - -//Mealy output logic ------------------------------------------------------ -void gsm_mealyOutputs() -{ - switch(gsm_current_state) - { - case GSM_INITIALIZE: - break; - case GSM_AT_OK: - sendCommand(AT_OK); - break; - case GSM_AT_CSQ: - sendCommand(AT_CSQ); - break; - case GSM_AT_CREG: - sendCommand(AT_CREG); - break; - case GSM_AT_CNMI: - sendCommand(AT_CNMI); - break; - case GSM_AT_CMGF: - sendCommand(AT_CMGF); - break; - case GSM_READ_MSG: - sendCommand(AT_READ_MSG); - break; - case GSM_AT_CMGS: - sendCommand(AT_CMGS); - break; - case GSM_AT_SENDSMS: - sendCommand(gsm_msg); //end char included - break; - case GSM_DEL_R_MSGS: - sendCommand(AT_DEL_R_MSGS); + case GSM_WAIT: + //check for text message from server asking for data + gsm_current_state = GSM_SEND; break; default: pc.printf("This is a state error\r\n");