diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/MTS_IO_ME910C1WWRadio.cpp | 604 | 
1 files changed, 1 insertions, 603 deletions
| diff --git a/src/MTS_IO_ME910C1WWRadio.cpp b/src/MTS_IO_ME910C1WWRadio.cpp index 80c2320..bf1be00 100644 --- a/src/MTS_IO_ME910C1WWRadio.cpp +++ b/src/MTS_IO_ME910C1WWRadio.cpp @@ -17,27 +17,14 @@   * along with libmts-io.  If not, see <http://www.gnu.org/licenses/>.   *   */ -#include <fstream>  #include <mts/MTS_Text.h>  #include <mts/MTS_Logger.h> -#include <mts/MTS_Thread.h> -#include <mts/MTS_Timer.h>  #include <mts/MTS_IO_ME910C1WWRadio.h>  using namespace MTS::IO;  const std::string ME910C1WWRadio::MODEL_NAME("ME910C1-WW"); -const std::string ME910C1WWRadio::KEY_FUMO_PDPID("pdpid");         // optional (default : "3") -const std::string ME910C1WWRadio::KEY_FUMO_PDPTYPE("pdptype");     // optional (default : "IPV4V6") -const std::string ME910C1WWRadio::KEY_FUMO_APN("apn");             // optional (default : "") -const std::string ME910C1WWRadio::KEY_FUMO_ADDRESS("address"); -const std::string ME910C1WWRadio::KEY_FUMO_DIR("dir"); -const std::string ME910C1WWRadio::KEY_FUMO_FILE("file"); -const std::string ME910C1WWRadio::KEY_FUMO_USER("user"); -const std::string ME910C1WWRadio::KEY_FUMO_PASSWORD("password"); -const std::string ME910C1WWRadio::KEY_FUMO_DRYRUN("dryrun"); -  ME910C1WWRadio::ME910C1WWRadio(const std::string& sPort)  : ME910Radio(MODEL_NAME, sPort)  { @@ -129,593 +116,4 @@ ICellularRadio::CODE ME910C1WWRadio::getActiveFirmware(std::string& sFwId) {      }      return SUCCESS; -} - -ICellularRadio::CODE ME910C1WWRadio::doGetFirmwareNumbers(std::string &sFirmware, std::string &sFirmwareBuild) { -    ICellularRadio::CODE rc = FAILURE; - -    rc = getFirmware(sFirmware); -    if (rc != SUCCESS){ -        return rc; -    } - -    rc = getFirmwareBuild(sFirmwareBuild); -    if (rc != SUCCESS){ -        return rc; -    } - -    return rc; -} - -ICellularRadio::CODE ME910C1WWRadio::doFumoReadConfig(const Json::Value& jArgs, Json::Value &jConfig) { -    ICellularRadio::CODE rc = INVALID_ARGS; -    std::string sPath; - -    do -    { -        if (!jArgs["config-file"].isString()) { -            rc = INVALID_ARGS; -            break; -        } - -        sPath = jArgs["config-file"].asString(); - -        std::ifstream file(sPath.c_str()); -        if (!file.is_open()) { -            printError("Failed to open file [%s]", sPath.c_str()); -            break; -        } - -        file.seekg(0, std::ios::end); -        size_t size = file.tellg(); -        std::string buffer(size, ' '); -        file.seekg(0); -        file.read(&buffer[0], size); -        file.close(); - -#if defined(JSONCPP_VERSION_HEXA) && (JSONCPP_VERSION_HEXA > 0x010600) // > 1.6.0 -        Json::CharReaderBuilder builder; -        std::istringstream ss(buffer); -        if (!Json::parseFromStream(builder, ss, &jConfig, NULL)) { -            printError("Error parsing FOTA configuration file"); -            break; -        } -#else -        Json::Features features = Json::Features::strictMode(); -        Json::Reader reader(features); -        if (!reader.parse(buffer, jConfig)) { -            printError("Error parsing FOTA configuration file"); -            break; -        } -#endif - -        // -        // set default values if missing -        // -        if (!jConfig.isMember(KEY_FUMO_PDPID)) { -            jConfig[KEY_FUMO_PDPID] = std::string("3"); -        } - -        if (!jConfig.isMember(KEY_FUMO_PDPTYPE)) { -            jConfig[KEY_FUMO_PDPTYPE] = std::string("IPV4V6"); -        } - -        if (!jConfig.isMember(KEY_FUMO_APN)) { -            jConfig[KEY_FUMO_APN] = std::string(""); -        } - -        // -        // validate -        // -        if (!jConfig[KEY_FUMO_PDPID].isString()) { -            printError("Error loading FOTA configuration: PDP context id is not set"); -            break; -        } - -        if (jConfig[KEY_FUMO_PDPID].asString().empty()) { -            printError("Error loading FOTA configuration: context id is empty"); -            break; -        } - -        if (!jConfig[KEY_FUMO_PDPTYPE].isString()) { -            printError("Error loading FOTA configuration: PDP type is not set"); -            break; -        } - -        if (jConfig[KEY_FUMO_PDPTYPE].asString().empty()) { -            printError("Error loading FOTA configuration: PDP type is empty"); -            break; -        } - -        // Note : allow empty APN -        if (!jConfig[KEY_FUMO_APN].isString()) { -            printError("Error loading FOTA configuration: APN is not set"); -            break; -        } - -        if (!jConfig[KEY_FUMO_ADDRESS].isString()) { -            printError("Error loading FOTA configuration: address is not set"); -            break; -        } - -        if (jConfig[KEY_FUMO_ADDRESS].asString().empty()) { -            printError("Error loading FOTA configuration: address is empty"); -            break; -        } - -        // Note: allow empty dir -        if (!jConfig[KEY_FUMO_DIR].isString()) { -            printError("Error loading FOTA configuration: directory is not set"); -            break; -        } - -        if (!jConfig[KEY_FUMO_FILE].isString()) { -            printError("Error loading FOTA configuration: filename is not set"); -            break; -        } - -        if (jConfig[KEY_FUMO_FILE].asString().empty()) { -            printError("Error loading FOTA configuration: filename is empty"); -            break; -        } - -        // Note: allow empty username/password -        if (!jConfig[KEY_FUMO_USER].isString()) { -            printError("Error loading FOTA configuration: username is not set"); -            break; -        } - -        if (!jConfig[KEY_FUMO_PASSWORD].isString()) { -            printError("Error loading FOTA configuration: password is not set"); -            break; -        } - -        rc = SUCCESS; -    } -    while(0); - -    return rc; -} - -ICellularRadio::CODE ME910C1WWRadio::doFumoSetup(const Json::Value &jConfig, UpdateCb& stepCb) { -    ICellularRadio::CODE rc = FAILURE; -    std::string sCmd; - -    std::string sContextId = jConfig[KEY_FUMO_PDPID].asString(); -    std::string sApn = jConfig[KEY_FUMO_APN].asString(); -    std::string sPdpType = jConfig[KEY_FUMO_PDPTYPE].asString(); - - -    do -    { -        // -        // Execution command is used to activate or deactivate either the GSM -        // context or the specified PDP context. -        // -        // AT#SGACT=<cid>,<stat>[,<userId>,<pwd>] -        // -        sCmd = "AT#SGACT=" + sContextId + ",0"; -        rc = sendBasicCommand(sCmd); -        if (rc != SUCCESS) { -            if(stepCb) { -                stepCb(Json::Value("FUMO Error: Failed to deactivate PDP context")); -            } -            break; -        } - -        // -        // Read current Firmware numbers (let it be after AT#SGACT not to confuse users) -        // -        rc = doGetFirmwareNumbers(m_sFw, m_sFwBuild); -        if (rc != SUCCESS) { -            if(stepCb) { -                stepCb(Json::Value("FUMO Error: Failed to obtain current firmware version")); -            } -            break; -        } - -        // -        // Set command specifies PDP context parameter values for a PDP context identified by -        // the (local) context identification parameter <cid>. -        // -        // AT+CGDCONT= [<cid>[,<PDP_type>[,<APN>[,<PDP_addr>[,<d_comp>[,<h_comp>[,<pd1>[,...[,pdN]]]]]]]]] -        // -        sCmd = "AT+CGDCONT=" + sContextId + ",\"" + sPdpType + "\""; -        if (!sApn.empty()) { -            sCmd += ",\"" + sApn + "\""; -        } -        rc = sendBasicCommand(sCmd, 1000); -        if (rc != SUCCESS) { -            if(stepCb) { -                stepCb(Json::Value("FUMO Error: Failed to setup PDP context")); -            } -            break; -        } - -        // -        // Set command sets the socket configuration parameters. -        // -        // AT#SCFG==<connId>,<cid>,<pktSz>,<maxTo>,<connTo>,<txTo> -        //    <connId> - socket connection identifier -        //    <cid> - PDP context identifier -        //    <pktSz> - packet size to be used by the TCP/UDP/IP stack for data sending. -        //    <maxTo> - exchange timeout (or socket inactivity timeout); if there’s no -        //             data exchange within this timeout period the connection is closed (timeout value in seconds). -        //    <connTo> - connection timeout; if we can’t establish a connection to the -        //             remote within this timeout period, an error is raised timeout value in hundreds of milliseconds. -        //    <txTo> - data sending timeout; after this period data are sent also if they’re -        //             less than max packet size (timeout value in hundreds of milliseconds). -        // -        sCmd = "AT#SCFG=1," + sContextId + ",300,90,600,50"; -        rc = sendBasicCommand(sCmd); -        if (rc != SUCCESS) { -            if(stepCb) { -                stepCb(Json::Value("FUMO Error: Failed to set connection configuration parameters")); -            } -            break; -        } - -        // -        // Activate PDP context -        // -        sCmd = "AT#SGACT=" + sContextId + ",1"; -        rc = sendBasicCommand(sCmd, 60 * 1000); -        if (rc != SUCCESS) { -            if(stepCb) { -                stepCb(Json::Value("FUMO Error: Failed to activate PDP context")); -            } -            break; -        } -    } -    while (0); - -    return rc; -} - -ICellularRadio::CODE ME910C1WWRadio::doFumoFtp(const Json::Value &jConfig, UpdateCb& stepCb) { -    ICellularRadio::CODE rc = FAILURE; -    std::string sCmd; -    std::string sResult; - -    // -    // Set command sets the time-out used when opening either the FTP control -    // channel or the FTP traffic channel. -    // -    // AT#FTPTO= [<tout>] -    // <tout> - time-out in 100 ms units -    // -    rc = sendBasicCommand("AT#FTPTO=2400"); -    if (rc != SUCCESS) { -        if(stepCb) { -            stepCb(Json::Value("FUMO Error: Failed to setup connection timeout")); -        } -        return rc; -    } - -    // -    // Execution command opens an FTP connection toward the FTP server. -    // -    // AT#FTPOPEN=[<server:port>,<username>,<password>[,<mode>]] -    // -    sCmd = "AT#FTPOPEN="; -    sCmd += "\"" + jConfig[KEY_FUMO_ADDRESS].asString() +  "\","; -    sCmd += "\"" + jConfig[KEY_FUMO_USER].asString() +  "\","; -    sCmd += "\"" + jConfig[KEY_FUMO_PASSWORD].asString() +  "\",1"; -    rc = sendBasicCommand(sCmd, 60 * 1000); -    if (rc != SUCCESS) { -        if(stepCb) { -            stepCb(Json::Value("FUMO Error: Failed to open connection")); -        } -        return rc; -    } - -    if (stepCb) { -        stepCb(Json::Value("FUMO Info: connection opened")); -    } - -    do -    { -        // -        // Set command, issued during an FTP connection, sets the file transfer type. -        // -        // AT#FTPTYPE=[<type>] -        //  <type> - file transfer type: -        //    0 - binary -        //    1 - ascii -        // -        rc = sendBasicCommand("AT#FTPTYPE=0", 1000); -        if (rc != SUCCESS) { -            if(stepCb) { -                stepCb(Json::Value("FUMO Error: failed to set file transfer type")); -            } -            break; -        } - -        // -        // Execution command, issued during an FTP connection, changes the -        //  working directory on FTP server. -        // -        // AT#FTPCWD=[<dirname>] -        // -        sCmd = "AT#FTPCWD=\"/"; -        if (!jConfig[KEY_FUMO_DIR].asString().empty()) { -            sCmd += jConfig[KEY_FUMO_DIR].asString() + "/"; -        } -        sCmd += "\""; -        rc = sendBasicCommand(sCmd, 60 * 1000); -        if (rc != SUCCESS) { -            if(stepCb) { -                stepCb(Json::Value("FUMO Error: failed to change working directory on the server")); -            } -            break; -        } - -        if (stepCb) { -            stepCb(Json::Value("FUMO Info: downloading the firmware")); -        } - -        // -        // Start FTP transfer -        // -        sCmd = "AT#FTPGETOTA="; -        sCmd += "\"" + jConfig[KEY_FUMO_FILE].asString() + "\",1,1"; -        sendBasicCommand(sCmd); - -        // -        // Noticed that after successful AT#FTPGETOTA the radio resets the connection. -        // and the response code (OK, ERROR.. ) not always reach the host. Therefore -        // we send the AT#FTPGETOTA with relatively small timeout and then poll with AT -        // until we get valid response. After that, using AT#FTPMSG we can check the -        // result of the last FTP command (which is AT#FTPGETOTA in our case). -        MTS::Timer oTimer; - -        oTimer.start(); - -        while (oTimer.getSeconds() < (30 * 60)) // 30 min -        { -            MTS::Thread::sleep(5000); - -            rc = sendBasicCommand("AT"); -            if (rc == SUCCESS) { -                break; -            } - -            resetConnection(1); -        } -        oTimer.stop(); - -        if (rc != SUCCESS) { -            if(stepCb) { -                stepCb(Json::Value("FUMO Error: unable to obtain radio after reset")); -            } -            break; -        } - -        // -        // Now check the FTP status -        // -        std::string sResult = sendCommand("AT#FTPMSG"); - -        printTrace("RADIO| AT#FTPMSG result [%s]", sResult.c_str()); - -        if (sResult.find(ICellularRadio::RSP_OK) == std::string::npos) { -            rc = FAILURE; -            if(stepCb) { -                stepCb(Json::Value("FUMO Error: failed to download the firmware file")); -            } -            break; -        } -        if (sResult.find("#FTPMSG: 550") != std::string::npos) { -            // FTP(550) : File not found -            rc = FAILURE; -            if(stepCb) { -                stepCb(Json::Value("FUMO Error: file not found")); -            } -            break; -        } -        if (sResult.find("#FTPMSG: 226") == std::string::npos) { -            // FTP(226) : Successfully transferred -            rc = FAILURE; -            if(stepCb) { -                stepCb(Json::Value("FUMO Error: failed to download the firmware file")); -            } -            break; -        } -    } -    while (0); - -    // -    // Execution command closes an FTP connection. -    // -    // AT#FTPCLOSE -    // -    ICellularRadio::CODE rcclose = sendBasicCommand("AT#FTPCLOSE", 60 * 1000); -    if (rcclose != SUCCESS && rc == SUCCESS) { -        if(stepCb) { -            // Only one "FUMO Error" message should be sent -            stepCb(Json::Value("FUMO Error: Failed to close FTP connection")); -        } -        rc = rcclose; -    } - -    if (rc == SUCCESS) { -        if(stepCb) { -            stepCb(Json::Value("FUMO Info: firmware downloaded successfully")); -        } -    } - -    return rc; -} - -ICellularRadio::CODE ME910C1WWRadio::doFumoCleanup(const Json::Value &jConfig, UpdateCb& stepCb) { -    ICellularRadio::CODE rc = FAILURE; -    std::string sCmd; - -    std::string sContextId = jConfig[KEY_FUMO_PDPID].asString(); - -    // -    // Deactivate PDP context -    // -    sCmd = "AT#SGACT=" + sContextId + ",0"; -    rc = sendBasicCommand(sCmd, 10000); -    if (rc != SUCCESS) { -        if(stepCb) { -            stepCb(Json::Value("FUMO Error: Failed to deactivate PDP context")); -        } -    } -    return rc; -} - -ICellularRadio::CODE ME910C1WWRadio::doFumoApplyFirmware(const Json::Value &jConfig, UpdateCb& stepCb) { -    ICellularRadio::CODE rc = FAILURE; - -    if (jConfig.isMember(KEY_FUMO_DRYRUN)) { -        if(stepCb) { -            stepCb(Json::Value("FUMO Info: applying the radio firmware")); -        } -        return SUCCESS; -    } - -    rc = sendBasicCommand("AT#OTAUP=0", 10000); -    if (rc != SUCCESS) { -        if(stepCb) { -            stepCb(Json::Value("FUMO Error: failed to apply the firmware")); -        } -        return rc; -    } - -    if(stepCb) { -        stepCb(Json::Value("FUMO Info: applying the radio firmware")); -    } - -    return rc; -} - -ICellularRadio::CODE ME910C1WWRadio::doFumoWaitNewFirmware(const Json::Value &jConfig, UpdateCb& stepCb) { -    std::string sFirmware; -    std::string sFirmwareBuild; -    ICellularRadio::CODE rc = FAILURE; - -    if (jConfig.isMember(KEY_FUMO_DRYRUN)) { -        if(stepCb) { -            stepCb(Json::Value("FUMO done: radio firmware applied successfully")); -        } -        return SUCCESS; -    } - -    // The radio is expected to send "#OTAEV: Module Upgraded To New Fw" unsolicited message -    // on success. However, for some reason, we do not see this message. - -    MTS::Timer oTimer; -    oTimer.start(); - -    while (oTimer.getSeconds() < (5 * 60)) { // 5 minutes - -        MTS::Thread::sleep(10000); - -        if (doGetFirmwareNumbers(sFirmware, sFirmwareBuild) != SUCCESS) { -            // The radio is probably unavailable -            resetConnection(100); -            continue; -        } - -        if (sFirmware == m_sFw && sFirmwareBuild == m_sFwBuild) { -            // Have the same firmware. The radio resets several time -            // before the firmware is actually get upgraded. So keep polling. -            continue; -        } - -        // The firmware numbers have changed -        rc = SUCCESS; -        break; -    } -    oTimer.stop(); - -    if (rc == SUCCESS) { -        if(stepCb) { -            stepCb(Json::Value("FUMO done: radio firmware applied successfully")); -        } -    } -    else { -        if(stepCb) { -            stepCb(Json::Value("FUMO error: radio firmware has not been updated")); -        } -    } - -    return rc; -} - - -ICellularRadio::CODE ME910C1WWRadio::doFumoPerform(const Json::Value &jConfig, UpdateCb& stepCb) { -    ICellularRadio::CODE rc = FAILURE; - -    UpdateCb dummyCb; - -    // Set the PDP context for the FOTA -    rc = doFumoSetup(jConfig, stepCb); -    if (rc != SUCCESS) { -        return rc; -    } - -    // Download FW over FTP -    rc = doFumoFtp(jConfig, stepCb); -    if (rc != SUCCESS) { -        doFumoCleanup(jConfig, dummyCb); -        return rc; -    } - -    // Clean up before applying the FW file -    rc = doFumoCleanup(jConfig, stepCb); -    if (rc != SUCCESS) { -        return rc; -    } - -    // Apply the FW file -    rc = doFumoApplyFirmware(jConfig, stepCb); -    if (rc != SUCCESS) { -        return rc; -    } - -    rc = doFumoWaitNewFirmware(jConfig, stepCb); - -    return rc; -} - -ICellularRadio::CODE ME910C1WWRadio::updateFumo(const Json::Value& jArgs, UpdateCb& stepCb) { -    Json::Value jConfig(Json::objectValue); -    ICellularRadio::CODE rc = FAILURE; -    std::string sFwId; - -    do -    { -        rc = getActiveFirmware(sFwId); -        if (rc != SUCCESS) { -            if(stepCb) { -                stepCb(Json::Value("FUMO Error: failed to obtain current active firmware id")); -            } -            break; -        } - -        // For Verizon Only -        if (sFwId != "1") { -            if(stepCb) { -                stepCb(Json::Value("FUMO Error: fumo is not supported")); -            } -            break; -        } - -        rc = doFumoReadConfig(jArgs, jConfig); -        if (rc != SUCCESS) { -            if(stepCb) { -                stepCb(Json::Value("FUMO Error: bad configuration parameters")); -            } -            break; -        } - -        rc = doFumoPerform(jConfig, stepCb); -    } -    while(0); - -    return rc; -} - +}
\ No newline at end of file | 
