summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Hatch <jhatch@multitech.com>2023-01-31 13:54:52 -0600
committerJeff Hatch <jhatch@multitech.com>2023-01-31 13:54:52 -0600
commitb504ed673fa55ae1a429fd468079ee8c16c4a04a (patch)
tree620e1d7509ddfe0e9b7102485ce01a0ff4549964
parent430506fb7757d6736988d75c8ea53c85f6c97da9 (diff)
parent23d702dfaaa6ef20a02e410a09ae6f67e967464f (diff)
downloadlibmts-io-b504ed673fa55ae1a429fd468079ee8c16c4a04a.tar.gz
libmts-io-b504ed673fa55ae1a429fd468079ee8c16c4a04a.tar.bz2
libmts-io-b504ed673fa55ae1a429fd468079ee8c16c4a04a.zip
Merge branch 'ym/GP-1733/add_sequans_support' into 'master'
[GP-1733] mPower R.6.3.X: L6G1 Support See merge request !53
-rw-r--r--Makefile6
-rw-r--r--data/MccMncTable.csv1
-rw-r--r--include/mts/MTS_IO_CB610LRadio.h48
-rw-r--r--include/mts/MTS_IO_CE910Radio.h2
-rw-r--r--include/mts/MTS_IO_CellularRadio.h2
-rw-r--r--include/mts/MTS_IO_CellularRadioFactory.h1
-rw-r--r--include/mts/MTS_IO_DE910Radio.h4
-rw-r--r--include/mts/MTS_IO_EG25Radio.h2
-rw-r--r--include/mts/MTS_IO_EG95Radio.h2
-rw-r--r--include/mts/MTS_IO_GE910Radio.h3
-rw-r--r--include/mts/MTS_IO_HE910Radio.h4
-rw-r--r--include/mts/MTS_IO_LE866Radio.h2
-rw-r--r--include/mts/MTS_IO_LE910Radio.h2
-rw-r--r--include/mts/MTS_IO_ME910Radio.h2
-rw-r--r--include/mts/MTS_IO_SequansRadio.h83
-rw-r--r--src/MTS_IO_CB610LRadio.cpp58
-rw-r--r--src/MTS_IO_CE910Radio.cpp6
-rw-r--r--src/MTS_IO_CellularRadio.cpp76
-rw-r--r--src/MTS_IO_CellularRadioFactory.cpp10
-rw-r--r--src/MTS_IO_DE910Radio.cpp4
-rw-r--r--src/MTS_IO_EG25Radio.cpp4
-rw-r--r--src/MTS_IO_EG95Radio.cpp4
-rw-r--r--src/MTS_IO_GE910Radio.cpp6
-rw-r--r--src/MTS_IO_HE910Radio.cpp4
-rw-r--r--src/MTS_IO_ICellularRadio.cpp8
-rw-r--r--src/MTS_IO_LE866Radio.cpp4
-rw-r--r--src/MTS_IO_LE910Radio.cpp6
-rw-r--r--src/MTS_IO_ME910Radio.cpp6
-rw-r--r--src/MTS_IO_MccMncTable.cpp3
-rw-r--r--src/MTS_IO_QuectelRadio.cpp6
-rw-r--r--src/MTS_IO_SequansRadio.cpp553
-rw-r--r--src/MTS_IO_TelitRadio.cpp14
32 files changed, 878 insertions, 58 deletions
diff --git a/Makefile b/Makefile
index 95b5e40..7095ddc 100644
--- a/Makefile
+++ b/Makefile
@@ -38,12 +38,14 @@ OBJS += \
src/MTS_IO_ME910Radio.o \
src/MTS_IO_LockFile.o \
src/MTS_IO_MccMncTable.o \
- src/MTS_IO_SerialConnection.o
+ src/MTS_IO_SerialConnection.o \
+ src/MTS_IO_SequansRadio.o \
+ src/MTS_IO_CB610LRadio.o
CC := $(CXX)
CXXFLAGS += -Wall -Werror -std=c++0x -fmessage-length=0 -fPIC -fvisibility=hidden -fvisibility-inlines-hidden
CPPFLAGS += -I=/usr/include/jsoncpp -Iinclude
-LDFLAGS += -s -shared -Wl,-soname,$(APPNAME).so.0
+LDFLAGS += -shared -Wl,-soname,$(APPNAME).so.0
.PHONY: all clean install
diff --git a/data/MccMncTable.csv b/data/MccMncTable.csv
index e79ef10..4c6f986 100644
--- a/data/MccMncTable.csv
+++ b/data/MccMncTable.csv
@@ -718,6 +718,7 @@
"313","130","us","United States","1","AT&T Wireless Inc.","att-first"
"313","140","us","United States","1","FirstNet","att-first"
"313","210","us","United States","1","AT&T Wireless Inc.","att"
+"315","010","us","United States","1","Generic CBRS","cbrs-generic"
"316","010","us","United States","1","Sprint Spectrum",
"316","011","us","United States","1","Southern Communications Services Inc.",
"330","11","pr","Puerto Rico","1787","Puerto Rico Telephone Company Inc. (PRTC)",
diff --git a/include/mts/MTS_IO_CB610LRadio.h b/include/mts/MTS_IO_CB610LRadio.h
new file mode 100644
index 0000000..b802a2b
--- /dev/null
+++ b/include/mts/MTS_IO_CB610LRadio.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2023 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/>.
+ *
+ */
+
+#ifndef MTS_IO_CB610LRADIO_H_
+#define MTS_IO_CB610LRADIO_H_
+
+#include <mts/MTS_IO_SequansRadio.h>
+
+namespace MTS {
+ namespace IO {
+
+ class CB610LRadio : public SequansRadio {
+
+ public:
+ static const std::string MODEL_NAME;
+
+ CB610LRadio(const std::string& sPort);
+ virtual ~CB610LRadio();
+
+ CODE setCellularMode(CELLULAR_MODES networks) override;
+ CODE getSupportedCellularModes(CELLULAR_MODES &networks) override;
+
+ protected:
+
+ private:
+
+ };
+ }
+}
+
+#endif /* MTS_IO_CB610LRADIO_H_ */ \ No newline at end of file
diff --git a/include/mts/MTS_IO_CE910Radio.h b/include/mts/MTS_IO_CE910Radio.h
index 58642cb..8d3b912 100644
--- a/include/mts/MTS_IO_CE910Radio.h
+++ b/include/mts/MTS_IO_CE910Radio.h
@@ -43,6 +43,8 @@ namespace MTS {
virtual ~CE910Radio(){};
CODE setRxDiversity(const Json::Value& jArgs);
+ virtual const std::vector<std::string> getRegistrationCommands() override;
+
protected:
private:
diff --git a/include/mts/MTS_IO_CellularRadio.h b/include/mts/MTS_IO_CellularRadio.h
index e985c21..68c1394 100644
--- a/include/mts/MTS_IO_CellularRadio.h
+++ b/include/mts/MTS_IO_CellularRadio.h
@@ -262,7 +262,7 @@ namespace MTS {
virtual std::string queryCGREGstring();
virtual void setCGREG(std::string value);
- const std::vector<std::string> getRegistrationCommands();
+ virtual const std::vector<std::string> getRegistrationCommands() = 0;
REGISTRATION parseRegResponse(std::string sResult);
CODE getRegistration(REGISTRATION& eRegistration, const std::string& sType);
diff --git a/include/mts/MTS_IO_CellularRadioFactory.h b/include/mts/MTS_IO_CellularRadioFactory.h
index 13f3993..127be65 100644
--- a/include/mts/MTS_IO_CellularRadioFactory.h
+++ b/include/mts/MTS_IO_CellularRadioFactory.h
@@ -56,6 +56,7 @@ namespace MTS {
ICellularRadio* createLE866A1JS(const std::string& sPort = ICellularRadio::DEFAULT_RADIO_PORT) const;
ICellularRadio* createEG95Radio(const std::string& sPort = ICellularRadio::DEFAULT_RADIO_PORT) const;
ICellularRadio* createEG25Radio(const std::string& sPort = ICellularRadio::DEFAULT_RADIO_PORT) const;
+ ICellularRadio* createCB610LRadio(const std::string& sPort = ICellularRadio::DEFAULT_RADIO_PORT) const;
protected:
typedef MTS::IO::ICellularRadio* (CellularRadioFactory::*CREATEFUNCPTR)(const std::string& sPort) const;
diff --git a/include/mts/MTS_IO_DE910Radio.h b/include/mts/MTS_IO_DE910Radio.h
index 9f9b9ae..67964fc 100644
--- a/include/mts/MTS_IO_DE910Radio.h
+++ b/include/mts/MTS_IO_DE910Radio.h
@@ -41,7 +41,9 @@ namespace MTS {
DE910Radio(const std::string& sPort);
virtual ~DE910Radio(){};
- CODE setRxDiversity(const Json::Value& jArgs);
+ CODE setRxDiversity(const Json::Value& jArgs);
+
+ const std::vector<std::string> getRegistrationCommands() override;
protected:
diff --git a/include/mts/MTS_IO_EG25Radio.h b/include/mts/MTS_IO_EG25Radio.h
index e05fa7d..326b192 100644
--- a/include/mts/MTS_IO_EG25Radio.h
+++ b/include/mts/MTS_IO_EG25Radio.h
@@ -35,6 +35,8 @@ namespace MTS {
EG25Radio(const std::string& sPort);
virtual ~EG25Radio();
+ const std::vector<std::string> getRegistrationCommands() override;
+
protected:
private:
diff --git a/include/mts/MTS_IO_EG95Radio.h b/include/mts/MTS_IO_EG95Radio.h
index 6fb47c8..a238e94 100644
--- a/include/mts/MTS_IO_EG95Radio.h
+++ b/include/mts/MTS_IO_EG95Radio.h
@@ -35,6 +35,8 @@ namespace MTS {
EG95Radio(const std::string& sPort);
virtual ~EG95Radio();
+ const std::vector<std::string> getRegistrationCommands() override;
+
protected:
private:
diff --git a/include/mts/MTS_IO_GE910Radio.h b/include/mts/MTS_IO_GE910Radio.h
index 4904ea7..499933c 100644
--- a/include/mts/MTS_IO_GE910Radio.h
+++ b/include/mts/MTS_IO_GE910Radio.h
@@ -41,7 +41,8 @@ namespace MTS {
GE910Radio(const std::string& sPort);
virtual ~GE910Radio(){};
- CODE setRxDiversity(const Json::Value& jArgs);
+ CODE setRxDiversity(const Json::Value& jArgs);
+ const std::vector<std::string> getRegistrationCommands() override;
protected:
diff --git a/include/mts/MTS_IO_HE910Radio.h b/include/mts/MTS_IO_HE910Radio.h
index c8700da..54ad5a3 100644
--- a/include/mts/MTS_IO_HE910Radio.h
+++ b/include/mts/MTS_IO_HE910Radio.h
@@ -39,10 +39,12 @@ namespace MTS {
public:
virtual ~HE910Radio(){};
- CODE setRxDiversity(const Json::Value& jArgs);
+ CODE setRxDiversity(const Json::Value& jArgs);
+ const std::vector<std::string> getRegistrationCommands() override;
protected:
HE910Radio(const std::string& sHE910Model, const std::string& sPort);
+
private:
};
diff --git a/include/mts/MTS_IO_LE866Radio.h b/include/mts/MTS_IO_LE866Radio.h
index 2775e4d..a127f63 100644
--- a/include/mts/MTS_IO_LE866Radio.h
+++ b/include/mts/MTS_IO_LE866Radio.h
@@ -48,6 +48,8 @@ namespace MTS {
LE866Radio(const std::string& sLE866Model, const std::string& sPort);
virtual ~LE866Radio(){};
+ const std::vector<std::string> getRegistrationCommands() override;
+
protected:
private:
diff --git a/include/mts/MTS_IO_LE910Radio.h b/include/mts/MTS_IO_LE910Radio.h
index 6700ee3..e509c95 100644
--- a/include/mts/MTS_IO_LE910Radio.h
+++ b/include/mts/MTS_IO_LE910Radio.h
@@ -48,6 +48,8 @@ namespace MTS {
CODE setUeModeOfOperation(ICellularRadio::UE_MODES_OF_OPERATION mode) override;
CODE getUeModeOfOperation(ICellularRadio::UE_MODES_OF_OPERATION& mode) override;
+ const std::vector<std::string> getRegistrationCommands() override;
+
protected:
const std::vector<std::string>& getDiagCommands(bool bIsSimReady = true) override;
diff --git a/include/mts/MTS_IO_ME910Radio.h b/include/mts/MTS_IO_ME910Radio.h
index 93af86f..7c34009 100644
--- a/include/mts/MTS_IO_ME910Radio.h
+++ b/include/mts/MTS_IO_ME910Radio.h
@@ -36,6 +36,8 @@ namespace MTS {
virtual CODE setRxDiversity(const Json::Value& jArgs);
+ const std::vector<std::string> getRegistrationCommands() override;
+
protected:
private:
diff --git a/include/mts/MTS_IO_SequansRadio.h b/include/mts/MTS_IO_SequansRadio.h
new file mode 100644
index 0000000..11f2c91
--- /dev/null
+++ b/include/mts/MTS_IO_SequansRadio.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2023 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/>.
+ *
+ */
+
+#ifndef MTS_IO_SEQUANSRADIO
+#define MTS_IO_SEQUANSRADIO
+
+#include <mts/MTS_IO_CellularRadio.h>
+
+namespace MTS {
+ namespace IO {
+
+ class SequansRadio : public CellularRadio {
+
+ public:
+ bool resetRadio(uint32_t iTimeoutMillis = 5000) override;
+
+ CODE getVendorFirmware(std::string& sVendorFirmware) override;
+ CODE getModel(std::string& sModel) override;
+ CODE getIccid(std::string& sIccid) override;
+ CODE getService(std::string& sService) override;
+ CODE getNetwork(std::string& sNetwork) override;
+ CODE getNetworkStatus(Json::Value& jData) override;
+
+ CODE convertSignalStrengthTodBm(const int32_t& iRssi, int32_t& iDBm) override;
+ CODE convertdBmToSignalStrength(const int32_t& dBm, int32_t& iRssi) override;
+
+ CODE setMdn(const Json::Value& jArgs) override;
+
+ CODE setUeModeOfOperation(ICellularRadio::UE_MODES_OF_OPERATION mode) override;
+ CODE getUeModeOfOperation(ICellularRadio::UE_MODES_OF_OPERATION& mode) override;
+
+ CODE setRxDiversity(const Json::Value& jArgs) override;
+
+ const std::vector<std::string> getRegistrationCommands() override;
+
+ protected:
+ SequansRadio(const std::string& sName, const std::string& sRadioPort);
+
+ CODE getIsSimInserted(bool& bData) override;
+ CODE getSimLockAttempts(int& iAttemptsPin, int& iAttemptsPuk) override;
+
+ const std::vector<std::string>& getDiagCommands(bool bIsSimReady = true) override;
+
+ private:
+ /*
+ * @brief getSimLockAttemptsByType - get the number of remaining attempts to
+ * enter the specified SIM password type
+ *
+ * @param sType - SIM password type, "SIM PIN", "SIM PUK", "SIM PIN2" or "SIM PUK2".
+ * @param iAttempts - the number of remaining attempts for this password type.
+ * @return CODE::SUCCESS when fetched successfully,
+ * CODE::NOT_APPLICABLE when the modem doesn't support this feature,
+ * CODE::NO_RESPONSE when the modem doesn't respond,
+ * CODE::ERROR when the radio returns "ERROR" (SIM card removed, etc),
+ * CODE::FAILURE otherwise (modem is inaccessible, etc).
+ */
+ CODE getSimLockAttemptsByType(const std::string& sType, int& iAttempts);
+ CODE getNetworkStatusSQN(Json::Value& jData, Json::Value& jDebug);
+ CODE getNetworkStatusSignal(Json::Value& jData, Json::Value& jDebug);
+ CODE getNetworkStatusTxPower(Json::Value& jData, Json::Value& jDebug);
+
+ };
+ }
+}
+
+#endif /* MTS_IO_SEQUANSRADIO */
diff --git a/src/MTS_IO_CB610LRadio.cpp b/src/MTS_IO_CB610LRadio.cpp
new file mode 100644
index 0000000..7fbd884
--- /dev/null
+++ b/src/MTS_IO_CB610LRadio.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2023 by Multi-Tech Systems
+ *
+ * This file is part of libmts-io.
+ *
+ * libmts-io is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts-io is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libmts-io. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <mts/MTS_IO_CB610LRadio.h>
+
+#include <mts/MTS_Logger.h>
+#include <mts/MTS_Thread.h>
+#include <mts/MTS_Text.h>
+#include <mts/MTS_Timer.h>
+
+using namespace MTS::IO;
+
+const std::string CB610LRadio::MODEL_NAME("CB610L");
+
+CB610LRadio::CB610LRadio(const std::string& sPort)
+: SequansRadio(MODEL_NAME, sPort) {
+
+}
+
+CB610LRadio::~CB610LRadio() {
+
+}
+
+ICellularRadio::CODE CB610LRadio::setCellularMode(CELLULAR_MODES networks) {
+ if (networks != CELLULAR_MODE_4G) {
+ printError("%s| The CB610L radios support only the 4G cellular mode", getName().c_str());
+ return FAILURE;
+ }
+ std::string sCmd("AT+WS46=28");
+ std::string cmdResult = sendCommand(sCmd);
+ if (cmdResult.find(ICellularRadio::RSP_OK) == std::string::npos) {
+ printError("%s| AT+WS46=28 returned unexpected response: [%s][%s]", getName().c_str(), sCmd.c_str(), cmdResult.c_str());
+ return FAILURE;
+ }
+ return SUCCESS;
+}
+
+ICellularRadio::CODE CB610LRadio::getSupportedCellularModes(CELLULAR_MODES &networks) {
+ networks = CELLULAR_MODE_4G;
+ return SUCCESS;
+} \ No newline at end of file
diff --git a/src/MTS_IO_CE910Radio.cpp b/src/MTS_IO_CE910Radio.cpp
index d1cad9b..f0ec560 100644
--- a/src/MTS_IO_CE910Radio.cpp
+++ b/src/MTS_IO_CE910Radio.cpp
@@ -41,5 +41,9 @@ CE910Radio::CE910Radio(const std::string& sPort)
ICellularRadio::CODE CE910Radio::setRxDiversity(const Json::Value& jArgs) {
/* Command string for CE radios: N/A */
- return FAILURE;
+ return NOT_APPLICABLE;
+}
+
+const std::vector<std::string> CE910Radio::getRegistrationCommands() {
+ return { "CREG" };
}
diff --git a/src/MTS_IO_CellularRadio.cpp b/src/MTS_IO_CellularRadio.cpp
index 069d5fa..3ce97ec 100644
--- a/src/MTS_IO_CellularRadio.cpp
+++ b/src/MTS_IO_CellularRadio.cpp
@@ -64,27 +64,41 @@ namespace {
// http://niviuk.free.fr/lte_band.php
const nameRangeMap EULTRAband[] =
{
- {"EUTRAN BAND1", 0, 599}, {"EUTRAN BAND2", 600, 1199},
- {"EUTRAN BAND3", 1200, 1949}, {"EUTRAN BAND4", 1950, 2399},
- {"EUTRAN BAND5", 2400, 2649}, {"EUTRAN BAND6", 2650, 2749},
- {"EUTRAN BAND7", 2750, 3449}, {"EUTRAN BAND8", 3450, 3799},
- {"EUTRAN BAND9", 3800, 4149}, {"EUTRAN BAND10", 4150, 4749},
- {"EUTRAN BAND11", 4750, 4999}, {"EUTRAN BAND12", 5000, 5179},
- {"EUTRAN BAND13", 5180, 5279}, {"EUTRAN BAND14", 5280, 5379},
- {"EUTRAN BAND17", 5730, 5849}, {"EUTRAN BAND18", 5850, 5999},
- {"EUTRAN BAND19", 6000, 6149}, {"EUTRAN BAND20", 6150, 6449},
- {"EUTRAN BAND21", 6450, 6525}, {"EUTRAN BAND22", 6600, 7399},
- {"EUTRAN BAND23", 7500, 7699}, {"EUTRAN BAND24", 7700, 8039},
- {"EUTRAN BAND25", 8040, 8689}, {"EUTRAN BAND26", 8690, 9039},
- {"EUTRAN BAND27", 9040, 9209}, {"EUTRAN BAND28", 9210, 9659},
- {"EUTRAN BAND29", 9660, 9769}, {"EUTRAN BAND30", 9770, 9869},
- {"EUTRAN BAND31", 9870, 9919}, {"EUTRAN BAND32", 9920, 10359},
- {"EUTRAN BAND33", 36000, 36199}, {"EUTRAN BAND34", 36200, 36349},
- {"EUTRAN BAND35", 36350, 36949}, {"EUTRAN BAND36", 36950, 37549},
- {"EUTRAN BAND37", 37550, 37749}, {"EUTRAN BAND38", 37750, 38249},
- {"EUTRAN BAND39", 38250, 38649}, {"EUTRAN BAND40", 38650, 39649},
- {"EUTRAN BAND41", 39650, 41589}, {"EUTRAN BAND42", 41590, 43589},
- {"EUTRAN BAND43", 43590, 45589}, {"EUTRAN BAND44", 45590, 46589}
+ {"EUTRAN BAND1", 0, 599}, {"EUTRAN BAND2", 600, 1199},
+ {"EUTRAN BAND3", 1200, 1949}, {"EUTRAN BAND4", 1950, 2399},
+ {"EUTRAN BAND5", 2400, 2649}, {"EUTRAN BAND6", 2650, 2749},
+ {"EUTRAN BAND7", 2750, 3449}, {"EUTRAN BAND8", 3450, 3799},
+ {"EUTRAN BAND9", 3800, 4149}, {"EUTRAN BAND10", 4150, 4749},
+ {"EUTRAN BAND11", 4750, 4999}, {"EUTRAN BAND12", 5000, 5179},
+ {"EUTRAN BAND13", 5180, 5279}, {"EUTRAN BAND14", 5280, 5379},
+ {"EUTRAN BAND17", 5730, 5849}, {"EUTRAN BAND18", 5850, 5999},
+ {"EUTRAN BAND19", 6000, 6149}, {"EUTRAN BAND20", 6150, 6449},
+ {"EUTRAN BAND21", 6450, 6525}, {"EUTRAN BAND22", 6600, 7399},
+ {"EUTRAN BAND23", 7500, 7699}, {"EUTRAN BAND24", 7700, 8039},
+ {"EUTRAN BAND25", 8040, 8689}, {"EUTRAN BAND26", 8690, 9039},
+ {"EUTRAN BAND27", 9040, 9209}, {"EUTRAN BAND28", 9210, 9659},
+ {"EUTRAN BAND29", 9660, 9769}, {"EUTRAN BAND30", 9770, 9869},
+ {"EUTRAN BAND31", 9870, 9919}, {"EUTRAN BAND32", 9920, 10359},
+ {"EUTRAN BAND33", 36000, 36199}, {"EUTRAN BAND34", 36200, 36349},
+ {"EUTRAN BAND35", 36350, 36949}, {"EUTRAN BAND36", 36950, 37549},
+ {"EUTRAN BAND37", 37550, 37749}, {"EUTRAN BAND38", 37750, 38249},
+ {"EUTRAN BAND39", 38250, 38649}, {"EUTRAN BAND40", 38650, 39649},
+ {"EUTRAN BAND41", 39650, 41589}, {"EUTRAN BAND42", 41590, 43589},
+ {"EUTRAN BAND43", 43590, 45589}, {"EUTRAN BAND44", 45590, 46589},
+ {"EUTRAN BAND45", 46590, 46789}, {"EUTRAN BAND46", 46790, 54539},
+ {"EUTRAN BAND47", 54540, 55239}, {"EUTRAN BAND48", 55240, 56739},
+ {"EUTRAN BAND49", 56740, 58239}, {"EUTRAN BAND50", 58240, 59089},
+ {"EUTRAN BAND51", 59090, 59139}, {"EUTRAN BAND52", 59140, 60139},
+ {"EUTRAN BAND53", 60140, 60254},
+ {"EUTRAN BAND65", 65536, 66435}, {"EUTRAN BAND66", 66436, 67335},
+ {"EUTRAN BAND67", 67336, 67535}, {"EUTRAN BAND68", 67536, 67835},
+ {"EUTRAN BAND69", 67836, 68335}, {"EUTRAN BAND70", 68336, 68585},
+ {"EUTRAN BAND71", 68586, 68935}, {"EUTRAN BAND72", 68936, 68985},
+ {"EUTRAN BAND73", 68986, 69035}, {"EUTRAN BAND74", 69036, 69465},
+ {"EUTRAN BAND75", 69466, 70315}, {"EUTRAN BAND76", 70316, 70365},
+ {"EUTRAN BAND85", 70366, 70545},
+ {"EUTRAN BAND87", 70546, 70595}, {"EUTRAN BAND88", 70596, 70645},
+ {"EUTRAN BAND103", 70646, 70655}
};
}
@@ -225,7 +239,7 @@ ICellularRadio::CODE CellularRadio::getHardware(std::string& sHardware) {
ICellularRadio::CODE CellularRadio::getManufacturer(std::string& sManufacturer) {
printTrace("%s| Get Manufacturer", m_sName.c_str());
sManufacturer = ICellularRadio::VALUE_NOT_SUPPORTED;
- std::string sCmd("AT+GMI");
+ std::string sCmd("AT+CGMI");
std::string sResult = sendCommand(sCmd);
size_t pos = sResult.find(ICellularRadio::RSP_OK);
if (pos == std::string::npos) {
@@ -309,6 +323,13 @@ ICellularRadio::CODE CellularRadio::getSimStatusSummary(Json::Value& jData) {
do {
retCode = getIsSimInserted(bIsSimInserted);
+
+ // Some radio modems do not have separate commands for the SIM presence check
+ if (retCode == NOT_APPLICABLE) {
+ retCode = SUCCESS;
+ bIsSimInserted = true;
+ }
+
if (retCode != SUCCESS) {
break;
}
@@ -841,17 +862,6 @@ void CellularRadio::initMipProfile(Json::Value& jData) {
jData[ICellularRadio::KEY_MIP_MNHASS] = false;
}
-const std::vector<std::string> CellularRadio::getRegistrationCommands() {
- std::string sType;
- convertModelToType(getName(), sType);
-
- if (sType == VALUE_TYPE_LTE) {
- return { "CREG", "CGREG", "CEREG" };
- } else {
- return { "CREG", "CGREG" };
- }
-}
-
ICellularRadio::REGISTRATION CellularRadio::parseRegResponse(std::string sResult) {
size_t start = sResult.find(',');
size_t stop = sResult.find(' ', start);
diff --git a/src/MTS_IO_CellularRadioFactory.cpp b/src/MTS_IO_CellularRadioFactory.cpp
index 1a2cee2..f545599 100644
--- a/src/MTS_IO_CellularRadioFactory.cpp
+++ b/src/MTS_IO_CellularRadioFactory.cpp
@@ -38,6 +38,7 @@
#include <mts/MTS_IO_DE910Radio.h>
#include "mts/MTS_IO_EG95Radio.h"
#include "mts/MTS_IO_EG25Radio.h"
+#include "mts/MTS_IO_CB610LRadio.h"
#include <mts/MTS_Logger.h>
using namespace MTS::IO;
@@ -62,6 +63,7 @@ CellularRadioFactory::CellularRadioFactory() {
m_mCreationMap[LE866A1JSRadio::MODEL_NAME] = &CellularRadioFactory::createLE866A1JS;
m_mCreationMap[EG95Radio::MODEL_NAME] = &CellularRadioFactory::createEG95Radio;
m_mCreationMap[EG25Radio::MODEL_NAME] = &CellularRadioFactory::createEG25Radio;
+ m_mCreationMap[CB610LRadio::MODEL_NAME] = &CellularRadioFactory::createCB610LRadio;
}
ICellularRadio* CellularRadioFactory::create(const std::string& sModel, const std::string& sPort) {
@@ -101,7 +103,7 @@ std::string CellularRadioFactory::identifyRadio(const std::string& sPort) {
//Get model
int count = 0;
- std::string sCmd("AT+GMM");
+ std::string sCmd("AT+CGMM");
std::string sResult;
do {
sResult = ICellularRadio::sendCommand(apIo, sCmd, ICellularRadio::DEFAULT_BAIL_STRINGS, 1000, ICellularRadio::CR);
@@ -120,7 +122,7 @@ std::string CellularRadioFactory::identifyRadio(const std::string& sPort) {
}
std::string sModel = ICellularRadio::extractModelFromResult(sResult);
- printDebug("RADIO| Extracted [%s] from AT+GMM query", sModel.c_str());
+ printDebug("RADIO| Extracted [%s] from AT+CGMM query", sModel.c_str());
apIo->close();
return sModel;
}
@@ -200,3 +202,7 @@ ICellularRadio* CellularRadioFactory::createEG95Radio(const std::string& sPort)
ICellularRadio* CellularRadioFactory::createEG25Radio(const std::string& sPort) const {
return new EG25Radio(sPort);
}
+
+ICellularRadio* CellularRadioFactory::createCB610LRadio(const std::string& sPort) const {
+ return new CB610LRadio(sPort);
+} \ No newline at end of file
diff --git a/src/MTS_IO_DE910Radio.cpp b/src/MTS_IO_DE910Radio.cpp
index 26668f1..d45515d 100644
--- a/src/MTS_IO_DE910Radio.cpp
+++ b/src/MTS_IO_DE910Radio.cpp
@@ -50,3 +50,7 @@ ICellularRadio::CODE DE910Radio::setRxDiversity(const Json::Value& jArgs) {
return sendBasicCommand(sCmd);
}
+
+const std::vector<std::string> DE910Radio::getRegistrationCommands() {
+ return { "CREG" };
+} \ No newline at end of file
diff --git a/src/MTS_IO_EG25Radio.cpp b/src/MTS_IO_EG25Radio.cpp
index c6d1c34..effac4c 100644
--- a/src/MTS_IO_EG25Radio.cpp
+++ b/src/MTS_IO_EG25Radio.cpp
@@ -38,4 +38,8 @@ EG25Radio::~EG25Radio() {
ICellularRadio::CODE EG25Radio::getSupportedCellularModes(CELLULAR_MODES &networks) {
networks = static_cast<CELLULAR_MODES>(CELLULAR_MODE_2G | CELLULAR_MODE_3G | CELLULAR_MODE_4G);
return SUCCESS;
+}
+
+const std::vector<std::string> EG25Radio::getRegistrationCommands() {
+ return { "CREG", "CGREG", "CEREG" };
} \ No newline at end of file
diff --git a/src/MTS_IO_EG95Radio.cpp b/src/MTS_IO_EG95Radio.cpp
index 83d6489..8dc79a3 100644
--- a/src/MTS_IO_EG95Radio.cpp
+++ b/src/MTS_IO_EG95Radio.cpp
@@ -52,4 +52,8 @@ ICellularRadio::CODE EG95Radio::getSupportedCellularModes(CELLULAR_MODES &networ
}
return SUCCESS;
+}
+
+const std::vector<std::string> EG95Radio::getRegistrationCommands() {
+ return { "CREG", "CGREG", "CEREG" };
} \ No newline at end of file
diff --git a/src/MTS_IO_GE910Radio.cpp b/src/MTS_IO_GE910Radio.cpp
index 61332b5..22a6482 100644
--- a/src/MTS_IO_GE910Radio.cpp
+++ b/src/MTS_IO_GE910Radio.cpp
@@ -41,5 +41,9 @@ GE910Radio::GE910Radio(const std::string& sPort)
ICellularRadio::CODE GE910Radio::setRxDiversity(const Json::Value& jArgs) {
/* Command string for GE radios: N/A */
- return FAILURE;
+ return NOT_APPLICABLE;
}
+
+const std::vector<std::string> GE910Radio::getRegistrationCommands() {
+ return { "CREG", "CGREG" };
+} \ No newline at end of file
diff --git a/src/MTS_IO_HE910Radio.cpp b/src/MTS_IO_HE910Radio.cpp
index 4c0a759..a1fddbd 100644
--- a/src/MTS_IO_HE910Radio.cpp
+++ b/src/MTS_IO_HE910Radio.cpp
@@ -48,3 +48,7 @@ ICellularRadio::CODE HE910Radio::setRxDiversity(const Json::Value& jArgs) {
return sendBasicCommand(sCmd);
}
+
+const std::vector<std::string> HE910Radio::getRegistrationCommands() {
+ return { "CREG", "CGREG" };
+}
diff --git a/src/MTS_IO_ICellularRadio.cpp b/src/MTS_IO_ICellularRadio.cpp
index 05af28d..e42713d 100644
--- a/src/MTS_IO_ICellularRadio.cpp
+++ b/src/MTS_IO_ICellularRadio.cpp
@@ -239,6 +239,9 @@ MTS::IO::ICellularRadio::CODE MTS::IO::ICellularRadio::convertModelToMtsShortCod
eCode = ERROR;
}
}
+ } else if (sModel.find("CB610L") == 0) {
+ sCode = "L6G1";
+ eCode = SUCCESS;
} else {
sCode = VALUE_NOT_SUPPORTED;
printError("RADIO| Could not identify MTS short code from model. [%s]", sModel.c_str());
@@ -335,6 +338,9 @@ MTS::IO::ICellularRadio::CODE MTS::IO::ICellularRadio::convertModelToType(const
} else if (sModel.find("EG25") == 0) {
sType = VALUE_TYPE_LTE;
eCode = SUCCESS;
+ } else if (sModel.find("CB610L") == 0) {
+ sType = VALUE_TYPE_LTE;
+ eCode = SUCCESS;
} else {
sType = VALUE_TYPE_GSM;
eCode = ERROR;
@@ -504,6 +510,8 @@ std::string MTS::IO::ICellularRadio::extractModelFromResult(const std::string& s
sModel = "EG95";
} else if(sResult.find("EG25") != std::string::npos) {
sModel = "EG25";
+ } else if(sResult.find("CB610L") != std::string::npos) {
+ sModel = "CB610L";
}
return sModel;
}
diff --git a/src/MTS_IO_LE866Radio.cpp b/src/MTS_IO_LE866Radio.cpp
index 85b8dc3..f695707 100644
--- a/src/MTS_IO_LE866Radio.cpp
+++ b/src/MTS_IO_LE866Radio.cpp
@@ -36,4 +36,6 @@ LE866Radio::LE866Radio(const std::string& sLE866Model, const std::string& sPort)
}
-
+const std::vector<std::string> LE866Radio::getRegistrationCommands() {
+ return { "CREG", "CGREG", "CEREG" };
+}
diff --git a/src/MTS_IO_LE910Radio.cpp b/src/MTS_IO_LE910Radio.cpp
index 2f1debb..3b2864b 100644
--- a/src/MTS_IO_LE910Radio.cpp
+++ b/src/MTS_IO_LE910Radio.cpp
@@ -64,7 +64,7 @@ ICellularRadio::CODE LE910Radio::getModemLocation(std::string& sLocation) {
}
printDebug("modem reply: [%s]", sResult.c_str());
size_t start = sResult.find(':');
- if (start==std::string::npos){
+ if (start==std::string::npos) {
start = 0;
} else {
start++;
@@ -230,3 +230,7 @@ const std::vector<std::string>& LE910Radio::getDiagCommands(bool bIsSimReady) {
return vSimLockedCommands;
}
}
+
+const std::vector<std::string> LE910Radio::getRegistrationCommands() {
+ return { "CREG", "CGREG", "CEREG" };
+}
diff --git a/src/MTS_IO_ME910Radio.cpp b/src/MTS_IO_ME910Radio.cpp
index ad3e7ec..1f4ff58 100644
--- a/src/MTS_IO_ME910Radio.cpp
+++ b/src/MTS_IO_ME910Radio.cpp
@@ -31,5 +31,9 @@ ME910Radio::ME910Radio(const std::string& sME910Model, const std::string& sPort)
}
ICellularRadio::CODE ME910Radio::setRxDiversity(const Json::Value& jArgs) {
- return FAILURE;
+ return NOT_APPLICABLE;
+}
+
+const std::vector<std::string> ME910Radio::getRegistrationCommands() {
+ return { "CREG", "CGREG", "CEREG" };
}
diff --git a/src/MTS_IO_MccMncTable.cpp b/src/MTS_IO_MccMncTable.cpp
index f1940be..6b45e77 100644
--- a/src/MTS_IO_MccMncTable.cpp
+++ b/src/MTS_IO_MccMncTable.cpp
@@ -21,7 +21,7 @@
/*!
\file MTS_IO_MccMncTable.cpp
\brief Auto-Generated MCC-MNC Lookup Table
- \date 2023-01-06
+ \date 2023-01-26
\author sgodinez
An Auto-Generated MCC-MNC Lookup Table
@@ -798,6 +798,7 @@ void MccMncTable::createTable() {
m_mTable[787][304] = "us,United States,1,AT&T Wireless Inc.,att-first";
m_mTable[787][320] = "us,United States,1,FirstNet,att-first";
m_mTable[787][528] = "us,United States,1,AT&T Wireless Inc.,att";
+ m_mTable[789][16] = "us,United States,1,Generic CBRS,cbrs-generic";
m_mTable[790][16] = "us,United States,1,Sprint Spectrum,";
m_mTable[790][17] = "us,United States,1,Southern Communications Services Inc.,";
m_mTable[816][287] = "pr,Puerto Rico,1787,Puerto Rico Telephone Company Inc. (PRTC),";
diff --git a/src/MTS_IO_QuectelRadio.cpp b/src/MTS_IO_QuectelRadio.cpp
index 3a5924c..af7adde 100644
--- a/src/MTS_IO_QuectelRadio.cpp
+++ b/src/MTS_IO_QuectelRadio.cpp
@@ -288,7 +288,7 @@ CellularRadio::CODE QuectelRadio::getNetworkStatus(Json::Value& jData) {
Json::Value jQuectelDebug;
if (vParts.size() < 3) {
- printDebug("%s| Network Status command reponse is an unknown format: [%s][%s]", getName().c_str(), sCmd.c_str(), sResult.c_str());
+ printDebug("%s| Network Status command response is an unknown format: [%s][%s]", getName().c_str(), sCmd.c_str(), sResult.c_str());
printTrace("%s| Network Status:\n%s\n", getName().c_str(), jData.toStyledString().c_str());
return SUCCESS; //return SUCCESS because getCommonNetworkStats() succeeded at top of this function
} else {
@@ -410,7 +410,7 @@ CellularRadio::CODE QuectelRadio::getNetworkStatus(Json::Value& jData) {
jDebug[ICellularRadio::KEY_SD] = sValue;
}
- // LAC is not provided by AT+QENG in WCDMA mode. Use another command instead
+ // LAC is not provided by AT+QENG in LTE mode. Use another command instead
jData[ICellularRadio::KEY_LAC] = queryLteLac();
jData["quectelDebug"] = jQuectelDebug;
@@ -842,7 +842,7 @@ ICellularRadio::CODE QuectelRadio::convertToActiveBand(const std::string& sQuect
ICellularRadio::CODE QuectelRadio::setCellularMode(CELLULAR_MODES networks) {
std::string prefNet;
unsigned int prefOnly = 0, prefCount = 0;
- for (int i = sizeof(networks)*CHAR_BIT-1; i>=0; --i){
+ for (int i = sizeof(networks)*CHAR_BIT-1; i>=0; --i) {
switch (1<<i & networks) {
case ICellularRadio::CELLULAR_MODE_2G: prefNet += "01" ; prefOnly = 1; prefCount++; break;
case ICellularRadio::CELLULAR_MODE_3G: prefNet += "0302"; prefOnly = 2; prefCount++; break;
diff --git a/src/MTS_IO_SequansRadio.cpp b/src/MTS_IO_SequansRadio.cpp
new file mode 100644
index 0000000..f3b32fb
--- /dev/null
+++ b/src/MTS_IO_SequansRadio.cpp
@@ -0,0 +1,553 @@
+/*
+ * Copyright (C) 2023 by Multi-Tech Systems
+ *
+ * This file is part of libmts-io.
+ *
+ * libmts-io is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts-io is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libmts-io. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <mts/MTS_IO_SequansRadio.h>
+
+#include <mts/MTS_Logger.h>
+#include <mts/MTS_Thread.h>
+#include <mts/MTS_Text.h>
+#include <mts/MTS_Timer.h>
+
+using namespace MTS::IO;
+
+bool SequansRadio::resetRadio(uint32_t iTimeoutMillis) {
+ printInfo("%s| Rebooting radio", getName().c_str());
+ if (sendBasicCommand("AT^RESET") == SUCCESS) {
+ if (iTimeoutMillis > 5000) {
+ MTS::Thread::sleep(5000);
+ iTimeoutMillis -= 5000;
+ }
+ return resetConnection(iTimeoutMillis);
+ }
+
+ return false;
+}
+
+ICellularRadio::CODE SequansRadio::getVendorFirmware(std::string& sVendorFirmware) {
+ return getFirmware(sVendorFirmware);
+}
+
+ICellularRadio::CODE SequansRadio::getModel(std::string& sModel) {
+ printTrace("%s| Get Model", getName().c_str());
+ //Always returns SUCCESS because the model should be m_sName
+ sModel = getName();
+ std::string sCmd("AT+CGMM");
+ std::string sResult = sendCommand(sCmd);
+ if (sResult.find("OK") == std::string::npos) {
+ printWarning("%s| Unable to get model from radio. Returning [%s]", getName().c_str(), getName().c_str());
+ return SUCCESS;
+ } else {
+ sModel = extractModelFromResult(sResult);
+ if (sModel.size() == 0) {
+ printWarning("%s| Unable to get model from radio. Returning [%s]", getName().c_str(), getName().c_str());
+ return SUCCESS;
+ }
+ }
+
+ printDebug("%s| Extracted [%s] from [%s] query", getName().c_str(), sModel.c_str(), sCmd.c_str());
+ if (sModel != getName()) {
+ printWarning("%s| Model identified [%s] does not match expected [%s]. Returning [%s]",
+ getName().c_str(), sModel.c_str(), getName().c_str(), sModel.c_str());
+ }
+
+ return SUCCESS;
+}
+
+ICellularRadio::CODE SequansRadio::getIccid(std::string& sIccid) {
+ printTrace("%s| Get ICCID", getName().c_str());
+
+ const int iEFiccidId = 0x2FE2;
+ const uint8_t iOffsetHigh = 0;
+ const uint8_t iOffsetLow = 0;
+ const uint8_t iNumBytes = 10;
+
+ CODE rc;
+ std::string sEFiccidContent;
+
+ rc = simAccessReadBinary(iEFiccidId, iOffsetLow, iOffsetHigh, iNumBytes, sEFiccidContent);
+ if (rc != SUCCESS) {
+ printError("%s| Failed to determine the SIM ICCID", getName().c_str());
+ return rc;
+ }
+
+ int iEFiccidLen = sEFiccidContent.size();
+ if (iEFiccidLen != 20) {
+ printError("%s| Invalid length of the raw ICCID value: expected [20], actual: [%d]", getName().c_str(), iEFiccidLen);
+ return FAILURE;
+ }
+
+ // sEFiccidContent is a raw Binary-Coded Decimal string with swapped nibbles.
+ for (int i = 0; i < iEFiccidLen; i+=2) {
+ std::string sPart = sEFiccidContent.substr(i, 2);
+ std::swap(sPart[0], sPart[1]);
+ sIccid.append(sPart);
+ }
+
+ printDebug("%s| Got ICCID [%s]", getName().c_str(), sIccid.c_str());
+
+ return SUCCESS;
+}
+
+ICellularRadio::CODE SequansRadio::getService(std::string& sService) {
+ printTrace("%s| Get Service", getName().c_str());
+ sService = ICellularRadio::VALUE_NOT_SUPPORTED;
+ std::string sCmd("AT+COPS?");
+ std::string sPrefix("+COPS:");
+ std::string sResult;
+ CODE rc;
+
+ rc = sendBasicQuery(sCmd, sPrefix, sResult, 100);
+ if (SUCCESS != rc) {
+ printWarning("%s| Unable to get Service from radio using command [%s]", getName().c_str(), sCmd.c_str());
+ return rc;
+ }
+
+ std::vector<std::string> vParts = MTS::Text::split(sResult, ',');
+ int32_t iAccessTechnology;
+
+ // +COPS: <mode>[,<format>[,<oper>][,<Act>]]
+ if (vParts.size() < 4 || !MTS::Text::parse(iAccessTechnology, vParts[3])) {
+ printWarning("%s| Unable to get Service from radio using command [%s]", getName().c_str(), sCmd.c_str());
+ return FAILURE;
+ }
+
+ switch(iAccessTechnology) {
+ case 0 : sService = "GPRS" ; break; // GSM
+ case 1 : sService = "GPRS" ; break; // GSM Compact
+ case 2 : sService = "WCDMA" ; break; // UTRAN
+ case 3 : sService = "EGPRS" ; break; // GSM W/EGPRS
+ case 4 : sService = "HSDPA" ; break; // UTRAN W/HSDPA
+ case 5 : sService = "WCDMA" ; break; // UTRAN W/HSUPA
+ case 6 : sService = "HSDPA" ; break; // UTRAN W/HSDPA and HSUPA
+ case 7 : sService = "LTE" ; break; // E-UTRAN
+ case 8 : sService = "EGPRS" ; break; // EC-GSM-IoT
+ case 9 : sService = "LTE" ; break; // E-UTRAN (NB-S1 mode)
+
+ default: sService = ICellularRadio::VALUE_UNKNOWN; break;
+ }
+
+ printDebug("%s| Service ID: [%d][%s]", getName().c_str(), iAccessTechnology, sService.c_str());
+
+ return SUCCESS;
+}
+
+ICellularRadio::CODE SequansRadio::getNetwork(std::string& sNetwork) {
+ printTrace("%s| Get Network", getName().c_str());
+ sNetwork = ICellularRadio::VALUE_NOT_SUPPORTED;
+ std::string sCmd("AT+COPS?");
+ std::string sPrefix("+COPS:");
+ std::string sResult;
+ CODE rc;
+
+ rc = sendBasicQuery(sCmd, sPrefix, sResult, 100);
+ if (SUCCESS != rc) {
+ printWarning("%s| Unable to get network name from radio using command [%s]", getName().c_str(), sCmd.c_str());
+ return rc;
+ }
+ std::vector<std::string> vParts = MTS::Text::split(sResult, ",");
+
+ if (vParts.size() > 3) {
+ const std::string sValue = vParts[2];
+
+ // +COPS: 0,2,"315010",7
+ // ^start ^end
+ size_t start = sValue.find("\"") + 1;
+ size_t end = sValue.find("\"", start);
+ sNetwork = sValue.substr(start, end-start);
+ } else {
+ sNetwork = ""; // Not connected to any network
+ }
+
+ return SUCCESS;
+}
+
+// AT+SQNQRCCI? -- This command queries and reports several information from camped cell.
+// +SQNQRCCI: [<mcc>,<mnc>,<cellId>,<pci>,<tac>,<dlBw>,<specialSubframeConfig>,<subframeAssignment>,<dlEarfcn>,<dlTxMode>,<band>]
+ICellularRadio::CODE SequansRadio::getNetworkStatusSQN(Json::Value& jData, Json::Value& jDebug) {
+ std::string sCmd;
+ std::string sResult;
+ std::string sPrefix;
+ std::vector<std::string> vParts;
+ CODE rc;
+
+ sCmd = "AT+SQNQRCCI?";
+ sPrefix = "+SQNQRCCI:";
+
+ rc = sendBasicQuery(sCmd, sPrefix, sResult, 200);
+ if (SUCCESS != rc) {
+ printDebug("%s| Network Status command returned unexpected response: [%s][%s]", getName().c_str(), sCmd.c_str(), sResult.c_str());
+ printTrace("%s| Network Status:\n%s\n", getName().c_str(), jData.toStyledString().c_str());
+ return rc;
+ }
+
+ // <mcc>,<mnc>,<cellId>,<pci>,<tac>,<dlBw>,<specialSubframeConfig>,<subframeAssignment>,<dlEarfcn>,<dlTxMode>,<band>
+ // [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10]
+ vParts = MTS::Text::split(sResult, ",");
+
+ if (vParts.size() < 11) {
+ printDebug("%s| Network Status command reponse is an unknown format: [%s][%s]", getName().c_str(), sCmd.c_str(), sResult.c_str());
+ printTrace("%s| Network Status:\n%s\n", getName().c_str(), jData.toStyledString().c_str());
+ return FAILURE;
+ }
+
+ jData[ICellularRadio::KEY_MCC] = vParts[0];
+ jData[ICellularRadio::KEY_MNC] = vParts[1];
+ jData[ICellularRadio::KEY_CID] = vParts[2];
+ jData["tac"] = vParts[4];
+ jData[ICellularRadio::KEY_CHANNEL] = vParts[8];
+ jData[ICellularRadio::KEY_ABND] = "EUTRAN BAND" + vParts[10]; // concat string to convert to common format
+
+ return SUCCESS;
+}
+
+// AT+CESQ? -- Execution command returns received signal quality parameters.
+// +CESQ: <rxlev>,<ber>,<rscp>,<ecno>,<rsrq>,<rsrp>
+ICellularRadio::CODE SequansRadio::getNetworkStatusSignal(Json::Value& jData, Json::Value& jDebug) {
+ std::string sCmd;
+ std::string sResult;
+ std::string sPrefix;
+ std::vector<std::string> vParts;
+ CODE rc;
+
+ sCmd = "AT+CESQ";
+ sPrefix = "+CESQ:";
+
+ rc = sendBasicQuery(sCmd, sPrefix, sResult, 200);
+ if (SUCCESS != rc) {
+ printDebug("%s| Network Status command returned unexpected response: [%s][%s]", getName().c_str(), sCmd.c_str(), sResult.c_str());
+ printTrace("%s| Network Status:\n%s\n", getName().c_str(), jData.toStyledString().c_str());
+ return rc;
+ }
+
+ // <rxlev>,<ber>,<rscp>,<ecno>,<rsrq>,<rsrp>
+ // [0] [1] [2] [3] [4] [5]
+ vParts = MTS::Text::split(sResult, ",");
+
+ if (vParts.size() < 6) {
+ printDebug("%s| Network Status command response is an unknown format: [%s][%s]", getName().c_str(), sCmd.c_str(), sResult.c_str());
+ printTrace("%s| Network Status:\n%s\n", getName().c_str(), jData.toStyledString().c_str());
+ return FAILURE;
+ }
+
+ int iValue;
+ if (MTS::Text::parse(iValue, vParts[5])) {
+ do {
+ if (255 == iValue) {
+ break; // invalid, not known or not detectable
+ }
+ if (iValue > 97 || iValue < 0) {
+ printDebug("%s| Network Status command returned unexpected value of RSRP: [%s][%d]", getName().c_str(), sCmd.c_str(), iValue);
+ printTrace("%s| Network Status:\n%s\n", getName().c_str(), jData.toStyledString().c_str());
+ break;
+ }
+ // converting value to rsrp dBm according to documentation
+ jDebug["rsrp"] = std::to_string(iValue - 141);
+ } while (false);
+ }
+
+ if (MTS::Text::parse(iValue, vParts[4])) {
+ do {
+ if (255 == iValue) {
+ break; // invalid, not known or not detectable
+ }
+ if (iValue > 34 || iValue < 0) {
+ printDebug("%s| Network Status command returned unexpected value of RSRQ: [%s][%d]", getName().c_str(), sCmd.c_str(), iValue);
+ printTrace("%s| Network Status:\n%s\n", getName().c_str(), jData.toStyledString().c_str());
+ break;
+ }
+ // converting value to rsrq in dBm according to documentation
+ jDebug["rsrq"] = std::to_string((iValue-40.0)/2.0);
+ } while (false);
+ }
+
+ return SUCCESS;
+}
+
+// AT+SQNQRUP? -- This command queries and reports the uplink power of the current LTE network.
+// +SQNQRUP: <txPower>,<maxTxPower>
+ICellularRadio::CODE SequansRadio::getNetworkStatusTxPower(Json::Value& jData, Json::Value& jDebug) {
+ std::string sCmd;
+ std::string sResult;
+ std::string sPrefix;
+ std::vector<std::string> vParts;
+ int iValue;
+ CODE rc;
+
+ sCmd = "AT+SQNQRUP?";
+ sPrefix = "+SQNQRUP:";
+
+ // the key must be present
+ jDebug[ICellularRadio::KEY_TXPWR] = "";
+
+ rc = sendBasicQuery(sCmd, sPrefix, sResult, 200);
+ if (SUCCESS != rc) {
+ printDebug("%s| Network Status command returned unexpected response: [%s][%s]", getName().c_str(), sCmd.c_str(), sResult.c_str());
+ printTrace("%s| Network Status:\n%s\n", getName().c_str(), jData.toStyledString().c_str());
+ return rc;
+ }
+ // <txPower>,<maxTxPower>
+ // [0] [1]
+ vParts = MTS::Text::split(sResult, ",");
+
+ if (vParts.size() < 2) {
+ printDebug("%s| Network Status command response is an unknown format: [%s][%s]", getName().c_str(), sCmd.c_str(), sResult.c_str());
+ printTrace("%s| Network Status:\n%s\n", getName().c_str(), jData.toStyledString().c_str());
+ return FAILURE;
+ }
+
+ double fTxPow;
+ if (MTS::Text::parse(fTxPow, vParts[0])) {
+ do {
+ if (-21474836.0 == fTxPow) {
+ break; // invalid, not known or not detectable
+ }
+ if (fTxPow < -255 || fTxPow > 99) {
+ printDebug("%s| Network Status command returned unexpected value of txPower: [%s][%d]", getName().c_str(), sCmd.c_str(), iValue);
+ printTrace("%s| Network Status:\n%s\n", getName().c_str(), jData.toStyledString().c_str());
+ break;
+ }
+ jDebug[ICellularRadio::KEY_TXPWR] = vParts[0];
+ } while (false);
+ }
+
+ return SUCCESS;
+}
+
+ICellularRadio::CODE SequansRadio::getNetworkStatus(Json::Value& jData) {
+ printTrace("%s| Get Network Status", getName().c_str());
+
+ // NOTE: Only the LTE radios from Sequans are supported at the moment
+
+ Json::Value jDebug;
+ std::string sResult;
+
+ getCommonNetworkStats(jData);
+ getNetworkStatusSQN(jData, jDebug);
+ getNetworkStatusSignal(jData, jDebug);
+ getNetworkStatusTxPower(jData, jDebug);
+
+ if (jData.isMember(ICellularRadio::KEY_RSSIDBM)) {
+ jDebug[ICellularRadio::KEY_RSSIDBM] = jData[ICellularRadio::KEY_RSSIDBM];
+ }
+
+ if (SUCCESS == getImsi(sResult)) {
+ jData[ICellularRadio::KEY_IMSI] = sResult;
+ }
+
+ if (SUCCESS == getNetwork(sResult)) {
+ jData[ICellularRadio::KEY_NETWORK] = sResult;
+ }
+
+ jDebug[ICellularRadio::KEY_SD] = "PS";
+
+ jData[ICellularRadio::KEY_DEBUG] = jDebug;
+
+ printTrace("%s| Network Status:\n%s\n", getName().c_str(), jData.toStyledString().c_str());
+ return SUCCESS;
+
+}
+
+ICellularRadio::CODE MTS::IO::SequansRadio::convertSignalStrengthTodBm(const int32_t &iRssi, int32_t &iDBm) {
+ const int dbmSteps = 2;
+ const int minValue = -113;
+ const int maxValue = -51;
+ const int rssiOffset = 0;
+ int rawDbm;
+
+ if (iRssi < 0 || iRssi > 99) {
+ return FAILURE; // invalid, not known or not detectable
+ }
+
+ rawDbm = minValue + ((iRssi - rssiOffset) * dbmSteps);
+ iDBm = std::min(maxValue, rawDbm);
+
+ return SUCCESS;
+}
+
+ICellularRadio::CODE SequansRadio::convertdBmToSignalStrength(const int32_t& iDBm, int32_t& iRssi) {
+ const int dbmSteps = 2;
+ const int minValue = -113;
+ const int rssiOffset = 0;
+
+ if (iDBm < -113) {
+ iRssi = 0;
+ } else if (iDBm > -51) {
+ iRssi = 31;
+ } else {
+ iRssi = ((iDBm - minValue) / dbmSteps) + rssiOffset;
+ }
+
+ return SUCCESS;
+}
+
+ICellularRadio::CODE SequansRadio::setMdn(const Json::Value& jArgs) {
+ printTrace("%s| Set MDN", getName().c_str());
+ return NOT_APPLICABLE;
+}
+
+ICellularRadio::CODE SequansRadio::setUeModeOfOperation(ICellularRadio::UE_MODES_OF_OPERATION mode) {
+ printTrace("%s| Set UE Mode Of Operation", getName().c_str());
+
+ std::string sValue;
+
+ switch (mode) {
+ case ICellularRadio::UE_MODES_OF_OPERATION::PS_MODE1:
+ sValue = "3";
+ break;
+ case ICellularRadio::UE_MODES_OF_OPERATION::PS_MODE2:
+ sValue = "0";
+ break;
+ case ICellularRadio::UE_MODES_OF_OPERATION::CS_PS_MODE1:
+ sValue = "1";
+ break;
+ case ICellularRadio::UE_MODES_OF_OPERATION::CS_PS_MODE2:
+ sValue = "2";
+ break;
+ default:
+ printError("%s| Set UE Mode Of Operation: invalid argument", getName().c_str());
+ return INVALID_ARGS;
+ }
+
+ const int dTimeout = 1000; // ms
+ const std::string sCmd = "AT+CEMODE=" + sValue;
+
+ return sendBasicCommand(sCmd, dTimeout);
+}
+
+ICellularRadio::CODE SequansRadio::getUeModeOfOperation(ICellularRadio::UE_MODES_OF_OPERATION& mode) {
+ printTrace("%s| Get UE Mode Of Operation", getName().c_str());
+
+ std::string sCmd = "AT+CEMODE?";
+ std::string sPrefix = "+CEMODE:";
+ std::string sResult;
+
+ if (SUCCESS != sendBasicQuery(sCmd, sPrefix, sResult, 1000)) {
+ printError("%s| Unable to get UE Mode Of Operation from radio using command [%s]", getName().c_str(), sCmd.c_str());
+ return FAILURE;
+ }
+
+ uint8_t uiValue;
+
+ if (!MTS::Text::parse(uiValue, sResult)) {
+ printError("%s| Unable to parse CEMODE from response [%s]", getName().c_str(), sResult.c_str());
+ return FAILURE;
+ }
+
+ CODE rc;
+ switch (uiValue) {
+ case 0:
+ mode = ICellularRadio::UE_MODES_OF_OPERATION::PS_MODE2;
+ rc = SUCCESS;
+ break;
+ case 1:
+ mode = ICellularRadio::UE_MODES_OF_OPERATION::CS_PS_MODE1;
+ rc = SUCCESS;
+ break;
+ case 2:
+ mode = ICellularRadio::UE_MODES_OF_OPERATION::CS_PS_MODE2;
+ rc = SUCCESS;
+ break;
+ case 3:
+ mode = ICellularRadio::UE_MODES_OF_OPERATION::PS_MODE1;
+ rc = SUCCESS;
+ break;
+ default:
+ printError("%s| Unable to parse CEMODE from response [%s]", getName().c_str(), sResult.c_str());
+ mode = ICellularRadio::UE_MODES_OF_OPERATION::UNKNOWN_MODE;
+ rc = FAILURE;
+ break;
+ }
+ return rc;
+}
+
+ICellularRadio::CODE SequansRadio::setRxDiversity(const Json::Value& jArgs) {
+ return NOT_APPLICABLE;
+}
+
+const std::vector<std::string> SequansRadio::getRegistrationCommands() {
+ return { "CEREG" };
+}
+
+SequansRadio::SequansRadio(const std::string& sName, const std::string& sRadioPort)
+: CellularRadio (sName, sRadioPort)
+{
+}
+
+ICellularRadio::CODE SequansRadio::getIsSimInserted(bool& bData) {
+ printTrace("%s| Get SIM insertion status", getName().c_str());
+ // there is no command to check SIM presence
+ return NOT_APPLICABLE;
+}
+
+ICellularRadio::CODE SequansRadio::getSimLockAttempts(int& iAttemptsPin, int& iAttemptsPuk) {
+ printTrace("%s| Get SIM unlock attempts left", getName().c_str());
+ CODE rc = FAILURE;
+
+ rc = getSimLockAttemptsByType("SIM PIN", iAttemptsPin);
+ if (rc != SUCCESS) {
+ return rc;
+ }
+
+ rc = getSimLockAttemptsByType("SIM PUK", iAttemptsPuk);
+ if (rc != SUCCESS) {
+ return rc;
+ }
+
+ return SUCCESS;
+}
+
+ICellularRadio::CODE SequansRadio::getSimLockAttemptsByType(const std::string& sArg, int& iAttempts) {
+ std::string sCmd("AT+CPINR");
+ std::string sPrefix("+CPINR:");
+ std::string sResult;
+ int iValue;
+ CODE rc = FAILURE;
+
+ sCmd += "=\"";
+ sCmd += sArg;
+ sCmd += "\"";
+
+ printDebug("%s| Sending SIM lock attempt query [%s]", getName().c_str(), sCmd.c_str());
+
+ rc = sendBasicQuery(sCmd, sPrefix, sResult, 500);
+ if (SUCCESS != rc) {
+ return rc;
+ }
+
+ std::vector<std::string> vParts = MTS::Text::split(sResult, ',');
+
+ if (vParts.size() < 3 || ! MTS::Text::parse(iValue, vParts[1])) {
+ printWarning("%s| Unable to parse SIM unlock attempts from response [%s]", getName().c_str(), sResult.c_str());
+ return FAILURE;
+ }
+
+ iAttempts = iValue;
+ return SUCCESS;
+}
+
+const std::vector<std::string>& SequansRadio::getDiagCommands(bool) {
+ // TODO: Fill the list of commands in scope of the "L6G1 - Cellular Diagnostics" feature
+
+ // Declare as static to initialize only when used, but cache the results.
+ const static std::vector<std::string> vCommands {
+ };
+
+ return vCommands;
+}
diff --git a/src/MTS_IO_TelitRadio.cpp b/src/MTS_IO_TelitRadio.cpp
index 4a0a8b2..704f692 100644
--- a/src/MTS_IO_TelitRadio.cpp
+++ b/src/MTS_IO_TelitRadio.cpp
@@ -110,12 +110,12 @@ ICellularRadio::CODE TelitRadio::getVendorFirmware(std::string& sVendorFirmware)
// Not Found. Then we will use "AT+CGMR" + "AT#CFVR"
rc = getFirmware(sFirmware);
- if (rc != SUCCESS){
+ if (rc != SUCCESS) {
break;
}
rc = getFirmwareBuild(sFirmwareBuild);
- if (rc != SUCCESS){
+ if (rc != SUCCESS) {
break;
}
@@ -714,7 +714,7 @@ ICellularRadio::CODE TelitRadio::getSupportedCellularModes(CELLULAR_MODES &netwo
networks = CELLULAR_MODE_NA;
std::set<int> wds;
- if ( TelitRadio::wdsList(wds) != SUCCESS ) {
+ if ( wdsList(wds) != SUCCESS ) {
return FAILURE;
}
for(const auto &it : wds) {
@@ -729,8 +729,7 @@ ICellularRadio::CODE TelitRadio::getSupportedCellularModes(CELLULAR_MODES &netwo
return SUCCESS;
}
-ICellularRadio::CODE TelitRadio::wdsList(std::set<int> &wds)
-{
+ICellularRadio::CODE TelitRadio::wdsList(std::set<int> &wds) {
std::string sCmd("AT+WS46=?");
std::string cmdResult = sendCommand(sCmd);
if (cmdResult.find("+WS46:") == std::string::npos) {
@@ -745,8 +744,7 @@ ICellularRadio::CODE TelitRadio::wdsList(std::set<int> &wds)
std::string s = MTS::Text::split(cmdResult, '(')[1];
s = MTS::Text::split(s, ')')[0];
std::vector<std::string>v = MTS::Text::split(s, ',');
- for(const auto &it : v)
- {
+ for(const auto &it : v) {
if (it.find("-") != std::string::npos) {
const std::vector<std::string> &r = MTS::Text::split(it, "-");
int begin, end;
@@ -778,7 +776,7 @@ ICellularRadio::CODE TelitRadio::wdsList(std::set<int> &wds)
ICellularRadio::CODE TelitRadio::setCellularMode(CELLULAR_MODES networks) {
std::set<int> supportedWds;
- if ( TelitRadio::wdsList(supportedWds) != SUCCESS ) {
+ if ( wdsList(supportedWds) != SUCCESS ) {
return FAILURE;
}