From da563a985ccb0b5f316b44e35aabd511687ff4bf Mon Sep 17 00:00:00 2001 From: Maksym Telychko Date: Thu, 6 Jun 2019 16:03:44 +0300 Subject: [MTS-MTQ] refactoring: added quectel empty classes, CellularRadio moved to TelitRadio --- src/MTS_IO_QuectelRadio.cpp | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/MTS_IO_QuectelRadio.cpp (limited to 'src/MTS_IO_QuectelRadio.cpp') diff --git a/src/MTS_IO_QuectelRadio.cpp b/src/MTS_IO_QuectelRadio.cpp new file mode 100644 index 0000000..365bbca --- /dev/null +++ b/src/MTS_IO_QuectelRadio.cpp @@ -0,0 +1 @@ +#include "mts/MTS_IO_QuectelRadio.h" -- cgit v1.2.3 From 20471af5d887ab2255716c734661abb95953676c Mon Sep 17 00:00:00 2001 From: Serhii Kostiuk Date: Tue, 11 Jun 2019 18:19:36 +0300 Subject: [MTS-MTQ] QuectelRadio implementation Added the full implementation of QuectelRadio class. Ported the changes from a local branch to the new libmts-io architecture. --- src/MTS_IO_QuectelRadio.cpp | 442 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 442 insertions(+) (limited to 'src/MTS_IO_QuectelRadio.cpp') diff --git a/src/MTS_IO_QuectelRadio.cpp b/src/MTS_IO_QuectelRadio.cpp index 365bbca..597bdac 100644 --- a/src/MTS_IO_QuectelRadio.cpp +++ b/src/MTS_IO_QuectelRadio.cpp @@ -1 +1,443 @@ +/* + * Copyright (C) 2019 by Multi-Tech Systems + * + * This file is part of libmts-io. + * + * libmts-io is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * libmts-io is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libmts-io. If not, see . + * + */ + #include "mts/MTS_IO_QuectelRadio.h" + +#include +#include +#include + +using namespace MTS::IO; + +QuectelRadio::QuectelRadio(const std::string& sName, const std::string& sRadioPort) +: CellularRadio (sName, sRadioPort) +{ +} + +bool QuectelRadio::resetRadio(uint32_t iTimeoutMillis) { + printInfo("%s| Rebooting radio", getName().c_str()); + if(sendBasicCommand("AT+CFUN=1,1") == SUCCESS) { + if(iTimeoutMillis > 5000) { + MTS::Thread::sleep(5000); + iTimeoutMillis -= 5000; + } + return resetConnection(iTimeoutMillis); + } + + return false; +} + +CellularRadio::CODE QuectelRadio::getModel(std::string& sModel) { + printTrace("%s| Get Model", getName().c_str()); + //Always returns SUCCESS because the model should be m_sName + sModel = getName(); + std::string sCmd("AT+GMM"); + std::string sResult = sendCommand(sCmd); + if (sResult.find("OK") == std::string::npos) { + printWarning("%s| Unable to get model from radio. Returning [%s]", getName().c_str(), getName().c_str()); + return SUCCESS; + } else { + sModel = extractModelFromResult(sResult); + if(sModel.size() == 0) { + printWarning("%s| Unable to get model from radio. Returning [%s]", getName().c_str(), getName().c_str()); + return SUCCESS; + } + } + + printDebug("%s| Extracted [%s] from [%s] query", getName().c_str(), sModel.c_str(), sCmd.c_str()); + if(sModel != getName()) { + printWarning("%s| Model identified [%s] does not match expected [%s]. Returning [%s]", + getName().c_str(), sModel.c_str(), getName().c_str(), sModel.c_str()); + } + + return SUCCESS; +} + +CellularRadio::CODE QuectelRadio::getIccid(std::string& sIccid) { + printTrace("%s| Get ICCID", getName().c_str()); + sIccid = VALUE_NOT_SUPPORTED; + std::string sCmd("AT+QCCID"); + std::string sResult = CellularRadio::sendCommand(sCmd); + size_t end = sResult.find(RSP_OK); + if (end == std::string::npos) { + printWarning("%s| Unable to get ICCID from radio using command [%s]", getName().c_str(), sCmd.c_str()); + return FAILURE; + } + + size_t start = sResult.find("+QCCID:"); + if(start != std::string::npos) { + start += sizeof("+QCCID:"); + sIccid = MTS::Text::trim(sResult.substr(start, end-start)); + if(sIccid.size() == 0) { + printWarning("%s| Unable to get ICCID from radio using command [%s]", getName().c_str(), sCmd.c_str()); + return FAILURE; + } + } + return SUCCESS; +} + +CellularRadio::CODE QuectelRadio::getService(std::string& sService) { + printTrace("%s| Get Service", getName().c_str()); + sService = VALUE_NOT_SUPPORTED; + std::string sCmd("AT+COPS?"); + std::string sResult = CellularRadio::sendCommand(sCmd); + size_t end = sResult.find(RSP_OK); + if (end == std::string::npos) { + printWarning("%s| Unable to get Service from radio using command [%s]", getName().c_str(), sCmd.c_str()); + return FAILURE; + } + + // +COPS: [,[,][,]] + int32_t iAccessTechnology = -1; + sscanf(sResult.c_str(), "%*d,%*d,%*s,%d", &iAccessTechnology); + + switch(iAccessTechnology) { + case 0 : sService = "GPRS" ; break; // GSM + case 2 : sService = "WCDMA" ; break; // UTRAN + case 3 : sService = "EGPRS" ; break; // GSM W/EGPRS + case 4 : sService = "HSDPA" ; break; // UTRAN W/HSDPA + case 5 : sService = "WCDMA" ; break; // UTRAN W/HSUPA + case 6 : sService = "HSDPA" ; break; // UTRAN W/HSDPA and HSUPA + case 7 : sService = "LTE" ; break; // E-UTRAN + case 100 : sService = "CDMA" ; break; // CDMA + + default: sService = VALUE_UNKNOWN; break; + } + + printDebug("%s| Service ID: [%d][%s]", getName().c_str(), iAccessTechnology, sService.c_str()); + + return SUCCESS; +} + +CellularRadio::CODE QuectelRadio::getNetwork(std::string& sNetwork) { + /* + * TODO: Refactor using MccMncTable once it'll be corrected. + * + * The proper way to determine the current network is to do that + * by MCC and MNC fetched from the `getNetworkStatus` and `AT+QENG` command. + * By using MCC and MNC from `AT+QENG` we can fetch the name of the network + * reported by a currently connected base station even if the SIM card is + * not installed or if we are currently working is a roaming mode. + * + * Until MccMncTable implementation is not fixed, we are using the name + * of a currently selected operator (AT+COPS). + */ + printTrace("%s| Get Network", getName().c_str()); + sNetwork = VALUE_NOT_SUPPORTED; + std::string sCmd("AT+COPS?"); + std::string sResult = CellularRadio::sendCommand(sCmd); + size_t end = sResult.find(RSP_OK); + + if (end == std::string::npos) { + printWarning("%s| Unable to get network name from radio using command [%s]", getName().c_str(), sCmd.c_str()); + return FAILURE; + } + + // +COPS: [, , ,] + // +COPS: vParts[0],vParts[1],vParts[2],vParts[3] + size_t start = sResult.find(":") + 1; //Position right after "+COPS:" + std::vector vParts = MTS::Text::split(MTS::Text::trim(sResult.substr(start)), ","); + + if(vParts.size() > 3) { + sNetwork = vParts[2]; + } else { + sNetwork = ""; // Not connected to any network + } + + return SUCCESS; +} + +/* AT+QENG="servingcell" - Query the information of serving cells + + (GSM network) + +QENG:"servingscell",,"GSM",,,,,,,,,,,,,,,,,,,,,,,, + + (WCDMA network) + +QENG:"servingcell",,"WCDMA",,,,,,,,,,,,,, + + (LTE Network) + +QENG:"servingcell",,"LTE",,,,,,,,,,,,,,, + + The following modes are NOT currently handled: + - TD-SCDMA mode; + - CDMA mode; + - HDR mode; + - SRLTE mode. + + In the case of TD-SCDMA mode: + +QENG:"servingscell",,"TDSCDMA",,,,,,,, + + In the case of CDMA mode or CDMA+HDR mode: + +QENG:"servingscell",,"CDMA",,,,,,,, + [+QENG:"servingscell",,"HDR",,,,,,,,] + + In the case of SRLTE mode: + +QENG:"servingscell",,"CDMA",,,,,,,, + +QENG:"servingcell",,"LTE",,,,,,,,,,,,,, +*/ +CellularRadio::CODE QuectelRadio::getNetworkStatus(Json::Value& jData) { + int32_t iValue; + ACTIVEBAND abnd; + SERVICEDOMAIN sd; + std::string sValue; + const uint32_t GSM_NETWORK_FORMAT = 27; + const uint32_t WCDMA_NETWORK_FORMAT = 17; + const uint32_t LTE_NETWORK_FORMAT = 18; + + printTrace("%s| Get Network Status", getName().c_str()); + + //Always get common network stats because this should never fail + //This way the basic stats are always returned even if AT+QENG fails below + getCommonNetworkStats(jData); + + // IMSI is not provided by AT+QENG. Fetch it separately to keep the same interface + if (getImsi(sValue) == SUCCESS) { + jData[KEY_IMSI] = sValue; + } + + // Network Name is not explicitly provided by AT+QENG. Fetch it separately to keep the same interface + // TODO: Replace with lookup by MCC and MNC once MccMncTable is fixed. + if (getNetwork(sValue) == SUCCESS) { + jData[KEY_NETWORK] = sValue; + } + + // Service Domain is not provided by AT+QENG. Fetch it separately to keep the same interface + if (getServiceDomain(sd) == SUCCESS && convertServiceDomainToString(sd, sValue) == SUCCESS) { + jData[KEY_SD] = sValue; + } + + std::string sCmd; + std::string sResult; + + sCmd = "AT+QENG=\"servingcell\""; + sResult = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, 200); + if (sResult.find("+QENG:\"servingscell\"") == std::string::npos) { + printDebug("%s| Network Status command returned unexpected response: [%s][%s]", getName().c_str(), sCmd.c_str(), sResult.c_str()); + printTrace("%s| Network Status:\n%s\n", getName().c_str(), jData.toStyledString().c_str()); + return SUCCESS; //return SUCCESS because getCommonNetworkStats() succeeded at top of this function + } + + size_t start = sResult.find(":") + 1; //Position right after "+QENG:" + std::vector vParts = MTS::Text::split(MTS::Text::trim(sResult.substr(start)), ","); + Json::Value jDebug; + + if (vParts.size() < 3) { + printDebug("%s| Network Status command reponse is an unknown format: [%s][%s]", getName().c_str(), sCmd.c_str(), sResult.c_str()); + printTrace("%s| Network Status:\n%s\n", getName().c_str(), jData.toStyledString().c_str()); + return SUCCESS; //return SUCCESS because getCommonNetworkStats() succeeded at top of this function + } + + // +QENG:"servingscell",,"GSM",,,,,,,,,,,,,,,,,,,,,,,, + // +QENG: [0], [1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13],[14],[15], [16], [17],[18],[19], [20], [21], [22], [23], [24], [25], [26] + if (vParts.size() == GSM_NETWORK_FORMAT ) { + //Parse as GSM Network Format + jData[KEY_MCC] = vParts[3]; + jData[KEY_MNC] = vParts[4]; + jData[KEY_LAC] = vParts[5]; + jData[KEY_CID] = vParts[6]; + jData[KEY_CHANNEL] = vParts[8]; + + if (convertToActiveBand(vParts[9], abnd) == SUCCESS && convertActiveBandToString(abnd, sValue) == SUCCESS) { + jData[KEY_ABND] = sValue; + } + + if (MTS::Text::parse(iValue, vParts[10])) { + // Number format. RX level value for base station selection in dB (see 3GPP 25.304). + // Range: 0-63. Subtracting 111 from the RX level value, a dBm value will be got. + int rssi = iValue - 111; + jData[KEY_RSSIDBM] = MTS::Text::format(rssi); + } + + jData[KEY_TXPWR] = vParts[11]; + + // The following fields can NOT be fetched for Quectel in GSM mode: RAC, MM, RR, NOM + + jData[KEY_DEBUG] = jDebug; + } + + // +QENG:"servingcell",,"WCDMA",,,,,,,,,,,,,, + // +QENG: [0], [1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12],[13], [14], [15], [16] + else if((vParts.size() == WCDMA_NETWORK_FORMAT)) { + //Parse as WCDMA Network Format + jData[KEY_MCC] = vParts[3]; + jData[KEY_MNC] = vParts[4]; + jData[KEY_LAC] = vParts[5]; + jData[KEY_CID] = vParts[6]; + jData[KEY_CHANNEL] = vParts[7]; + jDebug[KEY_PSC] = vParts[8]; + jData[KEY_RAC] = vParts[9]; + jDebug[KEY_RSCP] = vParts[10]; + jDebug[KEY_ECIO] = vParts[11]; + + // The following fields can NOT be fetched for Quectel in WCDMA mode: TXPWR, DRX, MM, RR, NOM, BLER + + // RSSI is not provided by AT+QENG in WCDMA mode. It was filled above by the getCommonNetworkStats + + // BLER is not provided by AT+QENG. Set to constant + jDebug[KEY_BLER] = "000"; + + // Get the radio band given the channel (UARFCN) + RadioBandMap radioBandMap(vParts[7], CellularRadio::VALUE_TYPE_CDMA); + jData[KEY_ABND] = radioBandMap.getRadioBandName(); + + jData[KEY_DEBUG] = jDebug; + } + + // +QENG:"servingcell",,"LTE",,,,,,,,,,,,,,, + // +QENG: [0], [1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13], [14], [15], [16], [17] + else if(vParts.size() == LTE_NETWORK_FORMAT) { + //Parse as LTE Network Format + jData[KEY_MCC] = vParts[4]; + jData[KEY_MNC] = vParts[5]; + jData[KEY_CID] = vParts[6]; + jData[KEY_CHANNEL] = vParts[8]; + jData["tac"] = vParts[12]; + jDebug["rsrp"] = vParts[13]; + jDebug["rsrq"] = vParts[14]; + jData[KEY_RSSIDBM] = vParts[15]; + + // Get the radio band given the channel (EARFCN) + RadioBandMap radioBandMap(vParts[8], CellularRadio::VALUE_TYPE_LTE); + jData[KEY_ABND] = radioBandMap.getRadioBandName(); + + // LAC is not provided by AT+QENG in WCDMA mode. Use another command instead + jData[KEY_LAC] = queryLteLac(); + + jData[KEY_DEBUG] = jDebug; + } + + printTrace("%s| Network Status:\n%s\n", getName().c_str(), jData.toStyledString().c_str()); + return SUCCESS; +} + +CellularRadio::CODE QuectelRadio::convertSignalStrengthTodBm(const int32_t& iRssi, int32_t& iDbm) { + int dbmSteps, minValue, maxValue, rssiOffset; + int rawDbm; + + if(iRssi >= 0 && iRssi < 99) { + // normal scaling + dbmSteps = 2; + minValue = -113; + maxValue = -51; + rssiOffset = 0; + } else if(iRssi >= 100 && iRssi < 199) { + // TD-SCDMA scaling + dbmSteps = 1; + minValue = -116; + maxValue = -25; + rssiOffset = 100; + } else { + return FAILURE; // invalid, not known or not detectable + } + + rawDbm = minValue + ((iRssi - rssiOffset) * dbmSteps); + iDbm = std::min(maxValue, rawDbm); + + return SUCCESS; +} + +CellularRadio::CODE QuectelRadio::convertdBmToSignalStrength(const int32_t& iDBm, int32_t& iRssi) { + //Quectel Conversion FOR NORMAL SCALING + const int dbmSteps = 2; + const int minValue = -113; + const int rssiOffset = 0; + + if (iDBm < -113) { + iRssi = 0; + } else if (iDBm > -51) { + iRssi = 31; + } else { + iRssi = ((iDBm - minValue) / dbmSteps) + rssiOffset; + } + + return SUCCESS; +} + +CellularRadio::CODE QuectelRadio::setMdn(const Json::Value& jArgs) { + printTrace("%s| Set MDN", getName().c_str()); + return NOT_APPLICABLE; +} + +CellularRadio::CODE QuectelRadio::getServiceDomain(CellularRadio::SERVICEDOMAIN& sd) { + printTrace("%s| Get Service Domain", getName().c_str()); + + std::string sCmd("AT+QCFG=\"servicedomain\""); + std::string sResult = CellularRadio::sendCommand(sCmd); + size_t end = sResult.find(RSP_OK); + + if (end == std::string::npos) { + printWarning("%s| Unable to get service domain using command [%s]", getName().c_str(), sCmd.c_str()); + return FAILURE; + } + + // +QCFG: "servicedomain", + size_t start = sResult.find(",") + 1; // Position right after comma + std::string sServiceDomain = MTS::Text::trim(sResult.substr(start, end)); + int iValue = -1; + + if (!MTS::Text::parse(iValue, sServiceDomain)) { + printWarning("%s| Failed to parse service domain from command output [%s]", getName().c_str(), sCmd.c_str()); + return FAILURE; + } + + switch (iValue) { + case 0: sd = SERVICEDOMAIN::CS_ONLY; break; + case 1: sd = SERVICEDOMAIN::PS_ONLY; break; + case 2: sd = SERVICEDOMAIN::CSPS; break; + + default: return FAILURE; // Unknown + } + + return SUCCESS; +} + +bool QuectelRadio::getCarrierFromFirmware(const std::string& sFirmware, std::string& sCarrier) { + // TODO: Implement properly if needed + // This function is used only in CdmaRadio implementation but was defined in + // the CellularRadio class before refactoring. + + // Find out if and how we can determine the operator by firmware version. + + return false; +} + +bool QuectelRadio::getHardwareVersionFromFirmware(const std::string& sFirmware, std::string& sHardware) { + // TODO: Implement properly + // Find out if and how we can extract the hardware version from firmware version on Quectel devices + + return false; +} + +CellularRadio::CODE QuectelRadio::convertToActiveBand(const std::string& sQuectelBand, CellularRadio::ACTIVEBAND& band) { + int iQuectelBand = -1; + + if (!MTS::Text::parse(iQuectelBand, sQuectelBand)) { + return FAILURE; // probably "-", other band + } + + switch (iQuectelBand) { + case 0: band = ACTIVEBAND::DCS_1800; break; + case 1: band = ACTIVEBAND::PCS_1900; break; + + default: return FAILURE; // actually, this case should never happen + } + + return SUCCESS; +} -- cgit v1.2.3 From 2dad34c7a24430ed8c55079405e2988d5a35cd87 Mon Sep 17 00:00:00 2001 From: Serhii Kostiuk Date: Tue, 11 Jun 2019 18:24:23 +0300 Subject: [MTS-MTQ] QuectelRadio implementation Modified QuectelRadio::getNetworkStatus to populate Quectel-specific debug information. Added as a separate commit for simple reverts --- src/MTS_IO_QuectelRadio.cpp | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'src/MTS_IO_QuectelRadio.cpp') diff --git a/src/MTS_IO_QuectelRadio.cpp b/src/MTS_IO_QuectelRadio.cpp index 597bdac..3f108e6 100644 --- a/src/MTS_IO_QuectelRadio.cpp +++ b/src/MTS_IO_QuectelRadio.cpp @@ -237,11 +237,16 @@ CellularRadio::CODE QuectelRadio::getNetworkStatus(Json::Value& jData) { size_t start = sResult.find(":") + 1; //Position right after "+QENG:" std::vector vParts = MTS::Text::split(MTS::Text::trim(sResult.substr(start)), ","); Json::Value jDebug; + Json::Value jQuectelDebug; if (vParts.size() < 3) { printDebug("%s| Network Status command reponse is an unknown format: [%s][%s]", getName().c_str(), sCmd.c_str(), sResult.c_str()); printTrace("%s| Network Status:\n%s\n", getName().c_str(), jData.toStyledString().c_str()); return SUCCESS; //return SUCCESS because getCommonNetworkStats() succeeded at top of this function + } else { + // UE state and Access technology, Quectel-specific information + jQuectelDebug["state"] = vParts[1]; + jQuectelDebug["rat"] = vParts[2]; } // +QENG:"servingscell",,"GSM",,,,,,,,,,,,,,,,,,,,,,,, @@ -252,6 +257,7 @@ CellularRadio::CODE QuectelRadio::getNetworkStatus(Json::Value& jData) { jData[KEY_MNC] = vParts[4]; jData[KEY_LAC] = vParts[5]; jData[KEY_CID] = vParts[6]; + jQuectelDebug["bsic"] = vParts[7]; jData[KEY_CHANNEL] = vParts[8]; if (convertToActiveBand(vParts[9], abnd) == SUCCESS && convertActiveBandToString(abnd, sValue) == SUCCESS) { @@ -266,9 +272,25 @@ CellularRadio::CODE QuectelRadio::getNetworkStatus(Json::Value& jData) { } jData[KEY_TXPWR] = vParts[11]; + jQuectelDebug["rla"] = vParts[12]; + jQuectelDebug["drx"] = vParts[13]; + jQuectelDebug["c1"] = vParts[14]; + jQuectelDebug["c2"] = vParts[15]; + jQuectelDebug["gprs"] = vParts[16]; + jQuectelDebug["tch"] = vParts[17]; + jQuectelDebug["ts"] = vParts[18]; + jQuectelDebug["ta"] = vParts[19]; + jQuectelDebug["maio"] = vParts[20]; + jQuectelDebug["hsn"] = vParts[21]; + jQuectelDebug["rxlevsub"] = vParts[22]; + jQuectelDebug["rxlevfull"] = vParts[23]; + jQuectelDebug["rxqualsub"] = vParts[24]; + jQuectelDebug["rxqualfull"] = vParts[25]; + jQuectelDebug["voicecodec"] = vParts[26]; // The following fields can NOT be fetched for Quectel in GSM mode: RAC, MM, RR, NOM + jData["quectelDebug"] = jQuectelDebug; jData[KEY_DEBUG] = jDebug; } @@ -285,6 +307,11 @@ CellularRadio::CODE QuectelRadio::getNetworkStatus(Json::Value& jData) { jData[KEY_RAC] = vParts[9]; jDebug[KEY_RSCP] = vParts[10]; jDebug[KEY_ECIO] = vParts[11]; + jQuectelDebug["phych"] = vParts[12]; + jQuectelDebug["sf"] = vParts[13]; + jQuectelDebug["slot"] = vParts[14]; + jQuectelDebug["speechCode"] = vParts[15]; + jQuectelDebug["comMod"] = vParts[16]; // The following fields can NOT be fetched for Quectel in WCDMA mode: TXPWR, DRX, MM, RR, NOM, BLER @@ -297,6 +324,7 @@ CellularRadio::CODE QuectelRadio::getNetworkStatus(Json::Value& jData) { RadioBandMap radioBandMap(vParts[7], CellularRadio::VALUE_TYPE_CDMA); jData[KEY_ABND] = radioBandMap.getRadioBandName(); + jData["quectelDebug"] = jQuectelDebug; jData[KEY_DEBUG] = jDebug; } @@ -304,14 +332,21 @@ CellularRadio::CODE QuectelRadio::getNetworkStatus(Json::Value& jData) { // +QENG: [0], [1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13], [14], [15], [16], [17] else if(vParts.size() == LTE_NETWORK_FORMAT) { //Parse as LTE Network Format + jQuectelDebug["isTdd"] = vParts[3]; jData[KEY_MCC] = vParts[4]; jData[KEY_MNC] = vParts[5]; jData[KEY_CID] = vParts[6]; + jQuectelDebug["pcid"] = vParts[7]; jData[KEY_CHANNEL] = vParts[8]; + jQuectelDebug["freqBandInd"] = vParts[9]; + jQuectelDebug["ulBandwidth"] = vParts[10]; + jQuectelDebug["dlBandwidth"] = vParts[11]; jData["tac"] = vParts[12]; jDebug["rsrp"] = vParts[13]; jDebug["rsrq"] = vParts[14]; jData[KEY_RSSIDBM] = vParts[15]; + jQuectelDebug["sinr"] = vParts[16]; + jQuectelDebug["srxlev"] = vParts[17]; // Get the radio band given the channel (EARFCN) RadioBandMap radioBandMap(vParts[8], CellularRadio::VALUE_TYPE_LTE); @@ -320,6 +355,7 @@ CellularRadio::CODE QuectelRadio::getNetworkStatus(Json::Value& jData) { // LAC is not provided by AT+QENG in WCDMA mode. Use another command instead jData[KEY_LAC] = queryLteLac(); + jData["quectelDebug"] = jQuectelDebug; jData[KEY_DEBUG] = jDebug; } -- cgit v1.2.3 From 2f451104dc4a5b3459ecf4ffade49efa55e2c454 Mon Sep 17 00:00:00 2001 From: Serhii Kostiuk Date: Wed, 12 Jun 2019 13:37:45 +0300 Subject: [MTS-MTQ] QuectelRadio implementation Corrected the check for QENG="servingcell" prefix --- src/MTS_IO_QuectelRadio.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/MTS_IO_QuectelRadio.cpp') diff --git a/src/MTS_IO_QuectelRadio.cpp b/src/MTS_IO_QuectelRadio.cpp index 3f108e6..414cd98 100644 --- a/src/MTS_IO_QuectelRadio.cpp +++ b/src/MTS_IO_QuectelRadio.cpp @@ -228,7 +228,7 @@ CellularRadio::CODE QuectelRadio::getNetworkStatus(Json::Value& jData) { sCmd = "AT+QENG=\"servingcell\""; sResult = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, 200); - if (sResult.find("+QENG:\"servingscell\"") == std::string::npos) { + if (sResult.find("+QENG: \"servingcell\"") == std::string::npos) { printDebug("%s| Network Status command returned unexpected response: [%s][%s]", getName().c_str(), sCmd.c_str(), sResult.c_str()); printTrace("%s| Network Status:\n%s\n", getName().c_str(), jData.toStyledString().c_str()); return SUCCESS; //return SUCCESS because getCommonNetworkStats() succeeded at top of this function -- cgit v1.2.3 From 6647e6fbb8f742727229309c9372d6c66291f805 Mon Sep 17 00:00:00 2001 From: Serhii Kostiuk Date: Wed, 12 Jun 2019 13:45:44 +0300 Subject: [MTS-MTQ] QuectelRadio implementation Fixes and improvements - Corrected the format of getNetwork output - Fixed pasrsing for the trailing values in QuectelRadio::getNetworkStatus (removed extra characters) - Removed empty "debug" field from QuectelRadio::getNetworkStatus output in GSM mode - Corrected parsing in the QuectelRadio::getServiceDomain - Corrected parsing in the QuectelRadio::getService - Corrected target fields for Service Domain value in QuectelRadio::getNetworkStatus --- src/MTS_IO_QuectelRadio.cpp | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) (limited to 'src/MTS_IO_QuectelRadio.cpp') diff --git a/src/MTS_IO_QuectelRadio.cpp b/src/MTS_IO_QuectelRadio.cpp index 414cd98..6c6ab4b 100644 --- a/src/MTS_IO_QuectelRadio.cpp +++ b/src/MTS_IO_QuectelRadio.cpp @@ -105,8 +105,9 @@ CellularRadio::CODE QuectelRadio::getService(std::string& sService) { } // +COPS: [,[,][,]] + // %*[^,] in scanf - ignore all symbols until next comma int32_t iAccessTechnology = -1; - sscanf(sResult.c_str(), "%*d,%*d,%*s,%d", &iAccessTechnology); + sscanf(sResult.c_str(), "+COPS: %*d,%*d,%*[^,],%d", &iAccessTechnology); switch(iAccessTechnology) { case 0 : sService = "GPRS" ; break; // GSM @@ -156,7 +157,13 @@ CellularRadio::CODE QuectelRadio::getNetwork(std::string& sNetwork) { std::vector vParts = MTS::Text::split(MTS::Text::trim(sResult.substr(start)), ","); if(vParts.size() > 3) { - sNetwork = vParts[2]; + const std::string sValue = vParts[2]; + + // +COPS: 0,0,"CHN-UNICOM UNICOM",7 + // ^start ^end + size_t start = sValue.find("\"") + 1; + size_t end = sValue.find(" ", start); + sNetwork = sValue.substr(start, end-start); } else { sNetwork = ""; // Not connected to any network } @@ -218,11 +225,6 @@ CellularRadio::CODE QuectelRadio::getNetworkStatus(Json::Value& jData) { jData[KEY_NETWORK] = sValue; } - // Service Domain is not provided by AT+QENG. Fetch it separately to keep the same interface - if (getServiceDomain(sd) == SUCCESS && convertServiceDomainToString(sd, sValue) == SUCCESS) { - jData[KEY_SD] = sValue; - } - std::string sCmd; std::string sResult; @@ -235,7 +237,8 @@ CellularRadio::CODE QuectelRadio::getNetworkStatus(Json::Value& jData) { } size_t start = sResult.find(":") + 1; //Position right after "+QENG:" - std::vector vParts = MTS::Text::split(MTS::Text::trim(sResult.substr(start)), ","); + size_t end = sResult.rfind(RSP_OK); + std::vector vParts = MTS::Text::split(MTS::Text::trim(sResult.substr(start, end-start)), ","); Json::Value jDebug; Json::Value jQuectelDebug; @@ -288,10 +291,14 @@ CellularRadio::CODE QuectelRadio::getNetworkStatus(Json::Value& jData) { jQuectelDebug["rxqualfull"] = vParts[25]; jQuectelDebug["voicecodec"] = vParts[26]; + // Service Domain is not provided by AT+QENG. Fetch it separately to keep the same interface + if (getServiceDomain(sd) == SUCCESS && convertServiceDomainToString(sd, sValue) == SUCCESS) { + jData[KEY_SD] = sValue; + } + // The following fields can NOT be fetched for Quectel in GSM mode: RAC, MM, RR, NOM jData["quectelDebug"] = jQuectelDebug; - jData[KEY_DEBUG] = jDebug; } // +QENG:"servingcell",,"WCDMA",,,,,,,,,,,,,, @@ -317,6 +324,11 @@ CellularRadio::CODE QuectelRadio::getNetworkStatus(Json::Value& jData) { // RSSI is not provided by AT+QENG in WCDMA mode. It was filled above by the getCommonNetworkStats + // Service Domain is not provided by AT+QENG. Fetch it separately to keep the same interface + if (getServiceDomain(sd) == SUCCESS && convertServiceDomainToString(sd, sValue) == SUCCESS) { + jDebug[KEY_SD] = sValue; + } + // BLER is not provided by AT+QENG. Set to constant jDebug[KEY_BLER] = "000"; @@ -352,6 +364,11 @@ CellularRadio::CODE QuectelRadio::getNetworkStatus(Json::Value& jData) { RadioBandMap radioBandMap(vParts[8], CellularRadio::VALUE_TYPE_LTE); jData[KEY_ABND] = radioBandMap.getRadioBandName(); + // Service Domain is not provided by AT+QENG. Fetch it separately to keep the same interface + if (getServiceDomain(sd) == SUCCESS && convertServiceDomainToString(sd, sValue) == SUCCESS) { + jDebug[KEY_SD] = sValue; + } + // LAC is not provided by AT+QENG in WCDMA mode. Use another command instead jData[KEY_LAC] = queryLteLac(); @@ -425,7 +442,7 @@ CellularRadio::CODE QuectelRadio::getServiceDomain(CellularRadio::SERVICEDOMAIN& // +QCFG: "servicedomain", size_t start = sResult.find(",") + 1; // Position right after comma - std::string sServiceDomain = MTS::Text::trim(sResult.substr(start, end)); + std::string sServiceDomain = MTS::Text::trim(sResult.substr(start, end-start)); int iValue = -1; if (!MTS::Text::parse(iValue, sServiceDomain)) { -- cgit v1.2.3 From d388f51c9611d0f5009abf105aba44c85fcee4b0 Mon Sep 17 00:00:00 2001 From: Serhii Kostiuk Date: Wed, 12 Jun 2019 16:30:46 +0300 Subject: [MTS-MTQ] QuectelRadio implementation Changed implementation of the QuectelRadio::getService - Replaced sscanf with functions from MTS::Text - Emulated the behaviour of TelitRadio::getService - return FAILURE when is not available The TelitRadio::getService returns FAILURE when device stays without a SIM card (probably, until it will be registered to the network) --- src/MTS_IO_QuectelRadio.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'src/MTS_IO_QuectelRadio.cpp') diff --git a/src/MTS_IO_QuectelRadio.cpp b/src/MTS_IO_QuectelRadio.cpp index 6c6ab4b..20a2a21 100644 --- a/src/MTS_IO_QuectelRadio.cpp +++ b/src/MTS_IO_QuectelRadio.cpp @@ -104,10 +104,16 @@ CellularRadio::CODE QuectelRadio::getService(std::string& sService) { return FAILURE; } + size_t start = sResult.find(":") + 1; //Position right after "+COPS:" + std::vector vParts = MTS::Text::split(MTS::Text::trim(sResult.substr(start, end-start)), ','); + + int32_t iAccessTechnology; + // +COPS: [,[,][,]] - // %*[^,] in scanf - ignore all symbols until next comma - int32_t iAccessTechnology = -1; - sscanf(sResult.c_str(), "+COPS: %*d,%*d,%*[^,],%d", &iAccessTechnology); + if (vParts.size() < 4 || !MTS::Text::parse(iAccessTechnology, vParts[3])) { + printWarning("%s| Unable to get Service from radio using command [%s]", getName().c_str(), sCmd.c_str()); + return FAILURE; + } switch(iAccessTechnology) { case 0 : sService = "GPRS" ; break; // GSM -- cgit v1.2.3 From acb40ca0033a48cedfeb118dcc216f60e4dd8c45 Mon Sep 17 00:00:00 2001 From: Serhii Kostiuk Date: Wed, 12 Jun 2019 17:23:03 +0300 Subject: [MTS-MTQ] QuectelRadio implementation Fixed parsing of RSSI dBm in QuectelRadio::getNetworkStatus for GSM mode. As stated in the datasheet[1], we should substract "111" from the value in field in order to get a proper value in dBm. The thing is that the values returned by a real device are already out of the "0-63" range stated in a datasheet. And looks like those values are already in a dBm scale. [2] This commit removes additional substraction and saves the value of field directly without any modifications. Sources: - [1] QuectelEC2x26EG9x26EM05QuecCellATCommandsManualV10.929966385.pdf, page 9, field description. - [2] +QENG: "servingcell","NOCONN","GSM",REDACTED,REDACTED,REFACTED,REDACTED,8,522,0,-66,255,255,0,41,41,1,-,-,-,-,-,-,-,-,-,"" --- src/MTS_IO_QuectelRadio.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'src/MTS_IO_QuectelRadio.cpp') diff --git a/src/MTS_IO_QuectelRadio.cpp b/src/MTS_IO_QuectelRadio.cpp index 20a2a21..af7fc7c 100644 --- a/src/MTS_IO_QuectelRadio.cpp +++ b/src/MTS_IO_QuectelRadio.cpp @@ -273,13 +273,7 @@ CellularRadio::CODE QuectelRadio::getNetworkStatus(Json::Value& jData) { jData[KEY_ABND] = sValue; } - if (MTS::Text::parse(iValue, vParts[10])) { - // Number format. RX level value for base station selection in dB (see 3GPP 25.304). - // Range: 0-63. Subtracting 111 from the RX level value, a dBm value will be got. - int rssi = iValue - 111; - jData[KEY_RSSIDBM] = MTS::Text::format(rssi); - } - + jData[KEY_RSSIDBM] = vParts[10]; // Values already negative. No need to substract 111 as stated in a datasheet jData[KEY_TXPWR] = vParts[11]; jQuectelDebug["rla"] = vParts[12]; jQuectelDebug["drx"] = vParts[13]; -- cgit v1.2.3 From 4220543c5e64d36eb94b8137f46079d1a2cb1d28 Mon Sep 17 00:00:00 2001 From: Serhii Kostiuk Date: Thu, 13 Jun 2019 10:47:10 +0300 Subject: [MTS-MTQ] refactoring: using full qualified names for consts [2] Made the same changes for QuectelRadio as for the whole project --- src/MTS_IO_QuectelRadio.cpp | 98 ++++++++++++++++++++++----------------------- 1 file changed, 49 insertions(+), 49 deletions(-) (limited to 'src/MTS_IO_QuectelRadio.cpp') diff --git a/src/MTS_IO_QuectelRadio.cpp b/src/MTS_IO_QuectelRadio.cpp index af7fc7c..5c7ceb7 100644 --- a/src/MTS_IO_QuectelRadio.cpp +++ b/src/MTS_IO_QuectelRadio.cpp @@ -72,10 +72,10 @@ CellularRadio::CODE QuectelRadio::getModel(std::string& sModel) { CellularRadio::CODE QuectelRadio::getIccid(std::string& sIccid) { printTrace("%s| Get ICCID", getName().c_str()); - sIccid = VALUE_NOT_SUPPORTED; + sIccid = ICellularRadio::VALUE_NOT_SUPPORTED; std::string sCmd("AT+QCCID"); - std::string sResult = CellularRadio::sendCommand(sCmd); - size_t end = sResult.find(RSP_OK); + std::string sResult = sendCommand(sCmd); + size_t end = sResult.find(ICellularRadio::RSP_OK); if (end == std::string::npos) { printWarning("%s| Unable to get ICCID from radio using command [%s]", getName().c_str(), sCmd.c_str()); return FAILURE; @@ -95,10 +95,10 @@ CellularRadio::CODE QuectelRadio::getIccid(std::string& sIccid) { CellularRadio::CODE QuectelRadio::getService(std::string& sService) { printTrace("%s| Get Service", getName().c_str()); - sService = VALUE_NOT_SUPPORTED; + sService = ICellularRadio::VALUE_NOT_SUPPORTED; std::string sCmd("AT+COPS?"); - std::string sResult = CellularRadio::sendCommand(sCmd); - size_t end = sResult.find(RSP_OK); + std::string sResult = sendCommand(sCmd); + size_t end = sResult.find(ICellularRadio::RSP_OK); if (end == std::string::npos) { printWarning("%s| Unable to get Service from radio using command [%s]", getName().c_str(), sCmd.c_str()); return FAILURE; @@ -125,7 +125,7 @@ CellularRadio::CODE QuectelRadio::getService(std::string& sService) { case 7 : sService = "LTE" ; break; // E-UTRAN case 100 : sService = "CDMA" ; break; // CDMA - default: sService = VALUE_UNKNOWN; break; + default: sService = ICellularRadio::VALUE_UNKNOWN; break; } printDebug("%s| Service ID: [%d][%s]", getName().c_str(), iAccessTechnology, sService.c_str()); @@ -147,10 +147,10 @@ CellularRadio::CODE QuectelRadio::getNetwork(std::string& sNetwork) { * of a currently selected operator (AT+COPS). */ printTrace("%s| Get Network", getName().c_str()); - sNetwork = VALUE_NOT_SUPPORTED; + sNetwork = ICellularRadio::VALUE_NOT_SUPPORTED; std::string sCmd("AT+COPS?"); - std::string sResult = CellularRadio::sendCommand(sCmd); - size_t end = sResult.find(RSP_OK); + std::string sResult = sendCommand(sCmd); + size_t end = sResult.find(ICellularRadio::RSP_OK); if (end == std::string::npos) { printWarning("%s| Unable to get network name from radio using command [%s]", getName().c_str(), sCmd.c_str()); @@ -222,13 +222,13 @@ CellularRadio::CODE QuectelRadio::getNetworkStatus(Json::Value& jData) { // IMSI is not provided by AT+QENG. Fetch it separately to keep the same interface if (getImsi(sValue) == SUCCESS) { - jData[KEY_IMSI] = sValue; + jData[ICellularRadio::KEY_IMSI] = sValue; } // Network Name is not explicitly provided by AT+QENG. Fetch it separately to keep the same interface // TODO: Replace with lookup by MCC and MNC once MccMncTable is fixed. if (getNetwork(sValue) == SUCCESS) { - jData[KEY_NETWORK] = sValue; + jData[ICellularRadio::KEY_NETWORK] = sValue; } std::string sCmd; @@ -243,7 +243,7 @@ CellularRadio::CODE QuectelRadio::getNetworkStatus(Json::Value& jData) { } size_t start = sResult.find(":") + 1; //Position right after "+QENG:" - size_t end = sResult.rfind(RSP_OK); + size_t end = sResult.rfind(ICellularRadio::RSP_OK); std::vector vParts = MTS::Text::split(MTS::Text::trim(sResult.substr(start, end-start)), ","); Json::Value jDebug; Json::Value jQuectelDebug; @@ -262,19 +262,19 @@ CellularRadio::CODE QuectelRadio::getNetworkStatus(Json::Value& jData) { // +QENG: [0], [1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13],[14],[15], [16], [17],[18],[19], [20], [21], [22], [23], [24], [25], [26] if (vParts.size() == GSM_NETWORK_FORMAT ) { //Parse as GSM Network Format - jData[KEY_MCC] = vParts[3]; - jData[KEY_MNC] = vParts[4]; - jData[KEY_LAC] = vParts[5]; - jData[KEY_CID] = vParts[6]; + jData[ICellularRadio::KEY_MCC] = vParts[3]; + jData[ICellularRadio::KEY_MNC] = vParts[4]; + jData[ICellularRadio::KEY_LAC] = vParts[5]; + jData[ICellularRadio::KEY_CID] = vParts[6]; jQuectelDebug["bsic"] = vParts[7]; - jData[KEY_CHANNEL] = vParts[8]; + jData[ICellularRadio::KEY_CHANNEL] = vParts[8]; if (convertToActiveBand(vParts[9], abnd) == SUCCESS && convertActiveBandToString(abnd, sValue) == SUCCESS) { - jData[KEY_ABND] = sValue; + jData[ICellularRadio::KEY_ABND] = sValue; } - jData[KEY_RSSIDBM] = vParts[10]; // Values already negative. No need to substract 111 as stated in a datasheet - jData[KEY_TXPWR] = vParts[11]; + jData[ICellularRadio::KEY_RSSIDBM] = vParts[10]; // Values already negative. No need to substract 111 as stated in a datasheet + jData[ICellularRadio::KEY_TXPWR] = vParts[11]; jQuectelDebug["rla"] = vParts[12]; jQuectelDebug["drx"] = vParts[13]; jQuectelDebug["c1"] = vParts[14]; @@ -293,7 +293,7 @@ CellularRadio::CODE QuectelRadio::getNetworkStatus(Json::Value& jData) { // Service Domain is not provided by AT+QENG. Fetch it separately to keep the same interface if (getServiceDomain(sd) == SUCCESS && convertServiceDomainToString(sd, sValue) == SUCCESS) { - jData[KEY_SD] = sValue; + jData[ICellularRadio::KEY_SD] = sValue; } // The following fields can NOT be fetched for Quectel in GSM mode: RAC, MM, RR, NOM @@ -305,15 +305,15 @@ CellularRadio::CODE QuectelRadio::getNetworkStatus(Json::Value& jData) { // +QENG: [0], [1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12],[13], [14], [15], [16] else if((vParts.size() == WCDMA_NETWORK_FORMAT)) { //Parse as WCDMA Network Format - jData[KEY_MCC] = vParts[3]; - jData[KEY_MNC] = vParts[4]; - jData[KEY_LAC] = vParts[5]; - jData[KEY_CID] = vParts[6]; - jData[KEY_CHANNEL] = vParts[7]; - jDebug[KEY_PSC] = vParts[8]; - jData[KEY_RAC] = vParts[9]; - jDebug[KEY_RSCP] = vParts[10]; - jDebug[KEY_ECIO] = vParts[11]; + jData[ICellularRadio::KEY_MCC] = vParts[3]; + jData[ICellularRadio::KEY_MNC] = vParts[4]; + jData[ICellularRadio::KEY_LAC] = vParts[5]; + jData[ICellularRadio::KEY_CID] = vParts[6]; + jData[ICellularRadio::KEY_CHANNEL] = vParts[7]; + jDebug[ICellularRadio::KEY_PSC] = vParts[8]; + jData[ICellularRadio::KEY_RAC] = vParts[9]; + jDebug[ICellularRadio::KEY_RSCP] = vParts[10]; + jDebug[ICellularRadio::KEY_ECIO] = vParts[11]; jQuectelDebug["phych"] = vParts[12]; jQuectelDebug["sf"] = vParts[13]; jQuectelDebug["slot"] = vParts[14]; @@ -326,18 +326,18 @@ CellularRadio::CODE QuectelRadio::getNetworkStatus(Json::Value& jData) { // Service Domain is not provided by AT+QENG. Fetch it separately to keep the same interface if (getServiceDomain(sd) == SUCCESS && convertServiceDomainToString(sd, sValue) == SUCCESS) { - jDebug[KEY_SD] = sValue; + jDebug[ICellularRadio::KEY_SD] = sValue; } // BLER is not provided by AT+QENG. Set to constant - jDebug[KEY_BLER] = "000"; + jDebug[ICellularRadio::KEY_BLER] = "000"; // Get the radio band given the channel (UARFCN) - RadioBandMap radioBandMap(vParts[7], CellularRadio::VALUE_TYPE_CDMA); - jData[KEY_ABND] = radioBandMap.getRadioBandName(); + RadioBandMap radioBandMap(vParts[7], ICellularRadio::VALUE_TYPE_CDMA); + jData[ICellularRadio::KEY_ABND] = radioBandMap.getRadioBandName(); jData["quectelDebug"] = jQuectelDebug; - jData[KEY_DEBUG] = jDebug; + jData[ICellularRadio::KEY_DEBUG] = jDebug; } // +QENG:"servingcell",,"LTE",,,,,,,,,,,,,,, @@ -345,35 +345,35 @@ CellularRadio::CODE QuectelRadio::getNetworkStatus(Json::Value& jData) { else if(vParts.size() == LTE_NETWORK_FORMAT) { //Parse as LTE Network Format jQuectelDebug["isTdd"] = vParts[3]; - jData[KEY_MCC] = vParts[4]; - jData[KEY_MNC] = vParts[5]; - jData[KEY_CID] = vParts[6]; + jData[ICellularRadio::KEY_MCC] = vParts[4]; + jData[ICellularRadio::KEY_MNC] = vParts[5]; + jData[ICellularRadio::KEY_CID] = vParts[6]; jQuectelDebug["pcid"] = vParts[7]; - jData[KEY_CHANNEL] = vParts[8]; + jData[ICellularRadio::KEY_CHANNEL] = vParts[8]; jQuectelDebug["freqBandInd"] = vParts[9]; jQuectelDebug["ulBandwidth"] = vParts[10]; jQuectelDebug["dlBandwidth"] = vParts[11]; jData["tac"] = vParts[12]; jDebug["rsrp"] = vParts[13]; jDebug["rsrq"] = vParts[14]; - jData[KEY_RSSIDBM] = vParts[15]; + jData[ICellularRadio::KEY_RSSIDBM] = vParts[15]; jQuectelDebug["sinr"] = vParts[16]; jQuectelDebug["srxlev"] = vParts[17]; // Get the radio band given the channel (EARFCN) - RadioBandMap radioBandMap(vParts[8], CellularRadio::VALUE_TYPE_LTE); - jData[KEY_ABND] = radioBandMap.getRadioBandName(); + RadioBandMap radioBandMap(vParts[8], ICellularRadio::VALUE_TYPE_LTE); + jData[ICellularRadio::KEY_ABND] = radioBandMap.getRadioBandName(); // Service Domain is not provided by AT+QENG. Fetch it separately to keep the same interface if (getServiceDomain(sd) == SUCCESS && convertServiceDomainToString(sd, sValue) == SUCCESS) { - jDebug[KEY_SD] = sValue; + jDebug[ICellularRadio::KEY_SD] = sValue; } // LAC is not provided by AT+QENG in WCDMA mode. Use another command instead - jData[KEY_LAC] = queryLteLac(); + jData[ICellularRadio::KEY_LAC] = queryLteLac(); jData["quectelDebug"] = jQuectelDebug; - jData[KEY_DEBUG] = jDebug; + jData[ICellularRadio::KEY_DEBUG] = jDebug; } printTrace("%s| Network Status:\n%s\n", getName().c_str(), jData.toStyledString().c_str()); @@ -428,11 +428,11 @@ CellularRadio::CODE QuectelRadio::setMdn(const Json::Value& jArgs) { return NOT_APPLICABLE; } -CellularRadio::CODE QuectelRadio::getServiceDomain(CellularRadio::SERVICEDOMAIN& sd) { +CellularRadio::CODE QuectelRadio::getServiceDomain(ICellularRadio::SERVICEDOMAIN& sd) { printTrace("%s| Get Service Domain", getName().c_str()); std::string sCmd("AT+QCFG=\"servicedomain\""); - std::string sResult = CellularRadio::sendCommand(sCmd); + std::string sResult = sendCommand(sCmd); size_t end = sResult.find(RSP_OK); if (end == std::string::npos) { @@ -478,7 +478,7 @@ bool QuectelRadio::getHardwareVersionFromFirmware(const std::string& sFirmware, return false; } -CellularRadio::CODE QuectelRadio::convertToActiveBand(const std::string& sQuectelBand, CellularRadio::ACTIVEBAND& band) { +CellularRadio::CODE QuectelRadio::convertToActiveBand(const std::string& sQuectelBand, ICellularRadio::ACTIVEBAND& band) { int iQuectelBand = -1; if (!MTS::Text::parse(iQuectelBand, sQuectelBand)) { -- cgit v1.2.3 From d3ab74f3f8957696077efbac756b52fbbbe49548 Mon Sep 17 00:00:00 2001 From: Serhii Kostiuk Date: Fri, 14 Jun 2019 18:02:17 +0300 Subject: [MTS-MTQ] QuectelRadio implementation Fixed a tiny difference between RSSI placement in TelitRadio and QuectelRadio implementation --- src/MTS_IO_QuectelRadio.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/MTS_IO_QuectelRadio.cpp') diff --git a/src/MTS_IO_QuectelRadio.cpp b/src/MTS_IO_QuectelRadio.cpp index 5c7ceb7..2f3c9b5 100644 --- a/src/MTS_IO_QuectelRadio.cpp +++ b/src/MTS_IO_QuectelRadio.cpp @@ -356,7 +356,7 @@ CellularRadio::CODE QuectelRadio::getNetworkStatus(Json::Value& jData) { jData["tac"] = vParts[12]; jDebug["rsrp"] = vParts[13]; jDebug["rsrq"] = vParts[14]; - jData[ICellularRadio::KEY_RSSIDBM] = vParts[15]; + jDebug[ICellularRadio::KEY_RSSIDBM] = vParts[15]; jQuectelDebug["sinr"] = vParts[16]; jQuectelDebug["srxlev"] = vParts[17]; -- cgit v1.2.3 From 143feb6a4587817d28c77e4df3a1b594b855f5e5 Mon Sep 17 00:00:00 2001 From: Maksym Telychko Date: Fri, 21 Jun 2019 17:19:09 +0300 Subject: [MTS-MTQ] RAT mode switch: implementation for telit and quectel RAT - Radio Access Technology --- src/MTS_IO_QuectelRadio.cpp | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'src/MTS_IO_QuectelRadio.cpp') diff --git a/src/MTS_IO_QuectelRadio.cpp b/src/MTS_IO_QuectelRadio.cpp index 2f3c9b5..50185b3 100644 --- a/src/MTS_IO_QuectelRadio.cpp +++ b/src/MTS_IO_QuectelRadio.cpp @@ -494,3 +494,39 @@ CellularRadio::CODE QuectelRadio::convertToActiveBand(const std::string& sQuecte return SUCCESS; } + +ICellularRadio::CODE QuectelRadio::getRadioMode(RADIOMODE &mode) +{ + std::string sCmd("AT+QCFG=\"nwscanmode\""); + std::string cmdResult = sendCommand(sCmd); + if (cmdResult.find(ICellularRadio::RSP_OK) == std::string::npos) { + printDebug("%s| AT+QCFG? returned unexpected response: [%s][%s]", getName().c_str(), sCmd.c_str(), cmdResult.c_str()); + return FAILURE; + } + switch (stoi(MTS::Text::split(cmdResult, ',')[1])) { + case 1: mode = ICellularRadio::RADIOMODE_GSM_ONLY; break; + case 5: mode = ICellularRadio::RADIOMODE_UMTS_ONLY; break; + case 0: mode = ICellularRadio::RADIOMODE_AUTO; break; + default: mode = ICellularRadio::RADIOMODE_UNKNOWN; break; + } + return SUCCESS; +} + +ICellularRadio::CODE QuectelRadio::setRadioMode(RADIOMODE mode) +{ + std::string value; + switch (mode) { + case ICellularRadio::RADIOMODE_GSM_ONLY: value = "1"; break; + case ICellularRadio::RADIOMODE_UMTS_ONLY: value = "5"; break; + case ICellularRadio::RADIOMODE_AUTO: value = "0"; break; + default: return FAILURE; + } + std::string sCmd("AT+QCFG=\"nwscanmode\","); + sCmd += value; + std::string cmdResult = sendCommand(sCmd); + if (cmdResult.find(ICellularRadio::RSP_OK) == std::string::npos) { + printDebug("%s| AT+QCFG? returned unexpected response: [%s][%s]", getName().c_str(), sCmd.c_str(), cmdResult.c_str()); + return FAILURE; + } + return SUCCESS; +} -- cgit v1.2.3 From 1cb0265df2b2e2171a874a52a782de3ecc6620fa Mon Sep 17 00:00:00 2001 From: Serhii Kostiuk Date: Sat, 22 Jun 2019 12:03:17 +0300 Subject: [MTS-MTQ] SIM status and PIN unlock procedures Added Quectel-specific implementation of the CellularRadio::getIsSimInserted and CellularRadio::getSimLockAttempts utility methods --- src/MTS_IO_QuectelRadio.cpp | 79 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) (limited to 'src/MTS_IO_QuectelRadio.cpp') diff --git a/src/MTS_IO_QuectelRadio.cpp b/src/MTS_IO_QuectelRadio.cpp index 2f3c9b5..0a054ff 100644 --- a/src/MTS_IO_QuectelRadio.cpp +++ b/src/MTS_IO_QuectelRadio.cpp @@ -478,6 +478,85 @@ bool QuectelRadio::getHardwareVersionFromFirmware(const std::string& sFirmware, return false; } +CellularRadio::CODE QuectelRadio::getIsSimInserted(bool& bData) { + printTrace("%s| Get SIM insertion status", getName().c_str()); + std::string sCmd("AT+QSIMSTAT?"); + std::string sResult = sendCommand(sCmd); + + const std::string sPrefix = "+QSIMSTAT: "; + size_t start = sResult.find(sPrefix); + size_t end = sResult.rfind(ICellularRadio::RSP_OK); + + if (end == std::string::npos) { + printWarning("%s| Unable to get SIM insertion status from radio using command [%s]", getName().c_str(), sCmd.c_str()); + return FAILURE; + } + + if (start == std::string::npos) { + printDebug("%s| AT+QSIMSTAT? returned unexpected response: [%s][%s]", getName().c_str(), sCmd.c_str(), sResult.c_str()); + return FAILURE; + } + + // +QSIMSTAT: , + start += sPrefix.size(); + std::vector vParts = MTS::Text::split(MTS::Text::trim(sResult.substr(start, end-start)), ','); + + if(vParts.size() != 2) { + printWarning("%s| Unable to parse SIM insertion status from response [%s]", getName().c_str(), sResult.c_str()); + return FAILURE; + } + + if (vParts[1] == "1") { // Inserted + bData = true; + } else { // Removed or Unknown, before (U)SIM initialization + bData = false; + } + + return SUCCESS; +} + +CellularRadio::CODE QuectelRadio::getSimLockAttempts(int& iAttemptsPin, int& iAttemptsPuk) { + printTrace("%s| Get SIM unlock attempts left", getName().c_str()); + std::string sCmd("AT+QPINC=\"SC\""); + std::string sResult = sendCommand(sCmd); + + const std::string sPrefix = "+QPINC: \"SC\","; + size_t start = sResult.find(sPrefix); + size_t end = sResult.rfind(ICellularRadio::RSP_OK); + + if (end == std::string::npos) { + printWarning("%s| Unable to get SIM unlock attempts from radio using command [%s]", getName().c_str(), sCmd.c_str()); + return FAILURE; + } + + if (start == std::string::npos) { + printDebug("%s| AT+QPINC returned unexpected response: [%s][%s]", getName().c_str(), sCmd.c_str(), sResult.c_str()); + return FAILURE; + } + + // +QPINC: ,, + // [x] ,[0] ,[1] + start += sPrefix.size(); + std::vector vParts = MTS::Text::split(MTS::Text::trim(sResult.substr(start, end-start)), ','); + + if(vParts.size() != 2) { + printWarning("%s| Unable to parse SIM unlock attempts left from response [%s]", getName().c_str(), sResult.c_str()); + return FAILURE; + } + + if (!MTS::Text::parse(iAttemptsPin, vParts[0])) { + printWarning("%s| Unable to parse SIM PIM unlock attempts from response [%s]", getName().c_str(), sResult.c_str()); + return FAILURE; + } + + if (!MTS::Text::parse(iAttemptsPuk, vParts[1])) { + printWarning("%s| Unable to parse SIM PUK unlock attempts from response [%s]", getName().c_str(), sResult.c_str()); + return FAILURE; + } + + return SUCCESS; +} + CellularRadio::CODE QuectelRadio::convertToActiveBand(const std::string& sQuectelBand, ICellularRadio::ACTIVEBAND& band) { int iQuectelBand = -1; -- cgit v1.2.3 From 49429a4f10d9e40d3c2bcba2d9c8fc0d5a9bc830 Mon Sep 17 00:00:00 2001 From: Serhii Kostiuk Date: Wed, 26 Jun 2019 09:03:38 +0300 Subject: [MTS-MTQ] QuectelRadio implementation A small fix for the QuectelRadio::getNetwork - removed extra `"` character when only short / long operator name is returned by +COPS? --- src/MTS_IO_QuectelRadio.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/MTS_IO_QuectelRadio.cpp') diff --git a/src/MTS_IO_QuectelRadio.cpp b/src/MTS_IO_QuectelRadio.cpp index 8ac9bac..472255f 100644 --- a/src/MTS_IO_QuectelRadio.cpp +++ b/src/MTS_IO_QuectelRadio.cpp @@ -167,8 +167,10 @@ CellularRadio::CODE QuectelRadio::getNetwork(std::string& sNetwork) { // +COPS: 0,0,"CHN-UNICOM UNICOM",7 // ^start ^end + // +COPS: 0,0,"AT&T",7 + // ^st ^end size_t start = sValue.find("\"") + 1; - size_t end = sValue.find(" ", start); + size_t end = sValue.find_first_of(" \"", start); sNetwork = sValue.substr(start, end-start); } else { sNetwork = ""; // Not connected to any network -- cgit v1.2.3 From 4ef332ec707946a3cf2a55473d05dfc9af3d4b11 Mon Sep 17 00:00:00 2001 From: Maksym Telychko Date: Wed, 26 Jun 2019 13:05:32 +0300 Subject: [MTS-MTQ] network radio mode switch: refactoring method name --- src/MTS_IO_QuectelRadio.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'src/MTS_IO_QuectelRadio.cpp') diff --git a/src/MTS_IO_QuectelRadio.cpp b/src/MTS_IO_QuectelRadio.cpp index 472255f..6f97989 100644 --- a/src/MTS_IO_QuectelRadio.cpp +++ b/src/MTS_IO_QuectelRadio.cpp @@ -576,7 +576,7 @@ CellularRadio::CODE QuectelRadio::convertToActiveBand(const std::string& sQuecte return SUCCESS; } -ICellularRadio::CODE QuectelRadio::getRadioMode(RADIOMODE &mode) +ICellularRadio::CODE QuectelRadio::getRadioNetworkMode(RADIO_NETWORK_MODE &mode) { std::string sCmd("AT+QCFG=\"nwscanmode\""); std::string cmdResult = sendCommand(sCmd); @@ -585,21 +585,21 @@ ICellularRadio::CODE QuectelRadio::getRadioMode(RADIOMODE &mode) return FAILURE; } switch (stoi(MTS::Text::split(cmdResult, ',')[1])) { - case 1: mode = ICellularRadio::RADIOMODE_GSM_ONLY; break; - case 5: mode = ICellularRadio::RADIOMODE_UMTS_ONLY; break; - case 0: mode = ICellularRadio::RADIOMODE_AUTO; break; - default: mode = ICellularRadio::RADIOMODE_UNKNOWN; break; + case 1: mode = ICellularRadio::RADIO_NETWORK_MODE_GSM_ONLY; break; + case 5: mode = ICellularRadio::RADIO_NETWORK_MODE_UMTS_ONLY; break; + case 0: mode = ICellularRadio::RADIO_NETWORK_MODE_AUTO; break; + default: mode = ICellularRadio::RADIO_NETWORK_MODE_UNKNOWN; break; } return SUCCESS; } -ICellularRadio::CODE QuectelRadio::setRadioMode(RADIOMODE mode) +ICellularRadio::CODE QuectelRadio::setRadioNetworkMode(RADIO_NETWORK_MODE mode) { std::string value; switch (mode) { - case ICellularRadio::RADIOMODE_GSM_ONLY: value = "1"; break; - case ICellularRadio::RADIOMODE_UMTS_ONLY: value = "5"; break; - case ICellularRadio::RADIOMODE_AUTO: value = "0"; break; + case ICellularRadio::RADIO_NETWORK_MODE_GSM_ONLY: value = "1"; break; + case ICellularRadio::RADIO_NETWORK_MODE_UMTS_ONLY: value = "5"; break; + case ICellularRadio::RADIO_NETWORK_MODE_AUTO: value = "0"; break; default: return FAILURE; } std::string sCmd("AT+QCFG=\"nwscanmode\","); -- cgit v1.2.3 From 6042426e8d21b9b92f7078f64f4b50c2f1b8bc8d Mon Sep 17 00:00:00 2001 From: Serhii Kostiuk Date: Mon, 15 Jul 2019 17:10:08 +0300 Subject: [MTX-2886] MTR_MTQ - radio-cmd shows invalid message on valid SIM PIN Fixed the timeouts for several AT commands, including SIM-related commands --- src/MTS_IO_QuectelRadio.cpp | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'src/MTS_IO_QuectelRadio.cpp') diff --git a/src/MTS_IO_QuectelRadio.cpp b/src/MTS_IO_QuectelRadio.cpp index 6f97989..b8c781f 100644 --- a/src/MTS_IO_QuectelRadio.cpp +++ b/src/MTS_IO_QuectelRadio.cpp @@ -73,8 +73,11 @@ CellularRadio::CODE QuectelRadio::getModel(std::string& sModel) { CellularRadio::CODE QuectelRadio::getIccid(std::string& sIccid) { printTrace("%s| Get ICCID", getName().c_str()); sIccid = ICellularRadio::VALUE_NOT_SUPPORTED; + + // AT+QCCID execution can take up to 300ms according to the datasheet. Setting timeout to 500ms just for sure. std::string sCmd("AT+QCCID"); - std::string sResult = sendCommand(sCmd); + std::string sResult = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, 500); + size_t end = sResult.find(ICellularRadio::RSP_OK); if (end == std::string::npos) { printWarning("%s| Unable to get ICCID from radio using command [%s]", getName().c_str(), sCmd.c_str()); @@ -482,8 +485,10 @@ bool QuectelRadio::getHardwareVersionFromFirmware(const std::string& sFirmware, CellularRadio::CODE QuectelRadio::getIsSimInserted(bool& bData) { printTrace("%s| Get SIM insertion status", getName().c_str()); + + // AT+QSIMSTAT? execution can take up to 300ms according to the datasheet. Setting timeout to 500ms just for sure. std::string sCmd("AT+QSIMSTAT?"); - std::string sResult = sendCommand(sCmd); + std::string sResult = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, 500); const std::string sPrefix = "+QSIMSTAT: "; size_t start = sResult.find(sPrefix); @@ -519,8 +524,10 @@ CellularRadio::CODE QuectelRadio::getIsSimInserted(bool& bData) { CellularRadio::CODE QuectelRadio::getSimLockAttempts(int& iAttemptsPin, int& iAttemptsPuk) { printTrace("%s| Get SIM unlock attempts left", getName().c_str()); + + // AT+QPINC execution can take up to 300ms according to the datasheet. Setting timeout to 500ms just for sure. std::string sCmd("AT+QPINC=\"SC\""); - std::string sResult = sendCommand(sCmd); + std::string sResult = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, 500); const std::string sPrefix = "+QPINC: \"SC\","; size_t start = sResult.find(sPrefix); @@ -578,8 +585,10 @@ CellularRadio::CODE QuectelRadio::convertToActiveBand(const std::string& sQuecte ICellularRadio::CODE QuectelRadio::getRadioNetworkMode(RADIO_NETWORK_MODE &mode) { + // AT+QCFG="nwscanmode" execution can take up to 300ms according to the datasheet. Setting timeout to 500ms just for sure. std::string sCmd("AT+QCFG=\"nwscanmode\""); - std::string cmdResult = sendCommand(sCmd); + std::string cmdResult = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, 500); + if (cmdResult.find(ICellularRadio::RSP_OK) == std::string::npos) { printDebug("%s| AT+QCFG? returned unexpected response: [%s][%s]", getName().c_str(), sCmd.c_str(), cmdResult.c_str()); return FAILURE; @@ -604,7 +613,10 @@ ICellularRadio::CODE QuectelRadio::setRadioNetworkMode(RADIO_NETWORK_MODE mode) } std::string sCmd("AT+QCFG=\"nwscanmode\","); sCmd += value; - std::string cmdResult = sendCommand(sCmd); + + // AT+QCFG="nwscanmode" execution can take up to 300ms according to the datasheet. Setting timeout to 500ms just for sure. + std::string cmdResult = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, 500); + if (cmdResult.find(ICellularRadio::RSP_OK) == std::string::npos) { printDebug("%s| AT+QCFG? returned unexpected response: [%s][%s]", getName().c_str(), sCmd.c_str(), cmdResult.c_str()); return FAILURE; -- cgit v1.2.3 From 60f4460b88b7c72f738dba47843961076c21ab9a Mon Sep 17 00:00:00 2001 From: Serhii Kostiuk Date: Mon, 15 Jul 2019 17:46:22 +0300 Subject: [MTS-MTQ] SIM status and PIN unlock procedures Increased timeout for the AT+QPINC="SC" command up to 2 seconds as the modem fails to respond in the current 500ms time limit while executing several successive commands. --- src/MTS_IO_QuectelRadio.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/MTS_IO_QuectelRadio.cpp') diff --git a/src/MTS_IO_QuectelRadio.cpp b/src/MTS_IO_QuectelRadio.cpp index b8c781f..a9f9721 100644 --- a/src/MTS_IO_QuectelRadio.cpp +++ b/src/MTS_IO_QuectelRadio.cpp @@ -525,9 +525,9 @@ CellularRadio::CODE QuectelRadio::getIsSimInserted(bool& bData) { CellularRadio::CODE QuectelRadio::getSimLockAttempts(int& iAttemptsPin, int& iAttemptsPuk) { printTrace("%s| Get SIM unlock attempts left", getName().c_str()); - // AT+QPINC execution can take up to 300ms according to the datasheet. Setting timeout to 500ms just for sure. + // AT+QPINC execution can take more time that expected. Set timeout to 2s just to be sure. std::string sCmd("AT+QPINC=\"SC\""); - std::string sResult = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, 500); + std::string sResult = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, 2000); const std::string sPrefix = "+QPINC: \"SC\","; size_t start = sResult.find(sPrefix); -- cgit v1.2.3 From ebfa95037a98d785029dc9afe8e4aafd8c81b843 Mon Sep 17 00:00:00 2001 From: Serhii Kostiuk Date: Thu, 18 Jul 2019 11:59:02 +0300 Subject: [MTS-MTQ] QuectelRadio implementation Now using "" field instead on number of fields returned in "AT+QENG" result for the QuectelRadio::getNetworkStatus implementation. This change was implemented after a code review. --- src/MTS_IO_QuectelRadio.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'src/MTS_IO_QuectelRadio.cpp') diff --git a/src/MTS_IO_QuectelRadio.cpp b/src/MTS_IO_QuectelRadio.cpp index a9f9721..4d13e7b 100644 --- a/src/MTS_IO_QuectelRadio.cpp +++ b/src/MTS_IO_QuectelRadio.cpp @@ -211,13 +211,15 @@ CellularRadio::CODE QuectelRadio::getNetwork(std::string& sNetwork) { +QENG:"servingcell",,"LTE",,,,,,,,,,,,,, */ CellularRadio::CODE QuectelRadio::getNetworkStatus(Json::Value& jData) { + const std::string RAT_GSM = "GSM"; + const std::string RAT_WCDMA = "WCDMA"; + const std::string RAT_LTE = "LTE"; + int32_t iValue; ACTIVEBAND abnd; SERVICEDOMAIN sd; std::string sValue; - const uint32_t GSM_NETWORK_FORMAT = 27; - const uint32_t WCDMA_NETWORK_FORMAT = 17; - const uint32_t LTE_NETWORK_FORMAT = 18; + std::string sRat; // Radio Access Technology which is currently used printTrace("%s| Get Network Status", getName().c_str()); @@ -260,12 +262,14 @@ CellularRadio::CODE QuectelRadio::getNetworkStatus(Json::Value& jData) { } else { // UE state and Access technology, Quectel-specific information jQuectelDebug["state"] = vParts[1]; - jQuectelDebug["rat"] = vParts[2]; + + sRat = MTS::Text::trim(vParts[2], '"'); + jQuectelDebug["rat"] = sRat; } // +QENG:"servingscell",,"GSM",,,,,,,,,,,,,,,,,,,,,,,, // +QENG: [0], [1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13],[14],[15], [16], [17],[18],[19], [20], [21], [22], [23], [24], [25], [26] - if (vParts.size() == GSM_NETWORK_FORMAT ) { + if (sRat == RAT_GSM) { //Parse as GSM Network Format jData[ICellularRadio::KEY_MCC] = vParts[3]; jData[ICellularRadio::KEY_MNC] = vParts[4]; @@ -308,7 +312,7 @@ CellularRadio::CODE QuectelRadio::getNetworkStatus(Json::Value& jData) { // +QENG:"servingcell",,"WCDMA",,,,,,,,,,,,,, // +QENG: [0], [1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12],[13], [14], [15], [16] - else if((vParts.size() == WCDMA_NETWORK_FORMAT)) { + else if(sRat == RAT_WCDMA) { //Parse as WCDMA Network Format jData[ICellularRadio::KEY_MCC] = vParts[3]; jData[ICellularRadio::KEY_MNC] = vParts[4]; @@ -347,7 +351,7 @@ CellularRadio::CODE QuectelRadio::getNetworkStatus(Json::Value& jData) { // +QENG:"servingcell",,"LTE",,,,,,,,,,,,,,, // +QENG: [0], [1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13], [14], [15], [16], [17] - else if(vParts.size() == LTE_NETWORK_FORMAT) { + else if(sRat == RAT_LTE) { //Parse as LTE Network Format jQuectelDebug["isTdd"] = vParts[3]; jData[ICellularRadio::KEY_MCC] = vParts[4]; -- cgit v1.2.3 From fe970f5bb77354b7507e230b1465e9178c80ee7a Mon Sep 17 00:00:00 2001 From: Serhii Kostiuk Date: Thu, 18 Jul 2019 11:59:02 +0300 Subject: [MTS-MTQ] QuectelRadio implementation Refactored the CellularRadio class to include base stub implementation for the "CellularRadio::getCarrierFromFirmware" and "CellularRadio::getHardwareVersionFromFirmware" methods. From now assuming that those two possibilities are not supported by the modem until otherwise specified (i.e. until the method implementation was overridden in derived class). This change was implemented after a code review. --- src/MTS_IO_QuectelRadio.cpp | 17 ----------------- 1 file changed, 17 deletions(-) (limited to 'src/MTS_IO_QuectelRadio.cpp') diff --git a/src/MTS_IO_QuectelRadio.cpp b/src/MTS_IO_QuectelRadio.cpp index 4d13e7b..0712788 100644 --- a/src/MTS_IO_QuectelRadio.cpp +++ b/src/MTS_IO_QuectelRadio.cpp @@ -470,23 +470,6 @@ CellularRadio::CODE QuectelRadio::getServiceDomain(ICellularRadio::SERVICEDOMAIN return SUCCESS; } -bool QuectelRadio::getCarrierFromFirmware(const std::string& sFirmware, std::string& sCarrier) { - // TODO: Implement properly if needed - // This function is used only in CdmaRadio implementation but was defined in - // the CellularRadio class before refactoring. - - // Find out if and how we can determine the operator by firmware version. - - return false; -} - -bool QuectelRadio::getHardwareVersionFromFirmware(const std::string& sFirmware, std::string& sHardware) { - // TODO: Implement properly - // Find out if and how we can extract the hardware version from firmware version on Quectel devices - - return false; -} - CellularRadio::CODE QuectelRadio::getIsSimInserted(bool& bData) { printTrace("%s| Get SIM insertion status", getName().c_str()); -- cgit v1.2.3 From 0330513b8913d1d7bf14bad99d64ab002b770b7c Mon Sep 17 00:00:00 2001 From: Serhii Kostiuk Date: Thu, 18 Jul 2019 11:41:24 +0300 Subject: [MTR-MTQ] Namespace-related usage improvements Restored full qualification of the ICellularRadio::CODE object type for all files that used full qualification before (effectively, for all source files and only one header file). This commit partially reverses 53efcef2e2f521135b323e194c45f1d9fa7b5d5d. --- src/MTS_IO_QuectelRadio.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'src/MTS_IO_QuectelRadio.cpp') diff --git a/src/MTS_IO_QuectelRadio.cpp b/src/MTS_IO_QuectelRadio.cpp index 0712788..f3227a5 100644 --- a/src/MTS_IO_QuectelRadio.cpp +++ b/src/MTS_IO_QuectelRadio.cpp @@ -44,7 +44,7 @@ bool QuectelRadio::resetRadio(uint32_t iTimeoutMillis) { return false; } -CellularRadio::CODE QuectelRadio::getModel(std::string& sModel) { +ICellularRadio::CODE QuectelRadio::getModel(std::string& sModel) { printTrace("%s| Get Model", getName().c_str()); //Always returns SUCCESS because the model should be m_sName sModel = getName(); @@ -70,7 +70,7 @@ CellularRadio::CODE QuectelRadio::getModel(std::string& sModel) { return SUCCESS; } -CellularRadio::CODE QuectelRadio::getIccid(std::string& sIccid) { +ICellularRadio::CODE QuectelRadio::getIccid(std::string& sIccid) { printTrace("%s| Get ICCID", getName().c_str()); sIccid = ICellularRadio::VALUE_NOT_SUPPORTED; @@ -96,7 +96,7 @@ CellularRadio::CODE QuectelRadio::getIccid(std::string& sIccid) { return SUCCESS; } -CellularRadio::CODE QuectelRadio::getService(std::string& sService) { +ICellularRadio::CODE QuectelRadio::getService(std::string& sService) { printTrace("%s| Get Service", getName().c_str()); sService = ICellularRadio::VALUE_NOT_SUPPORTED; std::string sCmd("AT+COPS?"); @@ -136,7 +136,7 @@ CellularRadio::CODE QuectelRadio::getService(std::string& sService) { return SUCCESS; } -CellularRadio::CODE QuectelRadio::getNetwork(std::string& sNetwork) { +ICellularRadio::CODE QuectelRadio::getNetwork(std::string& sNetwork) { /* * TODO: Refactor using MccMncTable once it'll be corrected. * @@ -389,7 +389,7 @@ CellularRadio::CODE QuectelRadio::getNetworkStatus(Json::Value& jData) { return SUCCESS; } -CellularRadio::CODE QuectelRadio::convertSignalStrengthTodBm(const int32_t& iRssi, int32_t& iDbm) { +ICellularRadio::CODE QuectelRadio::convertSignalStrengthTodBm(const int32_t& iRssi, int32_t& iDbm) { int dbmSteps, minValue, maxValue, rssiOffset; int rawDbm; @@ -415,7 +415,7 @@ CellularRadio::CODE QuectelRadio::convertSignalStrengthTodBm(const int32_t& iRss return SUCCESS; } -CellularRadio::CODE QuectelRadio::convertdBmToSignalStrength(const int32_t& iDBm, int32_t& iRssi) { +ICellularRadio::CODE QuectelRadio::convertdBmToSignalStrength(const int32_t& iDBm, int32_t& iRssi) { //Quectel Conversion FOR NORMAL SCALING const int dbmSteps = 2; const int minValue = -113; @@ -432,17 +432,17 @@ CellularRadio::CODE QuectelRadio::convertdBmToSignalStrength(const int32_t& iDBm return SUCCESS; } -CellularRadio::CODE QuectelRadio::setMdn(const Json::Value& jArgs) { +ICellularRadio::CODE QuectelRadio::setMdn(const Json::Value& jArgs) { printTrace("%s| Set MDN", getName().c_str()); return NOT_APPLICABLE; } -CellularRadio::CODE QuectelRadio::getServiceDomain(ICellularRadio::SERVICEDOMAIN& sd) { +ICellularRadio::CODE QuectelRadio::getServiceDomain(ICellularRadio::SERVICEDOMAIN& sd) { printTrace("%s| Get Service Domain", getName().c_str()); std::string sCmd("AT+QCFG=\"servicedomain\""); std::string sResult = sendCommand(sCmd); - size_t end = sResult.find(RSP_OK); + size_t end = sResult.find(ICellularRadio::RSP_OK); if (end == std::string::npos) { printWarning("%s| Unable to get service domain using command [%s]", getName().c_str(), sCmd.c_str()); @@ -470,7 +470,7 @@ CellularRadio::CODE QuectelRadio::getServiceDomain(ICellularRadio::SERVICEDOMAIN return SUCCESS; } -CellularRadio::CODE QuectelRadio::getIsSimInserted(bool& bData) { +ICellularRadio::CODE QuectelRadio::getIsSimInserted(bool& bData) { printTrace("%s| Get SIM insertion status", getName().c_str()); // AT+QSIMSTAT? execution can take up to 300ms according to the datasheet. Setting timeout to 500ms just for sure. @@ -509,7 +509,7 @@ CellularRadio::CODE QuectelRadio::getIsSimInserted(bool& bData) { return SUCCESS; } -CellularRadio::CODE QuectelRadio::getSimLockAttempts(int& iAttemptsPin, int& iAttemptsPuk) { +ICellularRadio::CODE QuectelRadio::getSimLockAttempts(int& iAttemptsPin, int& iAttemptsPuk) { printTrace("%s| Get SIM unlock attempts left", getName().c_str()); // AT+QPINC execution can take more time that expected. Set timeout to 2s just to be sure. @@ -553,7 +553,7 @@ CellularRadio::CODE QuectelRadio::getSimLockAttempts(int& iAttemptsPin, int& iAt return SUCCESS; } -CellularRadio::CODE QuectelRadio::convertToActiveBand(const std::string& sQuectelBand, ICellularRadio::ACTIVEBAND& band) { +ICellularRadio::CODE QuectelRadio::convertToActiveBand(const std::string& sQuectelBand, ICellularRadio::ACTIVEBAND& band) { int iQuectelBand = -1; if (!MTS::Text::parse(iQuectelBand, sQuectelBand)) { -- cgit v1.2.3