C027 の mbes os 5 での動作を確認しました。 I confirmed the operation at mbes os 5 of C 027.
Fork of C027_Support by
Diff: MDM.cpp
- Revision:
- 135:cbccf4052d45
- Parent:
- 134:2fbd5723e063
- Child:
- 136:8dc8f48275fc
--- a/MDM.cpp Tue Jan 12 08:37:29 2016 +0000 +++ b/MDM.cpp Thu Jan 21 15:59:42 2016 +0000 @@ -13,6 +13,10 @@ #define ISSOCKET(s) (((s) >= 0) && ((s) < NUMSOCKETS) && (_sockets[s].handle != SOCKET_ERROR)) //! check for timeout #define TIMEOUT(t, ms) ((ms != TIMEOUT_BLOCKING) && (ms < t.read_ms())) +// num HTTP profiles +#define NUMPROFILES (sizeof(_httpProfiles)/sizeof(*_httpProfiles)) +//! test if it is an HTTP profile is ok to use +#define ISPROFILE(p) (((p) >= 0) && ((p) < NUMPROFILES) && (_httpProfiles[p].handle != HTTP_PROF_ERROR)) //! registration ok check helper #define REG_OK(r) ((r == REG_HOME) || (r == REG_ROAMING)) //! registration done check helper (no need to poll further) @@ -103,6 +107,9 @@ memset(_sockets, 0, sizeof(_sockets)); for (int socket = 0; socket < NUMSOCKETS; socket ++) _sockets[socket].handle = SOCKET_ERROR; + memset(_httpProfiles, 0, sizeof(_httpProfiles)); + for (int profile = 0; profile < NUMPROFILES; profile ++) + _httpProfiles[profile].handle = HTTP_PROF_ERROR; #ifdef MDM_DEBUG _debugLevel = 1; _debugTime.start(); @@ -196,8 +203,13 @@ _loc.time.tm_yday=0; _loc.validData = true; TRACE("Parsed UULOC position\r\n"); - } - if (_dev.dev == DEV_LISA_C2) { + // +UHTTPCR: <profile_id>,<op_code>,<param_val> + } else if ((sscanf(cmd, "UUHTTPCR: %d,%d,%d", &a, &b, &c) == 3)) { + _httpProfiles[a].cmd = b; //command + _httpProfiles[a].result = c; //result + TRACE("%s for profile %d: result code is %d\r\n", getHTTPcmd(b), a, c); + } + if (_dev.dev == DEV_LISA_C2) { // CDMA Specific ------------------------------------------- // +CREG: <n><SID>,<NID>,<stat> if (sscanf(cmd, "CREG: %*d,%d,%d,%d",&a,&b,&c) == 3) { @@ -1315,6 +1327,301 @@ } // ---------------------------------------------------------------- +// HTTP + +int MDMParser::httpFindProfile() +{ + int profile = HTTP_PROF_ERROR; //default value + LOCK(); + // find a free HTTP profile + profile = _findProfile(); + TRACE("httpFindProfile: profile is %d\r\n", profile); + if (profile != HTTP_PROF_ERROR) { + _httpProfiles[profile].handle = 1; + _httpProfiles[profile].timeout_ms = TIMEOUT_BLOCKING; + _httpProfiles[profile].pending = false; + _httpProfiles[profile].cmd = -1; + _httpProfiles[profile].result = -1; + } + UNLOCK(); + return profile; +} + +int MDMParser::_findProfile(int handle) { + for (int profile = 0; profile < NUMPROFILES; profile++) { + if (_httpProfiles[profile].handle == handle) + return profile; + } + return HTTP_PROF_ERROR; +} + +bool MDMParser::httpSetBlocking(int profile, int timeout_ms) +{ + bool ok = false; + LOCK(); + TRACE("httpSetBlocking(%d,%d)\r\n", profile, timeout_ms); + if (ISPROFILE(profile)) { + _httpProfiles[profile].timeout_ms = timeout_ms; + ok = true; + } + UNLOCK(); + return ok; +} + +bool MDMParser::httpSetProfileForCmdMng(int profile) +{ + bool ok = false; + LOCK(); + TRACE("httpSetProfileForCmdMng(%d)\r\n", profile); + if (ISPROFILE(profile)) { + _httpProfiles[profile].pending = true; + _httpProfiles[profile].result = -1; + ok = true; + } + UNLOCK(); + return ok; +} + +bool MDMParser::httpFreeProfile(int profile) +{ + bool ok = true; + LOCK(); + if (ISPROFILE(profile)) { + TRACE("httpFreeProfile(%d)\r\n", profile); + _httpProfiles[profile].handle = HTTP_PROF_ERROR; + _httpProfiles[profile].timeout_ms = TIMEOUT_BLOCKING; + _httpProfiles[profile].pending = false; + _httpProfiles[profile].cmd = -1; + _httpProfiles[profile].result = -1; + ok = true; + } + UNLOCK(); + return ok; +} + +bool MDMParser::httpResetProfile(int httpProfile) +{ + bool ok = false; + + LOCK(); + TRACE("httpResetProfile(%d)\r\n", httpProfile); + sendFormated("AT+UHTTP=%d\r\n", httpProfile); + if (RESP_OK == waitFinalResp()) + ok = true; + UNLOCK(); + + return ok; +} + +bool MDMParser::httpSetPar(int httpProfile, HttpOpCode httpOpCode, const char * httpInPar) +{ + bool ok = false; + IP ip = NOIP; + int httpInParNum = 0; + + LOCK(); + TRACE("httpSetPar(%d,%d,\"%s\")\r\n", httpProfile, httpOpCode, httpInPar); + switch(httpOpCode){ + case HTTP_IP_ADDRESS: //0 + ip = gethostbyname(httpInPar); + if (ip == NOIP) + return false; + + sendFormated("AT+UHTTP=%d,%d,\"" IPSTR "\"\r\n", httpProfile, httpOpCode, IPNUM(ip)); + if (RESP_OK == waitFinalResp()) + ok = true; + break; + + case HTTP_SERVER_NAME: //1 + case HTTP_USER_NAME: //2 + case HTTP_PASSWORD: //3 + sendFormated("AT+UHTTP=%d,%d,\"%s\"\r\n", httpProfile, httpOpCode, httpInPar); + if (RESP_OK == waitFinalResp()) + ok = true; + break; + + case HTTP_AUTH_TYPE: //4 + case HTTP_PORT: //5 + httpInParNum = atoi(httpInPar); + sendFormated("AT+UHTTP=%d,%d,%d\r\n", httpProfile, httpOpCode, httpInParNum); + if (RESP_OK == waitFinalResp()) + ok = true; + break; + + case HTTP_SECURE: //6 + if(_dev.dev != DEV_LISA_C2) + { + httpInParNum = atoi(httpInPar); + sendFormated("AT+UHTTP=%d,%d,%d\r\n", httpProfile, httpOpCode, httpInParNum); + if (RESP_OK == waitFinalResp()) + ok = true; + } else { + TRACE("httpSetPar: HTTP secure option not supported by module\r\n"); + ok = false; + } + break; + + default: + TRACE("httpSetPar: unknown httpOpCode %s\r\n", httpOpCode); + ok = false; + break; + } + UNLOCK(); + return ok; +} + +bool MDMParser::httpCommand(int httpProfile, HttpCmd httpCmdCode, const char* httpPath, const char* httpOut, \ + const char* httpIn, int httpContentType, const char* httpCustomPar, char* buf, int len) +{ + bool ok = false; +#ifdef MDM_DEBUG + memset(buf, '\0', len); +#endif + LOCK(); + TRACE("%s\r\n", getHTTPcmd(httpCmdCode)); + switch (httpCmdCode) + { + case HTTP_HEAD: + sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\"\r\n", httpProfile, HTTP_HEAD, httpPath, httpOut); + break; + + case HTTP_GET: + sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\"\r\n", httpProfile, HTTP_GET, httpPath, httpOut); + break; + + case HTTP_DELETE: + sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\"\r\n", httpProfile, HTTP_DELETE, httpPath, httpOut); + break; + + case HTTP_PUT: + //in this case the parameter httpIn is a filename + sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\"\r\n", httpProfile, HTTP_PUT, httpPath, httpOut, httpIn); + break; + + case HTTP_POST_FILE: + //in this case the parameter httpIn is a filename + if(_dev.dev != DEV_LISA_C2) + { + if(httpContentType != 6) + sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\",%d\r\n", \ + httpProfile, HTTP_POST_FILE, httpPath, httpOut, httpIn, httpContentType); + else + sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\",%d,%d\r\n", \ + httpProfile, HTTP_POST_FILE, httpPath, httpOut, httpIn, httpContentType, httpCustomPar); + } + else{ + if((httpContentType != 5) && (httpContentType != 6) && (httpCustomPar == NULL)) + { + //parameters values consistent with the AT commands specs of LISA-C200 + //(in particular httpCustomPar has to be not defined) + sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\",%d\r\n", \ + httpProfile, HTTP_POST_FILE, httpPath, httpOut, httpIn, httpContentType); + } else { + TRACE("httpCommand: command not supported by module"); + return ok; //error + } + } + break; + + case HTTP_POST_DATA: + //in this case the parameter httpIn is a string containing data + if(_dev.dev != DEV_LISA_C2) + { + if(httpContentType != 6) + sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\",%d\r\n", \ + httpProfile, HTTP_POST_DATA, httpPath, httpOut, httpIn, httpContentType); + else + sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\",%d,%d\r\n", \ + httpProfile, HTTP_POST_DATA, httpPath, httpOut, httpIn, httpContentType, httpCustomPar); + } else { + if((httpContentType != 5) && (httpContentType != 6) && (httpCustomPar == NULL)) + { + //parameters values consistent with the AT commands specs of LISA-C200 + //(in particular httpCustomPar has to be not defined) + sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\",%d\r\n", \ + httpProfile, HTTP_POST_DATA, httpPath, httpOut, httpIn, httpContentType); + } else { + TRACE("httpCommand: command not supported by module"); + return ok; //error + } + } + break; + + default: + TRACE("HTTP command not recognized\r\n"); + return ok; //error + } + + if (RESP_OK == waitFinalResp()) + { + Timer timer; + timer.start(); + httpSetProfileForCmdMng(httpProfile); + while (_httpProfiles[httpProfile].pending) //waiting for unsolicited + { + ok = false; //reset variable + if(_httpProfiles[httpProfile].result != -1) + { + //received unsolicited: starting its analysis + _httpProfiles[httpProfile].pending = false; + if(_httpProfiles[httpProfile].result == 1) + { + //HTTP command successfully executed + if(_dev.dev != DEV_LISA_C2) + { + TRACE("httpCommand: reading files with a dimension " \ + "also greater than MAX_SIZE bytes\r\n"); + if(readFileNew(httpOut,buf,len) >=0 ) + ok = true; + } else { + TRACE("httpCommand: reading files with a dimension " \ + "less than MAX_SIZE bytes, otherwise error\r\n"); + if(readFile(httpOut,buf,len) >=0 ) + ok = true; + } + } else { + //HTTP command not successfully executed + ok = false; + } + } else if (!TIMEOUT(timer, _httpProfiles[httpProfile].timeout_ms)) { + ok = (WAIT == waitFinalResp(NULL,NULL,0)); // wait for URCs + } else { + //not received unsolicited and expired timer + TRACE("httpCommand: not received unsolicited and expired timer\r\n"); + ok = false; + } + if (!ok) { + TRACE("%s: ERROR\r\n", getHTTPcmd(httpCmdCode)); + _httpProfiles[httpProfile].pending = false; //no more while loops + } + } + } + UNLOCK(); + return ok; +} + +const char* MDMParser::getHTTPcmd(int httpCmdCode) +{ + switch (httpCmdCode) + { + case HTTP_HEAD: + return "HTTP HEAD command"; + case HTTP_GET: + return "HTTP GET command"; + case HTTP_DELETE: + return "HTTP DELETE command"; + case HTTP_PUT: + return "HTTP PUT command"; + case HTTP_POST_FILE: + return "HTTP POST file command"; + case HTTP_POST_DATA: + return "HTTP POST data command"; + default: + return "HTTP command not recognized"; + } +} + +// ---------------------------------------------------------------- int MDMParser::_cbCMGL(int type, const char* buf, int len, CMGLparam* param) { @@ -1482,7 +1789,112 @@ } return WAIT; } + +//The following function is useful for reading files with a dimension greater than MAX_SIZE bytes +int MDMParser::readFileNew(const char* filename, char* buf, int len) +{ + int countBytes = -1; //counter for file reading (default value) + + if(_dev.dev != DEV_LISA_C2) + { + //retrieve information about the file, in particular its size + int filesize = infoFile(filename); + TRACE("readFileNew: filename is %s; filesize is %d\r\n", filename, filesize); + + if (len < filesize) + TRACE("readFileNew: WARNING. Buffer dimension is %d bytes," \ + "while file size is %d bytes\r\n", len, filesize); + + if (filesize > 0) + { +#ifdef MDM_DEBUG + memset(buf, '\0', len); +#endif + int offset = 0; //start reading from 0 + int blockSize = MAX_SIZE; //still need space for headers and unsolicited commands + int bytesToRead = filesize; //bytes to read + + while (bytesToRead) + { + bool ok = false; + + if (bytesToRead < blockSize) + blockSize = bytesToRead; + + LOCK(); + if (blockSize > 0) { + + sendFormated("AT+URDBLOCK=\"%s\",%d,%d\r\n", filename, offset, blockSize); + + if (RESP_OK == waitFinalResp(_cbURDBLOCK, buf)) { + bytesToRead -= blockSize; + offset += blockSize; + buf += blockSize; + ok = true; + } else { + //error condition + countBytes = -1; + ok = false; + } + } + UNLOCK(); + + if (!ok) { + TRACE("readFileNew: ERROR\r\n"); + return countBytes; //in this case countBytes is -1 + } + } + + countBytes = offset; //total read bytes + return countBytes; + } + } else { + TRACE("httpCommand: command not supported by module"); + } + return countBytes; //it could be 0 or -1 (possible error) +} + +int MDMParser::_cbURDBLOCK(int type, const char* buf, int len, char* out) +{ + char fileNameRes[48]; + int sizeRes; + + if ((type == TYPE_PLUS) && out) { + if ((sscanf(buf, "\r\n+URDBLOCK: \"%[^\"]\",%d,", fileNameRes, &sizeRes) == 2) && + (buf[len-sizeRes-2] == '\"') && (buf[len-1] == '\"')) { + memcpy(out, &buf[len-1-sizeRes], sizeRes); + } + } + + return WAIT; +} + +int MDMParser::infoFile(const char* filename) +{ + int infoFile = 0; //default value + + LOCK(); + sendFormated("AT+ULSTFILE=2,\"%s\"\r\n", filename); + if (RESP_OK != waitFinalResp(_cbULSTFILE, &infoFile)) + infoFile = -1; //error condition + UNLOCK(); + + return infoFile; +} + +int MDMParser::_cbULSTFILE(int type, const char* buf, int len, int* infoFile) +{ + if (infoFile) { + if (type == TYPE_PLUS) { + if (sscanf(buf, "\r\n+ULSTFILE: %d\r\n", infoFile) == 1) { + } + } + } + return WAIT; +} + // ---------------------------------------------------------------- + int MDMParser::cellLocSrvHttp (const char* token, const char* server_1, const char* server_2, int days/* = 14*/, \ int period/* = 4*/, int resolution/* = 1*/) { @@ -1728,6 +2140,7 @@ { "\r\n+USORD: %d,%d,\"%c\"", TYPE_PLUS }, { "\r\n+USORF: %d,\"" IPSTR "\",%d,%d,\"%c\"", TYPE_PLUS }, { "\r\n+URDFILE: %s,%d,\"%c\"", TYPE_PLUS }, + { "\r\n+URDBLOCK: %s,%d,\"%c\"", TYPE_PLUS }, }; static struct { const char* sta; const char* end; int type;