mirror of https://github.com/ARMmbed/mbed-os.git
697 lines
20 KiB
C++
697 lines
20 KiB
C++
/*
|
|
* Copyright (c) 2017, Arm Limited and affiliates.
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include "AT_CellularNetwork.h"
|
|
#include "CellularUtil.h"
|
|
#include "CellularLog.h"
|
|
#include "CellularCommon.h"
|
|
|
|
using namespace std;
|
|
using namespace mbed_cellular_util;
|
|
using namespace mbed;
|
|
|
|
struct at_reg_t {
|
|
const CellularNetwork::RegistrationType type;
|
|
const char *const cmd;
|
|
const char *const urc_prefix;
|
|
};
|
|
|
|
static const at_reg_t at_reg[] = {
|
|
{ CellularNetwork::C_EREG, "AT+CEREG", "+CEREG:"},
|
|
{ CellularNetwork::C_GREG, "AT+CGREG", "+CGREG:"},
|
|
{ CellularNetwork::C_REG, "AT+CREG", "+CREG:"}
|
|
};
|
|
|
|
#if MBED_CONF_MBED_TRACE_ENABLE
|
|
static const char *const reg_type_str[(int)AT_CellularNetwork::RegistrationStatusMax] = {
|
|
"NotRegistered",
|
|
"RegisteredHomeNetwork",
|
|
"SearchingNetwork",
|
|
"RegistrationDenied",
|
|
"RegistrationUnknown",
|
|
"RegisteredRoaming",
|
|
"RegisteredSMSOnlyHome",
|
|
"RegisteredSMSOnlyRoaming",
|
|
"AttachedEmergencyOnly",
|
|
"RegisteredCSFBNotPreferredHome",
|
|
"RegisteredCSFBNotPreferredRoaming",
|
|
"AlreadyRegistered"
|
|
};
|
|
|
|
static const char *const rat_str[AT_CellularNetwork::RAT_MAX] = {
|
|
"GSM",
|
|
"GSM_COMPACT",
|
|
"UTRAN",
|
|
"EGPRS",
|
|
"HSDPA",
|
|
"HSUPA",
|
|
"HSDPA_HSUPA",
|
|
"E_UTRAN",
|
|
"CATM1",
|
|
"NB1",
|
|
"RAT unknown",
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
AT_CellularNetwork::AT_CellularNetwork(ATHandler &atHandler) : AT_CellularBase(atHandler),
|
|
_connection_status_cb(NULL), _ciotopt_network_support_cb(NULL), _op_act(RAT_UNKNOWN),
|
|
_connect_status(NSAPI_STATUS_DISCONNECTED), _supported_network_opt(CIOT_OPT_MAX)
|
|
{
|
|
|
|
_urc_funcs[C_EREG] = callback(this, &AT_CellularNetwork::urc_cereg);
|
|
_urc_funcs[C_GREG] = callback(this, &AT_CellularNetwork::urc_cgreg);
|
|
_urc_funcs[C_REG] = callback(this, &AT_CellularNetwork::urc_creg);
|
|
|
|
for (int type = 0; type < CellularNetwork::C_MAX; type++) {
|
|
if (get_property((AT_CellularBase::CellularProperty)type) != RegistrationModeDisable) {
|
|
_at.set_urc_handler(at_reg[type].urc_prefix, _urc_funcs[type]);
|
|
}
|
|
}
|
|
|
|
if (get_property(AT_CellularBase::PROPERTY_AT_CGEREP)) {
|
|
// additional urc to get better disconnect info for application. Not critical.
|
|
_at.set_urc_handler("+CGEV: NW DET", callback(this, &AT_CellularNetwork::urc_cgev));
|
|
_at.set_urc_handler("+CGEV: ME DET", callback(this, &AT_CellularNetwork::urc_cgev));
|
|
}
|
|
|
|
|
|
_at.set_urc_handler("+CCIOTOPTI:", callback(this, &AT_CellularNetwork::urc_cciotopti));
|
|
}
|
|
|
|
AT_CellularNetwork::~AT_CellularNetwork()
|
|
{
|
|
(void)set_packet_domain_event_reporting(false);
|
|
for (int type = 0; type < CellularNetwork::C_MAX; type++) {
|
|
if (get_property((AT_CellularBase::CellularProperty)type) != RegistrationModeDisable) {
|
|
_at.set_urc_handler(at_reg[type].urc_prefix, 0);
|
|
}
|
|
}
|
|
|
|
if (get_property(AT_CellularBase::PROPERTY_AT_CGEREP)) {
|
|
_at.set_urc_handler("+CGEV: ME DET", 0);
|
|
_at.set_urc_handler("+CGEV: NW DET", 0);
|
|
}
|
|
_at.set_urc_handler("+CCIOTOPTI:", 0);
|
|
}
|
|
|
|
void AT_CellularNetwork::urc_cgev()
|
|
{
|
|
call_network_cb(NSAPI_STATUS_DISCONNECTED);
|
|
}
|
|
|
|
void AT_CellularNetwork::read_reg_params_and_compare(RegistrationType type)
|
|
{
|
|
registration_params_t reg_params;
|
|
read_reg_params(type, reg_params);
|
|
|
|
if (_at.get_last_error() == NSAPI_ERROR_OK && _connection_status_cb) {
|
|
_reg_params._type = type;
|
|
cell_callback_data_t data;
|
|
data.error = NSAPI_ERROR_OK;
|
|
if (reg_params._act != _reg_params._act) {
|
|
_reg_params._act = reg_params._act;
|
|
data.status_data = reg_params._act;
|
|
_connection_status_cb((nsapi_event_t)CellularRadioAccessTechnologyChanged, (intptr_t)&data);
|
|
}
|
|
if (reg_params._status != _reg_params._status) {
|
|
RegistrationStatus previous_registration_status = _reg_params._status;
|
|
_reg_params._status = reg_params._status;
|
|
data.status_data = reg_params._status;
|
|
_connection_status_cb((nsapi_event_t)CellularRegistrationStatusChanged, (intptr_t)&data);
|
|
if (reg_params._status == NotRegistered) { // Other states means that we are trying to connect or connected
|
|
if (previous_registration_status == RegisteredHomeNetwork ||
|
|
previous_registration_status == RegisteredRoaming) {
|
|
if (type != C_REG) {// we are interested only if we drop from packet network
|
|
_connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_DISCONNECTED);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (reg_params._cell_id != -1 && reg_params._cell_id != _reg_params._cell_id) {
|
|
_reg_params._cell_id = reg_params._cell_id;
|
|
_reg_params._lac = reg_params._lac;
|
|
data.status_data = reg_params._cell_id;
|
|
_connection_status_cb((nsapi_event_t)CellularCellIDChanged, (intptr_t)&data);
|
|
}
|
|
}
|
|
}
|
|
|
|
void AT_CellularNetwork::urc_creg()
|
|
{
|
|
read_reg_params_and_compare(C_REG);
|
|
}
|
|
|
|
void AT_CellularNetwork::urc_cereg()
|
|
{
|
|
read_reg_params_and_compare(C_EREG);
|
|
}
|
|
|
|
void AT_CellularNetwork::urc_cgreg()
|
|
{
|
|
read_reg_params_and_compare(C_GREG);
|
|
}
|
|
|
|
void AT_CellularNetwork::call_network_cb(nsapi_connection_status_t status)
|
|
{
|
|
if (_connection_status_cb) {
|
|
_connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, _connect_status);
|
|
}
|
|
}
|
|
|
|
void AT_CellularNetwork::attach(Callback<void(nsapi_event_t, intptr_t)> status_cb)
|
|
{
|
|
_connection_status_cb = status_cb;
|
|
}
|
|
|
|
nsapi_error_t AT_CellularNetwork::set_registration_urc(RegistrationType type, bool urc_on)
|
|
{
|
|
int index = (int)type;
|
|
MBED_ASSERT(index >= 0 && index < C_MAX);
|
|
|
|
RegistrationMode mode = (RegistrationMode)get_property((AT_CellularBase::CellularProperty)type);
|
|
if (mode == RegistrationModeDisable) {
|
|
return NSAPI_ERROR_UNSUPPORTED;
|
|
} else {
|
|
_at.lock();
|
|
if (urc_on) {
|
|
_at.cmd_start(at_reg[index].cmd);
|
|
const uint8_t ch_eq = '=';
|
|
_at.write_bytes(&ch_eq, 1);
|
|
_at.write_int((int)mode);
|
|
} else {
|
|
_at.cmd_start(at_reg[index].cmd);
|
|
_at.write_string("=0", false);
|
|
}
|
|
|
|
_at.cmd_stop_read_resp();
|
|
return _at.unlock_return_error();
|
|
}
|
|
}
|
|
|
|
nsapi_error_t AT_CellularNetwork::get_network_registering_mode(NWRegisteringMode &mode)
|
|
{
|
|
_at.lock();
|
|
_at.cmd_start("AT+COPS?");
|
|
_at.cmd_stop();
|
|
_at.resp_start("+COPS:");
|
|
mode = (NWRegisteringMode)_at.read_int();
|
|
_at.resp_stop();
|
|
|
|
return _at.unlock_return_error();
|
|
}
|
|
|
|
nsapi_error_t AT_CellularNetwork::set_registration(const char *plmn)
|
|
{
|
|
_at.lock();
|
|
|
|
if (!plmn) {
|
|
tr_debug("Automatic network registration");
|
|
_at.cmd_start("AT+COPS?");
|
|
_at.cmd_stop();
|
|
_at.resp_start("+COPS:");
|
|
int mode = _at.read_int();
|
|
_at.resp_stop();
|
|
if (mode != 0) {
|
|
_at.clear_error();
|
|
_at.cmd_start("AT+COPS=0");
|
|
_at.cmd_stop_read_resp();
|
|
}
|
|
} else {
|
|
tr_debug("Manual network registration to %s", plmn);
|
|
_at.cmd_start("AT+COPS=1,2,");
|
|
_at.write_string(plmn);
|
|
if (_op_act != RAT_UNKNOWN) {
|
|
_at.write_int(_op_act);
|
|
}
|
|
_at.cmd_stop_read_resp();
|
|
}
|
|
|
|
return _at.unlock_return_error();
|
|
}
|
|
|
|
void AT_CellularNetwork::read_reg_params(RegistrationType type, registration_params_t ®_params)
|
|
{
|
|
const int MAX_STRING_LENGTH = 9;
|
|
char string_param[MAX_STRING_LENGTH] = {0};
|
|
|
|
reg_params._type = type;
|
|
|
|
int int_param = _at.read_int();
|
|
reg_params._status = (int_param >= 0 && int_param < RegistrationStatusMax) ? (RegistrationStatus)int_param : NotRegistered;
|
|
|
|
int len = _at.read_string(string_param, TWO_BYTES_HEX + 1);
|
|
if (len > 0) {
|
|
reg_params._lac = hex_str_to_int(string_param, TWO_BYTES_HEX);
|
|
} else {
|
|
reg_params._lac = -1;
|
|
}
|
|
|
|
len = _at.read_string(string_param, FOUR_BYTES_HEX + 1);
|
|
if (len > 0) {
|
|
reg_params._cell_id = hex_str_to_int(string_param, FOUR_BYTES_HEX);
|
|
} else {
|
|
reg_params._cell_id = -1;
|
|
}
|
|
|
|
int_param = _at.read_int();
|
|
reg_params._act = (int_param >= 0 && int_param < RAT_MAX) ? (RadioAccessTechnology)int_param : RAT_UNKNOWN ;
|
|
|
|
// Skip [<cause_type>],[<reject_cause>]
|
|
_at.skip_param(2);
|
|
|
|
len = _at.read_string(string_param, ONE_BYTE_BINARY + 1);
|
|
reg_params._active_time = calculate_active_time(string_param, len);
|
|
|
|
len = _at.read_string(string_param, ONE_BYTE_BINARY + 1);
|
|
reg_params._periodic_tau = calculate_periodic_tau(string_param, len);
|
|
|
|
#if MBED_CONF_MBED_TRACE_ENABLE
|
|
tr_debug("%s %s, LAC %d, cell %d, %s", at_reg[(int)type].urc_prefix, reg_type_str[reg_params._status], reg_params._lac, reg_params._cell_id, rat_str[reg_params._act]);
|
|
#endif
|
|
}
|
|
|
|
nsapi_error_t AT_CellularNetwork::set_attach()
|
|
{
|
|
_at.lock();
|
|
|
|
_at.cmd_start("AT+CGATT?");
|
|
_at.cmd_stop();
|
|
_at.resp_start("+CGATT:");
|
|
int attached_state = _at.read_int();
|
|
_at.resp_stop();
|
|
if (attached_state != 1) {
|
|
tr_debug("Network attach");
|
|
_at.cmd_start("AT+CGATT=1");
|
|
_at.cmd_stop_read_resp();
|
|
}
|
|
|
|
return _at.unlock_return_error();
|
|
}
|
|
|
|
nsapi_error_t AT_CellularNetwork::get_attach(AttachStatus &status)
|
|
{
|
|
_at.lock();
|
|
|
|
_at.cmd_start("AT+CGATT?");
|
|
_at.cmd_stop();
|
|
|
|
_at.resp_start("+CGATT:");
|
|
if (_at.info_resp()) {
|
|
int attach_status = _at.read_int();
|
|
status = (attach_status == 1) ? Attached : Detached;
|
|
}
|
|
_at.resp_stop();
|
|
|
|
return _at.unlock_return_error();
|
|
}
|
|
|
|
nsapi_error_t AT_CellularNetwork::detach()
|
|
{
|
|
_at.lock();
|
|
|
|
tr_debug("Network detach");
|
|
_at.cmd_start("AT+CGATT=0");
|
|
_at.cmd_stop_read_resp();
|
|
|
|
_at.cmd_start("AT+COPS=2");
|
|
_at.cmd_stop_read_resp();
|
|
|
|
call_network_cb(NSAPI_STATUS_DISCONNECTED);
|
|
|
|
return _at.unlock_return_error();
|
|
}
|
|
|
|
nsapi_error_t AT_CellularNetwork::set_access_technology_impl(RadioAccessTechnology opsAct)
|
|
{
|
|
_op_act = RAT_UNKNOWN;
|
|
return NSAPI_ERROR_UNSUPPORTED;
|
|
}
|
|
|
|
nsapi_error_t AT_CellularNetwork::set_access_technology(RadioAccessTechnology opAct)
|
|
{
|
|
if (opAct == RAT_UNKNOWN) {
|
|
return NSAPI_ERROR_UNSUPPORTED;
|
|
}
|
|
|
|
_op_act = opAct;
|
|
|
|
return set_access_technology_impl(opAct);
|
|
}
|
|
|
|
nsapi_error_t AT_CellularNetwork::scan_plmn(operList_t &operators, int &opsCount)
|
|
{
|
|
int idx = 0;
|
|
|
|
_at.lock();
|
|
|
|
_at.cmd_start("AT+COPS=?");
|
|
_at.cmd_stop();
|
|
|
|
_at.resp_start("+COPS:");
|
|
|
|
int ret, error_code = -1;
|
|
operator_t *op = NULL;
|
|
|
|
while (_at.info_elem('(')) {
|
|
|
|
op = operators.add_new();
|
|
op->op_status = (operator_t::Status)_at.read_int();
|
|
_at.read_string(op->op_long, sizeof(op->op_long));
|
|
_at.read_string(op->op_short, sizeof(op->op_short));
|
|
_at.read_string(op->op_num, sizeof(op->op_num));
|
|
|
|
// Optional - try read an int
|
|
ret = _at.read_int();
|
|
op->op_rat = (ret == error_code) ? RAT_UNKNOWN : (RadioAccessTechnology)ret;
|
|
|
|
if ((_op_act == RAT_UNKNOWN) ||
|
|
((op->op_rat != RAT_UNKNOWN) && (op->op_rat == _op_act))) {
|
|
idx++;
|
|
} else {
|
|
operators.delete_last();
|
|
}
|
|
}
|
|
|
|
_at.resp_stop();
|
|
|
|
opsCount = idx;
|
|
return _at.unlock_return_error();
|
|
}
|
|
|
|
nsapi_error_t AT_CellularNetwork::set_ciot_optimization_config(CIoT_Supported_Opt supported_opt,
|
|
CIoT_Preferred_UE_Opt preferred_opt,
|
|
Callback<void(CIoT_Supported_Opt)> network_support_cb)
|
|
{
|
|
_ciotopt_network_support_cb = network_support_cb;
|
|
_at.lock();
|
|
|
|
_at.cmd_start("AT+CCIOTOPT=");
|
|
_at.write_int(1); //enable CCIOTOPTI URC
|
|
_at.write_int(supported_opt);
|
|
_at.write_int(preferred_opt);
|
|
_at.cmd_stop_read_resp();
|
|
|
|
return _at.unlock_return_error();
|
|
}
|
|
|
|
void AT_CellularNetwork::urc_cciotopti()
|
|
{
|
|
_supported_network_opt = (CIoT_Supported_Opt)_at.read_int();
|
|
|
|
if (_ciotopt_network_support_cb) {
|
|
_ciotopt_network_support_cb(_supported_network_opt);
|
|
}
|
|
}
|
|
|
|
nsapi_error_t AT_CellularNetwork::get_ciot_ue_optimization_config(CIoT_Supported_Opt &supported_opt,
|
|
CIoT_Preferred_UE_Opt &preferred_opt)
|
|
{
|
|
_at.lock();
|
|
|
|
_at.cmd_start("AT+CCIOTOPT?");
|
|
_at.cmd_stop();
|
|
|
|
_at.resp_start("+CCIOTOPT:");
|
|
_at.read_int();
|
|
if (_at.get_last_error() == NSAPI_ERROR_OK) {
|
|
supported_opt = (CIoT_Supported_Opt)_at.read_int();
|
|
preferred_opt = (CIoT_Preferred_UE_Opt)_at.read_int();
|
|
}
|
|
|
|
_at.resp_stop();
|
|
|
|
return _at.unlock_return_error();
|
|
}
|
|
|
|
nsapi_error_t AT_CellularNetwork::get_ciot_network_optimization_config(CIoT_Supported_Opt &supported_network_opt)
|
|
{
|
|
supported_network_opt = _supported_network_opt;
|
|
return NSAPI_ERROR_OK;
|
|
}
|
|
|
|
nsapi_error_t AT_CellularNetwork::get_signal_quality(int &rssi, int *ber)
|
|
{
|
|
_at.lock();
|
|
|
|
_at.cmd_start("AT+CSQ");
|
|
_at.cmd_stop();
|
|
|
|
_at.resp_start("+CSQ:");
|
|
int t_rssi = _at.read_int();
|
|
int t_ber = _at.read_int();
|
|
_at.resp_stop();
|
|
if (t_rssi < 0 || t_ber < 0) {
|
|
_at.unlock();
|
|
return NSAPI_ERROR_DEVICE_ERROR;
|
|
}
|
|
|
|
// RSSI value is returned in dBm with range from -51 to -113 dBm, see 3GPP TS 27.007
|
|
if (t_rssi == 99) {
|
|
rssi = SignalQualityUnknown;
|
|
} else {
|
|
rssi = -113 + 2 * t_rssi;
|
|
}
|
|
|
|
if (ber) {
|
|
if (t_ber == 99) {
|
|
*ber = SignalQualityUnknown;
|
|
} else {
|
|
*ber = t_ber;
|
|
}
|
|
}
|
|
|
|
return _at.unlock_return_error();
|
|
}
|
|
|
|
/** Get the last 3GPP error code
|
|
* @return see 3GPP TS 27.007 error codes
|
|
*/
|
|
int AT_CellularNetwork::get_3gpp_error()
|
|
{
|
|
return _at.get_3gpp_error();
|
|
}
|
|
|
|
nsapi_error_t AT_CellularNetwork::get_operator_params(int &format, operator_t &operator_params)
|
|
{
|
|
_at.lock();
|
|
|
|
_at.cmd_start("AT+COPS?");
|
|
_at.cmd_stop();
|
|
|
|
_at.resp_start("+COPS:");
|
|
_at.read_int(); //ignore mode
|
|
format = _at.read_int();
|
|
|
|
if (_at.get_last_error() == NSAPI_ERROR_OK) {
|
|
switch (format) {
|
|
case 0:
|
|
_at.read_string(operator_params.op_long, sizeof(operator_params.op_long));
|
|
break;
|
|
case 1:
|
|
_at.read_string(operator_params.op_short, sizeof(operator_params.op_short));
|
|
break;
|
|
default:
|
|
_at.read_string(operator_params.op_num, sizeof(operator_params.op_num));
|
|
break;
|
|
}
|
|
operator_params.op_rat = (RadioAccessTechnology)_at.read_int();
|
|
}
|
|
|
|
_at.resp_stop();
|
|
|
|
return _at.unlock_return_error();
|
|
}
|
|
|
|
nsapi_error_t AT_CellularNetwork::get_operator_names(operator_names_list &op_names)
|
|
{
|
|
_at.lock();
|
|
|
|
_at.cmd_start("AT+COPN");
|
|
_at.cmd_stop();
|
|
|
|
_at.resp_start("+COPN:");
|
|
operator_names_t *names = NULL;
|
|
while (_at.info_resp()) {
|
|
names = op_names.add_new();
|
|
_at.read_string(names->numeric, sizeof(names->numeric));
|
|
_at.read_string(names->alpha, sizeof(names->alpha));
|
|
}
|
|
|
|
_at.resp_stop();
|
|
return _at.unlock_return_error();
|
|
}
|
|
|
|
void AT_CellularNetwork::get_context_state_command()
|
|
{
|
|
_at.cmd_start("AT+CGACT?");
|
|
_at.cmd_stop();
|
|
_at.resp_start("+CGACT:");
|
|
}
|
|
|
|
bool AT_CellularNetwork::is_active_context(int *number_of_active_contexts, int cid)
|
|
{
|
|
_at.lock();
|
|
|
|
if (number_of_active_contexts) {
|
|
*number_of_active_contexts = 0;
|
|
}
|
|
bool active_found = false;
|
|
int context_id;
|
|
// read active contexts
|
|
get_context_state_command();
|
|
|
|
while (_at.info_resp()) {
|
|
context_id = _at.read_int(); // discard context id
|
|
if (_at.read_int() == 1) { // check state
|
|
tr_debug("Found active context");
|
|
if (number_of_active_contexts) {
|
|
(*number_of_active_contexts)++;
|
|
}
|
|
if (cid == -1) {
|
|
active_found = true;
|
|
} else if (context_id == cid) {
|
|
active_found = true;
|
|
}
|
|
if (!number_of_active_contexts && active_found) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
_at.resp_stop();
|
|
_at.unlock();
|
|
|
|
return active_found;
|
|
}
|
|
|
|
nsapi_error_t AT_CellularNetwork::get_registration_params(registration_params_t ®_params)
|
|
{
|
|
reg_params = _reg_params;
|
|
return NSAPI_ERROR_OK;
|
|
}
|
|
|
|
nsapi_error_t AT_CellularNetwork::get_registration_params(RegistrationType type, registration_params_t ®_params)
|
|
{
|
|
int i = (int)type;
|
|
MBED_ASSERT(i >= 0 && i < C_MAX);
|
|
|
|
if (!get_property((AT_CellularBase::CellularProperty)at_reg[i].type)) {
|
|
return NSAPI_ERROR_UNSUPPORTED;
|
|
}
|
|
|
|
_at.lock();
|
|
|
|
const char *rsp[] = { "+CEREG:", "+CGREG:", "+CREG:"};
|
|
_at.cmd_start(at_reg[i].cmd);
|
|
_at.write_string("?", false);
|
|
_at.cmd_stop();
|
|
_at.resp_start(rsp[i]);
|
|
|
|
(void)_at.read_int(); // ignore urc mode subparam
|
|
read_reg_params(type, reg_params);
|
|
_at.resp_stop();
|
|
|
|
_reg_params = reg_params;
|
|
|
|
return _at.unlock_return_error();
|
|
}
|
|
|
|
int AT_CellularNetwork::calculate_active_time(const char *active_time_string, int active_time_length)
|
|
{
|
|
if (active_time_length != ONE_BYTE_BINARY) {
|
|
return -1;
|
|
}
|
|
|
|
uint32_t ie_unit = binary_str_to_uint(active_time_string, TIMER_UNIT_LENGTH);
|
|
uint32_t ie_value = binary_str_to_uint(active_time_string + TIMER_UNIT_LENGTH, active_time_length - TIMER_UNIT_LENGTH);
|
|
|
|
switch (ie_unit) {
|
|
case 0: // multiples of 2 seconds
|
|
return 2 * ie_value;
|
|
case 1: // multiples of 1 minute
|
|
return 60 * ie_value;
|
|
case 2: // multiples of decihours
|
|
return 6 * 60 * ie_value;
|
|
case 7: // timer is deactivated
|
|
return 0;
|
|
default: // other values shall be interpreted as multiples of 1 minute
|
|
return 60 * ie_value;
|
|
}
|
|
}
|
|
|
|
int AT_CellularNetwork::calculate_periodic_tau(const char *periodic_tau_string, int periodic_tau_length)
|
|
{
|
|
if (periodic_tau_length != ONE_BYTE_BINARY) {
|
|
return -1;
|
|
}
|
|
|
|
uint32_t ie_unit = binary_str_to_uint(periodic_tau_string, TIMER_UNIT_LENGTH);
|
|
uint32_t ie_value = binary_str_to_uint(periodic_tau_string + TIMER_UNIT_LENGTH, periodic_tau_length - TIMER_UNIT_LENGTH);
|
|
|
|
switch (ie_unit) {
|
|
case 0: // multiples of 10 minutes
|
|
return 60 * 10 * ie_value;
|
|
case 1: // multiples of 1 hour
|
|
return 60 * 60 * ie_value;
|
|
case 2: // multiples of 10 hours
|
|
return 10 * 60 * 60 * ie_value;
|
|
case 3: // multiples of 2 seconds
|
|
return 2 * ie_value;
|
|
case 4: // multiples of 30 seconds
|
|
return 30 * ie_value;
|
|
case 5: // multiples of 1 minute
|
|
return 60 * ie_value;
|
|
case 6: // multiples of 320 hours
|
|
return 320 * 60 * 60 * ie_value;
|
|
default: // timer is deactivated
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
nsapi_error_t AT_CellularNetwork::set_receive_period(int mode, EDRXAccessTechnology act_type, uint8_t edrx_value)
|
|
{
|
|
char edrx[5];
|
|
uint_to_binary_str(edrx_value, edrx, 5, 4);
|
|
edrx[4] = '\0';
|
|
|
|
_at.lock();
|
|
|
|
_at.cmd_start("AT+CEDRXS=");
|
|
_at.write_int(mode);
|
|
_at.write_int(act_type);
|
|
_at.write_string(edrx);
|
|
_at.cmd_stop_read_resp();
|
|
|
|
return _at.unlock_return_error();
|
|
}
|
|
|
|
nsapi_error_t AT_CellularNetwork::set_packet_domain_event_reporting(bool on)
|
|
{
|
|
if (!get_property(AT_CellularBase::PROPERTY_AT_CGEREP)) {
|
|
return NSAPI_ERROR_UNSUPPORTED;
|
|
}
|
|
|
|
_at.lock();
|
|
_at.cmd_start("AT+CGEREP=");
|
|
_at.write_int(on ? 1 : 0); // discard unsolicited result codes when MT TE link is reserved (e.g. in on line data mode); otherwise forward them directly to the TE
|
|
_at.cmd_stop_read_resp();
|
|
|
|
return _at.unlock_return_error();
|
|
}
|