Skip to content

Commit 9ac95dc

Browse files
[EGD-3839] Cellular - get time zone (#903)
1 parent 17757cd commit 9ac95dc

File tree

13 files changed

+204
-41
lines changed

13 files changed

+204
-41
lines changed

changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
* `[settings][bluetooth]` Add "Phone name" window.
88
* `[gui]` Add "ButtonOnOff" widget.
99
* `[cellular]` Add support for modem reset
10+
* `[cellular]` Obtain time zone through network
1011

1112
### Changed
1213

module-cellular/at/URC_CTZE.hpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,17 @@ namespace at::urc
2121

2222
public:
2323
explicit CTZE(const std::string &val);
24+
25+
constexpr static int maxTimezoneOffset = 56;
26+
constexpr static int minTimezoneOffset = -48;
27+
2428
~CTZE() override = default;
2529
[[nodiscard]] auto what() const noexcept -> std::string final;
2630
[[nodiscard]] auto isValid() const noexcept -> bool;
27-
2831
[[nodiscard]] auto getTimeInfo(void) const noexcept -> tm;
32+
33+
auto getTimeZoneOffset() const -> int;
34+
auto getTimeZoneString() const -> std::string;
35+
auto getGMTTime(void) const -> const struct tm;
2936
};
3037
}; // namespace at::urc

module-cellular/at/response.cpp

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,11 @@ namespace at
3232
if (pos != std::string::npos) {
3333
LOG_INFO("%s", CSQstring.c_str());
3434
CSQstring = CSQstring.substr(0, pos);
35-
return utils::toNumeric(CSQstring, result);
35+
int parsedVal = 0;
36+
if (utils::toNumeric(CSQstring, parsedVal) && parsedVal >= 0) {
37+
result = parsedVal;
38+
return true;
39+
}
3640
}
3741
}
3842
return false;
@@ -59,7 +63,11 @@ namespace at
5963
if (pos != std::string::npos) {
6064
auto constexpr digitLength = 1;
6165
resp = resp.substr(pos + digitLength, digitLength);
62-
return utils::toNumeric(resp, result);
66+
int parsedVal = 0;
67+
if (utils::toNumeric(resp, parsedVal) && parsedVal >= 0) {
68+
result = parsedVal;
69+
return true;
70+
}
6371
}
6472
return false;
6573
}
@@ -127,7 +135,7 @@ namespace at
127135
utils::findAndReplaceAll(string, " ", "");
128136
utils::findAndReplaceAll(string, "\"", "");
129137

130-
uint32_t freq = 0;
138+
int freq = 0;
131139
utils::toNumeric(string, freq);
132140
return freq;
133141
}
@@ -158,8 +166,10 @@ namespace at
158166
utils::findAndReplaceAll(string, "\"", emptyString);
159167
utils::findAndReplaceAll(string, toRemove, emptyString);
160168

161-
uint32_t band;
162-
utils::toNumeric(string, band);
169+
int band = 0;
170+
if (utils::toNumeric(string, band) && band < 0) {
171+
return 0;
172+
}
163173

164174
auto freq = lteFreqs.find(band);
165175
if (freq != lteFreqs.end()) {

module-cellular/at/src/URC_CTZE.cpp

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,21 @@
33

44
#include "../URC_CTZE.hpp"
55
#include <log/debug.hpp>
6+
#include <module-utils/time/time_conversion.hpp>
67

78
#include <module-utils/date/include/date/date.h>
89

910
using namespace at::urc;
1011

1112
CTZE::CTZE(const std::string &val) : Any(val)
12-
{}
13+
{
14+
if (!is()) {
15+
return;
16+
}
17+
for (auto &t : tokens) {
18+
utils::findAndReplaceAll(t, "\"", "");
19+
}
20+
}
1321

1422
auto CTZE::what() const noexcept -> std::string
1523
{
@@ -21,27 +29,65 @@ auto CTZE::isValid() const noexcept -> bool
2129
return tokens.size() == magic_enum::enum_count<Tokens>();
2230
}
2331

32+
int CTZE::getTimeZoneOffset() const
33+
{
34+
const std::string &tzOffsetToken = tokens[static_cast<uint32_t>(Tokens::GMTDifference)];
35+
36+
int offsetInQuartersOfHour = 0;
37+
bool failed = !utils::toNumeric(tzOffsetToken, offsetInQuartersOfHour);
38+
39+
if (offsetInQuartersOfHour != std::clamp(offsetInQuartersOfHour, minTimezoneOffset, maxTimezoneOffset)) {
40+
offsetInQuartersOfHour = 0;
41+
failed = true;
42+
}
43+
44+
if (failed) {
45+
LOG_ERROR("Failed to parse CTZE time zone offset: %s", tzOffsetToken.c_str());
46+
}
47+
48+
int offsetInSeconds = offsetInQuartersOfHour * utils::time::minutesInQuarterOfHour * utils::time::secondsInMinute;
49+
50+
return offsetInSeconds;
51+
}
52+
53+
std::string CTZE::getTimeZoneString() const
54+
{
55+
std::string timeZoneStr = tokens[static_cast<uint32_t>(Tokens::GMTDifference)] + "," +
56+
tokens[static_cast<uint32_t>(Tokens::DaylightSavingsAdjustment)];
57+
timeZoneStr.erase(remove_if(timeZoneStr.begin(), timeZoneStr.end(), isspace), timeZoneStr.end());
58+
return timeZoneStr;
59+
}
60+
61+
const struct tm CTZE::getGMTTime(void) const
62+
{
63+
struct tm timeinfo = {};
64+
std::stringstream stream(tokens[static_cast<uint32_t>(Tokens::Date)] + "," +
65+
tokens[static_cast<uint32_t>(Tokens::Time)]);
66+
stream >> std::get_time(&timeinfo, "%Y/%m/%d,%H:%M:%S");
67+
if (stream.fail()) {
68+
LOG_ERROR("Failed to parse CTZE time");
69+
}
70+
return timeinfo;
71+
}
72+
2473
auto CTZE::getTimeInfo() const noexcept -> tm
2574
{
2675
using namespace std::chrono;
2776

2877
std::tm timeinfo{};
2978
if (isValid()) {
3079
std::string dateTimeStr(tokens[Tokens::Date] + "," + tokens[Tokens::Time]);
31-
utils::findAndReplaceAll(dateTimeStr, "\"", "");
3280

3381
std::stringstream stream(dateTimeStr);
3482
date::sys_seconds tp;
3583
stream >> date::parse("%Y/%m/%d,%H:%M:%S", tp);
3684

3785
auto gmtDifferenceStr = tokens[Tokens::GMTDifference];
38-
utils::findAndReplaceAll(gmtDifferenceStr, "\"", "");
3986

40-
int gmtDifference = utils::getValue<int>(gmtDifferenceStr);
41-
constexpr auto minutesInQuartersOfHour = 15;
42-
constexpr auto secondsInMinutes = 60;
43-
auto time = system_clock::to_time_t(tp) + gmtDifference * minutesInQuartersOfHour * secondsInMinutes;
44-
timeinfo = *gmtime(&time);
87+
int gmtDifference = utils::getValue<int>(gmtDifferenceStr);
88+
auto time = system_clock::to_time_t(tp) +
89+
gmtDifference * utils::time::minutesInQuarterOfHour * utils::time::secondsInMinute;
90+
timeinfo = *gmtime(&time);
4591
}
4692
return timeinfo;
4793
}

module-cellular/test/unittest_URC.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#define CATCH_CONFIG_MAIN
99

1010
#include <catch2/catch.hpp>
11+
#include <module-utils/time/time_conversion.hpp>
1112

1213
#include "URC_QIND.hpp"
1314
#include "URC_CUSD.hpp"
@@ -197,6 +198,13 @@ TEST_CASE("+CTZE")
197198
std::stringstream ss;
198199
ss << std::put_time(&timeInfo, "%Y/%m/%d,%H:%M:%S");
199200
REQUIRE(ss.str() == "2020/10/21,15:49:57");
201+
202+
REQUIRE(ctze.getTimeZoneOffset() == 8 * utils::time::minutesInQuarterOfHour * utils::time::secondsInMinute);
203+
REQUIRE(ctze.getTimeZoneString() == "+08,1");
204+
ss.str(std::string());
205+
timeInfo = ctze.getGMTTime();
206+
ss << std::put_time(&timeInfo, "%Y/%m/%d,%H:%M:%S");
207+
REQUIRE(ss.str() == "2020/10/21,13:49:57");
200208
}
201209

202210
SECTION("ctze -08")
@@ -208,6 +216,31 @@ TEST_CASE("+CTZE")
208216
std::ostringstream ss;
209217
ss << std::put_time(&timeInfo, "%Y/%m/%d,%H:%M:%S");
210218
REQUIRE(ss.str() == "2020/10/21,11:49:57");
219+
220+
REQUIRE(ctze.getTimeZoneOffset() == -8 * utils::time::minutesInQuarterOfHour * utils::time::secondsInMinute);
221+
REQUIRE(ctze.getTimeZoneString() == "-08,1");
222+
ss.str(std::string());
223+
timeInfo = ctze.getGMTTime();
224+
ss << std::put_time(&timeInfo, "%Y/%m/%d,%H:%M:%S");
225+
REQUIRE(ss.str() == "2020/10/21,13:49:57");
226+
}
227+
228+
SECTION("ctze -00")
229+
{
230+
auto ctze = at::urc::CTZE("+CTZE: \"-00\",0,\"2020/10/21,13:49:57\"");
231+
REQUIRE(ctze.is());
232+
REQUIRE(ctze.isValid());
233+
auto timeInfo = ctze.getTimeInfo();
234+
std::ostringstream ss;
235+
ss << std::put_time(&timeInfo, "%Y/%m/%d,%H:%M:%S");
236+
REQUIRE(ss.str() == "2020/10/21,13:49:57");
237+
238+
REQUIRE(ctze.getTimeZoneOffset() == 0);
239+
REQUIRE(ctze.getTimeZoneString() == "-00,0");
240+
ss.str(std::string());
241+
timeInfo = ctze.getGMTTime();
242+
ss << std::put_time(&timeInfo, "%Y/%m/%d,%H:%M:%S");
243+
REQUIRE(ss.str() == "2020/10/21,13:49:57");
211244
}
212245

213246
SECTION("too short")

module-services/service-cellular/ServiceCellular.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,12 @@ ServiceCellular::~ServiceCellular()
187187
LOG_INFO("[ServiceCellular] Cleaning resources");
188188
}
189189

190+
// this static function will be replaced by Settings API
191+
static bool isSettingsAutomaticTimeSyncEnabled()
192+
{
193+
return true;
194+
}
195+
190196
void ServiceCellular::CallStateTimerHandler()
191197
{
192198
std::shared_ptr<CellularRequestMessage> msg =
@@ -977,8 +983,6 @@ std::optional<std::shared_ptr<CellularMessage>> ServiceCellular::identifyNotific
977983
std::string str(data.begin(), data.end());
978984

979985
std::string logStr = utils::removeNewLines(str);
980-
LOG_DEBUG("Notification:: %s", logStr.c_str());
981-
982986
if (auto ret = str.find("+CPIN: ") != std::string::npos) {
983987
/// TODO handle different sim statuses - i.e. no sim, sim error, sim puk, sim pin etc.
984988
if (str.find("NOT READY", ret) == std::string::npos) {
@@ -1075,8 +1079,9 @@ std::optional<std::shared_ptr<CellularMessage>> ServiceCellular::identifyNotific
10751079
*message);
10761080
}
10771081
auto ctze = at::urc::CTZE(str);
1078-
if (ctze.is()) {
1079-
auto msg = std::make_shared<CellularTimeNotificationMessage>(ctze.getTimeInfo());
1082+
if (ctze.is() && isSettingsAutomaticTimeSyncEnabled()) {
1083+
auto msg = std::make_shared<CellularTimeNotificationMessage>(
1084+
ctze.getGMTTime(), ctze.getTimeZoneOffset(), ctze.getTimeZoneString());
10801085
sys::Bus::SendUnicast(msg, service::name::evt_manager, this);
10811086
return std::nullopt;
10821087
}
@@ -1594,8 +1599,10 @@ bool ServiceCellular::handle_modem_on()
15941599
bool ServiceCellular::handle_URCReady()
15951600
{
15961601
auto channel = cmux->get(TS0710::Channel::Commands);
1597-
channel->cmd(at::AT::ENABLE_TIME_ZONE_UPDATE);
1598-
channel->cmd(at::AT::SET_TIME_ZONE_REPORTING);
1602+
if (isSettingsAutomaticTimeSyncEnabled()) {
1603+
channel->cmd(at::AT::ENABLE_TIME_ZONE_UPDATE);
1604+
channel->cmd(at::AT::SET_TIME_ZONE_REPORTING);
1605+
}
15991606
channel->cmd(at::AT::ENABLE_NETWORK_REGISTRATION_URC);
16001607
LOG_DEBUG("%s", state.c_str());
16011608
return true;

module-services/service-cellular/messages/CellularMessage.hpp

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,17 +83,40 @@ class CellularNotificationMessage : public CellularMessage
8383
class CellularTimeNotificationMessage : public CellularMessage
8484
{
8585
private:
86-
struct tm time;
86+
std::optional<struct tm> time;
87+
std::optional<int> timeZoneGmtOff;
88+
std::optional<std::string> timeZoneString;
8789

8890
public:
8991
CellularTimeNotificationMessage() = delete;
92+
explicit CellularTimeNotificationMessage(struct tm time, long int timeZoneGmtOff, std::string timeZoneString)
93+
: CellularMessage(MessageType::CellularTimeUpdated), time(time), timeZoneGmtOff(timeZoneGmtOff),
94+
timeZoneString(timeZoneString)
95+
{}
96+
97+
explicit CellularTimeNotificationMessage(long int timeZoneGmtOff, std::string timeZoneString)
98+
: CellularMessage(MessageType::CellularTimeUpdated), timeZoneGmtOff(timeZoneGmtOff),
99+
timeZoneString(timeZoneString)
100+
{}
101+
90102
explicit CellularTimeNotificationMessage(struct tm time)
91103
: CellularMessage(MessageType::CellularTimeUpdated), time(time)
92104
{}
93-
struct tm getTime(void)
105+
106+
std::optional<struct tm> getTime(void)
94107
{
95108
return time;
96109
}
110+
111+
std::optional<long int> getTimeZoneOffset(void)
112+
{
113+
return timeZoneGmtOff;
114+
}
115+
116+
std::optional<const std::string> getTimeZoneString(void)
117+
{
118+
return timeZoneString;
119+
}
97120
};
98121
class CellularUSSDMessage : public CellularMessage
99122
{

module-services/service-db/test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ add_catch2_executable(
99
test-service-db-settings-api.cpp
1010
LIBS
1111
module-services
12+
module-utils
1213
)

module-services/service-evtmgr/EventManager.cpp

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include "service-audio/messages/AudioMessage.hpp" // for AudioEventRequest
4242
#include "service-evtmgr/messages/BatteryMessages.hpp" // for BatteryLevelMessage, BatteryPlugMessage
4343
#include "service-evtmgr/messages/KbdMessage.hpp" // for KbdMessage
44+
#include "module-utils/time/time_conversion.hpp" // for Time Zone handling
4445

4546
EventManager::EventManager(const std::string &name) : sys::Service(name)
4647
{
@@ -57,6 +58,17 @@ EventManager::~EventManager()
5758
}
5859
}
5960

61+
// those static functions and variables will be replaced by Settings API
62+
static std::string tzSet;
63+
static void setSettingsTimeZone(const std::string &timeZone)
64+
{
65+
tzSet = timeZone;
66+
}
67+
std::string getSettingsTimeZone()
68+
{
69+
return tzSet;
70+
}
71+
6072
// Invoked upon receiving data message
6173
sys::Message_t EventManager::DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp)
6274
{
@@ -211,9 +223,14 @@ sys::Message_t EventManager::DataReceivedHandler(sys::DataMessage *msgl, sys::Re
211223
else if (msgl->messageType == MessageType::CellularTimeUpdated) {
212224
auto msg = dynamic_cast<CellularTimeNotificationMessage *>(msgl);
213225
if (msg != nullptr) {
214-
auto time = msg->getTime();
215-
bsp::rtc_SetDateTime(&time);
216-
LOG_INFO("RTC set by network time.");
226+
if (auto time = msg->getTime(); time) {
227+
LOG_INFO("RTC set by network time.");
228+
bsp::rtc_SetDateTime(&time.value());
229+
}
230+
if (auto timeZoneOffset = msg->getTimeZoneOffset(); timeZoneOffset) {
231+
setSettingsTimeZone(msg->getTimeZoneString().value());
232+
utils::time::Time::setTimeZoneOffset(msg->getTimeZoneOffset().value());
233+
}
217234
auto notification = std::make_shared<sys::DataMessage>(MessageType::EVMTimeUpdated);
218235
sys::Bus::SendMulticast(notification, sys::BusChannels::ServiceEvtmgrNotifications, this);
219236
}

module-utils/Utils.hpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -169,18 +169,16 @@ namespace utils
169169
findAndReplaceAll(data, {{toSearch, replaceStr}});
170170
}
171171

172-
static inline bool toNumeric(const std::string &text, uint32_t &value)
172+
static inline bool toNumeric(const std::string &text, int &value)
173173
{
174174
try {
175175
value = std::stoi(text);
176-
return true;
177176
}
178177
catch (const std::exception &e) {
179178
LOG_ERROR("toNumeric exception %s", e.what());
180179
return false;
181180
}
182-
183-
return false;
181+
return true;
184182
}
185183

186184
static inline uint32_t swapBytes(uint32_t toSwap)

0 commit comments

Comments
 (0)