diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/MTS_IO_CdmaRadio.cpp | 2 | ||||
| -rw-r--r-- | src/MTS_IO_CellularRadio.cpp | 1818 | ||||
| -rw-r--r-- | src/MTS_IO_CellularRadioFactory.cpp | 12 | ||||
| -rw-r--r-- | src/MTS_IO_EG95Radio.cpp | 1 | ||||
| -rw-r--r-- | src/MTS_IO_GE910Radio.cpp | 2 | ||||
| -rw-r--r-- | src/MTS_IO_HE910Radio.cpp | 2 | ||||
| -rw-r--r-- | src/MTS_IO_LE866Radio.cpp | 2 | ||||
| -rw-r--r-- | src/MTS_IO_LE910Radio.cpp | 2 | ||||
| -rw-r--r-- | src/MTS_IO_ME910Radio.cpp | 2 | ||||
| -rw-r--r-- | src/MTS_IO_QuectelRadio.cpp | 1 | ||||
| -rw-r--r-- | src/MTS_IO_TelitRadio.cpp | 1838 | 
11 files changed, 1853 insertions, 1829 deletions
| diff --git a/src/MTS_IO_CdmaRadio.cpp b/src/MTS_IO_CdmaRadio.cpp index 8057650..4ff5d63 100644 --- a/src/MTS_IO_CdmaRadio.cpp +++ b/src/MTS_IO_CdmaRadio.cpp @@ -35,7 +35,7 @@  using namespace MTS::IO;  CdmaRadio::CdmaRadio(const std::string& sName, const std::string& sPort) -: CellularRadio(sName, sPort) +: TelitRadio(sName, sPort)  {  } diff --git a/src/MTS_IO_CellularRadio.cpp b/src/MTS_IO_CellularRadio.cpp index f89e673..a29d14f 100644 --- a/src/MTS_IO_CellularRadio.cpp +++ b/src/MTS_IO_CellularRadio.cpp @@ -18,1820 +18,4 @@   *   */ -#include <mts/MTS_IO_CellularRadio.h> -#include <mts/MTS_IO_MccMncTable.h> -#include <mts/MTS_Thread.h> -#include <mts/MTS_Timer.h> -#include <mts/MTS_Logger.h> -#include <mts/MTS_Text.h> -#include <mts/MTS_System.h> -#include <map> -#include <cstring> -#include <sstream> -#include <sys/file.h> -#include <errno.h> -#include <unistd.h> - - -using namespace MTS::IO; - -const char CellularRadio::ETX    = 0x03;  //Ends socket connection -const char CellularRadio::DLE    = 0x10;  //Escapes ETX and DLE within Payload -const char CellularRadio::CR     = 0x0D; -const char CellularRadio::NL     = 0x0A; -const char CellularRadio::CTRL_Z = 0x1A; - -const std::string CellularRadio::RSP_ERROR("ERROR"); -const std::string CellularRadio::RSP_OK("OK"); - - -const std::string CellularRadio::DEFAULT_RADIO_PORT("/dev/modem_at1"); -const std::string CellularRadio::DEFAULT_RADIO_DIR("/var/run/radio/"); -const std::string CellularRadio::VALUE_UNKNOWN("Unknown"); -const std::string CellularRadio::VALUE_UNAVAILABLE("Unavailable"); -const std::string CellularRadio::VALUE_NOT_SUPPORTED("Not Supported"); - -const std::string CellularRadio::VALUE_NOT_REGISTERED("NOT REGISTERED"); -const std::string CellularRadio::VALUE_REGISTERED("REGISTERED"); -const std::string CellularRadio::VALUE_SEARCHING("SEARCHING"); -const std::string CellularRadio::VALUE_DENIED("DENIED"); -const std::string CellularRadio::VALUE_ROAMING("ROAMING"); - -//Static Data -const std::string CellularRadio::KEY_TYPE("type");                    //!< GSM or CDMA -const std::string CellularRadio::KEY_CODE("code");                    //!< Product Code : H5, H6, C2, EV3, G3 -const std::string CellularRadio::KEY_MODEL("model");                  //!< Model : HE910, LE910, CE910, DE910, GE910 -const std::string CellularRadio::KEY_MANUFACTURER("manufacturer");    //!< Manufacturer: Telit -const std::string CellularRadio::KEY_HARDWARE("hardware");            //!< Radio Hardware Version -const std::string CellularRadio::KEY_FIRMWARE("firmware");            //!< Radio Firmware Version -const std::string CellularRadio::KEY_FIRMWARE_BUILD("firmwarebuild"); //!< Radio Firmware Build - -const std::string CellularRadio::KEY_CARRIER("carrier");   //!< Cellular Service Provider (Home Network) -const std::string CellularRadio::VALUE_CARRIER_VERIZON("Verizon"); -const std::string CellularRadio::VALUE_CARRIER_AERIS("Aeris"); -const std::string CellularRadio::VALUE_CARRIER_SPRINT("Sprint"); -const std::string CellularRadio::VALUE_CARRIER_USCELLULAR("U.S. Cellular"); -const std::string CellularRadio::VALUE_CARRIER_ATT("AT&T"); -const std::string CellularRadio::VALUE_CARRIER_TMOBILE("T-Mobile"); - -const std::string CellularRadio::KEY_IMEI("imei");          //!< International Mobile Station Equipment Identity -const std::string CellularRadio::KEY_MEID("meid");          //!< Mobile Equipment Identifier -const std::string CellularRadio::KEY_IMSI("imsi");          //!< International Mobile Subscriber Identity -const std::string CellularRadio::KEY_MSID("msid");          //!< Mobil Station ID / Mobile Identification Number (MSID/MIN) (CDMA-Only) -const std::string CellularRadio::KEY_MDN("mdn");            //!< Mobile Directory Number : Actual phone number dialed to reach radio -const std::string CellularRadio::KEY_ICCID("iccid");        //!< Integrated Circuit Card Identifier -const std::string CellularRadio::KEY_MSL("msl");            //!< Master Subsidy Lock - -//Dynamic Data -const std::string CellularRadio::KEY_ROAMING("roaming");    //!< Indicates whether or not using Home Network -const std::string CellularRadio::KEY_DATETIME("datetime");  //!< Date and Time from tower -const std::string CellularRadio::KEY_SERVICE("service");    //!< Service Connection Type [GPRS, EGPRS, WCDMA, HSDPA, 1xRTT, EVDO] -const std::string CellularRadio::KEY_NETWORK("network");    //!< Cellular Service Provider -const std::string CellularRadio::KEY_NETWORK_REG("netreg"); //!< Network Registration -const std::string CellularRadio::KEY_CID("cid");            //!< Cellular ID (Tower) in HEX -const std::string CellularRadio::KEY_LAC("lac");            //!< Location Area Code in HEX -const std::string CellularRadio::KEY_RAC("rac");            //!< Routing Area Code in HEX -const std::string CellularRadio::KEY_RSSI("rssi");          //!< Signal Strength -const std::string CellularRadio::KEY_RSSIDBM("rssidBm");    //!< Signal Strength in dBm -const std::string CellularRadio::KEY_MCC("mcc");            //!< Country Code -const std::string CellularRadio::KEY_MNC("mnc");            //!< Operator Code -const std::string CellularRadio::KEY_CHANNEL("channel");    //!< ARFCN or UARFCN Assigned Radio Channel -const std::string CellularRadio::KEY_TXPWR("txpwr");        //!< Transmit Power -const std::string CellularRadio::KEY_PSC("psc");            //!< Active Primary Synchronization Code (PSC) -const std::string CellularRadio::KEY_ECIO("ecio");          //!< Active Ec/Io (chip energy per total wideband power in dBm) -const std::string CellularRadio::KEY_RSCP("rscp");          //!< Active RSCP (Received Signal Code Power in dBm) -const std::string CellularRadio::KEY_DRX("drx");            //!< Discontinuous reception cycle length (ms) -const std::string CellularRadio::KEY_MM("mm");              //!< Mobility Management State -const std::string CellularRadio::KEY_RR("rr");              //!< Radio Resource State -const std::string CellularRadio::KEY_NOM("nom");            //!< Network Operator Mode -const std::string CellularRadio::KEY_ABND("abnd");          //!< Active Band -const std::string CellularRadio::KEY_BLER("bler");          //!< Block Error Rate (percentage) -const std::string CellularRadio::KEY_SD("sd");              //!< Service Domain -const std::string CellularRadio::KEY_DEBUG("debug");        //!< Debug Information - -const std::string CellularRadio::KEY_MIP("mipProfile");                      //!< Mobile IP Information -const std::string CellularRadio::KEY_MIP_ID("id");                           //!< Mobile IP ID -const std::string CellularRadio::KEY_MIP_ENABLED("enabled");                 //!< Mobile IP Enabled/Disabled -const std::string CellularRadio::KEY_MIP_NAI("nai");                         //!< Network Access Identifier -const std::string CellularRadio::KEY_MIP_HOMEADDRESS("homeAddress");         //!< Home Address -const std::string CellularRadio::KEY_MIP_PRIMARYHA("primaryAddress");        //!< Primary Home Agent -const std::string CellularRadio::KEY_MIP_SECONDARYHA("secondaryAddress");    //!< Secondary Home Agent -const std::string CellularRadio::KEY_MIP_MNAAASPI("mnAaaSpi");               //!< Mobile Node Authentication, Authorization, and Accounting Server Security Parameter Index -const std::string CellularRadio::KEY_MIP_MNHASPI("mnHaSpi");                 //!< Mobile Node Home Agent Security Server Parameter Index -const std::string CellularRadio::KEY_MIP_REVTUN("revTun");                   //!< Reverse Tunneling Enabled -const std::string CellularRadio::KEY_MIP_MNAAASS("mnAaaSs");                 //!< Mobile Node Authentication, Authorization, and Accounting Server Shared Secret -const std::string CellularRadio::KEY_MIP_MNHASS("mnHaSs");                   //!< Mobile Node Home Agent Shared Secret - -const std::string CellularRadio::VALUE_TYPE_GSM("GSM"); -const std::string CellularRadio::VALUE_TYPE_LTE("LTE"); -const std::string CellularRadio::VALUE_TYPE_CDMA("CDMA"); - -const std::string CellularRadio::VALUE_SD_NO_SERVICE("NO SERVICE"); -const std::string CellularRadio::VALUE_SD_CS_ONLY("CS ONLY"); -const std::string CellularRadio::VALUE_SD_PS_ONLY("PS ONLY"); -const std::string CellularRadio::VALUE_SD_CSPS("CS+PS"); - -const std::string CellularRadio::VALUE_ABND_GSM_850("GSM 850"); -const std::string CellularRadio::VALUE_ABND_GSM_900("GSM 900"); -const std::string CellularRadio::VALUE_ABND_DCS_1800("DCS 1800"); -const std::string CellularRadio::VALUE_ABND_PCS_1900("PCS 1900"); - -const std::vector<std::string> CellularRadio::DEFAULT_BAIL_STRINGS = { CellularRadio::RSP_OK, CellularRadio::RSP_ERROR }; - -CellularRadio::CellularRadio(const std::string& sName, const std::string& sRadioPort) -: m_sName(sName) -, m_sRadioPort(sRadioPort) -, m_bEchoEnabled(false) -, m_bEnableEchoOnClose(false) -{ -    m_apIo.reset(new MTS::IO::SerialConnection( -                             MTS::IO::SerialConnection::Builder(m_sRadioPort) -                                .baudRate(115200) -                                .useLockFile() -                                .build())); -} - - -CellularRadio::~CellularRadio() { -    shutdown(); -    m_apIo.reset(); -} - -bool CellularRadio::initialize(uint32_t iTimeoutMillis) { -    if(!m_apIo->open(iTimeoutMillis)) { -        printError("%s| Failed to open radio port [%s]", m_sName.c_str(), m_sRadioPort.c_str()); -        return false; -    } - -    bool bEnabled; -    CODE eCode = getEcho(bEnabled); -    if(eCode == SUCCESS && bEnabled) { -        printDebug("%s| Disabling 'echo'", m_sName.c_str()); -        setEcho(false); -        m_bEnableEchoOnClose = true; -    } - -    return true; -} - -bool CellularRadio::resetRadio(uint32_t iTimeoutMillis) { - -    printInfo("%s| Rebooting radio", m_sName.c_str()); -    if(sendBasicCommand("AT#REBOOT") == SUCCESS) { -        if(iTimeoutMillis > 5000) { -            MTS::Thread::sleep(5000); -            iTimeoutMillis -= 5000; -        } -        return resetConnection(iTimeoutMillis); -    } - -    return false; -} - -bool CellularRadio::resetConnection(uint32_t iTimeoutMillis) { -    //Close Current Connection -    if(!m_apIo.isNull()) { -        m_apIo->close(); -    } - -    m_apIo.reset(new MTS::IO::SerialConnection( -                     MTS::IO::SerialConnection::Builder(m_sRadioPort) -                        .baudRate(115200) -                        .useLockFile() -                        .build())); - -    //Try to obtain the device port over the given period of time -    MTS::Timer oTimer; -    oTimer.start(); -    uint64_t iCurrentTime = 0; -    while(iCurrentTime < iTimeoutMillis) { - -        if(!m_apIo->open(iTimeoutMillis - iCurrentTime)) { -            printWarning("%s| Failed to re-open radio port [%s]", m_sName.c_str(), m_sRadioPort.c_str()); -        } else { -            printInfo("%s| Successfully re-opened radio port [%s]", m_sName.c_str(), m_sRadioPort.c_str()); -            printDebug("%s| Recovering 'echo' after connection reset", m_sName.c_str()); // see CellularRadio::initialize -            setEcho(m_bEchoEnabled); -            break; -        } - -        ::usleep(500000); //500 millis -        iCurrentTime = oTimer.getMillis(); -    } -    oTimer.stop(); -    return !m_apIo->isClosed(); -} - -void CellularRadio::shutdown() { - -    if(!m_apIo.isNull()) { -        if(m_bEnableEchoOnClose) { -            printDebug("%s| Enabling 'echo'", m_sName.c_str()); -            setEcho(true); -            m_bEnableEchoOnClose = false; -        } -        m_apIo->close(); -    } -} - -const std::string& CellularRadio::getName() const { -    return m_sName; -} - - -CellularRadio::CODE CellularRadio::getModel(std::string& sModel) { -    printTrace("%s| Get Model", m_sName.c_str()); -    //Always returns SUCCESS because the model should be m_sName -    sModel = m_sName; -    std::string sCmd("ATI4"); -    std::string sResult = CellularRadio::sendCommand(m_apIo, sCmd); -    if (sResult.find("OK") == std::string::npos) { -        printWarning("%s| Unable to get model from radio.  Returning [%s]", m_sName.c_str(), m_sName.c_str()); -        return SUCCESS; -    } else { -        sModel = CellularRadio::extractModelFromResult(sResult); -        if(sModel.size() == 0) { -            printWarning("%s| Unable to get model from radio.  Returning [%s]", m_sName.c_str(), m_sName.c_str()); -            return SUCCESS; -        } -    } - -    printDebug("%s| Extracted [%s] from [%s] query", m_sName.c_str(), sModel.c_str(), sCmd.c_str()); -    if(sModel != m_sName) { -        printWarning("%s| Model identified [%s] does not match expected [%s]. Returning [%s]", -                     m_sName.c_str(),  sModel.c_str(), m_sName.c_str(), sModel.c_str()); -    } - -    return SUCCESS; -} - -CellularRadio::CODE CellularRadio::convertModelToMtsShortCode(const std::string& sModel, std::string& sCode, CellularRadio *radioObject) { -    CODE eCode = FAILURE; - -    if(sModel.find("HE910-D") == 0) { -        sCode = "H5"; -        eCode = SUCCESS; -    } else if (sModel.find("HE910-EUD") == 0) { -        sCode = "H6"; -        eCode = SUCCESS; -    } else if (sModel.find("LE910-JN1") == 0) { -        sCode = "LDC3"; -        eCode = SUCCESS; -    } else if (sModel.find("LE866A1-JS") == 0) { -        sCode = "LSB3"; -        eCode = SUCCESS; -    } else if (sModel.find("LE910-NAG") == 0) { -        sCode = "LAT1"; -        eCode = SUCCESS; -    } else if (sModel.find("LE910C4-NF") == 0) { -        sCode = "L4N1"; -        eCode = SUCCESS; -    } else if (sModel.find("LE910-NA1") == 0) { -        if (NULL == radioObject) { -            sCode = VALUE_NOT_SUPPORTED; -            eCode = ERROR; -        } else { -            std::string sValue; -            eCode = radioObject->getActiveFirmware(sValue); -            if (eCode == SUCCESS) { -                sCode = "LNA3"; -            } else { -                sCode = "LAT3"; -            } -        } -        eCode = SUCCESS; -    } else if (sModel.find("LE910-SVG") == 0) { -        sCode = "LVW2"; -        eCode = SUCCESS; -    } else if (sModel.find("LE910C1-NS") == 0) { -    	sCode = "LSP3"; -    	eCode = SUCCESS; -    } else if (sModel.find("LE910C1-AP") == 0) { -    	sCode = "LAP3"; -    	eCode = SUCCESS; -    } else if (sModel.find("ME910C1-NA") == 0) { -        sCode = "MAT1"; -        eCode = SUCCESS; -    } else if (sModel.find("ME910C1-NV") == 0) { -        sCode = "MVW1"; -        eCode = SUCCESS; -    } else if (sModel.find("ME910C1-WW") == 0) { -        sCode = "MNG2"; -        eCode = SUCCESS; -    } else if (sModel.find("LE910-EUG") == 0) { -        sCode = "LEU1"; -        eCode = SUCCESS; -    } else if (sModel.find("LE910C4-EU") == 0) { -        sCode = "L4E1"; -        eCode = SUCCESS; -    } else if (sModel.find("LE910-EU1") == 0) { -        sCode = "LEU3"; -        eCode = SUCCESS; -    } else if (sModel.find("GE910") == 0) { -        sCode = "G3"; -        eCode = SUCCESS; -    } else if (sModel.find("CE910") == 0) { -        sCode = "C2"; -        eCode = SUCCESS; -    } else if (sModel.find("DE910") == 0) { -        sCode = "EV3"; -        eCode = SUCCESS; -    } else { -        sCode = VALUE_NOT_SUPPORTED; -        printError("RADIO| Could not identify MTS short code from model. [%s]", sModel.c_str()); -        eCode = ERROR; -    } -    return eCode; -} - -CellularRadio::CODE CellularRadio::convertServiceDomainToString(SERVICEDOMAIN eSd, std::string& sSd) { -    CODE eCode = FAILURE; -    switch(eSd) { -        case NO_SERVICE: sSd = VALUE_SD_NO_SERVICE; eCode = SUCCESS; break; -        case CS_ONLY: sSd = VALUE_SD_CS_ONLY; eCode = SUCCESS; break; -        case PS_ONLY: sSd = VALUE_SD_PS_ONLY; eCode = SUCCESS; break; -        case CSPS: sSd = VALUE_SD_CSPS; eCode = SUCCESS; break; -        default: sSd = VALUE_UNKNOWN; eCode = FAILURE; break; -    } -    return eCode; -} - -CellularRadio::CODE CellularRadio::convertActiveBandToString(ACTIVEBAND eBand, std::string& sBand) { -    CODE eCode = FAILURE; -    switch(eBand) { -        case GSM_850: sBand = VALUE_ABND_GSM_850; eCode = SUCCESS; break; -        case GSM_900: sBand = VALUE_ABND_GSM_900; eCode = SUCCESS; break; -        case DCS_1800: sBand = VALUE_ABND_DCS_1800; eCode = SUCCESS; break; -        case PCS_1900: sBand = VALUE_ABND_PCS_1900; eCode = SUCCESS; break; -        default: sBand = VALUE_UNKNOWN; eCode = FAILURE; break; -    } -    return eCode; -} - -CellularRadio::CODE CellularRadio::convertModelToType(const std::string& sModel, std::string& sType) { -    CODE eCode = FAILURE; -    sType = VALUE_NOT_SUPPORTED; - -    if(sModel.find("HE910-D") == 0) { -        sType = VALUE_TYPE_GSM; -        eCode = SUCCESS; -    } else if (sModel.find("HE910-EUD") == 0) { -        sType = VALUE_TYPE_GSM; -        eCode = SUCCESS; -    } else if (sModel.find("LE910-JN1") == 0) { -        sType = VALUE_TYPE_LTE; -        eCode = SUCCESS; -    } else if (sModel.find("LE866A1-JS") == 0) { -        sType = VALUE_TYPE_LTE; -        eCode = SUCCESS; -    } else if (sModel.find("LE910-NAG") == 0) { -        sType = VALUE_TYPE_LTE; -        eCode = SUCCESS; -    } else if (sModel.find("LE910C4-NF") == 0) { -        sType = VALUE_TYPE_LTE; -        eCode = SUCCESS; -    } else if (sModel.find("LE910-NA1") == 0) { -        sType = VALUE_TYPE_LTE; -        eCode = SUCCESS; -    } else if (sModel.find("LE910-SVG") == 0) { -        sType = VALUE_TYPE_LTE; -        eCode = SUCCESS; -    } else if (sModel.find("LE910-EUG") == 0) { -        sType = VALUE_TYPE_LTE; -        eCode = SUCCESS; -    } else if (sModel.find("LE910C4-EU") == 0) { -        sType = VALUE_TYPE_LTE; -        eCode = SUCCESS; -    } else if (sModel.find("LE910-EU1") == 0) { -        sType = VALUE_TYPE_LTE; -        eCode = SUCCESS; -    } else if (sModel.find("LE910C1-NS") == 0) { -    	sType = VALUE_TYPE_LTE; -    	eCode = SUCCESS; -    } else if (sModel.find("LE910C1-AP") == 0) { -    	sType = VALUE_TYPE_LTE; -    	eCode = SUCCESS; -    } else if (sModel.find("ME910C1-NA") == 0) { -        sType = VALUE_TYPE_LTE; -        eCode = SUCCESS; -    } else if (sModel.find("ME910C1-NV") == 0) { -        sType = VALUE_TYPE_LTE; -        eCode = SUCCESS; -    } else if (sModel.find("ME910C1-WW") == 0) { -        sType = VALUE_TYPE_LTE; -        eCode = SUCCESS; -    } else if (sModel.find("GE910") == 0) { -        sType = VALUE_TYPE_GSM; -        eCode = SUCCESS; -    } else if (sModel.find("CE910") == 0) { -        sType = VALUE_TYPE_CDMA; -        eCode = SUCCESS; -    } else if (sModel.find("DE910") == 0) { -        sType = VALUE_TYPE_CDMA; -        eCode = SUCCESS; -    } else { -        sType = VALUE_TYPE_GSM; -        eCode = ERROR; -        printError("RADIO| Could not identify type from model. [%s].  Assuming [%s]", sModel.c_str(), sType.c_str()); -    } -    return eCode; -} - -CellularRadio::CODE CellularRadio::getFirmware(std::string& sFirmware) { -    printTrace("%s| Get Firmware", m_sName.c_str()); -    sFirmware = VALUE_NOT_SUPPORTED; -    std::string sCmd("AT+CGMR"); -    std::string sResult = CellularRadio::sendCommand(sCmd); -    size_t pos = sResult.find(RSP_OK); -    if (pos == std::string::npos) { -        printWarning("%s| Unable to get firmware from radio using command [%s]", m_sName.c_str(), sCmd.c_str()); -        return FAILURE; -    } - -    sFirmware = MTS::Text::trim(sResult.substr(0, pos)); -    if(sFirmware.size() == 0) { -        printWarning("%s| Unable to get firmware from radio using command [%s]", m_sName.c_str(), sCmd.c_str()); -        return FAILURE; -    } - -    m_sFirmware = sFirmware; - -    return SUCCESS; -} - -CellularRadio::CODE CellularRadio::getFirmwareBuild(std::string& sFirmwareBuild) { -    sFirmwareBuild = VALUE_NOT_SUPPORTED; -    return FAILURE; -} - -CellularRadio::CODE CellularRadio::getHardware(std::string& sHardware) { -    printTrace("%s| Get Hardware", m_sName.c_str()); -    sHardware = VALUE_NOT_SUPPORTED; - -    if(m_sFirmware.size() == 0) { -        getFirmware(m_sFirmware); -    } - -    if(getHardwareVersionFromFirmware(m_sFirmware, sHardware)) { -        return SUCCESS; -    } -    return FAILURE; -} - -CellularRadio::CODE CellularRadio::getManufacturer(std::string& sManufacturer) { -    printTrace("%s| Get Manufacturer", m_sName.c_str()); -    sManufacturer = VALUE_NOT_SUPPORTED; -    std::string sCmd("AT+GMI"); -    std::string sResult = CellularRadio::sendCommand(sCmd); -    size_t pos = sResult.find(RSP_OK); -    if (pos == std::string::npos) { -        printWarning("%s| Unable to get manufacturer from radio using command [%s]", m_sName.c_str(), sCmd.c_str()); -        return FAILURE; -    } - -    sManufacturer = MTS::Text::trim(sResult.substr(0, pos)); -    if(sManufacturer.size() == 0) { -        printWarning("%s| Unable to get manufacturer from radio using command [%s]", m_sName.c_str(), sCmd.c_str()); -        return FAILURE; -    } - -    return SUCCESS; -} - -CellularRadio::CODE CellularRadio::getImei(std::string& sImei) { -    printTrace("%s| Get IMEI", m_sName.c_str()); -    sImei = VALUE_NOT_SUPPORTED; -    std::string sCmd("AT+CGSN"); -    std::string sResult = CellularRadio::sendCommand(sCmd); -    size_t pos = sResult.find(RSP_OK); -    if (pos == std::string::npos) { -        printWarning("%s| Unable to get IMEI from radio using command [%s]", m_sName.c_str(), sCmd.c_str()); -        return FAILURE; -    } - -    sImei = MTS::Text::trim(sResult.substr(0, pos)); -    if(sImei.size() == 0) { -        printWarning("%s| Unable to get IMEI from radio using command [%s]", m_sName.c_str(), sCmd.c_str()); -        return FAILURE; -    } - -    return SUCCESS; -} - -CellularRadio::CODE CellularRadio::getMeid(std::string& sMeid) { -    printTrace("%s| Get MEID", m_sName.c_str()); -    return getImei(sMeid); -} - -CellularRadio::CODE CellularRadio::getImsi(std::string& sImsi) { -    printTrace("%s| Get IMSI", m_sName.c_str()); -    sImsi = VALUE_NOT_SUPPORTED; -    std::string sCmd("AT+CIMI"); -    std::string sResult = CellularRadio::sendCommand(sCmd); -    size_t pos = sResult.find(RSP_OK); -    if (pos == std::string::npos) { -        printWarning("%s| Unable to get IMSI from radio using command [%s]", m_sName.c_str(), sCmd.c_str()); -        return FAILURE; -    } - -    sImsi = MTS::Text::trim(sResult.substr(0, pos)); -    if(sImsi.size() == 0) { -        printWarning("%s| Unable to get IMSI from radio using command [%s]", m_sName.c_str(), sCmd.c_str()); -        return FAILURE; -    } - -    return SUCCESS; -} - -CellularRadio::CODE CellularRadio::getSimStatus(std::string& sSimStatus) { -    printTrace("%s| Get SIM Status", getName().c_str()); -    sSimStatus = VALUE_UNKNOWN; -    return FAILURE; -} - -CellularRadio::CODE CellularRadio::getIccid(std::string& sIccid) { -    printTrace("%s| Get ICCID", m_sName.c_str()); -    sIccid = VALUE_NOT_SUPPORTED; -    std::string sCmd("AT#CCID"); -    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]", m_sName.c_str(), sCmd.c_str()); -        return FAILURE; -    } - -    size_t start = sResult.find("#CCID:"); -    if(start != std::string::npos) { -        start += sizeof("#CCID:"); -        sIccid = MTS::Text::trim(sResult.substr(start, end-start)); -        if(sIccid.size() == 0) { -            printWarning("%s| Unable to get ICCID from radio using command [%s]", m_sName.c_str(), sCmd.c_str()); -            return FAILURE; -        } -    } -    return SUCCESS; -} - -CellularRadio::CODE CellularRadio::getService(std::string& sService) { -    printTrace("%s| Get Service", m_sName.c_str()); -    sService = VALUE_NOT_SUPPORTED; -    std::string sCmd("AT#PSNT?"); -    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]", m_sName.c_str(), sCmd.c_str()); -        return FAILURE; -    } - -    size_t start = sResult.find(","); -    if(start != std::string::npos) { -        start += 1; //comma -        std::string sPsnt = MTS::Text::trim(sResult.substr(start, end-start)); -        int32_t iService; -        sscanf(sPsnt.c_str(), "%d", &iService); - -        switch(iService) { -            case 0: sService = "GPRS"; break; -            case 1: sService = "EGPRS"; break; -            case 2: sService = "WCDMA"; break; -            case 3: sService = "HSDPA"; break; -            case 4: sService = "LTE"; break; -            default: sService = VALUE_UNKNOWN; break; -        } - -        printDebug("%s| Service ID: [%d][%s]", m_sName.c_str(), iService, sService.c_str()); -    } -    return SUCCESS; -} - -CellularRadio::CODE CellularRadio::getLac(std::string& sLac) { -    Json::Value jData; - -    printTrace("%s| Get LAC", m_sName.c_str()); -    sLac = VALUE_NOT_SUPPORTED; - -    if(getNetworkStatus(jData) == SUCCESS) { -        if(jData.isMember(KEY_LAC)) { -            sLac = jData[KEY_LAC].asString(); -            return SUCCESS; -        } -    } - -    return FAILURE; -} - -CellularRadio::CODE CellularRadio::getMdn(std::string& sMdn) { -    printTrace("%s| Get MDN", m_sName.c_str()); -    sMdn = VALUE_NOT_SUPPORTED; -    std::string sCmd("AT+CNUM"); -    std::string sResult = CellularRadio::sendCommand(sCmd); -    size_t end = sResult.find(RSP_OK); -    if (end == std::string::npos) { -        printWarning("%s| Unable to get MDN from radio using command [%s]", m_sName.c_str(), sCmd.c_str()); -        return FAILURE; -    } - -    size_t start = sResult.find("CNUM:"); -    if(start != std::string::npos) { -        start += sizeof("CNUM:"); -        std::vector<std::string> vParts = MTS::Text::split(sResult.substr(start, end - start), ','); -        if(vParts.size() < 3) { -            printWarning("%s| Unable to parse MDN from response [%s]", m_sName.c_str(), sResult.c_str()); -            return FAILURE; -        } -        sMdn = MTS::Text::strip(vParts[1], '"'); -        if(sMdn.size() == 0) { -            printWarning("%s| Unable to get MDN from radio using command [%s].  MDN may not be set.", m_sName.c_str(), sCmd.c_str()); -        } -    } else { -        sMdn = ""; -        printWarning("%s| Unable to get MDN from radio using command [%s].  MDN may not be set.", m_sName.c_str(), sCmd.c_str()); -    } - -    return SUCCESS; -} - -CellularRadio::CODE CellularRadio::getMsid(std::string& sMsid) { -    printTrace("%s| Get MSID", m_sName.c_str()); -    sMsid = ""; - -    std::string sImsi; -    if(getImsi(sImsi) == SUCCESS) { -        if(sImsi.size() >= 10) { -            sMsid = sImsi.substr(sImsi.size() - 10); -            printTrace("IMSI: [%s] MEID [%s]", sImsi.c_str(), sMsid.c_str()); -            return SUCCESS; -        } -    } -    printWarning("%s| Unable to get MSID from radio", m_sName.c_str()); -    return FAILURE; -} - -CellularRadio::CODE CellularRadio::getType(std::string& sType) { -    printTrace("%s| Get Type", m_sName.c_str()); -    sType = VALUE_NOT_SUPPORTED; -    return FAILURE; -} - -CellularRadio::CODE CellularRadio::getCarrier(std::string& sCarrier) { -    printTrace("%s| Get Carrier", m_sName.c_str()); -    if(m_sCarrier == "") { -        Json::Value jData; -        if(getNetworkStatus(jData) == SUCCESS) { -            if(jData.isMember(KEY_MCC) && jData.isMember(KEY_MNC)) { -                std::string sMcc = jData[KEY_MCC].asString(); -                std::string sMnc = jData[KEY_MNC].asString(); -                Json::Value jLookup = MccMncTable::getInstance()->lookup(sMcc, sMnc); -                printTrace("%s| MCC-MNC Lookup: [%s][%s][%s]", m_sName.c_str(), -                           sMcc.c_str(), sMnc.c_str(), jLookup.toStyledString().c_str()); -                if(jLookup.isMember(KEY_CARRIER)) { -                    m_sCarrier = jLookup[KEY_CARRIER].asString(); -                } else { -                    printWarning("%s| MCC-MNC Lookup did not contain carrier", m_sName.c_str()); -                    return FAILURE; -                } -            } else { -                printWarning("%s| Network Status did no contain MCC or MNC", m_sName.c_str()); -                return FAILURE; -            } -        } else { -            return FAILURE; -        } -    } - -    sCarrier = m_sCarrier; -    return SUCCESS; -} - -CellularRadio::CODE CellularRadio::getTower(std::string& sTower) { -    Json::Value jData; - -    printTrace("%s| Get Tower", m_sName.c_str()); -    sTower = VALUE_NOT_SUPPORTED; - -    if(getNetworkStatus(jData) == SUCCESS) { -        if(jData.isMember(KEY_CID)) { -            sTower = jData[KEY_CID].asString(); -            return SUCCESS; -        } -    } -    return FAILURE; -} - -CellularRadio::CODE CellularRadio::getTime(std::string& sDate, std::string& sTime, std::string& sTimeZone) { -    Json::Value jData; - -    printTrace("%s| Get Time", m_sName.c_str()); -    sDate = ""; -    sTime = ""; -    sTimeZone = ""; - -    std::string sCmd("AT+CCLK?"); -    std::string sResult = CellularRadio::sendCommand(sCmd); -    size_t end = sResult.find(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) { -        start += sizeof("CCLK: "); -        std::string sValue = MTS::Text::trim(sResult.substr(start, end - start)); -        sValue = MTS::Text::strip(sValue, '"'); - -        std::vector<std::string> vParts = MTS::Text::split(sValue, ','); -        if(vParts.size() != 2) { -            printWarning("%s| Unable to parse Date from response [%s]", m_sName.c_str(), sResult.c_str()); -            return FAILURE; -        } - - -        std::vector<std::string> 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()); -            return FAILURE; -        } - -        //The Date format is YY/MM/DD -> Change to MM/DD/YY -        sDate = vDateParts[1] + "/" + vDateParts[2] + "/" + vDateParts[0]; - -        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[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()); -            return FAILURE; -        } - -        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 -            iZonePartial *= -1; -            sPlusSign = ""; -        } -        std::stringstream ss; -        ss << sPlusSign << iZone; -        if(iZonePartial != 0) { -            ss << ":" << iZonePartial; -        } - -        sTimeZone = ss.str(); -        return SUCCESS; - -    } else { -        printWarning("%s| Unable to get Time from radio using command [%s]", m_sName.c_str(), sCmd.c_str()); -    } - -    return FAILURE; -} - -CellularRadio::CODE CellularRadio::getRoaming(bool& bRoaming) { -    Json::Value jData; - -    printTrace("%s| Get Roaming", m_sName.c_str()); -    bRoaming = false; - -    REGISTRATION eReg; -    if(getRegistration(eReg) == SUCCESS) { -        bRoaming = (eReg == ROAMING); -        return SUCCESS; -    } -    return FAILURE; -} - -CellularRadio::CODE CellularRadio::getNetwork(std::string& sNetwork) { -    Json::Value jData; - -    printTrace("%s| Get Network", m_sName.c_str()); -    sNetwork = VALUE_NOT_SUPPORTED; - -    if(getNetworkStatus(jData) == SUCCESS) { -        if(jData.isMember(KEY_NETWORK)) { -            sNetwork = jData[KEY_NETWORK].asString(); -            return SUCCESS; -        } -    } -    return FAILURE; -} - -CellularRadio::CODE CellularRadio::getSignalStrength(int32_t& rssi) { -    printTrace("%s| Get Signal Strength", m_sName.c_str()); -    std::string sCmd("AT+CSQ"); -    std::string sResult = sendCommand(sCmd); -    if (sResult.find("+CSQ: ") == std::string::npos) { -        printDebug("%s| Signal Strength command returned unexpected response: [%s]", m_sName.c_str(), sResult.c_str()); -        return FAILURE; -    } - -    size_t start = sResult.find(':'); -    size_t stop = sResult.find(',', start); -    if(start == std::string::npos || stop == std::string::npos) { -        printDebug("%s| Signal Strength command returned malformed response: [%s]", m_sName.c_str(), sResult.c_str()); -        return FAILURE; -    } -    std::string signal = sResult.substr(start + 2, stop - start - 2); - -    sscanf(signal.c_str(), "%d", &rssi); -    printDebug("%s| Signal Strength: [%d]", m_sName.c_str(), rssi); - -    return SUCCESS; -} - -CellularRadio::CODE CellularRadio::getModemLocation(std::string& sLocation) { -    printTrace("%s|CellularRadio getModemLocation - not supported", m_sName.c_str()); -    return FAILURE; -} - -CellularRadio::CODE CellularRadio::convertSignalStrengthTodBm(const int32_t& iRssi, int32_t& iDbm) { - -    //Telit Conversion -    if(iRssi < 0 || iRssi == 99) { -        return FAILURE; -    } - -    if(iRssi == 0) { -        iDbm = -113; -    } else if(iRssi == 1) { -        iDbm = -111; -    } else if(iRssi <= 30) { -        //28 steps between 2 and 30 -        //54 dbm between 53 and 109 -        float stepSize = 54.0 / 28.0; -        iDbm = -109 + (int)(stepSize * (iRssi-2)); -    } else { -        iDbm = -51; -    } - -    return SUCCESS; -} - -CellularRadio::CODE CellularRadio::convertdBmToSignalStrength(const int32_t& iDBm, int32_t& iRssi) { -    //Telit Conversion -    if(iDBm <= -113) { -        iRssi = 0; -    } else if(iDBm <= -111) { -        iRssi = 1; -    } else if(iDBm <= -53) { -        //54 dbm between -109 and -53 -        //28 steps between 2 and 30 -        float stepSize = 28.0/54.0; -        iRssi = ((iDBm + 109)*stepSize) + 2; -    } else { -        iRssi = 31; -    } - -    return SUCCESS; -} - -CellularRadio::CODE CellularRadio::getEcho(bool& bEnabled) { -    printTrace("%s| Echo Test", m_sName.c_str()); -    std::string sResult = sendCommand("AT"); -    if(sResult.size() == 0) { -        return NO_RESPONSE; -    } - -    if(sResult.find("AT") != std::string::npos) { -        bEnabled = true; -    } else { -        bEnabled = false; -    } -    m_bEchoEnabled = bEnabled; -    return SUCCESS; -} - -CellularRadio::CODE CellularRadio::setEcho(bool bEnabled) { -    CODE eCode = FAILURE; -    if(bEnabled) { -        eCode = sendBasicCommand("ATE1"); -        m_bEchoEnabled = (eCode == SUCCESS ) ? true : m_bEchoEnabled; -    } else { -        eCode = sendBasicCommand("ATE0"); -        m_bEchoEnabled = (eCode == SUCCESS ) ? false : m_bEchoEnabled; -    } - -    return eCode; -} - -CellularRadio::CODE CellularRadio::getStaticInformation(Json::Value& jData) { -    printTrace("%s| Get Static Information", m_sName.c_str()); - -    printTrace("%s| Static Information:\n%s\n", m_sName.c_str(), jData.toStyledString().c_str()); - -    return FAILURE; -} - -/*  AT#RFSTS - NETWORK STATUS - -    (GSM network) -    #RFSTS:<PLMN>,<ARFCN>,<RSSI>,<LAC>,<RAC>,<TXPWR>,<MM>,<RR>,<NOM>,<CID>,<IMSI>,<NetNameAsc>,<SD>,<ABND> -    Where: -    <PLMN> - Country code and operator code(MCC, MNC) -    <ARFCN> - GSM Assigned Radio Channel -    <RSSI> - Received Signal Strength Indication -    <LAC> - Localization Area Code -    <RAC> - Routing Area Code -    <TXPWR> - Tx Power -    <MM> - Mobility Management state -    <RR> - Radio Resource state -    <NOM> - Network Operator Mode -    <CID> - Cell ID -    <IMSI> - International Mobile Subscriber Identity -    <NetNameAsc> - Operator name -    <SD> - Service Domain -    0 - No Service -    1 - CS only -    2 - PS only -    3 - CS+PS -    <ABND> - Active Band -    1 - GSM 850 -    2 - GSM 900 -    3 - DCS 1800 -    4 - PCS 1900 - - -    (WCDMA network) -    #RFSTS: -    <PLMN>,<UARFCN>,<PSC>,<Ec/Io>,<RSCP>, RSSI>,<LAC>,<RAC>,<TXPWR>,<DRX>,<MM>,<RRC>,<NOM>,<BLER>,<CID>,<IMSI>, -    <NetNameAsc>,<SD>,<nAST>[,<nUARFCN><nPSC>,<nEc/Io>] -    Where: -    <PLMN> - Country code and operator code(MCC, MNC) -    <UARFCN> - UMTS Assigned Radio Channel -    <PSC> - Active PSC(Primary Synchronization Code) -    <Ec/Io> - Active Ec/Io(chip energy per total wideband power in dBm) -    <RSCP> - Active RSCP (Received Signal Code Power in dBm) -    <RSSI> - Received Signal Strength Indication -    <LAC> - Localization Area Code -    <RAC> - Routing Area Code -    <TXPWR> - Tx Power -    <DRX> - Discontinuous reception cycle Length (cycle length in ms) -    <MM> - Mobility Management state -    <RR> - Radio Resource state -    <NOM> - Network Operator Mode -    <BLER> - Block Error Rate (e.g., 005 means 0.5 %) -    <CID> - Cell ID -    <IMSI> - International Mobile Station ID -    <NetNameAsc> - Operator name -    <SD> - Service Domain (see above) -    <nAST> - Number of Active Set (Maximum 6) -    <nUARFCN> UARFCN of n th active set -    <nPSC> PSC of n th active set -    <nEc/Io > Ec/Io of n th active Set - -    (LTE Network) -    #RFSTS: -    <PLMN> - -    <EARFCN> - -    <RSRP> - -    <RSSI> - -    <RSRQ> - -    <TAC> - -    [<TXPWR>] - -    <DRX> - -    <MM> - -    <RRC> - -    <CID> - -    <IMSI> - -    [<NetNameAsc>] - -    <SD> - -    <ABND> - -*/ -CellularRadio::CODE CellularRadio::getNetworkStatus(Json::Value& jData) { -    int32_t iValue; -    std::string sValue; -    const uint32_t GSM_NETWORK_FORMAT = 14; -    const uint32_t WCDMA_NETWORK_FORMAT = 19; -    const uint32_t LTE_NETWORK_FORMAT = 16; - -    printTrace("%s| Get Network Status", m_sName.c_str()); - -    //Always get common network stats because this should never fail -    //This way the basic stats are always returned even if AT#RFSTS fails below -    getCommonNetworkStats(jData); - -    std::string sCmd; -    std::string sResult; -    // LE910 radios have a bug where issuing AT#RFSTS with a locked SIM -    // will cause the radio to stop responding until a radio power cycle -    // Telit Support Portal Case #5069697 -    // LE910C1-NS is an LE910, so we stop the scan after the 0. -    if (m_sName.find("LE910") != std::string::npos) { -        sCmd = "AT+CPIN?"; -        sResult = sendCommand(sCmd); -        if (sResult.find("+CPIN:") == std::string::npos) { -            printDebug("%s| AT+CPIN? returned unexpected response: [%s][%s]", m_sName.c_str(), sCmd.c_str(), sResult.c_str()); -            printTrace("%s| Network Status:\n%s\n", m_sName.c_str(), jData.toStyledString().c_str()); -            return SUCCESS; //return SUCCESS because getCommonNetworkStats() succeeded at top of this function -        } -        if (sResult.find("SIM PIN") != std::string::npos) { -            printError("%s| The SIM is locked and must first be unlocked", m_sName.c_str()); -            printTrace("%s| Network Status:\n%s\n", m_sName.c_str(), jData.toStyledString().c_str()); -            return SUCCESS; //return SUCCESS because getCommonNetworkStats() succeeded at top of this function -        } -    } - -    sCmd = "AT#RFSTS"; -    sResult = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, 200); -    if (sResult.find("#RFSTS:") == std::string::npos) { -        //On LTE radios without signal, this case will run because AT#RFSTS just returns "OK" -        printDebug("%s| Network Status command returned unexpected response: [%s][%s]", m_sName.c_str(), sCmd.c_str(), sResult.c_str()); -        printTrace("%s| Network Status:\n%s\n", m_sName.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 "#RFSTS:" -    std::vector<std::string> vParts = MTS::Text::split(MTS::Text::trim(sResult.substr(start)), ","); - -    if (vParts.size() < 3) { -        printDebug("%s| Network Status command reponse is an unknown format: [%s][%s]", m_sName.c_str(), sCmd.c_str(), sResult.c_str()); -        printTrace("%s| Network Status:\n%s\n", m_sName.c_str(), jData.toStyledString().c_str()); -        return SUCCESS; //return SUCCESS because getCommonNetworkStats() succeeded at top of this function -    } else { -        //Country Code and Operator Code -        std::vector<std::string> vPLMN = MTS::Text::split(vParts[0], ' '); -        if(vPLMN.size() == 2) { -            jData[KEY_MCC] = MTS::Text::strip(vPLMN[0], '"'); -            jData[KEY_MNC] = MTS::Text::strip(vPLMN[1], '"'); -        } - -        jData[KEY_CHANNEL] = vParts[1]; -    } - -    if (vParts.size() == GSM_NETWORK_FORMAT ) { -        //Parse as GSM Network Format -        jData[KEY_RSSIDBM] = vParts[2]; -        jData[KEY_LAC] =  vParts[3]; -        jData[KEY_RAC] = vParts[4]; -        jData[KEY_TXPWR] = vParts[5]; -        jData[KEY_MM] = vParts[6]; -        jData[KEY_RR] = vParts[7]; -        jData[KEY_NOM] = vParts[8]; -        jData[KEY_CID] = vParts[9]; -        jData[KEY_IMSI] = MTS::Text::strip(vParts[10], '"'); -        jData[KEY_NETWORK] = MTS::Text::strip(vParts[11], '"'); -        if(MTS::Text::parse(iValue, vParts[12]) && convertServiceDomainToString((SERVICEDOMAIN)iValue, sValue) == SUCCESS) { -            jData[KEY_SD] = sValue; -        } -        if(MTS::Text::parse(iValue, vParts[13]) && convertActiveBandToString((ACTIVEBAND)iValue, sValue) == SUCCESS) { -            jData[KEY_ABND] = sValue; -        } -      // IN003567 ME910C1 radios have some odd behavior with regards to WCDMA.  The ordering of the fields from #RFSTS are -      // the same as LTE up to the 16th field (for ME901C1-WW anyway).  Drop into LTE parsing for ME910C1-WW. -    } else if((vParts.size() >= WCDMA_NETWORK_FORMAT) && (m_sName.find("ME910C1-WW") == std::string::npos)) { -        Json::Value jDebug; - -        //Parse as WCDMA Network Format - -        jDebug[KEY_PSC] = vParts[2]; -        jDebug[KEY_ECIO] = vParts[3]; -        jDebug[KEY_RSCP] = vParts[4]; - -        jData[KEY_RSSIDBM] = vParts[5]; -        jData[KEY_LAC] = vParts[6]; -        jData[KEY_RAC] = vParts[7]; - -        jDebug[KEY_TXPWR] = vParts[8]; -        jDebug[KEY_DRX] = vParts[9]; -        jDebug[KEY_MM] = vParts[10]; -        jDebug[KEY_RR] = vParts[11]; -        jDebug[KEY_NOM] = vParts[12]; - -        if(vParts[13].size() != 0) { -            jDebug[KEY_BLER] = vParts[13]; -        } else { -            jDebug[KEY_BLER] = "000"; -        } - -        jData[KEY_CID] = vParts[14]; -        jData[KEY_IMSI] = MTS::Text::strip(vParts[15], '"'); -        jData[KEY_NETWORK] = MTS::Text::strip(vParts[16], '"'); - -        // Get the radio band given the channel (UARFCN) -        RadioBandMap radioBandMap(vParts[1], CellularRadio::VALUE_TYPE_CDMA); -        jData[KEY_ABND] = radioBandMap.getRadioBandName(); - -        if(MTS::Text::parse(iValue, vParts[17]) && convertServiceDomainToString((SERVICEDOMAIN)iValue, sValue) == SUCCESS) { -            jDebug[KEY_SD] = sValue; -        } -        //Ignoring Active Set Values -        //  <nAST> - Number of Active Set (Maximum 6) -        //  <nUARFCN> - UARFCN of n th active set -        //  <nPSC> - PSC of n th active set -        //  <nEc/Io > - Ec/Io of n th active Set - -        jData[KEY_DEBUG] = jDebug; -    } else if(vParts.size() >= LTE_NETWORK_FORMAT) { -        Json::Value jDebug; - -        //Parse as LTE Network Format - -        // -        // MD: It is noticed that LTE Network format may vary depending on the firmware version: -        // -        // <PLMN>,<EARFCN>,<RSRP>,<RSSI>,<RSRQ>,<TAC>,[<TXPWR>],<DRX>,<MM>,<RRC>,<CID>,<IMSI>,[<NetNameAsc>],<SD>,<ABND>,<SINR> -        //    Ex 1: #RFSTS: "310 260",2300,-98,-63,-14,AA06,,128,19,0,0501D02,"310260754792598","T-Mobile",3,4,197 -        // -        // <PLMN>,<EARFCN>,<RSRP>,<RSSI>,<RSRQ>,<TAC>,<RAC>,[<TXPWR>],<DRX>,<MM>,<RRC>,<CID>,<IMSI>,[<NetNameAsc>],<SD>,<ABND> -        //    Ex 2: #RFSTS:"310 410",5780,-105,-73,-14,4603,255,,128,19,0,0000098,"310410536498694","AT&T",3,17 -        //          #RFSTS:"311 480",1150,-96,-66,-9.0,bf35,FF,0,0,19,1,"2ED1B0E","311480148817753","Verizon",2,2,720000,10800 -        //          #RFSTS:"310 410",2175,-120,-89,-17.5,4612,FF,0,0,19,1,"4E5E916","310410807276607","AT&T",3,4 -        // -        // Additional <RAC> parameter in the second example shifts the rest of the parameters. Here we are trying to figure out -        // which format is currently produced based on <NetNameAsc> field position which always has double quotation marks. -        // -        if (vParts[13].find("\"") != std::string::npos) { -            // parse the RAC and then remove it from the vector -            jData[KEY_RAC] = vParts[6]; -            vParts.erase(vParts.begin() + 6); -        } - -        jDebug["rsrp"] = vParts[2]; -        jDebug[KEY_RSSIDBM] = vParts[3]; -        jDebug["rsrq"] = vParts[4]; - -        jData["tac"] = vParts[5]; -        jDebug[KEY_TXPWR] = vParts[6]; -        jData[KEY_DRX] = vParts[7]; -        jDebug[KEY_MM] = vParts[8]; -        jDebug["rrc"] = vParts[9]; -        jData[KEY_CID] = MTS::Text::strip(vParts[10], '"'); -        jData[KEY_IMSI] = MTS::Text::strip(vParts[11], '"'); -        jData[KEY_NETWORK] = MTS::Text::strip(vParts[12], '"'); - -        // Get the radio band given the channel (EARFCN) -        RadioBandMap radioBandMap(vParts[1], CellularRadio::VALUE_TYPE_LTE); -        jData[KEY_ABND] = radioBandMap.getRadioBandName(); - -        jData[KEY_LAC] = queryLteLac(); - -        if(MTS::Text::parse(iValue, vParts[13]) && convertServiceDomainToString((SERVICEDOMAIN)iValue, sValue) == SUCCESS) { -            jDebug[KEY_SD] = sValue; -        } - -        jData[KEY_DEBUG] = jDebug; -    } - -    printTrace("%s| Network Status:\n%s\n", m_sName.c_str(), jData.toStyledString().c_str()); -    return SUCCESS; -} - -// Get the LAC for the LTE radio that's not in the #RFSTS response -std::string CellularRadio::queryLteLac() { -    std::string CGREGstring; -    std::string originalCGREG; -    std::string result; - -    CGREGstring = queryCGREGstring(); -    if (CGREGstring == RSP_ERROR) { -        originalCGREG = "0"; -    } else { -        originalCGREG = CGREGstring.at(CGREGstring.find(",") - 1); //Position right before first comma ("+CGREG: 0,1") -    } - -    // Temporarily set CGREG=2 to get more info -    setCGREG("2"); - -    CGREGstring = queryCGREGstring(); -    if (CGREGstring == RSP_ERROR) { -        result = CellularRadio::VALUE_UNKNOWN; -    } else { -        size_t start = CGREGstring.find(":") + 1; //Position right after "#RFSTS:" -        std::vector<std::string> vParts = MTS::Text::split(MTS::Text::trim(CGREGstring.substr(start)), ","); -        if(vParts.size() < 3) { -            result = CellularRadio::VALUE_UNAVAILABLE; -        } else { -            result = MTS::Text::strip(vParts[2], '"'); -        } -    } - -    setCGREG(originalCGREG); - -    return result; -} - -void CellularRadio::setCGREG(std::string value) { -    std::string sCmd("AT+CGREG=" + value); -    std::string cmdResult(sendCommand(sCmd)); -    if (cmdResult.find("OK") == std::string::npos) { -        printDebug("%s| AT#CGREG=%s returned unexpected response: [%s][%s]", m_sName.c_str(), value.c_str(), sCmd.c_str(), cmdResult.c_str()); -    } -} - -std::string CellularRadio::queryCGREGstring() { -    std::string sCmd("AT+CGREG?"); -    std::string cmdResult(sendCommand(sCmd)); -    if (cmdResult.find("+CGREG:") == std::string::npos) { -        printDebug("%s| AT#CGREG? returned unexpected response: [%s][%s]", m_sName.c_str(), sCmd.c_str(), cmdResult.c_str()); -        return RSP_ERROR; -    } -    return cmdResult; -} - -void CellularRadio::getCommonNetworkStats(Json::Value& jData) { - -    bool bRoaming = false; -    if(getRoaming(bRoaming) == SUCCESS) { -        jData[KEY_ROAMING] = bRoaming; -    } - -    int32_t iRssi; -    if(getSignalStrength(iRssi) == SUCCESS) { -        jData[KEY_RSSI] = iRssi; -        int32_t dBm; -        if(!jData.isMember(KEY_RSSIDBM) && convertSignalStrengthTodBm(iRssi, dBm) == SUCCESS) { -            //Add RSSI in dBm format -            jData[KEY_RSSIDBM] = MTS::Text::format(dBm); -        } -    } - -    std::string sService; -    if(getService(sService) == SUCCESS) { -        jData[KEY_SERVICE] = sService; -    } -    std::string sDate, sTime, sTimeZone; -    if(getTime(sDate, sTime, sTimeZone) == SUCCESS) { -        jData[KEY_DATETIME] = sDate + " " + sTime + " GMT" + sTimeZone; -    } - -    std::string sNetworkReg; -    CellularRadio::REGISTRATION eReg; -    if (getRegistration(eReg) == SUCCESS) { -        if (convertRegistrationToString(eReg, sNetworkReg) == SUCCESS) { -            jData[CellularRadio::KEY_NETWORK_REG] = sNetworkReg; -        } -    } -} - -void CellularRadio::initMipProfile(Json::Value& jData) { -    jData[KEY_MIP_ID] = 0; -    jData[KEY_MIP_ENABLED] = false; -    jData[KEY_MIP_NAI] = VALUE_UNKNOWN; -    jData[KEY_MIP_HOMEADDRESS] = VALUE_UNKNOWN; -    jData[KEY_MIP_PRIMARYHA] = VALUE_UNKNOWN; -    jData[KEY_MIP_SECONDARYHA] = VALUE_UNKNOWN; -    jData[KEY_MIP_MNAAASPI] = VALUE_UNKNOWN; -    jData[KEY_MIP_MNHASPI] = VALUE_UNKNOWN; -    jData[KEY_MIP_MNAAASS] = false; -    jData[KEY_MIP_MNHASS] = false; -} - -CellularRadio::CODE CellularRadio::getRegistration(REGISTRATION& eRegistration) { -    std::string sCmd; -    std::string sResp; - -    // LE910C1-NS is an LE910, so we stop the scan after the 0. -    if (m_sName.find("LE910") != std::string::npos) { -        // use AT+CGREG instead for LE910 models -        sCmd = "AT+CGREG?"; -        sResp = "+CGREG: "; -    } -    else { -        sCmd = "AT+CREG?"; -        sResp = "+CREG: "; -    } - -    std::string sResult = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, 5000); -    if (sResult.find(sResp) == std::string::npos) { -        if(sResult.size() == 0) { -            printDebug("%s| Registration command returned no response: [%s]", m_sName.c_str()); -            return NO_RESPONSE; -        } -        printDebug("%s| Registration command returned unexpected response: [%s]", m_sName.c_str(), sResult.c_str()); -        return FAILURE; -    } - -    size_t start = sResult.find(','); -    size_t stop = sResult.find(' ', start); -    std::string sRegStat = sResult.substr(start + 1, stop - start - 1); -    int32_t value; -    sscanf(sRegStat.c_str(), "%d", &value); -    eRegistration = (REGISTRATION)value; -    return SUCCESS; -} - -CellularRadio::CODE CellularRadio::convertRegistrationToString(REGISTRATION eRegistration, std::string& sRegistration) { - -    CODE eCode = FAILURE; -    switch (eRegistration) { -        case NOT_REGISTERED: sRegistration = VALUE_NOT_REGISTERED; eCode = SUCCESS; break; -        case REGISTERED: sRegistration = VALUE_REGISTERED; eCode = SUCCESS; break; -        case SEARCHING: sRegistration = VALUE_SEARCHING; eCode = SUCCESS; break; -        case DENIED: sRegistration = VALUE_DENIED; eCode = SUCCESS; break; -        case UNKNOWN: sRegistration = VALUE_UNKNOWN; eCode = SUCCESS; break; -        case ROAMING: sRegistration = VALUE_ROAMING; eCode = SUCCESS; break; -    } -    return eCode; -} - -CellularRadio::CODE CellularRadio::validateMsl(const Json::Value& jArgs) { -    printTrace("%s| Validate MSL", m_sName.c_str()); - -    return NOT_APPLICABLE; -} - -CellularRadio::CODE CellularRadio::setMdn(const Json::Value& jArgs) { -    printTrace("%s| Set MDN", m_sName.c_str()); - -    if(!jArgs["mdn"].isString()) { -        return INVALID_ARGS; -    } - -    std::string sCmd("AT#SNUM=1,\""); -    sCmd += jArgs["mdn"].asString() + "\""; - -    std::string sResult = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, 1000); -    size_t end = sResult.find(RSP_OK); -    if (end == std::string::npos) { -        printWarning("%s| Unable to set MDN for radio using command [%s]", m_sName.c_str(), sCmd.c_str()); -        return FAILURE; -    } - -    return SUCCESS; -} - -CellularRadio::CODE CellularRadio::setMsid(const Json::Value& jArgs) { -    printTrace("%s| Set MSID", m_sName.c_str()); - -    return NOT_APPLICABLE; -} - -CellularRadio::CODE CellularRadio::getMipProfile(Json::Value& jMipProfile) { -    printTrace("%s| Get MIP Active Profile", m_sName.c_str()); - -    return NOT_APPLICABLE; -} - -CellularRadio::CODE CellularRadio::setMipActiveProfile(const Json::Value& jArgs) { -    printTrace("%s| Set MIP Active Profile", m_sName.c_str()); - -    return NOT_APPLICABLE; -} - -CellularRadio::CODE CellularRadio::setMipNai(const Json::Value& jArgs) { -    printTrace("%s| Set MIP NAI", m_sName.c_str()); - -    return NOT_APPLICABLE; -} - -CellularRadio::CODE CellularRadio::setMipHomeIp(const Json::Value& jArgs) { -    printTrace("%s| Set MIP Home IP", m_sName.c_str()); - -    return NOT_APPLICABLE; -} - -CellularRadio::CODE CellularRadio::setMipPrimaryHa(const Json::Value& jArgs) { -    printTrace("%s| Set MIP Primary HA", m_sName.c_str()); - -    return NOT_APPLICABLE; -} - -CellularRadio::CODE CellularRadio::setMipSecondaryHa(const Json::Value& jArgs) { -    printTrace("%s| Set MIP Secondary HA", m_sName.c_str()); - -    return NOT_APPLICABLE; -} - -CellularRadio::CODE CellularRadio::setMipMnAaaSpi(const Json::Value& jArgs) { -    printTrace("%s| Set MIP MN-AAA SPI", m_sName.c_str()); - -    return NOT_APPLICABLE; -} - -CellularRadio::CODE CellularRadio::setMipMnHaSpi(const Json::Value& jArgs) { -    printTrace("%s| Set MIP MN-HA SPI", m_sName.c_str()); - -    return NOT_APPLICABLE; -} - -CellularRadio::CODE CellularRadio::setMipRevTun(const Json::Value& jArgs) { -    printTrace("%s| Set MIP Rev Tun", m_sName.c_str()); - -    return NOT_APPLICABLE; -} - -CellularRadio::CODE CellularRadio::setMipMnAaaSs(const Json::Value& jArgs) { -    printTrace("%s| Set MIP MN-AAA SS", m_sName.c_str()); - -    return NOT_APPLICABLE; -} - -CellularRadio::CODE CellularRadio::setMipMnHaSs(const Json::Value& jArgs) { -    printTrace("%s| Set MIP MN-HA SS", m_sName.c_str()); - -    return NOT_APPLICABLE; -} - -CellularRadio::CODE CellularRadio::updateDc(const Json::Value& jArgs, UpdateCb& stepCb) { -    printTrace("%s| Update Device Configuration", m_sName.c_str()); - -    return NOT_APPLICABLE; -} - -CellularRadio::CODE CellularRadio::updatePrl(const Json::Value& jArgs, UpdateCb& stepCb) { -    printTrace("%s| Update Preferred Roaming List", m_sName.c_str()); - -    return NOT_APPLICABLE; -} - -CellularRadio::CODE CellularRadio::updateFumo(const Json::Value& jArgs, UpdateCb& stepCb) { -    printTrace("%s| Update Firmware Update Management Object", m_sName.c_str()); - -    return NOT_APPLICABLE; -} - -CellularRadio::CODE CellularRadio::resetHfa(const Json::Value& jArgs, UpdateCb& stepCb) { -    printTrace("%s| HFA Reset", m_sName.c_str()); - -    return NOT_APPLICABLE; -} - -CellularRadio::CODE CellularRadio::activate(const Json::Value& jArgs, UpdateCb& stepCb) { -    printTrace("%s| Activation", m_sName.c_str()); - -    return NOT_APPLICABLE; -} - -CellularRadio::CODE CellularRadio::setActiveFirmware(const Json::Value& jArgs) { -    printTrace("%s| Set Active Firmware Image Number: not applicable", m_sName.c_str()); - -    return NOT_APPLICABLE; -} - -CellularRadio::CODE CellularRadio::getActiveFirmware(std::string& sFwId) { -    printTrace("%s| Get Active Firmware Image Number: not applicable", m_sName.c_str()); -    sFwId = VALUE_NOT_SUPPORTED; - -    return NOT_APPLICABLE; -} - -CellularRadio::CODE CellularRadio::sendBasicCommand(const std::string& sCmd, int32_t iTimeoutMillis, const char& ESC) { -    std::string response = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, iTimeoutMillis, ESC); -    if (response.size() == 0) { -        return NO_RESPONSE; -    } else if (response.find(RSP_OK) != std::string::npos) { -        return SUCCESS; -    } else if (response.find(RSP_ERROR) != std::string::npos) { -        return ERROR; -    } else { -        return FAILURE; -    } -} - -std::string CellularRadio::sendCommand(const std::string& sCmd, const std::vector<std::string>& vBail, int32_t timeoutMillis, const char& ESC) { -    return sendCommand(m_apIo, sCmd, vBail, timeoutMillis, ESC); -} - -std::string CellularRadio::sendCommand(MTS::AutoPtr<MTS::IO::Connection>& apIo, const std::string& sCmd, -                                       const std::vector<std::string>& vBail, int32_t timeoutMillis, const char& ESC) { -    IsNeedMoreData isNeedMoreData = [&vBail](const std::string& iterationData, const std::string& allData)->bool { -        for(size_t i = 0; i < vBail.size(); i++) { -            const std::string& sBail = vBail[i]; -            if(sBail.size() > 0) { -                if(allData.find(sBail) != std::string::npos) { -                    //Return when bail string is found -                    printTrace("RADIO| Found bail string [%s]", sBail.c_str()); -                    return false; -                } -            } -        } -        return true; -    }; - -    return sendCommand(apIo, sCmd, isNeedMoreData, timeoutMillis, ESC); -} - -std::string CellularRadio::sendCommand(const std::string& sCmd, MTS::IO::CellularRadio::IsNeedMoreData& isNeedMoreData, int32_t timeoutMillis, const char& ESC) { -    return sendCommand(m_apIo, sCmd, isNeedMoreData, timeoutMillis, ESC); -} - -std::string CellularRadio::sendCommand(MTS::AutoPtr<MTS::IO::Connection>& apIo, const std::string& sCmd, -                                       IsNeedMoreData& isNeedMoreData, int32_t timeoutMillis, const char& ESC) { -    if(MTS::Logger::getPrintLevel() >= MTS::Logger::PrintLevel::TRACE_LEVEL) { -        printTrace("RADIO| Sending command [%s]", sCmd.c_str()); -    } -    if(apIo.isNull()) { -        printError("RADIO| IO is not set in sendCommand"); -        return ""; -    } - -    int32_t iResult; -    if(ESC == 0x00) { -        iResult = apIo->write(sCmd.data(), sCmd.size()); -    } else { -        std::string sNewCmd(sCmd); -        sNewCmd.push_back(ESC); -        iResult = apIo->write(sNewCmd.data(), sNewCmd.size()); -    } - -    if(iResult == -1) { -        printError("RADIO| Failed to send command to radio"); -        return ""; -    } - -    bool done = false; -    const uint32_t capacity = 1024; -    char buffer[capacity]; -    std::string sResult; -    Timer timer; -    timer.start(); -    do { -        int32_t iterationTimeout = 100; -        int bytesRead = apIo->read((char*)buffer, capacity, iterationTimeout); -        if(bytesRead == -1) { -            printError("RADIO| Failed to read from radio"); -            break; -        } - -        std::string sIteration((char*)buffer, bytesRead); -        sResult += sIteration; - -        if(isNeedMoreData && !isNeedMoreData(sIteration, sResult)) { -            printTrace("RADIO| No more data needed"); -            return sResult; -        } -        if(timeoutMillis >= 0) { -            done = (timer.getMillis() >= (uint64_t)timeoutMillis); -        } else { -            //Do not stop looping until bail string is found -        } -    } while(!done); - -    //Timed out -    return sResult; -} - -CellularRadio::CODE CellularRadio::test(MTS::AutoPtr<MTS::IO::Connection>& apIo, uint32_t timeoutSeconds) { -    printTrace("RADIO| Basic Test"); -    uint32_t count = 0; -    std::string sCmd("AT"); -    do { -        std::string sResult = sendCommand(apIo, sCmd); -        if (sResult.find(RSP_OK) == std::string::npos) { -            printTrace("RADIO| Waiting for basic radio communication [%s] ...", sResult.c_str()); -        } else { -            break; -        } -        count++; -    } while (count < timeoutSeconds); - -    if(count == timeoutSeconds) { -        printWarning("RADIO| Basic radio communication FAILED"); -        return NO_RESPONSE; -    } -    return SUCCESS; -} - -std::string CellularRadio::extractModelFromResult(const std::string& sResult) { -    std::string sModel(CellularRadio::VALUE_NOT_SUPPORTED); - -    if(sResult.find("HE910-D") != std::string::npos) { -        sModel = "HE910-D"; -    } else if(sResult.find("HE910-EUD") != std::string::npos) { -        sModel = "HE910-EUD"; -    } else if(sResult.find("LE910-JN1") != std::string::npos) { -        sModel = "LE910-JN1"; -    } else if(sResult.find("LE866A1-JS") != std::string::npos) { -        sModel = "LE866A1-JS"; -    } else if(sResult.find("LE910-NAG") != std::string::npos) { -        sModel = "LE910-NAG"; -    } else if(sResult.find("LE910C4-NF") != std::string::npos) { -        sModel = "LE910C4-NF"; -    } else if(sResult.find("LE910-NA1") != std::string::npos) { -        sModel = "LE910-NA1"; -    } else if(sResult.find("ME910C1-NA") != std::string::npos) { -        sModel = "ME910C1-NA"; -    } else if(sResult.find("ME910C1-NV") != std::string::npos) { -        sModel = "ME910C1-NV"; -    } else if(sResult.find("ME910C1-WW") != std::string::npos) { -        sModel = "ME910C1-WW"; -    } else if(sResult.find("LE910-SVG") != std::string::npos) { -        sModel = "LE910-SVG"; -    } else if(sResult.find("LE910-EUG") != std::string::npos) { -        sModel = "LE910-EUG"; -    } else if(sResult.find("LE910C4-EU") != std::string::npos) { -        sModel = "LE910C4-EU"; -    } else if(sResult.find("LE910-EU1") != std::string::npos) { -        sModel = "LE910-EU1"; -    } else if(sResult.find("LE910C1-NS") != std::string::npos) { -    	sModel = "LE910C1-NS"; -    } else if(sResult.find("LE910C1-AP") != std::string::npos) { -    	sModel = "LE910C1-AP"; -    } else if(sResult.find("GE910") != std::string::npos) { -        sModel = "GE910"; -    } else if(sResult.find("DE910-DUAL") != std::string::npos) { -        sModel = "DE910-DUAL"; -    } else if(sResult.find("CE910") != std::string::npos) { -        sModel = "CE910"; -    } -    return sModel; -} - -std::string CellularRadio::getCodeAsString(CODE eCode) { -    switch(eCode) { -        case SUCCESS: -            return "SUCCESS"; -        case ERROR: -            return "ERROR"; -        case FAILURE: -            return "FAILURE"; -        case NO_RESPONSE: -            return "NO RESPONSE"; -        default: -            return "UNKNOWN"; -    } -} - -bool CellularRadio::splitAndAssign(const std::string& sLine, const std::string& sKey, Json::Value& jParent, const std::string& sJsonKey,  Json::ValueType eType) { - -    std::vector<std::string> vParts = MTS::Text::split(sLine, ":", 2); - -    if(vParts.size() == 2 && vParts[0] == sKey) { -        if(eType == Json::ValueType::stringValue) { -            jParent[sJsonKey] = MTS::Text::trim(vParts[1]); -        } else if (eType == Json::ValueType::intValue || eType == Json::ValueType::uintValue) { -            //TODO: -            printWarning("%s| Unable to parse requested type from line [%s]", getName().c_str(), sKey.c_str(), sLine.c_str()); -            return false; -        } else if(eType == Json::ValueType::realValue) { -            //TODO: -            printWarning("%s| Unable to parse requested type from line [%s]", getName().c_str(), sKey.c_str(), sLine.c_str()); -            return false; -        } else if(eType == Json::ValueType::booleanValue) { -            //TODO: -            printWarning("%s| Unable to parse requested type from line [%s]", getName().c_str(), sKey.c_str(), sLine.c_str()); -            return false; -        } else { -            printWarning("%s| Unable to parse requested type from line [%s]", getName().c_str(), sKey.c_str(), sLine.c_str()); -            return false; -        } -    } else { -        printWarning("%s| Unable to parse %s from line [%s]", getName().c_str(), sKey.c_str(), sLine.c_str()); -        return false; -    } - -    return true; -} - -bool CellularRadio::getCarrierFromFirmware(const std::string& sFirmware, std::string& sCarrier) { -    // Telit Radios -    //    H.ab.zyx => 3 Main Components -    //    "H" = Hardware -> 15 = DE910 family, 18 = CE910 family, 12 = HE910 family -    //    "a" = Hardware version -    //    "b" = Software Major Version -    //    "z" = is the product type, i.e. DUAL or SC -    //    "y" = is the carrier variant -    //    "x" = is the firmware version -    //    Telit will do their best to keep the carrier variant as "0" for Sprint, "1" for Aeris, "2" for Verizon, and "3" for U.S. Cellular. - -    const uint32_t CARRIER_INDEX = 1;   //y in [zyx] - -    bool bResult = false; -    std::vector<std::string> vParts = MTS::Text::split(sFirmware, '.'); - -    if(vParts.size() == 3) { -        //CDMA firmware version notation -        if(vParts[0] == "15" || vParts[0] == "18") { -            //DE910 or CE910 -> Good good -            std::string sID = vParts[2]; -            if(sID.size() == 3) { -                char cId = sID[CARRIER_INDEX]; - -                //Good good -                if(cId == '0') { -                    sCarrier = VALUE_CARRIER_SPRINT; -                    bResult = true; -                } else -                if(cId == '1') { -                    sCarrier = VALUE_CARRIER_AERIS; -                    bResult = true; -                } else -                if(cId == '2') { -                    sCarrier = VALUE_CARRIER_VERIZON; -                    bResult = true; -                } else -                if(cId == '3') { -                    sCarrier = VALUE_CARRIER_USCELLULAR; -                    bResult = true; -                } -            } -        } -    } - -    return bResult; -} - -bool CellularRadio::getHardwareVersionFromFirmware(const std::string& sFirmware, std::string& sHardware) { -    // Telit Radios -    //    H.ab.zyx => 3 Main Components -    //    "H" = Hardware -> 15 = DE910 family, 18 = CE910 family, 12 = HE910 family -    //    "a" = Hardware version -    //    "b" = Software Major Version -    //    "z" = is the product type, i.e. DUAL or SC -    //    "y" = is the carrier variant -    //    "x" = is the firmware version -    //    Telit will do their best to keep the carrier variant as "0" for Sprint, "1" for Aeris, and "2" for Verizon. - -    const uint32_t HARDWARE_INDEX = 0;   //a in [ab] - -    bool bResult = false; -    std::vector<std::string> vParts = MTS::Text::split(sFirmware, '.'); - -    if(vParts.size() == 3) { -        //GSM Hardware Version -        if(!(vParts[0] == "15" || vParts[0] == "18")) { -            //Not DE910 or CE910 -> Good good -            std::string sVersion = vParts[1]; -            if(sVersion.size() == 2) { -                sHardware = "1."; -                sHardware += sVersion[HARDWARE_INDEX]; -                bResult = true; -            } -        } -    } - -    return bResult; - -} - -const char *CellularRadio::RadioBandMap::getLTEBand(const int32_t channel) -{ -    for (unsigned int ii = 0; ii < NUM_LTE_BANDS; ii++) -    { -        if (EULTRAband[ii].low <= channel && EULTRAband[ii].high >= channel) -        { -            return EULTRAband[ii].name; -        } -    } -    return VALUE_UNKNOWN.c_str(); -} - -const char *CellularRadio::RadioBandMap::getCDMABand(const int channel) -{ -    for (unsigned int ii = 0; ii < NUM_WCDMA_BANDS; ii++) -    { -        if (WCDMAband[ii].low <= channel && WCDMAband[ii].high >= channel) -        { -            return WCDMAband[ii].name; -        } -    } -    return VALUE_UNKNOWN.c_str(); -} - -const char *CellularRadio::RadioBandMap::getGSMBand(const int channel) -{ -    for (unsigned int ii = 0; ii < NUM_GSM_BANDS; ii++) -    { -        if (GSMband[ii].low <= channel && GSMband[ii].high >= channel) -        { -            return GSMband[ii].name; -        } -    } -    return VALUE_UNKNOWN.c_str(); -} - -const char *CellularRadio::RadioBandMap::getRadioBandName() -{ -    const char *band = CellularRadio::VALUE_UNKNOWN.c_str(); - -    if (m_sRadioType == CellularRadio::VALUE_TYPE_LTE) -    { -        band = getLTEBand(m_iChannel); -    } -    else if (m_sRadioType == CellularRadio::VALUE_TYPE_CDMA) -    { -        band = getCDMABand(m_iChannel); -    } -    else if (m_sRadioType == CellularRadio::VALUE_TYPE_GSM) -    { -        band = getGSMBand(m_iChannel); -    } - -    return band; -} - -const char *CellularRadio::RadioBandMap::getRadioBandName(const std::string &channel, const std::string &radioType) -{ -    const char *band = CellularRadio::VALUE_UNKNOWN.c_str(); -    int32_t chan = strtol(channel.c_str(), NULL, 10); -    if (radioType == CellularRadio::VALUE_TYPE_LTE) -    { -        band = getLTEBand(chan); -    } -    else if (radioType == CellularRadio::VALUE_TYPE_CDMA) -    { -        band = getCDMABand(chan); -    } -    else if (radioType == CellularRadio::VALUE_TYPE_GSM) -    { -        band = getGSMBand(chan); -    } - -    return band; -} +#include "mts/MTS_IO_CellularRadio.h" diff --git a/src/MTS_IO_CellularRadioFactory.cpp b/src/MTS_IO_CellularRadioFactory.cpp index ef87f0e..17cbd05 100644 --- a/src/MTS_IO_CellularRadioFactory.cpp +++ b/src/MTS_IO_CellularRadioFactory.cpp @@ -87,14 +87,14 @@ std::string CellularRadioFactory::identifyRadio(const std::string& sPort) {      apIo.reset(new SerialConnection(SerialConnection::Builder(sPort).baudRate(115200).useLockFile().build()));      while(!apIo->open(30000)) {          printError("CellularRadioFactory| Failed to open radio port [%s]", sPort.c_str()); -        return CellularRadio::VALUE_UNKNOWN; +        return TelitRadio::VALUE_UNKNOWN;      }      //Attempt basic radio communication -    if(CellularRadio::test(apIo) != CellularRadio::SUCCESS) { +    if(TelitRadio::test(apIo) != TelitRadio::SUCCESS) {          printError("CellularRadioFactory| Failed to communicate with radio on port [%s]", sPort.c_str());          apIo->close(); -        return CellularRadio::VALUE_UNKNOWN; +        return TelitRadio::VALUE_UNKNOWN;      }      //Get model @@ -102,7 +102,7 @@ std::string CellularRadioFactory::identifyRadio(const std::string& sPort) {      std::string sCmd("ATI4");      std::string sResult;      do { -        sResult = CellularRadio::sendCommand(apIo, sCmd, CellularRadio::DEFAULT_BAIL_STRINGS, 1000, CellularRadio::CR); +        sResult = TelitRadio::sendCommand(apIo, sCmd, TelitRadio::DEFAULT_BAIL_STRINGS, 1000, TelitRadio::CR);          if (sResult.find("OK") == std::string::npos) {              printDebug("RADIO| Attempting to get radio model [%s] ...", sResult.c_str());          } else { @@ -114,10 +114,10 @@ std::string CellularRadioFactory::identifyRadio(const std::string& sPort) {      if(count == 30) {          printDebug("RADIO| Unable to get radio model");          apIo->close(); -        return CellularRadio::VALUE_UNKNOWN; +        return TelitRadio::VALUE_UNKNOWN;      } -    std::string sModel = CellularRadio::extractModelFromResult(sResult); +    std::string sModel = TelitRadio::extractModelFromResult(sResult);      printDebug("RADIO| Extracted [%s] from ATI4 query", sModel.c_str());      apIo->close();      return sModel; diff --git a/src/MTS_IO_EG95Radio.cpp b/src/MTS_IO_EG95Radio.cpp new file mode 100644 index 0000000..2fca48f --- /dev/null +++ b/src/MTS_IO_EG95Radio.cpp @@ -0,0 +1 @@ +#include "mts/MTS_IO_EG95Radio.h" diff --git a/src/MTS_IO_GE910Radio.cpp b/src/MTS_IO_GE910Radio.cpp index f31f4fc..c99d16c 100644 --- a/src/MTS_IO_GE910Radio.cpp +++ b/src/MTS_IO_GE910Radio.cpp @@ -34,7 +34,7 @@ using namespace MTS::IO;  const std::string GE910Radio::MODEL_NAME("GE910");  GE910Radio::GE910Radio(const std::string& sPort) -: CellularRadio(MODEL_NAME, sPort) +: TelitRadio(MODEL_NAME, sPort)  {  } diff --git a/src/MTS_IO_HE910Radio.cpp b/src/MTS_IO_HE910Radio.cpp index 0178c9d..cc0e873 100644 --- a/src/MTS_IO_HE910Radio.cpp +++ b/src/MTS_IO_HE910Radio.cpp @@ -32,7 +32,7 @@  using namespace MTS::IO;  HE910Radio::HE910Radio(const std::string& sHE910Model, const std::string& sPort) -: CellularRadio(sHE910Model, sPort) +: TelitRadio(sHE910Model, sPort)  {  } diff --git a/src/MTS_IO_LE866Radio.cpp b/src/MTS_IO_LE866Radio.cpp index 2e92f67..85b8dc3 100644 --- a/src/MTS_IO_LE866Radio.cpp +++ b/src/MTS_IO_LE866Radio.cpp @@ -31,7 +31,7 @@  using namespace MTS::IO;  LE866Radio::LE866Radio(const std::string& sLE866Model, const std::string& sPort) -: CellularRadio(sLE866Model, sPort) +: TelitRadio(sLE866Model, sPort)  {  } diff --git a/src/MTS_IO_LE910Radio.cpp b/src/MTS_IO_LE910Radio.cpp index f383b68..b02c2ce 100644 --- a/src/MTS_IO_LE910Radio.cpp +++ b/src/MTS_IO_LE910Radio.cpp @@ -33,7 +33,7 @@  using namespace MTS::IO;  LE910Radio::LE910Radio(const std::string& sLE910Model, const std::string& sPort) -: CellularRadio(sLE910Model, sPort) +: TelitRadio(sLE910Model, sPort)  {  } diff --git a/src/MTS_IO_ME910Radio.cpp b/src/MTS_IO_ME910Radio.cpp index 590a883..3ed9e50 100644 --- a/src/MTS_IO_ME910Radio.cpp +++ b/src/MTS_IO_ME910Radio.cpp @@ -25,7 +25,7 @@  using namespace MTS::IO;  ME910Radio::ME910Radio(const std::string& sME910Model, const std::string& sPort) -: CellularRadio(sME910Model, sPort) +: TelitRadio(sME910Model, sPort)  {  } 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" diff --git a/src/MTS_IO_TelitRadio.cpp b/src/MTS_IO_TelitRadio.cpp new file mode 100644 index 0000000..de863c3 --- /dev/null +++ b/src/MTS_IO_TelitRadio.cpp @@ -0,0 +1,1838 @@ +/* + * 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 <http://www.gnu.org/licenses/>. + * + */ + +#include <mts/MTS_IO_TelitRadio.h> + +#include <mts/MTS_IO_MccMncTable.h> +#include <mts/MTS_Thread.h> +#include <mts/MTS_Timer.h> +#include <mts/MTS_Logger.h> +#include <mts/MTS_Text.h> +#include <mts/MTS_System.h> +#include <map> +#include <cstring> +#include <sstream> +#include <sys/file.h> +#include <errno.h> +#include <unistd.h> + + +using namespace MTS::IO; + +const char TelitRadio::ETX    = 0x03;  //Ends socket connection +const char TelitRadio::DLE    = 0x10;  //Escapes ETX and DLE within Payload +const char TelitRadio::CR     = 0x0D; +const char TelitRadio::NL     = 0x0A; +const char TelitRadio::CTRL_Z = 0x1A; + +const std::string TelitRadio::RSP_ERROR("ERROR"); +const std::string TelitRadio::RSP_OK("OK"); + + +const std::string TelitRadio::DEFAULT_RADIO_PORT("/dev/modem_at1"); +const std::string TelitRadio::DEFAULT_RADIO_DIR("/var/run/radio/"); +const std::string TelitRadio::VALUE_UNKNOWN("Unknown"); +const std::string TelitRadio::VALUE_UNAVAILABLE("Unavailable"); +const std::string TelitRadio::VALUE_NOT_SUPPORTED("Not Supported"); + +const std::string TelitRadio::VALUE_NOT_REGISTERED("NOT REGISTERED"); +const std::string TelitRadio::VALUE_REGISTERED("REGISTERED"); +const std::string TelitRadio::VALUE_SEARCHING("SEARCHING"); +const std::string TelitRadio::VALUE_DENIED("DENIED"); +const std::string TelitRadio::VALUE_ROAMING("ROAMING"); + +//Static Data +const std::string TelitRadio::KEY_TYPE("type");                    //!< GSM or CDMA +const std::string TelitRadio::KEY_CODE("code");                    //!< Product Code : H5, H6, C2, EV3, G3 +const std::string TelitRadio::KEY_MODEL("model");                  //!< Model : HE910, LE910, CE910, DE910, GE910 +const std::string TelitRadio::KEY_MANUFACTURER("manufacturer");    //!< Manufacturer: Telit +const std::string TelitRadio::KEY_HARDWARE("hardware");            //!< Radio Hardware Version +const std::string TelitRadio::KEY_FIRMWARE("firmware");            //!< Radio Firmware Version +const std::string TelitRadio::KEY_FIRMWARE_BUILD("firmwarebuild"); //!< Radio Firmware Build + +const std::string TelitRadio::KEY_CARRIER("carrier");   //!< Cellular Service Provider (Home Network) +const std::string TelitRadio::VALUE_CARRIER_VERIZON("Verizon"); +const std::string TelitRadio::VALUE_CARRIER_AERIS("Aeris"); +const std::string TelitRadio::VALUE_CARRIER_SPRINT("Sprint"); +const std::string TelitRadio::VALUE_CARRIER_USCELLULAR("U.S. Cellular"); +const std::string TelitRadio::VALUE_CARRIER_ATT("AT&T"); +const std::string TelitRadio::VALUE_CARRIER_TMOBILE("T-Mobile"); + +const std::string TelitRadio::KEY_IMEI("imei");          //!< International Mobile Station Equipment Identity +const std::string TelitRadio::KEY_MEID("meid");          //!< Mobile Equipment Identifier +const std::string TelitRadio::KEY_IMSI("imsi");          //!< International Mobile Subscriber Identity +const std::string TelitRadio::KEY_MSID("msid");          //!< Mobil Station ID / Mobile Identification Number (MSID/MIN) (CDMA-Only) +const std::string TelitRadio::KEY_MDN("mdn");            //!< Mobile Directory Number : Actual phone number dialed to reach radio +const std::string TelitRadio::KEY_ICCID("iccid");        //!< Integrated Circuit Card Identifier +const std::string TelitRadio::KEY_MSL("msl");            //!< Master Subsidy Lock + +//Dynamic Data +const std::string TelitRadio::KEY_ROAMING("roaming");    //!< Indicates whether or not using Home Network +const std::string TelitRadio::KEY_DATETIME("datetime");  //!< Date and Time from tower +const std::string TelitRadio::KEY_SERVICE("service");    //!< Service Connection Type [GPRS, EGPRS, WCDMA, HSDPA, 1xRTT, EVDO] +const std::string TelitRadio::KEY_NETWORK("network");    //!< Cellular Service Provider +const std::string TelitRadio::KEY_NETWORK_REG("netreg"); //!< Network Registration +const std::string TelitRadio::KEY_CID("cid");            //!< Cellular ID (Tower) in HEX +const std::string TelitRadio::KEY_LAC("lac");            //!< Location Area Code in HEX +const std::string TelitRadio::KEY_RAC("rac");            //!< Routing Area Code in HEX +const std::string TelitRadio::KEY_RSSI("rssi");          //!< Signal Strength +const std::string TelitRadio::KEY_RSSIDBM("rssidBm");    //!< Signal Strength in dBm +const std::string TelitRadio::KEY_MCC("mcc");            //!< Country Code +const std::string TelitRadio::KEY_MNC("mnc");            //!< Operator Code +const std::string TelitRadio::KEY_CHANNEL("channel");    //!< ARFCN or UARFCN Assigned Radio Channel +const std::string TelitRadio::KEY_TXPWR("txpwr");        //!< Transmit Power +const std::string TelitRadio::KEY_PSC("psc");            //!< Active Primary Synchronization Code (PSC) +const std::string TelitRadio::KEY_ECIO("ecio");          //!< Active Ec/Io (chip energy per total wideband power in dBm) +const std::string TelitRadio::KEY_RSCP("rscp");          //!< Active RSCP (Received Signal Code Power in dBm) +const std::string TelitRadio::KEY_DRX("drx");            //!< Discontinuous reception cycle length (ms) +const std::string TelitRadio::KEY_MM("mm");              //!< Mobility Management State +const std::string TelitRadio::KEY_RR("rr");              //!< Radio Resource State +const std::string TelitRadio::KEY_NOM("nom");            //!< Network Operator Mode +const std::string TelitRadio::KEY_ABND("abnd");          //!< Active Band +const std::string TelitRadio::KEY_BLER("bler");          //!< Block Error Rate (percentage) +const std::string TelitRadio::KEY_SD("sd");              //!< Service Domain +const std::string TelitRadio::KEY_DEBUG("debug");        //!< Debug Information + +const std::string TelitRadio::KEY_MIP("mipProfile");                      //!< Mobile IP Information +const std::string TelitRadio::KEY_MIP_ID("id");                           //!< Mobile IP ID +const std::string TelitRadio::KEY_MIP_ENABLED("enabled");                 //!< Mobile IP Enabled/Disabled +const std::string TelitRadio::KEY_MIP_NAI("nai");                         //!< Network Access Identifier +const std::string TelitRadio::KEY_MIP_HOMEADDRESS("homeAddress");         //!< Home Address +const std::string TelitRadio::KEY_MIP_PRIMARYHA("primaryAddress");        //!< Primary Home Agent +const std::string TelitRadio::KEY_MIP_SECONDARYHA("secondaryAddress");    //!< Secondary Home Agent +const std::string TelitRadio::KEY_MIP_MNAAASPI("mnAaaSpi");               //!< Mobile Node Authentication, Authorization, and Accounting Server Security Parameter Index +const std::string TelitRadio::KEY_MIP_MNHASPI("mnHaSpi");                 //!< Mobile Node Home Agent Security Server Parameter Index +const std::string TelitRadio::KEY_MIP_REVTUN("revTun");                   //!< Reverse Tunneling Enabled +const std::string TelitRadio::KEY_MIP_MNAAASS("mnAaaSs");                 //!< Mobile Node Authentication, Authorization, and Accounting Server Shared Secret +const std::string TelitRadio::KEY_MIP_MNHASS("mnHaSs");                   //!< Mobile Node Home Agent Shared Secret + +const std::string TelitRadio::VALUE_TYPE_GSM("GSM"); +const std::string TelitRadio::VALUE_TYPE_LTE("LTE"); +const std::string TelitRadio::VALUE_TYPE_CDMA("CDMA"); + +const std::string TelitRadio::VALUE_SD_NO_SERVICE("NO SERVICE"); +const std::string TelitRadio::VALUE_SD_CS_ONLY("CS ONLY"); +const std::string TelitRadio::VALUE_SD_PS_ONLY("PS ONLY"); +const std::string TelitRadio::VALUE_SD_CSPS("CS+PS"); + +const std::string TelitRadio::VALUE_ABND_GSM_850("GSM 850"); +const std::string TelitRadio::VALUE_ABND_GSM_900("GSM 900"); +const std::string TelitRadio::VALUE_ABND_DCS_1800("DCS 1800"); +const std::string TelitRadio::VALUE_ABND_PCS_1900("PCS 1900"); + +const std::vector<std::string> TelitRadio::DEFAULT_BAIL_STRINGS = { TelitRadio::RSP_OK, TelitRadio::RSP_ERROR }; + +TelitRadio::TelitRadio(const std::string& sName, const std::string& sRadioPort) +: m_sName(sName) +, m_sRadioPort(sRadioPort) +, m_bEchoEnabled(false) +, m_bEnableEchoOnClose(false) +{ +    m_apIo.reset(new MTS::IO::SerialConnection( +                             MTS::IO::SerialConnection::Builder(m_sRadioPort) +                                .baudRate(115200) +                                .useLockFile() +                                .build())); +} + + +TelitRadio::~TelitRadio() { +    shutdown(); +    m_apIo.reset(); +} + +bool TelitRadio::initialize(uint32_t iTimeoutMillis) { +    if(!m_apIo->open(iTimeoutMillis)) { +        printError("%s| Failed to open radio port [%s]", m_sName.c_str(), m_sRadioPort.c_str()); +        return false; +    } + +    bool bEnabled; +    CODE eCode = getEcho(bEnabled); +    if(eCode == SUCCESS && bEnabled) { +        printDebug("%s| Disabling 'echo'", m_sName.c_str()); +        setEcho(false); +        m_bEnableEchoOnClose = true; +    } + +    return true; +} + +bool TelitRadio::resetRadio(uint32_t iTimeoutMillis) { + +    printInfo("%s| Rebooting radio", m_sName.c_str()); +    if(sendBasicCommand("AT#REBOOT") == SUCCESS) { +        if(iTimeoutMillis > 5000) { +            MTS::Thread::sleep(5000); +            iTimeoutMillis -= 5000; +        } +        return resetConnection(iTimeoutMillis); +    } + +    return false; +} + +bool TelitRadio::resetConnection(uint32_t iTimeoutMillis) { +    //Close Current Connection +    if(!m_apIo.isNull()) { +        m_apIo->close(); +    } + +    m_apIo.reset(new MTS::IO::SerialConnection( +                     MTS::IO::SerialConnection::Builder(m_sRadioPort) +                        .baudRate(115200) +                        .useLockFile() +                        .build())); + +    //Try to obtain the device port over the given period of time +    MTS::Timer oTimer; +    oTimer.start(); +    uint64_t iCurrentTime = 0; +    while(iCurrentTime < iTimeoutMillis) { + +        if(!m_apIo->open(iTimeoutMillis - iCurrentTime)) { +            printWarning("%s| Failed to re-open radio port [%s]", m_sName.c_str(), m_sRadioPort.c_str()); +        } else { +            printInfo("%s| Successfully re-opened radio port [%s]", m_sName.c_str(), m_sRadioPort.c_str()); +            printDebug("%s| Recovering 'echo' after connection reset", m_sName.c_str()); // see TelitRadio::initialize +            setEcho(m_bEchoEnabled); +            break; +        } + +        ::usleep(500000); //500 millis +        iCurrentTime = oTimer.getMillis(); +    } +    oTimer.stop(); +    return !m_apIo->isClosed(); +} + +void TelitRadio::shutdown() { + +    if(!m_apIo.isNull()) { +        if(m_bEnableEchoOnClose) { +            printDebug("%s| Enabling 'echo'", m_sName.c_str()); +            setEcho(true); +            m_bEnableEchoOnClose = false; +        } +        m_apIo->close(); +    } +} + +const std::string& TelitRadio::getName() const { +    return m_sName; +} + + +TelitRadio::CODE TelitRadio::getModel(std::string& sModel) { +    printTrace("%s| Get Model", m_sName.c_str()); +    //Always returns SUCCESS because the model should be m_sName +    sModel = m_sName; +    std::string sCmd("ATI4"); +    std::string sResult = TelitRadio::sendCommand(m_apIo, sCmd); +    if (sResult.find("OK") == std::string::npos) { +        printWarning("%s| Unable to get model from radio.  Returning [%s]", m_sName.c_str(), m_sName.c_str()); +        return SUCCESS; +    } else { +        sModel = TelitRadio::extractModelFromResult(sResult); +        if(sModel.size() == 0) { +            printWarning("%s| Unable to get model from radio.  Returning [%s]", m_sName.c_str(), m_sName.c_str()); +            return SUCCESS; +        } +    } + +    printDebug("%s| Extracted [%s] from [%s] query", m_sName.c_str(), sModel.c_str(), sCmd.c_str()); +    if(sModel != m_sName) { +        printWarning("%s| Model identified [%s] does not match expected [%s]. Returning [%s]", +                     m_sName.c_str(),  sModel.c_str(), m_sName.c_str(), sModel.c_str()); +    } + +    return SUCCESS; +} + +TelitRadio::CODE TelitRadio::convertModelToMtsShortCode(const std::string& sModel, std::string& sCode, TelitRadio *radioObject) { +    CODE eCode = FAILURE; + +    if(sModel.find("HE910-D") == 0) { +        sCode = "H5"; +        eCode = SUCCESS; +    } else if (sModel.find("HE910-EUD") == 0) { +        sCode = "H6"; +        eCode = SUCCESS; +    } else if (sModel.find("LE910-JN1") == 0) { +        sCode = "LDC3"; +        eCode = SUCCESS; +    } else if (sModel.find("LE866A1-JS") == 0) { +        sCode = "LSB3"; +        eCode = SUCCESS; +    } else if (sModel.find("LE910-NAG") == 0) { +        sCode = "LAT1"; +        eCode = SUCCESS; +    } else if (sModel.find("LE910C4-NF") == 0) { +        sCode = "L4N1"; +        eCode = SUCCESS; +    } else if (sModel.find("LE910-NA1") == 0) { +        if (NULL == radioObject) { +            sCode = VALUE_NOT_SUPPORTED; +            eCode = ERROR; +        } else { +            std::string sValue; +            eCode = radioObject->getActiveFirmware(sValue); +            if (eCode == SUCCESS) { +                sCode = "LNA3"; +            } else { +                sCode = "LAT3"; +            } +        } +        eCode = SUCCESS; +    } else if (sModel.find("LE910-SVG") == 0) { +        sCode = "LVW2"; +        eCode = SUCCESS; +    } else if (sModel.find("LE910C1-NS") == 0) { +    	sCode = "LSP3"; +    	eCode = SUCCESS; +    } else if (sModel.find("LE910C1-AP") == 0) { +    	sCode = "LAP3"; +    	eCode = SUCCESS; +    } else if (sModel.find("ME910C1-NA") == 0) { +        sCode = "MAT1"; +        eCode = SUCCESS; +    } else if (sModel.find("ME910C1-NV") == 0) { +        sCode = "MVW1"; +        eCode = SUCCESS; +    } else if (sModel.find("ME910C1-WW") == 0) { +        sCode = "MNG2"; +        eCode = SUCCESS; +    } else if (sModel.find("LE910-EUG") == 0) { +        sCode = "LEU1"; +        eCode = SUCCESS; +    } else if (sModel.find("LE910C4-EU") == 0) { +        sCode = "L4E1"; +        eCode = SUCCESS; +    } else if (sModel.find("LE910-EU1") == 0) { +        sCode = "LEU3"; +        eCode = SUCCESS; +    } else if (sModel.find("GE910") == 0) { +        sCode = "G3"; +        eCode = SUCCESS; +    } else if (sModel.find("CE910") == 0) { +        sCode = "C2"; +        eCode = SUCCESS; +    } else if (sModel.find("DE910") == 0) { +        sCode = "EV3"; +        eCode = SUCCESS; +    } else { +        sCode = VALUE_NOT_SUPPORTED; +        printError("RADIO| Could not identify MTS short code from model. [%s]", sModel.c_str()); +        eCode = ERROR; +    } +    return eCode; +} + +TelitRadio::CODE TelitRadio::convertServiceDomainToString(SERVICEDOMAIN eSd, std::string& sSd) { +    CODE eCode = FAILURE; +    switch(eSd) { +        case NO_SERVICE: sSd = VALUE_SD_NO_SERVICE; eCode = SUCCESS; break; +        case CS_ONLY: sSd = VALUE_SD_CS_ONLY; eCode = SUCCESS; break; +        case PS_ONLY: sSd = VALUE_SD_PS_ONLY; eCode = SUCCESS; break; +        case CSPS: sSd = VALUE_SD_CSPS; eCode = SUCCESS; break; +        default: sSd = VALUE_UNKNOWN; eCode = FAILURE; break; +    } +    return eCode; +} + +TelitRadio::CODE TelitRadio::convertActiveBandToString(ACTIVEBAND eBand, std::string& sBand) { +    CODE eCode = FAILURE; +    switch(eBand) { +        case GSM_850: sBand = VALUE_ABND_GSM_850; eCode = SUCCESS; break; +        case GSM_900: sBand = VALUE_ABND_GSM_900; eCode = SUCCESS; break; +        case DCS_1800: sBand = VALUE_ABND_DCS_1800; eCode = SUCCESS; break; +        case PCS_1900: sBand = VALUE_ABND_PCS_1900; eCode = SUCCESS; break; +        default: sBand = VALUE_UNKNOWN; eCode = FAILURE; break; +    } +    return eCode; +} + +TelitRadio::CODE TelitRadio::convertModelToType(const std::string& sModel, std::string& sType) { +    CODE eCode = FAILURE; +    sType = VALUE_NOT_SUPPORTED; + +    if(sModel.find("HE910-D") == 0) { +        sType = VALUE_TYPE_GSM; +        eCode = SUCCESS; +    } else if (sModel.find("HE910-EUD") == 0) { +        sType = VALUE_TYPE_GSM; +        eCode = SUCCESS; +    } else if (sModel.find("LE910-JN1") == 0) { +        sType = VALUE_TYPE_LTE; +        eCode = SUCCESS; +    } else if (sModel.find("LE866A1-JS") == 0) { +        sType = VALUE_TYPE_LTE; +        eCode = SUCCESS; +    } else if (sModel.find("LE910-NAG") == 0) { +        sType = VALUE_TYPE_LTE; +        eCode = SUCCESS; +    } else if (sModel.find("LE910C4-NF") == 0) { +        sType = VALUE_TYPE_LTE; +        eCode = SUCCESS; +    } else if (sModel.find("LE910-NA1") == 0) { +        sType = VALUE_TYPE_LTE; +        eCode = SUCCESS; +    } else if (sModel.find("LE910-SVG") == 0) { +        sType = VALUE_TYPE_LTE; +        eCode = SUCCESS; +    } else if (sModel.find("LE910-EUG") == 0) { +        sType = VALUE_TYPE_LTE; +        eCode = SUCCESS; +    } else if (sModel.find("LE910C4-EU") == 0) { +        sType = VALUE_TYPE_LTE; +        eCode = SUCCESS; +    } else if (sModel.find("LE910-EU1") == 0) { +        sType = VALUE_TYPE_LTE; +        eCode = SUCCESS; +    } else if (sModel.find("LE910C1-NS") == 0) { +    	sType = VALUE_TYPE_LTE; +    	eCode = SUCCESS; +    } else if (sModel.find("LE910C1-AP") == 0) { +    	sType = VALUE_TYPE_LTE; +    	eCode = SUCCESS; +    } else if (sModel.find("ME910C1-NA") == 0) { +        sType = VALUE_TYPE_LTE; +        eCode = SUCCESS; +    } else if (sModel.find("ME910C1-NV") == 0) { +        sType = VALUE_TYPE_LTE; +        eCode = SUCCESS; +    } else if (sModel.find("ME910C1-WW") == 0) { +        sType = VALUE_TYPE_LTE; +        eCode = SUCCESS; +    } else if (sModel.find("GE910") == 0) { +        sType = VALUE_TYPE_GSM; +        eCode = SUCCESS; +    } else if (sModel.find("CE910") == 0) { +        sType = VALUE_TYPE_CDMA; +        eCode = SUCCESS; +    } else if (sModel.find("DE910") == 0) { +        sType = VALUE_TYPE_CDMA; +        eCode = SUCCESS; +    } else { +        sType = VALUE_TYPE_GSM; +        eCode = ERROR; +        printError("RADIO| Could not identify type from model. [%s].  Assuming [%s]", sModel.c_str(), sType.c_str()); +    } +    return eCode; +} + +TelitRadio::CODE TelitRadio::getFirmware(std::string& sFirmware) { +    printTrace("%s| Get Firmware", m_sName.c_str()); +    sFirmware = VALUE_NOT_SUPPORTED; +    std::string sCmd("AT+CGMR"); +    std::string sResult = TelitRadio::sendCommand(sCmd); +    size_t pos = sResult.find(RSP_OK); +    if (pos == std::string::npos) { +        printWarning("%s| Unable to get firmware from radio using command [%s]", m_sName.c_str(), sCmd.c_str()); +        return FAILURE; +    } + +    sFirmware = MTS::Text::trim(sResult.substr(0, pos)); +    if(sFirmware.size() == 0) { +        printWarning("%s| Unable to get firmware from radio using command [%s]", m_sName.c_str(), sCmd.c_str()); +        return FAILURE; +    } + +    m_sFirmware = sFirmware; + +    return SUCCESS; +} + +TelitRadio::CODE TelitRadio::getFirmwareBuild(std::string& sFirmwareBuild) { +    sFirmwareBuild = VALUE_NOT_SUPPORTED; +    return FAILURE; +} + +TelitRadio::CODE TelitRadio::getHardware(std::string& sHardware) { +    printTrace("%s| Get Hardware", m_sName.c_str()); +    sHardware = VALUE_NOT_SUPPORTED; + +    if(m_sFirmware.size() == 0) { +        getFirmware(m_sFirmware); +    } + +    if(getHardwareVersionFromFirmware(m_sFirmware, sHardware)) { +        return SUCCESS; +    } +    return FAILURE; +} + +TelitRadio::CODE TelitRadio::getManufacturer(std::string& sManufacturer) { +    printTrace("%s| Get Manufacturer", m_sName.c_str()); +    sManufacturer = VALUE_NOT_SUPPORTED; +    std::string sCmd("AT+GMI"); +    std::string sResult = TelitRadio::sendCommand(sCmd); +    size_t pos = sResult.find(RSP_OK); +    if (pos == std::string::npos) { +        printWarning("%s| Unable to get manufacturer from radio using command [%s]", m_sName.c_str(), sCmd.c_str()); +        return FAILURE; +    } + +    sManufacturer = MTS::Text::trim(sResult.substr(0, pos)); +    if(sManufacturer.size() == 0) { +        printWarning("%s| Unable to get manufacturer from radio using command [%s]", m_sName.c_str(), sCmd.c_str()); +        return FAILURE; +    } + +    return SUCCESS; +} + +TelitRadio::CODE TelitRadio::getImei(std::string& sImei) { +    printTrace("%s| Get IMEI", m_sName.c_str()); +    sImei = VALUE_NOT_SUPPORTED; +    std::string sCmd("AT+CGSN"); +    std::string sResult = TelitRadio::sendCommand(sCmd); +    size_t pos = sResult.find(RSP_OK); +    if (pos == std::string::npos) { +        printWarning("%s| Unable to get IMEI from radio using command [%s]", m_sName.c_str(), sCmd.c_str()); +        return FAILURE; +    } + +    sImei = MTS::Text::trim(sResult.substr(0, pos)); +    if(sImei.size() == 0) { +        printWarning("%s| Unable to get IMEI from radio using command [%s]", m_sName.c_str(), sCmd.c_str()); +        return FAILURE; +    } + +    return SUCCESS; +} + +TelitRadio::CODE TelitRadio::getMeid(std::string& sMeid) { +    printTrace("%s| Get MEID", m_sName.c_str()); +    return getImei(sMeid); +} + +TelitRadio::CODE TelitRadio::getImsi(std::string& sImsi) { +    printTrace("%s| Get IMSI", m_sName.c_str()); +    sImsi = VALUE_NOT_SUPPORTED; +    std::string sCmd("AT+CIMI"); +    std::string sResult = TelitRadio::sendCommand(sCmd); +    size_t pos = sResult.find(RSP_OK); +    if (pos == std::string::npos) { +        printWarning("%s| Unable to get IMSI from radio using command [%s]", m_sName.c_str(), sCmd.c_str()); +        return FAILURE; +    } + +    sImsi = MTS::Text::trim(sResult.substr(0, pos)); +    if(sImsi.size() == 0) { +        printWarning("%s| Unable to get IMSI from radio using command [%s]", m_sName.c_str(), sCmd.c_str()); +        return FAILURE; +    } + +    return SUCCESS; +} + +TelitRadio::CODE TelitRadio::getSimStatus(std::string& sSimStatus) { +    printTrace("%s| Get SIM Status", getName().c_str()); +    sSimStatus = VALUE_UNKNOWN; +    return FAILURE; +} + +TelitRadio::CODE TelitRadio::getIccid(std::string& sIccid) { +    printTrace("%s| Get ICCID", m_sName.c_str()); +    sIccid = VALUE_NOT_SUPPORTED; +    std::string sCmd("AT#CCID"); +    std::string sResult = TelitRadio::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]", m_sName.c_str(), sCmd.c_str()); +        return FAILURE; +    } + +    size_t start = sResult.find("#CCID:"); +    if(start != std::string::npos) { +        start += sizeof("#CCID:"); +        sIccid = MTS::Text::trim(sResult.substr(start, end-start)); +        if(sIccid.size() == 0) { +            printWarning("%s| Unable to get ICCID from radio using command [%s]", m_sName.c_str(), sCmd.c_str()); +            return FAILURE; +        } +    } +    return SUCCESS; +} + +TelitRadio::CODE TelitRadio::getService(std::string& sService) { +    printTrace("%s| Get Service", m_sName.c_str()); +    sService = VALUE_NOT_SUPPORTED; +    std::string sCmd("AT#PSNT?"); +    std::string sResult = TelitRadio::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]", m_sName.c_str(), sCmd.c_str()); +        return FAILURE; +    } + +    size_t start = sResult.find(","); +    if(start != std::string::npos) { +        start += 1; //comma +        std::string sPsnt = MTS::Text::trim(sResult.substr(start, end-start)); +        int32_t iService; +        sscanf(sPsnt.c_str(), "%d", &iService); + +        switch(iService) { +            case 0: sService = "GPRS"; break; +            case 1: sService = "EGPRS"; break; +            case 2: sService = "WCDMA"; break; +            case 3: sService = "HSDPA"; break; +            case 4: sService = "LTE"; break; +            default: sService = VALUE_UNKNOWN; break; +        } + +        printDebug("%s| Service ID: [%d][%s]", m_sName.c_str(), iService, sService.c_str()); +    } +    return SUCCESS; +} + +TelitRadio::CODE TelitRadio::getLac(std::string& sLac) { +    Json::Value jData; + +    printTrace("%s| Get LAC", m_sName.c_str()); +    sLac = VALUE_NOT_SUPPORTED; + +    if(getNetworkStatus(jData) == SUCCESS) { +        if(jData.isMember(KEY_LAC)) { +            sLac = jData[KEY_LAC].asString(); +            return SUCCESS; +        } +    } + +    return FAILURE; +} + +TelitRadio::CODE TelitRadio::getMdn(std::string& sMdn) { +    printTrace("%s| Get MDN", m_sName.c_str()); +    sMdn = VALUE_NOT_SUPPORTED; +    std::string sCmd("AT+CNUM"); +    std::string sResult = TelitRadio::sendCommand(sCmd); +    size_t end = sResult.find(RSP_OK); +    if (end == std::string::npos) { +        printWarning("%s| Unable to get MDN from radio using command [%s]", m_sName.c_str(), sCmd.c_str()); +        return FAILURE; +    } + +    size_t start = sResult.find("CNUM:"); +    if(start != std::string::npos) { +        start += sizeof("CNUM:"); +        std::vector<std::string> vParts = MTS::Text::split(sResult.substr(start, end - start), ','); +        if(vParts.size() < 3) { +            printWarning("%s| Unable to parse MDN from response [%s]", m_sName.c_str(), sResult.c_str()); +            return FAILURE; +        } +        sMdn = MTS::Text::strip(vParts[1], '"'); +        if(sMdn.size() == 0) { +            printWarning("%s| Unable to get MDN from radio using command [%s].  MDN may not be set.", m_sName.c_str(), sCmd.c_str()); +        } +    } else { +        sMdn = ""; +        printWarning("%s| Unable to get MDN from radio using command [%s].  MDN may not be set.", m_sName.c_str(), sCmd.c_str()); +    } + +    return SUCCESS; +} + +TelitRadio::CODE TelitRadio::getMsid(std::string& sMsid) { +    printTrace("%s| Get MSID", m_sName.c_str()); +    sMsid = ""; + +    std::string sImsi; +    if(getImsi(sImsi) == SUCCESS) { +        if(sImsi.size() >= 10) { +            sMsid = sImsi.substr(sImsi.size() - 10); +            printTrace("IMSI: [%s] MEID [%s]", sImsi.c_str(), sMsid.c_str()); +            return SUCCESS; +        } +    } +    printWarning("%s| Unable to get MSID from radio", m_sName.c_str()); +    return FAILURE; +} + +TelitRadio::CODE TelitRadio::getType(std::string& sType) { +    printTrace("%s| Get Type", m_sName.c_str()); +    sType = VALUE_NOT_SUPPORTED; +    return FAILURE; +} + +TelitRadio::CODE TelitRadio::getCarrier(std::string& sCarrier) { +    printTrace("%s| Get Carrier", m_sName.c_str()); +    if(m_sCarrier == "") { +        Json::Value jData; +        if(getNetworkStatus(jData) == SUCCESS) { +            if(jData.isMember(KEY_MCC) && jData.isMember(KEY_MNC)) { +                std::string sMcc = jData[KEY_MCC].asString(); +                std::string sMnc = jData[KEY_MNC].asString(); +                Json::Value jLookup = MccMncTable::getInstance()->lookup(sMcc, sMnc); +                printTrace("%s| MCC-MNC Lookup: [%s][%s][%s]", m_sName.c_str(), +                           sMcc.c_str(), sMnc.c_str(), jLookup.toStyledString().c_str()); +                if(jLookup.isMember(KEY_CARRIER)) { +                    m_sCarrier = jLookup[KEY_CARRIER].asString(); +                } else { +                    printWarning("%s| MCC-MNC Lookup did not contain carrier", m_sName.c_str()); +                    return FAILURE; +                } +            } else { +                printWarning("%s| Network Status did no contain MCC or MNC", m_sName.c_str()); +                return FAILURE; +            } +        } else { +            return FAILURE; +        } +    } + +    sCarrier = m_sCarrier; +    return SUCCESS; +} + +TelitRadio::CODE TelitRadio::getTower(std::string& sTower) { +    Json::Value jData; + +    printTrace("%s| Get Tower", m_sName.c_str()); +    sTower = VALUE_NOT_SUPPORTED; + +    if(getNetworkStatus(jData) == SUCCESS) { +        if(jData.isMember(KEY_CID)) { +            sTower = jData[KEY_CID].asString(); +            return SUCCESS; +        } +    } +    return FAILURE; +} + +TelitRadio::CODE TelitRadio::getTime(std::string& sDate, std::string& sTime, std::string& sTimeZone) { +    Json::Value jData; + +    printTrace("%s| Get Time", m_sName.c_str()); +    sDate = ""; +    sTime = ""; +    sTimeZone = ""; + +    std::string sCmd("AT+CCLK?"); +    std::string sResult = TelitRadio::sendCommand(sCmd); +    size_t end = sResult.find(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) { +        start += sizeof("CCLK: "); +        std::string sValue = MTS::Text::trim(sResult.substr(start, end - start)); +        sValue = MTS::Text::strip(sValue, '"'); + +        std::vector<std::string> vParts = MTS::Text::split(sValue, ','); +        if(vParts.size() != 2) { +            printWarning("%s| Unable to parse Date from response [%s]", m_sName.c_str(), sResult.c_str()); +            return FAILURE; +        } + + +        std::vector<std::string> 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()); +            return FAILURE; +        } + +        //The Date format is YY/MM/DD -> Change to MM/DD/YY +        sDate = vDateParts[1] + "/" + vDateParts[2] + "/" + vDateParts[0]; + +        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[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()); +            return FAILURE; +        } + +        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 +            iZonePartial *= -1; +            sPlusSign = ""; +        } +        std::stringstream ss; +        ss << sPlusSign << iZone; +        if(iZonePartial != 0) { +            ss << ":" << iZonePartial; +        } + +        sTimeZone = ss.str(); +        return SUCCESS; + +    } else { +        printWarning("%s| Unable to get Time from radio using command [%s]", m_sName.c_str(), sCmd.c_str()); +    } + +    return FAILURE; +} + +TelitRadio::CODE TelitRadio::getRoaming(bool& bRoaming) { +    Json::Value jData; + +    printTrace("%s| Get Roaming", m_sName.c_str()); +    bRoaming = false; + +    REGISTRATION eReg; +    if(getRegistration(eReg) == SUCCESS) { +        bRoaming = (eReg == ROAMING); +        return SUCCESS; +    } +    return FAILURE; +} + +TelitRadio::CODE TelitRadio::getNetwork(std::string& sNetwork) { +    Json::Value jData; + +    printTrace("%s| Get Network", m_sName.c_str()); +    sNetwork = VALUE_NOT_SUPPORTED; + +    if(getNetworkStatus(jData) == SUCCESS) { +        if(jData.isMember(KEY_NETWORK)) { +            sNetwork = jData[KEY_NETWORK].asString(); +            return SUCCESS; +        } +    } +    return FAILURE; +} + +TelitRadio::CODE TelitRadio::getSignalStrength(int32_t& rssi) { +    printTrace("%s| Get Signal Strength", m_sName.c_str()); +    std::string sCmd("AT+CSQ"); +    std::string sResult = sendCommand(sCmd); +    if (sResult.find("+CSQ: ") == std::string::npos) { +        printDebug("%s| Signal Strength command returned unexpected response: [%s]", m_sName.c_str(), sResult.c_str()); +        return FAILURE; +    } + +    size_t start = sResult.find(':'); +    size_t stop = sResult.find(',', start); +    if(start == std::string::npos || stop == std::string::npos) { +        printDebug("%s| Signal Strength command returned malformed response: [%s]", m_sName.c_str(), sResult.c_str()); +        return FAILURE; +    } +    std::string signal = sResult.substr(start + 2, stop - start - 2); + +    sscanf(signal.c_str(), "%d", &rssi); +    printDebug("%s| Signal Strength: [%d]", m_sName.c_str(), rssi); + +    return SUCCESS; +} + +TelitRadio::CODE TelitRadio::getModemLocation(std::string& sLocation) { +    printTrace("%s|TelitRadio getModemLocation - not supported", m_sName.c_str()); +    return FAILURE; +} + +TelitRadio::CODE TelitRadio::convertSignalStrengthTodBm(const int32_t& iRssi, int32_t& iDbm) { + +    //Telit Conversion +    if(iRssi < 0 || iRssi == 99) { +        return FAILURE; +    } + +    if(iRssi == 0) { +        iDbm = -113; +    } else if(iRssi == 1) { +        iDbm = -111; +    } else if(iRssi <= 30) { +        //28 steps between 2 and 30 +        //54 dbm between 53 and 109 +        float stepSize = 54.0 / 28.0; +        iDbm = -109 + (int)(stepSize * (iRssi-2)); +    } else { +        iDbm = -51; +    } + +    return SUCCESS; +} + +TelitRadio::CODE TelitRadio::convertdBmToSignalStrength(const int32_t& iDBm, int32_t& iRssi) { +    //Telit Conversion +    if(iDBm <= -113) { +        iRssi = 0; +    } else if(iDBm <= -111) { +        iRssi = 1; +    } else if(iDBm <= -53) { +        //54 dbm between -109 and -53 +        //28 steps between 2 and 30 +        float stepSize = 28.0/54.0; +        iRssi = ((iDBm + 109)*stepSize) + 2; +    } else { +        iRssi = 31; +    } + +    return SUCCESS; +} + +TelitRadio::CODE TelitRadio::getEcho(bool& bEnabled) { +    printTrace("%s| Echo Test", m_sName.c_str()); +    std::string sResult = sendCommand("AT"); +    if(sResult.size() == 0) { +        return NO_RESPONSE; +    } + +    if(sResult.find("AT") != std::string::npos) { +        bEnabled = true; +    } else { +        bEnabled = false; +    } +    m_bEchoEnabled = bEnabled; +    return SUCCESS; +} + +TelitRadio::CODE TelitRadio::setEcho(bool bEnabled) { +    CODE eCode = FAILURE; +    if(bEnabled) { +        eCode = sendBasicCommand("ATE1"); +        m_bEchoEnabled = (eCode == SUCCESS ) ? true : m_bEchoEnabled; +    } else { +        eCode = sendBasicCommand("ATE0"); +        m_bEchoEnabled = (eCode == SUCCESS ) ? false : m_bEchoEnabled; +    } + +    return eCode; +} + +TelitRadio::CODE TelitRadio::getStaticInformation(Json::Value& jData) { +    printTrace("%s| Get Static Information", m_sName.c_str()); + +    printTrace("%s| Static Information:\n%s\n", m_sName.c_str(), jData.toStyledString().c_str()); + +    return FAILURE; +} + +/*  AT#RFSTS - NETWORK STATUS + +    (GSM network) +    #RFSTS:<PLMN>,<ARFCN>,<RSSI>,<LAC>,<RAC>,<TXPWR>,<MM>,<RR>,<NOM>,<CID>,<IMSI>,<NetNameAsc>,<SD>,<ABND> +    Where: +    <PLMN> - Country code and operator code(MCC, MNC) +    <ARFCN> - GSM Assigned Radio Channel +    <RSSI> - Received Signal Strength Indication +    <LAC> - Localization Area Code +    <RAC> - Routing Area Code +    <TXPWR> - Tx Power +    <MM> - Mobility Management state +    <RR> - Radio Resource state +    <NOM> - Network Operator Mode +    <CID> - Cell ID +    <IMSI> - International Mobile Subscriber Identity +    <NetNameAsc> - Operator name +    <SD> - Service Domain +    0 - No Service +    1 - CS only +    2 - PS only +    3 - CS+PS +    <ABND> - Active Band +    1 - GSM 850 +    2 - GSM 900 +    3 - DCS 1800 +    4 - PCS 1900 + + +    (WCDMA network) +    #RFSTS: +    <PLMN>,<UARFCN>,<PSC>,<Ec/Io>,<RSCP>, RSSI>,<LAC>,<RAC>,<TXPWR>,<DRX>,<MM>,<RRC>,<NOM>,<BLER>,<CID>,<IMSI>, +    <NetNameAsc>,<SD>,<nAST>[,<nUARFCN><nPSC>,<nEc/Io>] +    Where: +    <PLMN> - Country code and operator code(MCC, MNC) +    <UARFCN> - UMTS Assigned Radio Channel +    <PSC> - Active PSC(Primary Synchronization Code) +    <Ec/Io> - Active Ec/Io(chip energy per total wideband power in dBm) +    <RSCP> - Active RSCP (Received Signal Code Power in dBm) +    <RSSI> - Received Signal Strength Indication +    <LAC> - Localization Area Code +    <RAC> - Routing Area Code +    <TXPWR> - Tx Power +    <DRX> - Discontinuous reception cycle Length (cycle length in ms) +    <MM> - Mobility Management state +    <RR> - Radio Resource state +    <NOM> - Network Operator Mode +    <BLER> - Block Error Rate (e.g., 005 means 0.5 %) +    <CID> - Cell ID +    <IMSI> - International Mobile Station ID +    <NetNameAsc> - Operator name +    <SD> - Service Domain (see above) +    <nAST> - Number of Active Set (Maximum 6) +    <nUARFCN> UARFCN of n th active set +    <nPSC> PSC of n th active set +    <nEc/Io > Ec/Io of n th active Set + +    (LTE Network) +    #RFSTS: +    <PLMN> - +    <EARFCN> - +    <RSRP> - +    <RSSI> - +    <RSRQ> - +    <TAC> - +    [<TXPWR>] - +    <DRX> - +    <MM> - +    <RRC> - +    <CID> - +    <IMSI> - +    [<NetNameAsc>] - +    <SD> - +    <ABND> - +*/ +TelitRadio::CODE TelitRadio::getNetworkStatus(Json::Value& jData) { +    int32_t iValue; +    std::string sValue; +    const uint32_t GSM_NETWORK_FORMAT = 14; +    const uint32_t WCDMA_NETWORK_FORMAT = 19; +    const uint32_t LTE_NETWORK_FORMAT = 16; + +    printTrace("%s| Get Network Status", m_sName.c_str()); + +    //Always get common network stats because this should never fail +    //This way the basic stats are always returned even if AT#RFSTS fails below +    getCommonNetworkStats(jData); + +    std::string sCmd; +    std::string sResult; +    // LE910 radios have a bug where issuing AT#RFSTS with a locked SIM +    // will cause the radio to stop responding until a radio power cycle +    // Telit Support Portal Case #5069697 +    // LE910C1-NS is an LE910, so we stop the scan after the 0. +    if (m_sName.find("LE910") != std::string::npos) { +        sCmd = "AT+CPIN?"; +        sResult = sendCommand(sCmd); +        if (sResult.find("+CPIN:") == std::string::npos) { +            printDebug("%s| AT+CPIN? returned unexpected response: [%s][%s]", m_sName.c_str(), sCmd.c_str(), sResult.c_str()); +            printTrace("%s| Network Status:\n%s\n", m_sName.c_str(), jData.toStyledString().c_str()); +            return SUCCESS; //return SUCCESS because getCommonNetworkStats() succeeded at top of this function +        } +        if (sResult.find("SIM PIN") != std::string::npos) { +            printError("%s| The SIM is locked and must first be unlocked", m_sName.c_str()); +            printTrace("%s| Network Status:\n%s\n", m_sName.c_str(), jData.toStyledString().c_str()); +            return SUCCESS; //return SUCCESS because getCommonNetworkStats() succeeded at top of this function +        } +    } + +    sCmd = "AT#RFSTS"; +    sResult = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, 200); +    if (sResult.find("#RFSTS:") == std::string::npos) { +        //On LTE radios without signal, this case will run because AT#RFSTS just returns "OK" +        printDebug("%s| Network Status command returned unexpected response: [%s][%s]", m_sName.c_str(), sCmd.c_str(), sResult.c_str()); +        printTrace("%s| Network Status:\n%s\n", m_sName.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 "#RFSTS:" +    std::vector<std::string> vParts = MTS::Text::split(MTS::Text::trim(sResult.substr(start)), ","); + +    if (vParts.size() < 3) { +        printDebug("%s| Network Status command reponse is an unknown format: [%s][%s]", m_sName.c_str(), sCmd.c_str(), sResult.c_str()); +        printTrace("%s| Network Status:\n%s\n", m_sName.c_str(), jData.toStyledString().c_str()); +        return SUCCESS; //return SUCCESS because getCommonNetworkStats() succeeded at top of this function +    } else { +        //Country Code and Operator Code +        std::vector<std::string> vPLMN = MTS::Text::split(vParts[0], ' '); +        if(vPLMN.size() == 2) { +            jData[KEY_MCC] = MTS::Text::strip(vPLMN[0], '"'); +            jData[KEY_MNC] = MTS::Text::strip(vPLMN[1], '"'); +        } + +        jData[KEY_CHANNEL] = vParts[1]; +    } + +    if (vParts.size() == GSM_NETWORK_FORMAT ) { +        //Parse as GSM Network Format +        jData[KEY_RSSIDBM] = vParts[2]; +        jData[KEY_LAC] =  vParts[3]; +        jData[KEY_RAC] = vParts[4]; +        jData[KEY_TXPWR] = vParts[5]; +        jData[KEY_MM] = vParts[6]; +        jData[KEY_RR] = vParts[7]; +        jData[KEY_NOM] = vParts[8]; +        jData[KEY_CID] = vParts[9]; +        jData[KEY_IMSI] = MTS::Text::strip(vParts[10], '"'); +        jData[KEY_NETWORK] = MTS::Text::strip(vParts[11], '"'); +        if(MTS::Text::parse(iValue, vParts[12]) && convertServiceDomainToString((SERVICEDOMAIN)iValue, sValue) == SUCCESS) { +            jData[KEY_SD] = sValue; +        } +        if(MTS::Text::parse(iValue, vParts[13]) && convertActiveBandToString((ACTIVEBAND)iValue, sValue) == SUCCESS) { +            jData[KEY_ABND] = sValue; +        } +      // IN003567 ME910C1 radios have some odd behavior with regards to WCDMA.  The ordering of the fields from #RFSTS are +      // the same as LTE up to the 16th field (for ME901C1-WW anyway).  Drop into LTE parsing for ME910C1-WW. +    } else if((vParts.size() >= WCDMA_NETWORK_FORMAT) && (m_sName.find("ME910C1-WW") == std::string::npos)) { +        Json::Value jDebug; + +        //Parse as WCDMA Network Format + +        jDebug[KEY_PSC] = vParts[2]; +        jDebug[KEY_ECIO] = vParts[3]; +        jDebug[KEY_RSCP] = vParts[4]; + +        jData[KEY_RSSIDBM] = vParts[5]; +        jData[KEY_LAC] = vParts[6]; +        jData[KEY_RAC] = vParts[7]; + +        jDebug[KEY_TXPWR] = vParts[8]; +        jDebug[KEY_DRX] = vParts[9]; +        jDebug[KEY_MM] = vParts[10]; +        jDebug[KEY_RR] = vParts[11]; +        jDebug[KEY_NOM] = vParts[12]; + +        if(vParts[13].size() != 0) { +            jDebug[KEY_BLER] = vParts[13]; +        } else { +            jDebug[KEY_BLER] = "000"; +        } + +        jData[KEY_CID] = vParts[14]; +        jData[KEY_IMSI] = MTS::Text::strip(vParts[15], '"'); +        jData[KEY_NETWORK] = MTS::Text::strip(vParts[16], '"'); + +        // Get the radio band given the channel (UARFCN) +        RadioBandMap radioBandMap(vParts[1], TelitRadio::VALUE_TYPE_CDMA); +        jData[KEY_ABND] = radioBandMap.getRadioBandName(); + +        if(MTS::Text::parse(iValue, vParts[17]) && convertServiceDomainToString((SERVICEDOMAIN)iValue, sValue) == SUCCESS) { +            jDebug[KEY_SD] = sValue; +        } +        //Ignoring Active Set Values +        //  <nAST> - Number of Active Set (Maximum 6) +        //  <nUARFCN> - UARFCN of n th active set +        //  <nPSC> - PSC of n th active set +        //  <nEc/Io > - Ec/Io of n th active Set + +        jData[KEY_DEBUG] = jDebug; +    } else if(vParts.size() >= LTE_NETWORK_FORMAT) { +        Json::Value jDebug; + +        //Parse as LTE Network Format + +        // +        // MD: It is noticed that LTE Network format may vary depending on the firmware version: +        // +        // <PLMN>,<EARFCN>,<RSRP>,<RSSI>,<RSRQ>,<TAC>,[<TXPWR>],<DRX>,<MM>,<RRC>,<CID>,<IMSI>,[<NetNameAsc>],<SD>,<ABND>,<SINR> +        //    Ex 1: #RFSTS: "310 260",2300,-98,-63,-14,AA06,,128,19,0,0501D02,"310260754792598","T-Mobile",3,4,197 +        // +        // <PLMN>,<EARFCN>,<RSRP>,<RSSI>,<RSRQ>,<TAC>,<RAC>,[<TXPWR>],<DRX>,<MM>,<RRC>,<CID>,<IMSI>,[<NetNameAsc>],<SD>,<ABND> +        //    Ex 2: #RFSTS:"310 410",5780,-105,-73,-14,4603,255,,128,19,0,0000098,"310410536498694","AT&T",3,17 +        //          #RFSTS:"311 480",1150,-96,-66,-9.0,bf35,FF,0,0,19,1,"2ED1B0E","311480148817753","Verizon",2,2,720000,10800 +        //          #RFSTS:"310 410",2175,-120,-89,-17.5,4612,FF,0,0,19,1,"4E5E916","310410807276607","AT&T",3,4 +        // +        // Additional <RAC> parameter in the second example shifts the rest of the parameters. Here we are trying to figure out +        // which format is currently produced based on <NetNameAsc> field position which always has double quotation marks. +        // +        if (vParts[13].find("\"") != std::string::npos) { +            // parse the RAC and then remove it from the vector +            jData[KEY_RAC] = vParts[6]; +            vParts.erase(vParts.begin() + 6); +        } + +        jDebug["rsrp"] = vParts[2]; +        jDebug[KEY_RSSIDBM] = vParts[3]; +        jDebug["rsrq"] = vParts[4]; + +        jData["tac"] = vParts[5]; +        jDebug[KEY_TXPWR] = vParts[6]; +        jData[KEY_DRX] = vParts[7]; +        jDebug[KEY_MM] = vParts[8]; +        jDebug["rrc"] = vParts[9]; +        jData[KEY_CID] = MTS::Text::strip(vParts[10], '"'); +        jData[KEY_IMSI] = MTS::Text::strip(vParts[11], '"'); +        jData[KEY_NETWORK] = MTS::Text::strip(vParts[12], '"'); + +        // Get the radio band given the channel (EARFCN) +        RadioBandMap radioBandMap(vParts[1], TelitRadio::VALUE_TYPE_LTE); +        jData[KEY_ABND] = radioBandMap.getRadioBandName(); + +        jData[KEY_LAC] = queryLteLac(); + +        if(MTS::Text::parse(iValue, vParts[13]) && convertServiceDomainToString((SERVICEDOMAIN)iValue, sValue) == SUCCESS) { +            jDebug[KEY_SD] = sValue; +        } + +        jData[KEY_DEBUG] = jDebug; +    } + +    printTrace("%s| Network Status:\n%s\n", m_sName.c_str(), jData.toStyledString().c_str()); +    return SUCCESS; +} + +// Get the LAC for the LTE radio that's not in the #RFSTS response +std::string TelitRadio::queryLteLac() { +    std::string CGREGstring; +    std::string originalCGREG; +    std::string result; + +    CGREGstring = queryCGREGstring(); +    if (CGREGstring == RSP_ERROR) { +        originalCGREG = "0"; +    } else { +        originalCGREG = CGREGstring.at(CGREGstring.find(",") - 1); //Position right before first comma ("+CGREG: 0,1") +    } + +    // Temporarily set CGREG=2 to get more info +    setCGREG("2"); + +    CGREGstring = queryCGREGstring(); +    if (CGREGstring == RSP_ERROR) { +        result = TelitRadio::VALUE_UNKNOWN; +    } else { +        size_t start = CGREGstring.find(":") + 1; //Position right after "#RFSTS:" +        std::vector<std::string> vParts = MTS::Text::split(MTS::Text::trim(CGREGstring.substr(start)), ","); +        if(vParts.size() < 3) { +            result = TelitRadio::VALUE_UNAVAILABLE; +        } else { +            result = MTS::Text::strip(vParts[2], '"'); +        } +    } + +    setCGREG(originalCGREG); + +    return result; +} + +void TelitRadio::setCGREG(std::string value) { +    std::string sCmd("AT+CGREG=" + value); +    std::string cmdResult(sendCommand(sCmd)); +    if (cmdResult.find("OK") == std::string::npos) { +        printDebug("%s| AT#CGREG=%s returned unexpected response: [%s][%s]", m_sName.c_str(), value.c_str(), sCmd.c_str(), cmdResult.c_str()); +    } +} + +std::string TelitRadio::queryCGREGstring() { +    std::string sCmd("AT+CGREG?"); +    std::string cmdResult(sendCommand(sCmd)); +    if (cmdResult.find("+CGREG:") == std::string::npos) { +        printDebug("%s| AT#CGREG? returned unexpected response: [%s][%s]", m_sName.c_str(), sCmd.c_str(), cmdResult.c_str()); +        return RSP_ERROR; +    } +    return cmdResult; +} + +void TelitRadio::getCommonNetworkStats(Json::Value& jData) { + +    bool bRoaming = false; +    if(getRoaming(bRoaming) == SUCCESS) { +        jData[KEY_ROAMING] = bRoaming; +    } + +    int32_t iRssi; +    if(getSignalStrength(iRssi) == SUCCESS) { +        jData[KEY_RSSI] = iRssi; +        int32_t dBm; +        if(!jData.isMember(KEY_RSSIDBM) && convertSignalStrengthTodBm(iRssi, dBm) == SUCCESS) { +            //Add RSSI in dBm format +            jData[KEY_RSSIDBM] = MTS::Text::format(dBm); +        } +    } + +    std::string sService; +    if(getService(sService) == SUCCESS) { +        jData[KEY_SERVICE] = sService; +    } +    std::string sDate, sTime, sTimeZone; +    if(getTime(sDate, sTime, sTimeZone) == SUCCESS) { +        jData[KEY_DATETIME] = sDate + " " + sTime + " GMT" + sTimeZone; +    } + +    std::string sNetworkReg; +    TelitRadio::REGISTRATION eReg; +    if (getRegistration(eReg) == SUCCESS) { +        if (convertRegistrationToString(eReg, sNetworkReg) == SUCCESS) { +            jData[TelitRadio::KEY_NETWORK_REG] = sNetworkReg; +        } +    } +} + +void TelitRadio::initMipProfile(Json::Value& jData) { +    jData[KEY_MIP_ID] = 0; +    jData[KEY_MIP_ENABLED] = false; +    jData[KEY_MIP_NAI] = VALUE_UNKNOWN; +    jData[KEY_MIP_HOMEADDRESS] = VALUE_UNKNOWN; +    jData[KEY_MIP_PRIMARYHA] = VALUE_UNKNOWN; +    jData[KEY_MIP_SECONDARYHA] = VALUE_UNKNOWN; +    jData[KEY_MIP_MNAAASPI] = VALUE_UNKNOWN; +    jData[KEY_MIP_MNHASPI] = VALUE_UNKNOWN; +    jData[KEY_MIP_MNAAASS] = false; +    jData[KEY_MIP_MNHASS] = false; +} + +TelitRadio::CODE TelitRadio::getRegistration(REGISTRATION& eRegistration) { +    std::string sCmd; +    std::string sResp; + +    // LE910C1-NS is an LE910, so we stop the scan after the 0. +    if (m_sName.find("LE910") != std::string::npos) { +        // use AT+CGREG instead for LE910 models +        sCmd = "AT+CGREG?"; +        sResp = "+CGREG: "; +    } +    else { +        sCmd = "AT+CREG?"; +        sResp = "+CREG: "; +    } + +    std::string sResult = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, 5000); +    if (sResult.find(sResp) == std::string::npos) { +        if(sResult.size() == 0) { +            printDebug("%s| Registration command returned no response: [%s]", m_sName.c_str()); +            return NO_RESPONSE; +        } +        printDebug("%s| Registration command returned unexpected response: [%s]", m_sName.c_str(), sResult.c_str()); +        return FAILURE; +    } + +    size_t start = sResult.find(','); +    size_t stop = sResult.find(' ', start); +    std::string sRegStat = sResult.substr(start + 1, stop - start - 1); +    int32_t value; +    sscanf(sRegStat.c_str(), "%d", &value); +    eRegistration = (REGISTRATION)value; +    return SUCCESS; +} + +TelitRadio::CODE TelitRadio::convertRegistrationToString(REGISTRATION eRegistration, std::string& sRegistration) { + +    CODE eCode = FAILURE; +    switch (eRegistration) { +        case NOT_REGISTERED: sRegistration = VALUE_NOT_REGISTERED; eCode = SUCCESS; break; +        case REGISTERED: sRegistration = VALUE_REGISTERED; eCode = SUCCESS; break; +        case SEARCHING: sRegistration = VALUE_SEARCHING; eCode = SUCCESS; break; +        case DENIED: sRegistration = VALUE_DENIED; eCode = SUCCESS; break; +        case UNKNOWN: sRegistration = VALUE_UNKNOWN; eCode = SUCCESS; break; +        case ROAMING: sRegistration = VALUE_ROAMING; eCode = SUCCESS; break; +    } +    return eCode; +} + +TelitRadio::CODE TelitRadio::validateMsl(const Json::Value& jArgs) { +    printTrace("%s| Validate MSL", m_sName.c_str()); + +    return NOT_APPLICABLE; +} + +TelitRadio::CODE TelitRadio::setMdn(const Json::Value& jArgs) { +    printTrace("%s| Set MDN", m_sName.c_str()); + +    if(!jArgs["mdn"].isString()) { +        return INVALID_ARGS; +    } + +    std::string sCmd("AT#SNUM=1,\""); +    sCmd += jArgs["mdn"].asString() + "\""; + +    std::string sResult = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, 1000); +    size_t end = sResult.find(RSP_OK); +    if (end == std::string::npos) { +        printWarning("%s| Unable to set MDN for radio using command [%s]", m_sName.c_str(), sCmd.c_str()); +        return FAILURE; +    } + +    return SUCCESS; +} + +TelitRadio::CODE TelitRadio::setMsid(const Json::Value& jArgs) { +    printTrace("%s| Set MSID", m_sName.c_str()); + +    return NOT_APPLICABLE; +} + +TelitRadio::CODE TelitRadio::getMipProfile(Json::Value& jMipProfile) { +    printTrace("%s| Get MIP Active Profile", m_sName.c_str()); + +    return NOT_APPLICABLE; +} + +TelitRadio::CODE TelitRadio::setMipActiveProfile(const Json::Value& jArgs) { +    printTrace("%s| Set MIP Active Profile", m_sName.c_str()); + +    return NOT_APPLICABLE; +} + +TelitRadio::CODE TelitRadio::setMipNai(const Json::Value& jArgs) { +    printTrace("%s| Set MIP NAI", m_sName.c_str()); + +    return NOT_APPLICABLE; +} + +TelitRadio::CODE TelitRadio::setMipHomeIp(const Json::Value& jArgs) { +    printTrace("%s| Set MIP Home IP", m_sName.c_str()); + +    return NOT_APPLICABLE; +} + +TelitRadio::CODE TelitRadio::setMipPrimaryHa(const Json::Value& jArgs) { +    printTrace("%s| Set MIP Primary HA", m_sName.c_str()); + +    return NOT_APPLICABLE; +} + +TelitRadio::CODE TelitRadio::setMipSecondaryHa(const Json::Value& jArgs) { +    printTrace("%s| Set MIP Secondary HA", m_sName.c_str()); + +    return NOT_APPLICABLE; +} + +TelitRadio::CODE TelitRadio::setMipMnAaaSpi(const Json::Value& jArgs) { +    printTrace("%s| Set MIP MN-AAA SPI", m_sName.c_str()); + +    return NOT_APPLICABLE; +} + +TelitRadio::CODE TelitRadio::setMipMnHaSpi(const Json::Value& jArgs) { +    printTrace("%s| Set MIP MN-HA SPI", m_sName.c_str()); + +    return NOT_APPLICABLE; +} + +TelitRadio::CODE TelitRadio::setMipRevTun(const Json::Value& jArgs) { +    printTrace("%s| Set MIP Rev Tun", m_sName.c_str()); + +    return NOT_APPLICABLE; +} + +TelitRadio::CODE TelitRadio::setMipMnAaaSs(const Json::Value& jArgs) { +    printTrace("%s| Set MIP MN-AAA SS", m_sName.c_str()); + +    return NOT_APPLICABLE; +} + +TelitRadio::CODE TelitRadio::setMipMnHaSs(const Json::Value& jArgs) { +    printTrace("%s| Set MIP MN-HA SS", m_sName.c_str()); + +    return NOT_APPLICABLE; +} + +TelitRadio::CODE TelitRadio::updateDc(const Json::Value& jArgs, UpdateCb& stepCb) { +    printTrace("%s| Update Device Configuration", m_sName.c_str()); + +    return NOT_APPLICABLE; +} + +TelitRadio::CODE TelitRadio::updatePrl(const Json::Value& jArgs, UpdateCb& stepCb) { +    printTrace("%s| Update Preferred Roaming List", m_sName.c_str()); + +    return NOT_APPLICABLE; +} + +TelitRadio::CODE TelitRadio::updateFumo(const Json::Value& jArgs, UpdateCb& stepCb) { +    printTrace("%s| Update Firmware Update Management Object", m_sName.c_str()); + +    return NOT_APPLICABLE; +} + +TelitRadio::CODE TelitRadio::resetHfa(const Json::Value& jArgs, UpdateCb& stepCb) { +    printTrace("%s| HFA Reset", m_sName.c_str()); + +    return NOT_APPLICABLE; +} + +TelitRadio::CODE TelitRadio::activate(const Json::Value& jArgs, UpdateCb& stepCb) { +    printTrace("%s| Activation", m_sName.c_str()); + +    return NOT_APPLICABLE; +} + +TelitRadio::CODE TelitRadio::setActiveFirmware(const Json::Value& jArgs) { +    printTrace("%s| Set Active Firmware Image Number: not applicable", m_sName.c_str()); + +    return NOT_APPLICABLE; +} + +TelitRadio::CODE TelitRadio::getActiveFirmware(std::string& sFwId) { +    printTrace("%s| Get Active Firmware Image Number: not applicable", m_sName.c_str()); +    sFwId = VALUE_NOT_SUPPORTED; + +    return NOT_APPLICABLE; +} + +TelitRadio::CODE TelitRadio::sendBasicCommand(const std::string& sCmd, int32_t iTimeoutMillis, const char& ESC) { +    std::string response = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, iTimeoutMillis, ESC); +    if (response.size() == 0) { +        return NO_RESPONSE; +    } else if (response.find(RSP_OK) != std::string::npos) { +        return SUCCESS; +    } else if (response.find(RSP_ERROR) != std::string::npos) { +        return ERROR; +    } else { +        return FAILURE; +    } +} + +std::string TelitRadio::sendCommand(const std::string& sCmd, const std::vector<std::string>& vBail, int32_t timeoutMillis, const char& ESC) { +    return sendCommand(m_apIo, sCmd, vBail, timeoutMillis, ESC); +} + +std::string TelitRadio::sendCommand(MTS::AutoPtr<MTS::IO::Connection>& apIo, const std::string& sCmd, +                                       const std::vector<std::string>& vBail, int32_t timeoutMillis, const char& ESC) { +    IsNeedMoreData isNeedMoreData = [&vBail](const std::string& iterationData, const std::string& allData)->bool { +        for(size_t i = 0; i < vBail.size(); i++) { +            const std::string& sBail = vBail[i]; +            if(sBail.size() > 0) { +                if(allData.find(sBail) != std::string::npos) { +                    //Return when bail string is found +                    printTrace("RADIO| Found bail string [%s]", sBail.c_str()); +                    return false; +                } +            } +        } +        return true; +    }; + +    return sendCommand(apIo, sCmd, isNeedMoreData, timeoutMillis, ESC); +} + +std::string TelitRadio::sendCommand(const std::string& sCmd, MTS::IO::TelitRadio::IsNeedMoreData& isNeedMoreData, int32_t timeoutMillis, const char& ESC) { +    return sendCommand(m_apIo, sCmd, isNeedMoreData, timeoutMillis, ESC); +} + +std::string TelitRadio::sendCommand(MTS::AutoPtr<MTS::IO::Connection>& apIo, const std::string& sCmd, +                                       IsNeedMoreData& isNeedMoreData, int32_t timeoutMillis, const char& ESC) { +    if(MTS::Logger::getPrintLevel() >= MTS::Logger::PrintLevel::TRACE_LEVEL) { +        printTrace("RADIO| Sending command [%s]", sCmd.c_str()); +    } +    if(apIo.isNull()) { +        printError("RADIO| IO is not set in sendCommand"); +        return ""; +    } + +    int32_t iResult; +    if(ESC == 0x00) { +        iResult = apIo->write(sCmd.data(), sCmd.size()); +    } else { +        std::string sNewCmd(sCmd); +        sNewCmd.push_back(ESC); +        iResult = apIo->write(sNewCmd.data(), sNewCmd.size()); +    } + +    if(iResult == -1) { +        printError("RADIO| Failed to send command to radio"); +        return ""; +    } + +    bool done = false; +    const uint32_t capacity = 1024; +    char buffer[capacity]; +    std::string sResult; +    Timer timer; +    timer.start(); +    do { +        int32_t iterationTimeout = 100; +        int bytesRead = apIo->read((char*)buffer, capacity, iterationTimeout); +        if(bytesRead == -1) { +            printError("RADIO| Failed to read from radio"); +            break; +        } + +        std::string sIteration((char*)buffer, bytesRead); +        sResult += sIteration; + +        if(isNeedMoreData && !isNeedMoreData(sIteration, sResult)) { +            printTrace("RADIO| No more data needed"); +            return sResult; +        } +        if(timeoutMillis >= 0) { +            done = (timer.getMillis() >= (uint64_t)timeoutMillis); +        } else { +            //Do not stop looping until bail string is found +        } +    } while(!done); + +    //Timed out +    return sResult; +} + +TelitRadio::CODE TelitRadio::test(MTS::AutoPtr<MTS::IO::Connection>& apIo, uint32_t timeoutSeconds) { +    printTrace("RADIO| Basic Test"); +    uint32_t count = 0; +    std::string sCmd("AT"); +    do { +        std::string sResult = sendCommand(apIo, sCmd); +        if (sResult.find(RSP_OK) == std::string::npos) { +            printTrace("RADIO| Waiting for basic radio communication [%s] ...", sResult.c_str()); +        } else { +            break; +        } +        count++; +    } while (count < timeoutSeconds); + +    if(count == timeoutSeconds) { +        printWarning("RADIO| Basic radio communication FAILED"); +        return NO_RESPONSE; +    } +    return SUCCESS; +} + +std::string TelitRadio::extractModelFromResult(const std::string& sResult) { +    std::string sModel(TelitRadio::VALUE_NOT_SUPPORTED); + +    if(sResult.find("HE910-D") != std::string::npos) { +        sModel = "HE910-D"; +    } else if(sResult.find("HE910-EUD") != std::string::npos) { +        sModel = "HE910-EUD"; +    } else if(sResult.find("LE910-JN1") != std::string::npos) { +        sModel = "LE910-JN1"; +    } else if(sResult.find("LE866A1-JS") != std::string::npos) { +        sModel = "LE866A1-JS"; +    } else if(sResult.find("LE910-NAG") != std::string::npos) { +        sModel = "LE910-NAG"; +    } else if(sResult.find("LE910C4-NF") != std::string::npos) { +        sModel = "LE910C4-NF"; +    } else if(sResult.find("LE910-NA1") != std::string::npos) { +        sModel = "LE910-NA1"; +    } else if(sResult.find("ME910C1-NA") != std::string::npos) { +        sModel = "ME910C1-NA"; +    } else if(sResult.find("ME910C1-NV") != std::string::npos) { +        sModel = "ME910C1-NV"; +    } else if(sResult.find("ME910C1-WW") != std::string::npos) { +        sModel = "ME910C1-WW"; +    } else if(sResult.find("LE910-SVG") != std::string::npos) { +        sModel = "LE910-SVG"; +    } else if(sResult.find("LE910-EUG") != std::string::npos) { +        sModel = "LE910-EUG"; +    } else if(sResult.find("LE910C4-EU") != std::string::npos) { +        sModel = "LE910C4-EU"; +    } else if(sResult.find("LE910-EU1") != std::string::npos) { +        sModel = "LE910-EU1"; +    } else if(sResult.find("LE910C1-NS") != std::string::npos) { +    	sModel = "LE910C1-NS"; +    } else if(sResult.find("LE910C1-AP") != std::string::npos) { +    	sModel = "LE910C1-AP"; +    } else if(sResult.find("GE910") != std::string::npos) { +        sModel = "GE910"; +    } else if(sResult.find("DE910-DUAL") != std::string::npos) { +        sModel = "DE910-DUAL"; +    } else if(sResult.find("CE910") != std::string::npos) { +        sModel = "CE910"; +    } +    return sModel; +} + +std::string TelitRadio::getCodeAsString(CODE eCode) { +    switch(eCode) { +        case SUCCESS: +            return "SUCCESS"; +        case ERROR: +            return "ERROR"; +        case FAILURE: +            return "FAILURE"; +        case NO_RESPONSE: +            return "NO RESPONSE"; +        default: +            return "UNKNOWN"; +    } +} + +bool TelitRadio::splitAndAssign(const std::string& sLine, const std::string& sKey, Json::Value& jParent, const std::string& sJsonKey,  Json::ValueType eType) { + +    std::vector<std::string> vParts = MTS::Text::split(sLine, ":", 2); + +    if(vParts.size() == 2 && vParts[0] == sKey) { +        if(eType == Json::ValueType::stringValue) { +            jParent[sJsonKey] = MTS::Text::trim(vParts[1]); +        } else if (eType == Json::ValueType::intValue || eType == Json::ValueType::uintValue) { +            //TODO: +            printWarning("%s| Unable to parse requested type from line [%s]", getName().c_str(), sKey.c_str(), sLine.c_str()); +            return false; +        } else if(eType == Json::ValueType::realValue) { +            //TODO: +            printWarning("%s| Unable to parse requested type from line [%s]", getName().c_str(), sKey.c_str(), sLine.c_str()); +            return false; +        } else if(eType == Json::ValueType::booleanValue) { +            //TODO: +            printWarning("%s| Unable to parse requested type from line [%s]", getName().c_str(), sKey.c_str(), sLine.c_str()); +            return false; +        } else { +            printWarning("%s| Unable to parse requested type from line [%s]", getName().c_str(), sKey.c_str(), sLine.c_str()); +            return false; +        } +    } else { +        printWarning("%s| Unable to parse %s from line [%s]", getName().c_str(), sKey.c_str(), sLine.c_str()); +        return false; +    } + +    return true; +} + +bool TelitRadio::getCarrierFromFirmware(const std::string& sFirmware, std::string& sCarrier) { +    // Telit Radios +    //    H.ab.zyx => 3 Main Components +    //    "H" = Hardware -> 15 = DE910 family, 18 = CE910 family, 12 = HE910 family +    //    "a" = Hardware version +    //    "b" = Software Major Version +    //    "z" = is the product type, i.e. DUAL or SC +    //    "y" = is the carrier variant +    //    "x" = is the firmware version +    //    Telit will do their best to keep the carrier variant as "0" for Sprint, "1" for Aeris, "2" for Verizon, and "3" for U.S. Cellular. + +    const uint32_t CARRIER_INDEX = 1;   //y in [zyx] + +    bool bResult = false; +    std::vector<std::string> vParts = MTS::Text::split(sFirmware, '.'); + +    if(vParts.size() == 3) { +        //CDMA firmware version notation +        if(vParts[0] == "15" || vParts[0] == "18") { +            //DE910 or CE910 -> Good good +            std::string sID = vParts[2]; +            if(sID.size() == 3) { +                char cId = sID[CARRIER_INDEX]; + +                //Good good +                if(cId == '0') { +                    sCarrier = VALUE_CARRIER_SPRINT; +                    bResult = true; +                } else +                if(cId == '1') { +                    sCarrier = VALUE_CARRIER_AERIS; +                    bResult = true; +                } else +                if(cId == '2') { +                    sCarrier = VALUE_CARRIER_VERIZON; +                    bResult = true; +                } else +                if(cId == '3') { +                    sCarrier = VALUE_CARRIER_USCELLULAR; +                    bResult = true; +                } +            } +        } +    } + +    return bResult; +} + +bool TelitRadio::getHardwareVersionFromFirmware(const std::string& sFirmware, std::string& sHardware) { +    // Telit Radios +    //    H.ab.zyx => 3 Main Components +    //    "H" = Hardware -> 15 = DE910 family, 18 = CE910 family, 12 = HE910 family +    //    "a" = Hardware version +    //    "b" = Software Major Version +    //    "z" = is the product type, i.e. DUAL or SC +    //    "y" = is the carrier variant +    //    "x" = is the firmware version +    //    Telit will do their best to keep the carrier variant as "0" for Sprint, "1" for Aeris, and "2" for Verizon. + +    const uint32_t HARDWARE_INDEX = 0;   //a in [ab] + +    bool bResult = false; +    std::vector<std::string> vParts = MTS::Text::split(sFirmware, '.'); + +    if(vParts.size() == 3) { +        //GSM Hardware Version +        if(!(vParts[0] == "15" || vParts[0] == "18")) { +            //Not DE910 or CE910 -> Good good +            std::string sVersion = vParts[1]; +            if(sVersion.size() == 2) { +                sHardware = "1."; +                sHardware += sVersion[HARDWARE_INDEX]; +                bResult = true; +            } +        } +    } + +    return bResult; + +} + +const char *TelitRadio::RadioBandMap::getLTEBand(const int32_t channel) +{ +    for (unsigned int ii = 0; ii < NUM_LTE_BANDS; ii++) +    { +        if (EULTRAband[ii].low <= channel && EULTRAband[ii].high >= channel) +        { +            return EULTRAband[ii].name; +        } +    } +    return VALUE_UNKNOWN.c_str(); +} + +const char *TelitRadio::RadioBandMap::getCDMABand(const int channel) +{ +    for (unsigned int ii = 0; ii < NUM_WCDMA_BANDS; ii++) +    { +        if (WCDMAband[ii].low <= channel && WCDMAband[ii].high >= channel) +        { +            return WCDMAband[ii].name; +        } +    } +    return VALUE_UNKNOWN.c_str(); +} + +const char *TelitRadio::RadioBandMap::getGSMBand(const int channel) +{ +    for (unsigned int ii = 0; ii < NUM_GSM_BANDS; ii++) +    { +        if (GSMband[ii].low <= channel && GSMband[ii].high >= channel) +        { +            return GSMband[ii].name; +        } +    } +    return VALUE_UNKNOWN.c_str(); +} + +const char *TelitRadio::RadioBandMap::getRadioBandName() +{ +    const char *band = TelitRadio::VALUE_UNKNOWN.c_str(); + +    if (m_sRadioType == TelitRadio::VALUE_TYPE_LTE) +    { +        band = getLTEBand(m_iChannel); +    } +    else if (m_sRadioType == TelitRadio::VALUE_TYPE_CDMA) +    { +        band = getCDMABand(m_iChannel); +    } +    else if (m_sRadioType == TelitRadio::VALUE_TYPE_GSM) +    { +        band = getGSMBand(m_iChannel); +    } + +    return band; +} + +const char *TelitRadio::RadioBandMap::getRadioBandName(const std::string &channel, const std::string &radioType) +{ +    const char *band = TelitRadio::VALUE_UNKNOWN.c_str(); +    int32_t chan = strtol(channel.c_str(), NULL, 10); +    if (radioType == TelitRadio::VALUE_TYPE_LTE) +    { +        band = getLTEBand(chan); +    } +    else if (radioType == TelitRadio::VALUE_TYPE_CDMA) +    { +        band = getCDMABand(chan); +    } +    else if (radioType == TelitRadio::VALUE_TYPE_GSM) +    { +        band = getGSMBand(chan); +    } + +    return band; +} | 
