diff options
| author | Jeff Hatch <jhatch@multitech.com> | 2020-02-19 14:24:46 -0600 | 
|---|---|---|
| committer | Jeff Hatch <jhatch@multitech.com> | 2020-02-19 14:24:46 -0600 | 
| commit | cdd3fbe0f999546b3f39843f6f742f185781edd7 (patch) | |
| tree | dafe7aecac186e1d14aa317a487b4070ff681b33 | |
| parent | 545778caa05a2bc1ee3bfdeac2b48c8b51c54d64 (diff) | |
| parent | a19364df47f14bff07f8f1ade616fe147f910838 (diff) | |
| download | libmts-io-cdd3fbe0f999546b3f39843f6f742f185781edd7.tar.gz libmts-io-cdd3fbe0f999546b3f39843f6f742f185781edd7.tar.bz2 libmts-io-cdd3fbe0f999546b3f39843f6f742f185781edd7.zip | |
Merge branch 'cleanup_MAT1_MVW1_radios' into 'master'
MTX-3211 Remove the code that is used to support ME910C1-NV and ME910C1-NA
See merge request !10
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | include/mts/MTS_IO_CellularRadioFactory.h | 2 | ||||
| -rw-r--r-- | include/mts/MTS_IO_ME910C1NARadio.h | 57 | ||||
| -rw-r--r-- | include/mts/MTS_IO_ME910C1NVRadio.h | 77 | ||||
| -rw-r--r-- | include/mts/MTS_IO_ME910C1WWRadio.h | 23 | ||||
| -rw-r--r-- | src/MTS_IO_CellularRadioFactory.cpp | 12 | ||||
| -rw-r--r-- | src/MTS_IO_ICellularRadio.cpp | 16 | ||||
| -rw-r--r-- | src/MTS_IO_ME910C1NARadio.cpp | 127 | ||||
| -rw-r--r-- | src/MTS_IO_ME910C1NVRadio.cpp | 623 | ||||
| -rw-r--r-- | src/MTS_IO_ME910C1WWRadio.cpp | 593 | 
10 files changed, 615 insertions, 917 deletions
| @@ -33,8 +33,6 @@ OBJS += \  	src/MTS_IO_LE910EU1Radio.o \  	src/MTS_IO_LE910C1NSRadio.o \  	src/MTS_IO_LE910C1APRadio.o \ -	src/MTS_IO_ME910C1NARadio.o \ -	src/MTS_IO_ME910C1NVRadio.o \  	src/MTS_IO_ME910C1WWRadio.o \  	src/MTS_IO_ME910Radio.o \  	src/MTS_IO_LockFile.o \ diff --git a/include/mts/MTS_IO_CellularRadioFactory.h b/include/mts/MTS_IO_CellularRadioFactory.h index 9b36489..e57ca5e 100644 --- a/include/mts/MTS_IO_CellularRadioFactory.h +++ b/include/mts/MTS_IO_CellularRadioFactory.h @@ -49,8 +49,6 @@ namespace MTS {                  ICellularRadio* createLE910EU1(const std::string& sPort = ICellularRadio::DEFAULT_RADIO_PORT) const;                  ICellularRadio* createLE910C1NS(const std::string& sPort = ICellularRadio::DEFAULT_RADIO_PORT) const;                  ICellularRadio* createLE910C1AP(const std::string& sPort = ICellularRadio::DEFAULT_RADIO_PORT) const; -                ICellularRadio* createME910C1NA(const std::string& sPort = ICellularRadio::DEFAULT_RADIO_PORT) const; -                ICellularRadio* createME910C1NV(const std::string& sPort = ICellularRadio::DEFAULT_RADIO_PORT) const;                  ICellularRadio* createME910C1WW(const std::string& sPort = ICellularRadio::DEFAULT_RADIO_PORT) const;                  ICellularRadio* createGE910(const std::string& sPort = ICellularRadio::DEFAULT_RADIO_PORT) const;                  ICellularRadio* createDE910(const std::string& sPort = ICellularRadio::DEFAULT_RADIO_PORT) const; diff --git a/include/mts/MTS_IO_ME910C1NARadio.h b/include/mts/MTS_IO_ME910C1NARadio.h deleted file mode 100644 index e8120bd..0000000 --- a/include/mts/MTS_IO_ME910C1NARadio.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2015 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/>. - * - */ - -/*!  - \file MTS_IO_ME910C1NARadio.h - \brief A brief description  - \date Jan 19, 2015 - \author sgodinez - - A more elaborate description -*/ -#ifndef MTS_IO_ME910C1NARADIO_H_ -#define MTS_IO_ME910C1NARADIO_H_ - -#include <mts/MTS_IO_ME910Radio.h> - -namespace MTS { -    namespace IO { - -        class ME910C1NARadio : public ME910Radio { - -            public: -                static const std::string MODEL_NAME; - -                ME910C1NARadio(const std::string& sPort); -                virtual ~ME910C1NARadio(){}; - -                virtual CODE setActiveFirmware(const Json::Value& jArgs); - -                virtual CODE getActiveFirmware(std::string& sFwId); - -            protected: - -            private: - -        }; -    } -} - -#endif /* MTS_IO_ME910C1NARADIO_H_ */ diff --git a/include/mts/MTS_IO_ME910C1NVRadio.h b/include/mts/MTS_IO_ME910C1NVRadio.h deleted file mode 100644 index 3d0b3b0..0000000 --- a/include/mts/MTS_IO_ME910C1NVRadio.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2018 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/>. - * - */ - -/*!  - \file MTS_IO_ME910C1NVRadio.h - \brief A brief description  - \date May 1, 2018 - \author mykyta.dorokhin - - A more elaborate description -*/ -#ifndef MTS_IO_ME910C1NVRadio_H_ -#define MTS_IO_ME910C1NVRadio_H_ - -#include <mts/MTS_IO_ME910Radio.h> - -namespace MTS { -    namespace IO { - -        class ME910C1NVRadio : public ME910Radio { - -            public: -                static const std::string MODEL_NAME; - -                ME910C1NVRadio(const std::string& sPort); -                virtual ~ME910C1NVRadio(){}; - -                virtual CODE updateFumo(const Json::Value& jArgs, UpdateCb& stepCb); -                virtual CODE getCarrier(std::string& sCarrier); - -            protected: - -                CODE doGetFirmwareNumbers(std::string &sFirmware, std::string &sFirmwareBuild); - -            private: -                static const std::string KEY_FUMO_PDPID;     //!< PDP context id (default 3) -                static const std::string KEY_FUMO_PDPTYPE;   //!< PDP context type (default IPV4V6) -                static const std::string KEY_FUMO_APN;       //!< APN (default empty) -                static const std::string KEY_FUMO_ADDRESS;   //!< FTP server address -                static const std::string KEY_FUMO_DIR;       //!< Directory -                static const std::string KEY_FUMO_FILE;      //!< Name of the upgrade file -                static const std::string KEY_FUMO_USER;      //!< Username -                static const std::string KEY_FUMO_PASSWORD;  //!< Password -                static const std::string KEY_FUMO_DRYRUN;    //!< If set, do not apply the downloaded firmware - -                CODE doFumoPerform(const Json::Value &jConfig, UpdateCb& stepCb); -                CODE doFumoReadConfig(const Json::Value& jArgs, Json::Value &jConfig); -                CODE doFumoSetup(const Json::Value &jConfig, UpdateCb& stepCb); -                CODE doFumoFtp(const Json::Value &jConfig, UpdateCb& stepCb); -                CODE doFumoCleanup(const Json::Value &jConfig, UpdateCb& stepCb); -                CODE doFumoApplyFirmware(const Json::Value &jConfig, UpdateCb& stepCb); -                CODE doFumoWaitNewFirmware(const Json::Value &jConfig, UpdateCb& stepCb); - -                std::string m_sFw; -                std::string m_sFwBuild; -        }; -    } -} - -#endif /* MTS_IO_ME910C1NVRadio_H_ */ diff --git a/include/mts/MTS_IO_ME910C1WWRadio.h b/include/mts/MTS_IO_ME910C1WWRadio.h index d45d86a..9605862 100644 --- a/include/mts/MTS_IO_ME910C1WWRadio.h +++ b/include/mts/MTS_IO_ME910C1WWRadio.h @@ -36,10 +36,33 @@ namespace MTS {                  ICellularRadio::CODE setActiveFirmware(const Json::Value& jArgs);                  ICellularRadio::CODE getActiveFirmware(std::string& sFwId); +                virtual CODE updateFumo(const Json::Value& jArgs, UpdateCb& stepCb); +              protected: +                CODE doGetFirmwareNumbers(std::string &sFirmware, std::string &sFirmwareBuild); +              private: +                static const std::string KEY_FUMO_PDPID;     //!< PDP context id (default 3) +                static const std::string KEY_FUMO_PDPTYPE;   //!< PDP context type (default IPV4V6) +                static const std::string KEY_FUMO_APN;       //!< APN (default empty) +                static const std::string KEY_FUMO_ADDRESS;   //!< FTP server address +                static const std::string KEY_FUMO_DIR;       //!< Directory +                static const std::string KEY_FUMO_FILE;      //!< Name of the upgrade file +                static const std::string KEY_FUMO_USER;      //!< Username +                static const std::string KEY_FUMO_PASSWORD;  //!< Password +                static const std::string KEY_FUMO_DRYRUN;    //!< If set, do not apply the downloaded firmware + +                CODE doFumoPerform(const Json::Value &jConfig, UpdateCb& stepCb); +                CODE doFumoReadConfig(const Json::Value& jArgs, Json::Value &jConfig); +                CODE doFumoSetup(const Json::Value &jConfig, UpdateCb& stepCb); +                CODE doFumoFtp(const Json::Value &jConfig, UpdateCb& stepCb); +                CODE doFumoCleanup(const Json::Value &jConfig, UpdateCb& stepCb); +                CODE doFumoApplyFirmware(const Json::Value &jConfig, UpdateCb& stepCb); +                CODE doFumoWaitNewFirmware(const Json::Value &jConfig, UpdateCb& stepCb); +                std::string m_sFw; +                std::string m_sFwBuild;          };      }  } diff --git a/src/MTS_IO_CellularRadioFactory.cpp b/src/MTS_IO_CellularRadioFactory.cpp index b86f207..08c6315 100644 --- a/src/MTS_IO_CellularRadioFactory.cpp +++ b/src/MTS_IO_CellularRadioFactory.cpp @@ -31,8 +31,6 @@  #include <mts/MTS_IO_LE910EU1Radio.h>  #include <mts/MTS_IO_LE910C1NSRadio.h>  #include <mts/MTS_IO_LE910C1APRadio.h> -#include <mts/MTS_IO_ME910C1NARadio.h> -#include <mts/MTS_IO_ME910C1NVRadio.h>  #include <mts/MTS_IO_LE866A1JSRadio.h>  #include <mts/MTS_IO_ME910C1WWRadio.h>  #include <mts/MTS_IO_GE910Radio.h> @@ -56,8 +54,6 @@ CellularRadioFactory::CellularRadioFactory() {      m_mCreationMap[LE910EU1Radio::MODEL_NAME]     = &CellularRadioFactory::createLE910EU1;      m_mCreationMap[LE910C1NSRadio::MODEL_NAME]    = &CellularRadioFactory::createLE910C1NS;      m_mCreationMap[LE910C1APRadio::MODEL_NAME]    = &CellularRadioFactory::createLE910C1AP; -    m_mCreationMap[ME910C1NARadio::MODEL_NAME]    = &CellularRadioFactory::createME910C1NA; -    m_mCreationMap[ME910C1NVRadio::MODEL_NAME]    = &CellularRadioFactory::createME910C1NV;      m_mCreationMap[ME910C1WWRadio::MODEL_NAME]    = &CellularRadioFactory::createME910C1WW;      m_mCreationMap[GE910Radio::MODEL_NAME]        = &CellularRadioFactory::createGE910;      m_mCreationMap[DE910Radio::MODEL_NAME]        = &CellularRadioFactory::createDE910; @@ -175,14 +171,6 @@ ICellularRadio* CellularRadioFactory::createLE910C1AP(const std::string& sPort)      return new LE910C1APRadio(sPort);  } -ICellularRadio* CellularRadioFactory::createME910C1NA(const std::string& sPort) const { -    return new ME910C1NARadio(sPort); -} - -ICellularRadio* CellularRadioFactory::createME910C1NV(const std::string& sPort) const { -    return new ME910C1NVRadio(sPort); -} -  ICellularRadio* CellularRadioFactory::createME910C1WW(const std::string& sPort) const {      return new ME910C1WWRadio(sPort);  } diff --git a/src/MTS_IO_ICellularRadio.cpp b/src/MTS_IO_ICellularRadio.cpp index f7a5fe8..339294d 100644 --- a/src/MTS_IO_ICellularRadio.cpp +++ b/src/MTS_IO_ICellularRadio.cpp @@ -164,12 +164,6 @@ MTS::IO::ICellularRadio::CODE MTS::IO::ICellularRadio::convertModelToMtsShortCod      } 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; @@ -290,12 +284,6 @@ MTS::IO::ICellularRadio::CODE MTS::IO::ICellularRadio::convertModelToType(const      } 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; @@ -432,10 +420,6 @@ std::string MTS::IO::ICellularRadio::extractModelFromResult(const std::string& s          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) { diff --git a/src/MTS_IO_ME910C1NARadio.cpp b/src/MTS_IO_ME910C1NARadio.cpp deleted file mode 100644 index 8c9992e..0000000 --- a/src/MTS_IO_ME910C1NARadio.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (C) 2017 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/>. - * - */ - -/*! - \file MTS_IO_ME910C1NARadio.cpp - \brief A brief description - - A more elaborate description -*/ -#include <mts/MTS_Text.h> -#include <mts/MTS_Logger.h> -#include <mts/MTS_IO_ME910C1NARadio.h> - -using namespace MTS::IO; - -const std::string ME910C1NARadio::MODEL_NAME("ME910C1-NA"); - -ME910C1NARadio::ME910C1NARadio(const std::string& sPort) -: ME910Radio(MODEL_NAME, sPort) -{ - -} - -CellularRadio::CODE ME910C1NARadio::setActiveFirmware(const Json::Value& jArgs) { -    CellularRadio::CODE rc; - -    //    Set command allows enabling a specific firmware image on products -    //    embedding 2 different firmware images: -    // -    //    "AT#FWSWITCH=<image_number>[,<storage_conf>]" -    //    <image_number> - Firmware Image To Be Enabled -    //    0 – Image 1 (Default) -    //    1 – Image 2 -    //    <storage_conf> - Setting Storage Configuration -    //    0 – Save the <image_number> value in RAM -    //    1 – Save the <image_number> value in NVM - -    printTrace("%s| Set Active Firmware Image Number", getName().c_str()); - -    if(!jArgs["fwid"].isString()) { -        return INVALID_ARGS; -    } - -    if (jArgs["fwid"].asString() != "1" && jArgs["fwid"].asString() != "0") { -            return INVALID_ARGS; -    } - -    //  LE910-NA1 and LE910-NA V2 is orderable in single image or dual image (single SKU) -    //  configuration. So issue the test command first -    rc = sendBasicCommand("AT#FWSWITCH=?"); -    if (rc == ERROR) { -        printTrace("%s| FWSWITCH is not supported", getName().c_str()); -        return NOT_APPLICABLE; -    } -    else if (rc != SUCCESS) { -        return rc; -    } - -    std::string sCmd = "AT#FWSWITCH="; -    sCmd += jArgs["fwid"].asString(); -    sCmd += ",1"; - -    printTrace("%s| Issuing %s command", getName().c_str(), sCmd.c_str()); - -    return sendBasicCommand(sCmd, 5000); -} - -CellularRadio::CODE ME910C1NARadio::getActiveFirmware(std::string& sFwId) { -    std::string sCmd; -    CellularRadio::CODE rc; -    // -    // Read command reports the current active firmware image: -    // AT#FWSWITCH? -    // #FWSWITCH: 1 -    // -    // OK -    // -    printTrace("%s| Get Active Firmware Image Number", getName().c_str()); - -    //  LE910-NA1 and LE910-NA V2 is orderable in single image or dual image (single SKU) -    //  configuration. So issue the test command first -    sCmd = "AT#FWSWITCH=?"; -    rc = sendBasicCommand(sCmd); -    if (rc == ERROR) { -        printTrace("%s| FWSWITCH is not supported", getName().c_str()); -        return NOT_APPLICABLE; -    } -    else if (rc != SUCCESS) { -        return rc; -    } - -    sCmd = "AT#FWSWITCH?"; -    std::string sResult = sendCommand(sCmd); -    size_t end = sResult.find(RSP_OK); -    if (end == std::string::npos) { -        printWarning("%s| Unable to get active image number from radio using command [%s]", -                getName().c_str(), -                sCmd.c_str()); -        return FAILURE; -    } - -    size_t start = sResult.find("#FWSWITCH:") + sizeof("#FWSWITCH:"); -    sFwId = MTS::Text::trim(sResult.substr(start, end-start)); -    if(sFwId.size() == 0) { -        printWarning("%s| Firmware Image Number is empty", getName().c_str()); -        return FAILURE; -    } - -    return SUCCESS; -} diff --git a/src/MTS_IO_ME910C1NVRadio.cpp b/src/MTS_IO_ME910C1NVRadio.cpp deleted file mode 100644 index 0af5f24..0000000 --- a/src/MTS_IO_ME910C1NVRadio.cpp +++ /dev/null @@ -1,623 +0,0 @@ -/* - * Copyright (C) 2018 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/>. - * - */ - -/*! - \file MTS_IO_ME910C1NVRadio.cpp - \brief A brief description - \date May 1, 2018 - \author mykyta.dorokhin - - A more elaborate description -*/ -#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_ME910C1NVRadio.h> - -using namespace MTS::IO; - -const std::string ME910C1NVRadio::MODEL_NAME("ME910C1-NV"); - -const std::string ME910C1NVRadio::KEY_FUMO_PDPID("pdpid");         // optional (default : "3") -const std::string ME910C1NVRadio::KEY_FUMO_PDPTYPE("pdptype");     // optional (default : "IPV4V6") -const std::string ME910C1NVRadio::KEY_FUMO_APN("apn");             // optional (default : "") -const std::string ME910C1NVRadio::KEY_FUMO_ADDRESS("address"); -const std::string ME910C1NVRadio::KEY_FUMO_DIR("dir"); -const std::string ME910C1NVRadio::KEY_FUMO_FILE("file"); -const std::string ME910C1NVRadio::KEY_FUMO_USER("user"); -const std::string ME910C1NVRadio::KEY_FUMO_PASSWORD("password"); -const std::string ME910C1NVRadio::KEY_FUMO_DRYRUN("dryrun"); - -ME910C1NVRadio::ME910C1NVRadio(const std::string& sPort) -: ME910Radio(MODEL_NAME, sPort) -{ - -} - -ICellularRadio::CODE ME910C1NVRadio::getCarrier(std::string& sCarrier) { -    sCarrier = "Verizon"; -    return SUCCESS; -} - -ICellularRadio::CODE ME910C1NVRadio::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 ME910C1NVRadio::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(); - -        Json::Features features = Json::Features::strictMode(); -        Json::Reader reader(features); -        if (!reader.parse(buffer, jConfig)) { -            printError("Error parsing FOTA configuration file"); -            break; -        } - -        // -        // 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 ME910C1NVRadio::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 ME910C1NVRadio::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 ME910C1NVRadio::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 ME910C1NVRadio::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 ME910C1NVRadio::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 ME910C1NVRadio::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 ME910C1NVRadio::updateFumo(const Json::Value& jArgs, UpdateCb& stepCb) -{ -	Json::Value jConfig(Json::objectValue); -	ICellularRadio::CODE rc = FAILURE; - -    rc = doFumoReadConfig(jArgs, jConfig); -    if (rc != SUCCESS) { -        if(stepCb) { -            stepCb(Json::Value("FUMO Error: bad configuration parameters")); -        } -        return rc; -    } - -    return doFumoPerform(jConfig, stepCb); -} diff --git a/src/MTS_IO_ME910C1WWRadio.cpp b/src/MTS_IO_ME910C1WWRadio.cpp index 0469d5d..32c64b3 100644 --- a/src/MTS_IO_ME910C1WWRadio.cpp +++ b/src/MTS_IO_ME910C1WWRadio.cpp @@ -17,15 +17,27 @@   * 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)  { @@ -119,3 +131,582 @@ 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(); + +        Json::Features features = Json::Features::strictMode(); +        Json::Reader reader(features); +        if (!reader.parse(buffer, jConfig)) { +            printError("Error parsing FOTA configuration file"); +            break; +        } + +        // +        // 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; +} + | 
