Raghav Ganesh
/
AvnetATT_shape_hackathon
This program simply connects to a HTS221 I2C device to read Temperature
Revision 2:0e2ef866af95, committed 2016-07-10
- Comitter:
- JMF
- Date:
- Sun Jul 10 00:52:49 2016 +0000
- Parent:
- 1:af7a42f7d465
- Child:
- 3:26b3cc155f39
- Commit message:
- Adding in WNC code from Fred
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/config_me.h Sun Jul 10 00:52:49 2016 +0000 @@ -0,0 +1,10 @@ +#ifndef __CONFIG_ME_H_ +#define __CONFIG_ME_H_ + +// User must set these for own context: +static const char * MY_FLOW_DEVICE_ID_STR = "48482f"; +static const char * MY_SERVER_URL = "run-east.att.io"; +static const char * MY_APN_STR = "m2m.com.attz"; +static const char * MY_PORT_STR = "80"; + +#endif
--- a/main.cpp Sat Jul 09 00:45:53 2016 +0000 +++ b/main.cpp Sun Jul 10 00:52:49 2016 +0000 @@ -3,6 +3,9 @@ #include <string> #include "SerialBuffered.h" #include "HTS221.h" +#include "config_me.h" +#include "wnc_control.h" + // comment out the following line if color is not supported on the terminal #define USE_COLOR @@ -54,56 +57,6 @@ #define MAX_AT_RSP_LEN 255 -// -// The modem will return strings of HEX encoded data. This function takes -// a pointer to a string of HEX ASCII data and converts it into a string -// of ASCII data. It takes a pointer to the string of HEX ASCII data and -// a pointer to the destination string. It returns the number of characters -// it converted. -// -int DecodeASCIIstr(string& ins, string& outs) { - int val, n = 0; - char ts[] = {0,0,0}; - - while(n<ins.length()) { - ts[0] = ins[n]; - ts[1] = ins[n+1]; - sscanf(ts,"%X",&val); - sprintf(ts,"%c",val); - outs.append(ts); - n += 2; - } - return outs.length(); -} - - -// -// Modem expects data to be passed to it in the form of HEX encoded strings. This -// function takes a pointer to a users supplied ASCII string, and converts it into -// an ASCII string of equivelent HEX numbers encoded as a string. The function takes -// a pointer to the users input string, and a pointer to the output string. The -// function returns the number of characters converted or 0 if an error occurs or more -// than 750 characters were converted. The 750 chacter limit is because the modem -// will only accept up to 1500 characters, and the converted srings will be 2x the -// input string since the hex representation of 1 character is a two digit hex value. -// -int CreateASCIIstr(string& ins, string& outs) { - int i = 0; - char ts[3]; - - if( ins.length() > 749 ) - return 0; - - while(ins[i] != 0x00) { - sprintf(ts,"%02X", ins[i]); - outs.append(ts); - i++; - } - return outs.length(); -} - - - ssize_t mdm_getline(char *buff, size_t size, int timeout_ms) { int cin = -1; int cin_last; @@ -128,7 +81,7 @@ } wait_ms(1); } - buff[len] = NULL; + buff[len] = (char)NULL; return len; } @@ -189,6 +142,10 @@ // initialze comm with the modem mdm.baud(115200); + // clear out potential garbage + while (mdm.readable()) + mdm.getc(); + mdm_uart1_cts = 0; // enable the signal level translator to start @@ -210,15 +167,76 @@ return false; } +int mdm_sendAtCmdRsp(const char *cmd, const char **rsp_list, int timeout_ms, string * rsp, int * len) { + + static char cmd_buf[3200]; // Need enough room for the WNC sockreads (over 3000 chars) + + if (cmd && strlen(cmd) > 0) { + if (mdm_dbgmask & MDM_DBG_AT_CMDS) { + printf(MAG "ATCMD: " DEF "--> " GRN "%s" DEF "\n", cmd); + } + mdm.printf("%s\r\n", cmd); + } + + if (rsp_list) { + rsp->erase(); // Clean up from prior cmd response + *len = 0; + Timer timer; + timer.start(); + while (timer.read_ms() < timeout_ms) { + int lenCmd = mdm_getline(cmd_buf, sizeof(cmd_buf), timeout_ms - timer.read_ms()); + + if (lenCmd == 0) + continue; + + if (lenCmd < 0) + return MDM_ERR_TIMEOUT; + else { + *len += lenCmd; + *rsp += cmd_buf; + } + + if (mdm_dbgmask & MDM_DBG_AT_CMDS) { + printf(MAG "ATRSP: " DEF "<-- " CYN "%s" DEF "\n", cmd_buf); + } + + int rsp_idx = 0; + while (rsp_list[rsp_idx]) { + if (strcasecmp(cmd_buf, rsp_list[rsp_idx]) == 0) { + return rsp_idx; + } + rsp_idx++; + } + } + return MDM_ERR_TIMEOUT; + } + pc.printf("D %s",rsp); + return MDM_OK; +} + +void reinitialize_mdm(void) +{ + // Initialize the modem + printf(GRN "Modem RE-initializing..." DEF "\r\n"); + if (!mdm_init()) { + printf(RED "\n\rModem RE-initialization failed!" DEF "\n"); + } + printf("\r\n"); +} +// These are built on the fly +string MyServerIpAddress; +string MySocketData; + +// These are to be built on the fly +string my_temp; +string my_humidity; + #define CTOF(x) ((x)*1.8+32) int main() { + int i; HTS221 hts221; pc.baud(115200); - int i, - CreateASCIIstr(string& in, string& out), - DecodeASCIIstr(string& ins, string& outs); - string ins, outs; void hts221_init(void); @@ -233,15 +251,6 @@ printf("Temp is: %0.2f F \n\r",CTOF(hts221.readTemperature())); printf("Humid is: %02d %%\n\r",hts221.readHumidity()); - - string newstr, outstr, instr = "0123456789aAbBcCdDeEfFxXyYzZ"; - pc.printf("\n\rTest ASCII String creation: \n\r"); - i = CreateASCIIstr(instr,outstr); - pc.printf(">Initially the string is '%s' (%d long)\n\r>after encode it is '%s' (%d characters long).\n\r", - instr.c_str(),instr.length(),outstr.c_str(),i); - i = DecodeASCIIstr(outstr, newstr); - pc.printf(">after decoding the encoded string, it is '%s' (%d long)\n\r\n\r",newstr.c_str(),i); - // Initialize the modem printf(GRN "Modem initializing... will take up to 60 seconds" DEF "\r\n"); @@ -251,34 +260,23 @@ while (1); } - // Now that the modem is up and running, transfer characters - // between the pc terminal and the modem to give the user - // a virtual terminal to the modem. - pc.printf(YEL "\rAT command interface ready, completed in %d seconds. You may now type AT commands" DEF "\r\n",i); - - while(1) { - if(pc.readable()) { - char char_in = TOUPPER(pc.getc()); - - static char last_char_in = 0; + //Software init + software_init_mdm(); + + // Resolve URL to IP address to connect to + resolve_mdm(); - if (('\r' == char_in) || ('\n' == char_in)) - { - if (('\r' == char_in) || ('\r' != last_char_in)) - { - mdm.puts("\r\n"); - } - } - else - { - pc.putc(char_in); - mdm.putc(char_in); - } - last_char_in = char_in; - } - if(mdm.readable()) { - char ser_char = mdm.getc(); - pc.putc(ser_char); - } + // Send and receive data perpetually + while(1) { + sockopen_mdm(); + sockwrite_mdm("GET /f653d97537235/a31c2684a02c/d35e42196968fd6/in/flow/climate?deviceID=e5ee19804bd500c8fe69a809342384c2&temp=41.0&humidity=87.33 HTTP/1.1 Host: run-east.att.io:80 Accept: */*\r\n\r\n"); + sockread_mdm(&MySocketData, 1024, 20); + sockclose_mdm(); + } + + string * pStr; + while (1) + { + send_wnc_cmd("AT", &pStr, WNC_TIMEOUT_MS); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wnc_control.cpp Sun Jul 10 00:52:49 2016 +0000 @@ -0,0 +1,331 @@ +#include "mbed.h" +#include <cctype> +#include <string> +#include "config_me.h" +#include "SerialBuffered.h" +#include "wnc_control.h" + +extern Serial pc; +extern Serial mdm; +extern string MyServerIpAddress; +extern string MySocketData; + +int reinitialize_mdm(void); + +enum WNC_ERR_e { + WNC_OK =0, + WNC_CMD_ERR = -1, + WNC_NO_RESPONSE = -2 +}; + +// Contains result of last call to send_wnc_cmd(..) +WNC_ERR_e WNC_MDM_ERR = WNC_OK; + +// Contains the RAW WNC UART responses +static string wncStr; + +void software_init_mdm(void) +{ + do + { + WNC_MDM_ERR = WNC_OK; + at_init_wnc(); + if (WNC_MDM_ERR != WNC_OK) + reinitialize_mdm(); + } while (WNC_MDM_ERR != WNC_OK); +} + +void resolve_mdm(void) +{ + do + { + WNC_MDM_ERR = WNC_OK; + at_dnsresolve_wnc(MY_SERVER_URL, &MyServerIpAddress); + if (WNC_MDM_ERR == WNC_NO_RESPONSE) + { + reinitialize_mdm(); + software_init_mdm(); + } + else if (WNC_MDM_ERR == WNC_CMD_ERR) + { + pc.puts("Bad URL!!!!!!\r\n"); + MyServerIpAddress = "192.168.0.1"; + WNC_MDM_ERR = WNC_OK; + } + } while (WNC_MDM_ERR != WNC_OK); + + pc.printf("My Server IP: %s\r\n", MyServerIpAddress.data()); +} + +void sockopen_mdm(void) +{ + do + { + WNC_MDM_ERR = WNC_OK; + at_sockopen_wnc(MyServerIpAddress, MY_PORT_STR); + if (WNC_MDM_ERR == WNC_NO_RESPONSE) + { + reinitialize_mdm(); + software_init_mdm(); + } + else if (WNC_MDM_ERR == WNC_CMD_ERR) + pc.puts("Socket open fail!!!!\r\n"); + } while (WNC_MDM_ERR != WNC_OK); +} + +void sockwrite_mdm(const char * s) +{ + do + { + WNC_MDM_ERR = WNC_OK; + at_sockwrite_wnc(s); + if (WNC_MDM_ERR == WNC_NO_RESPONSE) + { + reinitialize_mdm(); + software_init_mdm(); + } + else if (WNC_MDM_ERR == WNC_CMD_ERR) + { + pc.puts("Socket Write fail!!!\r\n"); + // Have seen when write fails modem gets stuck in bad state, try to recover + reinitialize_mdm(); + software_init_mdm(); + } + } while (WNC_MDM_ERR != WNC_OK); +} + +void sockread_mdm(string * sockData, int len, int retries) +{ + do + { + WNC_MDM_ERR = WNC_OK; + at_sockread_wnc(sockData, len, retries); + if (WNC_MDM_ERR == WNC_NO_RESPONSE) + { + reinitialize_mdm(); + software_init_mdm(); + } + else if (WNC_MDM_ERR == WNC_CMD_ERR) + puts("Sock read fail!!!!\r\n"); + } while (WNC_MDM_ERR != WNC_OK); +} + +void sockclose_mdm(void) +{ + do + { + WNC_MDM_ERR = WNC_OK; + at_sockclose_wnc(); + if (WNC_MDM_ERR == WNC_NO_RESPONSE) + { + reinitialize_mdm(); + software_init_mdm(); + } + else if (WNC_MDM_ERR == WNC_CMD_ERR) + puts("Sock close fail!!!\r\n"); + } while (WNC_MDM_ERR != WNC_OK); +} + +/** + * C++ version 0.4 char* style "itoa": + * Written by Lukás Chmela + * Released under GPLv3. +*/ + +char* itoa(int value, char* result, int base) +{ + // check that the base if valid + if ( base < 2 || base > 36 ) { + *result = '\0'; + return result; + } + + char* ptr = result, *ptr1 = result, tmp_char; + int tmp_value; + + do { + tmp_value = value; + value /= base; + *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz"[35 + (tmp_value - value * base)]; + } while ( value ); + + // Apply negative sign + if ( tmp_value < 0 ) + *ptr++ = '-'; + *ptr-- = '\0'; + + while ( ptr1 < ptr ) { + tmp_char = *ptr; + *ptr-- = *ptr1; + *ptr1++ = tmp_char; + } + + return result; +} + +extern int mdm_sendAtCmdRsp(const char *cmd, const char **rsp_list, int timeout_ms, string * rsp, int * len); + +// Sets a global with failure or success, assumes 1 thread all the time +int send_wnc_cmd(const char * s, string ** r, int ms_timeout) +{ + static const char * rsp_lst[] = { "OK", "ERROR", NULL }; + int len; + + pc.printf("Send: %s\r\n",s); + int res = mdm_sendAtCmdRsp(s, rsp_lst, ms_timeout, &wncStr, &len); + *r = &wncStr; // Return a pointer to the static string + + if (res >= 0) + { + pc.puts("["); + pc.puts(wncStr.data()); + pc.puts("]\n\r"); + if (res > 0) + { + if (WNC_MDM_ERR != WNC_NO_RESPONSE) + WNC_MDM_ERR = WNC_CMD_ERR; + return -1; + } + else + return 0; + } + else + { + WNC_MDM_ERR = WNC_NO_RESPONSE; + pc.puts("No response from WNC!\n\r"); + return -2; + } +} + +void at_init_wnc(void) +{ + string * pRespStr; + send_wnc_cmd("AT", &pRespStr, WNC_TIMEOUT_MS); // Heartbeat? + send_wnc_cmd("ATE1", &pRespStr, WNC_TIMEOUT_MS); // Echo ON + string cmd_str("AT%PDNSET=1,"); + cmd_str += MY_APN_STR; + cmd_str += ",IP"; + send_wnc_cmd(cmd_str.data(), &pRespStr, 2*WNC_TIMEOUT_MS); // Set APN, cmd seems to take a little longer sometimes + send_wnc_cmd("AT@INTERNET=1", &pRespStr, WNC_TIMEOUT_MS); // Internet services enabled + send_wnc_cmd("AT@SOCKDIAL=1", &pRespStr, WNC_TIMEOUT_MS); +} + +void at_sockopen_wnc(const string & ipStr, const char * port ) +{ + string * pRespStr; + send_wnc_cmd("AT@SOCKCREAT=1", &pRespStr, WNC_TIMEOUT_MS); + string cmd_str("AT@SOCKCONN=1,\""); + cmd_str += ipStr; + cmd_str += "\","; + cmd_str += port; + send_wnc_cmd(cmd_str.data(), &pRespStr, WNC_TIMEOUT_MS); +} + +void at_sockclose_wnc(void) +{ + string * pRespStr; + send_wnc_cmd("AT@SOCKCLOSE=1", &pRespStr, WNC_TIMEOUT_MS); +} + +int at_dnsresolve_wnc(const char * s, string * ipStr) +{ + string * pRespStr; + string str(s); + str = "AT@DNSRESVDON=\"" + str; + str += "\"\r\n"; + if (send_wnc_cmd(str.data(), &pRespStr, WNC_TIMEOUT_MS) == 0) + { + size_t pos_start = pRespStr->find(":\"") + 2; + if (pos_start != string::npos) + { + size_t pos_end = pRespStr->rfind("\"") - 1; + if (pos_end != string::npos) + { + if (pos_end > pos_start) + { + // Make a copy for use later (the source string is re-used) + *ipStr = pRespStr->substr(pos_start, pos_end - pos_start + 1); + return 1; + } + else + pc.puts("URL Resolve fail, substr Err\r\n"); + } + else + pc.puts("URL Resolve fail, no 2nd quote\r\n"); + } + else + pc.puts("URL Resolve fail, no quotes\r\n"); + } + else + pc.puts("URL Resolve fail, WNC cmd fail\r\n"); + + return -1; +} + +void at_sockwrite_wnc(const char * s) +{ + string * pRespStr; + char num2str[6]; + size_t sLen = strlen(s); + if (sLen <= 99999) + { + string cmd_str("AT@SOCKWRITE=1,"); + itoa(sLen, num2str, 10); + cmd_str += num2str; + cmd_str += ",\""; + while(*s != '\0') + { + itoa((int)*s++, num2str, 16); + // Always 2-digit ascii hex: + if (strlen(num2str) == 1) + { + num2str[2] = '\0'; + num2str[1] = num2str[0]; + num2str[0] = '0'; + } + cmd_str += num2str; + } + cmd_str += "\""; + send_wnc_cmd(cmd_str.data(), &pRespStr, WNC_TIMEOUT_MS); + } + else + pc.puts("sockwrite Err, string to long\r\n"); +} + +unsigned at_sockread_wnc(string * pS, unsigned n, unsigned retries = 0) +{ + unsigned i; + string * pRespStr; + string cmd_str("AT@SOCKREAD=1,"); + if (n <= 1500) + { + char num2str[6]; + itoa(n, num2str, 10); + cmd_str += num2str; + retries += 1; + while (retries--) + { + send_wnc_cmd(cmd_str.data(), &pRespStr, WNC_TIMEOUT_MS); + size_t pos_start = pRespStr->find("\"") + 1; + size_t pos_end = pRespStr->rfind("\"") - 1; + i = pos_end - pos_start + 1; + if (i > 0) + { + retries = 0; // If any data found stop retrying + string byte; + pS->erase(); + while (pos_start < pos_end) + { + byte = pRespStr->substr(pos_start, 2); + *pS += (char)strtol(byte.data(), NULL, 16); + pos_start += 2; + } + return i; + } + } + } + else + pc.puts("sockread Err, to many to read\r\n"); + + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wnc_control.h Sun Jul 10 00:52:49 2016 +0000 @@ -0,0 +1,28 @@ + +#ifndef __WNC_CONTROL_H_ +#define __WNC_CONTROL_H_ + +static const unsigned WNC_TIMEOUT_MS = 5000; + +// Core function that sends data to the WNC UART +extern int send_wnc_cmd(const char * s, string ** r, int ms_timeout); + +// Low level command functions +extern void at_init_wnc(void); +extern void at_sockopen_wnc(const string & ipStr, const char * port ); +extern void at_sockclose_wnc(void); +extern int at_dnsresolve_wnc(const char * s, string * ipStr); +extern void at_sockwrite_wnc(const char * s); +extern unsigned at_sockread_wnc(string * pS, unsigned n, unsigned retries); + +// High level functions that attempt to correct for things going bad with the WNC +extern void software_init_mdm(void); +extern void resolve_mdm(void); +extern void sockopen_mdm(void); +extern void sockwrite_mdm(const char * s); +extern void sockread_mdm(string * sockData, int len, int retries); +extern void sockclose_mdm(void); + +#endif + +