summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--include/mts/MTS_IO_CellularRadioFactory.h2
-rw-r--r--include/mts/MTS_IO_ME910C1NARadio.h57
-rw-r--r--include/mts/MTS_IO_ME910C1NVRadio.h77
-rw-r--r--include/mts/MTS_IO_ME910C1WWRadio.h23
-rw-r--r--src/MTS_IO_CellularRadioFactory.cpp12
-rw-r--r--src/MTS_IO_ICellularRadio.cpp16
-rw-r--r--src/MTS_IO_ME910C1NARadio.cpp127
-rw-r--r--src/MTS_IO_ME910C1NVRadio.cpp623
-rw-r--r--src/MTS_IO_ME910C1WWRadio.cpp593
10 files changed, 615 insertions, 917 deletions
diff --git a/Makefile b/Makefile
index ac17f21..e93d3cc 100644
--- a/Makefile
+++ b/Makefile
@@ -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 89318ef..9f8955e 100644
--- a/src/MTS_IO_ICellularRadio.cpp
+++ b/src/MTS_IO_ICellularRadio.cpp
@@ -163,12 +163,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;
@@ -289,12 +283,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;
@@ -431,10 +419,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;
+}
+