Skip to content

Commit 38f79a9

Browse files
author
Ari Parkkila
committed
Cellular: Move PSM setting from power to device
1 parent 36292a4 commit 38f79a9

File tree

12 files changed

+182
-185
lines changed

12 files changed

+182
-185
lines changed

UNITTESTS/features/cellular/framework/AT/at_cellulardevice/at_cellulardevicetest.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,34 @@ TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_modem_debug_on)
232232
dev.close_sms();
233233
}
234234

235+
TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_set_power_save_mode)
236+
{
237+
EventQueue que;
238+
FileHandle_stub fh1;
239+
ATHandler at(&fh1, que, 0, ",");
240+
241+
AT_CellularDevice dev(&fh1);
242+
ATHandler_stub::nsapi_error_value = NSAPI_ERROR_OK;
243+
EXPECT_TRUE(NSAPI_ERROR_OK == dev.set_power_save_mode(0, 0));
244+
245+
EXPECT_TRUE(NSAPI_ERROR_OK == dev.set_power_save_mode(10, 0));
246+
247+
EXPECT_TRUE(NSAPI_ERROR_OK == dev.set_power_save_mode(912, 0));
248+
249+
EXPECT_TRUE(NSAPI_ERROR_OK == dev.set_power_save_mode(1834, 1834));
250+
251+
EXPECT_TRUE(NSAPI_ERROR_OK == dev.set_power_save_mode(18345, 18345));
252+
253+
EXPECT_TRUE(NSAPI_ERROR_OK == dev.set_power_save_mode(101234, 101234));
254+
255+
EXPECT_TRUE(NSAPI_ERROR_OK == dev.set_power_save_mode(1012345, 1012345));
256+
257+
EXPECT_TRUE(NSAPI_ERROR_OK == dev.set_power_save_mode(39612345, 39612345));
258+
259+
ATHandler_stub::nsapi_error_value = NSAPI_ERROR_DEVICE_ERROR;
260+
EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == dev.set_power_save_mode(0));
261+
}
262+
235263
TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_get_send_delay)
236264
{
237265
FileHandle_stub fh1;

UNITTESTS/features/cellular/framework/AT/at_cellularpower/at_cellularpowertest.cpp

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -123,34 +123,6 @@ TEST_F(TestAT_CellularPower, test_AT_CellularPower_reset)
123123
EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == pow.reset());
124124
}
125125

126-
TEST_F(TestAT_CellularPower, test_AT_CellularPower_opt_power_save_mode)
127-
{
128-
EventQueue que;
129-
FileHandle_stub fh1;
130-
ATHandler at(&fh1, que, 0, ",");
131-
132-
AT_CellularPower pow(at);
133-
ATHandler_stub::nsapi_error_value = NSAPI_ERROR_OK;
134-
EXPECT_TRUE(NSAPI_ERROR_OK == pow.opt_power_save_mode(0, 0));
135-
136-
EXPECT_TRUE(NSAPI_ERROR_OK == pow.opt_power_save_mode(10, 0));
137-
138-
EXPECT_TRUE(NSAPI_ERROR_OK == pow.opt_power_save_mode(912, 0));
139-
140-
EXPECT_TRUE(NSAPI_ERROR_OK == pow.opt_power_save_mode(1834, 1834));
141-
142-
EXPECT_TRUE(NSAPI_ERROR_OK == pow.opt_power_save_mode(18345, 18345));
143-
144-
EXPECT_TRUE(NSAPI_ERROR_OK == pow.opt_power_save_mode(101234, 101234));
145-
146-
EXPECT_TRUE(NSAPI_ERROR_OK == pow.opt_power_save_mode(1012345, 1012345));
147-
148-
EXPECT_TRUE(NSAPI_ERROR_OK == pow.opt_power_save_mode(39612345, 39612345));
149-
150-
ATHandler_stub::nsapi_error_value = NSAPI_ERROR_DEVICE_ERROR;
151-
EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == pow.opt_power_save_mode(0, 0));
152-
}
153-
154126
TEST_F(TestAT_CellularPower, test_AT_CellularPower_is_device_ready)
155127
{
156128
EventQueue que;

UNITTESTS/stubs/AT_CellularDevice_stub.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,11 @@ void AT_CellularDevice::modem_debug_on(bool on)
151151

152152
}
153153

154+
nsapi_error_t AT_CellularDevice::set_power_save_mode(int periodic_time, int active_time)
155+
{
156+
return NSAPI_ERROR_OK;
157+
}
158+
154159
nsapi_error_t AT_CellularDevice::init_module()
155160
{
156161
return NSAPI_ERROR_OK;

UNITTESTS/stubs/AT_CellularPower_stub.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,6 @@ nsapi_error_t AT_CellularPower::reset()
5555
return NSAPI_ERROR_OK;
5656
}
5757

58-
nsapi_error_t AT_CellularPower::opt_power_save_mode(int periodic_time, int active_time)
59-
{
60-
return NSAPI_ERROR_OK;
61-
}
62-
6358
nsapi_error_t AT_CellularPower::set_device_ready_urc_cb(mbed::Callback<void()> callback)
6459
{
6560
return NSAPI_ERROR_OK;

UNITTESTS/target_h/myCellularDevice.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,11 @@ class myCellularDevice : public CellularDevice {
109109

110110
virtual void modem_debug_on(bool on) {}
111111

112+
nsapi_error_t set_power_save_mode(int periodic_time, int active_time)
113+
{
114+
return NSAPI_ERROR_OK;
115+
}
116+
112117
virtual nsapi_error_t init_module()
113118
{
114119
return 0;

features/cellular/TESTS/api/cellular_power/main.cpp

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -87,16 +87,6 @@ static void test_power_interface()
8787
TEST_ASSERT(err == NSAPI_ERROR_OK);
8888
wait_for_power(pwr);
8989

90-
wait(1);
91-
err = pwr->opt_power_save_mode(0, 0);
92-
TEST_ASSERT(err == NSAPI_ERROR_OK || err == NSAPI_ERROR_DEVICE_ERROR);
93-
if (err == NSAPI_ERROR_DEVICE_ERROR) {
94-
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
95-
TEST_ASSERT(((AT_CellularPower *)pwr)->get_device_error().errCode == 100 && // 100 == unknown command for modem
96-
((AT_CellularPower *)pwr)->get_device_error().errType == 3); // 3 == CME error from the modem
97-
}
98-
}
99-
10090
err = pwr->off();
10191
TEST_ASSERT(err == NSAPI_ERROR_OK || err == NSAPI_ERROR_UNSUPPORTED);
10292

features/cellular/framework/API/CellularDevice.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#ifndef CELLULAR_DEVICE_H_
1919
#define CELLULAR_DEVICE_H_
2020

21+
#include "CellularUtil.h"
2122
#include "CellularTargets.h"
2223
#include "CellularStateMachine.h"
2324
#include "Callback.h"
@@ -249,6 +250,18 @@ class CellularDevice {
249250
*/
250251
virtual void modem_debug_on(bool on) = 0;
251252

253+
/** Set power save mode
254+
*
255+
* @remark See 3GPP TS 27.007 PSM for details
256+
*
257+
* @param periodic_time in seconds to enable power save, or zero to disable
258+
* @param active_time in seconds to wait before entering power save mode
259+
*
260+
* @return NSAPI_ERROR_OK on success
261+
* NSAPI_ERROR_DEVICE_ERROR on failure
262+
*/
263+
virtual nsapi_error_t set_power_save_mode(int periodic_time, int active_time = 0) = 0;
264+
252265
/** Initialize cellular module must be called right after module is ready.
253266
* For example, when multiple modules are supported in a single AT driver this function detects
254267
* and adapts to an actual module at runtime.

features/cellular/framework/API/CellularPower.h

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -93,18 +93,6 @@ class CellularPower {
9393
*/
9494
virtual nsapi_error_t reset() = 0;
9595

96-
/** Opt for power save setting on cellular device. If both parameters are zero, this disables PSM.
97-
*
98-
* @remark See 3GPP TS 27.007 PSM for details
99-
*
100-
* @param periodic_time Timeout in seconds IoT subsystem is not expecting messaging
101-
* @param active_time Timeout in seconds IoT subsystem waits for response
102-
*
103-
* @return NSAPI_ERROR_OK on success
104-
* NSAPI_ERROR_DEVICE_ERROR on failure
105-
*/
106-
virtual nsapi_error_t opt_power_save_mode(int periodic_time, int active_time) = 0;
107-
10896
/** Check whether the device is ready to accept commands.
10997
*
11098
* @return NSAPI_ERROR_OK on success

features/cellular/framework/AT/AT_CellularDevice.cpp

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "UARTSerial.h"
2828
#include "FileHandle.h"
2929

30+
using namespace mbed_cellular_util;
3031
using namespace events;
3132
using namespace mbed;
3233

@@ -365,6 +366,134 @@ void AT_CellularDevice::modem_debug_on(bool on)
365366
ATHandler::set_debug_list(_modem_debug_on);
366367
}
367368

369+
nsapi_error_t AT_CellularDevice::set_power_save_mode(int periodic_time, int active_time)
370+
{
371+
_at->lock();
372+
373+
if (periodic_time == 0 && active_time == 0) {
374+
// disable PSM
375+
_at->cmd_start("AT+CPSMS=");
376+
_at->write_int(0);
377+
_at->cmd_stop_read_resp();
378+
} else {
379+
const int PSMTimerBits = 5;
380+
381+
/**
382+
Table 10.5.163a/3GPP TS 24.008: GPRS Timer 3 information element
383+
384+
Bits 5 to 1 represent the binary coded timer value.
385+
386+
Bits 6 to 8 defines the timer value unit for the GPRS timer as follows:
387+
8 7 6
388+
0 0 0 value is incremented in multiples of 10 minutes
389+
0 0 1 value is incremented in multiples of 1 hour
390+
0 1 0 value is incremented in multiples of 10 hours
391+
0 1 1 value is incremented in multiples of 2 seconds
392+
1 0 0 value is incremented in multiples of 30 seconds
393+
1 0 1 value is incremented in multiples of 1 minute
394+
1 1 0 value is incremented in multiples of 320 hours (NOTE 1)
395+
1 1 1 value indicates that the timer is deactivated (NOTE 2).
396+
*/
397+
char pt[8 + 1]; // timer value encoded as 3GPP IE
398+
const int ie_value_max = 0x1f;
399+
uint32_t periodic_timer = 0;
400+
if (periodic_time <= 2 * ie_value_max) { // multiples of 2 seconds
401+
periodic_timer = periodic_time / 2;
402+
strcpy(pt, "01100000");
403+
} else {
404+
if (periodic_time <= 30 * ie_value_max) { // multiples of 30 seconds
405+
periodic_timer = periodic_time / 30;
406+
strcpy(pt, "10000000");
407+
} else {
408+
if (periodic_time <= 60 * ie_value_max) { // multiples of 1 minute
409+
periodic_timer = periodic_time / 60;
410+
strcpy(pt, "10100000");
411+
} else {
412+
if (periodic_time <= 10 * 60 * ie_value_max) { // multiples of 10 minutes
413+
periodic_timer = periodic_time / (10 * 60);
414+
strcpy(pt, "00000000");
415+
} else {
416+
if (periodic_time <= 60 * 60 * ie_value_max) { // multiples of 1 hour
417+
periodic_timer = periodic_time / (60 * 60);
418+
strcpy(pt, "00100000");
419+
} else {
420+
if (periodic_time <= 10 * 60 * 60 * ie_value_max) { // multiples of 10 hours
421+
periodic_timer = periodic_time / (10 * 60 * 60);
422+
strcpy(pt, "01000000");
423+
} else { // multiples of 320 hours
424+
int t = periodic_time / (320 * 60 * 60);
425+
if (t > ie_value_max) {
426+
t = ie_value_max;
427+
}
428+
periodic_timer = t;
429+
strcpy(pt, "11000000");
430+
}
431+
}
432+
}
433+
}
434+
}
435+
}
436+
437+
uint_to_binary_str(periodic_timer, &pt[3], sizeof(pt) - 3, PSMTimerBits);
438+
pt[8] = '\0';
439+
440+
/**
441+
Table 10.5.172/3GPP TS 24.008: GPRS Timer information element
442+
443+
Bits 5 to 1 represent the binary coded timer value.
444+
445+
Bits 6 to 8 defines the timer value unit for the GPRS timer as follows:
446+
447+
8 7 6
448+
0 0 0 value is incremented in multiples of 2 seconds
449+
0 0 1 value is incremented in multiples of 1 minute
450+
0 1 0 value is incremented in multiples of decihours
451+
1 1 1 value indicates that the timer is deactivated.
452+
453+
Other values shall be interpreted as multiples of 1 minute in this version of the protocol.
454+
*/
455+
char at[8 + 1];
456+
uint32_t active_timer; // timer value encoded as 3GPP IE
457+
if (active_time <= 2 * ie_value_max) { // multiples of 2 seconds
458+
active_timer = active_time / 2;
459+
strcpy(at, "00000000");
460+
} else {
461+
if (active_time <= 60 * ie_value_max) { // multiples of 1 minute
462+
active_timer = (1 << 5) | (active_time / 60);
463+
strcpy(at, "00100000");
464+
} else { // multiples of decihours
465+
int t = active_time / (6 * 60);
466+
if (t > ie_value_max) {
467+
t = ie_value_max;
468+
}
469+
active_timer = t;
470+
strcpy(at, "01000000");
471+
}
472+
}
473+
474+
uint_to_binary_str(active_timer, &at[3], sizeof(at) - 3, PSMTimerBits);
475+
at[8] = '\0';
476+
477+
// request for both GPRS and LTE
478+
_at->cmd_start("AT+CPSMS=");
479+
_at->write_int(1);
480+
_at->write_string(pt);
481+
_at->write_string(at);
482+
_at->write_string(pt);
483+
_at->write_string(at);
484+
_at->cmd_stop_read_resp();
485+
486+
if (_at->get_last_error() != NSAPI_ERROR_OK) {
487+
tr_warn("Power save mode not enabled!");
488+
} else {
489+
// network may not agree with power save options but
490+
// that should be fine as timeout is not longer than requested
491+
}
492+
}
493+
494+
return _at->unlock_return_error();
495+
}
496+
368497
nsapi_error_t AT_CellularDevice::init_module()
369498
{
370499
#if MBED_CONF_MBED_TRACE_ENABLE

features/cellular/framework/AT/AT_CellularDevice.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ class AT_CellularDevice : public CellularDevice {
7070

7171
virtual void modem_debug_on(bool on);
7272

73+
virtual nsapi_error_t set_power_save_mode(int periodic_time, int active_time = 0);
74+
7375
virtual nsapi_error_t init_module();
7476

7577
virtual ATHandler *get_at_handler(FileHandle *fh);

0 commit comments

Comments
 (0)