📄 gsm_me_ta.cc
字号:
// *************************************************************************// * GSM TA/ME library// *// * File: gsm_me_ta.cc// *// * Purpose: Mobile Equipment/Terminal Adapter functions// * (ETSI GSM 07.07)// *// * Author: Peter Hofmann (software@pxh.de)// *// * Created: 10.5.1999// *************************************************************************#ifdef HAVE_CONFIG_H#include <gsm_config.h>#endif#include <gsmlib/gsm_nls.h>#include <gsmlib/gsm_me_ta.h>#include <gsmlib/gsm_parser.h>#include <gsmlib/gsm_sysdep.h>using namespace std;using namespace gsmlib;// Capabilities membersCapabilities::Capabilities() : _hasSMSSCAprefix(true), _hasSMSPDUmode(true), _noCPBxParentheses(false), _cpmsParamCount(-1), // initialize to -1, must be set later by // setSMSStore() function _omitsColon(true), // FIXME _veryShortCOPSanswer(false), // Falcom A2-1 _wrongSMSStatusCode(false), // Motorola Timeport 260 _CDSmeansCDSI(false), // Nokia Cellular Card Phone RPE-1 GSM900 and // Nokia Card Phone RPM-1 GSM900/1800 _sendAck(false), // send ack for directly routed SMS _MotorolaModeCmd(false) // send "+MODE=" to Motorola phone{}// MeTa membersvoid MeTa::init() throw(GsmException){ // Motorola 60t needs "+MODE=2" before it will respond to GSM commands; // however it will identify itself with the mandatory ITU-T V.25ter // generic TA control command "+GMM". try { if (_at->chat("+GMM", "+GMM:") == "Motorola 60t Phone") { _capabilities._MotorolaModeCmd = true; _capabilities._noCPBxParentheses = true; // Put the phone in GSM command mode. The expected response is // <CR><LF>OK<CR><LF> // <CR><LF>+MBAN: Copyright 2000 Motorola, Inc.<CR><LF> _at->chat("+MODE=2", "", false, true); _at->getLine(); // consume <CR><LF> _at->getLine(); // consume +MBAN: ... <CR><LF> } } catch (GsmException) { // ignore, may not work on all phones } // switch on extended error codes // caution: may be ignored by some TAs, so allow it to fail _at->chat("+CMEE=1", "", true, true); // select SMS pdu mode try { _at->chat("+CMGF=0"); } catch (GsmException) { _capabilities._hasSMSPDUmode = false; } // now fill in capability object MEInfo info = getMEInfo(); // Ericsson model 6050102 if ((info._manufacturer == "ERICSSON" && (info._model == "1100801" || info._model == "1140801")) || getenv("GSMLIB_SH888_FIX") != NULL) { // the Ericsson leaves out the service centre address _capabilities._hasSMSSCAprefix = false; } // handle Falcom strangeness if ((info._manufacturer == "Funkanlagen Leipoldt OHG" && info._revision == "01.95.F2") || getenv("GSMLIB_FALCOM_A2_1_FIX") != NULL) { _capabilities._veryShortCOPSanswer = true; } // handle Motorola SMS store bug - wrong status code if ((info._manufacturer == "Motorola" && info._model == "L Series")) { _capabilities._wrongSMSStatusCode = true; } // handle Nokia Cellular Card Phone RPE-1 GSM900 and // Nokia Card Phone RPM-1 GSM900/1800 bug - CDS means CDSI if ((info._manufacturer == "Nokia Mobile Phones" && (info._model == "Nokia Cellular Card Phone RPE-1 GSM900" || info._model == "Nokia Card Phone RPM-1 GSM900/1800"))) { _capabilities._CDSmeansCDSI = true; } // find out whether we are supposed to send an acknowledgment Parser p(_at->chat("+CSMS?", "+CSMS:")); _capabilities._sendAck = p.parseInt() >= 1; // set GSM default character set try { setCharSet("GSM"); } catch (GsmException) { // ignore errors, some devices don't support this } // set default event handler // necessary to handle at least RING indications that might // otherwise confuse gsmlib _at->setEventHandler(&_defaultEventHandler);}MeTa::MeTa(Ref<Port> port) throw(GsmException) : _port(port){ // initialize AT handling _at = new GsmAt(*this); init();}// MeTa::MeTa(Ref<GsmAt> at) throw(GsmException) :// _at(at)// {// init();// }void MeTa::setPIN(string pin) throw(GsmException){ _at->chat("+CPIN=\"" + pin + "\"");}string MeTa::getPINStatus() throw(GsmException){ Parser p(_at->chat("+CPIN?", "+CPIN:")); return p.parseString();}void MeTa::setPhonebook(string phonebookName) throw(GsmException){ if (phonebookName != _lastPhonebookName) { _at->chat("+CPBS=\"" + phonebookName + "\""); _lastPhonebookName = phonebookName; }}string MeTa::setSMSStore(string smsStore, int storeTypes, bool needResultCode) throw(GsmException){ if (_capabilities._cpmsParamCount == -1) { // count the number of parameters for the CPMS AT sequences _capabilities._cpmsParamCount = 1; Parser p(_at->chat("+CPMS=?", "+CPMS:")); p.parseStringList(); while (p.parseComma(true)) { ++_capabilities._cpmsParamCount; p.parseStringList(); } } // optimatization: only set current SMS store if different from last call // or the result code is needed if (needResultCode || _lastSMSStoreName != smsStore) { _lastSMSStoreName = smsStore; // build chat string string chatString = "+CPMS=\"" + smsStore + "\""; for (int i = 1; i < min(_capabilities._cpmsParamCount, storeTypes); ++i) chatString += ",\"" + smsStore + "\""; return _at->chat(chatString, "+CPMS:"); } return "";}void MeTa::getSMSStore(string &readDeleteStore, string &writeSendStore, string &receiveStore) throw(GsmException){ Parser p(_at->chat("+CPMS?", "+CPMS:")); writeSendStore = receiveStore = ""; readDeleteStore = p.parseString(); p.parseComma(); p.parseInt(); p.parseComma(); p.parseInt(); if (p.parseComma(true)) { writeSendStore = p.parseString(); p.parseComma(); p.parseInt(); p.parseComma(); p.parseInt(); if (p.parseComma(true)) { receiveStore = p.parseString(); } }}void MeTa::waitEvent(GsmTime timeout) throw(GsmException){ if (_at->wait(timeout)) _at->chat(); // send AT, wait for OK, handle events}// aux function for MeTa::getMEInfo()static string stringVectorToString(const vector<string>& v, char separator = '\n'){ if (v.empty()) return ""; // concatenate string in vector as rows string result; for (vector<string>::const_iterator i = v.begin();;) { string s = *i; // remove leading and trailing "s if (s.length() > 0 && s[0] == '"') s.erase(s.begin()); if (s.length() > 0 && s[s.length() - 1] == '"') s.erase(s.end() - 1); result += s; // don't add end line to last if ( ++i == v.end() || !separator) break; result += separator; } return result;}MEInfo MeTa::getMEInfo() throw(GsmException){ MEInfo result; // some TAs just return OK and no info line // leave the info empty in this case // some TAs return multirows with info like address, firmware version result._manufacturer = stringVectorToString(_at->chatv("+CGMI", "+CGMI:", false)); result._model = stringVectorToString(_at->chatv("+CGMM", "+CGMM:", false)); result._revision = stringVectorToString(_at->chatv("+CGMR", "+CGMR:", false)); result._serialNumber = stringVectorToString(_at->chatv("+CGSN", "+CGSN:", false),0); return result;}vector<string> MeTa::getSupportedCharSets() throw(GsmException){ Parser p(_at->chat("+CSCS=?", "+CSCS:")); // Some phones leave out the parentheses return p.parseStringList(false, true);} string MeTa::getCurrentCharSet() throw(GsmException){ if (_lastCharSet == "") { Parser p(_at->chat("+CSCS?", "+CSCS:")); _lastCharSet = p.parseString(); } return _lastCharSet;}void MeTa::setCharSet(string charSetName) throw(GsmException){ _at->chat("+CSCS=\"" + charSetName + "\""); _lastCharSet = "";}string MeTa::getExtendedErrorReport() throw(GsmException){ return _at->chat("+CEER", "+CEER:");}void MeTa::dial(string number) throw(GsmException){ _at->chat("D" + number + ";");}void MeTa::answer() throw(GsmException){ _at->chat("A");}void MeTa::hangup() throw(GsmException){ _at->chat("H");}vector<OPInfo> MeTa::getAvailableOPInfo() throw(GsmException){ vector<OPInfo> result; vector<string> responses = _at->chatv("+COPS=?", "+COPS:"); // special treatment for Falcom A2-1, answer looks like // responses.push_back("(1,29341),(3,29340)"); if (_capabilities._veryShortCOPSanswer) { if (responses.size() == 1) { Parser p(responses[0]); while (p.parseChar('(', true)) { OPInfo opi; opi._status = (OPStatus)p.parseInt(); p.parseComma(); opi._numericName = p.parseInt(); p.parseChar(')'); p.parseComma(true); result.push_back(opi); } } } else // some formats I have encountered... //responses.push_back("2,,,31017,,(0,1),(2)"); //responses.push_back("(3,\"UK CELLNET\",\"CLNET\",\"23410\")," // "(3,\"ONE2 ONE\",\"ONE2ONE\",\"23430\")," // "(3,\"ORANGE\",\"ORANGE\",\"23433\")"); //responses.push_back("(2,\"D1-TELEKOM\",,26201)," // "(3,\"D2 PRIVAT\",,26202),,(0,1,3,4),(0,2)"); // some phones arbitrarily split the response into several lines //responses.push_back("(1,\"AMENA\",,\"21403\")," // "(3,\"MOVISTAR\",,\"21407\"),"); //responses.push_back("(3,\"E VODAFONE\",,\"21401\"),,(0,1),(2)"); // GSM modems might return // 1. quadruplets of info enclosed in brackets separated by comma // 2. several lines of quadruplets of info enclosed in brackets // 3. several lines of quadruplets without brackets and additional // info at EOL (e.g. Nokia 8290) for (vector<string>::iterator i = responses.begin(); i != responses.end(); ++i) {// while (i->length() > 0 && ! isprint((*i)[i->length() - 1]))// i->erase(i->length() - 1, 1); bool expectClosingParenthesis = false; Parser p(*i); while (1) { OPInfo opi; expectClosingParenthesis = p.parseChar('(', true); int status = p.parseInt(true); opi._status = (status == NOT_SET ? UnknownOPStatus : (OPStatus)status); p.parseComma(); opi._longName = p.parseString(true); p.parseComma(); opi._shortName = p.parseString(true); p.parseComma(); try { opi._numericName = p.parseInt(true); } catch (GsmException &e) { if (e.getErrorClass() == ParserError) { // the Ericsson GM12 GSM modem returns the numeric ID as string string s = p.parseString(); opi._numericName = checkNumber(s); } else throw e; } if (expectClosingParenthesis) p.parseChar(')'); result.push_back(opi); if (! p.parseComma(true)) break; // two commas ",," mean the list is finished if (p.getEol() == "" || p.parseComma(true)) break; } // without brackets, the ME/TA must use format 3. if (! expectClosingParenthesis) break; } return result;}OPInfo MeTa::getCurrentOPInfo() throw(GsmException){ OPInfo result; // 1. This exception thing is necessary because not all ME/TA combinations // might support all the formats and then return "ERROR". // 2. Additionally some modems return "ERROR" for all "COPS=3,n" command // and report only one format with the "COPS?" command (e.g. Nokia 8290). // get long format try { try { _at->chat("+COPS=3,0"); } catch (GsmException &e) { if (e.getErrorClass() != ChatError) throw;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -