From 576eb04e2d42e3b9c5fa40748d1d190a457fa1f8 Mon Sep 17 00:00:00 2001 From: sdesai Date: Wed, 15 Mar 2023 15:22:04 -0500 Subject: GP-139:Support Portal Case #5086148: use Cellular Radio timeas alternative to GPS or NTP --- include/mts/MTS_IO_CellularRadio.h | 167 ----------------- include/mts/MTS_IO_ICellularRadio.h | 53 ++---- include/mts/MTS_IO_QuectelRadio.h | 8 +- include/mts/MTS_IO_SequansRadio.h | 7 +- include/mts/MTS_IO_TelitRadio.h | 7 +- src/MTS_IO_CellularRadio.cpp | 353 +++++++++--------------------------- src/MTS_IO_ICellularRadio.cpp | 11 -- src/MTS_IO_QuectelRadio.cpp | 133 +++----------- src/MTS_IO_SequansRadio.cpp | 49 ++--- src/MTS_IO_TelitRadio.cpp | 139 ++++---------- 10 files changed, 190 insertions(+), 737 deletions(-) diff --git a/include/mts/MTS_IO_CellularRadio.h b/include/mts/MTS_IO_CellularRadio.h index 991dc47..68c1394 100644 --- a/include/mts/MTS_IO_CellularRadio.h +++ b/include/mts/MTS_IO_CellularRadio.h @@ -269,7 +269,6 @@ namespace MTS { virtual CODE sendData(const char* pData, size_t nBytes); virtual CODE sendBasicQuery(const std::string& sCmd, const std::string& sLabel, std::string& sResult, int32_t timeoutMillis = 100, const char& ESC = ICellularRadio::CR); - virtual CODE isCommandSupported(const std::string& sCmd, bool& bIsSupported); /** * @brief getDiagCommands - returns the list of Cellular Diagnostics commands for this radio. * @@ -279,172 +278,6 @@ namespace MTS { */ virtual const std::vector& getDiagCommands(bool bIsSimReady = true) = 0; - struct PdpContextInfo { - std::string sId; - std::string sIpMode; - std::string sApn; - std::string sAuthType; - std::string sUsername; - std::string sPassword; - }; - - virtual std::vector getSupportedPdpContextAuthTypes() const = 0; - static CODE convertPdpContextAuthTypeToString(PDP_CONTEXT_AUTH_TYPE eAuthType, std::string& sAuthType); - static CODE convertStringToPdpContextAuthType(const std::string& sAuthType, PDP_CONTEXT_AUTH_TYPE& eAuthType); - - /** - * @brief checks if PDP context authentication is supported by the modem. - * - * @param isSupported - sets to "true" if PDP context authentication is supported, "false" otherwise. - * - * @return CODE::SUCCESS when the response from the radio is received - * CODE::NO_RESPONSE when the modem doesn't respond, - * CODE::FAILURE otherwise. - */ - virtual CODE isPdpContextAuthSupported(bool& isSupported) = 0; - - /** - * @brief Get the list of PDP contexts with the base info about them from the radio. - * - * @param jData - a JSON object to be filled with data. - * { - * "context_number : STRING": { - * "apn" : "apn_value: STRING", - * "ipMode" : "ip_mode_value: STRING", - * } - * } - * - * @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 getPdpContextsBase(Json::Value& jData); - - /** - * @brief fills jData with the information about PDP context authentication - * - * @param jData - a JSON object that is pre-filled with the list of PDP contexts: - * { - * "context_number : STRING": { - * "apn" : "apn_value: STRING", - * "ipMode" : "ip_mode_value: STRING", - * } - * } - * On success the method will complement jData with the PDP context authentication fields: - * { - * "context_number : STRING": { - * "apn" : "apn_value: STRING", - * "authType" : "auth_type_value: STRING", - * "ipMode" : "ip_mode_value: STRING", - * "password" : "password_value (optional): STRING", - * "username" : "username_value (optional): STRING" - * } - * } - * - * @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 fillPdpContextAuthFields(Json::Value& jData) = 0; - - /** - * @brief merges the current configuration of the PDP context with the one requested by user - * - * @param sId - ID of the PDP context to change. - * @param jCurrentContext - a JSON object filled with current configuration data - * { - * "apn" : "apn_value (optional): STRING", - * "authType" : "auth_type_value: STRING", - * "ipMode" : "ip_mode_value: STRING", - * "password" : "password_value (optional): STRING", - * "username" : "username_value (optional): STRING" - * } - * @param jChanges - a JSON object filled with new configuration data - * { - * "apn" : "apn_value (optional): STRING", - * "authType" : "auth_type_value (optional): STRING", - * "ipMode" : "ip_mode_value (optional): STRING", - * "password" : "password_value (optional): STRING", - * "username" : "username_value (optional): STRING" - * } - * @param jResult - a JSON object to be filled with merged data - * { - * "apn" : "apn_value (optional): STRING", - * "authType" : "auth_type_value (optional): STRING", - * "id" : "ctx_id (optional): STRING", - * "ipMode" : "ip_mode_value (optional): STRING", - * "password" : "password_value (optional): STRING", - * "username" : "username_value (optional): STRING" - * } - * @return CODE::SUCCESS. - */ - virtual CODE mergePdpContexts(const std::string& sId, const Json::Value& jCurrentContext, const Json::Value& jChanges, Json::Value& jResult); - - /** - * @brief fills a PdpContextInfo instance with the data from JSON - * @param jData - a JSON object that contains: - * { - * "apn" : "apn_value: STRING", - * "authType" : "auth_type_value: STRING", - * "id" : "ctx_id: STRING", - * "ipMode" : "ip_mode_value: STRING", - * "password" : "password_value: STRING", - * "username" : "username_value: STRING" - * } - * @param pdpContextResult - PdpContextInfo object to be filled with parameters. - * @return CODE::SUCCESS if validated successfully, - * CODE::INVALID_ARGS if validation failed. - */ - virtual CODE initPdpContextInfo(const Json::Value& jConfig, PdpContextInfo& pdpContextResult); - - /** - * @brief checks if PDP context authentication should be configured - * @param jData - a JSON object that contains: - * { - * "apn" : "apn_value (optional): STRING", - * "authType" : "auth_type_value: STRING", - * "ipMode" : "ip_mode_value: STRING", - * "password" : "password_value (optional): STRING", - * "username" : "username_value (optional): STRING" - * } - * @param bIsAuthEditRequired - sets to "false" if there are no authType, username, and password fields in the json, otherwise sets to "true". - * @return CODE::SUCCESS. - */ - static CODE isPdpContextAuthEditRequired(const Json::Value& jConfig, bool& bIsAuthEditRequired); - - /** - * @brief Sets the base PDP context parameters: IP Mode and APN - * @param pdpContext - The new PDP context configuration - * @return CODE::SUCCESS when set successfully, - * CODE::NO_RESPONSE when the modem doesn't respond, - * CODE::ERROR when the radio returns "ERROR", - * CODE::FAILURE otherwise (unexpected response). - */ - virtual CODE setPdpContextBase(const PdpContextInfo& pdpContext); - - /** - * @brief Sets the Cellular Authentication parameters for this PDP context: Authentication Type, Username and Password. - * NOTE: Some implementations (Quectel) override the current IP Mode and APN in addition to the authentication fields. - * @param pdpContext - The new PDP context configuration - * @return CODE::SUCCESS when set successfully, - * CODE::NO_RESPONSE when the modem doesn't respond, - * CODE::ERROR when the radio returns "ERROR", - * CODE::FAILURE otherwise (unexpected response). - */ - virtual CODE setPdpContextAuth(const PdpContextInfo& pdpContext) = 0; - - /** - * @brief Delete the PDP context by its ID. - * @param sId - PDP context ID - * @return CODE::SUCCESS when delete successfully, - * CODE::NO_RESPONSE when the modem doesn't respond, - * CODE::ERROR when the radio returns "ERROR", - * CODE::FAILURE otherwise (unexpected response). - */ - virtual CODE deletePdpContext(const std::string& sId); - class RadioBandMap : public MTS::NonCopyable { public: RadioBandMap() diff --git a/include/mts/MTS_IO_ICellularRadio.h b/include/mts/MTS_IO_ICellularRadio.h index a698647..da8e130 100644 --- a/include/mts/MTS_IO_ICellularRadio.h +++ b/include/mts/MTS_IO_ICellularRadio.h @@ -78,13 +78,6 @@ namespace MTS { CS_MODE2 // only non-EPS services are allowed, the usage is "data centric" }; - enum PDP_CONTEXT_AUTH_TYPE : uint8_t { - NONE = 0, - PAP, - CHAP, - PAP_CHAP - }; - static CODE convertModelToType(const std::string& sModel, std::string& sType); static CODE convertModelToMtsShortCode(const std::string& sModel, std::string& sCode, ICellularRadio *radioObj = NULL); static CODE convertServiceDomainToString(SERVICEDOMAIN eSd, std::string& sSd); @@ -213,19 +206,8 @@ namespace MTS { 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_ID; static const char *KEY_PDP_CONTEXT_APN; static const char *KEY_PDP_CONTEXT_IPMODE; - static const char *KEY_PDP_CONTEXT_AUTH_TYPE; - static const char *KEY_PDP_CONTEXT_AUTH_USERNAME; - static const char *KEY_PDP_CONTEXT_AUTH_PASSWORD; - static const char *VALUE_PDP_CONTEXT_IP_MODE_IP; - static const char *VALUE_PDP_CONTEXT_IP_MODE_IPV6; - static const char *VALUE_PDP_CONTEXT_IP_MODE_IPV4V6; - static const char *VALUE_PDP_CONTEXT_AUTH_TYPE_NONE; - static const char *VALUE_PDP_CONTEXT_AUTH_TYPE_PAP; - static const char *VALUE_PDP_CONTEXT_AUTH_TYPE_CHAP; - static const char *VALUE_PDP_CONTEXT_AUTH_TYPE_PAP_CHAP; //Values - Type static const char *VALUE_TYPE_LTE; @@ -680,18 +662,12 @@ namespace MTS { /** * @brief Get the list of PDP contexts from the radio - * NOTE: authType, password and username are only present if the radio supports Cellular Authentication on - * the PDP Context Level. “password” and “username” are only present if the current authentication type is - * other than NONE. The “password” field is omitted on radios that do not allow reading the current password (i.e. on Telit LE910Cx). * * @param jData - an object to be filled with data. * { - * "context_number : STRING": { - * "apn" : "apn_value: STRING", - * "authType" : "auth_type_value: STRING", - * "ipMode" : "ip_mode_value: STRING", - * "password" : "password_value (optional): STRING", - * "username" : "username_value (optional): STRING" + * "": { + * "apn": "", + * "ipMode": "" * } * } * @@ -703,27 +679,20 @@ namespace MTS { virtual CODE getPdpContexts(Json::Value& jData) = 0; /** - * @brief Set the PDP context to the radio. If any of the fields are omitted, - * the system re-uses the current configuration for such fields. - * If all fields are omitted - the system deletes the context. - * "username" and "password" are mandatory if "ipMode" is PAP, CHAP or PAP-CHAP. - * "username", "password" and "authType" shall be omitted on radios that do NOT - * support Cellular Authentication on the PDP Context Level. + * @brief Set the PDP context to the radio * - * @param sId - ID of the PDP context that should be edited. - * @param jConfig - a JSON object that contains: + * @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_value (optional): STRING", - * "authType" : "auth_type_value (optional): STRING", - * "ipMode" : "ip_mode_value (optional): STRING", - * "password" : "password_value (optional): STRING", - * "username" : "username_value (optional): STRING" + * "apn": "", + * "ipMode": "" * } * * @return CODE::SUCCESS when fetched successfully, * CODE::NO_RESPONSE when the modem doesn't respond, * CODE::ERROR when the radio returns "ERROR", - * CODE::INVALID_ARGS when one of the JSON object values is incorrect OR not supported by the current radio, * CODE::FAILURE otherwise (unexpected response). */ virtual CODE setPdpContext(const std::string& sId, const Json::Value& jConfig) = 0; @@ -748,7 +717,7 @@ namespace MTS { * CODE::FAILURE otherwise. */ virtual CODE getDiagnostics(std::string& sDiagReport) = 0; - + virtual CODE getTimeUTC(void) = 0; }; } } diff --git a/include/mts/MTS_IO_QuectelRadio.h b/include/mts/MTS_IO_QuectelRadio.h index b3881cb..7015acb 100644 --- a/include/mts/MTS_IO_QuectelRadio.h +++ b/include/mts/MTS_IO_QuectelRadio.h @@ -85,14 +85,8 @@ namespace MTS { CODE setRxDiversity(const Json::Value& jArgs) override; - std::vector getSupportedPdpContextAuthTypes() const override; - static CODE convertStringToPdpContextType(const std::string& sStringType, std::string& sIntType); - CODE isPdpContextAuthSupported(bool& isSupported) override; - CODE fillPdpContextAuthFields(Json::Value& jData) override; - CODE setPdpContextAuth(const PdpContextInfo& pdpContext) override; - const std::vector& getDiagCommands(bool bIsSimReady = true) override; - + CODE getTimeUTC(void) override; private: // private variable to save old firmware versions during FOTA std::string m_sQuectelFirmware; diff --git a/include/mts/MTS_IO_SequansRadio.h b/include/mts/MTS_IO_SequansRadio.h index b5a3a38..d61ae67 100644 --- a/include/mts/MTS_IO_SequansRadio.h +++ b/include/mts/MTS_IO_SequansRadio.h @@ -49,18 +49,13 @@ namespace MTS { CODE setRxDiversity(const Json::Value& jArgs) override; const std::vector getRegistrationCommands() override; - + CODE getTimeUTC(void) override; protected: SequansRadio(const std::string& sName, const std::string& sRadioPort); CODE getIsSimInserted(bool& bData) override; CODE getSimLockAttempts(int& iAttemptsPin, int& iAttemptsPuk) override; - std::vector getSupportedPdpContextAuthTypes() const override; - CODE isPdpContextAuthSupported(bool& isSupported) override; - CODE fillPdpContextAuthFields(Json::Value& jData) override; - CODE setPdpContextAuth(const PdpContextInfo& pdpContext) override; - const std::vector& getDiagCommands(bool bIsSimReady = true) override; private: diff --git a/include/mts/MTS_IO_TelitRadio.h b/include/mts/MTS_IO_TelitRadio.h index dc02755..01897ac 100644 --- a/include/mts/MTS_IO_TelitRadio.h +++ b/include/mts/MTS_IO_TelitRadio.h @@ -51,7 +51,7 @@ namespace MTS { CODE fumoLocalApply(UpdateCb& stepCb) override; CODE getSelectedBandsRaw(std::string& sRawBands) override; - + CODE getTimeUTC(void) override; protected: TelitRadio(const std::string& sName, const std::string& sRadioPort); @@ -73,11 +73,6 @@ namespace MTS { virtual CODE fumoWriteGroupsABD(int fd, UpdateCb& stepCb); //virtual CODE fumoWriteGroupC(int fd, UpdateCb& stepCb); - std::vector getSupportedPdpContextAuthTypes() const override; - CODE isPdpContextAuthSupported(bool& isSupported) override; - CODE fillPdpContextAuthFields(Json::Value &jData) override; - CODE setPdpContextAuth(const PdpContextInfo& pdpContext) override; - const std::vector& getDiagCommands(bool bIsSimReady = true) override; static bool isContainsSignChar(const std::string& str); diff --git a/src/MTS_IO_CellularRadio.cpp b/src/MTS_IO_CellularRadio.cpp index 7200658..8cdaf44 100644 --- a/src/MTS_IO_CellularRadio.cpp +++ b/src/MTS_IO_CellularRadio.cpp @@ -22,7 +22,6 @@ #include #include -#include #include #include @@ -578,17 +577,25 @@ ICellularRadio::CODE CellularRadio::getTime(std::string& sDate, std::string& sTi sDate = ""; sTime = ""; sTimeZone = ""; + std::vector vTimeParts; + std::string sSign = "+"; + + if(getTimeUTC() == FAILURE) { + printWarning("%s| Unable to set Time Parameters for radio [%s]", m_sName.c_str()); + return FAILURE;; + } std::string sCmd("AT+CCLK?"); std::string sResult = sendCommand(sCmd); size_t end = sResult.find(ICellularRadio::RSP_OK); + if (end == std::string::npos) { printWarning("%s| Unable to get Time from radio using command [%s]", m_sName.c_str(), sCmd.c_str()); return FAILURE; } size_t start = sResult.find("CCLK: "); - if(start != std::string::npos) { + if (start != std::string::npos) { start += sizeof("CCLK: "); std::string sValue = MTS::Text::trim(sResult.substr(start, end - start)); sValue = MTS::Text::strip(sValue, '"'); @@ -599,39 +606,47 @@ ICellularRadio::CODE CellularRadio::getTime(std::string& sDate, std::string& sTi return FAILURE; } - std::vector vDateParts = MTS::Text::split(vParts[0], '/'); if(vDateParts.size() != 3) { - printWarning("%s| Unable to parse Date from response [%s]", m_sName.c_str(), sResult.c_str()); + printWarning("%s| Unable to parse Date parts from response [%s]", m_sName.c_str(), sResult.c_str()); return FAILURE; } - //The Date format is YY/MM/DD -> Change to MM/DD/YY - sDate = vDateParts[1] + "/" + vDateParts[2] + "/" + vDateParts[0]; + // The format is YYYY-MM-DD + sDate = vDateParts[0] + "-" + vDateParts[1] + "-" + vDateParts[2]; - vParts = MTS::Text::split(vParts[1], '-'); - if(vParts.size() != 2) { - printWarning("%s| Unable to parse Time from response [%s]", m_sName.c_str(), sResult.c_str()); - return FAILURE; + sTime = (vParts[1]); + + //E.g. 20:39:34-16. Split time and zone with + or - sign. + size_t psign = sTime.find("+"); + size_t nsign = sTime.find("-"); + + if (psign != std::string::npos) { + vTimeParts = MTS::Text::split(vParts[1], '+'); + } else if (nsign != std::string::npos) { + vTimeParts = MTS::Text::split(vParts[1], '-'); + sSign = "-"; } - sTime = vParts[0]; - int32_t iZoneUnits; //the difference, expressed in quarters of an hour, between the local time and GMT - if(!MTS::Text::parse(iZoneUnits, MTS::Text::strip(vParts[1], '+'))) { - printWarning("%s| Unable to parse Time Zone from response [%s]", m_sName.c_str(), sResult.c_str()); + if(vTimeParts.size() != 2) { + printWarning("%s| Unable to parse Time Zone from response [%s], size %d", m_sName.c_str(), sResult.c_str(),vTimeParts.size()); return FAILURE; } + //Get just the UTC time without zone info + sTime = (vTimeParts[0]); + + int32_t iZoneUnits = stoi(vTimeParts[1]); //the difference, expressed in quarters of an hour, between the local time and GMT int32_t iZone = iZoneUnits/4; //Divide by 4 to get hours difference int32_t iZonePartial = (iZoneUnits % 4) * 15; //Remainder in minutes - std::string sPlusSign = "+"; - if(iZonePartial < 0) { - //Remove negative sign from partial and clear plus sign component + + if (iZonePartial < 0) { + //Remove negative sign from partial and clear sign component iZonePartial *= -1; - sPlusSign = ""; + sSign = ""; } std::stringstream ss; - ss << sPlusSign << iZone; + ss << sSign << iZone; if(iZonePartial != 0) { ss << ":" << iZonePartial; } @@ -640,7 +655,7 @@ ICellularRadio::CODE CellularRadio::getTime(std::string& sDate, std::string& sTi return SUCCESS; } else { - printWarning("%s| Unable to get Time from radio using command [%s]", m_sName.c_str(), sCmd.c_str()); + printWarning("%s| Unable to parse Time from radio using command [%s]", m_sName.c_str(), sCmd.c_str()); } return FAILURE; @@ -1761,81 +1776,27 @@ ICellularRadio::CODE CellularRadio::sendBasicQuery(const std::string& sCmd, cons return SUCCESS; } -ICellularRadio::CODE CellularRadio::isCommandSupported(const std::string& sCmd, bool& bIsSupported) { - CODE rc; - bIsSupported = false; - - rc = sendBasicCommand(sCmd); - - if (SUCCESS == rc) { - bIsSupported = true; - } else if (ERROR == rc) { - // if not applicable - rc = SUCCESS; - } - - return rc; -} - ICellularRadio::CODE CellularRadio::getSelectedBandsRaw(std::string& sRawBands) { printTrace("%s| Acquiring selected bands: not applicable", m_sName.c_str()); return NOT_APPLICABLE; } -ICellularRadio::CODE CellularRadio::convertPdpContextAuthTypeToString(PDP_CONTEXT_AUTH_TYPE eAuthType, std::string& sAuthType) { - CODE rc = FAILURE; - - switch (eAuthType) { - case NONE: sAuthType = VALUE_PDP_CONTEXT_AUTH_TYPE_NONE; rc = SUCCESS; break; - case PAP: sAuthType = VALUE_PDP_CONTEXT_AUTH_TYPE_PAP; rc = SUCCESS; break; - case CHAP: sAuthType = VALUE_PDP_CONTEXT_AUTH_TYPE_CHAP; rc = SUCCESS; break; - case PAP_CHAP: sAuthType = VALUE_PDP_CONTEXT_AUTH_TYPE_PAP_CHAP; rc = SUCCESS; break; - default: sAuthType = ICellularRadio::VALUE_UNKNOWN; break; - } - return rc; -} - -ICellularRadio::CODE MTS::IO::CellularRadio::convertStringToPdpContextAuthType(const std::string& sAuthType, PDP_CONTEXT_AUTH_TYPE& eAuthType) { - CODE rc = FAILURE; - if (VALUE_PDP_CONTEXT_AUTH_TYPE_NONE == sAuthType) { - eAuthType = PDP_CONTEXT_AUTH_TYPE::NONE; - rc = SUCCESS; - } else if (VALUE_PDP_CONTEXT_AUTH_TYPE_PAP == sAuthType) { - eAuthType = PDP_CONTEXT_AUTH_TYPE::PAP; - rc = SUCCESS; - } else if (VALUE_PDP_CONTEXT_AUTH_TYPE_CHAP == sAuthType) { - eAuthType = PDP_CONTEXT_AUTH_TYPE::CHAP; - rc = SUCCESS; - } else if (VALUE_PDP_CONTEXT_AUTH_TYPE_PAP_CHAP == sAuthType) { - eAuthType = PDP_CONTEXT_AUTH_TYPE::PAP_CHAP; - rc = SUCCESS; - } - return rc; -} - -// When there are no defined contexts -// Telit returns: -// OK -// Quectel returns: -// +CGDCONT: -// -// OK -ICellularRadio::CODE CellularRadio::getPdpContextsBase(Json::Value& jData) { +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; - jData = Json::objectValue; - rc = sendBasicQuery(sCommand, "", sResult, dTimeout); if (rc != SUCCESS) { return rc; } - std::vector vContexts = MTS::Text::split(sResult, "+CGDCONT:"); + std::vector vContexts = MTS::Text::split(sResult, "+CGDCONT: "); + std::vector vContextParams; for (size_t i = 0; i < vContexts.size(); i++) { vContexts[i] = MTS::Text::trim(vContexts[i]); @@ -1844,7 +1805,7 @@ ICellularRadio::CODE CellularRadio::getPdpContextsBase(Json::Value& jData) { continue; } - std::vector vContextParams = MTS::Text::split(vContexts[i], ",", 4); + vContextParams = MTS::Text::split(vContexts[i], ",", 4); if (vContextParams.size() < 3) { return FAILURE; @@ -1861,216 +1822,78 @@ ICellularRadio::CODE CellularRadio::getPdpContextsBase(Json::Value& jData) { return SUCCESS; } -ICellularRadio::CODE CellularRadio::getPdpContexts(Json::Value& jData) { - printTrace("%s| Fetching the list of PDP contexts from the radio", getName().c_str()); +ICellularRadio::CODE CellularRadio::setPdpContext(const std::string& sId, const Json::Value& jConfig) { + printTrace("%s| Setting context to the radio", getName().c_str()); CODE rc; - bool bPdpAuthSupported; - // check if pdp context authentication is applicable - rc = isPdpContextAuthSupported(bPdpAuthSupported); - if (SUCCESS != rc) { - return rc; + if (sId.empty()) { + printError("%s| PDP Context ID is not specified", getName().c_str()); + return FAILURE; } - rc = getPdpContextsBase(jData); + std::string sCommand = "AT+CGDCONT=" + sId; + const int dTimeout = 1000; - if (SUCCESS != rc) { - printError("%s| Failed to fetch the list of the defined PDP contexts from the radio", getName().c_str()); + 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; } - if (bPdpAuthSupported) { - rc = fillPdpContextAuthFields(jData); - - if (SUCCESS != rc) { - printError("%s| Failed to fetch the authentication parameters for PDP contexts", getName().c_str()); + // 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; } } - return SUCCESS; -} - -ICellularRadio::CODE CellularRadio::mergePdpContexts(const std::string& sId, const Json::Value& jCurrentContext, const Json::Value& jChanges, Json::Value& jResult) { - jResult[KEY_PDP_CONTEXT_ID] = sId; - - if (jChanges.isMember(KEY_PDP_CONTEXT_IPMODE)) { - jResult[KEY_PDP_CONTEXT_IPMODE] = jChanges[KEY_PDP_CONTEXT_IPMODE].asString(); - } else if (jCurrentContext.isMember(KEY_PDP_CONTEXT_IPMODE)) { - printInfo("%s| Re-using IP Mode [%s] for PDP context [%s]", getName().c_str(), jCurrentContext[KEY_PDP_CONTEXT_IPMODE].asString().c_str(), sId.c_str()); - jResult[KEY_PDP_CONTEXT_IPMODE] = jCurrentContext[KEY_PDP_CONTEXT_IPMODE].asString(); - } - - if (jChanges.isMember(KEY_PDP_CONTEXT_APN)) { - jResult[KEY_PDP_CONTEXT_APN] = jChanges[KEY_PDP_CONTEXT_APN].asString(); - } else if (jCurrentContext.isMember(KEY_PDP_CONTEXT_APN)) { - printInfo("%s| Re-using APN [%s] for PDP context [%s]", getName().c_str(), jCurrentContext[KEY_PDP_CONTEXT_APN].asString().c_str(), sId.c_str()); - jResult[KEY_PDP_CONTEXT_APN] = jCurrentContext[KEY_PDP_CONTEXT_APN].asString(); - } - - if (jChanges.isMember(KEY_PDP_CONTEXT_AUTH_TYPE)) { - jResult[KEY_PDP_CONTEXT_AUTH_TYPE] = jChanges[KEY_PDP_CONTEXT_AUTH_TYPE].asString(); - } - - if (jChanges.isMember(KEY_PDP_CONTEXT_AUTH_USERNAME)) { - jResult[KEY_PDP_CONTEXT_AUTH_USERNAME] = jChanges[KEY_PDP_CONTEXT_AUTH_USERNAME].asString(); - } - - if (jChanges.isMember(KEY_PDP_CONTEXT_AUTH_PASSWORD)) { - jResult[KEY_PDP_CONTEXT_AUTH_PASSWORD] = jChanges[KEY_PDP_CONTEXT_AUTH_PASSWORD].asString(); - } - - return SUCCESS; -} - -ICellularRadio::CODE CellularRadio::initPdpContextInfo(const Json::Value& jConfig, PdpContextInfo& pdpContextResult) { - // validate IP mode - if (jConfig[KEY_PDP_CONTEXT_IPMODE].asString() != VALUE_PDP_CONTEXT_IP_MODE_IP && - jConfig[KEY_PDP_CONTEXT_IPMODE].asString() != VALUE_PDP_CONTEXT_IP_MODE_IPV6 && - jConfig[KEY_PDP_CONTEXT_IPMODE].asString() != VALUE_PDP_CONTEXT_IP_MODE_IPV4V6) { - printError("%s| The PDP context IP mode value is invalid [%s]", getName().c_str(), jConfig[KEY_PDP_CONTEXT_IPMODE].asString().c_str()); - return INVALID_ARGS; - } - - // validate authentication fields only if it is present - if (jConfig.isMember(KEY_PDP_CONTEXT_AUTH_TYPE)) { - - // check if the PDP context authentication is supported by the radio - const auto& sRequested = jConfig[KEY_PDP_CONTEXT_AUTH_TYPE].asString(); - const auto& vSupported = getSupportedPdpContextAuthTypes(); - - auto supportCheck = [sRequested](const std::string& sElement) { - return sRequested == sElement; - }; + std::string sIpMode; - if (std::none_of(vSupported.begin(), vSupported.end(), supportCheck)) { - printError("%s| PDP context parameters: authentication type [%s] is not supported", getName().c_str(), jConfig[KEY_PDP_CONTEXT_AUTH_TYPE].asString().c_str()); - return INVALID_ARGS; + 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; } - if (! jConfig.isMember(KEY_PDP_CONTEXT_AUTH_TYPE) && (jConfig.isMember(KEY_PDP_CONTEXT_AUTH_USERNAME) || jConfig.isMember(KEY_PDP_CONTEXT_AUTH_PASSWORD))) { - printError("%s| PDP context authentication type is not provided, but username or password are given", getName().c_str()); - return INVALID_ARGS; - } - - if (jConfig.isMember(KEY_PDP_CONTEXT_AUTH_TYPE) && jConfig[KEY_PDP_CONTEXT_AUTH_TYPE].asString() != VALUE_PDP_CONTEXT_AUTH_TYPE_NONE && - ! (jConfig.isMember(KEY_PDP_CONTEXT_AUTH_USERNAME) && jConfig.isMember(KEY_PDP_CONTEXT_AUTH_PASSWORD))) { - printError("%s| PDP context authentication type [%s]. The username or password are not provided", getName().c_str(), jConfig[KEY_PDP_CONTEXT_AUTH_TYPE].asString().c_str()); - return INVALID_ARGS; - } - - // fills with empty string if there are no such fields - pdpContextResult.sId = jConfig[KEY_PDP_CONTEXT_ID].asString(); - pdpContextResult.sIpMode = jConfig[KEY_PDP_CONTEXT_IPMODE].asString(); - pdpContextResult.sApn = jConfig[KEY_PDP_CONTEXT_APN].asString(); - pdpContextResult.sAuthType = jConfig[KEY_PDP_CONTEXT_AUTH_TYPE].asString(); - pdpContextResult.sUsername = jConfig[KEY_PDP_CONTEXT_AUTH_USERNAME].asString(); - pdpContextResult.sPassword = jConfig[KEY_PDP_CONTEXT_AUTH_PASSWORD].asString(); - - return SUCCESS; -} - -ICellularRadio::CODE CellularRadio::isPdpContextAuthEditRequired(const Json::Value& jConfig, bool& bIsAuthEditRequired) { - bIsAuthEditRequired = false; - - if (jConfig.isMember(KEY_PDP_CONTEXT_AUTH_TYPE) || - jConfig.isMember(KEY_PDP_CONTEXT_AUTH_PASSWORD) || - jConfig.isMember(KEY_PDP_CONTEXT_AUTH_USERNAME)) { - bIsAuthEditRequired = true; - } - - return SUCCESS; -} - -ICellularRadio::CODE CellularRadio::setPdpContextBase(const PdpContextInfo& pdpContext) { - std::string sCommand = "AT+CGDCONT="; - const int dTimeout = 1000; - - sCommand += pdpContext.sId; sCommand += ",\""; - sCommand += pdpContext.sIpMode; - sCommand += "\",\""; - sCommand += pdpContext.sApn; + sCommand += sIpMode; sCommand += "\""; - return sendBasicCommand(sCommand, dTimeout); -} - -ICellularRadio::CODE CellularRadio::deletePdpContext(const std::string& sId) { - std::string sCommand = "AT+CGDCONT=" + sId; - const int dTimeout = 1000; - - return sendBasicCommand(sCommand, dTimeout); -} - -ICellularRadio::CODE CellularRadio::setPdpContext(const std::string& sId, const Json::Value& jConfig) { - printTrace("%s| Setting PDP context [%s] to the radio", getName().c_str(), sId.c_str()); - - CODE rc; - Json::Value jCurrentContexts; - bool bPdpAuthSupported; - bool bPdpAuthEditRequired; - PdpContextInfo pdpContext; - - if (sId.empty()) { - printError("%s| PDP Context ID is not specified", getName().c_str()); - return INVALID_ARGS; - } - - rc = getPdpContexts(jCurrentContexts); - if (SUCCESS != rc) { - return rc; - } + std::string sApn; - // DELETE context - - if (jConfig.empty()) { - rc = deletePdpContext(sId); - if (SUCCESS != rc) { - printError("%s| Failed to delete PDP context [%s]", getName().c_str(), sId.c_str()); - } - return rc; - } - - // ADD or EDIT context - - // check if PDP context authentication is applicable - - (void) isPdpContextAuthEditRequired(jConfig, bPdpAuthEditRequired); - - rc = isPdpContextAuthSupported(bPdpAuthSupported); - if (SUCCESS != rc) { - return rc; - } - - if (! bPdpAuthSupported && bPdpAuthEditRequired) { - printError("%s| PDP context authentication is not supported by this radio, but arguments are provided", getName().c_str()); - return INVALID_ARGS; - } - - Json::Value jResult; - - // Edit - fetch missing arguments from the current state. - (void) mergePdpContexts(sId, jCurrentContexts[sId], jConfig, jResult); - - // validate fields and create a PDP context structure to use in the commands - rc = initPdpContextInfo(jResult, pdpContext); - if (SUCCESS != rc) { - return rc; + 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; } - // setting context - rc = setPdpContextBase(pdpContext); - if (SUCCESS != rc) { - return rc; - } + sCommand += ",\""; + sCommand += sApn; + sCommand += "\""; - if (bPdpAuthSupported && bPdpAuthEditRequired) { - return setPdpContextAuth(pdpContext); - } + rc = sendBasicCommand(sCommand, dTimeout); - return SUCCESS; + return rc; } ICellularRadio::CODE CellularRadio::getDiagnostics(std::string& sReport) { diff --git a/src/MTS_IO_ICellularRadio.cpp b/src/MTS_IO_ICellularRadio.cpp index f93cb21..e42713d 100644 --- a/src/MTS_IO_ICellularRadio.cpp +++ b/src/MTS_IO_ICellularRadio.cpp @@ -97,19 +97,8 @@ 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_ID = "id"; 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::KEY_PDP_CONTEXT_AUTH_TYPE = "authType"; -const char *MTS::IO::ICellularRadio::KEY_PDP_CONTEXT_AUTH_USERNAME = "username"; -const char *MTS::IO::ICellularRadio::KEY_PDP_CONTEXT_AUTH_PASSWORD = "password"; -const char *MTS::IO::ICellularRadio::VALUE_PDP_CONTEXT_IP_MODE_IP = "IP"; -const char *MTS::IO::ICellularRadio::VALUE_PDP_CONTEXT_IP_MODE_IPV6 = "IPV6"; -const char *MTS::IO::ICellularRadio::VALUE_PDP_CONTEXT_IP_MODE_IPV4V6 = "IPV4V6"; -const char *MTS::IO::ICellularRadio::VALUE_PDP_CONTEXT_AUTH_TYPE_NONE = "NONE"; -const char *MTS::IO::ICellularRadio::VALUE_PDP_CONTEXT_AUTH_TYPE_PAP = "PAP"; -const char *MTS::IO::ICellularRadio::VALUE_PDP_CONTEXT_AUTH_TYPE_CHAP = "CHAP"; -const char *MTS::IO::ICellularRadio::VALUE_PDP_CONTEXT_AUTH_TYPE_PAP_CHAP = "PAP-CHAP"; const char *MTS::IO::ICellularRadio::VALUE_TYPE_GSM = "GSM"; const char *MTS::IO::ICellularRadio::VALUE_TYPE_LTE = "LTE"; diff --git a/src/MTS_IO_QuectelRadio.cpp b/src/MTS_IO_QuectelRadio.cpp index b01bbb1..655fb38 100644 --- a/src/MTS_IO_QuectelRadio.cpp +++ b/src/MTS_IO_QuectelRadio.cpp @@ -1629,114 +1629,6 @@ ICellularRadio::CODE QuectelRadio::setRxDiversity(const Json::Value& jArgs) { return SUCCESS; } -ICellularRadio::CODE QuectelRadio::convertStringToPdpContextType(const std::string& sStringType, std::string& sIntType) { - CODE rc = FAILURE; - - if ("IP" == sStringType) { - sIntType = "1"; - rc = SUCCESS; - } else if ("IPV6" == sStringType) { - sIntType = "2"; - rc = SUCCESS; - } else if ("IPV4V6" == sStringType) { - sIntType = "3"; - rc = SUCCESS; - } - - return rc; -} - -std::vector QuectelRadio::getSupportedPdpContextAuthTypes() const { - return { - VALUE_PDP_CONTEXT_AUTH_TYPE_NONE, - VALUE_PDP_CONTEXT_AUTH_TYPE_PAP, - VALUE_PDP_CONTEXT_AUTH_TYPE_CHAP, - VALUE_PDP_CONTEXT_AUTH_TYPE_PAP_CHAP - }; -} - -ICellularRadio::CODE QuectelRadio::isPdpContextAuthSupported(bool& isSupported) { - std::string sCmd("AT+QICSGP=?"); - return isCommandSupported(sCmd, isSupported); -} - -ICellularRadio::CODE QuectelRadio::fillPdpContextAuthFields(Json::Value& jData) { - CODE rc; - std::string sCmd("AT+QICSGP="); - std::string sResult; - uint8_t iValue; - - // iterate over PDP contex IDs to get context settings - for (std::string & sContextId : jData.getMemberNames()) { - // +QICSGP: ,,,, - // +QICSGP: 0,"","","",0 -- if the context does not exist - - rc = sendBasicQuery(sCmd+sContextId, "+QICSGP:", sResult, 300); - - if (SUCCESS != rc) { - return rc; - } - - // 1,"test","login","password",1 - // [0] [1] [2] [3] [4] - auto vAuthParams = MTS::Text::split(sResult, ","); - - if (vAuthParams.size() < 5) { - printError("%s| Failed to parse PDP context authentication string [%s]", getName().c_str(), sResult.c_str()); - return FAILURE; - } - - if (! MTS::Text::parse(iValue, vAuthParams[4])) { - printError("%s| Failed to parse PDP context authentication type [%s]", getName().c_str(), vAuthParams[4].c_str()); - return FAILURE; - } - - rc = convertPdpContextAuthTypeToString(static_cast(iValue), sResult); - if (SUCCESS != rc) { - return rc; - } - - jData[sContextId][KEY_PDP_CONTEXT_AUTH_TYPE] = sResult; - - if (iValue != PDP_CONTEXT_AUTH_TYPE::NONE) { - jData[sContextId][KEY_PDP_CONTEXT_AUTH_USERNAME] = MTS::Text::trim(vAuthParams[2], '"'); - jData[sContextId][KEY_PDP_CONTEXT_AUTH_PASSWORD] = MTS::Text::trim(vAuthParams[3], '"'); - } - } - - return SUCCESS; -} - -// AT+QICSGP=[,,[,,)[,[,]]]] -ICellularRadio::CODE QuectelRadio::setPdpContextAuth(const PdpContextInfo& pdpContext) { - printTrace("%s| Setting PDP context authentication to the radio", getName().c_str()); - - CODE rc; - std::string sContextType; - std::string sCmd = "AT+QICSGP="; - PDP_CONTEXT_AUTH_TYPE eAuthType; - - rc = convertStringToPdpContextType(pdpContext.sIpMode, sContextType); - if (SUCCESS != rc) { - return rc; - } - - rc = convertStringToPdpContextAuthType(pdpContext.sAuthType, eAuthType); - if (SUCCESS != rc) { - return rc; - } - - sCmd += pdpContext.sId + "," + sContextType + ",\"" + pdpContext.sApn + "\""; - - if (PDP_CONTEXT_AUTH_TYPE::NONE == eAuthType) { - sCmd += ",\"\",\"\"," + std::to_string(eAuthType); - } else { - sCmd += ",\"" + pdpContext.sUsername + "\",\"" + pdpContext.sPassword +"\"," + std::to_string(eAuthType); - } - - return sendBasicCommand(sCmd); -} - const std::vector& QuectelRadio::getDiagCommands(bool) { // Declare as static to initialize only when used, but cache the results. const static std::vector vCommands { @@ -1783,3 +1675,28 @@ const std::vector& QuectelRadio::getDiagCommands(bool) { return vCommands; } + +ICellularRadio::CODE QuectelRadio::getTimeUTC(void) { + printTrace("%s| Get Time in UTC", getName().c_str()); + + // Set year format in YYYY first, in case it is in YY format to get accurate year + std::string sCmdCSDF("AT+CSDF=1,2"); + std::string sRes = sendCommand(sCmdCSDF); + size_t endr = sRes.find(ICellularRadio::RSP_OK); + + if (endr == std::string::npos) { + printWarning("%s| Unable to set year format for radio using command [%s]", getName().c_str(), sCmdCSDF.c_str()); + return FAILURE; + } + + // Set command enables/disables the automatic time zone update + std::string sCmdCTZU("AT+CTZU=1"); + sRes = sendCommand(sCmdCTZU); + size_t endc = sRes.find(ICellularRadio::RSP_OK); + + if (endc == std::string::npos) { + printWarning("%s| Unable to set automatic time zone update for radio using command [%s]", getName().c_str(), sCmdCTZU.c_str()); + return FAILURE; + } + return SUCCESS; +} \ No newline at end of file diff --git a/src/MTS_IO_SequansRadio.cpp b/src/MTS_IO_SequansRadio.cpp index 380dd80..33bd068 100644 --- a/src/MTS_IO_SequansRadio.cpp +++ b/src/MTS_IO_SequansRadio.cpp @@ -282,6 +282,7 @@ ICellularRadio::CODE SequansRadio::getNetworkStatusTxPower(Json::Value& jData, J std::string sResult; std::string sPrefix; std::vector vParts; + int iValue; CODE rc; sCmd = "AT+SQNQRUP?"; @@ -311,7 +312,7 @@ ICellularRadio::CODE SequansRadio::getNetworkStatusTxPower(Json::Value& jData, J break; // invalid, not known or not detectable } if (fTxPow < -255 || fTxPow > 99) { - printDebug("%s| Network Status command returned unexpected value of txPower: [%s][%f]", getName().c_str(), sCmd.c_str(), fTxPow); + printDebug("%s| Network Status command returned unexpected value of txPower: [%s][%d]", getName().c_str(), sCmd.c_str(), iValue); break; } jDebug[ICellularRadio::KEY_TXPWR] = vParts[0]; @@ -533,27 +534,6 @@ ICellularRadio::CODE SequansRadio::getSimLockAttemptsByType(const std::string& s return SUCCESS; } -std::vector SequansRadio::getSupportedPdpContextAuthTypes() const { - return { - VALUE_PDP_CONTEXT_AUTH_TYPE_NONE, - VALUE_PDP_CONTEXT_AUTH_TYPE_PAP, - VALUE_PDP_CONTEXT_AUTH_TYPE_CHAP - }; -} - -ICellularRadio::CODE SequansRadio::isPdpContextAuthSupported(bool& isSupported) { - isSupported = false; - return SUCCESS; -} - -ICellularRadio::CODE SequansRadio::fillPdpContextAuthFields(Json::Value& jData) { - return NOT_APPLICABLE; -} - -ICellularRadio::CODE SequansRadio::setPdpContextAuth(const PdpContextInfo& pdpContext) { - return NOT_APPLICABLE; -} - const std::vector& SequansRadio::getDiagCommands(bool) { // Declare as static to initialize only when used, but cache the results. const static std::vector vCommands { @@ -588,3 +568,28 @@ const std::vector& SequansRadio::getDiagCommands(bool) { return vCommands; } + +ICellularRadio::CODE SequansRadio::getTimeUTC(void) { + printTrace("%s| Get Time in UTC", getName().c_str()); + + // Set year format in YYYY first, in case it is in YY format to get accurate year + std::string sCmdCSDF("AT+CSDF=1,2"); + std::string sRes = sendCommand(sCmdCSDF); + size_t endr = sRes.find(ICellularRadio::RSP_OK); + + if (endr == std::string::npos) { + printWarning("%s| Unable to set year format for radio using command [%s]", getName().c_str(), sCmdCSDF.c_str()); + return FAILURE; + } + + // Set year format in YYYY first, in case it is in YY format to get accurate year + std::string sCmdCTZU("AT+CTZU=1"); + sRes = sendCommand(sCmdCTZU); + size_t endc = sRes.find(ICellularRadio::RSP_OK); + + if (endc == std::string::npos) { + printWarning("%s| Unable to set automatic time zone update for radio using command [%s]", getName().c_str(), sCmdCTZU.c_str()); + return FAILURE; + } + return SUCCESS; +} \ No newline at end of file diff --git a/src/MTS_IO_TelitRadio.cpp b/src/MTS_IO_TelitRadio.cpp index 00c1686..2c50208 100644 --- a/src/MTS_IO_TelitRadio.cpp +++ b/src/MTS_IO_TelitRadio.cpp @@ -1178,109 +1178,6 @@ bool MTS::IO::TelitRadio::isContainsSignChar(const std::string& str) { return true; } -std::vector TelitRadio::getSupportedPdpContextAuthTypes() const { - return { - VALUE_PDP_CONTEXT_AUTH_TYPE_NONE, - VALUE_PDP_CONTEXT_AUTH_TYPE_PAP, - VALUE_PDP_CONTEXT_AUTH_TYPE_CHAP - }; -} - -ICellularRadio::CODE TelitRadio::isPdpContextAuthSupported(bool& isSupported) { - std::string sCmd("AT#PDPAUTH=?"); - return isCommandSupported(sCmd, isSupported); -} - -ICellularRadio::CODE TelitRadio::fillPdpContextAuthFields(Json::Value& jData) { - CODE rc; - std::string sCmd("AT#PDPAUTH?"); - std::string sResult; - - // #PDPAUTH: 1,0 - // #PDPAUTH: 2,0 - // #PDPAUTH: 3,0 - // #PDPAUTH: 4,1,"admin" - rc = sendBasicQuery(sCmd, "", sResult, 300); - - if (SUCCESS != rc) { - return rc; - } - - std::vector vContexts = MTS::Text::split(sResult, "#PDPAUTH:"); - std::string sContextId; - - for (std::string& sLine : vContexts) { - sLine = MTS::Text::trim(sLine); - - if (sLine.empty()) { - continue; - } - - // 4,1,"admin" - // [0][1] [2] - auto vAuthParams = MTS::Text::split(sLine, ","); - - // Contains 2 elements when the authentication type is NONE, contains 3 elements in other cases - if (vAuthParams.size() < 2) { - printError("%s| Failed to parse PDP context authentication string [%s]", getName().c_str(), sLine.c_str()); - return FAILURE; - } - - sContextId = vAuthParams[0]; - - uint8_t iValue; - if (! MTS::Text::parse(iValue, vAuthParams[1])) { - printError("%s| Failed to parse PDP context authentication type [%s]", getName().c_str(), vAuthParams[1].c_str()); - return FAILURE; - } - - rc = convertPdpContextAuthTypeToString(static_cast(iValue), sResult); - if (SUCCESS != rc) { - printError("%s| Failed to convert PDP context authentication type to string [%d]", getName().c_str(), iValue); - return rc; - } - - jData[sContextId][KEY_PDP_CONTEXT_AUTH_TYPE] = sResult; - - if (iValue == PDP_CONTEXT_AUTH_TYPE::NONE) { - continue; - } - - if (vAuthParams.size() < 3) { - printError("%s| Failed to parse PDP context authentication string [%s]", getName().c_str(), sLine.c_str()); - return FAILURE; - } - - jData[sContextId][KEY_PDP_CONTEXT_AUTH_USERNAME] = MTS::Text::trim(vAuthParams[2], '"'); - } - - return SUCCESS; -} - -ICellularRadio::CODE TelitRadio::setPdpContextAuth(const PdpContextInfo& pdpContext) { - printTrace("%s| Setting PDP context authentication to the radio", getName().c_str()); - - CODE rc; - std::string sCmd = "AT#PDPAUTH="; - PDP_CONTEXT_AUTH_TYPE eAuthType; - - sCmd += pdpContext.sId + ","; - - rc = convertStringToPdpContextAuthType(pdpContext.sAuthType, eAuthType); - - if (SUCCESS != rc) { - return rc; - } - - sCmd += std::to_string(eAuthType); - - if (PDP_CONTEXT_AUTH_TYPE::NONE != eAuthType) { - sCmd += "," + pdpContext.sUsername + "," + pdpContext.sPassword; - } - - return sendBasicCommand(sCmd); -} - const std::vector& TelitRadio::getDiagCommands(bool) { // Declare as static to initialize only when used, but cache the results. const static std::vector vCommands { @@ -1315,3 +1212,39 @@ const std::vector& TelitRadio::getDiagCommands(bool) { return vCommands; } + +ICellularRadio::CODE TelitRadio::getTimeUTC(void) { + printTrace("%s| Get Time in UTC", getName().c_str()); + + // Set year format in YYYY first, in case it is in YY format to get accurate year + std::string sCmdCSDF("AT+CSDF=1,2"); + std::string sRes = sendCommand(sCmdCSDF); + size_t endr = sRes.find(ICellularRadio::RSP_OK); + + if (endr == std::string::npos) { + printWarning("%s| Unable to set year format for radio using command [%s]", getName().c_str(), sCmdCSDF.c_str()); + return FAILURE; + } + + // Set command enables/disables the automatic time zone update via NITZ. + std::string sCmdCTZU("AT+CTZU=1"); + sRes = sendCommand(sCmdCTZU); + size_t endc = sRes.find(ICellularRadio::RSP_OK); + + if (endc == std::string::npos) { + printWarning("%s| Unable to set year format for radio using command [%s]", getName().c_str(), sCmdCTZU.c_str()); + return FAILURE; + } + + //Enables/disables the automatic date/time updating and the + //Full Network Name applying. It enables also the #NITZ URC in the format. + std::string sCmdNITZ("AT#NITZ"); + sRes = sendCommand(sCmdNITZ); + size_t endn = sRes.find(ICellularRadio::RSP_OK); + + if (endn == std::string::npos) { + printWarning("%s| Unable to set automatic time zone update for radio using command [%s]", getName().c_str(), sCmdNITZ.c_str()); + return FAILURE; + } + return SUCCESS; +} \ No newline at end of file -- cgit v1.2.3