diff options
-rw-r--r-- | include/mts/MTS_IO_CellularRadio.h | 3 | ||||
-rw-r--r-- | include/mts/MTS_IO_ICellularRadio.h | 41 | ||||
-rw-r--r-- | src/MTS_IO_CellularRadio.cpp | 114 | ||||
-rw-r--r-- | src/MTS_IO_ICellularRadio.cpp | 3 |
4 files changed, 161 insertions, 0 deletions
diff --git a/include/mts/MTS_IO_CellularRadio.h b/include/mts/MTS_IO_CellularRadio.h index f32251c..60659dc 100644 --- a/include/mts/MTS_IO_CellularRadio.h +++ b/include/mts/MTS_IO_CellularRadio.h @@ -145,6 +145,9 @@ namespace MTS { CODE getVoiceSupport(Json::Value& jData) override; CODE getVoiceSupport(bool& bVoiceEnabled, bool& bSmsOnly) override; + CODE getPdpContexts(Json::Value& jData) override; + CODE setPdpContext(const std::string& sId, const Json::Value& jConfig) override; + protected: CellularRadio(const std::string& sName, const std::string& sRadioPort); diff --git a/include/mts/MTS_IO_ICellularRadio.h b/include/mts/MTS_IO_ICellularRadio.h index f3e15e2..91ab782 100644 --- a/include/mts/MTS_IO_ICellularRadio.h +++ b/include/mts/MTS_IO_ICellularRadio.h @@ -205,6 +205,10 @@ namespace MTS { static const char *KEY_ATTEMPTS_PIN; //!< The number of attempts left to unlock the SIM card using PIN code static const char *KEY_ATTEMPTS_PUK; //!< The number of attempts left to unlock the SIM card using PUK code + //PDP Context + static const char *KEY_PDP_CONTEXT_APN; + static const char *KEY_PDP_CONTEXT_IPMODE; + //Values - Type static const char *VALUE_TYPE_LTE; static const char *VALUE_TYPE_GSM; @@ -656,6 +660,43 @@ namespace MTS { */ virtual CODE getSelectedBandsRaw(std::string& sRawBands) = 0; + /** + * @brief Get the list of PDP contexts from the radio + * + * @param jData - an object to be filled with data. + * { + * "<context_number: str>": { + * "apn": "<apn_value: str>", + * "ipMode": "<ip_mode: str>" + * } + * } + * + * @return CODE::SUCCESS when fetched successfully, + * CODE::NO_RESPONSE when the modem doesn't respond, + * CODE::ERROR when the radio returns "ERROR", + * CODE::FAILURE otherwise (unexpected response). + */ + virtual CODE getPdpContexts(Json::Value& jData) = 0; + + /** + * @brief Set the PDP context to the radio + * + * @param sId - a string value that contains an ID of the PDP context to change. + * @param jConfig - a JSON-object that contains: + * an IP mode for the specified PDP context, + * an APN for the specified PDP context. + * { + * "apn": "<APN>", + * "ipMode": "<IP MODE>" + * } + * + * @return CODE::SUCCESS when fetched successfully, + * CODE::NO_RESPONSE when the modem doesn't respond, + * CODE::ERROR when the radio returns "ERROR", + * CODE::FAILURE otherwise (unexpected response). + */ + virtual CODE setPdpContext(const std::string& sId, const Json::Value& jConfig) = 0; + }; } } diff --git a/src/MTS_IO_CellularRadio.cpp b/src/MTS_IO_CellularRadio.cpp index afdfc1e..3de96ce 100644 --- a/src/MTS_IO_CellularRadio.cpp +++ b/src/MTS_IO_CellularRadio.cpp @@ -1755,3 +1755,117 @@ ICellularRadio::CODE CellularRadio::getSelectedBandsRaw(std::string& sRawBands) printTrace("%s| Acquiring selected bands: not applicable", m_sName.c_str()); return NOT_APPLICABLE; } + +ICellularRadio::CODE CellularRadio::getPdpContexts(Json::Value& jData) { + printTrace("%s| Fetching the list of PDP contexts from the radio", getName().c_str()); + CODE rc; + + const std::string sCommand = "AT+CGDCONT?"; + const int dTimeout = 1000; + std::string sResult; + + rc = sendBasicQuery(sCommand, "", sResult, dTimeout); + if (rc != SUCCESS) { + return rc; + } + + std::vector<std::string> vContexts = MTS::Text::split(sResult, "+CGDCONT: "); + std::vector<std::string> vContextParams; + + for (size_t i = 0; i < vContexts.size(); i++) { + vContexts[i] = MTS::Text::trim(vContexts[i]); + + if (vContexts[i].empty()) { + continue; + } + + vContextParams = MTS::Text::split(vContexts[i], ",", 4); + + if (vContextParams.size() < 3) { + return FAILURE; + } + + std::string sContextId = vContextParams[0]; + std::string sIpMode = MTS::Text::trim(vContextParams[1], '"'); // Remove double quotes from the start and end of the value + std::string sApn = MTS::Text::trim(vContextParams[2], '"'); // Remove double quotes from the start and end of the value + + jData[sContextId][ICellularRadio::KEY_PDP_CONTEXT_IPMODE] = sIpMode; + jData[sContextId][ICellularRadio::KEY_PDP_CONTEXT_APN] = sApn; + } + + return SUCCESS; +} + +ICellularRadio::CODE CellularRadio::setPdpContext(const std::string& sId, const Json::Value& jConfig) { + printTrace("%s| Setting context to the radio", getName().c_str()); + CODE rc; + + if (sId.empty()) { + printError("%s| PDP Context ID is not specified", getName().c_str()); + return FAILURE; + } + + std::string sCommand = "AT+CGDCONT=" + sId; + const int dTimeout = 1000; + + Json::Value jAllContexts; + + rc = getPdpContexts(jAllContexts); + if (rc != SUCCESS) { + printError("%s| Failed to retrieve the current PDP context configuration: [%d]", getName().c_str(), rc); + return rc; + } + + // Remove the context if no parameters defined + if (!jConfig.isMember(ICellularRadio::KEY_PDP_CONTEXT_IPMODE) && !jConfig.isMember(ICellularRadio::KEY_PDP_CONTEXT_APN)) { + if (jAllContexts.isMember(sId)) { + rc = sendBasicCommand(sCommand, dTimeout); + return rc; + } else { + printError("%s| PDP Context [%s] does not exist", getName().c_str(), sId.c_str()); + return FAILURE; + } + } + + std::string sIpMode; + + if (jConfig.isMember(ICellularRadio::KEY_PDP_CONTEXT_IPMODE)) { + if (jConfig[ICellularRadio::KEY_PDP_CONTEXT_IPMODE] == "IP" || jConfig[ICellularRadio::KEY_PDP_CONTEXT_IPMODE] == "PPP" || + jConfig[ICellularRadio::KEY_PDP_CONTEXT_IPMODE] == "IPV6" || jConfig[ICellularRadio::KEY_PDP_CONTEXT_IPMODE] == "IPV4V6") { + sIpMode = jConfig[ICellularRadio::KEY_PDP_CONTEXT_IPMODE].asString(); + } else { + printError("%s| Invalid IP Mode defined: [%s]", getName().c_str(), jConfig[ICellularRadio::KEY_PDP_CONTEXT_IPMODE].asString().c_str()); + return FAILURE; + } + } else if (jAllContexts.isMember(sId)) { + printInfo("%s| Re-using IP Mode [%s] for PDP context [%s]", getName().c_str(), jAllContexts[sId][ICellularRadio::KEY_PDP_CONTEXT_IPMODE].asString().c_str(), sId.c_str()); + sIpMode = jAllContexts[sId][ICellularRadio::KEY_PDP_CONTEXT_IPMODE].asString(); + } else { + printError("%s| Failed to edit PDP context [%s] - no such context defined", getName().c_str(), sId.c_str()); + return FAILURE; + } + + sCommand += ",\""; + sCommand += sIpMode; + sCommand += "\""; + + std::string sApn; + + if (jConfig.isMember(ICellularRadio::KEY_PDP_CONTEXT_APN)) { + sApn = jConfig[ICellularRadio::KEY_PDP_CONTEXT_APN].asString(); + } else if (jAllContexts.isMember(sId)) { + printInfo("%s| Re-using APN [%s] for PDP context [%s]", getName().c_str(), jAllContexts[sId][ICellularRadio::KEY_PDP_CONTEXT_APN].asString().c_str(), sId.c_str()); + sApn = jAllContexts[sId][ICellularRadio::KEY_PDP_CONTEXT_APN].asString(); + } else { + printError("%s| Failed to edit PDP context [%s] - no such context defined", getName().c_str(), sId.c_str()); + return FAILURE; + } + + sCommand += ",\""; + sCommand += sApn; + sCommand += "\""; + + rc = sendBasicCommand(sCommand, dTimeout); + + return rc; +}
\ No newline at end of file diff --git a/src/MTS_IO_ICellularRadio.cpp b/src/MTS_IO_ICellularRadio.cpp index 7453662..05af28d 100644 --- a/src/MTS_IO_ICellularRadio.cpp +++ b/src/MTS_IO_ICellularRadio.cpp @@ -97,6 +97,9 @@ const char *MTS::IO::ICellularRadio::KEY_MIP_REVTUN = "revTun"; const char *MTS::IO::ICellularRadio::KEY_MIP_MNAAASS = "mnAaaSs"; //!< Mobile Node Authentication, Authorization, and Accounting Server Shared Secret const char *MTS::IO::ICellularRadio::KEY_MIP_MNHASS = "mnHaSs"; //!< Mobile Node Home Agent Shared Secret +const char *MTS::IO::ICellularRadio::KEY_PDP_CONTEXT_APN = "apn"; +const char *MTS::IO::ICellularRadio::KEY_PDP_CONTEXT_IPMODE = "ipMode"; + const char *MTS::IO::ICellularRadio::VALUE_TYPE_GSM = "GSM"; const char *MTS::IO::ICellularRadio::VALUE_TYPE_LTE = "LTE"; const char *MTS::IO::ICellularRadio::VALUE_TYPE_CDMA = "CDMA"; |