Cellular: Move PSM setting from power to device

pull/9472/head
Ari Parkkila 2018-11-28 00:57:11 -08:00
parent 36292a4f14
commit 38f79a9b65
12 changed files with 182 additions and 185 deletions

View File

@ -232,6 +232,34 @@ TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_modem_debug_on)
dev.close_sms();
}
TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_set_power_save_mode)
{
EventQueue que;
FileHandle_stub fh1;
ATHandler at(&fh1, que, 0, ",");
AT_CellularDevice dev(&fh1);
ATHandler_stub::nsapi_error_value = NSAPI_ERROR_OK;
EXPECT_TRUE(NSAPI_ERROR_OK == dev.set_power_save_mode(0, 0));
EXPECT_TRUE(NSAPI_ERROR_OK == dev.set_power_save_mode(10, 0));
EXPECT_TRUE(NSAPI_ERROR_OK == dev.set_power_save_mode(912, 0));
EXPECT_TRUE(NSAPI_ERROR_OK == dev.set_power_save_mode(1834, 1834));
EXPECT_TRUE(NSAPI_ERROR_OK == dev.set_power_save_mode(18345, 18345));
EXPECT_TRUE(NSAPI_ERROR_OK == dev.set_power_save_mode(101234, 101234));
EXPECT_TRUE(NSAPI_ERROR_OK == dev.set_power_save_mode(1012345, 1012345));
EXPECT_TRUE(NSAPI_ERROR_OK == dev.set_power_save_mode(39612345, 39612345));
ATHandler_stub::nsapi_error_value = NSAPI_ERROR_DEVICE_ERROR;
EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == dev.set_power_save_mode(0));
}
TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_get_send_delay)
{
FileHandle_stub fh1;

View File

@ -123,34 +123,6 @@ TEST_F(TestAT_CellularPower, test_AT_CellularPower_reset)
EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == pow.reset());
}
TEST_F(TestAT_CellularPower, test_AT_CellularPower_opt_power_save_mode)
{
EventQueue que;
FileHandle_stub fh1;
ATHandler at(&fh1, que, 0, ",");
AT_CellularPower pow(at);
ATHandler_stub::nsapi_error_value = NSAPI_ERROR_OK;
EXPECT_TRUE(NSAPI_ERROR_OK == pow.opt_power_save_mode(0, 0));
EXPECT_TRUE(NSAPI_ERROR_OK == pow.opt_power_save_mode(10, 0));
EXPECT_TRUE(NSAPI_ERROR_OK == pow.opt_power_save_mode(912, 0));
EXPECT_TRUE(NSAPI_ERROR_OK == pow.opt_power_save_mode(1834, 1834));
EXPECT_TRUE(NSAPI_ERROR_OK == pow.opt_power_save_mode(18345, 18345));
EXPECT_TRUE(NSAPI_ERROR_OK == pow.opt_power_save_mode(101234, 101234));
EXPECT_TRUE(NSAPI_ERROR_OK == pow.opt_power_save_mode(1012345, 1012345));
EXPECT_TRUE(NSAPI_ERROR_OK == pow.opt_power_save_mode(39612345, 39612345));
ATHandler_stub::nsapi_error_value = NSAPI_ERROR_DEVICE_ERROR;
EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == pow.opt_power_save_mode(0, 0));
}
TEST_F(TestAT_CellularPower, test_AT_CellularPower_is_device_ready)
{
EventQueue que;

View File

@ -151,6 +151,11 @@ void AT_CellularDevice::modem_debug_on(bool on)
}
nsapi_error_t AT_CellularDevice::set_power_save_mode(int periodic_time, int active_time)
{
return NSAPI_ERROR_OK;
}
nsapi_error_t AT_CellularDevice::init_module()
{
return NSAPI_ERROR_OK;

View File

@ -55,11 +55,6 @@ nsapi_error_t AT_CellularPower::reset()
return NSAPI_ERROR_OK;
}
nsapi_error_t AT_CellularPower::opt_power_save_mode(int periodic_time, int active_time)
{
return NSAPI_ERROR_OK;
}
nsapi_error_t AT_CellularPower::set_device_ready_urc_cb(mbed::Callback<void()> callback)
{
return NSAPI_ERROR_OK;

View File

@ -109,6 +109,11 @@ public:
virtual void modem_debug_on(bool on) {}
nsapi_error_t set_power_save_mode(int periodic_time, int active_time)
{
return NSAPI_ERROR_OK;
}
virtual nsapi_error_t init_module()
{
return 0;

View File

@ -87,16 +87,6 @@ static void test_power_interface()
TEST_ASSERT(err == NSAPI_ERROR_OK);
wait_for_power(pwr);
wait(1);
err = pwr->opt_power_save_mode(0, 0);
TEST_ASSERT(err == NSAPI_ERROR_OK || err == NSAPI_ERROR_DEVICE_ERROR);
if (err == NSAPI_ERROR_DEVICE_ERROR) {
if (!(strcmp(devi, "TELIT_HE910") == 0 || strcmp(devi, "QUECTEL_BG96") == 0)) { // TELIT_HE910 and QUECTEL_BG96 just gives an error and no specific error number so we can't know is this real error or that modem/network does not support the command
TEST_ASSERT(((AT_CellularPower *)pwr)->get_device_error().errCode == 100 && // 100 == unknown command for modem
((AT_CellularPower *)pwr)->get_device_error().errType == 3); // 3 == CME error from the modem
}
}
err = pwr->off();
TEST_ASSERT(err == NSAPI_ERROR_OK || err == NSAPI_ERROR_UNSUPPORTED);

View File

@ -18,6 +18,7 @@
#ifndef CELLULAR_DEVICE_H_
#define CELLULAR_DEVICE_H_
#include "CellularUtil.h"
#include "CellularTargets.h"
#include "CellularStateMachine.h"
#include "Callback.h"
@ -249,6 +250,18 @@ public:
*/
virtual void modem_debug_on(bool on) = 0;
/** Set power save mode
*
* @remark See 3GPP TS 27.007 PSM for details
*
* @param periodic_time in seconds to enable power save, or zero to disable
* @param active_time in seconds to wait before entering power save mode
*
* @return NSAPI_ERROR_OK on success
* NSAPI_ERROR_DEVICE_ERROR on failure
*/
virtual nsapi_error_t set_power_save_mode(int periodic_time, int active_time = 0) = 0;
/** Initialize cellular module must be called right after module is ready.
* For example, when multiple modules are supported in a single AT driver this function detects
* and adapts to an actual module at runtime.

View File

@ -93,18 +93,6 @@ public:
*/
virtual nsapi_error_t reset() = 0;
/** Opt for power save setting on cellular device. If both parameters are zero, this disables PSM.
*
* @remark See 3GPP TS 27.007 PSM for details
*
* @param periodic_time Timeout in seconds IoT subsystem is not expecting messaging
* @param active_time Timeout in seconds IoT subsystem waits for response
*
* @return NSAPI_ERROR_OK on success
* NSAPI_ERROR_DEVICE_ERROR on failure
*/
virtual nsapi_error_t opt_power_save_mode(int periodic_time, int active_time) = 0;
/** Check whether the device is ready to accept commands.
*
* @return NSAPI_ERROR_OK on success

View File

@ -27,6 +27,7 @@
#include "UARTSerial.h"
#include "FileHandle.h"
using namespace mbed_cellular_util;
using namespace events;
using namespace mbed;
@ -365,6 +366,134 @@ void AT_CellularDevice::modem_debug_on(bool on)
ATHandler::set_debug_list(_modem_debug_on);
}
nsapi_error_t AT_CellularDevice::set_power_save_mode(int periodic_time, int active_time)
{
_at->lock();
if (periodic_time == 0 && active_time == 0) {
// disable PSM
_at->cmd_start("AT+CPSMS=");
_at->write_int(0);
_at->cmd_stop_read_resp();
} else {
const int PSMTimerBits = 5;
/**
Table 10.5.163a/3GPP TS 24.008: GPRS Timer 3 information element
Bits 5 to 1 represent the binary coded timer value.
Bits 6 to 8 defines the timer value unit for the GPRS timer as follows:
8 7 6
0 0 0 value is incremented in multiples of 10 minutes
0 0 1 value is incremented in multiples of 1 hour
0 1 0 value is incremented in multiples of 10 hours
0 1 1 value is incremented in multiples of 2 seconds
1 0 0 value is incremented in multiples of 30 seconds
1 0 1 value is incremented in multiples of 1 minute
1 1 0 value is incremented in multiples of 320 hours (NOTE 1)
1 1 1 value indicates that the timer is deactivated (NOTE 2).
*/
char pt[8 + 1]; // timer value encoded as 3GPP IE
const int ie_value_max = 0x1f;
uint32_t periodic_timer = 0;
if (periodic_time <= 2 * ie_value_max) { // multiples of 2 seconds
periodic_timer = periodic_time / 2;
strcpy(pt, "01100000");
} else {
if (periodic_time <= 30 * ie_value_max) { // multiples of 30 seconds
periodic_timer = periodic_time / 30;
strcpy(pt, "10000000");
} else {
if (periodic_time <= 60 * ie_value_max) { // multiples of 1 minute
periodic_timer = periodic_time / 60;
strcpy(pt, "10100000");
} else {
if (periodic_time <= 10 * 60 * ie_value_max) { // multiples of 10 minutes
periodic_timer = periodic_time / (10 * 60);
strcpy(pt, "00000000");
} else {
if (periodic_time <= 60 * 60 * ie_value_max) { // multiples of 1 hour
periodic_timer = periodic_time / (60 * 60);
strcpy(pt, "00100000");
} else {
if (periodic_time <= 10 * 60 * 60 * ie_value_max) { // multiples of 10 hours
periodic_timer = periodic_time / (10 * 60 * 60);
strcpy(pt, "01000000");
} else { // multiples of 320 hours
int t = periodic_time / (320 * 60 * 60);
if (t > ie_value_max) {
t = ie_value_max;
}
periodic_timer = t;
strcpy(pt, "11000000");
}
}
}
}
}
}
uint_to_binary_str(periodic_timer, &pt[3], sizeof(pt) - 3, PSMTimerBits);
pt[8] = '\0';
/**
Table 10.5.172/3GPP TS 24.008: GPRS Timer information element
Bits 5 to 1 represent the binary coded timer value.
Bits 6 to 8 defines the timer value unit for the GPRS timer as follows:
8 7 6
0 0 0 value is incremented in multiples of 2 seconds
0 0 1 value is incremented in multiples of 1 minute
0 1 0 value is incremented in multiples of decihours
1 1 1 value indicates that the timer is deactivated.
Other values shall be interpreted as multiples of 1 minute in this version of the protocol.
*/
char at[8 + 1];
uint32_t active_timer; // timer value encoded as 3GPP IE
if (active_time <= 2 * ie_value_max) { // multiples of 2 seconds
active_timer = active_time / 2;
strcpy(at, "00000000");
} else {
if (active_time <= 60 * ie_value_max) { // multiples of 1 minute
active_timer = (1 << 5) | (active_time / 60);
strcpy(at, "00100000");
} else { // multiples of decihours
int t = active_time / (6 * 60);
if (t > ie_value_max) {
t = ie_value_max;
}
active_timer = t;
strcpy(at, "01000000");
}
}
uint_to_binary_str(active_timer, &at[3], sizeof(at) - 3, PSMTimerBits);
at[8] = '\0';
// request for both GPRS and LTE
_at->cmd_start("AT+CPSMS=");
_at->write_int(1);
_at->write_string(pt);
_at->write_string(at);
_at->write_string(pt);
_at->write_string(at);
_at->cmd_stop_read_resp();
if (_at->get_last_error() != NSAPI_ERROR_OK) {
tr_warn("Power save mode not enabled!");
} else {
// network may not agree with power save options but
// that should be fine as timeout is not longer than requested
}
}
return _at->unlock_return_error();
}
nsapi_error_t AT_CellularDevice::init_module()
{
#if MBED_CONF_MBED_TRACE_ENABLE

View File

@ -70,6 +70,8 @@ public:
virtual void modem_debug_on(bool on);
virtual nsapi_error_t set_power_save_mode(int periodic_time, int active_time = 0);
virtual nsapi_error_t init_module();
virtual ATHandler *get_at_handler(FileHandle *fh);

View File

@ -21,8 +21,6 @@
#include "CellularTargets.h"
#include "nsapi_types.h"
static const int PSMTimerBits = 5;
using namespace mbed_cellular_util;
using namespace mbed;
@ -76,132 +74,6 @@ nsapi_error_t AT_CellularPower::reset()
return _at.unlock_return_error();
}
nsapi_error_t AT_CellularPower::opt_power_save_mode(int periodic_time, int active_time)
{
_at.lock();
if (periodic_time == 0 && active_time == 0) {
// disable PSM
_at.cmd_start("AT+CPSMS=");
_at.write_int(0);
_at.cmd_stop_read_resp();
} else {
/**
Table 10.5.163a/3GPP TS 24.008: GPRS Timer 3 information element
Bits 5 to 1 represent the binary coded timer value.
Bits 6 to 8 defines the timer value unit for the GPRS timer as follows:
8 7 6
0 0 0 value is incremented in multiples of 10 minutes
0 0 1 value is incremented in multiples of 1 hour
0 1 0 value is incremented in multiples of 10 hours
0 1 1 value is incremented in multiples of 2 seconds
1 0 0 value is incremented in multiples of 30 seconds
1 0 1 value is incremented in multiples of 1 minute
1 1 0 value is incremented in multiples of 320 hours (NOTE 1)
1 1 1 value indicates that the timer is deactivated (NOTE 2).
*/
char pt[8 + 1]; // timer value encoded as 3GPP IE
const int ie_value_max = 0x1f;
uint32_t periodic_timer = 0;
if (periodic_time <= 2 * ie_value_max) { // multiples of 2 seconds
periodic_timer = periodic_time / 2;
strcpy(pt, "01100000");
} else {
if (periodic_time <= 30 * ie_value_max) { // multiples of 30 seconds
periodic_timer = periodic_time / 30;
strcpy(pt, "10000000");
} else {
if (periodic_time <= 60 * ie_value_max) { // multiples of 1 minute
periodic_timer = periodic_time / 60;
strcpy(pt, "10100000");
} else {
if (periodic_time <= 10 * 60 * ie_value_max) { // multiples of 10 minutes
periodic_timer = periodic_time / (10 * 60);
strcpy(pt, "00000000");
} else {
if (periodic_time <= 60 * 60 * ie_value_max) { // multiples of 1 hour
periodic_timer = periodic_time / (60 * 60);
strcpy(pt, "00100000");
} else {
if (periodic_time <= 10 * 60 * 60 * ie_value_max) { // multiples of 10 hours
periodic_timer = periodic_time / (10 * 60 * 60);
strcpy(pt, "01000000");
} else { // multiples of 320 hours
int t = periodic_time / (320 * 60 * 60);
if (t > ie_value_max) {
t = ie_value_max;
}
periodic_timer = t;
strcpy(pt, "11000000");
}
}
}
}
}
}
uint_to_binary_str(periodic_timer, &pt[3], sizeof(pt) - 3, PSMTimerBits);
pt[8] = '\0';
/**
Table 10.5.172/3GPP TS 24.008: GPRS Timer information element
Bits 5 to 1 represent the binary coded timer value.
Bits 6 to 8 defines the timer value unit for the GPRS timer as follows:
8 7 6
0 0 0 value is incremented in multiples of 2 seconds
0 0 1 value is incremented in multiples of 1 minute
0 1 0 value is incremented in multiples of decihours
1 1 1 value indicates that the timer is deactivated.
Other values shall be interpreted as multiples of 1 minute in this version of the protocol.
*/
char at[8 + 1];
uint32_t active_timer; // timer value encoded as 3GPP IE
if (active_time <= 2 * ie_value_max) { // multiples of 2 seconds
active_timer = active_time / 2;
strcpy(at, "00000000");
} else {
if (active_time <= 60 * ie_value_max) { // multiples of 1 minute
active_timer = (1 << 5) | (active_time / 60);
strcpy(at, "00100000");
} else { // multiples of decihours
int t = active_time / (6 * 60);
if (t > ie_value_max) {
t = ie_value_max;
}
active_timer = t;
strcpy(at, "01000000");
}
}
uint_to_binary_str(active_timer, &at[3], sizeof(at) - 3, PSMTimerBits);
at[8] = '\0';
// request for both GPRS and LTE
_at.cmd_start("AT+CPSMS=");
_at.write_int(1);
_at.write_string(pt);
_at.write_string(at);
_at.write_string(pt);
_at.write_string(at);
_at.cmd_stop_read_resp();
if (_at.get_last_error() != NSAPI_ERROR_OK) {
tr_warn("Power save mode not enabled!");
} else {
// network may not agree with power save options but
// that should be fine as timeout is not longer than requested
}
}
return _at.unlock_return_error();
}
nsapi_error_t AT_CellularPower::is_device_ready()
{
_at.lock();

View File

@ -44,8 +44,6 @@ public:
virtual nsapi_error_t reset();
virtual nsapi_error_t opt_power_save_mode(int periodic_time, int active_time);
virtual nsapi_error_t is_device_ready();
virtual nsapi_error_t set_device_ready_urc_cb(mbed::Callback<void()> callback);