diff options
author | Jeff Hatch <jhatch@multitech.com> | 2019-07-23 08:51:41 -0500 |
---|---|---|
committer | Jeff Hatch <jhatch@multitech.com> | 2019-07-23 08:51:41 -0500 |
commit | f6f7d0e174d2bf5eb4494e2508c17d3d7fbdc4e9 (patch) | |
tree | 4f0e44ed31f0e536835260ff5b4849f84289ee9c | |
parent | 86e572b513259e1f7164dd4e4b0f490c870bfc30 (diff) | |
parent | 0330513b8913d1d7bf14bad99d64ab002b770b7c (diff) | |
download | libmts-io-f6f7d0e174d2bf5eb4494e2508c17d3d7fbdc4e9.tar.gz libmts-io-f6f7d0e174d2bf5eb4494e2508c17d3d7fbdc4e9.tar.bz2 libmts-io-f6f7d0e174d2bf5eb4494e2508c17d3d7fbdc4e9.zip |
Merge branch 'quectel-radio' into 'master'
Quectel radio
See merge request !1
34 files changed, 3117 insertions, 1824 deletions
@@ -1,104 +1,73 @@ include version -includedir ?= /usr/include +APPNAME = libmts-io +SONAME = $(APPNAME).so.$(VERSION) libdir ?= /usr/lib OBJS += \ -MTS_IO_CdmaRadio.o \ -MTS_IO_CE910Radio.o \ -MTS_IO_CellularRadio.o \ -MTS_IO_CellularRadioFactory.o \ -MTS_IO_Connection.o \ -MTS_IO_DE910Radio.o \ -MTS_IO_GE910Radio.o \ -MTS_IO_HE910Radio.o \ -MTS_IO_HE910DRadio.o \ -MTS_IO_HE910EUDRadio.o \ -MTS_IO_LE910JN1Radio.o \ -MTS_IO_LE866Radio.o \ -MTS_IO_LE866A1JSRadio.o \ -MTS_IO_LE910Radio.o \ -MTS_IO_LE910NAGRadio.o \ -MTS_IO_LE910C4NFRadio.o \ -MTS_IO_LE910NA1Radio.o \ -MTS_IO_LE910SVGRadio.o \ -MTS_IO_LE910EUGRadio.o \ -MTS_IO_LE910C4EURadio.o \ -MTS_IO_LE910EU1Radio.o \ -MTS_IO_LE910C1NSRadio.o \ -MTS_IO_LE910C1APRadio.o \ -MTS_IO_ME910C1NARadio.o \ -MTS_IO_ME910C1NVRadio.o \ -MTS_IO_ME910C1WWRadio.o \ -MTS_IO_ME910Radio.o \ -MTS_IO_LockFile.o \ -MTS_IO_MccMncTable.o \ -MTS_IO_SerialConnection.o + src/MTS_IO_TelitRadio.o \ + src/MTS_IO_EG95Radio.o \ + src/MTS_IO_QuectelRadio.o \ + src/MTS_IO_CdmaRadio.o \ + src/MTS_IO_CE910Radio.o \ + src/MTS_IO_CellularRadio.o \ + src/MTS_IO_ICellularRadio.o \ + src/MTS_IO_CellularRadioFactory.o \ + src/MTS_IO_Connection.o \ + src/MTS_IO_DE910Radio.o \ + src/MTS_IO_GE910Radio.o \ + src/MTS_IO_HE910Radio.o \ + src/MTS_IO_HE910DRadio.o \ + src/MTS_IO_HE910EUDRadio.o \ + src/MTS_IO_LE910JN1Radio.o \ + src/MTS_IO_LE866Radio.o \ + src/MTS_IO_LE866A1JSRadio.o \ + src/MTS_IO_LE910Radio.o \ + src/MTS_IO_LE910NAGRadio.o \ + src/MTS_IO_LE910C4NFRadio.o \ + src/MTS_IO_LE910NA1Radio.o \ + src/MTS_IO_LE910SVGRadio.o \ + src/MTS_IO_LE910EUGRadio.o \ + src/MTS_IO_LE910C4EURadio.o \ + 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 \ + src/MTS_IO_MccMncTable.o \ + src/MTS_IO_SerialConnection.o -CPP_DEPS += \ -MTS_IO_CdmaRadio.d \ -MTS_IO_CE910Radio.d \ -MTS_IO_CellularRadio.d \ -MTS_IO_CellularRadioFactory.d \ -MTS_IO_Connection.d \ -MTS_IO_DE910Radio.d \ -MTS_IO_GE910Radio.d \ -MTS_IO_HE910Radio.d \ -MTS_IO_HE910DRadio.d \ -MTS_IO_HE910EUDRadio.d \ -MTS_IO_LE910JN1Radio.d \ -MTS_IO_LE866Radio.d \ -MTS_IO_LE866A1JSRadio.d \ -MTS_IO_LE910Radio.d \ -MTS_IO_LE910NAGRadio.d \ -MTS_IO_LE910C4NFRadio.d \ -MTS_IO_LE910NA1Radio.d \ -MTS_IO_LE910SVGRadio.d \ -MTS_IO_LE910EUGRadio.d \ -MTS_IO_LE910C4EURadio.d \ -MTS_IO_LE910EU1Radio.d \ -MTS_IO_LE910C1NSRadio.d \ -MTS_IO_LE910C1APRadio.d \ -MTS_IO_ME910C1NARadio.d \ -MTS_IO_ME910C1NVRadio.d \ -MTS_IO_ME910C1WWRadio.d \ -MTS_IO_ME910Radio.d \ -MTS_IO_LockFile.d \ -MTS_IO_MccMncTable.d \ -MTS_IO_SerialConnection.d +CC := $(CXX) +#-Werror +CXXFLAGS += -Wall -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 -all: libmts-io.a libmts-io.so.0 +.PHONY: all clean install -libmts-io.a: $(OBJS) - @echo 'Building target: $@' - $(AR) -r libmts-io.a $(OBJS) - @echo 'Finished building target: $@' - @echo ' ' +all: $(APPNAME).a $(SONAME) -libmts-io.so.0: $(OBJS) - @echo 'Building target: $@' - $(CXX) $(LDFLAGS) -shared -Wl,-soname,$@ -o libmts-io.so.$(VERSION) $(OBJS) - @echo 'Finished building target: $@' - @echo ' ' +$(APPNAME).a: $(OBJS) + $(AR) -rs $@ $? -%.o: src/%.cpp - @echo 'Building file: $<' - $(CXX) $(CFLAGS) -I=$(includedir)/jsoncpp -Iinclude -Wall -Werror -c -fPIC -fmessage-length=0 -std=c++0x -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<" - @echo 'Finished building: $<' - @echo ' ' +$(SONAME): $(OBJS) + $(CC) $(LDFLAGS) -o $@ $? $(LDLIBS) + +# Handle header dependencies +DEPS = $(OBJS:.o=.d) +CPPFLAGS += -MMD +-include $(DEPS) install: mkdir -p $(DESTDIR)$(libdir) mkdir -p $(DESTDIR)$(includedir)/mts - install -m 0644 libmts-io.a libmts-io.so.$(VERSION) $(DESTDIR)$(libdir)/ - ln -sf libmts-io.so.$(VERSION) $(DESTDIR)$(libdir)/libmts-io.so.0 - ln -sf libmts-io.so.0 $(DESTDIR)$(libdir)/libmts-io.so + install -m 0644 $(APPNAME).a $(SONAME) $(DESTDIR)$(libdir)/ + ln -sf $(SONAME) $(DESTDIR)$(libdir)/$(APPNAME).so.0 + ln -sf $(SONAME) $(DESTDIR)$(libdir)/$(APPNAME).so install -m 0644 include/mts/* $(DESTDIR)$(includedir)/mts/ clean: - -$(RM) $(OBJS) $(CPP_DEPS) libmts-io.a libmts-io.so* - -@echo ' ' - -.PHONY: all clean dependents install -.SECONDARY: - + $(RM) $(OBJS) $(APPNAME).a $(SONAME) $(DEPS) diff --git a/include/mts/MTS_IO_CdmaRadio.h b/include/mts/MTS_IO_CdmaRadio.h index 448cdc7..7cdba02 100644 --- a/include/mts/MTS_IO_CdmaRadio.h +++ b/include/mts/MTS_IO_CdmaRadio.h @@ -29,12 +29,12 @@ #ifndef MTS_IO_CDMARADIO_H_ #define MTS_IO_CDMARADIO_H_ -#include <mts/MTS_IO_CellularRadio.h> +#include <mts/MTS_IO_TelitRadio.h> namespace MTS { namespace IO { - class CdmaRadio : public CellularRadio { + class CdmaRadio : public TelitRadio { public: virtual ~CdmaRadio(); diff --git a/include/mts/MTS_IO_CellularRadio.h b/include/mts/MTS_IO_CellularRadio.h index 007c130..eecefee 100644 --- a/include/mts/MTS_IO_CellularRadio.h +++ b/include/mts/MTS_IO_CellularRadio.h @@ -29,449 +29,93 @@ #ifndef MTS_IO_CELLULARRADIO_H_ #define MTS_IO_CELLULARRADIO_H_ +#include <string> +#include <vector> + +#include <json/json.h> + +#include <mts/MTS_IO_ICellularRadio.h> #include <mts/MTS_IO_SerialConnection.h> #include <mts/MTS_NonCopyable.h> #include <mts/MTS_AutoPtr.h> -#include <mts/MTS_Lock.h> #include <mts/MTS_Stdint.h> -#include <json/json.h> -#include <string> -#include <vector> -#include <functional> - -typedef struct -{ - const char *name; - int32_t low; - int32_t high; -} *pNameRangeMap, nameRangeMap; - -static const unsigned int NUM_GSM_BANDS = 7; -static const unsigned int NUM_WCDMA_BANDS = 6; -static const unsigned int NUM_LTE_BANDS = 42; - -// http://niviuk.free.fr/gsm_band.php -static const nameRangeMap GSMband[] = -{ - {"GSM 450", 259, 293}, {"GSM 480", 306, 340}, - {"GSM 750", 438, 511}, {"GSM 850", 128, 251}, - {"GSM 900 P", 1, 124}, {"GSM 900 E/R", 955, 1023}, - {"GSM DCS 1800/1900", 512, 885}, - -}; - -// http://niviuk.free.fr/umts_band.php -static const nameRangeMap WCDMAband[] = -{ - {"BAND I", 10592, 10838}, {"BAND II", 9662, 9938}, - {"BAND III", 1162, 1513}, {"BAND IV", 1537, 1738}, - {"BAND V", 4357, 4458}, {"BAND VI", 4387, 4413} -}; - -// http://niviuk.free.fr/lte_band.php -static 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} -}; namespace MTS { namespace IO { - - class CellularRadio : NonCopyable { + class CellularRadio : public ICellularRadio { public: - static const std::string DEFAULT_RADIO_PORT; - static const std::string DEFAULT_RADIO_DIR; - - static const std::string VALUE_UNKNOWN; - static const std::string VALUE_UNAVAILABLE; - static const std::string VALUE_NOT_SUPPORTED; - - //Special Payload Characters - static const char ETX; //Ends socket connection - static const char DLE; //Escapes ETX and DLE within Payload - static const char CR; - static const char NL; - static const char CTRL_Z; - - static const std::string RSP_OK; - static const std::string RSP_ERROR; - - //Registration Values - enum REGISTRATION : uint8_t { - NOT_REGISTERED = 0, - REGISTERED = 1, - SEARCHING=2, - DENIED=3, - UNKNOWN=4, - ROAMING=5 - }; - - enum SERVICEDOMAIN : uint8_t { - NO_SERVICE = 0, - CS_ONLY = 1, - PS_ONLY = 2, - CSPS = 3 - }; - - enum ACTIVEBAND : uint8_t { - GSM_850 = 0, - GSM_900 = 1, - DCS_1800 = 2, - PCS_1900 = 3 - }; - - enum CODE : uint8_t { - SUCCESS = 0, - ERROR, - FAILURE, - NO_RESPONSE, - NOT_APPLICABLE, - INVALID_ARGS - }; - - enum SIMSTATUS : uint8_t { - READY = 0, - LOCKED, - BLOCKED, - NOT_INSERTED - }; - - static const std::string VALUE_NOT_REGISTERED; - static const std::string VALUE_REGISTERED; - static const std::string VALUE_SEARCHING; - static const std::string VALUE_DENIED; - static const std::string VALUE_ROAMING; - - //Static Data - static const std::string KEY_TYPE; //!< GSM or CDMA - static const std::string KEY_CODE; //!< Product Code : H5, H6, C2, EV3, G3 - static const std::string KEY_MODEL; //!< Model : HE910, CE910, DE910, GE910 - static const std::string KEY_MANUFACTURER; //!< Manufacturer: Telit - static const std::string KEY_HARDWARE; //!< Radio Hardware Version - static const std::string KEY_FIRMWARE; //!< Radio Firmware Version - static const std::string KEY_FIRMWARE_BUILD;//!< Radio Firmware Build - static const std::string KEY_IMEI; //!< International Mobile Station Equipment Identity - static const std::string KEY_MEID; //!< Mobile Equipment Identifier - static const std::string KEY_IMSI; //!< International Mobile Subscriber Identity - static const std::string KEY_MSID; //!< Mobil Station ID (MSID) aka MIN aka MSIN aka Last few digits of IMSI - static const std::string KEY_MDN; //!< Mobile Directory Number : Actual phone number dialed to reach radio - static const std::string KEY_CARRIER; //!< Cellular Service Provider (Home Network) - static const std::string KEY_ICCID; //!< Integrated Circuit Card Identifier - static const std::string KEY_MSL; //!< Master Subsidy Lock - - - //Network Status Data - static const std::string KEY_ROAMING; //!< Indicates whether or not using Home Network - static const std::string KEY_DATETIME; //!< Date and Time from tower - static const std::string KEY_SERVICE; //!< Service Connection Type [GPRS, EGPRS, WCDMA, HSDPA, 1xRTT, EVDO] - static const std::string KEY_NETWORK; //!< Cellular Service Provider - static const std::string KEY_NETWORK_REG; //!< Network Registration - static const std::string KEY_CID; //!< Cellular ID (Tower) in HEX - static const std::string KEY_LAC; //!< Location Area Code in HEX - static const std::string KEY_RAC; //!< Routing Area Code in HEX - static const std::string KEY_RSSI; //!< Received Signal Strength Indication - static const std::string KEY_RSSIDBM; //!< Received Signal Strength Indication in dBm - static const std::string KEY_MCC; //!< Mobile Country Code - static const std::string KEY_MNC; //!< Mobile Network (Operator) Code - static const std::string KEY_CHANNEL; //!< ARFCN or UARFCN Assigned Radio Channel - static const std::string KEY_TXPWR; //!< Transmit Power - static const std::string KEY_PSC; //!< Active Primary Synchronization Code (PSC) - static const std::string KEY_ECIO; //!< Active Ec/Io (chip energy per total wideband power in dBm) - static const std::string KEY_RSCP; //!< Active RSCP (Received Signal Code Power in dBm) - static const std::string KEY_DRX; //!< Discontinuous reception cycle length (ms) - static const std::string KEY_MM; //!< Mobility Management State - static const std::string KEY_RR; //!< Radio Resource State - static const std::string KEY_NOM; //!< Network Operator Mode - static const std::string KEY_ABND; //!< Active Band - static const std::string KEY_BLER; //!< Block Error Rate (percentage) - static const std::string KEY_SD; //!< Service Domain - static const std::string KEY_DEBUG; //!< Debug Information - - static const std::string KEY_MIP; //!< Mobile IP Information - static const std::string KEY_MIP_ID; //!< MIP Profile ID - static const std::string KEY_MIP_ENABLED; //!< MIP Profile Enabled/Disabled - static const std::string KEY_MIP_NAI; //!< Network Access Identifier - static const std::string KEY_MIP_HOMEADDRESS; //!< Home Address - static const std::string KEY_MIP_PRIMARYHA; //!< Primary Home Agent - static const std::string KEY_MIP_SECONDARYHA; //!< Secondary Home Agent - static const std::string KEY_MIP_MNAAASPI; //!< Mobile Node Authentication, Authorization, and Accounting Server Security Parameter Index - static const std::string KEY_MIP_MNHASPI; //!< Mobile Node Home Agent Security Server Parameter Index - static const std::string KEY_MIP_REVTUN; //!< Reverse Tunneling Enabled - static const std::string KEY_MIP_MNAAASS; //!< Mobile Node Authentication, Authorization, and Accounting Server Shared Secret - static const std::string KEY_MIP_MNHASS; //!< Mobile Node Home Agent Shared Secret - - - //Values - Type - static const std::string VALUE_TYPE_LTE; - static const std::string VALUE_TYPE_GSM; - static const std::string VALUE_TYPE_CDMA; - - //Values - Carrier - static const std::string VALUE_CARRIER_VERIZON; - static const std::string VALUE_CARRIER_AERIS; - static const std::string VALUE_CARRIER_SPRINT; - static const std::string VALUE_CARRIER_USCELLULAR; - static const std::string VALUE_CARRIER_ATT; - static const std::string VALUE_CARRIER_TMOBILE; - - static const std::string VALUE_SD_NO_SERVICE; - static const std::string VALUE_SD_CS_ONLY; - static const std::string VALUE_SD_PS_ONLY; - static const std::string VALUE_SD_CSPS; - - static const std::string VALUE_ABND_GSM_850; - static const std::string VALUE_ABND_GSM_900; - static const std::string VALUE_ABND_DCS_1800; - static const std::string VALUE_ABND_PCS_1900; - - static const std::vector<std::string> DEFAULT_BAIL_STRINGS; - - typedef std::function<bool(const std::string&/*iterationData*/, const std::string&/*allData*/)> IsNeedMoreData; - typedef std::function<void(const Json::Value&)> UpdateCb; - - virtual ~CellularRadio(); - - virtual bool initialize(uint32_t iTimeoutMillis = 5000); - virtual bool resetRadio(uint32_t iTimeoutMillis = 5000); - virtual bool resetConnection(uint32_t iTimeoutMillis = 5000); - virtual void shutdown(); - - const std::string& getName() const; - - virtual CODE getModel(std::string& sModel); - static CODE convertModelToType(const std::string& sModel, std::string& sType); - static CODE convertModelToMtsShortCode(const std::string& sModel, std::string& sCode, CellularRadio *radioObj = NULL); - static CODE convertServiceDomainToString(SERVICEDOMAIN eSd, std::string& sSd); - static CODE convertActiveBandToString(ACTIVEBAND eBand, std::string& sBand); - - virtual CODE getFirmware(std::string& sFirmware); - virtual CODE getFirmwareBuild(std::string& sFirmwareBuild); - virtual CODE getHardware(std::string& sHardware); - virtual CODE getManufacturer(std::string& sManufacturer); - virtual CODE getImei(std::string& sImei); - virtual CODE getMeid(std::string& sMeid); - virtual CODE getImsi(std::string& sImsi); - virtual CODE getSimStatus(std::string& sSimStatus); - virtual CODE getIccid(std::string& sIccid); - virtual CODE getService(std::string& sService); - virtual CODE getLac(std::string& sLac); - virtual CODE getMdn(std::string& sMdn); - virtual CODE getMsid(std::string& sMsid); - virtual CODE getType(std::string& sType); - virtual CODE getCarrier(std::string& sCarrier); - virtual CODE getNetwork(std::string& sNetwork); - virtual CODE getTower(std::string& sTower); - virtual CODE getTime(std::string& sDate, std::string& sTime, std::string& sTimeZone); - virtual CODE getRoaming(bool& bRoaming); - - virtual CODE getSignalStrength(int32_t& iRssi); - virtual CODE getModemLocation(std::string& sLocation); - virtual CODE convertSignalStrengthTodBm(const int32_t& iRssi, int32_t& dBm); - virtual CODE convertdBmToSignalStrength(const int32_t& dBm, int32_t& iRssi); - - virtual CODE getRegistration(REGISTRATION& eRegistration); - virtual CODE convertRegistrationToString(REGISTRATION eRegistration, std::string& sRegistration); - - //! Gather details of the radio's Mobile IP Profile - /*! - \param Json::Value object that will be populated with MIP data - \return Returns result code of gathering MIP - */ - virtual CODE getMipProfile(Json::Value& jMipProfile); - - /* - * jArgs = { - * "msl" : "Master Subsidy Lock (Aeris, Sprint): STRING" - * } - */ - virtual CODE validateMsl(const Json::Value& jArgs); - - /* - * jArgs = { - * "mdn" : "Mobile Directory Number : STRING", - * "msl" : "[OPTIONAL] Master Subsidy Lock (Aeris, Sprint): STRING" - * } - */ - virtual CODE setMdn(const Json::Value& jArgs); - - /* - * jArgs = { - * "msid" : "Mobil Station ID (MSID) aka MIN aka MSIN : STRING", - * "msl" : "[OPTIONAL] Master Subsidy Lock (Aeris, Sprint): STRING" - * } - */ - virtual CODE setMsid(const Json::Value& jArgs); - - /* - * jArgs = { - * "activeProfile" : "Set active profile: STRING" - * } - */ - virtual CODE setMipActiveProfile(const Json::Value& jArgs); - - /* - * jArgs = { - * "nai" : "Network Access Identifier : STRING" - * } - */ - virtual CODE setMipNai(const Json::Value& jArgs); - - /* - * jArgs = { - * "homeIp" : "Home Address : STRING" - * } - */ - virtual CODE setMipHomeIp(const Json::Value& jArgs); - - /* - * jArgs = { - * "primaryHa" : "Primary Home Agent : STRING" - * } - */ - virtual CODE setMipPrimaryHa(const Json::Value& jArgs); - - /* - * jArgs = { - * "secondaryHa" : "Secondary Home Agent : STRING" - * } - */ - virtual CODE setMipSecondaryHa(const Json::Value& jArgs); - - /* - * jArgs = { - * "mnAaaSpi" : "Mobile Node Authentication, Authorization, and Accounting Server Security Parameter Index : STRING" - * } - */ - virtual CODE setMipMnAaaSpi(const Json::Value& jArgs); - - /* - * jArgs = { - * "mnHaSpi" : "Mobile Node Home Agent Security Server Parameter Index : STRING" - * } - */ - virtual CODE setMipMnHaSpi(const Json::Value& jArgs); - - /* - * jArgs = { - * "revTun" : "[DESCRIPTION] : STRING" - * } - */ - virtual CODE setMipRevTun(const Json::Value& jArgs); - - /* - * jArgs = { - * "mnAaaSs" : "Mobile Node Authentication, Authorization, and Accounting Server Shared Secret : STRING" - * } - */ - virtual CODE setMipMnAaaSs(const Json::Value& jArgs); - - /* - * jArgs = { - * "mnHaSs" : "Mobile Node Home Agent Shared Secret : STRING" - * } - */ - virtual CODE setMipMnHaSs(const Json::Value& jArgs); - - /* - * jArgs = null - */ - virtual CODE updateDc(const Json::Value& jArgs, UpdateCb& stepCb); - - /* - * jArgs = null - */ - virtual CODE updatePrl(const Json::Value& jArgs, UpdateCb& stepCb); - - /* - * jArgs = null - */ - virtual CODE updateFumo(const Json::Value& jArgs, UpdateCb& stepCb); - - /* - * jArgs = { - * "msl" : "Master Subsidy Lock (Sprint): STRING" - * } - */ - virtual CODE resetHfa(const Json::Value& jArgs, UpdateCb& stepCb); - - /* - * jArgs = { - * "mdn" : "Mobile Directory Number (Aeris): STRING" - * "msid" : "Mobile Station ID (Aeris): STRING" - * } - */ - virtual CODE activate(const Json::Value& jArgs, UpdateCb& stepCb); - - /* - * jArgs = { - * "enabled" : "RX Diversity Enabled ("0" or "1"): STRING" - * } - */ - virtual CODE setRxDiversity(const Json::Value& jArgs)=0; - /* - * jArgs = { - * "fwid" : "Firmware Image To Be Enabled: STRING" - * } - */ - virtual CODE setActiveFirmware(const Json::Value& jArgs); - virtual CODE getActiveFirmware(std::string& sFwId); - - virtual CODE getEcho(bool& bEnabled); - virtual CODE setEcho(bool bEnabled = true); - - virtual CODE getStaticInformation(Json::Value& jData); - virtual CODE getNetworkStatus(Json::Value& jData); - - virtual CODE sendBasicCommand(const std::string& sCmd, int32_t timeoutMillis = 100, const char& ESC = CR); - - virtual std::string sendCommand(const std::string& sCmd, + const std::string& getName() const override; + + ~CellularRadio() override; + + bool initialize(uint32_t iTimeoutMillis = 5000) override; + bool resetConnection(uint32_t iTimeoutMillis = 5000) override; + void shutdown() override; + + CODE getFirmware(std::string& sFirmware) override; + CODE getFirmwareBuild(std::string& sFirmwareBuild) override; + CODE getHardware(std::string& sHardware) override; + CODE getManufacturer(std::string& sManufacturer) override; + CODE getImei(std::string& sImei) override; + CODE getMeid(std::string& sMeid) override; + CODE getImsi(std::string& sImsi) override; + CODE getSimStatus(std::string& sSimStatus) override; + CODE getSimStatusSummary(Json::Value& jData) override; + CODE getLac(std::string& sLac) override; + CODE getMdn(std::string& sMdn) override; + CODE getMsid(std::string& sMsid) override; + CODE getType(std::string& sType) override; + CODE getCarrier(std::string& sCarrier) override; + CODE getTower(std::string& sTower) override; + CODE getTime(std::string& sDate, std::string& sTime, std::string& sTimeZone) override; + CODE getRoaming(bool& bRoaming) override; + + CODE getSignalStrength(int32_t& iRssi) override; + CODE getModemLocation(std::string& sLocation) override; + + CODE getRegistration(REGISTRATION& eRegistration) override; + CODE convertRegistrationToString(REGISTRATION eRegistration, std::string& sRegistration) override; + + CODE unlockSimCard(const Json::Value& jArgs) override; + + CODE getMipProfile(Json::Value& jMipProfile) override; + CODE validateMsl(const Json::Value& jArgs) override; + CODE setMsid(const Json::Value& jArgs) override; + CODE setMipActiveProfile(const Json::Value& jArgs) override; + CODE setMipNai(const Json::Value& jArgs) override; + CODE setMipHomeIp(const Json::Value& jArgs) override; + CODE setMipPrimaryHa(const Json::Value& jArgs) override; + CODE setMipSecondaryHa(const Json::Value& jArgs) override; + CODE setMipMnAaaSpi(const Json::Value& jArgs) override; + CODE setMipMnHaSpi(const Json::Value& jArgs) override; + CODE setMipRevTun(const Json::Value& jArgs) override; + CODE setMipMnAaaSs(const Json::Value& jArgs) override; + CODE setMipMnHaSs(const Json::Value& jArgs) override; + CODE updateDc(const Json::Value& jArgs, UpdateCb& stepCb) override; + CODE updatePrl(const Json::Value& jArgs, UpdateCb& stepCb) override; + CODE updateFumo(const Json::Value& jArgs, UpdateCb& stepCb) override; + CODE resetHfa(const Json::Value& jArgs, UpdateCb& stepCb) override; + CODE activate(const Json::Value& jArgs, UpdateCb& stepCb) override; + CODE setActiveFirmware(const Json::Value& jArgs) override; + CODE getActiveFirmware(std::string& sFwId) override; + CODE getEcho(bool& bEnabled) override; + CODE setEcho(bool bEnabled = true) override; + CODE getStaticInformation(Json::Value& jData) override; + CODE sendBasicCommand(const std::string& sCmd, int32_t timeoutMillis = 100, const char& ESC = ICellularRadio::CR) override; + + std::string sendCommand(const std::string& sCmd, const std::vector<std::string>& vBail = DEFAULT_BAIL_STRINGS, int32_t timeoutMillis = 100, - const char& ESC = CR); + const char& ESC = ICellularRadio::CR) override; - static std::string sendCommand(MTS::AutoPtr<MTS::IO::Connection>& apIo, - const std::string& sCmd, - const std::vector<std::string>& vBail = DEFAULT_BAIL_STRINGS, - int32_t timeoutMillis = 100, - const char& ESC = CR); - virtual std::string sendCommand(const std::string& sCmd, + std::string sendCommand(const std::string& sCmd, IsNeedMoreData& isNeedMoreData, int32_t timeoutMillis = 100, - const char& ESC = CR); - - static std::string sendCommand(MTS::AutoPtr<MTS::IO::Connection>& apIo, - const std::string& sCmd, - IsNeedMoreData& isNeedMoreData, - int32_t timeoutMillis = 100, - const char& ESC = CR); + const char& ESC = ICellularRadio::CR) override; - static CODE test(MTS::AutoPtr<MTS::IO::Connection>& apIo, uint32_t timeoutSeconds = 30); - - static std::string extractModelFromResult(const std::string& sResult); - static std::string getCodeAsString(CODE code); protected: @@ -482,27 +126,61 @@ namespace MTS { virtual void getCommonNetworkStats(Json::Value& jData); - void initMipProfile(Json::Value& jData); + /** + * @brief getIsSimInserted - returns if the SIM card is inserted / installed or not. + * + * @param bData - an object to be filled with the SIM card insertion status. + * `true` when SIM card is inserted / installed / present, + * `false` otherwise. + * @return CODE::SUCCESS when SIM insertion status is fetched successfully, + * CODE::NOT_APPLICABLE when the modem doesn't support this feature, + * CODE::ERROR otherwise (when modem is inaccessible or in other cases). + */ + virtual CODE getIsSimInserted(bool& bData) = 0; + + /** + * @brief getSimLockStatus - return the SIM lock status as defined by AT+CPIN? command. + * Returns "READY", "SIM PIN", "SIM PUK" or other SIM status. + * + * @param sData - an object to be filled with the SIM lock status + * @return CODE::SUCCESS when SIM status is fetched successfully, + * CODE::NOT_APPLICABLE when the modem doesn't support this feature, + * CODE::ERROR otherwise (SIM card removed, modem is inaccessible, etc). + */ + virtual CODE getSimLockStatus(std::string& sData); + + /** + * @brief getSimLockAttempts - get the number of SIM unlock attempts left. + * + * @param iAttemptsPin - the number of attempts left to enter a PIN code. + * @param iAttemptsPuk - the number of attempts left to enter a PUK code. + * @return CODE::SUCCESS when both numbers are fetched successfully, + * CODE::NOT_APPLICABLE when the modem doesn't support this feature, + * CODE::ERROR otherwise (SIM card removed, modem is inaccessible, etc). + */ + virtual CODE getSimLockAttempts(int& iAttemptsPin, int& iAttemptsPuk) = 0; + void initMipProfile(Json::Value& jData); bool splitAndAssign(const std::string& sLine, const std::string& sKey, Json::Value& jParent, const std::string& sJsonKey, Json::ValueType eType = Json::ValueType::stringValue); + virtual std::string queryLteLac(); + virtual std::string queryCGREGstring(); + virtual void setCGREG(std::string value); - - private: - class RadioBandMap : NonCopyable { + class RadioBandMap : public MTS::NonCopyable { public: - RadioBandMap() - { - m_sChannel = CellularRadio::VALUE_UNKNOWN; + RadioBandMap() + { + m_sChannel = ICellularRadio::VALUE_UNKNOWN; m_iChannel = 0; - m_sRadioType = CellularRadio::VALUE_UNKNOWN; - } + m_sRadioType = ICellularRadio::VALUE_UNKNOWN; + } RadioBandMap(const std::string &channel, const std::string &radioType) : m_sChannel(channel), m_sRadioType(radioType) { - m_iChannel = strtol(m_sChannel.c_str(), NULL, 10); + m_iChannel = strtol(m_sChannel.c_str(), NULL, 10); } virtual ~RadioBandMap() {} @@ -521,6 +199,7 @@ namespace MTS { std::string m_sRadioType; }; + private: std::string m_sName; std::string m_sRadioPort; std::string m_sFirmware; @@ -529,14 +208,8 @@ namespace MTS { bool m_bEchoEnabled; bool m_bEnableEchoOnClose; - - std::string queryLteLac(); - std::string queryCGREGstring(); - void setCGREG(std::string value); }; } } - - #endif /* MTS_IO_CELLULARRADIO_H_ */ diff --git a/include/mts/MTS_IO_CellularRadioFactory.h b/include/mts/MTS_IO_CellularRadioFactory.h index 49f63bd..c9cb56f 100644 --- a/include/mts/MTS_IO_CellularRadioFactory.h +++ b/include/mts/MTS_IO_CellularRadioFactory.h @@ -21,47 +21,44 @@ #ifndef MTS_IO_CELLULARRADIOFACTORY_H_ #define MTS_IO_CELLULARRADIOFACTORY_H_ -#include <mts/MTS_IO_CellularRadio.h> #include <string> #include <map> +#include <mts/MTS_IO_ICellularRadio.h> + namespace MTS { namespace IO { - - class HE910Radio; - class GE910Radio; - class DE910Radio; - class CE910Radio; - class CellularRadioFactory { + class EXPORT CellularRadioFactory { public: CellularRadioFactory(); virtual ~CellularRadioFactory() {}; - virtual CellularRadio* create(const std::string& sModel, const std::string& sPort = CellularRadio::DEFAULT_RADIO_PORT); - - virtual CellularRadio* createHE910D(const std::string& sPort = CellularRadio::DEFAULT_RADIO_PORT); - virtual CellularRadio* createHE910EUD(const std::string& sPort = CellularRadio::DEFAULT_RADIO_PORT); - virtual CellularRadio* createLE910NAG(const std::string& sPort = CellularRadio::DEFAULT_RADIO_PORT); - virtual CellularRadio* createLE910C4NF(const std::string& sPort = CellularRadio::DEFAULT_RADIO_PORT); - virtual CellularRadio* createLE910NA1(const std::string& sPort = CellularRadio::DEFAULT_RADIO_PORT); - virtual CellularRadio* createLE910SVG(const std::string& sPort = CellularRadio::DEFAULT_RADIO_PORT); - virtual CellularRadio* createLE910EUG(const std::string& sPort = CellularRadio::DEFAULT_RADIO_PORT); - virtual CellularRadio* createLE910C4EU(const std::string& sPort = CellularRadio::DEFAULT_RADIO_PORT); - virtual CellularRadio* createLE910EU1(const std::string& sPort = CellularRadio::DEFAULT_RADIO_PORT); - virtual CellularRadio* createLE910C1NS(const std::string& sPort = CellularRadio::DEFAULT_RADIO_PORT); - virtual CellularRadio* createLE910C1AP(const std::string& sPort = CellularRadio::DEFAULT_RADIO_PORT); - virtual CellularRadio* createME910C1NA(const std::string& sPort = CellularRadio::DEFAULT_RADIO_PORT); - virtual CellularRadio* createME910C1NV(const std::string& sPort = CellularRadio::DEFAULT_RADIO_PORT); - virtual CellularRadio* createME910C1WW(const std::string& sPort = CellularRadio::DEFAULT_RADIO_PORT); - virtual CellularRadio* createGE910(const std::string& sPort = CellularRadio::DEFAULT_RADIO_PORT); - virtual CellularRadio* createDE910(const std::string& sPort = CellularRadio::DEFAULT_RADIO_PORT); - virtual CellularRadio* createCE910(const std::string& sPort = CellularRadio::DEFAULT_RADIO_PORT); - virtual CellularRadio* createLE866A1JS(const std::string& sPort = CellularRadio::DEFAULT_RADIO_PORT); + ICellularRadio* create(const std::string& sModel, const std::string& sPort = ICellularRadio::DEFAULT_RADIO_PORT); + + ICellularRadio* createHE910D(const std::string& sPort = ICellularRadio::DEFAULT_RADIO_PORT) const; + ICellularRadio* createHE910EUD(const std::string& sPort = ICellularRadio::DEFAULT_RADIO_PORT) const; + ICellularRadio* createLE910NAG(const std::string& sPort = ICellularRadio::DEFAULT_RADIO_PORT) const; + ICellularRadio* createLE910C4NF(const std::string& sPort = ICellularRadio::DEFAULT_RADIO_PORT) const; + ICellularRadio* createLE910NA1(const std::string& sPort = ICellularRadio::DEFAULT_RADIO_PORT) const; + ICellularRadio* createLE910SVG(const std::string& sPort = ICellularRadio::DEFAULT_RADIO_PORT) const; + ICellularRadio* createLE910EUG(const std::string& sPort = ICellularRadio::DEFAULT_RADIO_PORT) const; + ICellularRadio* createLE910C4EU(const std::string& sPort = ICellularRadio::DEFAULT_RADIO_PORT) const; + 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; + ICellularRadio* createCE910(const std::string& sPort = ICellularRadio::DEFAULT_RADIO_PORT) const; + ICellularRadio* createLE866A1JS(const std::string& sPort = ICellularRadio::DEFAULT_RADIO_PORT) const; + ICellularRadio* createEG95Radio(const std::string& sPort = ICellularRadio::DEFAULT_RADIO_PORT) const; protected: - typedef MTS::IO::CellularRadio* (CellularRadioFactory::*CREATEFUNCPTR)(const std::string& sPort); + typedef MTS::IO::ICellularRadio* (CellularRadioFactory::*CREATEFUNCPTR)(const std::string& sPort) const; std::map< std::string, CREATEFUNCPTR > m_mCreationMap; virtual std::string identifyRadio(const std::string& sPort); diff --git a/include/mts/MTS_IO_EG95Radio.h b/include/mts/MTS_IO_EG95Radio.h new file mode 100644 index 0000000..f3021cc --- /dev/null +++ b/include/mts/MTS_IO_EG95Radio.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2019 by Multi-Tech Systems + * + * This file is part of libmts-io. + * + * libmts-io is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * libmts-io is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libmts-io. If not, see <http://www.gnu.org/licenses/>. + * + */ + + +#ifndef MTS_IO_EG95RADIO_H_ +#define MTS_IO_EG95RADIO_H_ + +#include "mts/MTS_IO_QuectelRadio.h" + +namespace MTS { + namespace IO { + + class EG95Radio : public QuectelRadio { + + public: + static const std::string MODEL_NAME; + + EG95Radio(const std::string& sPort); + virtual ~EG95Radio(); + CODE setRxDiversity(const Json::Value& jArgs); + + protected: + + private: + + }; + } +} + +#endif /* MTS_IO_EG95RADIO_H_ */ diff --git a/include/mts/MTS_IO_GE910Radio.h b/include/mts/MTS_IO_GE910Radio.h index 27efbac..4904ea7 100644 --- a/include/mts/MTS_IO_GE910Radio.h +++ b/include/mts/MTS_IO_GE910Radio.h @@ -29,12 +29,12 @@ #ifndef MTS_IO_GE910RADIO_H_ #define MTS_IO_GE910RADIO_H_ -#include <mts/MTS_IO_CellularRadio.h> +#include <mts/MTS_IO_TelitRadio.h> namespace MTS { namespace IO { - class GE910Radio : public CellularRadio { + class GE910Radio : public TelitRadio { public: static const std::string MODEL_NAME; diff --git a/include/mts/MTS_IO_HE910Radio.h b/include/mts/MTS_IO_HE910Radio.h index e6fc73c..c8700da 100644 --- a/include/mts/MTS_IO_HE910Radio.h +++ b/include/mts/MTS_IO_HE910Radio.h @@ -29,12 +29,12 @@ #ifndef MTS_IO_HE910RADIO_H_ #define MTS_IO_HE910RADIO_H_ -#include <mts/MTS_IO_CellularRadio.h> +#include <mts/MTS_IO_TelitRadio.h> namespace MTS { namespace IO { - class HE910Radio : public CellularRadio { + class HE910Radio : public TelitRadio { public: diff --git a/include/mts/MTS_IO_ICellularRadio.h b/include/mts/MTS_IO_ICellularRadio.h new file mode 100644 index 0000000..e2bf652 --- /dev/null +++ b/include/mts/MTS_IO_ICellularRadio.h @@ -0,0 +1,453 @@ +#ifndef MTS_IO_ICELLULARRADIO_H +#define MTS_IO_ICELLULARRADIO_H + +#include <string> +#include <vector> +#include <functional> + +#include <json/json.h> + +#include <mts/MTS_AutoPtr.h> +#include <mts/MTS_IO_SerialConnection.h> + +#define EXPORT __attribute__((visibility("default"))) + +namespace MTS { + namespace IO { + class EXPORT ICellularRadio + { + public: + typedef std::function<bool(const std::string&/*iterationData*/, const std::string&/*allData*/)> IsNeedMoreData; + typedef std::function<void(const Json::Value&)> UpdateCb; + + //Registration Values + enum REGISTRATION : uint8_t { + NOT_REGISTERED = 0, + REGISTERED = 1, + SEARCHING=2, + DENIED=3, + UNKNOWN=4, + ROAMING=5 + }; + + enum SERVICEDOMAIN : uint8_t { + NO_SERVICE = 0, + CS_ONLY = 1, + PS_ONLY = 2, + CSPS = 3 + }; + + enum ACTIVEBAND : uint8_t { + GSM_850 = 0, + GSM_900 = 1, + DCS_1800 = 2, + PCS_1900 = 3 + }; + + enum CODE : uint8_t { + SUCCESS = 0, + ERROR, + FAILURE, + NO_RESPONSE, + NOT_APPLICABLE, + INVALID_ARGS + }; + + enum SIMSTATUS : uint8_t { + READY = 0, + LOCKED, + BLOCKED, + NOT_INSERTED + }; + + enum RADIO_NETWORK_MODE : uint8_t { + RADIO_NETWORK_MODE_UNKNOWN = 0, + RADIO_NETWORK_MODE_AUTO, + RADIO_NETWORK_MODE_GSM_ONLY, + RADIO_NETWORK_MODE_UMTS_ONLY, + RADIO_NETWORK_MODE_LTE_ONLY + }; + + static CODE convertModelToType(const std::string& sModel, std::string& sType); + static CODE convertModelToMtsShortCode(const std::string& sModel, std::string& sCode, ICellularRadio *radioObj = NULL); + static CODE convertServiceDomainToString(SERVICEDOMAIN eSd, std::string& sSd); + static CODE convertActiveBandToString(ACTIVEBAND eBand, std::string& sBand); + + static std::string sendCommand(MTS::AutoPtr<MTS::IO::Connection>& apIo, + const std::string& sCmd, + IsNeedMoreData& isNeedMoreData, + int32_t timeoutMillis = 100, + const char& ESC = CR); + static std::string sendCommand(MTS::AutoPtr<MTS::IO::Connection>& apIo, + const std::string& sCmd, + const std::vector<std::string>& vBail = DEFAULT_BAIL_STRINGS, + int32_t timeoutMillis = 100, + const char& ESC = CR); + static CODE test(MTS::AutoPtr<MTS::IO::Connection>& apIo, uint32_t timeoutSeconds = 30); + static std::string extractModelFromResult(const std::string& sResult); + static std::string getCodeAsString(CODE code); + + static const char *DEFAULT_RADIO_PORT; + static const char *DEFAULT_RADIO_DIR; + + static const char *VALUE_UNKNOWN; + static const char *VALUE_UNAVAILABLE; + static const char *VALUE_NOT_SUPPORTED; + + //Special Payload Characters + static const char ETX; //Ends socket connection + static const char DLE; //Escapes ETX and DLE within Payload + static const char CR; + static const char NL; + static const char CTRL_Z; + + static const char *RSP_OK; + static const char *RSP_ERROR; + + static const char *VALUE_NOT_REGISTERED; + static const char *VALUE_REGISTERED; + static const char *VALUE_SEARCHING; + static const char *VALUE_DENIED; + static const char *VALUE_ROAMING; + + //Static Data + static const char *KEY_TYPE; //!< GSM or CDMA + static const char *KEY_CODE; //!< Product Code : H5, H6, C2, EV3, G3 + static const char *KEY_MODEL; //!< Model : HE910, CE910, DE910, GE910 + static const char *KEY_MANUFACTURER; //!< Manufacturer: Telit + static const char *KEY_HARDWARE; //!< Radio Hardware Version + static const char *KEY_FIRMWARE; //!< Radio Firmware Version + static const char *KEY_FIRMWARE_BUILD;//!< Radio Firmware Build + static const char *KEY_IMEI; //!< International Mobile Station Equipment Identity + static const char *KEY_MEID; //!< Mobile Equipment Identifier + static const char *KEY_IMSI; //!< International Mobile Subscriber Identity + static const char *KEY_MSID; //!< Mobil Station ID (MSID) aka MIN aka MSIN aka Last few digits of IMSI + static const char *KEY_MDN; //!< Mobile Directory Number : Actual phone number dialed to reach radio + static const char *KEY_CARRIER; //!< Cellular Service Provider (Home Network) + static const char *KEY_ICCID; //!< Integrated Circuit Card Identifier + static const char *KEY_MSL; //!< Master Subsidy Lock + + + //Network Status Data + static const char *KEY_ROAMING; //!< Indicates whether or not using Home Network + static const char *KEY_DATETIME; //!< Date and Time from tower + static const char *KEY_SERVICE; //!< Service Connection Type [GPRS, EGPRS, WCDMA, HSDPA, 1xRTT, EVDO] + static const char *KEY_NETWORK; //!< Cellular Service Provider + static const char *KEY_NETWORK_REG; //!< Network Registration + static const char *KEY_CID; //!< Cellular ID (Tower) in HEX + static const char *KEY_LAC; //!< Location Area Code in HEX + static const char *KEY_RAC; //!< Routing Area Code in HEX + static const char *KEY_RSSI; //!< Received Signal Strength Indication + static const char *KEY_RSSIDBM; //!< Received Signal Strength Indication in dBm + static const char *KEY_MCC; //!< Mobile Country Code + static const char *KEY_MNC; //!< Mobile Network (Operator) Code + static const char *KEY_CHANNEL; //!< ARFCN or UARFCN Assigned Radio Channel + static const char *KEY_TXPWR; //!< Transmit Power + static const char *KEY_PSC; //!< Active Primary Synchronization Code (PSC) + static const char *KEY_ECIO; //!< Active Ec/Io (chip energy per total wideband power in dBm) + static const char *KEY_RSCP; //!< Active RSCP (Received Signal Code Power in dBm) + static const char *KEY_DRX; //!< Discontinuous reception cycle length (ms) + static const char *KEY_MM; //!< Mobility Management State + static const char *KEY_RR; //!< Radio Resource State + static const char *KEY_NOM; //!< Network Operator Mode + static const char *KEY_ABND; //!< Active Band + static const char *KEY_BLER; //!< Block Error Rate (percentage) + static const char *KEY_SD; //!< Service Domain + static const char *KEY_DEBUG; //!< Debug Information + + static const char *KEY_MIP; //!< Mobile IP Information + static const char *KEY_MIP_ID; //!< MIP Profile ID + static const char *KEY_MIP_ENABLED; //!< MIP Profile Enabled/Disabled + static const char *KEY_MIP_NAI; //!< Network Access Identifier + static const char *KEY_MIP_HOMEADDRESS; //!< Home Address + static const char *KEY_MIP_PRIMARYHA; //!< Primary Home Agent + static const char *KEY_MIP_SECONDARYHA; //!< Secondary Home Agent + static const char *KEY_MIP_MNAAASPI; //!< Mobile Node Authentication, Authorization, and Accounting Server Security Parameter Index + static const char *KEY_MIP_MNHASPI; //!< Mobile Node Home Agent Security Server Parameter Index + static const char *KEY_MIP_REVTUN; //!< Reverse Tunneling Enabled + static const char *KEY_MIP_MNAAASS; //!< Mobile Node Authentication, Authorization, and Accounting Server Shared Secret + static const char *KEY_MIP_MNHASS; //!< Mobile Node Home Agent Shared Secret + + //SIM Status Summary data + static const char *KEY_IS_SIM_INSERTED; //!< SIM card insertion indicator. True when a SIM card is inserted + static const char *KEY_IS_SIM_LOCKED; //!< SIM card lock status indicator. True when a SIM card is locked by PIN / PUK / other code + static const char *KEY_SIM_LOCK_STATUS; //!< SIM card lock status string. Either "READY", "SIM PIN", "SIM PUK" or other state + static const char *KEY_ATTEMPTS_PIN; //!< The number of attempts left to unlock the SIM card using PIN code + static const char *KEY_ATTEMPTS_PUK; //!< The number of attempts left to unlock the SIM card using PUK code + + //Values - Type + static const char *VALUE_TYPE_LTE; + static const char *VALUE_TYPE_GSM; + static const char *VALUE_TYPE_CDMA; + + //Values - Carrier + static const char *VALUE_CARRIER_VERIZON; + static const char *VALUE_CARRIER_AERIS; + static const char *VALUE_CARRIER_SPRINT; + static const char *VALUE_CARRIER_USCELLULAR; + static const char *VALUE_CARRIER_ATT; + static const char *VALUE_CARRIER_TMOBILE; + + static const char *VALUE_SD_NO_SERVICE; + static const char *VALUE_SD_CS_ONLY; + static const char *VALUE_SD_PS_ONLY; + static const char *VALUE_SD_CSPS; + + static const char *VALUE_ABND_GSM_850; + static const char *VALUE_ABND_GSM_900; + static const char *VALUE_ABND_DCS_1800; + static const char *VALUE_ABND_PCS_1900; + + static const std::vector<std::string> DEFAULT_BAIL_STRINGS; + + virtual ~ICellularRadio() = 0; + + virtual bool initialize(uint32_t iTimeoutMillis = 5000) = 0; + virtual bool resetRadio(uint32_t iTimeoutMillis = 5000) = 0; + virtual bool resetConnection(uint32_t iTimeoutMillis = 5000) = 0; + virtual void shutdown() = 0; + + virtual const std::string& getName() const = 0; + + virtual CODE getModel(std::string& sModel) = 0; + + virtual CODE getFirmware(std::string& sFirmware) = 0; + virtual CODE getFirmwareBuild(std::string& sFirmwareBuild) = 0; + virtual CODE getHardware(std::string& sHardware) = 0; + virtual CODE getManufacturer(std::string& sManufacturer) = 0; + virtual CODE getImei(std::string& sImei) = 0; + virtual CODE getMeid(std::string& sMeid) = 0; + virtual CODE getImsi(std::string& sImsi) = 0; + virtual CODE getSimStatus(std::string& sSimStatus) = 0; + + /** + * @brief getSimStatusSummary - get summary on the SIM card status + * (if there is a SIM card inserted, is it locked, etc). + * See below for the full list of returned fields. + * + * - `isSimInserted` - bool, is the SIM card installed or not; + * - `isSimLocked` - bool, is the SIM card blocked with PIN/PUK or not (or is READY); + * - `lockStatus` - string, either "READY", "SIM PUK", "SIM PIN" or other status as + * returned by "AT+CPIN?" AT command; + * - `attemptsPin` - integer, the number of attempts lef to enter a PIN code; + * - `attemptsPuk` - integer, the number of attempts lef to enter a PUK code. + * + * **Only `isSimInserted` is always present.** All other fields are omitted if + * the SIM card is removed. + * + * @param jData - an object to be filled with data + * @return CODE::SUCCESS on success, + * CODE::NOT_APPLICABLE if not supported by this radio + * and CODE::ERROR otherwise + */ + virtual CODE getSimStatusSummary(Json::Value& jData) = 0; + + virtual CODE getIccid(std::string& sIccid) = 0; + virtual CODE getService(std::string& sService) = 0; + virtual CODE getLac(std::string& sLac) = 0; + virtual CODE getMdn(std::string& sMdn) = 0; + virtual CODE getMsid(std::string& sMsid) = 0; + virtual CODE getType(std::string& sType) = 0; + virtual CODE getCarrier(std::string& sCarrier) = 0; + virtual CODE getNetwork(std::string& sNetwork) = 0; + virtual CODE getTower(std::string& sTower) = 0; + virtual CODE getTime(std::string& sDate, std::string& sTime, std::string& sTimeZone) = 0; + virtual CODE getRoaming(bool& bRoaming) = 0; + + virtual CODE getSignalStrength(int32_t& iRssi) = 0; + virtual CODE getModemLocation(std::string& sLocation) = 0; + virtual CODE convertSignalStrengthTodBm(const int32_t& iRssi, int32_t& dBm) = 0; + virtual CODE convertdBmToSignalStrength(const int32_t& dBm, int32_t& iRssi) = 0; + + virtual CODE getRegistration(REGISTRATION& eRegistration) = 0; + virtual CODE convertRegistrationToString(REGISTRATION eRegistration, std::string& sRegistration) = 0; + + /** + * @brief unlockSimCard - unlock the SIM card using PIN code provided + * + * This command does not peform any checks on the number of attempts left. + * Use with caution, verify the SIM status manually before execution. + * + * @param jArgs - a JSON object with the following format: + * + * jArgs = { + * "pin" : "A correct PIN code to unlock the SIM card: STRING" + * } + * + * @return CODE::SUCCESS when SIM card was succeffully unlocked, + * CODE::INVALID_ARGS when passed arguments are invalid, + * CODE::ERROR otherwise (i.e. when modem is not responding, + * when SIM card is removed, when PIN code is not correct + * or on any other error). + */ + virtual CODE unlockSimCard(const Json::Value& jArgs) = 0; + virtual CODE getRadioNetworkMode(RADIO_NETWORK_MODE &mode) = 0; + virtual CODE setRadioNetworkMode(RADIO_NETWORK_MODE mode) = 0; + + //! Gather details of the radio's Mobile IP Profile + /*! + \param Json::Value object that will be populated with MIP data + \return Returns result code of gathering MIP + */ + virtual CODE getMipProfile(Json::Value& jMipProfile) = 0; + + /* + * jArgs = { + * "msl" : "Master Subsidy Lock (Aeris, Sprint): STRING" + * } + */ + virtual CODE validateMsl(const Json::Value& jArgs) = 0; + + /* + * jArgs = { + * "mdn" : "Mobile Directory Number : STRING", + * "msl" : "[OPTIONAL] Master Subsidy Lock (Aeris, Sprint): STRING" + * } + */ + virtual CODE setMdn(const Json::Value& jArgs) = 0; + + /* + * jArgs = { + * "msid" : "Mobil Station ID (MSID) aka MIN aka MSIN : STRING", + * "msl" : "[OPTIONAL] Master Subsidy Lock (Aeris, Sprint): STRING" + * } + */ + virtual CODE setMsid(const Json::Value& jArgs) = 0; + + /* + * jArgs = { + * "activeProfile" : "Set active profile: STRING" + * } + */ + virtual CODE setMipActiveProfile(const Json::Value& jArgs) = 0; + + /* + * jArgs = { + * "nai" : "Network Access Identifier : STRING" + * } + */ + virtual CODE setMipNai(const Json::Value& jArgs) = 0; + + /* + * jArgs = { + * "homeIp" : "Home Address : STRING" + * } + */ + virtual CODE setMipHomeIp(const Json::Value& jArgs) = 0; + + /* + * jArgs = { + * "primaryHa" : "Primary Home Agent : STRING" + * } + */ + virtual CODE setMipPrimaryHa(const Json::Value& jArgs) = 0; + + /* + * jArgs = { + * "secondaryHa" : "Secondary Home Agent : STRING" + * } + */ + virtual CODE setMipSecondaryHa(const Json::Value& jArgs) = 0; + + /* + * jArgs = { + * "mnAaaSpi" : "Mobile Node Authentication, Authorization, and Accounting Server Security Parameter Index : STRING" + * } + */ + virtual CODE setMipMnAaaSpi(const Json::Value& jArgs) = 0; + + /* + * jArgs = { + * "mnHaSpi" : "Mobile Node Home Agent Security Server Parameter Index : STRING" + * } + */ + virtual CODE setMipMnHaSpi(const Json::Value& jArgs) = 0; + + /* + * jArgs = { + * "revTun" : "[DESCRIPTION] : STRING" + * } + */ + virtual CODE setMipRevTun(const Json::Value& jArgs) = 0; + + /* + * jArgs = { + * "mnAaaSs" : "Mobile Node Authentication, Authorization, and Accounting Server Shared Secret : STRING" + * } + */ + virtual CODE setMipMnAaaSs(const Json::Value& jArgs) = 0; + + /* + * jArgs = { + * "mnHaSs" : "Mobile Node Home Agent Shared Secret : STRING" + * } + */ + virtual CODE setMipMnHaSs(const Json::Value& jArgs) = 0; + + /* + * jArgs = null + */ + virtual CODE updateDc(const Json::Value& jArgs, UpdateCb& stepCb) = 0; + + /* + * jArgs = null + */ + virtual CODE updatePrl(const Json::Value& jArgs, UpdateCb& stepCb) = 0; + + /* + * jArgs = null + */ + virtual CODE updateFumo(const Json::Value& jArgs, UpdateCb& stepCb) = 0; + + /* + * jArgs = { + * "msl" : "Master Subsidy Lock (Sprint): STRING" + * } + */ + virtual CODE resetHfa(const Json::Value& jArgs, UpdateCb& stepCb) = 0; + + /* + * jArgs = { + * "mdn" : "Mobile Directory Number (Aeris): STRING" + * "msid" : "Mobile Station ID (Aeris): STRING" + * } + */ + virtual CODE activate(const Json::Value& jArgs, UpdateCb& stepCb) = 0; + + /* + * jArgs = { + * "enabled" : "RX Diversity Enabled ("0" or "1"): STRING" + * } + */ + virtual CODE setRxDiversity(const Json::Value& jArgs) = 0; + /* + * jArgs = { + * "fwid" : "Firmware Image To Be Enabled: STRING" + * } + */ + virtual CODE setActiveFirmware(const Json::Value& jArgs) = 0; + virtual CODE getActiveFirmware(std::string& sFwId) = 0; + + virtual CODE getEcho(bool& bEnabled) = 0; + virtual CODE setEcho(bool bEnabled = true) = 0; + + virtual CODE getStaticInformation(Json::Value& jData) = 0; + virtual CODE getNetworkStatus(Json::Value& jData) = 0; + + virtual CODE sendBasicCommand(const std::string& sCmd, int32_t timeoutMillis = 100, const char& ESC = CR) = 0; + + virtual std::string sendCommand(const std::string& sCmd, + const std::vector<std::string>& vBail = DEFAULT_BAIL_STRINGS, + int32_t timeoutMillis = 100, + const char& ESC = CR) = 0; + + virtual std::string sendCommand(const std::string& sCmd, + IsNeedMoreData& isNeedMoreData, + int32_t timeoutMillis = 100, + const char& ESC = CR) = 0; + + }; + } +} + +#endif diff --git a/include/mts/MTS_IO_LE866Radio.h b/include/mts/MTS_IO_LE866Radio.h index c11c5b4..2775e4d 100644 --- a/include/mts/MTS_IO_LE866Radio.h +++ b/include/mts/MTS_IO_LE866Radio.h @@ -35,12 +35,12 @@ A more elaborate description */ -#include <mts/MTS_IO_CellularRadio.h> +#include <mts/MTS_IO_TelitRadio.h> namespace MTS { namespace IO { - class LE866Radio : public CellularRadio { + class LE866Radio : public TelitRadio { public: static const std::string MODEL_NAME; diff --git a/include/mts/MTS_IO_LE910Radio.h b/include/mts/MTS_IO_LE910Radio.h index e8ac21f..35e704d 100644 --- a/include/mts/MTS_IO_LE910Radio.h +++ b/include/mts/MTS_IO_LE910Radio.h @@ -29,12 +29,12 @@ #ifndef MTS_IO_LE910RADIO_H_ #define MTS_IO_LE910RADIO_H_ -#include <mts/MTS_IO_CellularRadio.h> +#include <mts/MTS_IO_TelitRadio.h> namespace MTS { namespace IO { - class LE910Radio : public CellularRadio { + class LE910Radio : public TelitRadio { public: static const std::string MODEL_NAME; diff --git a/include/mts/MTS_IO_ME910C1WWRadio.h b/include/mts/MTS_IO_ME910C1WWRadio.h index bfbb8a6..d45d86a 100644 --- a/include/mts/MTS_IO_ME910C1WWRadio.h +++ b/include/mts/MTS_IO_ME910C1WWRadio.h @@ -33,8 +33,8 @@ namespace MTS { ME910C1WWRadio(const std::string& sPort); virtual ~ME910C1WWRadio(){}; - CellularRadio::CODE setActiveFirmware(const Json::Value& jArgs); - CellularRadio::CODE getActiveFirmware(std::string& sFwId); + ICellularRadio::CODE setActiveFirmware(const Json::Value& jArgs); + ICellularRadio::CODE getActiveFirmware(std::string& sFwId); protected: diff --git a/include/mts/MTS_IO_ME910Radio.h b/include/mts/MTS_IO_ME910Radio.h index 91cdfc6..09e8ede 100644 --- a/include/mts/MTS_IO_ME910Radio.h +++ b/include/mts/MTS_IO_ME910Radio.h @@ -21,12 +21,12 @@ #ifndef MTS_IO_ME910RADIO_H_ #define MTS_IO_ME910RADIO_H_ -#include <mts/MTS_IO_CellularRadio.h> +#include <mts/MTS_IO_TelitRadio.h> namespace MTS { namespace IO { - class ME910Radio : public CellularRadio { + class ME910Radio : public TelitRadio { public: static const std::string MODEL_NAME; diff --git a/include/mts/MTS_IO_QuectelRadio.h b/include/mts/MTS_IO_QuectelRadio.h new file mode 100644 index 0000000..3b1ba5a --- /dev/null +++ b/include/mts/MTS_IO_QuectelRadio.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2019 by Multi-Tech Systems + * + * This file is part of libmts-io. + * + * libmts-io is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * libmts-io is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libmts-io. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#ifndef MTS_IO_QUECTELRADIO_H_ +#define MTS_IO_QUECTELRADIO_H_ + +#include <mts/MTS_IO_CellularRadio.h> + +namespace MTS { + namespace IO { + + class QuectelRadio : public CellularRadio { + + public: + bool resetRadio(uint32_t iTimeoutMillis = 5000) 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& dBm) override; + CODE convertdBmToSignalStrength(const int32_t& dBm, int32_t& iRssi) override; + + CODE setMdn(const Json::Value& jArgs) override; + CODE getRadioNetworkMode(RADIO_NETWORK_MODE &mode) override; + CODE setRadioNetworkMode(RADIO_NETWORK_MODE mode) override; + + protected: + QuectelRadio(const std::string& sName, const std::string& sRadioPort); + + CODE getIsSimInserted(bool& bData) override; + CODE getSimLockAttempts(int& iAttemptsPin, int& iAttemptsPuk) override; + + virtual CODE getServiceDomain(SERVICEDOMAIN& sd); + virtual CODE convertToActiveBand(const std::string& sQuectelBand, ACTIVEBAND& band); + + private: + + }; + } +} + +#endif /* MTS_IO_QUECTELRADIO_H_ */ diff --git a/include/mts/MTS_IO_TelitRadio.h b/include/mts/MTS_IO_TelitRadio.h new file mode 100644 index 0000000..6382696 --- /dev/null +++ b/include/mts/MTS_IO_TelitRadio.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2019 by Multi-Tech Systems + * + * This file is part of libmts-io. + * + * libmts-io is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * libmts-io is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libmts-io. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#ifndef MTS_IO_TELITRADIO_H_ +#define MTS_IO_TELITRADIO_H_ + +#include <mts/MTS_IO_CellularRadio.h> + +namespace MTS { + namespace IO { + class TelitRadio : public CellularRadio { + public: + bool resetRadio(uint32_t iTimeoutMillis = 5000) 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& dBm) override; + CODE convertdBmToSignalStrength(const int32_t& dBm, int32_t& iRssi) override; + + CODE setMdn(const Json::Value& jArgs) override; + CODE getRadioNetworkMode(RADIO_NETWORK_MODE &mode) override; + CODE setRadioNetworkMode(RADIO_NETWORK_MODE mode) override; + + protected: + TelitRadio(const std::string& sName, const std::string& sRadioPort); + + bool getCarrierFromFirmware(const std::string& sFirmware, std::string& sCarrier) override; + bool getHardwareVersionFromFirmware(const std::string& sFirmware, std::string& sHardware) override; + + CODE getIsSimInserted(bool& bData) override; + CODE getSimLockAttempts(int& iAttemptsPin, int& iAttemptsPuk) override; + + private: + virtual CODE getSimLockAttempts(int& iAttemptsPin, int& iAttemptsPuk, const std::string& sLockStatus); + + }; + } +} +#endif diff --git a/src/MTS_IO_CE910Radio.cpp b/src/MTS_IO_CE910Radio.cpp index 7bdf280..d1cad9b 100644 --- a/src/MTS_IO_CE910Radio.cpp +++ b/src/MTS_IO_CE910Radio.cpp @@ -39,7 +39,7 @@ CE910Radio::CE910Radio(const std::string& sPort) } -CellularRadio::CODE CE910Radio::setRxDiversity(const Json::Value& jArgs) { +ICellularRadio::CODE CE910Radio::setRxDiversity(const Json::Value& jArgs) { /* Command string for CE radios: N/A */ return FAILURE; } diff --git a/src/MTS_IO_CdmaRadio.cpp b/src/MTS_IO_CdmaRadio.cpp index 5b53f02..f84fd34 100644 --- a/src/MTS_IO_CdmaRadio.cpp +++ b/src/MTS_IO_CdmaRadio.cpp @@ -35,7 +35,7 @@ using namespace MTS::IO; CdmaRadio::CdmaRadio(const std::string& sName, const std::string& sPort) -: CellularRadio(sName, sPort) +: TelitRadio(sName, sPort) { } @@ -44,17 +44,17 @@ CdmaRadio::~CdmaRadio() { } -CellularRadio::CODE CdmaRadio::getImei(std::string& sImei) { +ICellularRadio::CODE CdmaRadio::getImei(std::string& sImei) { printTrace("%s| Get IMEI", getName().c_str()); return getMeid(sImei); } -CellularRadio::CODE CdmaRadio::getMeid(std::string& sMeid) { +ICellularRadio::CODE CdmaRadio::getMeid(std::string& sMeid) { printTrace("%s| Get MEID", getName().c_str()); - sMeid = VALUE_NOT_SUPPORTED; + sMeid = ICellularRadio::VALUE_NOT_SUPPORTED; std::string sCmd("AT#MEIDESN?"); - std::string sResult = CellularRadio::sendCommand(sCmd); - size_t pos = sResult.find(RSP_OK); + std::string sResult = sendCommand(sCmd); + size_t pos = sResult.find(ICellularRadio::RSP_OK); if (pos == std::string::npos) { printWarning("%s| Unable to get MEID from radio using command [%s]", getName().c_str(), sCmd.c_str()); return FAILURE; @@ -72,12 +72,12 @@ CellularRadio::CODE CdmaRadio::getMeid(std::string& sMeid) { return SUCCESS; } -CellularRadio::CODE CdmaRadio::getMsid(std::string& sMsid) { +ICellularRadio::CODE CdmaRadio::getMsid(std::string& sMsid) { printTrace("%s| Get MSID", getName().c_str()); - sMsid = VALUE_NOT_SUPPORTED; + sMsid = ICellularRadio::VALUE_NOT_SUPPORTED; std::string sCmd("AT$MSID?"); - std::string sResult = CellularRadio::sendCommand(sCmd); - size_t end = sResult.find(RSP_OK); + std::string sResult = sendCommand(sCmd); + size_t end = sResult.find(ICellularRadio::RSP_OK); if (end == std::string::npos) { printWarning("%s| Unable to get MSID from radio using command [%s]", getName().c_str(), sCmd.c_str()); return FAILURE; @@ -92,14 +92,14 @@ CellularRadio::CODE CdmaRadio::getMsid(std::string& sMsid) { return SUCCESS; } -CellularRadio::CODE CdmaRadio::getCarrier(std::string& sCarrier) { +ICellularRadio::CODE CdmaRadio::getCarrier(std::string& sCarrier) { if(m_sCarrier != "") { sCarrier = m_sCarrier; return SUCCESS; } std::string sFirmware; - CODE code = getFirmware(sFirmware); + ICellularRadio::CODE code = getFirmware(sFirmware); if(code != SUCCESS) { return code; } @@ -113,34 +113,34 @@ CellularRadio::CODE CdmaRadio::getCarrier(std::string& sCarrier) { return SUCCESS; } -CellularRadio::CODE CdmaRadio::getNetwork(std::string& sNetwork) { +ICellularRadio::CODE CdmaRadio::getNetwork(std::string& sNetwork) { return getCarrier(sNetwork); } -CellularRadio::CODE CdmaRadio::getSimStatus(std::string& sSimStatus) { +ICellularRadio::CODE CdmaRadio::getSimStatus(std::string& sSimStatus) { printTrace("%s| Get SIM Status", getName().c_str()); - sSimStatus = VALUE_NOT_SUPPORTED; + sSimStatus = ICellularRadio::VALUE_NOT_SUPPORTED; return NOT_APPLICABLE; } -CellularRadio::CODE CdmaRadio::getIccid(std::string& sIccid) { +ICellularRadio::CODE CdmaRadio::getIccid(std::string& sIccid) { printTrace("%s| Get ICCID", getName().c_str()); - sIccid = VALUE_NOT_SUPPORTED; + sIccid = ICellularRadio::VALUE_NOT_SUPPORTED; return NOT_APPLICABLE; } -CellularRadio::CODE CdmaRadio::getLac(std::string& sLac) { +ICellularRadio::CODE CdmaRadio::getLac(std::string& sLac) { printTrace("%s| Get LAC", getName().c_str()); - sLac = VALUE_NOT_SUPPORTED; + sLac = ICellularRadio::VALUE_NOT_SUPPORTED; return NOT_APPLICABLE; } -CellularRadio::CODE CdmaRadio::getService(std::string& sService) { +ICellularRadio::CODE CdmaRadio::getService(std::string& sService) { printTrace("%s| Get Service", getName().c_str()); - sService = VALUE_NOT_SUPPORTED; + sService = ICellularRadio::VALUE_NOT_SUPPORTED; std::string sCmd("AT+SERVICE?"); - std::string sResult = CellularRadio::sendCommand(sCmd); - size_t end = sResult.find(RSP_OK); + std::string sResult = sendCommand(sCmd); + size_t end = sResult.find(ICellularRadio::RSP_OK); if (end == std::string::npos) { printWarning("%s| Unable to get Service from radio using command [%s]", getName().c_str(), sCmd.c_str()); return FAILURE; @@ -159,7 +159,7 @@ CellularRadio::CODE CdmaRadio::getService(std::string& sService) { case 2: sService = "EVDO"; break; //Release 0 case 3: sService = "EVDO"; break; //Release A case 4: sService = "GPRS"; break; - default: sService = VALUE_UNKNOWN; break; + default: sService = ICellularRadio::VALUE_UNKNOWN; break; } printDebug("%s| Service ID: [%d][%s]", getName().c_str(), iService, sService.c_str()); @@ -167,12 +167,12 @@ CellularRadio::CODE CdmaRadio::getService(std::string& sService) { return SUCCESS; } -CellularRadio::CODE CdmaRadio::getHardware(std::string& sHardware) { +ICellularRadio::CODE CdmaRadio::getHardware(std::string& sHardware) { printTrace("%s| Get Hardware", getName().c_str()); - sHardware = VALUE_NOT_SUPPORTED; + sHardware = ICellularRadio::VALUE_NOT_SUPPORTED; std::string sCmd("AT#HWREV"); - std::string sResult = CellularRadio::sendCommand(sCmd); - size_t pos = sResult.find(RSP_OK); + std::string sResult = sendCommand(sCmd); + size_t pos = sResult.find(ICellularRadio::RSP_OK); if (pos == std::string::npos) { printWarning("%s| Unable to get hardware from radio using command [%s]", getName().c_str(), sCmd.c_str()); return FAILURE; @@ -187,12 +187,12 @@ CellularRadio::CODE CdmaRadio::getHardware(std::string& sHardware) { return SUCCESS; } -CellularRadio::CODE CdmaRadio::getMdn(std::string& sMdn) { +ICellularRadio::CODE CdmaRadio::getMdn(std::string& sMdn) { printTrace("%s| Get MDN", getName().c_str()); - sMdn = VALUE_NOT_SUPPORTED; + sMdn = ICellularRadio::VALUE_NOT_SUPPORTED; std::string sCmd("AT+CNUM"); - std::string sResult = CellularRadio::sendCommand(sCmd); - size_t end = sResult.find(RSP_OK); + std::string sResult = sendCommand(sCmd); + size_t end = sResult.find(ICellularRadio::RSP_OK); if (end == std::string::npos) { printWarning("%s| Unable to get MDN from radio using command [%s]", getName().c_str(), sCmd.c_str()); return FAILURE; @@ -213,7 +213,7 @@ CellularRadio::CODE CdmaRadio::getMdn(std::string& sMdn) { return SUCCESS; } -CellularRadio::CODE CdmaRadio::validateMsl(const Json::Value& jArgs) { +ICellularRadio::CODE CdmaRadio::validateMsl(const Json::Value& jArgs) { printTrace("%s| Validate MSL", getName().c_str()); if(!jArgs["msl"].isString()) { @@ -239,7 +239,7 @@ CellularRadio::CODE CdmaRadio::validateMsl(const Json::Value& jArgs) { return setMdn(jMdn); } -CellularRadio::CODE CdmaRadio::setMdn(const Json::Value& jArgs) { +ICellularRadio::CODE CdmaRadio::setMdn(const Json::Value& jArgs) { printTrace("%s| Set MDN", getName().c_str()); if(!jArgs["mdn"].isString()) { @@ -274,7 +274,7 @@ CellularRadio::CODE CdmaRadio::setMdn(const Json::Value& jArgs) { sCmd += sMdn; std::string sResult = sendCommand(sCmd); - size_t end = sResult.find(RSP_OK); + size_t end = sResult.find(ICellularRadio::RSP_OK); if (end == std::string::npos) { printWarning("%s| Unable to set MDN for radio using command [%s]", getName().c_str(), sCmd.c_str()); return FAILURE; @@ -283,7 +283,7 @@ CellularRadio::CODE CdmaRadio::setMdn(const Json::Value& jArgs) { return SUCCESS; } -CellularRadio::CODE CdmaRadio::setMsid(const Json::Value& jArgs) { +ICellularRadio::CODE CdmaRadio::setMsid(const Json::Value& jArgs) { printTrace("%s| Set MSID", getName().c_str()); if(!jArgs["msid"].isString()) { printError("%s| Arguments missing \"msid\"", getName().c_str()); @@ -309,7 +309,7 @@ CellularRadio::CODE CdmaRadio::setMsid(const Json::Value& jArgs) { sCmd += jArgs["msid"].asString(); std::string sResult = sendCommand(sCmd); - size_t end = sResult.find(RSP_OK); + size_t end = sResult.find(ICellularRadio::RSP_OK); if (end == std::string::npos) { printWarning("%s| Unable to set MSID for radio using command [%s]", getName().c_str(), sCmd.c_str()); return FAILURE; @@ -318,7 +318,7 @@ CellularRadio::CODE CdmaRadio::setMsid(const Json::Value& jArgs) { return SUCCESS; } -CellularRadio::CODE CdmaRadio::getMipProfile(Json::Value& jMipProfile) { +ICellularRadio::CODE CdmaRadio::getMipProfile(Json::Value& jMipProfile) { printTrace("%s| Get MIP Active Profile", getName().c_str()); initMipProfile(jMipProfile); @@ -329,7 +329,7 @@ CellularRadio::CODE CdmaRadio::getMipProfile(Json::Value& jMipProfile) { if(sCarrier == "Aeris" || sCarrier == "Sprint") { std::string sCmd("AT$QCMIPGETP"); std::string sResult = MTS::Text::trim(sendCommand(sCmd)); - if (sResult.find(RSP_OK) == std::string::npos) { + if (sResult.find(ICellularRadio::RSP_OK) == std::string::npos) { printWarning("%s| Unable to get active MIP profile for radio using command [%s]", getName().c_str(), sCmd.c_str()); return FAILURE; } @@ -341,34 +341,34 @@ CellularRadio::CODE CdmaRadio::getMipProfile(Json::Value& jMipProfile) { std::vector<std::string> vParts = MTS::Text::split(sLine, ':', 2); if(vParts.size() == 2 && vParts[0] == "Profile") { if(vParts[1].find("Enabled") != std::string::npos) { - jMipProfile[KEY_MIP_ENABLED] = true; + jMipProfile[ICellularRadio::KEY_MIP_ENABLED] = true; } else { - jMipProfile[KEY_MIP_ENABLED] = false; + jMipProfile[ICellularRadio::KEY_MIP_ENABLED] = false; } int32_t id; sscanf(vParts[1].c_str(), "%d", &id); - jMipProfile[KEY_MIP_ID] = id; + jMipProfile[ICellularRadio::KEY_MIP_ID] = id; } else { printWarning("%s| Unable to parse active MIP profile from line [%s]", getName().c_str(), sLine.c_str()); } - splitAndAssign(vLine[1], "NAI", jMipProfile, KEY_MIP_NAI); - splitAndAssign(vLine[2], "Home Addr", jMipProfile, KEY_MIP_HOMEADDRESS); - splitAndAssign(vLine[3], "Primary HA", jMipProfile, KEY_MIP_PRIMARYHA); - splitAndAssign(vLine[4], "Secondary HA", jMipProfile, KEY_MIP_SECONDARYHA); - splitAndAssign(vLine[5], "MN-AAA SPI", jMipProfile, KEY_MIP_MNAAASPI); - splitAndAssign(vLine[6], "MN-HA SPI", jMipProfile, KEY_MIP_MNHASPI); + splitAndAssign(vLine[1], "NAI", jMipProfile, ICellularRadio::KEY_MIP_NAI); + splitAndAssign(vLine[2], "Home Addr", jMipProfile, ICellularRadio::KEY_MIP_HOMEADDRESS); + splitAndAssign(vLine[3], "Primary HA", jMipProfile, ICellularRadio::KEY_MIP_PRIMARYHA); + splitAndAssign(vLine[4], "Secondary HA", jMipProfile, ICellularRadio::KEY_MIP_SECONDARYHA); + splitAndAssign(vLine[5], "MN-AAA SPI", jMipProfile, ICellularRadio::KEY_MIP_MNAAASPI); + splitAndAssign(vLine[6], "MN-HA SPI", jMipProfile, ICellularRadio::KEY_MIP_MNHASPI); //Reverse Tunneling sLine = vLine[7]; vParts = MTS::Text::split(sLine, ':', 2); if(vParts.size() == 2 && vParts[0] == "Rev Tun") { if(vParts[1] == "1") { - jMipProfile[KEY_MIP_REVTUN] = true; + jMipProfile[ICellularRadio::KEY_MIP_REVTUN] = true; } else { - jMipProfile[KEY_MIP_REVTUN] = false; + jMipProfile[ICellularRadio::KEY_MIP_REVTUN] = false; } } else { printWarning("%s| Unable to parse Reverse Tunneling from line [%s]", getName().c_str(), sLine.c_str()); @@ -379,9 +379,9 @@ CellularRadio::CODE CdmaRadio::getMipProfile(Json::Value& jMipProfile) { vParts = MTS::Text::split(sLine, ':', 2); if(vParts.size() == 2 && vParts[0] == "MN-AAA SS") { if(vParts[1] == "Set") { - jMipProfile[KEY_MIP_MNAAASS] = true; + jMipProfile[ICellularRadio::KEY_MIP_MNAAASS] = true; } else { - jMipProfile[KEY_MIP_MNAAASS] = false; + jMipProfile[ICellularRadio::KEY_MIP_MNAAASS] = false; } } else { printWarning("%s| Unable to parse MN-AAA SS from line [%s]", getName().c_str(), sLine.c_str()); @@ -392,9 +392,9 @@ CellularRadio::CODE CdmaRadio::getMipProfile(Json::Value& jMipProfile) { vParts = MTS::Text::split(sLine, ':', 2); if(vParts.size() == 2 && vParts[0] == "MN-HA SS") { if(vParts[1] == "Set") { - jMipProfile[KEY_MIP_MNHASS] = true; + jMipProfile[ICellularRadio::KEY_MIP_MNHASS] = true; } else { - jMipProfile[KEY_MIP_MNHASS] = false; + jMipProfile[ICellularRadio::KEY_MIP_MNHASS] = false; } } else { printWarning("%s| Unable to parse MN-HA SS from line [%s]", getName().c_str(), sLine.c_str()); @@ -406,7 +406,7 @@ CellularRadio::CODE CdmaRadio::getMipProfile(Json::Value& jMipProfile) { } -CellularRadio::CODE CdmaRadio::setMipActiveProfile(const Json::Value& jArgs) { +ICellularRadio::CODE CdmaRadio::setMipActiveProfile(const Json::Value& jArgs) { printTrace("%s| Set MIP Active Profile", getName().c_str()); if(!jArgs["activeProfile"].isString()) { @@ -417,7 +417,7 @@ CellularRadio::CODE CdmaRadio::setMipActiveProfile(const Json::Value& jArgs) { sCmd += jArgs["activeProfile"].asString(); std::string sResult = sendCommand(sCmd); - size_t end = sResult.find(RSP_OK); + size_t end = sResult.find(ICellularRadio::RSP_OK); if (end == std::string::npos) { printWarning("%s| Unable to set Active profile for radio using command [%s]", getName().c_str(), sCmd.c_str()); return FAILURE; @@ -426,7 +426,7 @@ CellularRadio::CODE CdmaRadio::setMipActiveProfile(const Json::Value& jArgs) { return SUCCESS; } -CellularRadio::CODE CdmaRadio::setMipNai(const Json::Value& jArgs) { +ICellularRadio::CODE CdmaRadio::setMipNai(const Json::Value& jArgs) { printTrace("%s| Set MIP NAI", getName().c_str()); if(!jArgs["nai"].isString()) { @@ -437,7 +437,7 @@ CellularRadio::CODE CdmaRadio::setMipNai(const Json::Value& jArgs) { sCmd += jArgs["nai"].asString() + ",1"; std::string sResult = sendCommand(sCmd); - size_t end = sResult.find(RSP_OK); + size_t end = sResult.find(ICellularRadio::RSP_OK); if (end == std::string::npos) { printWarning("%s| Unable to set NAI for radio using command [%s]", getName().c_str(), sCmd.c_str()); return FAILURE; @@ -446,7 +446,7 @@ CellularRadio::CODE CdmaRadio::setMipNai(const Json::Value& jArgs) { return SUCCESS; } -CellularRadio::CODE CdmaRadio::setMipHomeIp(const Json::Value& jArgs) { +ICellularRadio::CODE CdmaRadio::setMipHomeIp(const Json::Value& jArgs) { printTrace("%s| Set MIP Home IP", getName().c_str()); if(!jArgs["homeIp"].isString()) { @@ -457,7 +457,7 @@ CellularRadio::CODE CdmaRadio::setMipHomeIp(const Json::Value& jArgs) { sCmd += jArgs["homeIp"].asString() + ",1"; std::string sResult = sendCommand(sCmd); - size_t end = sResult.find(RSP_OK); + size_t end = sResult.find(ICellularRadio::RSP_OK); if (end == std::string::npos) { printWarning("%s| Unable to set Home IP profile for radio using command [%s]", getName().c_str(), sCmd.c_str()); return FAILURE; @@ -466,7 +466,7 @@ CellularRadio::CODE CdmaRadio::setMipHomeIp(const Json::Value& jArgs) { return SUCCESS; } -CellularRadio::CODE CdmaRadio::setMipPrimaryHa(const Json::Value& jArgs) { +ICellularRadio::CODE CdmaRadio::setMipPrimaryHa(const Json::Value& jArgs) { printTrace("%s| Set MIP Primary HA", getName().c_str()); if(!jArgs["primaryHa"].isString()) { @@ -477,7 +477,7 @@ CellularRadio::CODE CdmaRadio::setMipPrimaryHa(const Json::Value& jArgs) { sCmd += jArgs["primaryHa"].asString() + ",1"; std::string sResult = sendCommand(sCmd); - size_t end = sResult.find(RSP_OK); + size_t end = sResult.find(ICellularRadio::RSP_OK); if (end == std::string::npos) { printWarning("%s| Unable to set Primary HA for radio using command [%s]", getName().c_str(), sCmd.c_str()); return FAILURE; @@ -486,7 +486,7 @@ CellularRadio::CODE CdmaRadio::setMipPrimaryHa(const Json::Value& jArgs) { return SUCCESS; } -CellularRadio::CODE CdmaRadio::setMipSecondaryHa(const Json::Value& jArgs) { +ICellularRadio::CODE CdmaRadio::setMipSecondaryHa(const Json::Value& jArgs) { printTrace("%s| Set MIP Secondary HA", getName().c_str()); if(!jArgs["secondaryHa"].isString()) { @@ -497,7 +497,7 @@ CellularRadio::CODE CdmaRadio::setMipSecondaryHa(const Json::Value& jArgs) { sCmd += jArgs["secondaryHa"].asString() + ",1"; std::string sResult = sendCommand(sCmd); - size_t end = sResult.find(RSP_OK); + size_t end = sResult.find(ICellularRadio::RSP_OK); if (end == std::string::npos) { printWarning("%s| Unable to set Secondary HA for radio using command [%s]", getName().c_str(), sCmd.c_str()); return FAILURE; @@ -506,7 +506,7 @@ CellularRadio::CODE CdmaRadio::setMipSecondaryHa(const Json::Value& jArgs) { return SUCCESS; } -CellularRadio::CODE CdmaRadio::setMipMnAaaSpi(const Json::Value& jArgs) { +ICellularRadio::CODE CdmaRadio::setMipMnAaaSpi(const Json::Value& jArgs) { printTrace("%s| Set MIP MN-AAA SPI", getName().c_str()); if(!jArgs["mnAaaSpi"].isString()) { @@ -517,7 +517,7 @@ CellularRadio::CODE CdmaRadio::setMipMnAaaSpi(const Json::Value& jArgs) { sCmd += jArgs["mnAaaSpi"].asString() + ",1"; std::string sResult = sendCommand(sCmd); - size_t end = sResult.find(RSP_OK); + size_t end = sResult.find(ICellularRadio::RSP_OK); if (end == std::string::npos) { printWarning("%s| Unable to set MN-AAA SPI for radio using command [%s]", getName().c_str(), sCmd.c_str()); return FAILURE; @@ -526,7 +526,7 @@ CellularRadio::CODE CdmaRadio::setMipMnAaaSpi(const Json::Value& jArgs) { return SUCCESS; } -CellularRadio::CODE CdmaRadio::setMipMnHaSpi(const Json::Value& jArgs) { +ICellularRadio::CODE CdmaRadio::setMipMnHaSpi(const Json::Value& jArgs) { printTrace("%s| Set MIP MN-HA SPI", getName().c_str()); if(!jArgs["mnHaSpi"].isString()) { @@ -537,7 +537,7 @@ CellularRadio::CODE CdmaRadio::setMipMnHaSpi(const Json::Value& jArgs) { sCmd += jArgs["mnHaSpi"].asString() + ",1"; std::string sResult = sendCommand(sCmd); - size_t end = sResult.find(RSP_OK); + size_t end = sResult.find(ICellularRadio::RSP_OK); if (end == std::string::npos) { printWarning("%s| Unable to set MN-HA SPI for radio using command [%s]", getName().c_str(), sCmd.c_str()); return FAILURE; @@ -546,7 +546,7 @@ CellularRadio::CODE CdmaRadio::setMipMnHaSpi(const Json::Value& jArgs) { return SUCCESS; } -CellularRadio::CODE CdmaRadio::setMipRevTun(const Json::Value& jArgs) { +ICellularRadio::CODE CdmaRadio::setMipRevTun(const Json::Value& jArgs) { printTrace("%s| Set MIP Rev Tun", getName().c_str()); if(!jArgs["revTun"].isString()) { @@ -557,7 +557,7 @@ CellularRadio::CODE CdmaRadio::setMipRevTun(const Json::Value& jArgs) { sCmd += jArgs["revTun"].asString() + ",1"; std::string sResult = sendCommand(sCmd); - size_t end = sResult.find(RSP_OK); + size_t end = sResult.find(ICellularRadio::RSP_OK); if (end == std::string::npos) { printWarning("%s| Unable to set Rev Tun for radio using command [%s]", getName().c_str(), sCmd.c_str()); return FAILURE; @@ -566,7 +566,7 @@ CellularRadio::CODE CdmaRadio::setMipRevTun(const Json::Value& jArgs) { return SUCCESS; } -CellularRadio::CODE CdmaRadio::setMipMnAaaSs(const Json::Value& jArgs) { +ICellularRadio::CODE CdmaRadio::setMipMnAaaSs(const Json::Value& jArgs) { printTrace("%s| Set MIP MN-AAA SS", getName().c_str()); if(!jArgs["mnAaaSs"].isString()) { @@ -577,7 +577,7 @@ CellularRadio::CODE CdmaRadio::setMipMnAaaSs(const Json::Value& jArgs) { sCmd += jArgs["mnAaaSs"].asString() + ",1"; std::string sResult = sendCommand(sCmd); - size_t end = sResult.find(RSP_OK); + size_t end = sResult.find(ICellularRadio::RSP_OK); if (end == std::string::npos) { printWarning("%s| Unable to set MN-AAA SS for radio using command [%s]", getName().c_str(), sCmd.c_str()); return FAILURE; @@ -586,7 +586,7 @@ CellularRadio::CODE CdmaRadio::setMipMnAaaSs(const Json::Value& jArgs) { return SUCCESS; } -CellularRadio::CODE CdmaRadio::setMipMnHaSs(const Json::Value& jArgs) { +ICellularRadio::CODE CdmaRadio::setMipMnHaSs(const Json::Value& jArgs) { printTrace("%s| Set MIP MN-HA SS", getName().c_str()); if(!jArgs["mnHaSs"].isString()) { @@ -597,7 +597,7 @@ CellularRadio::CODE CdmaRadio::setMipMnHaSs(const Json::Value& jArgs) { sCmd += jArgs["mnHaSs"].asString() + ",1"; std::string sResult = sendCommand(sCmd); - size_t end = sResult.find(RSP_OK); + size_t end = sResult.find(ICellularRadio::RSP_OK); if (end == std::string::npos) { printWarning("%s| Unable to set MN-HA SS for radio using command [%s]", getName().c_str(), sCmd.c_str()); return FAILURE; @@ -606,7 +606,7 @@ CellularRadio::CODE CdmaRadio::setMipMnHaSs(const Json::Value& jArgs) { return SUCCESS; } -CellularRadio::CODE CdmaRadio::updateDc(const Json::Value& jArgs, UpdateCb& stepCb) { +ICellularRadio::CODE CdmaRadio::updateDc(const Json::Value& jArgs, UpdateCb& stepCb) { printTrace("%s| Update Device Configuration", getName().c_str()); std::string sCarrier; @@ -616,7 +616,7 @@ CellularRadio::CODE CdmaRadio::updateDc(const Json::Value& jArgs, UpdateCb& step return NOT_APPLICABLE; } - CellularRadio::CODE result = FAILURE; + ICellularRadio::CODE result = FAILURE; std::size_t pos = 0; std::size_t end = 0; @@ -627,7 +627,7 @@ CellularRadio::CODE CdmaRadio::updateDc(const Json::Value& jArgs, UpdateCb& step return true; } - end = allData.find(NL, pos); + end = allData.find(ICellularRadio::NL, pos); printTrace("%s| Update DC Callback Started", this->getName().c_str()); while(end != std::string::npos) { @@ -683,7 +683,7 @@ CellularRadio::CODE CdmaRadio::updateDc(const Json::Value& jArgs, UpdateCb& step stepCb(Json::Value("DC Error: update fails with other reasons")); } return false; - }else if(sLine == RSP_ERROR) { + }else if(sLine == ICellularRadio::RSP_ERROR) { result = ERROR; return false; } @@ -692,7 +692,7 @@ CellularRadio::CODE CdmaRadio::updateDc(const Json::Value& jArgs, UpdateCb& step if(next != std::string::npos) { pos = next; } - end = allData.find(NL, pos); + end = allData.find(ICellularRadio::NL, pos); } printTrace("%s| Update DC Callback Finished", this->getName().c_str()); @@ -703,7 +703,7 @@ CellularRadio::CODE CdmaRadio::updateDc(const Json::Value& jArgs, UpdateCb& step return result; } -CellularRadio::CODE CdmaRadio::updatePrl(const Json::Value& jArgs, UpdateCb& stepCb) { +ICellularRadio::CODE CdmaRadio::updatePrl(const Json::Value& jArgs, UpdateCb& stepCb) { printTrace("%s| Update Preferred Roaming List", getName().c_str()); std::string sCarrier; @@ -713,7 +713,7 @@ CellularRadio::CODE CdmaRadio::updatePrl(const Json::Value& jArgs, UpdateCb& ste return NOT_APPLICABLE; } - CellularRadio::CODE result = FAILURE; + ICellularRadio::CODE result = FAILURE; std::size_t pos = 0; std::size_t end = 0; @@ -724,7 +724,7 @@ CellularRadio::CODE CdmaRadio::updatePrl(const Json::Value& jArgs, UpdateCb& ste return true; } - end = allData.find(NL, pos); + end = allData.find(ICellularRadio::NL, pos); printTrace("%s| Update PRL Callback Started", this->getName().c_str()); while(end != std::string::npos) { @@ -780,7 +780,7 @@ CellularRadio::CODE CdmaRadio::updatePrl(const Json::Value& jArgs, UpdateCb& ste stepCb(Json::Value("PRL Error: update fails with other reasons")); } return false; - } else if(sLine == RSP_ERROR) { + } else if(sLine == ICellularRadio::RSP_ERROR) { result = ERROR; return false; } @@ -789,7 +789,7 @@ CellularRadio::CODE CdmaRadio::updatePrl(const Json::Value& jArgs, UpdateCb& ste if(next != std::string::npos) { pos = next; } - end = allData.find(NL, pos); + end = allData.find(ICellularRadio::NL, pos); } printTrace("%s| Update PRL Callback Finished", this->getName().c_str()); @@ -800,7 +800,7 @@ CellularRadio::CODE CdmaRadio::updatePrl(const Json::Value& jArgs, UpdateCb& ste return result; } -CellularRadio::CODE CdmaRadio::updateFumo(const Json::Value& jArgs, UpdateCb& stepCb) { +ICellularRadio::CODE CdmaRadio::updateFumo(const Json::Value& jArgs, UpdateCb& stepCb) { printTrace("%s| Update Firmware Update Management Object", getName().c_str()); std::string sCarrier; @@ -810,7 +810,7 @@ CellularRadio::CODE CdmaRadio::updateFumo(const Json::Value& jArgs, UpdateCb& st return NOT_APPLICABLE; } - CellularRadio::CODE result = FAILURE; + ICellularRadio::CODE result = FAILURE; std::size_t pos = 0; std::size_t end = 0; @@ -821,7 +821,7 @@ CellularRadio::CODE CdmaRadio::updateFumo(const Json::Value& jArgs, UpdateCb& st return true; } - end = allData.find(NL, pos); + end = allData.find(ICellularRadio::NL, pos); printTrace("%s| Update FUMO Callback Started", this->getName().c_str()); while(end != std::string::npos) { @@ -937,7 +937,7 @@ CellularRadio::CODE CdmaRadio::updateFumo(const Json::Value& jArgs, UpdateCb& st if(stepCb) { stepCb(Json::Value("FUMO Info: reporting of firmware update result to server")); } - } else if(sLine == RSP_ERROR) { + } else if(sLine == ICellularRadio::RSP_ERROR) { result = ERROR; return false; } @@ -946,7 +946,7 @@ CellularRadio::CODE CdmaRadio::updateFumo(const Json::Value& jArgs, UpdateCb& st if(next != std::string::npos) { pos = next; } - end = allData.find(NL, pos); + end = allData.find(ICellularRadio::NL, pos); } printTrace("%s| Update FUMO Callback Finished", this->getName().c_str()); @@ -957,7 +957,7 @@ CellularRadio::CODE CdmaRadio::updateFumo(const Json::Value& jArgs, UpdateCb& st return result; } -CellularRadio::CODE CdmaRadio::resetHfa(const Json::Value& jArgs, UpdateCb& stepCb) { +ICellularRadio::CODE CdmaRadio::resetHfa(const Json::Value& jArgs, UpdateCb& stepCb) { printTrace("%s| HFA Reset (after device reboot HFA will occur)", getName().c_str()); std::string sCarrier; @@ -971,7 +971,7 @@ CellularRadio::CODE CdmaRadio::resetHfa(const Json::Value& jArgs, UpdateCb& step return INVALID_ARGS; } - CellularRadio::CODE result = FAILURE; + ICellularRadio::CODE result = FAILURE; std::size_t pos = 0; std::size_t end = 0; @@ -992,7 +992,7 @@ CellularRadio::CODE CdmaRadio::resetHfa(const Json::Value& jArgs, UpdateCb& step return true; } - end = allData.find(NL, pos); + end = allData.find(ICellularRadio::NL, pos); printTrace("%s| HFA Reset Callback Started", this->getName().c_str()); while(end != std::string::npos) { @@ -1032,10 +1032,10 @@ CellularRadio::CODE CdmaRadio::resetHfa(const Json::Value& jArgs, UpdateCb& step stepCb(Json::Value("RTN Done: Firmware DM - Session Completed Successfully")); } return false; - } else if(sLine == RSP_ERROR) { + } else if(sLine == ICellularRadio::RSP_ERROR) { result = ERROR; return false; - } else if(sLine == RSP_OK) { + } else if(sLine == ICellularRadio::RSP_OK) { //The Device will reboot now, so reset the connection if(stepCb) { stepCb(Json::Value("RTN Info: Resetting Radio")); @@ -1062,7 +1062,7 @@ CellularRadio::CODE CdmaRadio::resetHfa(const Json::Value& jArgs, UpdateCb& step if(next != std::string::npos) { pos = next; } - end = allData.find(NL, pos); + end = allData.find(ICellularRadio::NL, pos); } printTrace("%s| HFA Reset Callback Finished", this->getName().c_str()); @@ -1075,14 +1075,14 @@ CellularRadio::CODE CdmaRadio::resetHfa(const Json::Value& jArgs, UpdateCb& step return result; } -CellularRadio::CODE CdmaRadio::activate(const Json::Value& jArgs, UpdateCb& stepCb) { +ICellularRadio::CODE CdmaRadio::activate(const Json::Value& jArgs, UpdateCb& stepCb) { printTrace("%s| Activation", getName().c_str()); std::string sActivationCmd; std::string sCarrier; getCarrier(sCarrier); - if(sCarrier == VALUE_CARRIER_AERIS) { + if(sCarrier == ICellularRadio::VALUE_CARRIER_AERIS) { if(!jArgs["msid"].isString()) { printError("%s| Arguments missing \"msid\"", getName().c_str()); @@ -1107,7 +1107,7 @@ CellularRadio::CODE CdmaRadio::activate(const Json::Value& jArgs, UpdateCb& step } //Set MDN & MSID - CellularRadio::CODE code; + ICellularRadio::CODE code; code = setMdn(jArgs); if(code != SUCCESS) { return code; @@ -1122,15 +1122,15 @@ CellularRadio::CODE CdmaRadio::activate(const Json::Value& jArgs, UpdateCb& step return SUCCESS; - } else if(sCarrier == VALUE_CARRIER_VERIZON) { + } else if(sCarrier == ICellularRadio::VALUE_CARRIER_VERIZON) { sActivationCmd = "AT+CDV*22899\r"; - } else if(sCarrier == VALUE_CARRIER_USCELLULAR) { + } else if(sCarrier == ICellularRadio::VALUE_CARRIER_USCELLULAR) { sActivationCmd = "AT+CDV*228\r"; } else { return NOT_APPLICABLE; } - CellularRadio::CODE result = FAILURE; + ICellularRadio::CODE result = FAILURE; std::size_t pos = 0; std::size_t end = 0; @@ -1153,7 +1153,7 @@ CellularRadio::CODE CdmaRadio::activate(const Json::Value& jArgs, UpdateCb& step return true; } - end = allData.find(NL, pos); + end = allData.find(ICellularRadio::NL, pos); printTrace("%s| Activation Reset Callback Started", this->getName().c_str()); while(end != std::string::npos) { @@ -1162,7 +1162,7 @@ CellularRadio::CODE CdmaRadio::activate(const Json::Value& jArgs, UpdateCb& step printTrace("%s| Line: [%s]", this->getName().c_str(), sLine.c_str()); - if(sLine == RSP_OK) { + if(sLine == ICellularRadio::RSP_OK) { if(stepCb) { stepCb(Json::Value("Activation Info: Over-the-Air Programming in Process")); } @@ -1194,7 +1194,7 @@ CellularRadio::CODE CdmaRadio::activate(const Json::Value& jArgs, UpdateCb& step } result = ERROR; return false; - } else if(sLine == RSP_ERROR) { + } else if(sLine == ICellularRadio::RSP_ERROR) { result = ERROR; return false; } @@ -1203,7 +1203,7 @@ CellularRadio::CODE CdmaRadio::activate(const Json::Value& jArgs, UpdateCb& step if(next != std::string::npos) { pos = next; } - end = allData.find(NL, pos); + end = allData.find(ICellularRadio::NL, pos); } printTrace("%s| Activation Callback Finished", this->getName().c_str()); @@ -1214,7 +1214,7 @@ CellularRadio::CODE CdmaRadio::activate(const Json::Value& jArgs, UpdateCb& step return result; } -CellularRadio::CODE CdmaRadio::getNetworkStatus(Json::Value& jData) { +ICellularRadio::CODE CdmaRadio::getNetworkStatus(Json::Value& jData) { printTrace("%s| Get Network Status", getName().c_str()); getCommonNetworkStats(jData); @@ -1222,11 +1222,11 @@ CellularRadio::CODE CdmaRadio::getNetworkStatus(Json::Value& jData) { std::string sCarrier; getCarrier(sCarrier); - if(sCarrier == VALUE_CARRIER_SPRINT) { + if(sCarrier == ICellularRadio::VALUE_CARRIER_SPRINT) { Json::Value& jDebug = jData["debug"]; std::string sCmd("AT$DEBUG?"); std::string sResult = MTS::Text::trim(sendCommand(sCmd)); - if (sResult.find(RSP_OK) != std::string::npos) { + if (sResult.find(ICellularRadio::RSP_OK) != std::string::npos) { std::vector<std::string> vCategories = MTS::Text::split(sResult, "\r\n\r\n"); for(size_t i = 0 ; i < vCategories.size(); i++) { std::vector<std::string> vLine = MTS::Text::split(vCategories[i], "\r\n"); diff --git a/src/MTS_IO_CellularRadio.cpp b/src/MTS_IO_CellularRadio.cpp index f89e673..3f0c037 100644 --- a/src/MTS_IO_CellularRadio.cpp +++ b/src/MTS_IO_CellularRadio.cpp @@ -18,125 +18,74 @@ * */ -#include <mts/MTS_IO_CellularRadio.h> +#include "mts/MTS_IO_CellularRadio.h" + +#include <unistd.h> + #include <mts/MTS_IO_MccMncTable.h> #include <mts/MTS_Thread.h> #include <mts/MTS_Timer.h> #include <mts/MTS_Logger.h> #include <mts/MTS_Text.h> -#include <mts/MTS_System.h> -#include <map> -#include <cstring> -#include <sstream> -#include <sys/file.h> -#include <errno.h> -#include <unistd.h> - using namespace MTS::IO; -const char CellularRadio::ETX = 0x03; //Ends socket connection -const char CellularRadio::DLE = 0x10; //Escapes ETX and DLE within Payload -const char CellularRadio::CR = 0x0D; -const char CellularRadio::NL = 0x0A; -const char CellularRadio::CTRL_Z = 0x1A; - -const std::string CellularRadio::RSP_ERROR("ERROR"); -const std::string CellularRadio::RSP_OK("OK"); - - -const std::string CellularRadio::DEFAULT_RADIO_PORT("/dev/modem_at1"); -const std::string CellularRadio::DEFAULT_RADIO_DIR("/var/run/radio/"); -const std::string CellularRadio::VALUE_UNKNOWN("Unknown"); -const std::string CellularRadio::VALUE_UNAVAILABLE("Unavailable"); -const std::string CellularRadio::VALUE_NOT_SUPPORTED("Not Supported"); - -const std::string CellularRadio::VALUE_NOT_REGISTERED("NOT REGISTERED"); -const std::string CellularRadio::VALUE_REGISTERED("REGISTERED"); -const std::string CellularRadio::VALUE_SEARCHING("SEARCHING"); -const std::string CellularRadio::VALUE_DENIED("DENIED"); -const std::string CellularRadio::VALUE_ROAMING("ROAMING"); - -//Static Data -const std::string CellularRadio::KEY_TYPE("type"); //!< GSM or CDMA -const std::string CellularRadio::KEY_CODE("code"); //!< Product Code : H5, H6, C2, EV3, G3 -const std::string CellularRadio::KEY_MODEL("model"); //!< Model : HE910, LE910, CE910, DE910, GE910 -const std::string CellularRadio::KEY_MANUFACTURER("manufacturer"); //!< Manufacturer: Telit -const std::string CellularRadio::KEY_HARDWARE("hardware"); //!< Radio Hardware Version -const std::string CellularRadio::KEY_FIRMWARE("firmware"); //!< Radio Firmware Version -const std::string CellularRadio::KEY_FIRMWARE_BUILD("firmwarebuild"); //!< Radio Firmware Build - -const std::string CellularRadio::KEY_CARRIER("carrier"); //!< Cellular Service Provider (Home Network) -const std::string CellularRadio::VALUE_CARRIER_VERIZON("Verizon"); -const std::string CellularRadio::VALUE_CARRIER_AERIS("Aeris"); -const std::string CellularRadio::VALUE_CARRIER_SPRINT("Sprint"); -const std::string CellularRadio::VALUE_CARRIER_USCELLULAR("U.S. Cellular"); -const std::string CellularRadio::VALUE_CARRIER_ATT("AT&T"); -const std::string CellularRadio::VALUE_CARRIER_TMOBILE("T-Mobile"); - -const std::string CellularRadio::KEY_IMEI("imei"); //!< International Mobile Station Equipment Identity -const std::string CellularRadio::KEY_MEID("meid"); //!< Mobile Equipment Identifier -const std::string CellularRadio::KEY_IMSI("imsi"); //!< International Mobile Subscriber Identity -const std::string CellularRadio::KEY_MSID("msid"); //!< Mobil Station ID / Mobile Identification Number (MSID/MIN) (CDMA-Only) -const std::string CellularRadio::KEY_MDN("mdn"); //!< Mobile Directory Number : Actual phone number dialed to reach radio -const std::string CellularRadio::KEY_ICCID("iccid"); //!< Integrated Circuit Card Identifier -const std::string CellularRadio::KEY_MSL("msl"); //!< Master Subsidy Lock - -//Dynamic Data -const std::string CellularRadio::KEY_ROAMING("roaming"); //!< Indicates whether or not using Home Network -const std::string CellularRadio::KEY_DATETIME("datetime"); //!< Date and Time from tower -const std::string CellularRadio::KEY_SERVICE("service"); //!< Service Connection Type [GPRS, EGPRS, WCDMA, HSDPA, 1xRTT, EVDO] -const std::string CellularRadio::KEY_NETWORK("network"); //!< Cellular Service Provider -const std::string CellularRadio::KEY_NETWORK_REG("netreg"); //!< Network Registration -const std::string CellularRadio::KEY_CID("cid"); //!< Cellular ID (Tower) in HEX -const std::string CellularRadio::KEY_LAC("lac"); //!< Location Area Code in HEX -const std::string CellularRadio::KEY_RAC("rac"); //!< Routing Area Code in HEX -const std::string CellularRadio::KEY_RSSI("rssi"); //!< Signal Strength -const std::string CellularRadio::KEY_RSSIDBM("rssidBm"); //!< Signal Strength in dBm -const std::string CellularRadio::KEY_MCC("mcc"); //!< Country Code -const std::string CellularRadio::KEY_MNC("mnc"); //!< Operator Code -const std::string CellularRadio::KEY_CHANNEL("channel"); //!< ARFCN or UARFCN Assigned Radio Channel -const std::string CellularRadio::KEY_TXPWR("txpwr"); //!< Transmit Power -const std::string CellularRadio::KEY_PSC("psc"); //!< Active Primary Synchronization Code (PSC) -const std::string CellularRadio::KEY_ECIO("ecio"); //!< Active Ec/Io (chip energy per total wideband power in dBm) -const std::string CellularRadio::KEY_RSCP("rscp"); //!< Active RSCP (Received Signal Code Power in dBm) -const std::string CellularRadio::KEY_DRX("drx"); //!< Discontinuous reception cycle length (ms) -const std::string CellularRadio::KEY_MM("mm"); //!< Mobility Management State -const std::string CellularRadio::KEY_RR("rr"); //!< Radio Resource State -const std::string CellularRadio::KEY_NOM("nom"); //!< Network Operator Mode -const std::string CellularRadio::KEY_ABND("abnd"); //!< Active Band -const std::string CellularRadio::KEY_BLER("bler"); //!< Block Error Rate (percentage) -const std::string CellularRadio::KEY_SD("sd"); //!< Service Domain -const std::string CellularRadio::KEY_DEBUG("debug"); //!< Debug Information - -const std::string CellularRadio::KEY_MIP("mipProfile"); //!< Mobile IP Information -const std::string CellularRadio::KEY_MIP_ID("id"); //!< Mobile IP ID -const std::string CellularRadio::KEY_MIP_ENABLED("enabled"); //!< Mobile IP Enabled/Disabled -const std::string CellularRadio::KEY_MIP_NAI("nai"); //!< Network Access Identifier -const std::string CellularRadio::KEY_MIP_HOMEADDRESS("homeAddress"); //!< Home Address -const std::string CellularRadio::KEY_MIP_PRIMARYHA("primaryAddress"); //!< Primary Home Agent -const std::string CellularRadio::KEY_MIP_SECONDARYHA("secondaryAddress"); //!< Secondary Home Agent -const std::string CellularRadio::KEY_MIP_MNAAASPI("mnAaaSpi"); //!< Mobile Node Authentication, Authorization, and Accounting Server Security Parameter Index -const std::string CellularRadio::KEY_MIP_MNHASPI("mnHaSpi"); //!< Mobile Node Home Agent Security Server Parameter Index -const std::string CellularRadio::KEY_MIP_REVTUN("revTun"); //!< Reverse Tunneling Enabled -const std::string CellularRadio::KEY_MIP_MNAAASS("mnAaaSs"); //!< Mobile Node Authentication, Authorization, and Accounting Server Shared Secret -const std::string CellularRadio::KEY_MIP_MNHASS("mnHaSs"); //!< Mobile Node Home Agent Shared Secret - -const std::string CellularRadio::VALUE_TYPE_GSM("GSM"); -const std::string CellularRadio::VALUE_TYPE_LTE("LTE"); -const std::string CellularRadio::VALUE_TYPE_CDMA("CDMA"); - -const std::string CellularRadio::VALUE_SD_NO_SERVICE("NO SERVICE"); -const std::string CellularRadio::VALUE_SD_CS_ONLY("CS ONLY"); -const std::string CellularRadio::VALUE_SD_PS_ONLY("PS ONLY"); -const std::string CellularRadio::VALUE_SD_CSPS("CS+PS"); - -const std::string CellularRadio::VALUE_ABND_GSM_850("GSM 850"); -const std::string CellularRadio::VALUE_ABND_GSM_900("GSM 900"); -const std::string CellularRadio::VALUE_ABND_DCS_1800("DCS 1800"); -const std::string CellularRadio::VALUE_ABND_PCS_1900("PCS 1900"); - -const std::vector<std::string> CellularRadio::DEFAULT_BAIL_STRINGS = { CellularRadio::RSP_OK, CellularRadio::RSP_ERROR }; +namespace { + typedef struct + { + const char *name; + int32_t low; + int32_t high; + } *pNameRangeMap, nameRangeMap; + + const unsigned int NUM_GSM_BANDS = 7; + const unsigned int NUM_WCDMA_BANDS = 6; + const unsigned int NUM_LTE_BANDS = 42; + + // http://niviuk.free.fr/gsm_band.php + const nameRangeMap GSMband[] = + { + {"GSM 450", 259, 293}, {"GSM 480", 306, 340}, + {"GSM 750", 438, 511}, {"GSM 850", 128, 251}, + {"GSM 900 P", 1, 124}, {"GSM 900 E/R", 955, 1023}, + {"GSM DCS 1800/1900", 512, 885}, + + }; + + // http://niviuk.free.fr/umts_band.php + const nameRangeMap WCDMAband[] = + { + {"BAND I", 10592, 10838}, {"BAND II", 9662, 9938}, + {"BAND III", 1162, 1513}, {"BAND IV", 1537, 1738}, + {"BAND V", 4357, 4458}, {"BAND VI", 4387, 4413} + }; + + // 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} + }; +} CellularRadio::CellularRadio(const std::string& sName, const std::string& sRadioPort) : m_sName(sName) @@ -164,7 +113,7 @@ bool CellularRadio::initialize(uint32_t iTimeoutMillis) { } bool bEnabled; - CODE eCode = getEcho(bEnabled); + ICellularRadio::CODE eCode = getEcho(bEnabled); if(eCode == SUCCESS && bEnabled) { printDebug("%s| Disabling 'echo'", m_sName.c_str()); setEcho(false); @@ -174,20 +123,6 @@ bool CellularRadio::initialize(uint32_t iTimeoutMillis) { return true; } -bool CellularRadio::resetRadio(uint32_t iTimeoutMillis) { - - printInfo("%s| Rebooting radio", m_sName.c_str()); - if(sendBasicCommand("AT#REBOOT") == SUCCESS) { - if(iTimeoutMillis > 5000) { - MTS::Thread::sleep(5000); - iTimeoutMillis -= 5000; - } - return resetConnection(iTimeoutMillis); - } - - return false; -} - bool CellularRadio::resetConnection(uint32_t iTimeoutMillis) { //Close Current Connection if(!m_apIo.isNull()) { @@ -238,211 +173,12 @@ const std::string& CellularRadio::getName() const { return m_sName; } - -CellularRadio::CODE CellularRadio::getModel(std::string& sModel) { - printTrace("%s| Get Model", m_sName.c_str()); - //Always returns SUCCESS because the model should be m_sName - sModel = m_sName; - std::string sCmd("ATI4"); - std::string sResult = CellularRadio::sendCommand(m_apIo, sCmd); - if (sResult.find("OK") == std::string::npos) { - printWarning("%s| Unable to get model from radio. Returning [%s]", m_sName.c_str(), m_sName.c_str()); - return SUCCESS; - } else { - sModel = CellularRadio::extractModelFromResult(sResult); - if(sModel.size() == 0) { - printWarning("%s| Unable to get model from radio. Returning [%s]", m_sName.c_str(), m_sName.c_str()); - return SUCCESS; - } - } - - printDebug("%s| Extracted [%s] from [%s] query", m_sName.c_str(), sModel.c_str(), sCmd.c_str()); - if(sModel != m_sName) { - printWarning("%s| Model identified [%s] does not match expected [%s]. Returning [%s]", - m_sName.c_str(), sModel.c_str(), m_sName.c_str(), sModel.c_str()); - } - - return SUCCESS; -} - -CellularRadio::CODE CellularRadio::convertModelToMtsShortCode(const std::string& sModel, std::string& sCode, CellularRadio *radioObject) { - CODE eCode = FAILURE; - - if(sModel.find("HE910-D") == 0) { - sCode = "H5"; - eCode = SUCCESS; - } else if (sModel.find("HE910-EUD") == 0) { - sCode = "H6"; - eCode = SUCCESS; - } else if (sModel.find("LE910-JN1") == 0) { - sCode = "LDC3"; - eCode = SUCCESS; - } else if (sModel.find("LE866A1-JS") == 0) { - sCode = "LSB3"; - eCode = SUCCESS; - } else if (sModel.find("LE910-NAG") == 0) { - sCode = "LAT1"; - eCode = SUCCESS; - } else if (sModel.find("LE910C4-NF") == 0) { - sCode = "L4N1"; - eCode = SUCCESS; - } else if (sModel.find("LE910-NA1") == 0) { - if (NULL == radioObject) { - sCode = VALUE_NOT_SUPPORTED; - eCode = ERROR; - } else { - std::string sValue; - eCode = radioObject->getActiveFirmware(sValue); - if (eCode == SUCCESS) { - sCode = "LNA3"; - } else { - sCode = "LAT3"; - } - } - eCode = SUCCESS; - } else if (sModel.find("LE910-SVG") == 0) { - sCode = "LVW2"; - eCode = SUCCESS; - } else if (sModel.find("LE910C1-NS") == 0) { - sCode = "LSP3"; - eCode = SUCCESS; - } else if (sModel.find("LE910C1-AP") == 0) { - sCode = "LAP3"; - eCode = SUCCESS; - } else if (sModel.find("ME910C1-NA") == 0) { - sCode = "MAT1"; - eCode = SUCCESS; - } else if (sModel.find("ME910C1-NV") == 0) { - sCode = "MVW1"; - eCode = SUCCESS; - } else if (sModel.find("ME910C1-WW") == 0) { - sCode = "MNG2"; - eCode = SUCCESS; - } else if (sModel.find("LE910-EUG") == 0) { - sCode = "LEU1"; - eCode = SUCCESS; - } else if (sModel.find("LE910C4-EU") == 0) { - sCode = "L4E1"; - eCode = SUCCESS; - } else if (sModel.find("LE910-EU1") == 0) { - sCode = "LEU3"; - eCode = SUCCESS; - } else if (sModel.find("GE910") == 0) { - sCode = "G3"; - eCode = SUCCESS; - } else if (sModel.find("CE910") == 0) { - sCode = "C2"; - eCode = SUCCESS; - } else if (sModel.find("DE910") == 0) { - sCode = "EV3"; - eCode = SUCCESS; - } else { - sCode = VALUE_NOT_SUPPORTED; - printError("RADIO| Could not identify MTS short code from model. [%s]", sModel.c_str()); - eCode = ERROR; - } - return eCode; -} - -CellularRadio::CODE CellularRadio::convertServiceDomainToString(SERVICEDOMAIN eSd, std::string& sSd) { - CODE eCode = FAILURE; - switch(eSd) { - case NO_SERVICE: sSd = VALUE_SD_NO_SERVICE; eCode = SUCCESS; break; - case CS_ONLY: sSd = VALUE_SD_CS_ONLY; eCode = SUCCESS; break; - case PS_ONLY: sSd = VALUE_SD_PS_ONLY; eCode = SUCCESS; break; - case CSPS: sSd = VALUE_SD_CSPS; eCode = SUCCESS; break; - default: sSd = VALUE_UNKNOWN; eCode = FAILURE; break; - } - return eCode; -} - -CellularRadio::CODE CellularRadio::convertActiveBandToString(ACTIVEBAND eBand, std::string& sBand) { - CODE eCode = FAILURE; - switch(eBand) { - case GSM_850: sBand = VALUE_ABND_GSM_850; eCode = SUCCESS; break; - case GSM_900: sBand = VALUE_ABND_GSM_900; eCode = SUCCESS; break; - case DCS_1800: sBand = VALUE_ABND_DCS_1800; eCode = SUCCESS; break; - case PCS_1900: sBand = VALUE_ABND_PCS_1900; eCode = SUCCESS; break; - default: sBand = VALUE_UNKNOWN; eCode = FAILURE; break; - } - return eCode; -} - -CellularRadio::CODE CellularRadio::convertModelToType(const std::string& sModel, std::string& sType) { - CODE eCode = FAILURE; - sType = VALUE_NOT_SUPPORTED; - - if(sModel.find("HE910-D") == 0) { - sType = VALUE_TYPE_GSM; - eCode = SUCCESS; - } else if (sModel.find("HE910-EUD") == 0) { - sType = VALUE_TYPE_GSM; - eCode = SUCCESS; - } else if (sModel.find("LE910-JN1") == 0) { - sType = VALUE_TYPE_LTE; - eCode = SUCCESS; - } else if (sModel.find("LE866A1-JS") == 0) { - sType = VALUE_TYPE_LTE; - eCode = SUCCESS; - } else if (sModel.find("LE910-NAG") == 0) { - sType = VALUE_TYPE_LTE; - eCode = SUCCESS; - } else if (sModel.find("LE910C4-NF") == 0) { - sType = VALUE_TYPE_LTE; - eCode = SUCCESS; - } else if (sModel.find("LE910-NA1") == 0) { - sType = VALUE_TYPE_LTE; - eCode = SUCCESS; - } else if (sModel.find("LE910-SVG") == 0) { - sType = VALUE_TYPE_LTE; - eCode = SUCCESS; - } else if (sModel.find("LE910-EUG") == 0) { - sType = VALUE_TYPE_LTE; - eCode = SUCCESS; - } else if (sModel.find("LE910C4-EU") == 0) { - sType = VALUE_TYPE_LTE; - eCode = SUCCESS; - } else if (sModel.find("LE910-EU1") == 0) { - sType = VALUE_TYPE_LTE; - eCode = SUCCESS; - } else if (sModel.find("LE910C1-NS") == 0) { - sType = VALUE_TYPE_LTE; - eCode = SUCCESS; - } else if (sModel.find("LE910C1-AP") == 0) { - sType = VALUE_TYPE_LTE; - eCode = SUCCESS; - } else if (sModel.find("ME910C1-NA") == 0) { - sType = VALUE_TYPE_LTE; - eCode = SUCCESS; - } else if (sModel.find("ME910C1-NV") == 0) { - sType = VALUE_TYPE_LTE; - eCode = SUCCESS; - } else if (sModel.find("ME910C1-WW") == 0) { - sType = VALUE_TYPE_LTE; - eCode = SUCCESS; - } else if (sModel.find("GE910") == 0) { - sType = VALUE_TYPE_GSM; - eCode = SUCCESS; - } else if (sModel.find("CE910") == 0) { - sType = VALUE_TYPE_CDMA; - eCode = SUCCESS; - } else if (sModel.find("DE910") == 0) { - sType = VALUE_TYPE_CDMA; - eCode = SUCCESS; - } else { - sType = VALUE_TYPE_GSM; - eCode = ERROR; - printError("RADIO| Could not identify type from model. [%s]. Assuming [%s]", sModel.c_str(), sType.c_str()); - } - return eCode; -} - -CellularRadio::CODE CellularRadio::getFirmware(std::string& sFirmware) { +ICellularRadio::CODE CellularRadio::getFirmware(std::string& sFirmware) { printTrace("%s| Get Firmware", m_sName.c_str()); - sFirmware = VALUE_NOT_SUPPORTED; + sFirmware = ICellularRadio::VALUE_NOT_SUPPORTED; std::string sCmd("AT+CGMR"); - std::string sResult = CellularRadio::sendCommand(sCmd); - size_t pos = sResult.find(RSP_OK); + std::string sResult = sendCommand(sCmd); + size_t pos = sResult.find(ICellularRadio::RSP_OK); if (pos == std::string::npos) { printWarning("%s| Unable to get firmware from radio using command [%s]", m_sName.c_str(), sCmd.c_str()); return FAILURE; @@ -459,14 +195,14 @@ CellularRadio::CODE CellularRadio::getFirmware(std::string& sFirmware) { return SUCCESS; } -CellularRadio::CODE CellularRadio::getFirmwareBuild(std::string& sFirmwareBuild) { - sFirmwareBuild = VALUE_NOT_SUPPORTED; +ICellularRadio::CODE CellularRadio::getFirmwareBuild(std::string& sFirmwareBuild) { + sFirmwareBuild = ICellularRadio::VALUE_NOT_SUPPORTED; return FAILURE; } -CellularRadio::CODE CellularRadio::getHardware(std::string& sHardware) { +ICellularRadio::CODE CellularRadio::getHardware(std::string& sHardware) { printTrace("%s| Get Hardware", m_sName.c_str()); - sHardware = VALUE_NOT_SUPPORTED; + sHardware = ICellularRadio::VALUE_NOT_SUPPORTED; if(m_sFirmware.size() == 0) { getFirmware(m_sFirmware); @@ -478,12 +214,12 @@ CellularRadio::CODE CellularRadio::getHardware(std::string& sHardware) { return FAILURE; } -CellularRadio::CODE CellularRadio::getManufacturer(std::string& sManufacturer) { +ICellularRadio::CODE CellularRadio::getManufacturer(std::string& sManufacturer) { printTrace("%s| Get Manufacturer", m_sName.c_str()); - sManufacturer = VALUE_NOT_SUPPORTED; + sManufacturer = ICellularRadio::VALUE_NOT_SUPPORTED; std::string sCmd("AT+GMI"); - std::string sResult = CellularRadio::sendCommand(sCmd); - size_t pos = sResult.find(RSP_OK); + std::string sResult = sendCommand(sCmd); + size_t pos = sResult.find(ICellularRadio::RSP_OK); if (pos == std::string::npos) { printWarning("%s| Unable to get manufacturer from radio using command [%s]", m_sName.c_str(), sCmd.c_str()); return FAILURE; @@ -498,12 +234,15 @@ CellularRadio::CODE CellularRadio::getManufacturer(std::string& sManufacturer) { return SUCCESS; } -CellularRadio::CODE CellularRadio::getImei(std::string& sImei) { +ICellularRadio::CODE CellularRadio::getImei(std::string& sImei) { printTrace("%s| Get IMEI", m_sName.c_str()); - sImei = VALUE_NOT_SUPPORTED; + sImei = ICellularRadio::VALUE_NOT_SUPPORTED; + + // AT+CGSN execution can take up to 300ms according to the Quectel datasheet. Setting timeout to 500ms just for sure. std::string sCmd("AT+CGSN"); - std::string sResult = CellularRadio::sendCommand(sCmd); - size_t pos = sResult.find(RSP_OK); + std::string sResult = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, 500); + + size_t pos = sResult.find(ICellularRadio::RSP_OK); if (pos == std::string::npos) { printWarning("%s| Unable to get IMEI from radio using command [%s]", m_sName.c_str(), sCmd.c_str()); return FAILURE; @@ -518,17 +257,20 @@ CellularRadio::CODE CellularRadio::getImei(std::string& sImei) { return SUCCESS; } -CellularRadio::CODE CellularRadio::getMeid(std::string& sMeid) { +ICellularRadio::CODE CellularRadio::getMeid(std::string& sMeid) { printTrace("%s| Get MEID", m_sName.c_str()); return getImei(sMeid); } -CellularRadio::CODE CellularRadio::getImsi(std::string& sImsi) { +ICellularRadio::CODE CellularRadio::getImsi(std::string& sImsi) { printTrace("%s| Get IMSI", m_sName.c_str()); - sImsi = VALUE_NOT_SUPPORTED; + sImsi = ICellularRadio::VALUE_NOT_SUPPORTED; + + // AT+CIMI execution can take up to 300ms according to the Quectel datasheet. Setting timeout to 500ms just for sure. std::string sCmd("AT+CIMI"); - std::string sResult = CellularRadio::sendCommand(sCmd); - size_t pos = sResult.find(RSP_OK); + std::string sResult = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, 500); + + size_t pos = sResult.find(ICellularRadio::RSP_OK); if (pos == std::string::npos) { printWarning("%s| Unable to get IMSI from radio using command [%s]", m_sName.c_str(), sCmd.c_str()); return FAILURE; @@ -543,76 +285,65 @@ CellularRadio::CODE CellularRadio::getImsi(std::string& sImsi) { return SUCCESS; } -CellularRadio::CODE CellularRadio::getSimStatus(std::string& sSimStatus) { +ICellularRadio::CODE CellularRadio::getSimStatus(std::string& sSimStatus) { printTrace("%s| Get SIM Status", getName().c_str()); - sSimStatus = VALUE_UNKNOWN; + sSimStatus = ICellularRadio::VALUE_UNKNOWN; return FAILURE; } -CellularRadio::CODE CellularRadio::getIccid(std::string& sIccid) { - printTrace("%s| Get ICCID", m_sName.c_str()); - sIccid = VALUE_NOT_SUPPORTED; - std::string sCmd("AT#CCID"); - std::string sResult = CellularRadio::sendCommand(sCmd); - size_t end = sResult.find(RSP_OK); - if (end == std::string::npos) { - printWarning("%s| Unable to get ICCID from radio using command [%s]", m_sName.c_str(), sCmd.c_str()); - return FAILURE; - } +ICellularRadio::CODE CellularRadio::getSimStatusSummary(Json::Value& jData) { + bool bIsSimInserted = false; + bool bIsSimLocked = true; + int iAttemptsPin = 0; + int iAttemptsPuk = 0; + std::string sSimLockStatus; + ICellularRadio::CODE retCode; - size_t start = sResult.find("#CCID:"); - if(start != std::string::npos) { - start += sizeof("#CCID:"); - sIccid = MTS::Text::trim(sResult.substr(start, end-start)); - if(sIccid.size() == 0) { - printWarning("%s| Unable to get ICCID from radio using command [%s]", m_sName.c_str(), sCmd.c_str()); - return FAILURE; + do { + retCode = getIsSimInserted(bIsSimInserted); + if (retCode != SUCCESS) { + break; } - } - return SUCCESS; -} -CellularRadio::CODE CellularRadio::getService(std::string& sService) { - printTrace("%s| Get Service", m_sName.c_str()); - sService = VALUE_NOT_SUPPORTED; - std::string sCmd("AT#PSNT?"); - std::string sResult = CellularRadio::sendCommand(sCmd); - size_t end = sResult.find(RSP_OK); - if (end == std::string::npos) { - printWarning("%s| Unable to get Service from radio using command [%s]", m_sName.c_str(), sCmd.c_str()); - return FAILURE; - } + if (!bIsSimInserted) { + // There is no left much to do. Return one field only. + jData[KEY_IS_SIM_INSERTED] = bIsSimInserted; + break; + } - size_t start = sResult.find(","); - if(start != std::string::npos) { - start += 1; //comma - std::string sPsnt = MTS::Text::trim(sResult.substr(start, end-start)); - int32_t iService; - sscanf(sPsnt.c_str(), "%d", &iService); - - switch(iService) { - case 0: sService = "GPRS"; break; - case 1: sService = "EGPRS"; break; - case 2: sService = "WCDMA"; break; - case 3: sService = "HSDPA"; break; - case 4: sService = "LTE"; break; - default: sService = VALUE_UNKNOWN; break; + // The following code assumes that the SIM card is inserted + retCode = getSimLockStatus(sSimLockStatus); + if (retCode != SUCCESS) { + break; } - printDebug("%s| Service ID: [%d][%s]", m_sName.c_str(), iService, sService.c_str()); - } - return SUCCESS; + bIsSimLocked = (sSimLockStatus != "READY"); // SIM PIN, SIM PUK or other values + + retCode = getSimLockAttempts(iAttemptsPin, iAttemptsPuk); + if (retCode != SUCCESS) { + break; + } + + // Everything fetched successfully. Populate the jData object + jData[KEY_IS_SIM_INSERTED] = bIsSimInserted; + jData[KEY_IS_SIM_LOCKED] = bIsSimLocked; + jData[KEY_SIM_LOCK_STATUS] = sSimLockStatus; + jData[KEY_ATTEMPTS_PIN] = iAttemptsPin; + jData[KEY_ATTEMPTS_PUK] = iAttemptsPuk; + } while (false); + + return retCode; } -CellularRadio::CODE CellularRadio::getLac(std::string& sLac) { +ICellularRadio::CODE CellularRadio::getLac(std::string& sLac) { Json::Value jData; printTrace("%s| Get LAC", m_sName.c_str()); - sLac = VALUE_NOT_SUPPORTED; + sLac = ICellularRadio::VALUE_NOT_SUPPORTED; if(getNetworkStatus(jData) == SUCCESS) { - if(jData.isMember(KEY_LAC)) { - sLac = jData[KEY_LAC].asString(); + if(jData.isMember(ICellularRadio::KEY_LAC)) { + sLac = jData[ICellularRadio::KEY_LAC].asString(); return SUCCESS; } } @@ -620,12 +351,15 @@ CellularRadio::CODE CellularRadio::getLac(std::string& sLac) { return FAILURE; } -CellularRadio::CODE CellularRadio::getMdn(std::string& sMdn) { +ICellularRadio::CODE CellularRadio::getMdn(std::string& sMdn) { printTrace("%s| Get MDN", m_sName.c_str()); - sMdn = VALUE_NOT_SUPPORTED; + sMdn = ICellularRadio::VALUE_NOT_SUPPORTED; + + // AT+CNUM execution can take up to 300ms according to the Quectel datasheet. Setting timeout to 500ms just for sure. std::string sCmd("AT+CNUM"); - std::string sResult = CellularRadio::sendCommand(sCmd); - size_t end = sResult.find(RSP_OK); + std::string sResult = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, 500); + + size_t end = sResult.find(ICellularRadio::RSP_OK); if (end == std::string::npos) { printWarning("%s| Unable to get MDN from radio using command [%s]", m_sName.c_str(), sCmd.c_str()); return FAILURE; @@ -651,7 +385,7 @@ CellularRadio::CODE CellularRadio::getMdn(std::string& sMdn) { return SUCCESS; } -CellularRadio::CODE CellularRadio::getMsid(std::string& sMsid) { +ICellularRadio::CODE CellularRadio::getMsid(std::string& sMsid) { printTrace("%s| Get MSID", m_sName.c_str()); sMsid = ""; @@ -667,25 +401,25 @@ CellularRadio::CODE CellularRadio::getMsid(std::string& sMsid) { return FAILURE; } -CellularRadio::CODE CellularRadio::getType(std::string& sType) { +ICellularRadio::CODE CellularRadio::getType(std::string& sType) { printTrace("%s| Get Type", m_sName.c_str()); - sType = VALUE_NOT_SUPPORTED; + sType = ICellularRadio::VALUE_NOT_SUPPORTED; return FAILURE; } -CellularRadio::CODE CellularRadio::getCarrier(std::string& sCarrier) { +ICellularRadio::CODE CellularRadio::getCarrier(std::string& sCarrier) { printTrace("%s| Get Carrier", m_sName.c_str()); if(m_sCarrier == "") { Json::Value jData; if(getNetworkStatus(jData) == SUCCESS) { - if(jData.isMember(KEY_MCC) && jData.isMember(KEY_MNC)) { - std::string sMcc = jData[KEY_MCC].asString(); - std::string sMnc = jData[KEY_MNC].asString(); + if(jData.isMember(ICellularRadio::KEY_MCC) && jData.isMember(ICellularRadio::KEY_MNC)) { + std::string sMcc = jData[ICellularRadio::KEY_MCC].asString(); + std::string sMnc = jData[ICellularRadio::KEY_MNC].asString(); Json::Value jLookup = MccMncTable::getInstance()->lookup(sMcc, sMnc); printTrace("%s| MCC-MNC Lookup: [%s][%s][%s]", m_sName.c_str(), sMcc.c_str(), sMnc.c_str(), jLookup.toStyledString().c_str()); - if(jLookup.isMember(KEY_CARRIER)) { - m_sCarrier = jLookup[KEY_CARRIER].asString(); + if(jLookup.isMember(ICellularRadio::KEY_CARRIER)) { + m_sCarrier = jLookup[ICellularRadio::KEY_CARRIER].asString(); } else { printWarning("%s| MCC-MNC Lookup did not contain carrier", m_sName.c_str()); return FAILURE; @@ -703,22 +437,22 @@ CellularRadio::CODE CellularRadio::getCarrier(std::string& sCarrier) { return SUCCESS; } -CellularRadio::CODE CellularRadio::getTower(std::string& sTower) { +ICellularRadio::CODE CellularRadio::getTower(std::string& sTower) { Json::Value jData; printTrace("%s| Get Tower", m_sName.c_str()); - sTower = VALUE_NOT_SUPPORTED; + sTower = ICellularRadio::VALUE_NOT_SUPPORTED; if(getNetworkStatus(jData) == SUCCESS) { - if(jData.isMember(KEY_CID)) { - sTower = jData[KEY_CID].asString(); + if(jData.isMember(ICellularRadio::KEY_CID)) { + sTower = jData[ICellularRadio::KEY_CID].asString(); return SUCCESS; } } return FAILURE; } -CellularRadio::CODE CellularRadio::getTime(std::string& sDate, std::string& sTime, std::string& sTimeZone) { +ICellularRadio::CODE CellularRadio::getTime(std::string& sDate, std::string& sTime, std::string& sTimeZone) { Json::Value jData; printTrace("%s| Get Time", m_sName.c_str()); @@ -727,8 +461,8 @@ CellularRadio::CODE CellularRadio::getTime(std::string& sDate, std::string& sTim sTimeZone = ""; std::string sCmd("AT+CCLK?"); - std::string sResult = CellularRadio::sendCommand(sCmd); - size_t end = sResult.find(RSP_OK); + std::string sResult = sendCommand(sCmd); + size_t end = sResult.find(ICellularRadio::RSP_OK); if (end == std::string::npos) { printWarning("%s| Unable to get Time from radio using command [%s]", m_sName.c_str(), sCmd.c_str()); return FAILURE; @@ -793,7 +527,7 @@ CellularRadio::CODE CellularRadio::getTime(std::string& sDate, std::string& sTim return FAILURE; } -CellularRadio::CODE CellularRadio::getRoaming(bool& bRoaming) { +ICellularRadio::CODE CellularRadio::getRoaming(bool& bRoaming) { Json::Value jData; printTrace("%s| Get Roaming", m_sName.c_str()); @@ -807,25 +541,13 @@ CellularRadio::CODE CellularRadio::getRoaming(bool& bRoaming) { return FAILURE; } -CellularRadio::CODE CellularRadio::getNetwork(std::string& sNetwork) { - Json::Value jData; - - printTrace("%s| Get Network", m_sName.c_str()); - sNetwork = VALUE_NOT_SUPPORTED; - - if(getNetworkStatus(jData) == SUCCESS) { - if(jData.isMember(KEY_NETWORK)) { - sNetwork = jData[KEY_NETWORK].asString(); - return SUCCESS; - } - } - return FAILURE; -} - -CellularRadio::CODE CellularRadio::getSignalStrength(int32_t& rssi) { +ICellularRadio::CODE CellularRadio::getSignalStrength(int32_t& rssi) { printTrace("%s| Get Signal Strength", m_sName.c_str()); + + // AT+CSQ execution can take up to 300ms according to the Quectel datasheet. Setting timeout to 500ms just for sure. std::string sCmd("AT+CSQ"); - std::string sResult = sendCommand(sCmd); + std::string sResult = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, 500); + if (sResult.find("+CSQ: ") == std::string::npos) { printDebug("%s| Signal Strength command returned unexpected response: [%s]", m_sName.c_str(), sResult.c_str()); return FAILURE; @@ -845,53 +567,12 @@ CellularRadio::CODE CellularRadio::getSignalStrength(int32_t& rssi) { return SUCCESS; } -CellularRadio::CODE CellularRadio::getModemLocation(std::string& sLocation) { +ICellularRadio::CODE CellularRadio::getModemLocation(std::string&) { printTrace("%s|CellularRadio getModemLocation - not supported", m_sName.c_str()); return FAILURE; } -CellularRadio::CODE CellularRadio::convertSignalStrengthTodBm(const int32_t& iRssi, int32_t& iDbm) { - - //Telit Conversion - if(iRssi < 0 || iRssi == 99) { - return FAILURE; - } - - if(iRssi == 0) { - iDbm = -113; - } else if(iRssi == 1) { - iDbm = -111; - } else if(iRssi <= 30) { - //28 steps between 2 and 30 - //54 dbm between 53 and 109 - float stepSize = 54.0 / 28.0; - iDbm = -109 + (int)(stepSize * (iRssi-2)); - } else { - iDbm = -51; - } - - return SUCCESS; -} - -CellularRadio::CODE CellularRadio::convertdBmToSignalStrength(const int32_t& iDBm, int32_t& iRssi) { - //Telit Conversion - if(iDBm <= -113) { - iRssi = 0; - } else if(iDBm <= -111) { - iRssi = 1; - } else if(iDBm <= -53) { - //54 dbm between -109 and -53 - //28 steps between 2 and 30 - float stepSize = 28.0/54.0; - iRssi = ((iDBm + 109)*stepSize) + 2; - } else { - iRssi = 31; - } - - return SUCCESS; -} - -CellularRadio::CODE CellularRadio::getEcho(bool& bEnabled) { +ICellularRadio::CODE CellularRadio::getEcho(bool& bEnabled) { printTrace("%s| Echo Test", m_sName.c_str()); std::string sResult = sendCommand("AT"); if(sResult.size() == 0) { @@ -907,8 +588,8 @@ CellularRadio::CODE CellularRadio::getEcho(bool& bEnabled) { return SUCCESS; } -CellularRadio::CODE CellularRadio::setEcho(bool bEnabled) { - CODE eCode = FAILURE; +ICellularRadio::CODE CellularRadio::setEcho(bool bEnabled) { + ICellularRadio::CODE eCode = FAILURE; if(bEnabled) { eCode = sendBasicCommand("ATE1"); m_bEchoEnabled = (eCode == SUCCESS ) ? true : m_bEchoEnabled; @@ -920,7 +601,7 @@ CellularRadio::CODE CellularRadio::setEcho(bool bEnabled) { return eCode; } -CellularRadio::CODE CellularRadio::getStaticInformation(Json::Value& jData) { +ICellularRadio::CODE CellularRadio::getStaticInformation(Json::Value& jData) { printTrace("%s| Get Static Information", m_sName.c_str()); printTrace("%s| Static Information:\n%s\n", m_sName.c_str(), jData.toStyledString().c_str()); @@ -928,268 +609,14 @@ CellularRadio::CODE CellularRadio::getStaticInformation(Json::Value& jData) { return FAILURE; } -/* AT#RFSTS - NETWORK STATUS - - (GSM network) - #RFSTS:<PLMN>,<ARFCN>,<RSSI>,<LAC>,<RAC>,<TXPWR>,<MM>,<RR>,<NOM>,<CID>,<IMSI>,<NetNameAsc>,<SD>,<ABND> - Where: - <PLMN> - Country code and operator code(MCC, MNC) - <ARFCN> - GSM Assigned Radio Channel - <RSSI> - Received Signal Strength Indication - <LAC> - Localization Area Code - <RAC> - Routing Area Code - <TXPWR> - Tx Power - <MM> - Mobility Management state - <RR> - Radio Resource state - <NOM> - Network Operator Mode - <CID> - Cell ID - <IMSI> - International Mobile Subscriber Identity - <NetNameAsc> - Operator name - <SD> - Service Domain - 0 - No Service - 1 - CS only - 2 - PS only - 3 - CS+PS - <ABND> - Active Band - 1 - GSM 850 - 2 - GSM 900 - 3 - DCS 1800 - 4 - PCS 1900 - - - (WCDMA network) - #RFSTS: - <PLMN>,<UARFCN>,<PSC>,<Ec/Io>,<RSCP>, RSSI>,<LAC>,<RAC>,<TXPWR>,<DRX>,<MM>,<RRC>,<NOM>,<BLER>,<CID>,<IMSI>, - <NetNameAsc>,<SD>,<nAST>[,<nUARFCN><nPSC>,<nEc/Io>] - Where: - <PLMN> - Country code and operator code(MCC, MNC) - <UARFCN> - UMTS Assigned Radio Channel - <PSC> - Active PSC(Primary Synchronization Code) - <Ec/Io> - Active Ec/Io(chip energy per total wideband power in dBm) - <RSCP> - Active RSCP (Received Signal Code Power in dBm) - <RSSI> - Received Signal Strength Indication - <LAC> - Localization Area Code - <RAC> - Routing Area Code - <TXPWR> - Tx Power - <DRX> - Discontinuous reception cycle Length (cycle length in ms) - <MM> - Mobility Management state - <RR> - Radio Resource state - <NOM> - Network Operator Mode - <BLER> - Block Error Rate (e.g., 005 means 0.5 %) - <CID> - Cell ID - <IMSI> - International Mobile Station ID - <NetNameAsc> - Operator name - <SD> - Service Domain (see above) - <nAST> - Number of Active Set (Maximum 6) - <nUARFCN> UARFCN of n th active set - <nPSC> PSC of n th active set - <nEc/Io > Ec/Io of n th active Set - - (LTE Network) - #RFSTS: - <PLMN> - - <EARFCN> - - <RSRP> - - <RSSI> - - <RSRQ> - - <TAC> - - [<TXPWR>] - - <DRX> - - <MM> - - <RRC> - - <CID> - - <IMSI> - - [<NetNameAsc>] - - <SD> - - <ABND> - -*/ -CellularRadio::CODE CellularRadio::getNetworkStatus(Json::Value& jData) { - int32_t iValue; - std::string sValue; - const uint32_t GSM_NETWORK_FORMAT = 14; - const uint32_t WCDMA_NETWORK_FORMAT = 19; - const uint32_t LTE_NETWORK_FORMAT = 16; - - printTrace("%s| Get Network Status", m_sName.c_str()); - - //Always get common network stats because this should never fail - //This way the basic stats are always returned even if AT#RFSTS fails below - getCommonNetworkStats(jData); - - std::string sCmd; - std::string sResult; - // LE910 radios have a bug where issuing AT#RFSTS with a locked SIM - // will cause the radio to stop responding until a radio power cycle - // Telit Support Portal Case #5069697 - // LE910C1-NS is an LE910, so we stop the scan after the 0. - if (m_sName.find("LE910") != std::string::npos) { - sCmd = "AT+CPIN?"; - sResult = sendCommand(sCmd); - if (sResult.find("+CPIN:") == std::string::npos) { - printDebug("%s| AT+CPIN? returned unexpected response: [%s][%s]", m_sName.c_str(), sCmd.c_str(), sResult.c_str()); - printTrace("%s| Network Status:\n%s\n", m_sName.c_str(), jData.toStyledString().c_str()); - return SUCCESS; //return SUCCESS because getCommonNetworkStats() succeeded at top of this function - } - if (sResult.find("SIM PIN") != std::string::npos) { - printError("%s| The SIM is locked and must first be unlocked", m_sName.c_str()); - printTrace("%s| Network Status:\n%s\n", m_sName.c_str(), jData.toStyledString().c_str()); - return SUCCESS; //return SUCCESS because getCommonNetworkStats() succeeded at top of this function - } - } - - sCmd = "AT#RFSTS"; - sResult = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, 200); - if (sResult.find("#RFSTS:") == std::string::npos) { - //On LTE radios without signal, this case will run because AT#RFSTS just returns "OK" - printDebug("%s| Network Status command returned unexpected response: [%s][%s]", m_sName.c_str(), sCmd.c_str(), sResult.c_str()); - printTrace("%s| Network Status:\n%s\n", m_sName.c_str(), jData.toStyledString().c_str()); - return SUCCESS; //return SUCCESS because getCommonNetworkStats() succeeded at top of this function - } - - size_t start = sResult.find(":") + 1; //Position right after "#RFSTS:" - std::vector<std::string> vParts = MTS::Text::split(MTS::Text::trim(sResult.substr(start)), ","); - - if (vParts.size() < 3) { - printDebug("%s| Network Status command reponse is an unknown format: [%s][%s]", m_sName.c_str(), sCmd.c_str(), sResult.c_str()); - printTrace("%s| Network Status:\n%s\n", m_sName.c_str(), jData.toStyledString().c_str()); - return SUCCESS; //return SUCCESS because getCommonNetworkStats() succeeded at top of this function - } else { - //Country Code and Operator Code - std::vector<std::string> vPLMN = MTS::Text::split(vParts[0], ' '); - if(vPLMN.size() == 2) { - jData[KEY_MCC] = MTS::Text::strip(vPLMN[0], '"'); - jData[KEY_MNC] = MTS::Text::strip(vPLMN[1], '"'); - } - - jData[KEY_CHANNEL] = vParts[1]; - } - - if (vParts.size() == GSM_NETWORK_FORMAT ) { - //Parse as GSM Network Format - jData[KEY_RSSIDBM] = vParts[2]; - jData[KEY_LAC] = vParts[3]; - jData[KEY_RAC] = vParts[4]; - jData[KEY_TXPWR] = vParts[5]; - jData[KEY_MM] = vParts[6]; - jData[KEY_RR] = vParts[7]; - jData[KEY_NOM] = vParts[8]; - jData[KEY_CID] = vParts[9]; - jData[KEY_IMSI] = MTS::Text::strip(vParts[10], '"'); - jData[KEY_NETWORK] = MTS::Text::strip(vParts[11], '"'); - if(MTS::Text::parse(iValue, vParts[12]) && convertServiceDomainToString((SERVICEDOMAIN)iValue, sValue) == SUCCESS) { - jData[KEY_SD] = sValue; - } - if(MTS::Text::parse(iValue, vParts[13]) && convertActiveBandToString((ACTIVEBAND)iValue, sValue) == SUCCESS) { - jData[KEY_ABND] = sValue; - } - // IN003567 ME910C1 radios have some odd behavior with regards to WCDMA. The ordering of the fields from #RFSTS are - // the same as LTE up to the 16th field (for ME901C1-WW anyway). Drop into LTE parsing for ME910C1-WW. - } else if((vParts.size() >= WCDMA_NETWORK_FORMAT) && (m_sName.find("ME910C1-WW") == std::string::npos)) { - Json::Value jDebug; - - //Parse as WCDMA Network Format - - jDebug[KEY_PSC] = vParts[2]; - jDebug[KEY_ECIO] = vParts[3]; - jDebug[KEY_RSCP] = vParts[4]; - - jData[KEY_RSSIDBM] = vParts[5]; - jData[KEY_LAC] = vParts[6]; - jData[KEY_RAC] = vParts[7]; - - jDebug[KEY_TXPWR] = vParts[8]; - jDebug[KEY_DRX] = vParts[9]; - jDebug[KEY_MM] = vParts[10]; - jDebug[KEY_RR] = vParts[11]; - jDebug[KEY_NOM] = vParts[12]; - - if(vParts[13].size() != 0) { - jDebug[KEY_BLER] = vParts[13]; - } else { - jDebug[KEY_BLER] = "000"; - } - - jData[KEY_CID] = vParts[14]; - jData[KEY_IMSI] = MTS::Text::strip(vParts[15], '"'); - jData[KEY_NETWORK] = MTS::Text::strip(vParts[16], '"'); - - // Get the radio band given the channel (UARFCN) - RadioBandMap radioBandMap(vParts[1], CellularRadio::VALUE_TYPE_CDMA); - jData[KEY_ABND] = radioBandMap.getRadioBandName(); - - if(MTS::Text::parse(iValue, vParts[17]) && convertServiceDomainToString((SERVICEDOMAIN)iValue, sValue) == SUCCESS) { - jDebug[KEY_SD] = sValue; - } - //Ignoring Active Set Values - // <nAST> - Number of Active Set (Maximum 6) - // <nUARFCN> - UARFCN of n th active set - // <nPSC> - PSC of n th active set - // <nEc/Io > - Ec/Io of n th active Set - - jData[KEY_DEBUG] = jDebug; - } else if(vParts.size() >= LTE_NETWORK_FORMAT) { - Json::Value jDebug; - - //Parse as LTE Network Format - - // - // MD: It is noticed that LTE Network format may vary depending on the firmware version: - // - // <PLMN>,<EARFCN>,<RSRP>,<RSSI>,<RSRQ>,<TAC>,[<TXPWR>],<DRX>,<MM>,<RRC>,<CID>,<IMSI>,[<NetNameAsc>],<SD>,<ABND>,<SINR> - // Ex 1: #RFSTS: "310 260",2300,-98,-63,-14,AA06,,128,19,0,0501D02,"310260754792598","T-Mobile",3,4,197 - // - // <PLMN>,<EARFCN>,<RSRP>,<RSSI>,<RSRQ>,<TAC>,<RAC>,[<TXPWR>],<DRX>,<MM>,<RRC>,<CID>,<IMSI>,[<NetNameAsc>],<SD>,<ABND> - // Ex 2: #RFSTS:"310 410",5780,-105,-73,-14,4603,255,,128,19,0,0000098,"310410536498694","AT&T",3,17 - // #RFSTS:"311 480",1150,-96,-66,-9.0,bf35,FF,0,0,19,1,"2ED1B0E","311480148817753","Verizon",2,2,720000,10800 - // #RFSTS:"310 410",2175,-120,-89,-17.5,4612,FF,0,0,19,1,"4E5E916","310410807276607","AT&T",3,4 - // - // Additional <RAC> parameter in the second example shifts the rest of the parameters. Here we are trying to figure out - // which format is currently produced based on <NetNameAsc> field position which always has double quotation marks. - // - if (vParts[13].find("\"") != std::string::npos) { - // parse the RAC and then remove it from the vector - jData[KEY_RAC] = vParts[6]; - vParts.erase(vParts.begin() + 6); - } - - jDebug["rsrp"] = vParts[2]; - jDebug[KEY_RSSIDBM] = vParts[3]; - jDebug["rsrq"] = vParts[4]; - - jData["tac"] = vParts[5]; - jDebug[KEY_TXPWR] = vParts[6]; - jData[KEY_DRX] = vParts[7]; - jDebug[KEY_MM] = vParts[8]; - jDebug["rrc"] = vParts[9]; - jData[KEY_CID] = MTS::Text::strip(vParts[10], '"'); - jData[KEY_IMSI] = MTS::Text::strip(vParts[11], '"'); - jData[KEY_NETWORK] = MTS::Text::strip(vParts[12], '"'); - - // Get the radio band given the channel (EARFCN) - RadioBandMap radioBandMap(vParts[1], CellularRadio::VALUE_TYPE_LTE); - jData[KEY_ABND] = radioBandMap.getRadioBandName(); - - jData[KEY_LAC] = queryLteLac(); - - if(MTS::Text::parse(iValue, vParts[13]) && convertServiceDomainToString((SERVICEDOMAIN)iValue, sValue) == SUCCESS) { - jDebug[KEY_SD] = sValue; - } - - jData[KEY_DEBUG] = jDebug; - } - - printTrace("%s| Network Status:\n%s\n", m_sName.c_str(), jData.toStyledString().c_str()); - return SUCCESS; -} - -// Get the LAC for the LTE radio that's not in the #RFSTS response +// Get the LAC for the LTE radio that's not in the #RFSTS or +QENG response std::string CellularRadio::queryLteLac() { std::string CGREGstring; std::string originalCGREG; std::string result; CGREGstring = queryCGREGstring(); - if (CGREGstring == RSP_ERROR) { + if (CGREGstring == ICellularRadio::RSP_ERROR) { originalCGREG = "0"; } else { originalCGREG = CGREGstring.at(CGREGstring.find(",") - 1); //Position right before first comma ("+CGREG: 0,1") @@ -1199,13 +626,13 @@ std::string CellularRadio::queryLteLac() { setCGREG("2"); CGREGstring = queryCGREGstring(); - if (CGREGstring == RSP_ERROR) { - result = CellularRadio::VALUE_UNKNOWN; + if (CGREGstring == ICellularRadio::RSP_ERROR) { + result = ICellularRadio::VALUE_UNKNOWN; } else { - size_t start = CGREGstring.find(":") + 1; //Position right after "#RFSTS:" + size_t start = CGREGstring.find(":") + 1; //Position right after "+CGREG:" std::vector<std::string> vParts = MTS::Text::split(MTS::Text::trim(CGREGstring.substr(start)), ","); if(vParts.size() < 3) { - result = CellularRadio::VALUE_UNAVAILABLE; + result = ICellularRadio::VALUE_UNAVAILABLE; } else { result = MTS::Text::strip(vParts[2], '"'); } @@ -1220,7 +647,7 @@ void CellularRadio::setCGREG(std::string value) { std::string sCmd("AT+CGREG=" + value); std::string cmdResult(sendCommand(sCmd)); if (cmdResult.find("OK") == std::string::npos) { - printDebug("%s| AT#CGREG=%s returned unexpected response: [%s][%s]", m_sName.c_str(), value.c_str(), sCmd.c_str(), cmdResult.c_str()); + printDebug("%s| AT+CGREG=%s returned unexpected response: [%s][%s]", m_sName.c_str(), value.c_str(), sCmd.c_str(), cmdResult.c_str()); } } @@ -1228,8 +655,8 @@ std::string CellularRadio::queryCGREGstring() { std::string sCmd("AT+CGREG?"); std::string cmdResult(sendCommand(sCmd)); if (cmdResult.find("+CGREG:") == std::string::npos) { - printDebug("%s| AT#CGREG? returned unexpected response: [%s][%s]", m_sName.c_str(), sCmd.c_str(), cmdResult.c_str()); - return RSP_ERROR; + printDebug("%s| AT+CGREG? returned unexpected response: [%s][%s]", m_sName.c_str(), sCmd.c_str(), cmdResult.c_str()); + return ICellularRadio::RSP_ERROR; } return cmdResult; } @@ -1238,51 +665,78 @@ void CellularRadio::getCommonNetworkStats(Json::Value& jData) { bool bRoaming = false; if(getRoaming(bRoaming) == SUCCESS) { - jData[KEY_ROAMING] = bRoaming; + jData[ICellularRadio::KEY_ROAMING] = bRoaming; } int32_t iRssi; if(getSignalStrength(iRssi) == SUCCESS) { - jData[KEY_RSSI] = iRssi; + jData[ICellularRadio::KEY_RSSI] = iRssi; int32_t dBm; - if(!jData.isMember(KEY_RSSIDBM) && convertSignalStrengthTodBm(iRssi, dBm) == SUCCESS) { + if(!jData.isMember(ICellularRadio::KEY_RSSIDBM) && convertSignalStrengthTodBm(iRssi, dBm) == SUCCESS) { //Add RSSI in dBm format - jData[KEY_RSSIDBM] = MTS::Text::format(dBm); + jData[ICellularRadio::KEY_RSSIDBM] = MTS::Text::format(dBm); } } std::string sService; if(getService(sService) == SUCCESS) { - jData[KEY_SERVICE] = sService; + jData[ICellularRadio::KEY_SERVICE] = sService; } std::string sDate, sTime, sTimeZone; if(getTime(sDate, sTime, sTimeZone) == SUCCESS) { - jData[KEY_DATETIME] = sDate + " " + sTime + " GMT" + sTimeZone; + jData[ICellularRadio::KEY_DATETIME] = sDate + " " + sTime + " GMT" + sTimeZone; } std::string sNetworkReg; - CellularRadio::REGISTRATION eReg; + REGISTRATION eReg; if (getRegistration(eReg) == SUCCESS) { if (convertRegistrationToString(eReg, sNetworkReg) == SUCCESS) { - jData[CellularRadio::KEY_NETWORK_REG] = sNetworkReg; + jData[ICellularRadio::KEY_NETWORK_REG] = sNetworkReg; } } } +ICellularRadio::CODE CellularRadio::getSimLockStatus(std::string& sData) +{ + printTrace("%s| Get SIM lock status", m_sName.c_str()); + + // SIM card may introduce a delay to AT+CPIN? execution. Setting timeout to 1s as set in PPP chat patches. + std::string sCmd("AT+CPIN?"); + std::string sResult = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, 1000); + + const std::string sPrefix = "+CPIN: "; + size_t start = sResult.find(sPrefix); + size_t end = sResult.rfind(ICellularRadio::RSP_OK); + + if (start == std::string::npos || end == std::string::npos) { + printWarning("%s| Unable to get SIM lock status from radio using command [%s]", m_sName.c_str(), sCmd.c_str()); + return FAILURE; + } + + start += sPrefix.size(); + sData = MTS::Text::trim(sResult.substr(start, end-start)); + if(sData.size() == 0) { + printWarning("%s| Unable to get SIM lock status from radio using command [%s]", m_sName.c_str(), sCmd.c_str()); + return FAILURE; + } + + return SUCCESS; +} + void CellularRadio::initMipProfile(Json::Value& jData) { - jData[KEY_MIP_ID] = 0; - jData[KEY_MIP_ENABLED] = false; - jData[KEY_MIP_NAI] = VALUE_UNKNOWN; - jData[KEY_MIP_HOMEADDRESS] = VALUE_UNKNOWN; - jData[KEY_MIP_PRIMARYHA] = VALUE_UNKNOWN; - jData[KEY_MIP_SECONDARYHA] = VALUE_UNKNOWN; - jData[KEY_MIP_MNAAASPI] = VALUE_UNKNOWN; - jData[KEY_MIP_MNHASPI] = VALUE_UNKNOWN; - jData[KEY_MIP_MNAAASS] = false; - jData[KEY_MIP_MNHASS] = false; -} - -CellularRadio::CODE CellularRadio::getRegistration(REGISTRATION& eRegistration) { + jData[ICellularRadio::KEY_MIP_ID] = 0; + jData[ICellularRadio::KEY_MIP_ENABLED] = false; + jData[ICellularRadio::KEY_MIP_NAI] = ICellularRadio::VALUE_UNKNOWN; + jData[ICellularRadio::KEY_MIP_HOMEADDRESS] = ICellularRadio::VALUE_UNKNOWN; + jData[ICellularRadio::KEY_MIP_PRIMARYHA] = ICellularRadio::VALUE_UNKNOWN; + jData[ICellularRadio::KEY_MIP_SECONDARYHA] = ICellularRadio::VALUE_UNKNOWN; + jData[ICellularRadio::KEY_MIP_MNAAASPI] = ICellularRadio::VALUE_UNKNOWN; + jData[ICellularRadio::KEY_MIP_MNHASPI] = ICellularRadio::VALUE_UNKNOWN; + jData[ICellularRadio::KEY_MIP_MNAAASS] = false; + jData[ICellularRadio::KEY_MIP_MNHASS] = false; +} + +ICellularRadio::CODE CellularRadio::getRegistration(REGISTRATION& eRegistration) { std::string sCmd; std::string sResp; @@ -1316,168 +770,167 @@ CellularRadio::CODE CellularRadio::getRegistration(REGISTRATION& eRegistration) return SUCCESS; } -CellularRadio::CODE CellularRadio::convertRegistrationToString(REGISTRATION eRegistration, std::string& sRegistration) { +ICellularRadio::CODE CellularRadio::convertRegistrationToString(REGISTRATION eRegistration, std::string& sRegistration) { - CODE eCode = FAILURE; + ICellularRadio::CODE eCode = FAILURE; switch (eRegistration) { - case NOT_REGISTERED: sRegistration = VALUE_NOT_REGISTERED; eCode = SUCCESS; break; - case REGISTERED: sRegistration = VALUE_REGISTERED; eCode = SUCCESS; break; - case SEARCHING: sRegistration = VALUE_SEARCHING; eCode = SUCCESS; break; - case DENIED: sRegistration = VALUE_DENIED; eCode = SUCCESS; break; - case UNKNOWN: sRegistration = VALUE_UNKNOWN; eCode = SUCCESS; break; - case ROAMING: sRegistration = VALUE_ROAMING; eCode = SUCCESS; break; + case NOT_REGISTERED: sRegistration = ICellularRadio::VALUE_NOT_REGISTERED; eCode = SUCCESS; break; + case REGISTERED: sRegistration = ICellularRadio::VALUE_REGISTERED; eCode = SUCCESS; break; + case SEARCHING: sRegistration = ICellularRadio::VALUE_SEARCHING; eCode = SUCCESS; break; + case DENIED: sRegistration = ICellularRadio::VALUE_DENIED; eCode = SUCCESS; break; + case UNKNOWN: sRegistration = ICellularRadio::VALUE_UNKNOWN; eCode = SUCCESS; break; + case ROAMING: sRegistration = ICellularRadio::VALUE_ROAMING; eCode = SUCCESS; break; } return eCode; } -CellularRadio::CODE CellularRadio::validateMsl(const Json::Value& jArgs) { - printTrace("%s| Validate MSL", m_sName.c_str()); - - return NOT_APPLICABLE; -} - -CellularRadio::CODE CellularRadio::setMdn(const Json::Value& jArgs) { - printTrace("%s| Set MDN", m_sName.c_str()); +ICellularRadio::CODE CellularRadio::unlockSimCard(const Json::Value& jArgs) { + printTrace("%s| Unlock the SIM card using PIN code", m_sName.c_str()); - if(!jArgs["mdn"].isString()) { + if(!jArgs["pin"].isString()) { return INVALID_ARGS; } - std::string sCmd("AT#SNUM=1,\""); - sCmd += jArgs["mdn"].asString() + "\""; + std::string sCmd = "AT+CPIN=" + jArgs["pin"].asString(); + std::string sResult = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, 5000); - std::string sResult = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, 1000); - size_t end = sResult.find(RSP_OK); - if (end == std::string::npos) { - printWarning("%s| Unable to set MDN for radio using command [%s]", m_sName.c_str(), sCmd.c_str()); + size_t pos = sResult.find(ICellularRadio::RSP_OK); + if (pos == std::string::npos) { + printWarning("%s| Failed to unlock the SIM card using command [%s]", m_sName.c_str(), sCmd.c_str()); return FAILURE; } return SUCCESS; } -CellularRadio::CODE CellularRadio::setMsid(const Json::Value& jArgs) { +ICellularRadio::CODE CellularRadio::validateMsl(const Json::Value&) { + printTrace("%s| Validate MSL", m_sName.c_str()); + + return NOT_APPLICABLE; +} + +ICellularRadio::CODE CellularRadio::setMsid(const Json::Value&) { printTrace("%s| Set MSID", m_sName.c_str()); return NOT_APPLICABLE; } -CellularRadio::CODE CellularRadio::getMipProfile(Json::Value& jMipProfile) { +ICellularRadio::CODE CellularRadio::getMipProfile(Json::Value&) { printTrace("%s| Get MIP Active Profile", m_sName.c_str()); return NOT_APPLICABLE; } -CellularRadio::CODE CellularRadio::setMipActiveProfile(const Json::Value& jArgs) { +ICellularRadio::CODE CellularRadio::setMipActiveProfile(const Json::Value&) { printTrace("%s| Set MIP Active Profile", m_sName.c_str()); return NOT_APPLICABLE; } -CellularRadio::CODE CellularRadio::setMipNai(const Json::Value& jArgs) { +ICellularRadio::CODE CellularRadio::setMipNai(const Json::Value&) { printTrace("%s| Set MIP NAI", m_sName.c_str()); return NOT_APPLICABLE; } -CellularRadio::CODE CellularRadio::setMipHomeIp(const Json::Value& jArgs) { +ICellularRadio::CODE CellularRadio::setMipHomeIp(const Json::Value&) { printTrace("%s| Set MIP Home IP", m_sName.c_str()); return NOT_APPLICABLE; } -CellularRadio::CODE CellularRadio::setMipPrimaryHa(const Json::Value& jArgs) { +ICellularRadio::CODE CellularRadio::setMipPrimaryHa(const Json::Value&) { printTrace("%s| Set MIP Primary HA", m_sName.c_str()); return NOT_APPLICABLE; } -CellularRadio::CODE CellularRadio::setMipSecondaryHa(const Json::Value& jArgs) { +ICellularRadio::CODE CellularRadio::setMipSecondaryHa(const Json::Value&) { printTrace("%s| Set MIP Secondary HA", m_sName.c_str()); return NOT_APPLICABLE; } -CellularRadio::CODE CellularRadio::setMipMnAaaSpi(const Json::Value& jArgs) { +ICellularRadio::CODE CellularRadio::setMipMnAaaSpi(const Json::Value&) { printTrace("%s| Set MIP MN-AAA SPI", m_sName.c_str()); return NOT_APPLICABLE; } -CellularRadio::CODE CellularRadio::setMipMnHaSpi(const Json::Value& jArgs) { +ICellularRadio::CODE CellularRadio::setMipMnHaSpi(const Json::Value&) { printTrace("%s| Set MIP MN-HA SPI", m_sName.c_str()); return NOT_APPLICABLE; } -CellularRadio::CODE CellularRadio::setMipRevTun(const Json::Value& jArgs) { +ICellularRadio::CODE CellularRadio::setMipRevTun(const Json::Value&) { printTrace("%s| Set MIP Rev Tun", m_sName.c_str()); return NOT_APPLICABLE; } -CellularRadio::CODE CellularRadio::setMipMnAaaSs(const Json::Value& jArgs) { +ICellularRadio::CODE CellularRadio::setMipMnAaaSs(const Json::Value&) { printTrace("%s| Set MIP MN-AAA SS", m_sName.c_str()); return NOT_APPLICABLE; } -CellularRadio::CODE CellularRadio::setMipMnHaSs(const Json::Value& jArgs) { +ICellularRadio::CODE CellularRadio::setMipMnHaSs(const Json::Value&) { printTrace("%s| Set MIP MN-HA SS", m_sName.c_str()); return NOT_APPLICABLE; } -CellularRadio::CODE CellularRadio::updateDc(const Json::Value& jArgs, UpdateCb& stepCb) { +ICellularRadio::CODE CellularRadio::updateDc(const Json::Value&, UpdateCb&) { printTrace("%s| Update Device Configuration", m_sName.c_str()); return NOT_APPLICABLE; } -CellularRadio::CODE CellularRadio::updatePrl(const Json::Value& jArgs, UpdateCb& stepCb) { +ICellularRadio::CODE CellularRadio::updatePrl(const Json::Value&, UpdateCb&) { printTrace("%s| Update Preferred Roaming List", m_sName.c_str()); return NOT_APPLICABLE; } -CellularRadio::CODE CellularRadio::updateFumo(const Json::Value& jArgs, UpdateCb& stepCb) { +ICellularRadio::CODE CellularRadio::updateFumo(const Json::Value&, UpdateCb&) { printTrace("%s| Update Firmware Update Management Object", m_sName.c_str()); return NOT_APPLICABLE; } -CellularRadio::CODE CellularRadio::resetHfa(const Json::Value& jArgs, UpdateCb& stepCb) { +ICellularRadio::CODE CellularRadio::resetHfa(const Json::Value&, UpdateCb&) { printTrace("%s| HFA Reset", m_sName.c_str()); return NOT_APPLICABLE; } -CellularRadio::CODE CellularRadio::activate(const Json::Value& jArgs, UpdateCb& stepCb) { +ICellularRadio::CODE CellularRadio::activate(const Json::Value&, UpdateCb&) { printTrace("%s| Activation", m_sName.c_str()); return NOT_APPLICABLE; } -CellularRadio::CODE CellularRadio::setActiveFirmware(const Json::Value& jArgs) { +ICellularRadio::CODE CellularRadio::setActiveFirmware(const Json::Value&) { printTrace("%s| Set Active Firmware Image Number: not applicable", m_sName.c_str()); return NOT_APPLICABLE; } -CellularRadio::CODE CellularRadio::getActiveFirmware(std::string& sFwId) { +ICellularRadio::CODE CellularRadio::getActiveFirmware(std::string& sFwId) { printTrace("%s| Get Active Firmware Image Number: not applicable", m_sName.c_str()); - sFwId = VALUE_NOT_SUPPORTED; + sFwId = ICellularRadio::VALUE_NOT_SUPPORTED; return NOT_APPLICABLE; } -CellularRadio::CODE CellularRadio::sendBasicCommand(const std::string& sCmd, int32_t iTimeoutMillis, const char& ESC) { +ICellularRadio::CODE CellularRadio::sendBasicCommand(const std::string& sCmd, int32_t iTimeoutMillis, const char& ESC) { std::string response = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, iTimeoutMillis, ESC); if (response.size() == 0) { return NO_RESPONSE; - } else if (response.find(RSP_OK) != std::string::npos) { + } else if (response.find(ICellularRadio::RSP_OK) != std::string::npos) { return SUCCESS; - } else if (response.find(RSP_ERROR) != std::string::npos) { + } else if (response.find(ICellularRadio::RSP_ERROR) != std::string::npos) { return ERROR; } else { return FAILURE; @@ -1485,167 +938,11 @@ CellularRadio::CODE CellularRadio::sendBasicCommand(const std::string& sCmd, int } std::string CellularRadio::sendCommand(const std::string& sCmd, const std::vector<std::string>& vBail, int32_t timeoutMillis, const char& ESC) { - return sendCommand(m_apIo, sCmd, vBail, timeoutMillis, ESC); -} - -std::string CellularRadio::sendCommand(MTS::AutoPtr<MTS::IO::Connection>& apIo, const std::string& sCmd, - const std::vector<std::string>& vBail, int32_t timeoutMillis, const char& ESC) { - IsNeedMoreData isNeedMoreData = [&vBail](const std::string& iterationData, const std::string& allData)->bool { - for(size_t i = 0; i < vBail.size(); i++) { - const std::string& sBail = vBail[i]; - if(sBail.size() > 0) { - if(allData.find(sBail) != std::string::npos) { - //Return when bail string is found - printTrace("RADIO| Found bail string [%s]", sBail.c_str()); - return false; - } - } - } - return true; - }; - - return sendCommand(apIo, sCmd, isNeedMoreData, timeoutMillis, ESC); + return ICellularRadio::sendCommand(m_apIo, sCmd, vBail, timeoutMillis, ESC); } std::string CellularRadio::sendCommand(const std::string& sCmd, MTS::IO::CellularRadio::IsNeedMoreData& isNeedMoreData, int32_t timeoutMillis, const char& ESC) { - return sendCommand(m_apIo, sCmd, isNeedMoreData, timeoutMillis, ESC); -} - -std::string CellularRadio::sendCommand(MTS::AutoPtr<MTS::IO::Connection>& apIo, const std::string& sCmd, - IsNeedMoreData& isNeedMoreData, int32_t timeoutMillis, const char& ESC) { - if(MTS::Logger::getPrintLevel() >= MTS::Logger::PrintLevel::TRACE_LEVEL) { - printTrace("RADIO| Sending command [%s]", sCmd.c_str()); - } - if(apIo.isNull()) { - printError("RADIO| IO is not set in sendCommand"); - return ""; - } - - int32_t iResult; - if(ESC == 0x00) { - iResult = apIo->write(sCmd.data(), sCmd.size()); - } else { - std::string sNewCmd(sCmd); - sNewCmd.push_back(ESC); - iResult = apIo->write(sNewCmd.data(), sNewCmd.size()); - } - - if(iResult == -1) { - printError("RADIO| Failed to send command to radio"); - return ""; - } - - bool done = false; - const uint32_t capacity = 1024; - char buffer[capacity]; - std::string sResult; - Timer timer; - timer.start(); - do { - int32_t iterationTimeout = 100; - int bytesRead = apIo->read((char*)buffer, capacity, iterationTimeout); - if(bytesRead == -1) { - printError("RADIO| Failed to read from radio"); - break; - } - - std::string sIteration((char*)buffer, bytesRead); - sResult += sIteration; - - if(isNeedMoreData && !isNeedMoreData(sIteration, sResult)) { - printTrace("RADIO| No more data needed"); - return sResult; - } - if(timeoutMillis >= 0) { - done = (timer.getMillis() >= (uint64_t)timeoutMillis); - } else { - //Do not stop looping until bail string is found - } - } while(!done); - - //Timed out - return sResult; -} - -CellularRadio::CODE CellularRadio::test(MTS::AutoPtr<MTS::IO::Connection>& apIo, uint32_t timeoutSeconds) { - printTrace("RADIO| Basic Test"); - uint32_t count = 0; - std::string sCmd("AT"); - do { - std::string sResult = sendCommand(apIo, sCmd); - if (sResult.find(RSP_OK) == std::string::npos) { - printTrace("RADIO| Waiting for basic radio communication [%s] ...", sResult.c_str()); - } else { - break; - } - count++; - } while (count < timeoutSeconds); - - if(count == timeoutSeconds) { - printWarning("RADIO| Basic radio communication FAILED"); - return NO_RESPONSE; - } - return SUCCESS; -} - -std::string CellularRadio::extractModelFromResult(const std::string& sResult) { - std::string sModel(CellularRadio::VALUE_NOT_SUPPORTED); - - if(sResult.find("HE910-D") != std::string::npos) { - sModel = "HE910-D"; - } else if(sResult.find("HE910-EUD") != std::string::npos) { - sModel = "HE910-EUD"; - } else if(sResult.find("LE910-JN1") != std::string::npos) { - sModel = "LE910-JN1"; - } else if(sResult.find("LE866A1-JS") != std::string::npos) { - sModel = "LE866A1-JS"; - } else if(sResult.find("LE910-NAG") != std::string::npos) { - sModel = "LE910-NAG"; - } else if(sResult.find("LE910C4-NF") != std::string::npos) { - sModel = "LE910C4-NF"; - } else if(sResult.find("LE910-NA1") != std::string::npos) { - sModel = "LE910-NA1"; - } else if(sResult.find("ME910C1-NA") != std::string::npos) { - sModel = "ME910C1-NA"; - } else if(sResult.find("ME910C1-NV") != std::string::npos) { - sModel = "ME910C1-NV"; - } else if(sResult.find("ME910C1-WW") != std::string::npos) { - sModel = "ME910C1-WW"; - } else if(sResult.find("LE910-SVG") != std::string::npos) { - sModel = "LE910-SVG"; - } else if(sResult.find("LE910-EUG") != std::string::npos) { - sModel = "LE910-EUG"; - } else if(sResult.find("LE910C4-EU") != std::string::npos) { - sModel = "LE910C4-EU"; - } else if(sResult.find("LE910-EU1") != std::string::npos) { - sModel = "LE910-EU1"; - } else if(sResult.find("LE910C1-NS") != std::string::npos) { - sModel = "LE910C1-NS"; - } else if(sResult.find("LE910C1-AP") != std::string::npos) { - sModel = "LE910C1-AP"; - } else if(sResult.find("GE910") != std::string::npos) { - sModel = "GE910"; - } else if(sResult.find("DE910-DUAL") != std::string::npos) { - sModel = "DE910-DUAL"; - } else if(sResult.find("CE910") != std::string::npos) { - sModel = "CE910"; - } - return sModel; -} - -std::string CellularRadio::getCodeAsString(CODE eCode) { - switch(eCode) { - case SUCCESS: - return "SUCCESS"; - case ERROR: - return "ERROR"; - case FAILURE: - return "FAILURE"; - case NO_RESPONSE: - return "NO RESPONSE"; - default: - return "UNKNOWN"; - } + return ICellularRadio::sendCommand(m_apIo, sCmd, isNeedMoreData, timeoutMillis, ESC); } bool CellularRadio::splitAndAssign(const std::string& sLine, const std::string& sKey, Json::Value& jParent, const std::string& sJsonKey, Json::ValueType eType) { @@ -1680,84 +977,15 @@ bool CellularRadio::splitAndAssign(const std::string& sLine, const std::string& } bool CellularRadio::getCarrierFromFirmware(const std::string& sFirmware, std::string& sCarrier) { - // Telit Radios - // H.ab.zyx => 3 Main Components - // "H" = Hardware -> 15 = DE910 family, 18 = CE910 family, 12 = HE910 family - // "a" = Hardware version - // "b" = Software Major Version - // "z" = is the product type, i.e. DUAL or SC - // "y" = is the carrier variant - // "x" = is the firmware version - // Telit will do their best to keep the carrier variant as "0" for Sprint, "1" for Aeris, "2" for Verizon, and "3" for U.S. Cellular. - - const uint32_t CARRIER_INDEX = 1; //y in [zyx] - - bool bResult = false; - std::vector<std::string> vParts = MTS::Text::split(sFirmware, '.'); - - if(vParts.size() == 3) { - //CDMA firmware version notation - if(vParts[0] == "15" || vParts[0] == "18") { - //DE910 or CE910 -> Good good - std::string sID = vParts[2]; - if(sID.size() == 3) { - char cId = sID[CARRIER_INDEX]; - - //Good good - if(cId == '0') { - sCarrier = VALUE_CARRIER_SPRINT; - bResult = true; - } else - if(cId == '1') { - sCarrier = VALUE_CARRIER_AERIS; - bResult = true; - } else - if(cId == '2') { - sCarrier = VALUE_CARRIER_VERIZON; - bResult = true; - } else - if(cId == '3') { - sCarrier = VALUE_CARRIER_USCELLULAR; - bResult = true; - } - } - } - } + // Assuming that this function is not supported by the modem until overriden. - return bResult; + return false; } bool CellularRadio::getHardwareVersionFromFirmware(const std::string& sFirmware, std::string& sHardware) { - // Telit Radios - // H.ab.zyx => 3 Main Components - // "H" = Hardware -> 15 = DE910 family, 18 = CE910 family, 12 = HE910 family - // "a" = Hardware version - // "b" = Software Major Version - // "z" = is the product type, i.e. DUAL or SC - // "y" = is the carrier variant - // "x" = is the firmware version - // Telit will do their best to keep the carrier variant as "0" for Sprint, "1" for Aeris, and "2" for Verizon. - - const uint32_t HARDWARE_INDEX = 0; //a in [ab] - - bool bResult = false; - std::vector<std::string> vParts = MTS::Text::split(sFirmware, '.'); - - if(vParts.size() == 3) { - //GSM Hardware Version - if(!(vParts[0] == "15" || vParts[0] == "18")) { - //Not DE910 or CE910 -> Good good - std::string sVersion = vParts[1]; - if(sVersion.size() == 2) { - sHardware = "1."; - sHardware += sVersion[HARDWARE_INDEX]; - bResult = true; - } - } - } - - return bResult; + // Assuming that this function is not supported by the modem until overriden. + return false; } const char *CellularRadio::RadioBandMap::getLTEBand(const int32_t channel) @@ -1769,7 +997,7 @@ const char *CellularRadio::RadioBandMap::getLTEBand(const int32_t channel) return EULTRAband[ii].name; } } - return VALUE_UNKNOWN.c_str(); + return ICellularRadio::VALUE_UNKNOWN; } const char *CellularRadio::RadioBandMap::getCDMABand(const int channel) @@ -1781,7 +1009,7 @@ const char *CellularRadio::RadioBandMap::getCDMABand(const int channel) return WCDMAband[ii].name; } } - return VALUE_UNKNOWN.c_str(); + return ICellularRadio::VALUE_UNKNOWN; } const char *CellularRadio::RadioBandMap::getGSMBand(const int channel) @@ -1793,22 +1021,22 @@ const char *CellularRadio::RadioBandMap::getGSMBand(const int channel) return GSMband[ii].name; } } - return VALUE_UNKNOWN.c_str(); + return ICellularRadio::VALUE_UNKNOWN; } const char *CellularRadio::RadioBandMap::getRadioBandName() { - const char *band = CellularRadio::VALUE_UNKNOWN.c_str(); + const char *band = ICellularRadio::VALUE_UNKNOWN; - if (m_sRadioType == CellularRadio::VALUE_TYPE_LTE) + if (m_sRadioType == ICellularRadio::VALUE_TYPE_LTE) { band = getLTEBand(m_iChannel); } - else if (m_sRadioType == CellularRadio::VALUE_TYPE_CDMA) + else if (m_sRadioType == ICellularRadio::VALUE_TYPE_CDMA) { band = getCDMABand(m_iChannel); } - else if (m_sRadioType == CellularRadio::VALUE_TYPE_GSM) + else if (m_sRadioType == ICellularRadio::VALUE_TYPE_GSM) { band = getGSMBand(m_iChannel); } @@ -1818,17 +1046,17 @@ const char *CellularRadio::RadioBandMap::getRadioBandName() const char *CellularRadio::RadioBandMap::getRadioBandName(const std::string &channel, const std::string &radioType) { - const char *band = CellularRadio::VALUE_UNKNOWN.c_str(); + const char *band = ICellularRadio::VALUE_UNKNOWN; int32_t chan = strtol(channel.c_str(), NULL, 10); - if (radioType == CellularRadio::VALUE_TYPE_LTE) + if (radioType == ICellularRadio::VALUE_TYPE_LTE) { band = getLTEBand(chan); } - else if (radioType == CellularRadio::VALUE_TYPE_CDMA) + else if (radioType == ICellularRadio::VALUE_TYPE_CDMA) { band = getCDMABand(chan); } - else if (radioType == CellularRadio::VALUE_TYPE_GSM) + else if (radioType == ICellularRadio::VALUE_TYPE_GSM) { band = getGSMBand(chan); } diff --git a/src/MTS_IO_CellularRadioFactory.cpp b/src/MTS_IO_CellularRadioFactory.cpp index ef87f0e..4ee8756 100644 --- a/src/MTS_IO_CellularRadioFactory.cpp +++ b/src/MTS_IO_CellularRadioFactory.cpp @@ -37,6 +37,7 @@ #include <mts/MTS_IO_GE910Radio.h> #include <mts/MTS_IO_CE910Radio.h> #include <mts/MTS_IO_DE910Radio.h> +#include "mts/MTS_IO_EG95Radio.h" #include <mts/MTS_Logger.h> using namespace MTS::IO; @@ -60,9 +61,10 @@ CellularRadioFactory::CellularRadioFactory() { m_mCreationMap[DE910Radio::MODEL_NAME] = &CellularRadioFactory::createDE910; m_mCreationMap[CE910Radio::MODEL_NAME] = &CellularRadioFactory::createCE910; m_mCreationMap[LE866A1JSRadio::MODEL_NAME] = &CellularRadioFactory::createLE866A1JS; + m_mCreationMap[EG95Radio::MODEL_NAME] = &CellularRadioFactory::createEG95Radio; } -MTS::IO::CellularRadio* CellularRadioFactory::create(const std::string& sModel, const std::string& sPort) { +ICellularRadio* CellularRadioFactory::create(const std::string& sModel, const std::string& sPort) { std::string model(sModel); @@ -87,22 +89,22 @@ std::string CellularRadioFactory::identifyRadio(const std::string& sPort) { apIo.reset(new SerialConnection(SerialConnection::Builder(sPort).baudRate(115200).useLockFile().build())); while(!apIo->open(30000)) { printError("CellularRadioFactory| Failed to open radio port [%s]", sPort.c_str()); - return CellularRadio::VALUE_UNKNOWN; + return ICellularRadio::VALUE_UNKNOWN; } //Attempt basic radio communication - if(CellularRadio::test(apIo) != CellularRadio::SUCCESS) { + if(ICellularRadio::test(apIo) != ICellularRadio::SUCCESS) { printError("CellularRadioFactory| Failed to communicate with radio on port [%s]", sPort.c_str()); apIo->close(); - return CellularRadio::VALUE_UNKNOWN; + return ICellularRadio::VALUE_UNKNOWN; } //Get model int count = 0; - std::string sCmd("ATI4"); + std::string sCmd("AT+GMM"); std::string sResult; do { - sResult = CellularRadio::sendCommand(apIo, sCmd, CellularRadio::DEFAULT_BAIL_STRINGS, 1000, CellularRadio::CR); + sResult = ICellularRadio::sendCommand(apIo, sCmd, ICellularRadio::DEFAULT_BAIL_STRINGS, 1000, ICellularRadio::CR); if (sResult.find("OK") == std::string::npos) { printDebug("RADIO| Attempting to get radio model [%s] ...", sResult.c_str()); } else { @@ -114,83 +116,88 @@ std::string CellularRadioFactory::identifyRadio(const std::string& sPort) { if(count == 30) { printDebug("RADIO| Unable to get radio model"); apIo->close(); - return CellularRadio::VALUE_UNKNOWN; + return ICellularRadio::VALUE_UNKNOWN; } - std::string sModel = CellularRadio::extractModelFromResult(sResult); - printDebug("RADIO| Extracted [%s] from ATI4 query", sModel.c_str()); + std::string sModel = ICellularRadio::extractModelFromResult(sResult); + printDebug("RADIO| Extracted [%s] from AT+GMM query", sModel.c_str()); apIo->close(); return sModel; } -CellularRadio* CellularRadioFactory::createHE910D(const std::string& sPort) { +ICellularRadio* CellularRadioFactory::createHE910D(const std::string& sPort) const { return new HE910DRadio(sPort); } -CellularRadio* CellularRadioFactory::createHE910EUD(const std::string& sPort) { +ICellularRadio* CellularRadioFactory::createHE910EUD(const std::string& sPort) const { return new HE910EUDRadio(sPort); } -CellularRadio* CellularRadioFactory::createLE910NAG(const std::string& sPort) { +ICellularRadio* CellularRadioFactory::createLE910NAG(const std::string& sPort) const { return new LE910NAGRadio(sPort); } -CellularRadio* CellularRadioFactory::createLE910C4NF(const std::string& sPort) { +ICellularRadio* CellularRadioFactory::createLE910C4NF(const std::string& sPort) const { return new LE910C4NFRadio(sPort); } -CellularRadio* CellularRadioFactory::createLE910NA1(const std::string& sPort) { +ICellularRadio* CellularRadioFactory::createLE910NA1(const std::string& sPort) const { return new LE910NA1Radio(sPort); } -CellularRadio* CellularRadioFactory::createLE910SVG(const std::string& sPort) { +ICellularRadio* CellularRadioFactory::createLE910SVG(const std::string& sPort) const { return new LE910SVGRadio(sPort); } -CellularRadio* CellularRadioFactory::createLE910EUG(const std::string& sPort) { +ICellularRadio* CellularRadioFactory::createLE910EUG(const std::string& sPort) const { return new LE910EUGRadio(sPort); } -CellularRadio* CellularRadioFactory::createLE910C4EU(const std::string& sPort) { +ICellularRadio* CellularRadioFactory::createLE910C4EU(const std::string& sPort) const { return new LE910C4EURadio(sPort); } -CellularRadio* CellularRadioFactory::createLE910EU1(const std::string& sPort) { +ICellularRadio* CellularRadioFactory::createLE910EU1(const std::string& sPort) const { return new LE910EU1Radio(sPort); } -CellularRadio* CellularRadioFactory::createLE910C1NS(const std::string& sPort) { +ICellularRadio* CellularRadioFactory::createLE910C1NS(const std::string& sPort) const { return new LE910C1NSRadio(sPort); } -CellularRadio* CellularRadioFactory::createLE910C1AP(const std::string& sPort) { +ICellularRadio* CellularRadioFactory::createLE910C1AP(const std::string& sPort) const { return new LE910C1APRadio(sPort); } -CellularRadio* CellularRadioFactory::createME910C1NA(const std::string& sPort) { +ICellularRadio* CellularRadioFactory::createME910C1NA(const std::string& sPort) const { return new ME910C1NARadio(sPort); } -CellularRadio* CellularRadioFactory::createME910C1NV(const std::string& sPort) { +ICellularRadio* CellularRadioFactory::createME910C1NV(const std::string& sPort) const { return new ME910C1NVRadio(sPort); } -CellularRadio* CellularRadioFactory::createME910C1WW(const std::string& sPort) { +ICellularRadio* CellularRadioFactory::createME910C1WW(const std::string& sPort) const { return new ME910C1WWRadio(sPort); } -CellularRadio* CellularRadioFactory::createGE910(const std::string& sPort) { +ICellularRadio* CellularRadioFactory::createGE910(const std::string& sPort) const { return new GE910Radio(sPort); } -CellularRadio* CellularRadioFactory::createDE910(const std::string& sPort) { +ICellularRadio* CellularRadioFactory::createDE910(const std::string& sPort) const { return new DE910Radio(sPort); } -CellularRadio* CellularRadioFactory::createCE910(const std::string& sPort) { +ICellularRadio* CellularRadioFactory::createCE910(const std::string& sPort) const { return new CE910Radio(sPort); } -CellularRadio* CellularRadioFactory::createLE866A1JS(const std::string &sPort) { +ICellularRadio* CellularRadioFactory::createLE866A1JS(const std::string &sPort) const { return new LE866A1JSRadio(sPort); } + +ICellularRadio* CellularRadioFactory::createEG95Radio(const std::string& sPort) const +{ + return new EG95Radio(sPort); +} diff --git a/src/MTS_IO_DE910Radio.cpp b/src/MTS_IO_DE910Radio.cpp index eccb3eb..26668f1 100644 --- a/src/MTS_IO_DE910Radio.cpp +++ b/src/MTS_IO_DE910Radio.cpp @@ -39,7 +39,7 @@ DE910Radio::DE910Radio(const std::string& sPort) } -CellularRadio::CODE DE910Radio::setRxDiversity(const Json::Value& jArgs) { +ICellularRadio::CODE DE910Radio::setRxDiversity(const Json::Value& jArgs) { /* Command string for EV3 radios: AT#CRXD= */ if (jArgs["enabled"].asString() != "1" && jArgs["enabled"].asString() != "0") { diff --git a/src/MTS_IO_EG95Radio.cpp b/src/MTS_IO_EG95Radio.cpp new file mode 100644 index 0000000..5c9ed69 --- /dev/null +++ b/src/MTS_IO_EG95Radio.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2019 by Multi-Tech Systems + * + * This file is part of libmts-io. + * + * libmts-io is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * libmts-io is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libmts-io. If not, see <http://www.gnu.org/licenses/>. + * + */ + + +#include <mts/MTS_IO_EG95Radio.h> + +using namespace MTS::IO; + +const std::string EG95Radio::MODEL_NAME("EG95"); + +EG95Radio::EG95Radio(const std::string& sPort) +: QuectelRadio(MODEL_NAME, sPort) +{ + +} + +EG95Radio::~EG95Radio() { + +} + +ICellularRadio::CODE EG95Radio::setRxDiversity(const Json::Value& jArgs) { + /* Command string for EG95 radios: AT+QCFG="diversity",(0-1) */ + if (jArgs["enabled"].asString() != "1" && jArgs["enabled"].asString() != "0") { + return FAILURE; + } + std::string sCmd = "AT+QCFG=\"diversity\","; + sCmd += jArgs["enabled"].asString(); + + return sendBasicCommand(sCmd); +} diff --git a/src/MTS_IO_GE910Radio.cpp b/src/MTS_IO_GE910Radio.cpp index e402b13..61332b5 100644 --- a/src/MTS_IO_GE910Radio.cpp +++ b/src/MTS_IO_GE910Radio.cpp @@ -34,12 +34,12 @@ using namespace MTS::IO; const std::string GE910Radio::MODEL_NAME("GE910"); GE910Radio::GE910Radio(const std::string& sPort) -: CellularRadio(MODEL_NAME, sPort) +: TelitRadio(MODEL_NAME, sPort) { } -CellularRadio::CODE GE910Radio::setRxDiversity(const Json::Value& jArgs) { +ICellularRadio::CODE GE910Radio::setRxDiversity(const Json::Value& jArgs) { /* Command string for GE radios: N/A */ return FAILURE; } diff --git a/src/MTS_IO_HE910Radio.cpp b/src/MTS_IO_HE910Radio.cpp index bc08932..4c0a759 100644 --- a/src/MTS_IO_HE910Radio.cpp +++ b/src/MTS_IO_HE910Radio.cpp @@ -32,12 +32,12 @@ using namespace MTS::IO; HE910Radio::HE910Radio(const std::string& sHE910Model, const std::string& sPort) -: CellularRadio(sHE910Model, sPort) +: TelitRadio(sHE910Model, sPort) { } -CellularRadio::CODE HE910Radio::setRxDiversity(const Json::Value& jArgs) { +ICellularRadio::CODE HE910Radio::setRxDiversity(const Json::Value& jArgs) { /* Command string for H5 radios: "AT#RXDIV" */ if (jArgs["enabled"].asString() != "1" && jArgs["enabled"].asString() != "0") { diff --git a/src/MTS_IO_ICellularRadio.cpp b/src/MTS_IO_ICellularRadio.cpp new file mode 100644 index 0000000..4e7809e --- /dev/null +++ b/src/MTS_IO_ICellularRadio.cpp @@ -0,0 +1,472 @@ +#include "mts/MTS_IO_ICellularRadio.h" + +#include <mts/MTS_Logger.h> +#include <mts/MTS_Timer.h> + +const char MTS::IO::ICellularRadio::ETX = 0x03; //Ends socket connection +const char MTS::IO::ICellularRadio::DLE = 0x10; //Escapes ETX and DLE within Payload +const char MTS::IO::ICellularRadio::CR = 0x0D; +const char MTS::IO::ICellularRadio::NL = 0x0A; +const char MTS::IO::ICellularRadio::CTRL_Z = 0x1A; + +const char *MTS::IO::ICellularRadio::RSP_ERROR = "ERROR"; +const char *MTS::IO::ICellularRadio::RSP_OK = "OK"; + + +const char *MTS::IO::ICellularRadio::DEFAULT_RADIO_PORT = "/dev/modem_at1"; +const char *MTS::IO::ICellularRadio::DEFAULT_RADIO_DIR = "/var/run/radio/"; +const char *MTS::IO::ICellularRadio::VALUE_UNKNOWN = "Unknown"; +const char *MTS::IO::ICellularRadio::VALUE_UNAVAILABLE = "Unavailable"; +const char *MTS::IO::ICellularRadio::VALUE_NOT_SUPPORTED = "Not Supported"; + +const char *MTS::IO::ICellularRadio::VALUE_NOT_REGISTERED = "NOT REGISTERED"; +const char *MTS::IO::ICellularRadio::VALUE_REGISTERED = "REGISTERED"; +const char *MTS::IO::ICellularRadio::VALUE_SEARCHING = "SEARCHING"; +const char *MTS::IO::ICellularRadio::VALUE_DENIED = "DENIED"; +const char *MTS::IO::ICellularRadio::VALUE_ROAMING = "ROAMING"; + +//Static Data +const char *MTS::IO::ICellularRadio::KEY_TYPE = "type"; //!< GSM or CDMA +const char *MTS::IO::ICellularRadio::KEY_CODE = "code"; //!< Product Code : H5, H6, C2, EV3, G3 +const char *MTS::IO::ICellularRadio::KEY_MODEL = "model"; //!< Model : HE910, LE910, CE910, DE910, GE910 +const char *MTS::IO::ICellularRadio::KEY_MANUFACTURER = "manufacturer"; //!< Manufacturer: Telit +const char *MTS::IO::ICellularRadio::KEY_HARDWARE = "hardware"; //!< Radio Hardware Version +const char *MTS::IO::ICellularRadio::KEY_FIRMWARE = "firmware"; //!< Radio Firmware Version +const char *MTS::IO::ICellularRadio::KEY_FIRMWARE_BUILD = "firmwarebuild"; //!< Radio Firmware Build + +const char *MTS::IO::ICellularRadio::KEY_CARRIER = "carrier"; //!< Cellular Service Provider = Home Network +const char *MTS::IO::ICellularRadio::VALUE_CARRIER_VERIZON = "Verizon"; +const char *MTS::IO::ICellularRadio::VALUE_CARRIER_AERIS = "Aeris"; +const char *MTS::IO::ICellularRadio::VALUE_CARRIER_SPRINT = "Sprint"; +const char *MTS::IO::ICellularRadio::VALUE_CARRIER_USCELLULAR = "U.S. Cellular"; +const char *MTS::IO::ICellularRadio::VALUE_CARRIER_ATT = "AT&T"; +const char *MTS::IO::ICellularRadio::VALUE_CARRIER_TMOBILE = "T-Mobile"; + +const char *MTS::IO::ICellularRadio::KEY_IMEI = "imei"; //!< International Mobile Station Equipment Identity +const char *MTS::IO::ICellularRadio::KEY_MEID = "meid"; //!< Mobile Equipment Identifier +const char *MTS::IO::ICellularRadio::KEY_IMSI = "imsi"; //!< International Mobile Subscriber Identity +const char *MTS::IO::ICellularRadio::KEY_MSID = "msid"; //!< Mobil Station ID / Mobile Identification Number = MSID/MIN = CDMA-Only +const char *MTS::IO::ICellularRadio::KEY_MDN = "mdn"; //!< Mobile Directory Number : Actual phone number dialed to reach radio +const char *MTS::IO::ICellularRadio::KEY_ICCID = "iccid"; //!< Integrated Circuit Card Identifier +const char *MTS::IO::ICellularRadio::KEY_MSL = "msl"; //!< Master Subsidy Lock + +//Dynamic Data +const char *MTS::IO::ICellularRadio::KEY_ROAMING = "roaming"; //!< Indicates whether or not using Home Network +const char *MTS::IO::ICellularRadio::KEY_DATETIME = "datetime"; //!< Date and Time from tower +const char *MTS::IO::ICellularRadio::KEY_SERVICE = "service"; //!< Service Connection Type [GPRS, EGPRS, WCDMA, HSDPA, 1xRTT, EVDO] +const char *MTS::IO::ICellularRadio::KEY_NETWORK = "network"; //!< Cellular Service Provider +const char *MTS::IO::ICellularRadio::KEY_NETWORK_REG = "netreg"; //!< Network Registration +const char *MTS::IO::ICellularRadio::KEY_CID = "cid"; //!< Cellular ID = Tower in HEX +const char *MTS::IO::ICellularRadio::KEY_LAC = "lac"; //!< Location Area Code in HEX +const char *MTS::IO::ICellularRadio::KEY_RAC = "rac"; //!< Routing Area Code in HEX +const char *MTS::IO::ICellularRadio::KEY_RSSI = "rssi"; //!< Signal Strength +const char *MTS::IO::ICellularRadio::KEY_RSSIDBM = "rssidBm"; //!< Signal Strength in dBm +const char *MTS::IO::ICellularRadio::KEY_MCC = "mcc"; //!< Country Code +const char *MTS::IO::ICellularRadio::KEY_MNC = "mnc"; //!< Operator Code +const char *MTS::IO::ICellularRadio::KEY_CHANNEL = "channel"; //!< ARFCN or UARFCN Assigned Radio Channel +const char *MTS::IO::ICellularRadio::KEY_TXPWR = "txpwr"; //!< Transmit Power +const char *MTS::IO::ICellularRadio::KEY_PSC = "psc"; //!< Active Primary Synchronization Code = PSC +const char *MTS::IO::ICellularRadio::KEY_ECIO = "ecio"; //!< Active Ec/Io = chip energy per total wideband power in dBm +const char *MTS::IO::ICellularRadio::KEY_RSCP = "rscp"; //!< Active RSCP = Received Signal Code Power in dBm +const char *MTS::IO::ICellularRadio::KEY_DRX = "drx"; //!< Discontinuous reception cycle length = ms +const char *MTS::IO::ICellularRadio::KEY_MM = "mm"; //!< Mobility Management State +const char *MTS::IO::ICellularRadio::KEY_RR = "rr"; //!< Radio Resource State +const char *MTS::IO::ICellularRadio::KEY_NOM = "nom"; //!< Network Operator Mode +const char *MTS::IO::ICellularRadio::KEY_ABND = "abnd"; //!< Active Band +const char *MTS::IO::ICellularRadio::KEY_BLER = "bler"; //!< Block Error Rate = percentage +const char *MTS::IO::ICellularRadio::KEY_SD = "sd"; //!< Service Domain +const char *MTS::IO::ICellularRadio::KEY_DEBUG = "debug"; //!< Debug Information + +const char *MTS::IO::ICellularRadio::KEY_MIP = "mipProfile"; //!< Mobile IP Information +const char *MTS::IO::ICellularRadio::KEY_MIP_ID = "id"; //!< Mobile IP ID +const char *MTS::IO::ICellularRadio::KEY_MIP_ENABLED = "enabled"; //!< Mobile IP Enabled/Disabled +const char *MTS::IO::ICellularRadio::KEY_MIP_NAI = "nai"; //!< Network Access Identifier +const char *MTS::IO::ICellularRadio::KEY_MIP_HOMEADDRESS = "homeAddress"; //!< Home Address +const char *MTS::IO::ICellularRadio::KEY_MIP_PRIMARYHA = "primaryAddress"; //!< Primary Home Agent +const char *MTS::IO::ICellularRadio::KEY_MIP_SECONDARYHA = "secondaryAddress"; //!< Secondary Home Agent +const char *MTS::IO::ICellularRadio::KEY_MIP_MNAAASPI = "mnAaaSpi"; //!< Mobile Node Authentication, Authorization, and Accounting Server Security Parameter Index +const char *MTS::IO::ICellularRadio::KEY_MIP_MNHASPI = "mnHaSpi"; //!< Mobile Node Home Agent Security Server Parameter Index +const char *MTS::IO::ICellularRadio::KEY_MIP_REVTUN = "revTun"; //!< Reverse Tunneling Enabled +const char *MTS::IO::ICellularRadio::KEY_MIP_MNAAASS = "mnAaaSs"; //!< Mobile Node Authentication, Authorization, and Accounting Server Shared Secret +const char *MTS::IO::ICellularRadio::KEY_MIP_MNHASS = "mnHaSs"; //!< Mobile Node Home Agent Shared Secret + +const char *MTS::IO::ICellularRadio::VALUE_TYPE_GSM = "GSM"; +const char *MTS::IO::ICellularRadio::VALUE_TYPE_LTE = "LTE"; +const char *MTS::IO::ICellularRadio::VALUE_TYPE_CDMA = "CDMA"; + +const char *MTS::IO::ICellularRadio::KEY_IS_SIM_INSERTED = "isSimInserted"; //!< SIM card insertion indicator. True when a SIM card is inserted +const char *MTS::IO::ICellularRadio::KEY_IS_SIM_LOCKED = "isSimLocked"; //!< SIM card lock status indicator. True when a SIM card is locked by PIN / PUK / other code +const char *MTS::IO::ICellularRadio::KEY_SIM_LOCK_STATUS = "lockStatus"; //!< SIM card lock status string. Either "READY", "SIM PIN", "SIM PUK" or other state +const char *MTS::IO::ICellularRadio::KEY_ATTEMPTS_PIN = "attemptsPin"; //!< The number of attempts left to unlock the SIM card using PIN code +const char *MTS::IO::ICellularRadio::KEY_ATTEMPTS_PUK = "attemptsPuk"; //!< The number of attempts left to unlock the SIM card using PUK code + +const char *MTS::IO::ICellularRadio::VALUE_SD_NO_SERVICE = "NO SERVICE"; +const char *MTS::IO::ICellularRadio::VALUE_SD_CS_ONLY = "CS ONLY"; +const char *MTS::IO::ICellularRadio::VALUE_SD_PS_ONLY = "PS ONLY"; +const char *MTS::IO::ICellularRadio::VALUE_SD_CSPS = "CS+PS"; + +const char *MTS::IO::ICellularRadio::VALUE_ABND_GSM_850 = "GSM 850"; +const char *MTS::IO::ICellularRadio::VALUE_ABND_GSM_900 = "GSM 900"; +const char *MTS::IO::ICellularRadio::VALUE_ABND_DCS_1800 = "DCS 1800"; +const char *MTS::IO::ICellularRadio::VALUE_ABND_PCS_1900 = "PCS 1900"; + +const std::vector<std::string> MTS::IO::ICellularRadio::DEFAULT_BAIL_STRINGS = { MTS::IO::ICellularRadio::RSP_OK, MTS::IO::ICellularRadio::RSP_ERROR }; + +MTS::IO::ICellularRadio::~ICellularRadio() +{ +} + +MTS::IO::ICellularRadio::CODE MTS::IO::ICellularRadio::convertModelToMtsShortCode(const std::string& sModel, std::string& sCode, MTS::IO::ICellularRadio *radioObject) { + CODE eCode = FAILURE; + + if(sModel.find("HE910-D") == 0) { + sCode = "H5"; + eCode = SUCCESS; + } else if (sModel.find("HE910-EUD") == 0) { + sCode = "H6"; + eCode = SUCCESS; + } else if (sModel.find("LE910-JN1") == 0) { + sCode = "LDC3"; + eCode = SUCCESS; + } else if (sModel.find("LE866A1-JS") == 0) { + sCode = "LSB3"; + eCode = SUCCESS; + } else if (sModel.find("LE910-NAG") == 0) { + sCode = "LAT1"; + eCode = SUCCESS; + } else if (sModel.find("LE910C4-NF") == 0) { + sCode = "L4N1"; + eCode = SUCCESS; + } else if (sModel.find("LE910-NA1") == 0) { + if (NULL == radioObject) { + sCode = VALUE_NOT_SUPPORTED; + eCode = ERROR; + } else { + std::string sValue; + eCode = radioObject->getActiveFirmware(sValue); + if (eCode == SUCCESS) { + sCode = "LNA3"; + } else { + sCode = "LAT3"; + } + } + eCode = SUCCESS; + } else if (sModel.find("LE910-SVG") == 0) { + sCode = "LVW2"; + eCode = SUCCESS; + } else if (sModel.find("LE910C1-NS") == 0) { + sCode = "LSP3"; + eCode = SUCCESS; + } else if (sModel.find("LE910C1-AP") == 0) { + sCode = "LAP3"; + eCode = SUCCESS; + } else if (sModel.find("ME910C1-NA") == 0) { + sCode = "MAT1"; + eCode = SUCCESS; + } else if (sModel.find("ME910C1-NV") == 0) { + sCode = "MVW1"; + eCode = SUCCESS; + } else if (sModel.find("ME910C1-WW") == 0) { + sCode = "MNG2"; + eCode = SUCCESS; + } else if (sModel.find("LE910-EUG") == 0) { + sCode = "LEU1"; + eCode = SUCCESS; + } else if (sModel.find("LE910C4-EU") == 0) { + sCode = "L4E1"; + eCode = SUCCESS; + } else if (sModel.find("LE910-EU1") == 0) { + sCode = "LEU3"; + eCode = SUCCESS; + } else if (sModel.find("GE910") == 0) { + sCode = "G3"; + eCode = SUCCESS; + } else if (sModel.find("CE910") == 0) { + sCode = "C2"; + eCode = SUCCESS; + } else if (sModel.find("DE910") == 0) { + sCode = "EV3"; + eCode = SUCCESS; + } else if (sModel.find("EG95") == 0) { + if (NULL == radioObject) { + sCode = VALUE_NOT_SUPPORTED; + eCode = ERROR; + } else { + std::string sValue; + eCode = radioObject->getFirmware(sValue); + if (eCode != SUCCESS) { + sCode = VALUE_NOT_SUPPORTED; + eCode = ERROR; + } else if (sValue.find("EG95E") != std::string::npos) { + sCode = "LEU7"; + eCode = SUCCESS; + } else if (sValue.find("EG95NA") != std::string::npos) { + sCode = "LNA7"; + eCode = SUCCESS; + } else { + sCode = VALUE_NOT_SUPPORTED; + eCode = ERROR; + } + } + } else { + sCode = VALUE_NOT_SUPPORTED; + printError("RADIO| Could not identify MTS short code from model. [%s]", sModel.c_str()); + eCode = ERROR; + } + return eCode; +} + +MTS::IO::ICellularRadio::CODE MTS::IO::ICellularRadio::convertServiceDomainToString(SERVICEDOMAIN eSd, std::string& sSd) { + CODE eCode = FAILURE; + switch(eSd) { + case NO_SERVICE: sSd = VALUE_SD_NO_SERVICE; eCode = SUCCESS; break; + case CS_ONLY: sSd = VALUE_SD_CS_ONLY; eCode = SUCCESS; break; + case PS_ONLY: sSd = VALUE_SD_PS_ONLY; eCode = SUCCESS; break; + case CSPS: sSd = VALUE_SD_CSPS; eCode = SUCCESS; break; + default: sSd = VALUE_UNKNOWN; eCode = FAILURE; break; + } + return eCode; +} + +MTS::IO::ICellularRadio::CODE MTS::IO::ICellularRadio::convertActiveBandToString(ACTIVEBAND eBand, std::string& sBand) { + CODE eCode = FAILURE; + switch(eBand) { + case GSM_850: sBand = VALUE_ABND_GSM_850; eCode = SUCCESS; break; + case GSM_900: sBand = VALUE_ABND_GSM_900; eCode = SUCCESS; break; + case DCS_1800: sBand = VALUE_ABND_DCS_1800; eCode = SUCCESS; break; + case PCS_1900: sBand = VALUE_ABND_PCS_1900; eCode = SUCCESS; break; + default: sBand = VALUE_UNKNOWN; eCode = FAILURE; break; + } + return eCode; +} + +MTS::IO::ICellularRadio::CODE MTS::IO::ICellularRadio::convertModelToType(const std::string& sModel, std::string& sType) { + CODE eCode = FAILURE; + sType = VALUE_NOT_SUPPORTED; + + if(sModel.find("HE910-D") == 0) { + sType = VALUE_TYPE_GSM; + eCode = SUCCESS; + } else if (sModel.find("HE910-EUD") == 0) { + sType = VALUE_TYPE_GSM; + eCode = SUCCESS; + } else if (sModel.find("LE910-JN1") == 0) { + sType = VALUE_TYPE_LTE; + eCode = SUCCESS; + } else if (sModel.find("LE866A1-JS") == 0) { + sType = VALUE_TYPE_LTE; + eCode = SUCCESS; + } else if (sModel.find("LE910-NAG") == 0) { + sType = VALUE_TYPE_LTE; + eCode = SUCCESS; + } else if (sModel.find("LE910C4-NF") == 0) { + sType = VALUE_TYPE_LTE; + eCode = SUCCESS; + } else if (sModel.find("LE910-NA1") == 0) { + sType = VALUE_TYPE_LTE; + eCode = SUCCESS; + } else if (sModel.find("LE910-SVG") == 0) { + sType = VALUE_TYPE_LTE; + eCode = SUCCESS; + } else if (sModel.find("LE910-EUG") == 0) { + sType = VALUE_TYPE_LTE; + eCode = SUCCESS; + } else if (sModel.find("LE910C4-EU") == 0) { + sType = VALUE_TYPE_LTE; + eCode = SUCCESS; + } else if (sModel.find("LE910-EU1") == 0) { + sType = VALUE_TYPE_LTE; + eCode = SUCCESS; + } else if (sModel.find("LE910C1-NS") == 0) { + sType = VALUE_TYPE_LTE; + eCode = SUCCESS; + } else if (sModel.find("LE910C1-AP") == 0) { + sType = VALUE_TYPE_LTE; + eCode = SUCCESS; + } else if (sModel.find("ME910C1-NA") == 0) { + sType = VALUE_TYPE_LTE; + eCode = SUCCESS; + } else if (sModel.find("ME910C1-NV") == 0) { + sType = VALUE_TYPE_LTE; + eCode = SUCCESS; + } else if (sModel.find("ME910C1-WW") == 0) { + sType = VALUE_TYPE_LTE; + eCode = SUCCESS; + } else if (sModel.find("GE910") == 0) { + sType = VALUE_TYPE_GSM; + eCode = SUCCESS; + } else if (sModel.find("CE910") == 0) { + sType = VALUE_TYPE_CDMA; + eCode = SUCCESS; + } else if (sModel.find("DE910") == 0) { + sType = VALUE_TYPE_CDMA; + eCode = SUCCESS; + } else if (sModel.find("EG95") == 0) { + sType = VALUE_TYPE_LTE; + eCode = SUCCESS; + } else { + sType = VALUE_TYPE_GSM; + eCode = ERROR; + printError("RADIO| Could not identify type from model. [%s]. Assuming [%s]", sModel.c_str(), sType.c_str()); + } + return eCode; +} + +std::string MTS::IO::ICellularRadio::sendCommand(MTS::AutoPtr<MTS::IO::Connection>& apIo, const std::string& sCmd, + const std::vector<std::string>& vBail, int32_t timeoutMillis, const char& ESC) { + IsNeedMoreData isNeedMoreData = [&vBail](const std::string&, const std::string& allData)->bool { + for(size_t i = 0; i < vBail.size(); i++) { + const std::string& sBail = vBail[i]; + if(sBail.size() > 0) { + if(allData.find(sBail) != std::string::npos) { + //Return when bail string is found + printTrace("RADIO| Found bail string [%s]", sBail.c_str()); + return false; + } + } + } + return true; + }; + + return sendCommand(apIo, sCmd, isNeedMoreData, timeoutMillis, ESC); +} + +std::string MTS::IO::ICellularRadio::sendCommand(MTS::AutoPtr<MTS::IO::Connection>& apIo, const std::string& sCmd, + IsNeedMoreData& isNeedMoreData, int32_t timeoutMillis, const char& ESC) { + if(MTS::Logger::getPrintLevel() >= MTS::Logger::PrintLevel::TRACE_LEVEL) { + printTrace("RADIO| Sending command [%s]", sCmd.c_str()); + } + if(apIo.isNull()) { + printError("RADIO| IO is not set in sendCommand"); + return ""; + } + + int32_t iResult; + if(ESC == 0x00) { + iResult = apIo->write(sCmd.data(), sCmd.size()); + } else { + std::string sNewCmd(sCmd); + sNewCmd.push_back(ESC); + iResult = apIo->write(sNewCmd.data(), sNewCmd.size()); + } + + if(iResult == -1) { + printError("RADIO| Failed to send command to radio"); + return ""; + } + + bool done = false; + const uint32_t capacity = 1024; + char buffer[capacity]; + std::string sResult; + Timer timer; + timer.start(); + do { + int32_t iterationTimeout = 100; + int bytesRead = apIo->read((char*)buffer, capacity, iterationTimeout); + if(bytesRead == -1) { + printError("RADIO| Failed to read from radio"); + break; + } + + std::string sIteration((char*)buffer, bytesRead); + sResult += sIteration; + + if(isNeedMoreData && !isNeedMoreData(sIteration, sResult)) { + printTrace("RADIO| No more data needed"); + return sResult; + } + if(timeoutMillis >= 0) { + done = (timer.getMillis() >= (uint64_t)timeoutMillis); + } else { + //Do not stop looping until bail string is found + } + } while(!done); + + //Timed out + return sResult; +} + +MTS::IO::ICellularRadio::CODE MTS::IO::ICellularRadio::test(MTS::AutoPtr<MTS::IO::Connection>& apIo, uint32_t timeoutSeconds) { + printTrace("RADIO| Basic Test"); + uint32_t count = 0; + std::string sCmd("AT"); + do { + std::string sResult = sendCommand(apIo, sCmd); + if (sResult.find(RSP_OK) == std::string::npos) { + printTrace("RADIO| Waiting for basic radio communication [%s] ...", sResult.c_str()); + } else { + break; + } + count++; + } while (count < timeoutSeconds); + + if(count == timeoutSeconds) { + printWarning("RADIO| Basic radio communication FAILED"); + return NO_RESPONSE; + } + return SUCCESS; +} + +std::string MTS::IO::ICellularRadio::extractModelFromResult(const std::string& sResult) { + std::string sModel(VALUE_NOT_SUPPORTED); + + if(sResult.find("HE910-D") != std::string::npos) { + sModel = "HE910-D"; + } else if(sResult.find("HE910-EUD") != std::string::npos) { + sModel = "HE910-EUD"; + } else if(sResult.find("LE910-JN1") != std::string::npos) { + sModel = "LE910-JN1"; + } else if(sResult.find("LE866A1-JS") != std::string::npos) { + sModel = "LE866A1-JS"; + } else if(sResult.find("LE910-NAG") != std::string::npos) { + sModel = "LE910-NAG"; + } else if(sResult.find("LE910C4-NF") != std::string::npos) { + sModel = "LE910C4-NF"; + } else if(sResult.find("LE910-NA1") != std::string::npos) { + sModel = "LE910-NA1"; + } else if(sResult.find("ME910C1-NA") != std::string::npos) { + sModel = "ME910C1-NA"; + } else if(sResult.find("ME910C1-NV") != std::string::npos) { + sModel = "ME910C1-NV"; + } else if(sResult.find("ME910C1-WW") != std::string::npos) { + sModel = "ME910C1-WW"; + } else if(sResult.find("LE910-SVG") != std::string::npos) { + sModel = "LE910-SVG"; + } else if(sResult.find("LE910-EUG") != std::string::npos) { + sModel = "LE910-EUG"; + } else if(sResult.find("LE910C4-EU") != std::string::npos) { + sModel = "LE910C4-EU"; + } else if(sResult.find("LE910-EU1") != std::string::npos) { + sModel = "LE910-EU1"; + } else if(sResult.find("LE910C1-NS") != std::string::npos) { + sModel = "LE910C1-NS"; + } else if(sResult.find("LE910C1-AP") != std::string::npos) { + sModel = "LE910C1-AP"; + } else if(sResult.find("GE910") != std::string::npos) { + sModel = "GE910"; + } else if(sResult.find("DE910-DUAL") != std::string::npos) { + sModel = "DE910-DUAL"; + } else if(sResult.find("CE910") != std::string::npos) { + sModel = "CE910"; + } else if(sResult.find("EG95") != std::string::npos) { + sModel = "EG95"; + } + return sModel; +} + +std::string MTS::IO::ICellularRadio::getCodeAsString(CODE eCode) { + switch(eCode) { + case SUCCESS: + return "SUCCESS"; + case ERROR: + return "ERROR"; + case FAILURE: + return "FAILURE"; + case NO_RESPONSE: + return "NO RESPONSE"; + default: + return "UNKNOWN"; + } +} + diff --git a/src/MTS_IO_LE866Radio.cpp b/src/MTS_IO_LE866Radio.cpp index 2e92f67..85b8dc3 100644 --- a/src/MTS_IO_LE866Radio.cpp +++ b/src/MTS_IO_LE866Radio.cpp @@ -31,7 +31,7 @@ using namespace MTS::IO; LE866Radio::LE866Radio(const std::string& sLE866Model, const std::string& sPort) -: CellularRadio(sLE866Model, sPort) +: TelitRadio(sLE866Model, sPort) { } diff --git a/src/MTS_IO_LE910C1APRadio.cpp b/src/MTS_IO_LE910C1APRadio.cpp index 3a560fa..dca5faa 100644 --- a/src/MTS_IO_LE910C1APRadio.cpp +++ b/src/MTS_IO_LE910C1APRadio.cpp @@ -30,7 +30,7 @@ LE910C1APRadio::LE910C1APRadio(const std::string& sPort) } -CellularRadio::CODE LE910C1APRadio::getCarrier(std::string& sCarrier) { +ICellularRadio::CODE LE910C1APRadio::getCarrier(std::string& sCarrier) { sCarrier = "Sprint"; return SUCCESS; } diff --git a/src/MTS_IO_LE910C1NSRadio.cpp b/src/MTS_IO_LE910C1NSRadio.cpp index 6c403a0..907edd7 100644 --- a/src/MTS_IO_LE910C1NSRadio.cpp +++ b/src/MTS_IO_LE910C1NSRadio.cpp @@ -39,7 +39,7 @@ LE910C1NSRadio::LE910C1NSRadio(const std::string& sPort) } -CellularRadio::CODE LE910C1NSRadio::getCarrier(std::string& sCarrier) { +ICellularRadio::CODE LE910C1NSRadio::getCarrier(std::string& sCarrier) { sCarrier = "Sprint"; return SUCCESS; } diff --git a/src/MTS_IO_LE910NA1Radio.cpp b/src/MTS_IO_LE910NA1Radio.cpp index 64583b4..c7341b0 100644 --- a/src/MTS_IO_LE910NA1Radio.cpp +++ b/src/MTS_IO_LE910NA1Radio.cpp @@ -38,8 +38,8 @@ LE910NA1Radio::LE910NA1Radio(const std::string& sPort) } -CellularRadio::CODE LE910NA1Radio::setActiveFirmware(const Json::Value& jArgs) { - CellularRadio::CODE rc; +ICellularRadio::CODE LE910NA1Radio::setActiveFirmware(const Json::Value& jArgs) { + ICellularRadio::CODE rc; // Set command allows enabling a specific firmware image on products // embedding 2 different firmware images: @@ -82,9 +82,9 @@ CellularRadio::CODE LE910NA1Radio::setActiveFirmware(const Json::Value& jArgs) { return sendBasicCommand(sCmd, 5000); } -CellularRadio::CODE LE910NA1Radio::getActiveFirmware(std::string& sFwId) { +ICellularRadio::CODE LE910NA1Radio::getActiveFirmware(std::string& sFwId) { std::string sCmd; - CellularRadio::CODE rc; + ICellularRadio::CODE rc; // // Read command reports the current active firmware image: // AT#FWSWITCH? @@ -108,7 +108,7 @@ CellularRadio::CODE LE910NA1Radio::getActiveFirmware(std::string& sFwId) { sCmd = "AT#FWSWITCH?"; std::string sResult = sendCommand(sCmd); - size_t end = sResult.find(RSP_OK); + size_t end = sResult.find(ICellularRadio::RSP_OK); if (end == std::string::npos) { printWarning("%s| Unable to get active image number from radio using command [%s]", getName().c_str(), diff --git a/src/MTS_IO_LE910Radio.cpp b/src/MTS_IO_LE910Radio.cpp index 76ccae2..ea905a8 100644 --- a/src/MTS_IO_LE910Radio.cpp +++ b/src/MTS_IO_LE910Radio.cpp @@ -33,12 +33,12 @@ using namespace MTS::IO; LE910Radio::LE910Radio(const std::string& sLE910Model, const std::string& sPort) -: CellularRadio(sLE910Model, sPort) +: TelitRadio(sLE910Model, sPort) { } -CellularRadio::CODE LE910Radio::setRxDiversity(const Json::Value& jArgs) { +ICellularRadio::CODE LE910Radio::setRxDiversity(const Json::Value& jArgs) { /* Command string for LAT1,LVW2,LEU1 radios: "AT#RXDIV=" */ /* Setting needs to append ",1" to the 0/1 value */ if (jArgs["enabled"].asString() != "1" && jArgs["enabled"].asString() != "0") @@ -49,10 +49,10 @@ CellularRadio::CODE LE910Radio::setRxDiversity(const Json::Value& jArgs) { sCmd += jArgs["enabled"].asString(); sCmd += ",1"; - return CellularRadio::sendBasicCommand(sCmd); + return sendBasicCommand(sCmd); } -CellularRadio::CODE LE910Radio::getModemLocation(std::string& sLocation) { +ICellularRadio::CODE LE910Radio::getModemLocation(std::string& sLocation) { const std::string& whitespace = " \t"; printTrace("LE910Radio getModemLocation"); std::string sCmd("AT$GPSACP"); diff --git a/src/MTS_IO_LE910SVGRadio.cpp b/src/MTS_IO_LE910SVGRadio.cpp index 692350d..a43165a 100644 --- a/src/MTS_IO_LE910SVGRadio.cpp +++ b/src/MTS_IO_LE910SVGRadio.cpp @@ -39,7 +39,7 @@ LE910SVGRadio::LE910SVGRadio(const std::string& sPort) } -CellularRadio::CODE LE910SVGRadio::getCarrier(std::string& sCarrier) { +ICellularRadio::CODE LE910SVGRadio::getCarrier(std::string& sCarrier) { sCarrier = "Verizon"; return SUCCESS; } diff --git a/src/MTS_IO_ME910C1NVRadio.cpp b/src/MTS_IO_ME910C1NVRadio.cpp index e9a4874..0af5f24 100644 --- a/src/MTS_IO_ME910C1NVRadio.cpp +++ b/src/MTS_IO_ME910C1NVRadio.cpp @@ -53,13 +53,13 @@ ME910C1NVRadio::ME910C1NVRadio(const std::string& sPort) } -CellularRadio::CODE ME910C1NVRadio::getCarrier(std::string& sCarrier) { +ICellularRadio::CODE ME910C1NVRadio::getCarrier(std::string& sCarrier) { sCarrier = "Verizon"; return SUCCESS; } -CellularRadio::CODE ME910C1NVRadio::doGetFirmwareNumbers(std::string &sFirmware, std::string &sFirmwareBuild) { - CellularRadio::CODE rc = FAILURE; +ICellularRadio::CODE ME910C1NVRadio::doGetFirmwareNumbers(std::string &sFirmware, std::string &sFirmwareBuild) { + ICellularRadio::CODE rc = FAILURE; rc = getFirmware(sFirmware); if (rc != SUCCESS){ @@ -74,9 +74,9 @@ CellularRadio::CODE ME910C1NVRadio::doGetFirmwareNumbers(std::string &sFirmware, return rc; } -CellularRadio::CODE ME910C1NVRadio::doFumoReadConfig(const Json::Value& jArgs, Json::Value &jConfig) +ICellularRadio::CODE ME910C1NVRadio::doFumoReadConfig(const Json::Value& jArgs, Json::Value &jConfig) { - CellularRadio::CODE rc = INVALID_ARGS; + ICellularRadio::CODE rc = INVALID_ARGS; std::string sPath; do @@ -196,9 +196,9 @@ CellularRadio::CODE ME910C1NVRadio::doFumoReadConfig(const Json::Value& jArgs, J return rc; } -CellularRadio::CODE ME910C1NVRadio::doFumoSetup(const Json::Value &jConfig, UpdateCb& stepCb) +ICellularRadio::CODE ME910C1NVRadio::doFumoSetup(const Json::Value &jConfig, UpdateCb& stepCb) { - CellularRadio::CODE rc = FAILURE; + ICellularRadio::CODE rc = FAILURE; std::string sCmd; std::string sContextId = jConfig[KEY_FUMO_PDPID].asString(); @@ -215,7 +215,7 @@ CellularRadio::CODE ME910C1NVRadio::doFumoSetup(const Json::Value &jConfig, Upda // AT#SGACT=<cid>,<stat>[,<userId>,<pwd>] // sCmd = "AT#SGACT=" + sContextId + ",0"; - rc = CellularRadio::sendBasicCommand(sCmd); + rc = sendBasicCommand(sCmd); if (rc != SUCCESS) { if(stepCb) { stepCb(Json::Value("FUMO Error: Failed to deactivate PDP context")); @@ -244,7 +244,7 @@ CellularRadio::CODE ME910C1NVRadio::doFumoSetup(const Json::Value &jConfig, Upda if (!sApn.empty()) { sCmd += ",\"" + sApn + "\""; } - rc = CellularRadio::sendBasicCommand(sCmd, 1000); + rc = sendBasicCommand(sCmd, 1000); if (rc != SUCCESS) { if(stepCb) { stepCb(Json::Value("FUMO Error: Failed to setup PDP context")); @@ -267,7 +267,7 @@ CellularRadio::CODE ME910C1NVRadio::doFumoSetup(const Json::Value &jConfig, Upda // less than max packet size (timeout value in hundreds of milliseconds). // sCmd = "AT#SCFG=1," + sContextId + ",300,90,600,50"; - rc = CellularRadio::sendBasicCommand(sCmd); + rc = sendBasicCommand(sCmd); if (rc != SUCCESS) { if(stepCb) { stepCb(Json::Value("FUMO Error: Failed to set connection configuration parameters")); @@ -279,7 +279,7 @@ CellularRadio::CODE ME910C1NVRadio::doFumoSetup(const Json::Value &jConfig, Upda // Activate PDP context // sCmd = "AT#SGACT=" + sContextId + ",1"; - rc = CellularRadio::sendBasicCommand(sCmd, 60 * 1000); + rc = sendBasicCommand(sCmd, 60 * 1000); if (rc != SUCCESS) { if(stepCb) { stepCb(Json::Value("FUMO Error: Failed to activate PDP context")); @@ -292,9 +292,9 @@ CellularRadio::CODE ME910C1NVRadio::doFumoSetup(const Json::Value &jConfig, Upda return rc; } -CellularRadio::CODE ME910C1NVRadio::doFumoFtp(const Json::Value &jConfig, UpdateCb& stepCb) +ICellularRadio::CODE ME910C1NVRadio::doFumoFtp(const Json::Value &jConfig, UpdateCb& stepCb) { - CellularRadio::CODE rc = FAILURE; + ICellularRadio::CODE rc = FAILURE; std::string sCmd; std::string sResult; @@ -305,7 +305,7 @@ CellularRadio::CODE ME910C1NVRadio::doFumoFtp(const Json::Value &jConfig, Update // AT#FTPTO= [<tout>] // <tout> - time-out in 100 ms units // - rc = CellularRadio::sendBasicCommand("AT#FTPTO=2400"); + rc = sendBasicCommand("AT#FTPTO=2400"); if (rc != SUCCESS) { if(stepCb) { stepCb(Json::Value("FUMO Error: Failed to setup connection timeout")); @@ -322,7 +322,7 @@ CellularRadio::CODE ME910C1NVRadio::doFumoFtp(const Json::Value &jConfig, Update sCmd += "\"" + jConfig[KEY_FUMO_ADDRESS].asString() + "\","; sCmd += "\"" + jConfig[KEY_FUMO_USER].asString() + "\","; sCmd += "\"" + jConfig[KEY_FUMO_PASSWORD].asString() + "\",1"; - rc = CellularRadio::sendBasicCommand(sCmd, 60 * 1000); + rc = sendBasicCommand(sCmd, 60 * 1000); if (rc != SUCCESS) { if(stepCb) { stepCb(Json::Value("FUMO Error: Failed to open connection")); @@ -344,7 +344,7 @@ CellularRadio::CODE ME910C1NVRadio::doFumoFtp(const Json::Value &jConfig, Update // 0 - binary // 1 - ascii // - rc = CellularRadio::sendBasicCommand("AT#FTPTYPE=0", 1000); + rc = sendBasicCommand("AT#FTPTYPE=0", 1000); if (rc != SUCCESS) { if(stepCb) { stepCb(Json::Value("FUMO Error: failed to set file transfer type")); @@ -363,7 +363,7 @@ CellularRadio::CODE ME910C1NVRadio::doFumoFtp(const Json::Value &jConfig, Update sCmd += jConfig[KEY_FUMO_DIR].asString() + "/"; } sCmd += "\""; - rc = CellularRadio::sendBasicCommand(sCmd, 60 * 1000); + rc = sendBasicCommand(sCmd, 60 * 1000); if (rc != SUCCESS) { if(stepCb) { stepCb(Json::Value("FUMO Error: failed to change working directory on the server")); @@ -380,7 +380,7 @@ CellularRadio::CODE ME910C1NVRadio::doFumoFtp(const Json::Value &jConfig, Update // sCmd = "AT#FTPGETOTA="; sCmd += "\"" + jConfig[KEY_FUMO_FILE].asString() + "\",1,1"; - CellularRadio::sendBasicCommand(sCmd); + sendBasicCommand(sCmd); // // Noticed that after successful AT#FTPGETOTA the radio resets the connection. @@ -396,12 +396,12 @@ CellularRadio::CODE ME910C1NVRadio::doFumoFtp(const Json::Value &jConfig, Update { MTS::Thread::sleep(5000); - rc = CellularRadio::sendBasicCommand("AT"); + rc = sendBasicCommand("AT"); if (rc == SUCCESS) { break; } - CellularRadio::resetConnection(1); + resetConnection(1); } oTimer.stop(); @@ -419,7 +419,7 @@ CellularRadio::CODE ME910C1NVRadio::doFumoFtp(const Json::Value &jConfig, Update printTrace("RADIO| AT#FTPMSG result [%s]", sResult.c_str()); - if (sResult.find(RSP_OK) == std::string::npos) { + if (sResult.find(ICellularRadio::RSP_OK) == std::string::npos) { rc = FAILURE; if(stepCb) { stepCb(Json::Value("FUMO Error: failed to download the firmware file")); @@ -450,7 +450,7 @@ CellularRadio::CODE ME910C1NVRadio::doFumoFtp(const Json::Value &jConfig, Update // // AT#FTPCLOSE // - CellularRadio::CODE rcclose = CellularRadio::sendBasicCommand("AT#FTPCLOSE", 60 * 1000); + ICellularRadio::CODE rcclose = sendBasicCommand("AT#FTPCLOSE", 60 * 1000); if (rcclose != SUCCESS && rc == SUCCESS) { if(stepCb) { // Only one "FUMO Error" message should be sent @@ -468,9 +468,9 @@ CellularRadio::CODE ME910C1NVRadio::doFumoFtp(const Json::Value &jConfig, Update return rc; } -CellularRadio::CODE ME910C1NVRadio::doFumoCleanup(const Json::Value &jConfig, UpdateCb& stepCb) +ICellularRadio::CODE ME910C1NVRadio::doFumoCleanup(const Json::Value &jConfig, UpdateCb& stepCb) { - CellularRadio::CODE rc = FAILURE; + ICellularRadio::CODE rc = FAILURE; std::string sCmd; std::string sContextId = jConfig[KEY_FUMO_PDPID].asString(); @@ -479,7 +479,7 @@ CellularRadio::CODE ME910C1NVRadio::doFumoCleanup(const Json::Value &jConfig, Up // Deactivate PDP context // sCmd = "AT#SGACT=" + sContextId + ",0"; - rc = CellularRadio::sendBasicCommand(sCmd, 10000); + rc = sendBasicCommand(sCmd, 10000); if (rc != SUCCESS) { if(stepCb) { stepCb(Json::Value("FUMO Error: Failed to deactivate PDP context")); @@ -488,9 +488,9 @@ CellularRadio::CODE ME910C1NVRadio::doFumoCleanup(const Json::Value &jConfig, Up return rc; } -CellularRadio::CODE ME910C1NVRadio::doFumoApplyFirmware(const Json::Value &jConfig, UpdateCb& stepCb) +ICellularRadio::CODE ME910C1NVRadio::doFumoApplyFirmware(const Json::Value &jConfig, UpdateCb& stepCb) { - CellularRadio::CODE rc = FAILURE; + ICellularRadio::CODE rc = FAILURE; if (jConfig.isMember(KEY_FUMO_DRYRUN)) { if(stepCb) { @@ -499,7 +499,7 @@ CellularRadio::CODE ME910C1NVRadio::doFumoApplyFirmware(const Json::Value &jConf return SUCCESS; } - rc = CellularRadio::sendBasicCommand("AT#OTAUP=0", 10000); + rc = sendBasicCommand("AT#OTAUP=0", 10000); if (rc != SUCCESS) { if(stepCb) { stepCb(Json::Value("FUMO Error: failed to apply the firmware")); @@ -514,11 +514,11 @@ CellularRadio::CODE ME910C1NVRadio::doFumoApplyFirmware(const Json::Value &jConf return rc; } -CellularRadio::CODE ME910C1NVRadio::doFumoWaitNewFirmware(const Json::Value &jConfig, UpdateCb& stepCb) +ICellularRadio::CODE ME910C1NVRadio::doFumoWaitNewFirmware(const Json::Value &jConfig, UpdateCb& stepCb) { std::string sFirmware; std::string sFirmwareBuild; - CellularRadio::CODE rc = FAILURE; + ICellularRadio::CODE rc = FAILURE; if (jConfig.isMember(KEY_FUMO_DRYRUN)) { if(stepCb) { @@ -539,7 +539,7 @@ CellularRadio::CODE ME910C1NVRadio::doFumoWaitNewFirmware(const Json::Value &jCo if (doGetFirmwareNumbers(sFirmware, sFirmwareBuild) != SUCCESS) { // The radio is probably unavailable - CellularRadio::resetConnection(100); + resetConnection(100); continue; } @@ -570,9 +570,9 @@ CellularRadio::CODE ME910C1NVRadio::doFumoWaitNewFirmware(const Json::Value &jCo } -CellularRadio::CODE ME910C1NVRadio::doFumoPerform(const Json::Value &jConfig, UpdateCb& stepCb) +ICellularRadio::CODE ME910C1NVRadio::doFumoPerform(const Json::Value &jConfig, UpdateCb& stepCb) { - CellularRadio::CODE rc = FAILURE; + ICellularRadio::CODE rc = FAILURE; UpdateCb dummyCb; @@ -606,10 +606,10 @@ CellularRadio::CODE ME910C1NVRadio::doFumoPerform(const Json::Value &jConfig, Up return rc; } -CellularRadio::CODE ME910C1NVRadio::updateFumo(const Json::Value& jArgs, UpdateCb& stepCb) +ICellularRadio::CODE ME910C1NVRadio::updateFumo(const Json::Value& jArgs, UpdateCb& stepCb) { Json::Value jConfig(Json::objectValue); - CellularRadio::CODE rc = FAILURE; + ICellularRadio::CODE rc = FAILURE; rc = doFumoReadConfig(jArgs, jConfig); if (rc != SUCCESS) { diff --git a/src/MTS_IO_ME910C1WWRadio.cpp b/src/MTS_IO_ME910C1WWRadio.cpp index d26749a..0469d5d 100644 --- a/src/MTS_IO_ME910C1WWRadio.cpp +++ b/src/MTS_IO_ME910C1WWRadio.cpp @@ -32,8 +32,8 @@ ME910C1WWRadio::ME910C1WWRadio(const std::string& sPort) } -CellularRadio::CODE ME910C1WWRadio::setActiveFirmware(const Json::Value& jArgs) { - CellularRadio::CODE rc; +ICellularRadio::CODE ME910C1WWRadio::setActiveFirmware(const Json::Value& jArgs) { + ICellularRadio::CODE rc; // Set command allows enabling a specific firmware image on products // embedding 2 different firmware images: @@ -76,9 +76,9 @@ CellularRadio::CODE ME910C1WWRadio::setActiveFirmware(const Json::Value& jArgs) return sendBasicCommand(sCmd, 5000); } -CellularRadio::CODE ME910C1WWRadio::getActiveFirmware(std::string& sFwId) { +ICellularRadio::CODE ME910C1WWRadio::getActiveFirmware(std::string& sFwId) { std::string sCmd; - CellularRadio::CODE rc; + ICellularRadio::CODE rc; // // Read command reports the current active firmware image: // AT#FWSWITCH? @@ -101,7 +101,7 @@ CellularRadio::CODE ME910C1WWRadio::getActiveFirmware(std::string& sFwId) { sCmd = "AT#FWSWITCH?"; std::string sResult = sendCommand(sCmd); - size_t end = sResult.find(RSP_OK); + size_t end = sResult.find(ICellularRadio::RSP_OK); if (end == std::string::npos) { printWarning("%s| Unable to get active image number from radio using command [%s]", getName().c_str(), diff --git a/src/MTS_IO_ME910Radio.cpp b/src/MTS_IO_ME910Radio.cpp index 42796e9..2b181d2 100644 --- a/src/MTS_IO_ME910Radio.cpp +++ b/src/MTS_IO_ME910Radio.cpp @@ -25,22 +25,22 @@ using namespace MTS::IO; ME910Radio::ME910Radio(const std::string& sME910Model, const std::string& sPort) -: CellularRadio(sME910Model, sPort) +: TelitRadio(sME910Model, sPort) { } -CellularRadio::CODE ME910Radio::setRxDiversity(const Json::Value& jArgs) { +ICellularRadio::CODE ME910Radio::setRxDiversity(const Json::Value& jArgs) { return FAILURE; } -CellularRadio::CODE ME910Radio::getFirmwareBuild(std::string& sFirmwareBuild) { +ICellularRadio::CODE ME910Radio::getFirmwareBuild(std::string& sFirmwareBuild) { std::string sCmd("AT#CFVR"); std::string sResult = sendCommand(sCmd); - size_t end = sResult.find(RSP_OK); + size_t end = sResult.find(ICellularRadio::RSP_OK); if (end == std::string::npos) { printWarning("%s| Unable to get firmware build number [%s]", getName().c_str(), diff --git a/src/MTS_IO_QuectelRadio.cpp b/src/MTS_IO_QuectelRadio.cpp new file mode 100644 index 0000000..f3227a5 --- /dev/null +++ b/src/MTS_IO_QuectelRadio.cpp @@ -0,0 +1,612 @@ +/* + * Copyright (C) 2019 by Multi-Tech Systems + * + * This file is part of libmts-io. + * + * libmts-io is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * libmts-io is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libmts-io. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#include "mts/MTS_IO_QuectelRadio.h" + +#include <mts/MTS_Logger.h> +#include <mts/MTS_Thread.h> +#include <mts/MTS_Text.h> + +using namespace MTS::IO; + +QuectelRadio::QuectelRadio(const std::string& sName, const std::string& sRadioPort) +: CellularRadio (sName, sRadioPort) +{ +} + +bool QuectelRadio::resetRadio(uint32_t iTimeoutMillis) { + printInfo("%s| Rebooting radio", getName().c_str()); + if(sendBasicCommand("AT+CFUN=1,1") == SUCCESS) { + if(iTimeoutMillis > 5000) { + MTS::Thread::sleep(5000); + iTimeoutMillis -= 5000; + } + return resetConnection(iTimeoutMillis); + } + + return false; +} + +ICellularRadio::CODE QuectelRadio::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+GMM"); + 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 QuectelRadio::getIccid(std::string& sIccid) { + printTrace("%s| Get ICCID", getName().c_str()); + sIccid = ICellularRadio::VALUE_NOT_SUPPORTED; + + // AT+QCCID execution can take up to 300ms according to the datasheet. Setting timeout to 500ms just for sure. + std::string sCmd("AT+QCCID"); + std::string sResult = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, 500); + + size_t end = sResult.find(ICellularRadio::RSP_OK); + if (end == std::string::npos) { + printWarning("%s| Unable to get ICCID from radio using command [%s]", getName().c_str(), sCmd.c_str()); + return FAILURE; + } + + size_t start = sResult.find("+QCCID:"); + if(start != std::string::npos) { + start += sizeof("+QCCID:"); + sIccid = MTS::Text::trim(sResult.substr(start, end-start)); + if(sIccid.size() == 0) { + printWarning("%s| Unable to get ICCID from radio using command [%s]", getName().c_str(), sCmd.c_str()); + return FAILURE; + } + } + return SUCCESS; +} + +ICellularRadio::CODE QuectelRadio::getService(std::string& sService) { + printTrace("%s| Get Service", getName().c_str()); + sService = ICellularRadio::VALUE_NOT_SUPPORTED; + std::string sCmd("AT+COPS?"); + std::string sResult = sendCommand(sCmd); + size_t end = sResult.find(ICellularRadio::RSP_OK); + if (end == std::string::npos) { + printWarning("%s| Unable to get Service from radio using command [%s]", getName().c_str(), sCmd.c_str()); + return FAILURE; + } + + size_t start = sResult.find(":") + 1; //Position right after "+COPS:" + std::vector<std::string> vParts = MTS::Text::split(MTS::Text::trim(sResult.substr(start, end-start)), ','); + + 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 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 100 : sService = "CDMA" ; break; // CDMA + + default: sService = ICellularRadio::VALUE_UNKNOWN; break; + } + + printDebug("%s| Service ID: [%d][%s]", getName().c_str(), iAccessTechnology, sService.c_str()); + + return SUCCESS; +} + +ICellularRadio::CODE QuectelRadio::getNetwork(std::string& sNetwork) { + /* + * TODO: Refactor using MccMncTable once it'll be corrected. + * + * The proper way to determine the current network is to do that + * by MCC and MNC fetched from the `getNetworkStatus` and `AT+QENG` command. + * By using MCC and MNC from `AT+QENG` we can fetch the name of the network + * reported by a currently connected base station even if the SIM card is + * not installed or if we are currently working is a roaming mode. + * + * Until MccMncTable implementation is not fixed, we are using the name + * of a currently selected operator (AT+COPS). + */ + printTrace("%s| Get Network", getName().c_str()); + sNetwork = ICellularRadio::VALUE_NOT_SUPPORTED; + std::string sCmd("AT+COPS?"); + std::string sResult = sendCommand(sCmd); + size_t end = sResult.find(ICellularRadio::RSP_OK); + + if (end == std::string::npos) { + printWarning("%s| Unable to get network name from radio using command [%s]", getName().c_str(), sCmd.c_str()); + return FAILURE; + } + + // +COPS: <mode>[, <format>, <oper>,<AcT>] + // +COPS: vParts[0],vParts[1],vParts[2],vParts[3] + size_t start = sResult.find(":") + 1; //Position right after "+COPS:" + std::vector<std::string> vParts = MTS::Text::split(MTS::Text::trim(sResult.substr(start)), ","); + + if(vParts.size() > 3) { + const std::string sValue = vParts[2]; + + // +COPS: 0,0,"CHN-UNICOM UNICOM",7 + // ^start ^end + // +COPS: 0,0,"AT&T",7 + // ^st ^end + size_t start = sValue.find("\"") + 1; + size_t end = sValue.find_first_of(" \"", start); + sNetwork = sValue.substr(start, end-start); + } else { + sNetwork = ""; // Not connected to any network + } + + return SUCCESS; +} + +/* AT+QENG="servingcell" - Query the information of serving cells + + (GSM network) + +QENG:"servingscell",<state>,"GSM",<mcc>,<mnc>,<lac>,<cellid>,<bsic>,<arfcn>,<band>,<rxlev>,<txp>,<rla>,<drx>,<c1>,<c2>,<gprs>,<tch>,<ts>,<ta>,<maio>,<hsn>,<rxlevsub>,<rxlevfull>,<rxqualsub>,<rxqualfull>,<voicecodec> + + (WCDMA network) + +QENG:"servingcell",<state>,"WCDMA",<mcc>,<mnc>,<lac>,<cellid>,<uarfcn>,<psc>,<rac>,<rscp>,<ecio>,<phych>,<sf>,<slot>,<speech_code>,<comMod> + + (LTE Network) + +QENG:"servingcell",<state>,"LTE",<is_tdd>,<mcc>,<mnc>,<cellid>,<pcid>,<earfcn>,<freq_band_ind>,<ul_bandwidth>,<dl_bandwidth>,<tac>,<rsrp>,<rsrq>,<rssi>,<sinr>,<srxlev> + + The following modes are NOT currently handled: + - TD-SCDMA mode; + - CDMA mode; + - HDR mode; + - SRLTE mode. + + In the case of TD-SCDMA mode: + +QENG:"servingscell",<state>,"TDSCDMA",<mcc>,<mnc>,<lac>,<cellid>,<pfreq>,<rssi>,<rscp>,<ecio> + + In the case of CDMA mode or CDMA+HDR mode: + +QENG:"servingscell",<state>,"CDMA",<mcc>,<mnc>,<lac>,<cellid>,<bcch>,<rxpwr>,<ecio>,<txpwr> + [+QENG:"servingscell",<state>,"HDR",<mcc>,<mnc>,<lac>,<cellid>,<bcch>,<rxpwr>,<ecio>,<txpwr>] + + In the case of SRLTE mode: + +QENG:"servingscell",<state>,"CDMA",<mcc>,<mnc>,<lac>,<cellid>,<bcch>,<rxpwr>,<ecio>,<txpwr> + +QENG:"servingcell",<state>,"LTE",<is_tdd>,<mcc>,<mnc>,<cellid>,<pcid>,<earfcn>,<freq_band_ind>,<ul_bandwidth>,<dl_bandwidth>,<tac>,<rsrp>,<rsrq>,<rssi>,<sinr><srxlev> +*/ +CellularRadio::CODE QuectelRadio::getNetworkStatus(Json::Value& jData) { + const std::string RAT_GSM = "GSM"; + const std::string RAT_WCDMA = "WCDMA"; + const std::string RAT_LTE = "LTE"; + + int32_t iValue; + ACTIVEBAND abnd; + SERVICEDOMAIN sd; + std::string sValue; + std::string sRat; // Radio Access Technology which is currently used + + printTrace("%s| Get Network Status", getName().c_str()); + + //Always get common network stats because this should never fail + //This way the basic stats are always returned even if AT+QENG fails below + getCommonNetworkStats(jData); + + // IMSI is not provided by AT+QENG. Fetch it separately to keep the same interface + if (getImsi(sValue) == SUCCESS) { + jData[ICellularRadio::KEY_IMSI] = sValue; + } + + // Network Name is not explicitly provided by AT+QENG. Fetch it separately to keep the same interface + // TODO: Replace with lookup by MCC and MNC once MccMncTable is fixed. + if (getNetwork(sValue) == SUCCESS) { + jData[ICellularRadio::KEY_NETWORK] = sValue; + } + + std::string sCmd; + std::string sResult; + + sCmd = "AT+QENG=\"servingcell\""; + sResult = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, 200); + if (sResult.find("+QENG: \"servingcell\"") == std::string::npos) { + 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 SUCCESS; //return SUCCESS because getCommonNetworkStats() succeeded at top of this function + } + + size_t start = sResult.find(":") + 1; //Position right after "+QENG:" + size_t end = sResult.rfind(ICellularRadio::RSP_OK); + std::vector<std::string> vParts = MTS::Text::split(MTS::Text::trim(sResult.substr(start, end-start)), ","); + Json::Value jDebug; + 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()); + 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 { + // UE state and Access technology, Quectel-specific information + jQuectelDebug["state"] = vParts[1]; + + sRat = MTS::Text::trim(vParts[2], '"'); + jQuectelDebug["rat"] = sRat; + } + + // +QENG:"servingscell",<state>,"GSM",<mcc>,<mnc>,<lac>,<cellid>,<bsic>,<arfcn>,<band>,<rxlev>,<txp>,<rla>,<drx>,<c1>,<c2>,<gprs>,<tch>,<ts>,<ta>,<maio>,<hsn>,<rxlevsub>,<rxlevfull>,<rxqualsub>,<rxqualfull>,<voicecodec> + // +QENG: [0], [1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13],[14],[15], [16], [17],[18],[19], [20], [21], [22], [23], [24], [25], [26] + if (sRat == RAT_GSM) { + //Parse as GSM Network Format + jData[ICellularRadio::KEY_MCC] = vParts[3]; + jData[ICellularRadio::KEY_MNC] = vParts[4]; + jData[ICellularRadio::KEY_LAC] = vParts[5]; + jData[ICellularRadio::KEY_CID] = vParts[6]; + jQuectelDebug["bsic"] = vParts[7]; + jData[ICellularRadio::KEY_CHANNEL] = vParts[8]; + + if (convertToActiveBand(vParts[9], abnd) == SUCCESS && convertActiveBandToString(abnd, sValue) == SUCCESS) { + jData[ICellularRadio::KEY_ABND] = sValue; + } + + jData[ICellularRadio::KEY_RSSIDBM] = vParts[10]; // Values already negative. No need to substract 111 as stated in a datasheet + jData[ICellularRadio::KEY_TXPWR] = vParts[11]; + jQuectelDebug["rla"] = vParts[12]; + jQuectelDebug["drx"] = vParts[13]; + jQuectelDebug["c1"] = vParts[14]; + jQuectelDebug["c2"] = vParts[15]; + jQuectelDebug["gprs"] = vParts[16]; + jQuectelDebug["tch"] = vParts[17]; + jQuectelDebug["ts"] = vParts[18]; + jQuectelDebug["ta"] = vParts[19]; + jQuectelDebug["maio"] = vParts[20]; + jQuectelDebug["hsn"] = vParts[21]; + jQuectelDebug["rxlevsub"] = vParts[22]; + jQuectelDebug["rxlevfull"] = vParts[23]; + jQuectelDebug["rxqualsub"] = vParts[24]; + jQuectelDebug["rxqualfull"] = vParts[25]; + jQuectelDebug["voicecodec"] = vParts[26]; + + // Service Domain is not provided by AT+QENG. Fetch it separately to keep the same interface + if (getServiceDomain(sd) == SUCCESS && convertServiceDomainToString(sd, sValue) == SUCCESS) { + jData[ICellularRadio::KEY_SD] = sValue; + } + + // The following fields can NOT be fetched for Quectel in GSM mode: RAC, MM, RR, NOM + + jData["quectelDebug"] = jQuectelDebug; + } + + // +QENG:"servingcell",<state>,"WCDMA",<mcc>,<mnc>,<lac>,<cellid>,<uarfcn>,<psc>,<rac>,<rscp>,<ecio>,<phych>,<sf>,<slot>,<speech_code>,<comMod> + // +QENG: [0], [1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12],[13], [14], [15], [16] + else if(sRat == RAT_WCDMA) { + //Parse as WCDMA Network Format + jData[ICellularRadio::KEY_MCC] = vParts[3]; + jData[ICellularRadio::KEY_MNC] = vParts[4]; + jData[ICellularRadio::KEY_LAC] = vParts[5]; + jData[ICellularRadio::KEY_CID] = vParts[6]; + jData[ICellularRadio::KEY_CHANNEL] = vParts[7]; + jDebug[ICellularRadio::KEY_PSC] = vParts[8]; + jData[ICellularRadio::KEY_RAC] = vParts[9]; + jDebug[ICellularRadio::KEY_RSCP] = vParts[10]; + jDebug[ICellularRadio::KEY_ECIO] = vParts[11]; + jQuectelDebug["phych"] = vParts[12]; + jQuectelDebug["sf"] = vParts[13]; + jQuectelDebug["slot"] = vParts[14]; + jQuectelDebug["speechCode"] = vParts[15]; + jQuectelDebug["comMod"] = vParts[16]; + + // The following fields can NOT be fetched for Quectel in WCDMA mode: TXPWR, DRX, MM, RR, NOM, BLER + + // RSSI is not provided by AT+QENG in WCDMA mode. It was filled above by the getCommonNetworkStats + + // Service Domain is not provided by AT+QENG. Fetch it separately to keep the same interface + if (getServiceDomain(sd) == SUCCESS && convertServiceDomainToString(sd, sValue) == SUCCESS) { + jDebug[ICellularRadio::KEY_SD] = sValue; + } + + // BLER is not provided by AT+QENG. Set to constant + jDebug[ICellularRadio::KEY_BLER] = "000"; + + // Get the radio band given the channel (UARFCN) + RadioBandMap radioBandMap(vParts[7], ICellularRadio::VALUE_TYPE_CDMA); + jData[ICellularRadio::KEY_ABND] = radioBandMap.getRadioBandName(); + + jData["quectelDebug"] = jQuectelDebug; + jData[ICellularRadio::KEY_DEBUG] = jDebug; + } + + // +QENG:"servingcell",<state>,"LTE",<is_tdd>,<mcc>,<mnc>,<cellid>,<pcid>,<earfcn>,<freq_band_ind>,<ul_bandwidth>,<dl_bandwidth>,<tac>,<rsrp>,<rsrq>,<rssi>,<sinr>,<srxlev> + // +QENG: [0], [1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13], [14], [15], [16], [17] + else if(sRat == RAT_LTE) { + //Parse as LTE Network Format + jQuectelDebug["isTdd"] = vParts[3]; + jData[ICellularRadio::KEY_MCC] = vParts[4]; + jData[ICellularRadio::KEY_MNC] = vParts[5]; + jData[ICellularRadio::KEY_CID] = vParts[6]; + jQuectelDebug["pcid"] = vParts[7]; + jData[ICellularRadio::KEY_CHANNEL] = vParts[8]; + jQuectelDebug["freqBandInd"] = vParts[9]; + jQuectelDebug["ulBandwidth"] = vParts[10]; + jQuectelDebug["dlBandwidth"] = vParts[11]; + jData["tac"] = vParts[12]; + jDebug["rsrp"] = vParts[13]; + jDebug["rsrq"] = vParts[14]; + jDebug[ICellularRadio::KEY_RSSIDBM] = vParts[15]; + jQuectelDebug["sinr"] = vParts[16]; + jQuectelDebug["srxlev"] = vParts[17]; + + // Get the radio band given the channel (EARFCN) + RadioBandMap radioBandMap(vParts[8], ICellularRadio::VALUE_TYPE_LTE); + jData[ICellularRadio::KEY_ABND] = radioBandMap.getRadioBandName(); + + // Service Domain is not provided by AT+QENG. Fetch it separately to keep the same interface + if (getServiceDomain(sd) == SUCCESS && convertServiceDomainToString(sd, sValue) == SUCCESS) { + jDebug[ICellularRadio::KEY_SD] = sValue; + } + + // LAC is not provided by AT+QENG in WCDMA mode. Use another command instead + jData[ICellularRadio::KEY_LAC] = queryLteLac(); + + jData["quectelDebug"] = jQuectelDebug; + jData[ICellularRadio::KEY_DEBUG] = jDebug; + } + + printTrace("%s| Network Status:\n%s\n", getName().c_str(), jData.toStyledString().c_str()); + return SUCCESS; +} + +ICellularRadio::CODE QuectelRadio::convertSignalStrengthTodBm(const int32_t& iRssi, int32_t& iDbm) { + int dbmSteps, minValue, maxValue, rssiOffset; + int rawDbm; + + if(iRssi >= 0 && iRssi < 99) { + // normal scaling + dbmSteps = 2; + minValue = -113; + maxValue = -51; + rssiOffset = 0; + } else if(iRssi >= 100 && iRssi < 199) { + // TD-SCDMA scaling + dbmSteps = 1; + minValue = -116; + maxValue = -25; + rssiOffset = 100; + } else { + return FAILURE; // invalid, not known or not detectable + } + + rawDbm = minValue + ((iRssi - rssiOffset) * dbmSteps); + iDbm = std::min(maxValue, rawDbm); + + return SUCCESS; +} + +ICellularRadio::CODE QuectelRadio::convertdBmToSignalStrength(const int32_t& iDBm, int32_t& iRssi) { + //Quectel Conversion FOR NORMAL SCALING + 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 QuectelRadio::setMdn(const Json::Value& jArgs) { + printTrace("%s| Set MDN", getName().c_str()); + return NOT_APPLICABLE; +} + +ICellularRadio::CODE QuectelRadio::getServiceDomain(ICellularRadio::SERVICEDOMAIN& sd) { + printTrace("%s| Get Service Domain", getName().c_str()); + + std::string sCmd("AT+QCFG=\"servicedomain\""); + std::string sResult = sendCommand(sCmd); + size_t end = sResult.find(ICellularRadio::RSP_OK); + + if (end == std::string::npos) { + printWarning("%s| Unable to get service domain using command [%s]", getName().c_str(), sCmd.c_str()); + return FAILURE; + } + + // +QCFG: "servicedomain",<service> + size_t start = sResult.find(",") + 1; // Position right after comma + std::string sServiceDomain = MTS::Text::trim(sResult.substr(start, end-start)); + int iValue = -1; + + if (!MTS::Text::parse(iValue, sServiceDomain)) { + printWarning("%s| Failed to parse service domain from command output [%s]", getName().c_str(), sCmd.c_str()); + return FAILURE; + } + + switch (iValue) { + case 0: sd = SERVICEDOMAIN::CS_ONLY; break; + case 1: sd = SERVICEDOMAIN::PS_ONLY; break; + case 2: sd = SERVICEDOMAIN::CSPS; break; + + default: return FAILURE; // Unknown + } + + return SUCCESS; +} + +ICellularRadio::CODE QuectelRadio::getIsSimInserted(bool& bData) { + printTrace("%s| Get SIM insertion status", getName().c_str()); + + // AT+QSIMSTAT? execution can take up to 300ms according to the datasheet. Setting timeout to 500ms just for sure. + std::string sCmd("AT+QSIMSTAT?"); + std::string sResult = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, 500); + + const std::string sPrefix = "+QSIMSTAT: "; + size_t start = sResult.find(sPrefix); + size_t end = sResult.rfind(ICellularRadio::RSP_OK); + + if (end == std::string::npos) { + printWarning("%s| Unable to get SIM insertion status from radio using command [%s]", getName().c_str(), sCmd.c_str()); + return FAILURE; + } + + if (start == std::string::npos) { + printDebug("%s| AT+QSIMSTAT? returned unexpected response: [%s][%s]", getName().c_str(), sCmd.c_str(), sResult.c_str()); + return FAILURE; + } + + // +QSIMSTAT: <enable>,<inserted_status> + start += sPrefix.size(); + std::vector<std::string> vParts = MTS::Text::split(MTS::Text::trim(sResult.substr(start, end-start)), ','); + + if(vParts.size() != 2) { + printWarning("%s| Unable to parse SIM insertion status from response [%s]", getName().c_str(), sResult.c_str()); + return FAILURE; + } + + if (vParts[1] == "1") { // Inserted + bData = true; + } else { // Removed or Unknown, before (U)SIM initialization + bData = false; + } + + return SUCCESS; +} + +ICellularRadio::CODE QuectelRadio::getSimLockAttempts(int& iAttemptsPin, int& iAttemptsPuk) { + printTrace("%s| Get SIM unlock attempts left", getName().c_str()); + + // AT+QPINC execution can take more time that expected. Set timeout to 2s just to be sure. + std::string sCmd("AT+QPINC=\"SC\""); + std::string sResult = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, 2000); + + const std::string sPrefix = "+QPINC: \"SC\","; + size_t start = sResult.find(sPrefix); + size_t end = sResult.rfind(ICellularRadio::RSP_OK); + + if (end == std::string::npos) { + printWarning("%s| Unable to get SIM unlock attempts from radio using command [%s]", getName().c_str(), sCmd.c_str()); + return FAILURE; + } + + if (start == std::string::npos) { + printDebug("%s| AT+QPINC returned unexpected response: [%s][%s]", getName().c_str(), sCmd.c_str(), sResult.c_str()); + return FAILURE; + } + + // +QPINC: <facility>,<pincounter>,<pukcounter> + // [x] ,[0] ,[1] + start += sPrefix.size(); + std::vector<std::string> vParts = MTS::Text::split(MTS::Text::trim(sResult.substr(start, end-start)), ','); + + if(vParts.size() != 2) { + printWarning("%s| Unable to parse SIM unlock attempts left from response [%s]", getName().c_str(), sResult.c_str()); + return FAILURE; + } + + if (!MTS::Text::parse(iAttemptsPin, vParts[0])) { + printWarning("%s| Unable to parse SIM PIM unlock attempts from response [%s]", getName().c_str(), sResult.c_str()); + return FAILURE; + } + + if (!MTS::Text::parse(iAttemptsPuk, vParts[1])) { + printWarning("%s| Unable to parse SIM PUK unlock attempts from response [%s]", getName().c_str(), sResult.c_str()); + return FAILURE; + } + + return SUCCESS; +} + +ICellularRadio::CODE QuectelRadio::convertToActiveBand(const std::string& sQuectelBand, ICellularRadio::ACTIVEBAND& band) { + int iQuectelBand = -1; + + if (!MTS::Text::parse(iQuectelBand, sQuectelBand)) { + return FAILURE; // probably "-", other band + } + + switch (iQuectelBand) { + case 0: band = ACTIVEBAND::DCS_1800; break; + case 1: band = ACTIVEBAND::PCS_1900; break; + + default: return FAILURE; // actually, this case should never happen + } + + return SUCCESS; +} + +ICellularRadio::CODE QuectelRadio::getRadioNetworkMode(RADIO_NETWORK_MODE &mode) +{ + // AT+QCFG="nwscanmode" execution can take up to 300ms according to the datasheet. Setting timeout to 500ms just for sure. + std::string sCmd("AT+QCFG=\"nwscanmode\""); + std::string cmdResult = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, 500); + + if (cmdResult.find(ICellularRadio::RSP_OK) == std::string::npos) { + printDebug("%s| AT+QCFG? returned unexpected response: [%s][%s]", getName().c_str(), sCmd.c_str(), cmdResult.c_str()); + return FAILURE; + } + switch (stoi(MTS::Text::split(cmdResult, ',')[1])) { + case 1: mode = ICellularRadio::RADIO_NETWORK_MODE_GSM_ONLY; break; + case 5: mode = ICellularRadio::RADIO_NETWORK_MODE_UMTS_ONLY; break; + case 0: mode = ICellularRadio::RADIO_NETWORK_MODE_AUTO; break; + default: mode = ICellularRadio::RADIO_NETWORK_MODE_UNKNOWN; break; + } + return SUCCESS; +} + +ICellularRadio::CODE QuectelRadio::setRadioNetworkMode(RADIO_NETWORK_MODE mode) +{ + std::string value; + switch (mode) { + case ICellularRadio::RADIO_NETWORK_MODE_GSM_ONLY: value = "1"; break; + case ICellularRadio::RADIO_NETWORK_MODE_UMTS_ONLY: value = "5"; break; + case ICellularRadio::RADIO_NETWORK_MODE_AUTO: value = "0"; break; + default: return FAILURE; + } + std::string sCmd("AT+QCFG=\"nwscanmode\","); + sCmd += value; + + // AT+QCFG="nwscanmode" execution can take up to 300ms according to the datasheet. Setting timeout to 500ms just for sure. + std::string cmdResult = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, 500); + + if (cmdResult.find(ICellularRadio::RSP_OK) == std::string::npos) { + printDebug("%s| AT+QCFG? returned unexpected response: [%s][%s]", getName().c_str(), sCmd.c_str(), cmdResult.c_str()); + return FAILURE; + } + return SUCCESS; +} diff --git a/src/MTS_IO_TelitRadio.cpp b/src/MTS_IO_TelitRadio.cpp new file mode 100644 index 0000000..340c0ac --- /dev/null +++ b/src/MTS_IO_TelitRadio.cpp @@ -0,0 +1,666 @@ +/* + * Copyright (C) 2019 by Multi-Tech Systems + * + * This file is part of libmts-io. + * + * libmts-io is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * libmts-io is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libmts-io. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#include <mts/MTS_IO_TelitRadio.h> + +#include <mts/MTS_Logger.h> +#include <mts/MTS_Thread.h> +#include <mts/MTS_Text.h> + +using namespace MTS::IO; + +TelitRadio::TelitRadio(const std::string& sName, const std::string& sRadioPort) +: CellularRadio(sName, sRadioPort) +{ +} + +bool TelitRadio::resetRadio(uint32_t iTimeoutMillis) { + + printInfo("%s| Rebooting radio", getName().c_str()); + if(sendBasicCommand("AT#REBOOT") == SUCCESS) { + if(iTimeoutMillis > 5000) { + MTS::Thread::sleep(5000); + iTimeoutMillis -= 5000; + } + return resetConnection(iTimeoutMillis); + } + + return false; +} + + +ICellularRadio::CODE TelitRadio::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("ATI4"); + 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 TelitRadio::getIccid(std::string& sIccid) { + printTrace("%s| Get ICCID", getName().c_str()); + sIccid = ICellularRadio::VALUE_NOT_SUPPORTED; + std::string sCmd("AT#CCID"); + std::string sResult = CellularRadio::sendCommand(sCmd); + size_t end = sResult.find(ICellularRadio::RSP_OK); + if (end == std::string::npos) { + printWarning("%s| Unable to get ICCID from radio using command [%s]", getName().c_str(), sCmd.c_str()); + return FAILURE; + } + + size_t start = sResult.find("#CCID:"); + if(start != std::string::npos) { + start += sizeof("#CCID:"); + sIccid = MTS::Text::trim(sResult.substr(start, end-start)); + if(sIccid.size() == 0) { + printWarning("%s| Unable to get ICCID from radio using command [%s]", getName().c_str(), sCmd.c_str()); + return FAILURE; + } + } + return SUCCESS; +} + +ICellularRadio::CODE TelitRadio::getService(std::string& sService) { + printTrace("%s| Get Service", getName().c_str()); + sService = ICellularRadio::VALUE_NOT_SUPPORTED; + std::string sCmd("AT#PSNT?"); + std::string sResult = CellularRadio::sendCommand(sCmd); + size_t end = sResult.find(ICellularRadio::RSP_OK); + if (end == std::string::npos) { + printWarning("%s| Unable to get Service from radio using command [%s]", getName().c_str(), sCmd.c_str()); + return FAILURE; + } + + size_t start = sResult.find(","); + if(start != std::string::npos) { + start += 1; //comma + std::string sPsnt = MTS::Text::trim(sResult.substr(start, end-start)); + int32_t iService; + sscanf(sPsnt.c_str(), "%d", &iService); + + switch(iService) { + case 0: sService = "GPRS"; break; + case 1: sService = "EGPRS"; break; + case 2: sService = "WCDMA"; break; + case 3: sService = "HSDPA"; break; + case 4: sService = "LTE"; break; + default: sService = ICellularRadio::VALUE_UNKNOWN; break; + } + + printDebug("%s| Service ID: [%d][%s]", getName().c_str(), iService, sService.c_str()); + } + return SUCCESS; +} + +ICellularRadio::CODE TelitRadio::getNetwork(std::string& sNetwork) { + Json::Value jData; + + printTrace("%s| Get Network", getName().c_str()); + sNetwork = ICellularRadio::VALUE_NOT_SUPPORTED; + + if(getNetworkStatus(jData) == SUCCESS) { + if(jData.isMember(ICellularRadio::KEY_NETWORK)) { + sNetwork = jData[ICellularRadio::KEY_NETWORK].asString(); + return SUCCESS; + } + } + return FAILURE; +} + +/* AT#RFSTS - NETWORK STATUS + + (GSM network) + #RFSTS:<PLMN>,<ARFCN>,<RSSI>,<LAC>,<RAC>,<TXPWR>,<MM>,<RR>,<NOM>,<CID>,<IMSI>,<NetNameAsc>,<SD>,<ABND> + Where: + <PLMN> - Country code and operator code(MCC, MNC) + <ARFCN> - GSM Assigned Radio Channel + <RSSI> - Received Signal Strength Indication + <LAC> - Localization Area Code + <RAC> - Routing Area Code + <TXPWR> - Tx Power + <MM> - Mobility Management state + <RR> - Radio Resource state + <NOM> - Network Operator Mode + <CID> - Cell ID + <IMSI> - International Mobile Subscriber Identity + <NetNameAsc> - Operator name + <SD> - Service Domain + 0 - No Service + 1 - CS only + 2 - PS only + 3 - CS+PS + <ABND> - Active Band + 1 - GSM 850 + 2 - GSM 900 + 3 - DCS 1800 + 4 - PCS 1900 + + + (WCDMA network) + #RFSTS: + <PLMN>,<UARFCN>,<PSC>,<Ec/Io>,<RSCP>, RSSI>,<LAC>,<RAC>,<TXPWR>,<DRX>,<MM>,<RRC>,<NOM>,<BLER>,<CID>,<IMSI>, + <NetNameAsc>,<SD>,<nAST>[,<nUARFCN><nPSC>,<nEc/Io>] + Where: + <PLMN> - Country code and operator code(MCC, MNC) + <UARFCN> - UMTS Assigned Radio Channel + <PSC> - Active PSC(Primary Synchronization Code) + <Ec/Io> - Active Ec/Io(chip energy per total wideband power in dBm) + <RSCP> - Active RSCP (Received Signal Code Power in dBm) + <RSSI> - Received Signal Strength Indication + <LAC> - Localization Area Code + <RAC> - Routing Area Code + <TXPWR> - Tx Power + <DRX> - Discontinuous reception cycle Length (cycle length in ms) + <MM> - Mobility Management state + <RR> - Radio Resource state + <NOM> - Network Operator Mode + <BLER> - Block Error Rate (e.g., 005 means 0.5 %) + <CID> - Cell ID + <IMSI> - International Mobile Station ID + <NetNameAsc> - Operator name + <SD> - Service Domain (see above) + <nAST> - Number of Active Set (Maximum 6) + <nUARFCN> UARFCN of n th active set + <nPSC> PSC of n th active set + <nEc/Io > Ec/Io of n th active Set + + (LTE Network) + #RFSTS: + <PLMN> - + <EARFCN> - + <RSRP> - + <RSSI> - + <RSRQ> - + <TAC> - + [<TXPWR>] - + <DRX> - + <MM> - + <RRC> - + <CID> - + <IMSI> - + [<NetNameAsc>] - + <SD> - + <ABND> - +*/ +ICellularRadio::CODE TelitRadio::getNetworkStatus(Json::Value& jData) { + int32_t iValue; + std::string sValue; + const uint32_t GSM_NETWORK_FORMAT = 14; + const uint32_t WCDMA_NETWORK_FORMAT = 19; + const uint32_t LTE_NETWORK_FORMAT = 16; + + printTrace("%s| Get Network Status", getName().c_str()); + + //Always get common network stats because this should never fail + //This way the basic stats are always returned even if AT#RFSTS fails below + getCommonNetworkStats(jData); + + std::string sCmd; + std::string sResult; + // LE910 radios have a bug where issuing AT#RFSTS with a locked SIM + // will cause the radio to stop responding until a radio power cycle + // Telit Support Portal Case #5069697 + // LE910C1-NS is an LE910, so we stop the scan after the 0. + if (getName().find("LE910") != std::string::npos) { + sCmd = "AT+CPIN?"; + sResult = sendCommand(sCmd); + if (sResult.find("+CPIN:") == std::string::npos) { + printDebug("%s| AT+CPIN? returned unexpected response: [%s][%s]", 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 + } + if (sResult.find("SIM PIN") != std::string::npos) { + printError("%s| The SIM is locked and must first be unlocked", getName().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 + } + } + + sCmd = "AT#RFSTS"; + sResult = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, 200); + if (sResult.find("#RFSTS:") == std::string::npos) { + //On LTE radios without signal, this case will run because AT#RFSTS just returns "OK" + printDebug("%s| Network Status command returned unexpected response: [%s][%s]", 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 + } + + size_t start = sResult.find(":") + 1; //Position right after "#RFSTS:" + std::vector<std::string> vParts = MTS::Text::split(MTS::Text::trim(sResult.substr(start)), ","); + + if (vParts.size() < 3) { + printDebug("%s| Network Status command reponse is an unknown format: [%s][%s]", 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 { + //Country Code and Operator Code + std::vector<std::string> vPLMN = MTS::Text::split(vParts[0], ' '); + if(vPLMN.size() == 2) { + jData[ICellularRadio::KEY_MCC] = MTS::Text::strip(vPLMN[0], '"'); + jData[ICellularRadio::KEY_MNC] = MTS::Text::strip(vPLMN[1], '"'); + } + + jData[ICellularRadio::KEY_CHANNEL] = vParts[1]; + } + + if (vParts.size() == GSM_NETWORK_FORMAT ) { + //Parse as GSM Network Format + jData[ICellularRadio::KEY_RSSIDBM] = vParts[2]; + jData[ICellularRadio::KEY_LAC] = vParts[3]; + jData[ICellularRadio::KEY_RAC] = vParts[4]; + jData[ICellularRadio::KEY_TXPWR] = vParts[5]; + jData[ICellularRadio::KEY_MM] = vParts[6]; + jData[ICellularRadio::KEY_RR] = vParts[7]; + jData[ICellularRadio::KEY_NOM] = vParts[8]; + jData[ICellularRadio::KEY_CID] = vParts[9]; + jData[ICellularRadio::KEY_IMSI] = MTS::Text::strip(vParts[10], '"'); + jData[ICellularRadio::KEY_NETWORK] = MTS::Text::strip(vParts[11], '"'); + if(MTS::Text::parse(iValue, vParts[12]) && convertServiceDomainToString((SERVICEDOMAIN)iValue, sValue) == SUCCESS) { + jData[ICellularRadio::KEY_SD] = sValue; + } + if(MTS::Text::parse(iValue, vParts[13]) && convertActiveBandToString((ACTIVEBAND)iValue, sValue) == SUCCESS) { + jData[ICellularRadio::KEY_ABND] = sValue; + } + // IN003567 ME910C1 radios have some odd behavior with regards to WCDMA. The ordering of the fields from #RFSTS are + // the same as LTE up to the 16th field (for ME901C1-WW anyway). Drop into LTE parsing for ME910C1-WW. + } else if((vParts.size() >= WCDMA_NETWORK_FORMAT) && (getName().find("ME910C1-WW") == std::string::npos)) { + Json::Value jDebug; + + //Parse as WCDMA Network Format + + jDebug[ICellularRadio::KEY_PSC] = vParts[2]; + jDebug[ICellularRadio::KEY_ECIO] = vParts[3]; + jDebug[ICellularRadio::KEY_RSCP] = vParts[4]; + + jData[ICellularRadio::KEY_RSSIDBM] = vParts[5]; + jData[ICellularRadio::KEY_LAC] = vParts[6]; + jData[ICellularRadio::KEY_RAC] = vParts[7]; + + jDebug[ICellularRadio::KEY_TXPWR] = vParts[8]; + jDebug[ICellularRadio::KEY_DRX] = vParts[9]; + jDebug[ICellularRadio::KEY_MM] = vParts[10]; + jDebug[ICellularRadio::KEY_RR] = vParts[11]; + jDebug[ICellularRadio::KEY_NOM] = vParts[12]; + + if(vParts[13].size() != 0) { + jDebug[ICellularRadio::KEY_BLER] = vParts[13]; + } else { + jDebug[ICellularRadio::KEY_BLER] = "000"; + } + + jData[ICellularRadio::KEY_CID] = vParts[14]; + jData[ICellularRadio::KEY_IMSI] = MTS::Text::strip(vParts[15], '"'); + jData[ICellularRadio::KEY_NETWORK] = MTS::Text::strip(vParts[16], '"'); + + // Get the radio band given the channel (UARFCN) + RadioBandMap radioBandMap(vParts[1], CellularRadio::ICellularRadio::VALUE_TYPE_CDMA); + jData[ICellularRadio::KEY_ABND] = radioBandMap.getRadioBandName(); + + if(MTS::Text::parse(iValue, vParts[17]) && convertServiceDomainToString((SERVICEDOMAIN)iValue, sValue) == SUCCESS) { + jDebug[ICellularRadio::KEY_SD] = sValue; + } + //Ignoring Active Set Values + // <nAST> - Number of Active Set (Maximum 6) + // <nUARFCN> - UARFCN of n th active set + // <nPSC> - PSC of n th active set + // <nEc/Io > - Ec/Io of n th active Set + + jData[ICellularRadio::KEY_DEBUG] = jDebug; + } else if(vParts.size() >= LTE_NETWORK_FORMAT) { + Json::Value jDebug; + + //Parse as LTE Network Format + + // + // MD: It is noticed that LTE Network format may vary depending on the firmware version: + // + // <PLMN>,<EARFCN>,<RSRP>,<RSSI>,<RSRQ>,<TAC>,[<TXPWR>],<DRX>,<MM>,<RRC>,<CID>,<IMSI>,[<NetNameAsc>],<SD>,<ABND>,<SINR> + // Ex 1: #RFSTS: "310 260",2300,-98,-63,-14,AA06,,128,19,0,0501D02,"310260754792598","T-Mobile",3,4,197 + // + // <PLMN>,<EARFCN>,<RSRP>,<RSSI>,<RSRQ>,<TAC>,<RAC>,[<TXPWR>],<DRX>,<MM>,<RRC>,<CID>,<IMSI>,[<NetNameAsc>],<SD>,<ABND> + // Ex 2: #RFSTS:"310 410",5780,-105,-73,-14,4603,255,,128,19,0,0000098,"310410536498694","AT&T",3,17 + // #RFSTS:"311 480",1150,-96,-66,-9.0,bf35,FF,0,0,19,1,"2ED1B0E","311480148817753","Verizon",2,2,720000,10800 + // #RFSTS:"310 410",2175,-120,-89,-17.5,4612,FF,0,0,19,1,"4E5E916","310410807276607","AT&T",3,4 + // + // Additional <RAC> parameter in the second example shifts the rest of the parameters. Here we are trying to figure out + // which format is currently produced based on <NetNameAsc> field position which always has double quotation marks. + // + if (vParts[13].find("\"") != std::string::npos) { + // parse the RAC and then remove it from the vector + jData[ICellularRadio::KEY_RAC] = vParts[6]; + vParts.erase(vParts.begin() + 6); + } + + jDebug["rsrp"] = vParts[2]; + jDebug[ICellularRadio::KEY_RSSIDBM] = vParts[3]; + jDebug["rsrq"] = vParts[4]; + + jData["tac"] = vParts[5]; + jDebug[ICellularRadio::KEY_TXPWR] = vParts[6]; + jData[ICellularRadio::KEY_DRX] = vParts[7]; + jDebug[ICellularRadio::KEY_MM] = vParts[8]; + jDebug["rrc"] = vParts[9]; + jData[ICellularRadio::KEY_CID] = MTS::Text::strip(vParts[10], '"'); + jData[ICellularRadio::KEY_IMSI] = MTS::Text::strip(vParts[11], '"'); + jData[ICellularRadio::KEY_NETWORK] = MTS::Text::strip(vParts[12], '"'); + + // Get the radio band given the channel (EARFCN) + RadioBandMap radioBandMap(vParts[1], ICellularRadio::VALUE_TYPE_LTE); + jData[ICellularRadio::KEY_ABND] = radioBandMap.getRadioBandName(); + + jData[ICellularRadio::KEY_LAC] = queryLteLac(); + + if(MTS::Text::parse(iValue, vParts[13]) && convertServiceDomainToString((SERVICEDOMAIN)iValue, sValue) == SUCCESS) { + jDebug[ICellularRadio::KEY_SD] = sValue; + } + + jData[ICellularRadio::KEY_DEBUG] = jDebug; + } + + printTrace("%s| Network Status:\n%s\n", getName().c_str(), jData.toStyledString().c_str()); + return SUCCESS; +} + +ICellularRadio::CODE TelitRadio::convertSignalStrengthTodBm(const int32_t& iRssi, int32_t& iDbm) { + + //Telit Conversion + if(iRssi < 0 || iRssi == 99) { + return FAILURE; + } + + if(iRssi == 0) { + iDbm = -113; + } else if(iRssi == 1) { + iDbm = -111; + } else if(iRssi <= 30) { + //28 steps between 2 and 30 + //54 dbm between 53 and 109 + float stepSize = 54.0 / 28.0; + iDbm = -109 + (int)(stepSize * (iRssi-2)); + } else { + iDbm = -51; + } + + return SUCCESS; +} + +ICellularRadio::CODE TelitRadio::convertdBmToSignalStrength(const int32_t& iDBm, int32_t& iRssi) { + //Telit Conversion + if(iDBm <= -113) { + iRssi = 0; + } else if(iDBm <= -111) { + iRssi = 1; + } else if(iDBm <= -53) { + //54 dbm between -109 and -53 + //28 steps between 2 and 30 + float stepSize = 28.0/54.0; + iRssi = ((iDBm + 109)*stepSize) + 2; + } else { + iRssi = 31; + } + + return SUCCESS; +} + +ICellularRadio::CODE TelitRadio::setMdn(const Json::Value& jArgs) { + printTrace("%s| Set MDN", getName().c_str()); + + if(!jArgs["mdn"].isString()) { + return INVALID_ARGS; + } + + std::string sCmd("AT#SNUM=1,\""); + sCmd += jArgs["mdn"].asString() + "\""; + + std::string sResult = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, 1000); + size_t end = sResult.find(ICellularRadio::RSP_OK); + if (end == std::string::npos) { + printWarning("%s| Unable to set MDN for radio using command [%s]", getName().c_str(), sCmd.c_str()); + return FAILURE; + } + + return SUCCESS; +} + +bool TelitRadio::getCarrierFromFirmware(const std::string& sFirmware, std::string& sCarrier) { + // Telit Radios + // H.ab.zyx => 3 Main Components + // "H" = Hardware -> 15 = DE910 family, 18 = CE910 family, 12 = HE910 family + // "a" = Hardware version + // "b" = Software Major Version + // "z" = is the product type, i.e. DUAL or SC + // "y" = is the carrier variant + // "x" = is the firmware version + // Telit will do their best to keep the carrier variant as "0" for Sprint, "1" for Aeris, "2" for Verizon, and "3" for U.S. Cellular. + + const uint32_t CARRIER_INDEX = 1; //y in [zyx] + + bool bResult = false; + std::vector<std::string> vParts = MTS::Text::split(sFirmware, '.'); + + if(vParts.size() == 3) { + //CDMA firmware version notation + if(vParts[0] == "15" || vParts[0] == "18") { + //DE910 or CE910 -> Good good + std::string sID = vParts[2]; + if(sID.size() == 3) { + char cId = sID[CARRIER_INDEX]; + + //Good good + if(cId == '0') { + sCarrier = ICellularRadio::VALUE_CARRIER_SPRINT; + bResult = true; + } else + if(cId == '1') { + sCarrier = ICellularRadio::VALUE_CARRIER_AERIS; + bResult = true; + } else + if(cId == '2') { + sCarrier = ICellularRadio::VALUE_CARRIER_VERIZON; + bResult = true; + } else + if(cId == '3') { + sCarrier = ICellularRadio::VALUE_CARRIER_USCELLULAR; + bResult = true; + } + } + } + } + + return bResult; +} + +bool TelitRadio::getHardwareVersionFromFirmware(const std::string& sFirmware, std::string& sHardware) { + // Telit Radios + // H.ab.zyx => 3 Main Components + // "H" = Hardware -> 15 = DE910 family, 18 = CE910 family, 12 = HE910 family + // "a" = Hardware version + // "b" = Software Major Version + // "z" = is the product type, i.e. DUAL or SC + // "y" = is the carrier variant + // "x" = is the firmware version + // Telit will do their best to keep the carrier variant as "0" for Sprint, "1" for Aeris, and "2" for Verizon. + + const uint32_t HARDWARE_INDEX = 0; //a in [ab] + + bool bResult = false; + std::vector<std::string> vParts = MTS::Text::split(sFirmware, '.'); + + if(vParts.size() == 3) { + //GSM Hardware Version + if(!(vParts[0] == "15" || vParts[0] == "18")) { + //Not DE910 or CE910 -> Good good + std::string sVersion = vParts[1]; + if(sVersion.size() == 2) { + sHardware = "1."; + sHardware += sVersion[HARDWARE_INDEX]; + bResult = true; + } + } + } + + return bResult; + +} + +ICellularRadio::CODE TelitRadio::getRadioNetworkMode(RADIO_NETWORK_MODE &mode) +{ + std::string sCmd("AT+WS46?"); + std::string cmdResult = sendCommand(sCmd); + if (cmdResult.find("+WS46:") == std::string::npos) { + printDebug("%s| AT+WS46? returned unexpected response: [%s][%s]", getName().c_str(), sCmd.c_str(), cmdResult.c_str()); + return FAILURE; + } + switch (stoi(MTS::Text::split(cmdResult, ':')[1])) { + case 12: mode = ICellularRadio::RADIO_NETWORK_MODE_GSM_ONLY; break; + case 22: mode = ICellularRadio::RADIO_NETWORK_MODE_UMTS_ONLY; break; + case 25: mode = ICellularRadio::RADIO_NETWORK_MODE_AUTO; break; + default: mode = ICellularRadio::RADIO_NETWORK_MODE_UNKNOWN; break; + } + return SUCCESS; +} + +ICellularRadio::CODE TelitRadio::setRadioNetworkMode(RADIO_NETWORK_MODE mode) +{ + std::string value; + switch (mode) { + case ICellularRadio::RADIO_NETWORK_MODE_GSM_ONLY: value = "12"; break; + case ICellularRadio::RADIO_NETWORK_MODE_UMTS_ONLY: value = "22"; break; + case ICellularRadio::RADIO_NETWORK_MODE_AUTO: value = "25"; break; + default: return FAILURE; + } + std::string sCmd("AT+WS46="); + sCmd += value; + std::string cmdResult = sendCommand(sCmd); + if (cmdResult.find(ICellularRadio::RSP_OK) == std::string::npos) { + printDebug("%s| AT+WS46? returned unexpected response: [%s][%s]", getName().c_str(), sCmd.c_str(), cmdResult.c_str()); + return FAILURE; + } + return SUCCESS; +} + +ICellularRadio::CODE TelitRadio::getIsSimInserted(bool& bData) { + printTrace("%s| Get SIM insertion status", getName().c_str()); + std::string sCmd("AT#SIMDET?"); + std::string sResult = sendCommand(sCmd); + + const std::string sPrefix = "#SIMDET: "; + size_t start = sResult.find(sPrefix); + size_t end = sResult.rfind(ICellularRadio::RSP_OK); + + if (end == std::string::npos) { + printWarning("%s| Unable to get SIM insertion status from radio using command [%s]", getName().c_str(), sCmd.c_str()); + return FAILURE; + } + + if (start == std::string::npos) { + printDebug("%s| AT#SIMDET? returned unexpected response: [%s][%s]", getName().c_str(), sCmd.c_str(), sResult.c_str()); + return FAILURE; + } + + // #SIMDET: <mode>,<simin> + start += sPrefix.size(); + std::vector<std::string> vParts = MTS::Text::split(MTS::Text::trim(sResult.substr(start, end-start)), ','); + + if(vParts.size() != 2) { + printWarning("%s| Unable to parse SIM insertion status from response [%s]", getName().c_str(), sResult.c_str()); + return FAILURE; + } + + if (vParts[1] == "1") { // <simin> + bData = true; + } else { + bData = false; + } + + return SUCCESS; +} + +ICellularRadio::CODE TelitRadio::getSimLockAttempts(int& iAttemptsPin, int& iAttemptsPuk) { + std::string sLockStatus; + ICellularRadio::CODE retCode; + + retCode = getSimLockStatus(sLockStatus); + if (retCode != SUCCESS) { + printWarning("%s| Unable determine the number of SIM unlock attempts: SIM lock status is unavailable [%s]", getName().c_str(), sLockStatus.c_str()); + return retCode; + } + + return getSimLockAttempts(iAttemptsPin, iAttemptsPuk, sLockStatus); +} + +ICellularRadio::CODE TelitRadio::getSimLockAttempts(int& iAttemptsPin, int& iAttemptsPuk, const std::string& sLockStatus) { + printTrace("%s| Get SIM unlock attempts left", getName().c_str()); + std::string sCmd("AT#PCT"); + std::string sResult = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, 500); + std::string sValue; + int iValue; + + const std::string sPrefix = "#PCT: "; + size_t start = sResult.find(sPrefix); + size_t end = sResult.rfind(ICellularRadio::RSP_OK); + + if (end == std::string::npos) { + printWarning("%s| Unable to get SIM unlock attempts from radio using command [%s]", getName().c_str(), sCmd.c_str()); + return FAILURE; + } + + if (start == std::string::npos) { + printDebug("%s| AT#PCT? returned unexpected response: [%s][%s]", getName().c_str(), sCmd.c_str(), sResult.c_str()); + return FAILURE; + } + + // #PCT: <n> + start += sPrefix.size(); + sValue = MTS::Text::trim(sResult.substr(start, end-start)); + + if (!MTS::Text::parse(iValue, sValue)) { + printWarning("%s| Unable to parse SIM unlock attempts from response [%s]", getName().c_str(), sResult.c_str()); + return FAILURE; + } + + if (sLockStatus == "READY" || sLockStatus == "SIM PIN") { + iAttemptsPin = iValue; // Some PIN attempts left, maximum PUK attempts left + iAttemptsPuk = 10; + } else { + iAttemptsPin = 0; // No PIN attempts left + iAttemptsPuk = iValue; + } + + return SUCCESS; +} |