/*
* Copyright (C) 2015 by Multi-Tech Systems
*
* This file is part of libmts-io.
*
* libmts-io is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* libmts-io is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with libmts-io. If not, see .
*
*/
/*!
\file MTS_IO_LE910Radio.cpp
\brief A brief description
\date Nov 6, 2014
\author sgodinez
A more elaborate description
*/
#include
#include
#include
using namespace MTS::IO;
LE910Radio::LE910Radio(const std::string& sLE910Model, const std::string& sPort)
: TelitRadio(sLE910Model, sPort)
{
}
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")
{
return FAILURE;
}
std::string sCmd = "AT#RXDIV=";
sCmd += jArgs["enabled"].asString();
sCmd += ",1";
return sendBasicCommand(sCmd);
}
ICellularRadio::CODE LE910Radio::getModemLocation(std::string& sLocation) {
const std::string& whitespace = " \t";
printTrace("LE910Radio getModemLocation");
std::string sCmd("AT$GPSACP");
std::string sResult = sendCommand(sCmd);
if (sResult.find("$GPSACP: ") == std::string::npos) {
printDebug("AT$GPSACP command returned unexpected response: [%s]", sResult.c_str());
return FAILURE;
}
printDebug("modem reply: [%s]", sResult.c_str());
size_t start = sResult.find(':');
if (start==std::string::npos) {
start = 0;
} else {
start++;
}
start = sResult.find_first_not_of(whitespace, start);
size_t stop = sResult.find('\n', start);
sLocation = sResult.substr(start, stop - start - 1);
printDebug("function reply: [%s]", sLocation.c_str());
return SUCCESS;
}
ICellularRadio::CODE LE910Radio::setUeModeOfOperation(ICellularRadio::UE_MODES_OF_OPERATION mode) {
printTrace("%s| Set UE Mode Of Operation", getName().c_str());
std::string sValue;
switch (mode) {
case ICellularRadio::UE_MODES_OF_OPERATION::PS_MODE1:
sValue = "3";
break;
case ICellularRadio::UE_MODES_OF_OPERATION::PS_MODE2:
sValue = "0";
break;
case ICellularRadio::UE_MODES_OF_OPERATION::CS_PS_MODE1:
sValue = "1";
break;
case ICellularRadio::UE_MODES_OF_OPERATION::CS_PS_MODE2:
sValue = "2";
break;
default:
printError("%s| Set UE Mode Of Operation: invalid argument", getName().c_str());
return INVALID_ARGS;
}
const int dTimeout = 1000; // ms
const std::string sCommand = "AT+CEMODE=" + sValue;
return sendBasicCommand(sCommand, dTimeout);
}
ICellularRadio::CODE LE910Radio::getUeModeOfOperation(ICellularRadio::UE_MODES_OF_OPERATION& mode) {
printTrace("%s| Get UE Mode Of Operation", getName().c_str());
const std::string sCommand = "AT+CEMODE?";
const int dTimeout = 1000; // ms
std::string sResult = sendCommand(sCommand, ICellularRadio::DEFAULT_BAIL_STRINGS, dTimeout);
printTrace("%s| Got response from the radio: %s", getName().c_str(), sResult.c_str());
size_t end = sResult.rfind(ICellularRadio::RSP_OK);
if (std::string::npos == end) {
printError("%s| Unable to get UE Mode Of Operation from radio using command [%s]", getName().c_str(), sCommand.c_str());
return FAILURE;
}
const std::string sLabel = "+CEMODE: ";
size_t start = sResult.find(sLabel);
if (std::string::npos == start) {
printError("%s| Unable to get UE Mode Of Operation from radio using command [%s]", getName().c_str(), sCommand.c_str());
return FAILURE;
}
start += sLabel.length();
const std::string sValue = MTS::Text::trim(sResult.substr(start, end - start));
uint8_t uiValue;
if (!MTS::Text::parse(uiValue, sValue)) {
printError("%s| Unable to parse CEMODE from response [%s]", getName().c_str(), sResult.c_str());
return FAILURE;
}
CODE rc;
switch (uiValue) {
case 0:
mode = ICellularRadio::UE_MODES_OF_OPERATION::PS_MODE2;
rc = SUCCESS;
break;
case 1:
mode = ICellularRadio::UE_MODES_OF_OPERATION::CS_PS_MODE1;
rc = SUCCESS;
break;
case 2:
mode = ICellularRadio::UE_MODES_OF_OPERATION::CS_PS_MODE2;
rc = SUCCESS;
break;
case 3:
mode = ICellularRadio::UE_MODES_OF_OPERATION::PS_MODE1;
rc = SUCCESS;
break;
default:
printError("%s| Unable to parse CEMODE from response [%s]", getName().c_str(), sResult.c_str());
mode = ICellularRadio::UE_MODES_OF_OPERATION::UNKNOWN_MODE;
rc = FAILURE;
break;
}
return rc;
}
const std::vector& LE910Radio::getDiagCommands(bool bIsSimReady) {
// Declare as static to initialize only when used, but cache the results.
const static std::vector vCommands {
// Radio model and firmware:
"AT+CGMI", "AT+CGMM", "AT+CGMR", "AT#SWPKGV", "AT#CFVR",
// All carrier profiles that are supported:
"AT#FWSWITCH=?",
// Current operator profile on the radio side:
"AT#FWSWITCH?", "AT+CGSN",
// SIM card information:
"AT#SIMDET?", "AT#CCID", "AT+CPIN?", "AT#PCT",
// Operating mode of the radio:
"AT+CFUN?",
// Low-level network settings:
"AT+WS46?", "AT#RXDIV", "AT#CALLDISA?", "AT+CEMODE?",
// Data connection configuration:
"AT+CGDCONT?", "AT#PDPAUTH?",
// Registration and connection to the tower:
"AT+CIND?", "AT+CSQ", "AT+COPS?", "AT+CREG?", "AT+CGREG?", "AT+CEREG?",
"AT#RFSTS", "AT#PSNT?", "AT#MONI",
// Data connection status:
"AT+CGACT?", "AT+CGCONTRDP=1", "AT+CGCONTRDP=2", "AT+CGCONTRDP=3"
};
const static std::vector vSimLockedCommands {
// Radio model and firmware:
"AT+CGMI", "AT+CGMM", "AT+CGMR", "AT#SWPKGV", "AT#CFVR",
// All carrier profiles that are supported:
"AT#FWSWITCH=?",
// Current operator profile on the radio side:
"AT#FWSWITCH?", "AT+CGSN",
// SIM card information:
"AT#SIMDET?", "AT#CCID", "AT+CPIN?", "AT#PCT",
// Operating mode of the radio:
"AT+CFUN?",
// Low-level network settings:
"AT+WS46?", "AT#RXDIV", "AT#CALLDISA?", "AT+CEMODE?",
// Data connection configuration:
"AT+CGDCONT?", "AT#PDPAUTH?",
// Registration and connection to the tower.
// The same set of commands, but AT#RFSTS is replaced with a dummy command.
"AT+CIND?", "AT+CSQ", "AT+COPS?", "AT+CREG?", "AT+CGREG?", "AT+CEREG?",
"AT#RFSTS_IGNORED", "AT#PSNT?", "AT#MONI",
// Data connection status:
"AT+CGACT?", "AT+CGCONTRDP=1", "AT+CGCONTRDP=2", "AT+CGCONTRDP=3"
};
// Ignore AT#RFSTS on LE910 radios (mostly legacy ones like LAT1 and LEU1) if
// the SIM card is locked by PIN or PUK. Telit Support Portal Case #5069697.
if (bIsSimReady) {
return vCommands;
} else {
return vSimLockedCommands;
}
}
const std::vector LE910Radio::getRegistrationCommands() {
return { "CREG", "CGREG", "CEREG" };
}