summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mts/MTS_IO_CellularRadio.h3
-rw-r--r--include/mts/MTS_IO_ICellularRadio.h41
-rw-r--r--src/MTS_IO_CellularRadio.cpp114
-rw-r--r--src/MTS_IO_ICellularRadio.cpp3
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";