M image/assets/lang/English.json => image/assets/lang/English.json +2 -1
@@ 503,5 503,6 @@
"app_desktop_update_start": "Update start",
"app_desktop_update_size": "size",
"app_desktop_update_bytes": "bytes",
- "app_desktop_update_unpacking": "Unpacking"
+ "app_desktop_update_unpacking": "Unpacking",
+ "app_call_private_number": "Private number"
}
M module-apps/application-call/ApplicationCall.cpp => module-apps/application-call/ApplicationCall.cpp +44 -34
@@ 50,40 50,27 @@ namespace app
switchWindow(app::window::name_emergencyCall, std::forward<decltype(data)>(data));
return msgHandled();
});
-
- auto convertibleToActionHandler = [this](sys::Message *request) { return HandleMessageAsAction(request); };
- connect(typeid(CellularActionResponseMessage), convertibleToActionHandler);
- }
-
- auto ApplicationCall::HandleMessageAsAction(sys::Message *request) -> std::shared_ptr<sys::ResponseMessage>
- {
- auto actionMsg = dynamic_cast<manager::actions::ConvertibleToAction *>(request);
- if (!actionMsg) {
- return std::make_shared<sys::ResponseMessage>(sys::ReturnCodes::Failure);
- }
-
- auto buttonAction = [=]() -> bool {
- returnToPreviousWindow();
- return true;
- };
-
- constexpr auto iconNoEmergency = "emergency_W_G";
- auto textNoEmergency = utils::localize.get("app_call_wrong_emergency");
- constexpr auto iconNoSim = "info_big_circle_W_G";
- const auto textNoSim = utils::localize.get("app_call_no_sim");
-
- auto action = actionMsg->toAction();
-
- switch (const auto actionId = action->getAction(); actionId) {
- case app::manager::actions::CallRejectNotEmergency:
- utils::findAndReplaceAll(textNoEmergency, "$NUMBER", action->getData()->getDescription());
+ addActionReceiver(manager::actions::NotAnEmergencyNotification, [this](auto &&data) {
+ auto buttonAction = [=]() -> bool {
+ returnToPreviousWindow();
+ return true;
+ };
+ constexpr auto iconNoEmergency = "emergency_W_G";
+ auto textNoEmergency = utils::localize.get("app_call_wrong_emergency");
+ utils::findAndReplaceAll(textNoEmergency, "$NUMBER", data->getDescription());
showNotification(buttonAction, iconNoEmergency, textNoEmergency);
- break;
- case app::manager::actions::CallRejectNoSim:
+ return msgHandled();
+ });
+ addActionReceiver(manager::actions::NoSimNotification, [this](auto &&data) {
+ auto buttonAction = [=]() -> bool {
+ returnToPreviousWindow();
+ return true;
+ };
+ constexpr auto iconNoSim = "info_big_circle_W_G";
+ const auto textNoSim = utils::localize.get("app_call_no_sim");
showNotification(buttonAction, iconNoSim, textNoSim);
- break;
- }
- return std::make_shared<sys::ResponseMessage>();
+ return msgHandled();
+ });
}
// number of seconds after end call to switch back to previous application
@@ 99,14 86,34 @@ namespace app
manager::Controller::sendAction(this, manager::actions::Call, std::make_unique<app::CallActiveData>());
}
- void ApplicationCall::IncomingCallHandler(const CellularCallMessage *const msg)
+ void ApplicationCall::CallerIdHandler(const CellularCallMessage *const msg)
{
- if (state == call::State::IDLE) {
+ if (getState() == call::State::IDLE) {
+ if (callerIdTimer) {
+ callerIdTimer->stop();
+ callerIdTimer.reset(nullptr);
+ }
manager::Controller::sendAction(
this, manager::actions::Call, std::make_unique<app::IncomingCallData>(msg->number));
}
}
+ void ApplicationCall::IncomingCallHandler(const CellularCallMessage *const msg)
+ {
+ if (getState() == call::State::IDLE) {
+ constexpr sys::ms callerIdTimeout = 1000;
+ callerIdTimer =
+ std::make_unique<sys::Timer>("CallerIdTimer", this, callerIdTimeout, sys::Timer::Type::SingleShot);
+ callerIdTimer->connect([=](sys::Timer &) {
+ callerIdTimer->stop();
+ manager::Controller::sendAction(
+ this,
+ manager::actions::Call,
+ std::make_unique<app::IncomingCallData>(utils::PhoneNumber().getView()));
+ });
+ }
+ }
+
void ApplicationCall::RingingHandler(const CellularCallMessage *const msg)
{
manager::Controller::sendAction(
@@ 153,6 160,9 @@ namespace app
case CellularCallMessage::Type::IncomingCall: {
IncomingCallHandler(msg);
} break;
+ case CellularCallMessage::Type::CallerId: {
+ CallerIdHandler(msg);
+ } break;
}
}
M module-apps/application-call/ApplicationCall.hpp => module-apps/application-call/ApplicationCall.hpp +7 -2
@@ 32,6 32,7 @@ namespace app
class CallWindowInterface
{
public:
+ using NumberChangeCallback = std::function<void(utils::PhoneNumber::View)>;
virtual ~CallWindowInterface() noexcept = default;
virtual void setState(app::call::State state) noexcept = 0;
@@ 70,8 71,10 @@ namespace app
void CallAbortHandler();
void CallActiveHandler();
void IncomingCallHandler(const CellularCallMessage *const msg);
+ void CallerIdHandler(const CellularCallMessage *const msg);
void RingingHandler(const CellularCallMessage *const msg);
- auto HandleMessageAsAction(sys::Message *request) -> std::shared_ptr<sys::ResponseMessage>;
+
+ std::unique_ptr<sys::Timer> callerIdTimer;
protected:
call::State state = call::State::IDLE;
@@ 124,7 127,9 @@ namespace app
return {{manager::actions::Launch,
manager::actions::Call,
manager::actions::Dial,
- manager::actions::EmergencyDial}};
+ manager::actions::EmergencyDial,
+ manager::actions::NotAnEmergencyNotification,
+ manager::actions::NoSimNotification}};
}
};
} /* namespace app */
M module-apps/application-call/data/CallAppStyle.hpp => module-apps/application-call/data/CallAppStyle.hpp +1 -0
@@ 25,6 25,7 @@ namespace callAppStyle
inline constexpr auto speaker = "app_call_speaker";
inline constexpr auto speakeron = "app_call_speaker_on";
inline constexpr auto bluetooth = "app_call_bluetooth";
+ inline constexpr auto privateNumber = "app_call_private_number";
} // namespace strings
namespace numberLabel
M module-apps/application-call/windows/CallWindow.cpp => module-apps/application-call/windows/CallWindow.cpp +31 -17
@@ 162,15 162,22 @@ namespace gui
switch (state) {
case State::INCOMING_CALL: {
interface->startAudioRinging();
- bottomBar->setActive(gui::BottomBar::Side::CENTER, true);
bottomBar->setText(gui::BottomBar::Side::LEFT, utils::localize.get(strings::answer), true);
bottomBar->setText(gui::BottomBar::Side::RIGHT, utils::localize.get(strings::reject), true);
durationLabel->setText(utils::localize.get(strings::iscalling));
durationLabel->setVisible(true);
- sendSmsIcon->setVisible(true);
speakerIcon->setVisible(false);
microphoneIcon->setVisible(false);
- setFocusItem(sendSmsIcon);
+ if (phoneNumber.getFormatted().empty()) {
+ bottomBar->setActive(gui::BottomBar::Side::CENTER, false);
+ sendSmsIcon->setVisible(false);
+ setFocusItem(nullptr);
+ }
+ else {
+ bottomBar->setActive(gui::BottomBar::Side::CENTER, true);
+ sendSmsIcon->setVisible(true);
+ setFocusItem(sendSmsIcon);
+ }
} break;
case State::CALL_ENDED: {
interface->stopAudio();
@@ 222,6 229,7 @@ namespace gui
stopCallTimer();
[[fallthrough]];
default:
+ numberLabel->clear();
bottomBar->setActive(gui::BottomBar::Side::LEFT, false);
bottomBar->setActive(gui::BottomBar::Side::CENTER, false);
bottomBar->setActive(gui::BottomBar::Side::RIGHT, false);
@@ 249,22 257,27 @@ namespace gui
void CallWindow::onBeforeShow(ShowMode mode, SwitchData *data)
{
if (auto callData = dynamic_cast<app::CallSwitchData *>(data); callData != nullptr) {
- phoneNumber = callData->getPhoneNumber();
- auto contact = DBServiceAPI::MatchContactByPhoneNumber(this->application, phoneNumber);
- auto displayName = phoneNumber.getFormatted();
- if (contact) {
- LOG_INFO("number = %s recognized as contact id = %" PRIu32 ", name = %s",
- phoneNumber.getEntered().c_str(),
- contact->ID,
- contact->getFormattedName().c_str());
- displayName = contact->getFormattedName();
+ phoneNumber = callData->getPhoneNumber();
+ if (!callData->getPhoneNumber().getFormatted().empty()) {
+ auto contact = DBServiceAPI::MatchContactByPhoneNumber(this->application, phoneNumber);
+ auto displayName = phoneNumber.getFormatted();
+ if (contact) {
+ LOG_INFO("number = %s recognized as contact id = %" PRIu32 ", name = %s",
+ phoneNumber.getEntered().c_str(),
+ contact->ID,
+ contact->getFormattedName().c_str());
+ displayName = contact->getFormattedName();
+ }
+ else {
+ LOG_INFO("number = %s was not recognized as any valid contact", phoneNumber.getEntered().c_str());
+ }
+
+ numberLabel->setText(displayName);
}
else {
- LOG_INFO("number = %s was not recognized as any valid contact", phoneNumber.getEntered().c_str());
+ numberLabel->setText(utils::localize.get(strings::privateNumber));
}
- numberLabel->setText(displayName);
-
if (dynamic_cast<app::IncomingCallData *>(data) != nullptr) {
if (getState() == State::INCOMING_CALL) {
LOG_DEBUG("ignoring IncomingCallData message");
@@ 317,8 330,8 @@ namespace gui
case State::CALL_IN_PROGRESS:
interface->hangupCall();
return true;
- break;
- default:
+ case State::IDLE:
+ case State::CALL_ENDED:
break;
}
@@ 411,4 424,5 @@ namespace gui
callDuration = std::chrono::seconds().zero();
stop_timer = true;
}
+
} /* namespace gui */
M module-apps/application-calllog/CalllogModel.cpp => module-apps/application-calllog/CalllogModel.cpp +26 -11
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "CalllogModel.hpp"
@@ 61,20 61,11 @@ gui::ListItem *CalllogModel::getItem(gui::Order order)
auto item = new gui::CalllogItem(this, !(application->isTimeFormat12()));
- item->setCall(call);
- item->activatedCallback = [=](gui::Item &item) {
- LOG_INFO("activatedCallback");
- std::unique_ptr<gui::SwitchData> data = std::make_unique<calllog::CallLogSwitchData>(*call);
- application->switchWindow(calllog::settings::DetailsWindowStr, std::move(data));
- return true;
- };
-
- item->inputCallback = [this, item](gui::Item &, const gui::InputEvent &event) {
+ auto callCallback = [this, item](gui::Item &, const gui::InputEvent &event) {
if (event.state != gui::InputEvent::State::keyReleasedShort) {
return false;
}
if (event.keyCode == gui::KeyCode::KEY_LF) {
- LOG_DEBUG("calling");
return app::manager::Controller::sendAction(
application,
app::manager::actions::Dial,
@@ 82,5 73,29 @@ gui::ListItem *CalllogModel::getItem(gui::Order order)
}
return false;
};
+
+ item->focusChangedCallback = [=](gui::Item &item) {
+ if (item.focus == true) {
+ auto &callLogItem = dynamic_cast<gui::CalllogItem &>(item);
+ if (callLogItem.getCall().presentation == PresentationType::PR_UNKNOWN) {
+ // disable call button since the number is unknown
+ application->getCurrentWindow()->setBottomBarActive(gui::BottomBar::Side::LEFT, false);
+ item.inputCallback = nullptr;
+ }
+ else {
+ application->getCurrentWindow()->setBottomBarActive(gui::BottomBar::Side::LEFT, true);
+ item.inputCallback = callCallback;
+ }
+ }
+ return true;
+ };
+
+ item->setCall(call);
+ item->activatedCallback = [=](gui::Item &item) {
+ std::unique_ptr<gui::SwitchData> data = std::make_unique<calllog::CallLogSwitchData>(*call);
+ application->switchWindow(calllog::settings::DetailsWindowStr, std::move(data));
+ return true;
+ };
+
return item;
}
M module-apps/application-calllog/data/CallLogStyle.hpp => module-apps/application-calllog/data/CallLogStyle.hpp +5 -1
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 7,6 7,10 @@
// CALL LOG STYLE
namespace callLogStyle
{
+ namespace strings
+ {
+ inline constexpr auto privateNumber = "app_call_private_number";
+ }
// DETAILS WINDOW
namespace detailsWindow
{
M module-apps/application-calllog/widgets/CalllogItem.cpp => module-apps/application-calllog/widgets/CalllogItem.cpp +6 -1
@@ 63,7 63,12 @@ namespace gui
void CalllogItem::setCall(std::shared_ptr<CalllogRecord> &call)
{
this->call = call;
- text->setText(call->name);
+ if (call->presentation == PresentationType::PR_UNKNOWN) {
+ text->setText(utils::localize.get(callLogStyle::strings::privateNumber));
+ }
+ else {
+ text->setText(call->name);
+ }
auto callType = calllog::toCallLogCallType(call->type);
if (callType == calllog::CallLogCallType::MISSED) {
M module-apps/application-calllog/windows/CallLogDetailsWindow.cpp => module-apps/application-calllog/windows/CallLogDetailsWindow.cpp +15 -3
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "CallLogDetailsWindow.hpp"
@@ 206,8 206,6 @@ namespace gui
setTitle(record.name);
- number->setText(record.phoneNumber.getFormatted());
-
auto callType = toCallLogCallType(record.type);
for (auto &img : callTypeImg) {
img->setVisible(false);
@@ 243,6 241,20 @@ namespace gui
if (mode == ShowMode::GUI_SHOW_INIT)
setFocusItem(rects[static_cast<uint32_t>(FocusRects::Call)]);
+
+ if (record.presentation == PresentationType::PR_UNKNOWN) {
+ rects[FocusRects::Call]->setVisible(false);
+ rects[FocusRects::Call]->activatedCallback = nullptr;
+ rects[FocusRects::Call]->focusChangedCallback = nullptr;
+ rects[FocusRects::Sms]->setVisible(false);
+ rects[FocusRects::Sms]->activatedCallback = nullptr;
+ rects[FocusRects::Sms]->focusChangedCallback = nullptr;
+ number->setText(utils::localize.get(callLogStyle::strings::privateNumber));
+ bottomBar->setActive(BottomBar::Side::CENTER, false);
+ }
+ else {
+ number->setText(record.phoneNumber.getFormatted());
+ }
}
bool CallLogDetailsWindow::onInput(const InputEvent &inputEvent)
M module-apps/application-calllog/windows/CallLogMainWindow.cpp => module-apps/application-calllog/windows/CallLogMainWindow.cpp +7 -4
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "CallLogMainWindow.hpp"
@@ 13,6 13,7 @@
#include <Label.hpp>
#include <Margins.hpp>
#include <Style.hpp>
+#include <InputEvent.hpp>
#include <cassert>
#include <functional>
@@ 75,8 76,10 @@ namespace gui
bool CallLogMainWindow::onDatabaseMessage(sys::Message *msgl)
{
- DBCalllogResponseMessage *msg = reinterpret_cast<DBCalllogResponseMessage *>(msgl);
- return calllogModel->updateRecords(std::move(*msg->records));
+ auto *msg = dynamic_cast<DBCalllogResponseMessage *>(msgl);
+ if (msg != nullptr) {
+ return calllogModel->updateRecords(std::move(*msg->records));
+ }
+ return false;
}
-
} /* namespace gui */
M module-apps/application-calllog/windows/CallLogMainWindow.hpp => module-apps/application-calllog/windows/CallLogMainWindow.hpp +1 -1
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
M module-apps/application-calllog/windows/CallLogOptionsWindow.cpp => module-apps/application-calllog/windows/CallLogOptionsWindow.cpp +13 -12
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "CallLogOptionsWindow.hpp"
@@ 10,19 10,20 @@
std::list<gui::Option> calllogWindowOptions(app::ApplicationCallLog *app, const CalllogRecord &record)
{
- auto searchResults = DBServiceAPI::ContactGetByIDWithTemporary(app, record.getContactId());
-
std::list<gui::Option> options;
+ if (record.presentation != PresentationType::PR_UNKNOWN) {
+ auto searchResults = DBServiceAPI::ContactGetByIDWithTemporary(app, record.getContactId());
- if (searchResults->empty() || !searchResults->front().isValid() || searchResults->front().isTemporary()) {
- // add option - add contact
- options.emplace_back(gui::Option{
- std::make_unique<gui::option::Contact>(app, gui::option::ContactOperation::Add, searchResults->front())});
- }
- else {
- // add option - contact details
- options.emplace_back(gui::Option{std::make_unique<gui::option::Contact>(
- app, gui::option::ContactOperation::Details, searchResults->front())});
+ if (searchResults->empty() || !searchResults->front().isValid() || searchResults->front().isTemporary()) {
+ // add option - add contact
+ options.emplace_back(gui::Option{std::make_unique<gui::option::Contact>(
+ app, gui::option::ContactOperation::Add, searchResults->front())});
+ }
+ else {
+ // add option - contact details
+ options.emplace_back(gui::Option{std::make_unique<gui::option::Contact>(
+ app, gui::option::ContactOperation::Details, searchResults->front())});
+ }
}
// add option delete call option
M module-apps/windows/AppWindow.hpp => module-apps/windows/AppWindow.hpp +1 -1
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
M module-cellular/CMakeLists.txt => module-cellular/CMakeLists.txt +1 -0
@@ 34,6 34,7 @@ set(SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/at/src/UrcCpin.cpp
${CMAKE_CURRENT_SOURCE_DIR}/at/src/UrcQiurc.cpp
${CMAKE_CURRENT_SOURCE_DIR}/at/src/UrcPoweredDown.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/at/src/UrcRing.cpp
${CMAKE_CURRENT_SOURCE_DIR}/at/src/UrcResponse.cpp
${CMAKE_CURRENT_SOURCE_DIR}/at/src/UrcFactory.cpp
${CMAKE_CURRENT_SOURCE_DIR}/at/src/Commands.cpp
M module-cellular/at/UrcHandler.hpp => module-cellular/at/UrcHandler.hpp +3 -1
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 13,6 13,7 @@ namespace at::urc
class Qind;
class Cpin;
class Qiurc;
+ class Ring;
class PoweredDown;
class UrcResponse;
@@ 27,6 28,7 @@ namespace at::urc
virtual void Handle(Qind &urc) = 0;
virtual void Handle(Cpin &urc) = 0;
virtual void Handle(Qiurc &urc) = 0;
+ virtual void Handle(Ring &urc) = 0;
virtual void Handle(PoweredDown &urc) = 0;
virtual void Handle(UrcResponse &urc) = 0;
};
A module-cellular/at/UrcRing.hpp => module-cellular/at/UrcRing.hpp +42 -0
@@ 0,0 1,42 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include "Urc.hpp"
+
+namespace at::urc
+{
+ class Ring : public Urc
+ {
+ public:
+ enum RingType
+ {
+ Normal,
+ Async,
+ Sync,
+ RelAsync,
+ RelSync,
+ Fax,
+ Voice
+ };
+
+ static constexpr std::string_view headUnsolicited = "+CRING";
+ static constexpr std::string_view headNormal = "RING";
+
+ static auto isURC(const std::string &uHead) -> bool
+ {
+ return uHead.find(Ring::headUnsolicited) == 0 || uHead.find(Ring::headNormal) == 0;
+ }
+
+ using Urc::Urc;
+
+ [[nodiscard]] auto isValid() const noexcept -> bool override;
+ [[nodiscard]] auto getType() const -> std::optional<enum RingType>;
+
+ void Handle(UrcHandler &h) final
+ {
+ h.Handle(*this);
+ }
+ };
+} // namespace at::urc
M module-cellular/at/src/Urc.cpp => module-cellular/at/src/Urc.cpp +2 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include <Urc.hpp>
@@ 6,7 6,7 @@
namespace at::urc
{
- Urc::Urc(const std::string &urcBody, const std::string &urcHead) : urcBody(urcBody), urcHead(urcHead)
+ Urc::Urc(const std::string &urcBody, const std::string &urcHead) : urcBody(utils::trim(urcBody)), urcHead(urcHead)
{
split(urcBody);
}
M module-cellular/at/src/UrcFactory.cpp => module-cellular/at/src/UrcFactory.cpp +7 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include <UrcFactory.hpp>
@@ 13,6 13,8 @@
#include <UrcResponse.hpp>
#include <UrcCpin.hpp>
#include <UrcQiurc.hpp>
+#include <UrcRing.hpp>
+
using namespace at::urc;
std::unique_ptr<Urc> UrcFactory::Create(const std::string &urcMessage)
@@ 22,7 24,7 @@ std::unique_ptr<Urc> UrcFactory::Create(const std::string &urcMessage)
}
const char headDelimiter = ':';
auto it = std::find(urcMessage.begin(), urcMessage.end(), headDelimiter);
- std::string head = std::string(urcMessage.begin(), it);
+ std::string head = utils::trim(std::string(urcMessage.begin(), it));
std::string body = std::string(it == urcMessage.end() ? urcMessage.begin() : it + 1, urcMessage.end());
if (Ctze::isURC(head)) {
@@ 49,6 51,9 @@ std::unique_ptr<Urc> UrcFactory::Create(const std::string &urcMessage)
else if (PoweredDown::isURC(head)) {
return std::make_unique<PoweredDown>(body);
}
+ else if (Ring::isURC(head)) {
+ return std::make_unique<Ring>(body);
+ }
else if (auto type = UrcResponse::isURC(head)) {
return std::make_unique<UrcResponse>(type.value());
}
A module-cellular/at/src/UrcRing.cpp => module-cellular/at/src/UrcRing.cpp +39 -0
@@ 0,0 1,39 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include <UrcRing.hpp>
+
+auto at::urc::Ring::isValid() const noexcept -> bool
+{
+ if (getType() == std::nullopt) {
+ return false;
+ }
+ return Urc::isValid();
+}
+
+auto at::urc::Ring::getType() const -> std::optional<at::urc::Ring::RingType>
+{
+ if (urcBody == at::urc::Ring::headNormal) {
+ return at::urc::Ring::RingType::Normal;
+ }
+ else if (urcBody == "ASYNC") {
+ return at::urc::Ring::RingType::Async;
+ }
+ else if (urcBody == "SYNC") {
+ return at::urc::Ring::RingType::Sync;
+ }
+ else if (urcBody == "REL ASYNC") {
+ return at::urc::Ring::RingType::RelAsync;
+ }
+ else if (urcBody == "REL SYNC") {
+ return at::urc::Ring::RingType::RelSync;
+ }
+ else if (urcBody == "FAX") {
+ return at::urc::Ring::RingType::Fax;
+ }
+ else if (urcBody == "VOICE") {
+ return at::urc::Ring::RingType::Voice;
+ }
+
+ return std::nullopt;
+}
M module-cellular/test/unittest_URC.cpp => module-cellular/test/unittest_URC.cpp +36 -6
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "Utils.hpp"
@@ 18,6 18,7 @@
#include "UrcClip.hpp"
#include "UrcCpin.hpp"
#include "UrcQiurc.hpp"
+#include "UrcRing.hpp"
#include "UrcPoweredDown.hpp"
#include "UrcResponse.hpp"
#include "UrcFactory.hpp"
@@ 753,11 754,6 @@ TEST_CASE("Urc RESPONSE")
REQUIRE(rsp);
REQUIRE(rsp->getURCResponseType() == at::urc::UrcResponse::URCResponseType::Connect);
- urc = at::urc::UrcFactory::Create("RING");
- rsp = getURC<at::urc::UrcResponse>(urc);
- REQUIRE(rsp);
- REQUIRE(rsp->getURCResponseType() == at::urc::UrcResponse::URCResponseType::Ring);
-
urc = at::urc::UrcFactory::Create("NO CARRIER");
rsp = getURC<at::urc::UrcResponse>(urc);
REQUIRE(rsp);
@@ 841,3 837,37 @@ TEST_CASE("+Qiurc: TCP Context and connection message")
REQUIRE(qiurc->getType() == std::nullopt);
}
}
+
+TEST_CASE("RING")
+{
+ struct RingTest
+ {
+ std::string body;
+ std::optional<at::urc::Ring::RingType> ringType;
+ };
+
+ std::vector<RingTest> testCases = {
+ {"RING", at::urc::Ring::Normal},
+ {"+CRING: ASYNC", at::urc::Ring::Async},
+ {"+CRING: SYNC", at::urc::Ring::Sync},
+ {"+CRING: REL ASYNC", at::urc::Ring::RelAsync},
+ {"\r\n+CRING: REL SYNC", at::urc::Ring::RelSync},
+ {"+CRING: FAX", at::urc::Ring::Fax},
+ {"+CRING: VOICE", at::urc::Ring::Voice},
+ {"+CRING: BUMMER", std::nullopt},
+ };
+
+ for (auto &test : testCases) {
+ auto urc = at::urc::UrcFactory::Create(test.body);
+ auto ring = getURC<at::urc::Ring>(urc);
+ REQUIRE(ring);
+ if (test.ringType) {
+ REQUIRE(ring->getType());
+ REQUIRE(ring->getType().value() == test.ringType);
+ }
+ else {
+ REQUIRE(!ring->isValid());
+ REQUIRE(!ring->getType());
+ }
+ }
+}
M module-db/Interface/CalllogRecord.cpp => module-db/Interface/CalllogRecord.cpp +49 -21
@@ 47,19 47,29 @@ CalllogRecordInterface::CalllogRecordInterface(CalllogDB *calllogDb, ContactsDB
bool CalllogRecordInterface::Add(const CalllogRecord &rec)
{
- ContactRecordInterface contactInterface(contactsDB);
- auto contactMatch =
- contactInterface.MatchByNumber(rec.phoneNumber, ContactRecordInterface::CreateTempContact::True);
- if (!contactMatch) {
- LOG_ERROR("Cannot get contact, for number %s", rec.phoneNumber.getNonEmpty().c_str());
- return false;
- }
- auto &contactRec = contactMatch->contact;
-
auto localRec = rec;
- localRec.contactId = contactRec.ID;
- localRec.name = contactRec.getFormattedName();
- LOG_DEBUG("Adding calllog record %s", utils::to_string(localRec).c_str());
+ if (!rec.phoneNumber.getFormatted().empty()) {
+ ContactRecordInterface contactInterface(contactsDB);
+ auto contactMatch =
+ contactInterface.MatchByNumber(rec.phoneNumber, ContactRecordInterface::CreateTempContact::True);
+ if (!contactMatch) {
+ LOG_ERROR("Cannot get contact, for number %s", rec.phoneNumber.getNonEmpty().c_str());
+ return false;
+ }
+ auto &contactRec = contactMatch->contact;
+
+ localRec.contactId = contactRec.ID;
+ localRec.name = contactRec.getFormattedName();
+ if (localRec.presentation == PresentationType::PR_UNKNOWN) {
+ localRec.presentation = PresentationType::PR_ALLOWED;
+ }
+ LOG_DEBUG("Adding call log record %s", utils::to_string(localRec).c_str());
+ }
+ else {
+ // private number so do not add contact just call log entry
+ localRec.presentation = PresentationType::PR_UNKNOWN;
+ LOG_DEBUG("Adding private call entry to call log record.");
+ }
return calllogDB->calls.add(CalllogTableRow{{.ID = localRec.ID}, // this is only to remove warning
.number = localRec.phoneNumber.getEntered(),
@@ 71,7 81,6 @@ bool CalllogRecordInterface::Add(const CalllogRecord &rec)
.name = localRec.name,
.contactId = localRec.contactId,
.isRead = localRec.isRead});
- ;
}
uint32_t CalllogRecordInterface::GetLastID()
@@ 119,21 128,37 @@ std::unique_ptr<std::vector<CalllogRecord>> CalllogRecordInterface::GetLimitOffs
bool CalllogRecordInterface::Update(const CalllogRecord &rec)
{
-
auto call = calllogDB->calls.getById(rec.ID);
if (!call.isValid()) {
return false;
}
+ auto contactID = rec.contactId;
+ auto presentation = rec.presentation;
+ if (call.presentation == PresentationType::PR_UNKNOWN && rec.phoneNumber.isValid()) {
+ // entry added as private was updated with phone number
+ ContactRecordInterface contactInterface(contactsDB);
+ auto contactMatch =
+ contactInterface.MatchByNumber(rec.phoneNumber, ContactRecordInterface::CreateTempContact::True);
+ if (!contactMatch) {
+ LOG_ERROR("Cannot get or create temporary contact for number %s", rec.phoneNumber.getNonEmpty().c_str());
+ return false;
+ }
+ contactID = contactMatch->contact.ID;
+ if (presentation == PresentationType::PR_UNKNOWN) {
+ presentation = PresentationType::PR_ALLOWED;
+ }
+ }
+
return calllogDB->calls.update(CalllogTableRow{{.ID = rec.ID},
.number = rec.phoneNumber.getEntered(),
.e164number = rec.phoneNumber.getE164(),
- .presentation = rec.presentation,
+ .presentation = presentation,
.date = rec.date,
.duration = rec.duration,
.type = rec.type,
.name = rec.name,
- .contactId = rec.contactId,
+ .contactId = contactID,
.isRead = rec.isRead});
}
@@ 165,13 190,16 @@ CalllogRecord CalllogRecordInterface::GetByID(uint32_t id)
{
auto call = calllogDB->calls.getById(id);
- auto contactRec = GetContactRecordByID(call.contactId);
- if (contactRec.ID == DB_ID_NONE) {
- LOG_ERROR("Cannot find contact for ID %" PRIu32, call.contactId);
- return CalllogRecord();
+ if (call.contactId != DB_ID_NONE) {
+ auto contactRec = GetContactRecordByID(call.contactId);
+ if (contactRec.ID == DB_ID_NONE) {
+ LOG_ERROR("Cannot find contact for ID %" PRIu32, call.contactId);
+ return CalllogRecord();
+ }
+
+ call.name = contactRec.getFormattedName();
}
- call.name = contactRec.getFormattedName();
return CalllogRecord(call);
}
M module-services/service-appmgr/model/ApplicationManager.cpp => module-services/service-appmgr/model/ApplicationManager.cpp +2 -0
@@ 295,6 295,8 @@ namespace app::manager
connect(typeid(CellularMMIResultMessage), convertibleToActionHandler);
connect(typeid(CellularMMIResponseMessage), convertibleToActionHandler);
connect(typeid(CellularMMIPushMessage), convertibleToActionHandler);
+ connect(typeid(CellularNoSimNotification), convertibleToActionHandler);
+ connect(typeid(CellularNotAnEmergencyNotification), convertibleToActionHandler);
connect(typeid(sys::CriticalBatteryLevelNotification), convertibleToActionHandler);
connect(typeid(sys::SystemBrownoutMesssage), convertibleToActionHandler);
}
M module-services/service-appmgr/service-appmgr/Actions.hpp => module-services/service-appmgr/service-appmgr/Actions.hpp +2 -2
@@ 26,8 26,8 @@ namespace app::manager
Launch,
CloseSystem,
Call,
- CallRejectNotEmergency,
- CallRejectNoSim,
+ NotAnEmergencyNotification,
+ NoSimNotification,
Dial,
EmergencyDial,
ShowCallLog,
M module-services/service-cellular/CellularCall.cpp => module-services/service-cellular/CellularCall.cpp +8 -2
@@ 29,8 29,8 @@ namespace CellularCall
CalllogRecord callRec;
callRec.type = type;
callRec.date = utils::time::Timestamp().getTime();
- callRec.name = number.getFormatted(); // temporary set name to entered number
- callRec.phoneNumber = number;
+ callRec.presentation = PresentationType::PR_UNKNOWN;
+ callRec.phoneNumber = number;
call = startCallAction ? startCallAction(callRec) : CalllogRecord();
if (!call.isValid()) {
LOG_ERROR("startCallAction failed");
@@ 95,4 95,10 @@ namespace CellularCall
return true;
}
+
+ void CellularCall::setNumber(const utils::PhoneNumber::View &number)
+ {
+ call.presentation = number.getFormatted().empty() ? PresentationType::PR_UNKNOWN : PresentationType::PR_ALLOWED;
+ call.phoneNumber = number;
+ }
} // namespace CellularCall
M module-services/service-cellular/CellularRequestHandler.cpp => module-services/service-cellular/CellularRequestHandler.cpp +14 -0
@@ 19,6 19,7 @@
#include "service-cellular/requests/ClirRequest.hpp"
#include "service-cellular/requests/ClipRequest.hpp"
#include "service-cellular/requests/CallWaitingRequest.hpp"
+#include "service-cellular/requests/RejectRequest.hpp"
#include <service-appmgr/model/ApplicationManager.hpp>
@@ 72,6 73,19 @@ void CellularRequestHandler::handle(cellular::CallRequest &request, at::Result &
request.setHandled(true);
}
+void CellularRequestHandler::handle(cellular::RejectRequest &request, at::Result &result)
+{
+ if (request.getRejectReason() == cellular::RejectRequest::RejectReason::NoSim) {
+ auto message = std::make_shared<CellularNoSimNotification>(request.getNumber());
+ cellular.bus.sendUnicast(message, app::manager::ApplicationManager::ServiceName);
+ }
+ else if (request.getRejectReason() == cellular::RejectRequest::RejectReason::NotAnEmergencyNumber) {
+ auto message = std::make_shared<CellularNotAnEmergencyNotification>(request.getNumber());
+ cellular.bus.sendUnicast(message, app::manager::ApplicationManager::ServiceName);
+ }
+ request.setHandled(true);
+}
+
void CellularRequestHandler::handle(cellular::SupplementaryServicesRequest &request, at::Result &result)
{
auto requestHandled = request.checkModemResponse(result);
M module-services/service-cellular/CellularUrcHandler.cpp => module-services/service-cellular/CellularUrcHandler.cpp +8 -3
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "CellularUrcHandler.hpp"
@@ 25,8 25,13 @@ void CellularUrcHandler::Handle(Clip &urc)
if (urc.isValid()) {
phoneNumber = urc.getNumber();
}
- // continue without number
- response = std::make_unique<CellularCallMessage>(CellularCallMessage::Type::IncomingCall, phoneNumber);
+ response = std::make_unique<CellularCallMessage>(CellularCallMessage::Type::CallerId, phoneNumber);
+ urc.setHandled(true);
+}
+
+void CellularUrcHandler::Handle(Ring &urc)
+{
+ response = std::make_unique<CellularCallMessage>(CellularCallMessage::Type::IncomingCall, "");
urc.setHandled(true);
}
M module-services/service-cellular/CellularUrcHandler.hpp => module-services/service-cellular/CellularUrcHandler.hpp +2 -0
@@ 17,6 17,7 @@
#include <module-cellular/at/UrcQind.hpp>
#include <module-cellular/at/UrcResponse.hpp>
#include <module-cellular/at/UrcQiurc.hpp>
+#include <module-cellular/at/UrcRing.hpp>
/**
* ServiceCellular helper for handling Urc messages
@@ 35,6 36,7 @@ class CellularUrcHandler : public at::urc::UrcHandler
void Handle(at::urc::Qind &urc) final;
void Handle(at::urc::Cpin &urc) final;
void Handle(at::urc::Qiurc &urc) final;
+ void Handle(at::urc::Ring &urc) final;
void Handle(at::urc::PoweredDown &urc) final;
void Handle(at::urc::UrcResponse &urc) final;
M module-services/service-cellular/RequestFactory.cpp => module-services/service-cellular/RequestFactory.cpp +4 -13
@@ 14,6 14,7 @@
#include "service-cellular/requests/PinChangeRequest.hpp"
#include "service-cellular/requests/ImeiRequest.hpp"
#include "service-cellular/requests/UssdRequest.hpp"
+#include "service-cellular/requests/RejectRequest.hpp"
#include <common_data/EventStore.hpp>
#include <cmd/QECCNUM.hpp>
@@ 57,11 58,11 @@ namespace cellular
return std::make_unique<CallRequest>(request);
}
else {
- actionRequest = app::manager::actions::Action::CallRejectNoSim;
+ return std::make_unique<RejectRequest>(RejectRequest::RejectReason::NoSim, request);
}
}
else if (requestMode == CellularCallRequestMessage::RequestMode::Emergency) {
- actionRequest = app::manager::actions::Action::CallRejectNotEmergency;
+ return std::make_unique<RejectRequest>(RejectRequest::RejectReason::NotAnEmergencyNumber, request);
}
return nullptr;
}
@@ 72,10 73,6 @@ namespace cellular
return req;
}
- if (actionRequest) {
- return nullptr;
- }
-
std::string groupA, groupB, groupC, groupD, groupE, groupF;
GroupMatch matchPack = {groupA, groupB, groupC, groupD, groupE, groupF};
@@ 120,15 117,9 @@ namespace cellular
}
if (simStatus == SimStatus::SimSlotEmpty) {
- actionRequest = app::manager::actions::Action::CallRejectNoSim;
- return nullptr;
+ return std::make_unique<RejectRequest>(RejectRequest::RejectReason::NoSim, request);
}
return std::make_unique<CallRequest>(request);
}
- std::optional<app::manager::actions::Action> &RequestFactory::getActionRequest()
- {
- return actionRequest;
- }
-
} // namespace cellular
M module-services/service-cellular/ServiceCellular.cpp => module-services/service-cellular/ServiceCellular.cpp +8 -9
@@ 768,6 768,10 @@ sys::MessagePointer ServiceCellular::DataReceivedHandler(sys::DataMessage *msgl,
responseMsg = std::make_shared<CellularResponseMessage>(ret);
break;
}
+ case CellularCallMessage::Type::CallerId: {
+ ongoingCall.setNumber(msg->number);
+ break;
+ }
}
} break;
// Incoming notifications from Notification Virtual Channel
@@ 932,15 936,10 @@ sys::MessagePointer ServiceCellular::DataReceivedHandler(sys::DataMessage *msgl,
auto request = factory.create();
- if (auto action = factory.getActionRequest(); action) {
- responseMsg = std::make_shared<CellularActionResponseMessage>(action.value(), msg->number.getEntered());
- }
- else {
- CellularRequestHandler handler(*this);
- auto result = channel->cmd(request->command(), at::default_doc_timeout);
- request->handle(handler, result);
- responseMsg = std::make_shared<CellularResponseMessage>(request->isHandled());
- }
+ CellularRequestHandler handler(*this);
+ auto result = channel->cmd(request->command(), at::default_doc_timeout);
+ request->handle(handler, result);
+ responseMsg = std::make_shared<CellularResponseMessage>(request->isHandled());
} break;
case MessageType::DBServiceNotification: {
M module-services/service-cellular/service-cellular/CellularCall.hpp => module-services/service-cellular/service-cellular/CellularCall.hpp +3 -2
@@ 8,6 8,7 @@
#include <Tables/CalllogTable.hpp>
#include <time/time_conversion.hpp>
#include <utf8/UTF8.hpp>
+#include <Utils.hpp>
#include <cstdint>
#include <functional>
@@ 73,10 74,10 @@ namespace CellularCall
endCallAction = callAction;
}
- bool startCall(const utils::PhoneNumber::View &number, const CallType type);
-
bool setActive();
+ void setNumber(const utils::PhoneNumber::View &number);
+ bool startCall(const utils::PhoneNumber::View &number, const CallType type);
bool endCall(Forced forced = Forced::False);
bool isValid() const
M module-services/service-cellular/service-cellular/CellularMessage.hpp => module-services/service-cellular/service-cellular/CellularMessage.hpp +33 -17
@@ 37,6 37,7 @@ class CellularCallMessage : public CellularMessage
{
Ringing, // user provided number to call to and service initialized calling procedure.
IncomingCall, // device receives connection from other device.
+ CallerId, // device receives caller id
};
CellularCallMessage() = delete;
@@ 626,23 627,6 @@ class CellularResponseMessage : public sys::ResponseMessage
std::string data;
};
-class CellularActionResponseMessage : public CellularResponseMessage, public app::manager::actions::ConvertibleToAction
-{
- public:
- CellularActionResponseMessage(app::manager::actions::ActionId actionId, std::string data)
- : CellularResponseMessage(false, data), actionId(actionId)
- {}
-
- [[nodiscard]] auto toAction() const -> std::unique_ptr<app::manager::ActionRequest>
- {
- return std::make_unique<app::manager::ActionRequest>(
- sender, actionId, std::make_unique<app::manager::actions::ActionParams>(data));
- }
-
- private:
- const app::manager::actions::ActionId actionId;
-};
-
class CellularAntennaResponseMessage : public sys::ResponseMessage
{
public:
@@ 760,6 744,38 @@ class CellularCheckIfStartAllowedMessage : public sys::Message
CellularCheckIfStartAllowedMessage() : sys::Message()
{}
};
+
+class CellularNoSimNotification : public CellularResponseMessage, public app::manager::actions::ConvertibleToAction
+{
+ public:
+ CellularNoSimNotification(std::string data) : CellularResponseMessage(false, data)
+ {}
+
+ [[nodiscard]] auto toAction() const -> std::unique_ptr<app::manager::ActionRequest>
+ {
+ return std::make_unique<app::manager::ActionRequest>(
+ sender,
+ app::manager::actions::NoSimNotification,
+ std::make_unique<app::manager::actions::ActionParams>(data));
+ }
+};
+
+class CellularNotAnEmergencyNotification : public CellularResponseMessage,
+ public app::manager::actions::ConvertibleToAction
+{
+ public:
+ CellularNotAnEmergencyNotification(std::string data) : CellularResponseMessage(false, data)
+ {}
+
+ [[nodiscard]] auto toAction() const -> std::unique_ptr<app::manager::ActionRequest>
+ {
+ return std::make_unique<app::manager::ActionRequest>(
+ sender,
+ app::manager::actions::NotAnEmergencyNotification,
+ std::make_unique<app::manager::actions::ActionParams>(data));
+ }
+};
+
namespace cellular
{
M module-services/service-cellular/service-cellular/CellularRequestHandler.hpp => module-services/service-cellular/service-cellular/CellularRequestHandler.hpp +1 -0
@@ 15,6 15,7 @@ class CellularRequestHandler : public cellular::RequestHandler
void handle(cellular::ImeiRequest &request, at::Result &result) final;
void handle(cellular::UssdRequest &request, at::Result &result) final;
void handle(cellular::CallRequest &request, at::Result &result) final;
+ void handle(cellular::RejectRequest &request, at::Result &result) final;
void handle(cellular::PasswordRegistrationRequest &request, at::Result &result) final;
void handle(cellular::SupplementaryServicesRequest &request, at::Result &result) final;
void handle(cellular::PinChangeRequest &request, at::Result &result) final;
M module-services/service-cellular/service-cellular/RequestFactory.hpp => module-services/service-cellular/service-cellular/RequestFactory.hpp +0 -2
@@ 32,7 32,6 @@ namespace cellular
CellularCallRequestMessage::RequestMode requestMode,
SimStatus simCardStatus);
std::unique_ptr<IRequest> create();
- std::optional<app::manager::actions::Action> &getActionRequest();
private:
void registerRequest(std::string regex, CreateCallback);
@@ 40,7 39,6 @@ namespace cellular
std::string request;
std::vector<std::pair<std::string, CreateCallback>> requestMap;
- std::optional<app::manager::actions::Action> actionRequest;
at::BaseChannel &channel;
const CellularCallRequestMessage::RequestMode requestMode;
M module-services/service-cellular/service-cellular/RequestHandler.hpp => module-services/service-cellular/service-cellular/RequestHandler.hpp +2 -0
@@ 10,6 10,7 @@ namespace cellular
class ImeiRequest;
class UssdRequest;
class CallRequest;
+ class RejectRequest;
class SupplementaryServicesRequest;
class PasswordRegistrationRequest;
class PinChangeRequest;
@@ 25,6 26,7 @@ namespace cellular
virtual void handle(ImeiRequest &request, at::Result &result) = 0;
virtual void handle(UssdRequest &request, at::Result &result) = 0;
virtual void handle(CallRequest &request, at::Result &result) = 0;
+ virtual void handle(RejectRequest &request, at::Result &result) = 0;
virtual void handle(PasswordRegistrationRequest &request, at::Result &result) = 0;
virtual void handle(PinChangeRequest &request, at::Result &result) = 0;
virtual void handle(SupplementaryServicesRequest &request, at::Result &result) = 0;
M module-services/service-cellular/service-cellular/ServiceCellular.hpp => module-services/service-cellular/service-cellular/ServiceCellular.hpp +1 -0
@@ 189,6 189,7 @@ class ServiceCellular : public sys::Service
PowerCycle, //<! PWRKEY pin toggle
HardReset //<! RESET_N pin
};
+
bool resetCellularModule(ResetType type);
bool isAfterForceReboot = false;
bool nextPowerStateChangeAwaiting = false;
A module-services/service-cellular/service-cellular/requests/RejectRequest.hpp => module-services/service-cellular/service-cellular/requests/RejectRequest.hpp +48 -0
@@ 0,0 1,48 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <at/Result.hpp>
+
+#include "service-cellular/RequestHandler.hpp"
+#include "service-cellular/requests/Request.hpp"
+
+namespace cellular
+{
+ class RejectRequest : public Request
+ {
+ public:
+ enum class RejectReason
+ {
+ NoSim,
+ NotAnEmergencyNumber
+ };
+
+ RejectRequest(RejectReason rejectReason, const std::string &number)
+ : Request(number), rejectReason(rejectReason){};
+
+ std::string command() final
+ {
+ return std::string();
+ }
+
+ void handle(RequestHandler &h, at::Result &result)
+ {
+ h.handle(*this, result);
+ }
+
+ RejectReason getRejectReason()
+ {
+ return rejectReason;
+ }
+
+ std::string getNumber() const
+ {
+ return request;
+ }
+
+ private:
+ RejectReason rejectReason;
+ };
+}; // namespace cellular
M module-services/service-cellular/tests/unittest_request_factory.cpp => module-services/service-cellular/tests/unittest_request_factory.cpp +24 -18
@@ 15,6 15,7 @@
#include <service-cellular/requests/ClipRequest.hpp>
#include <service-cellular/requests/ClirRequest.hpp>
#include <service-cellular/requests/ColpRequest.hpp>
+#include <service-cellular/requests/RejectRequest.hpp>
#include <module-cellular/test/mock/AtCommon_channel.hpp>
@@ 33,15 34,15 @@ TEST_CASE("Emergency handling")
bool isNumberEmergencyNoSim;
// mock that sim is inserted
bool insertSim;
- // expected action returned
- std::optional<app::manager::actions::Action> expectedAction;
+ // reject reason if applicable
+ std::optional<RejectRequest::RejectReason> rejectReason;
// expected typeid name of created request
std::string expectedType;
- // test number
- std::string number = "600700800";
// expected command crated by factory
std::string expectedCommand = "ATD600700800;";
+ // test number
+ std::string number = "600700800";
};
std::vector<EmergencyTest> testCases = {
@@ 58,11 59,11 @@ TEST_CASE("Emergency handling")
// no SIM emergency number / no sim inserted
{false, false, true, false, std::nullopt, typeid(CallRequest).name()},
// SIM emergency number / no sim inserted
- {false, true, false, false, Action::CallRejectNoSim, ""},
+ {false, true, false, false, RejectRequest::RejectReason::NoSim, typeid(RejectRequest).name(), ""},
// normal number / sim inserted
{false, false, false, true, std::nullopt, typeid(CallRequest).name()},
// normal number / no sim inserted
- {false, false, false, false, Action::CallRejectNoSim, ""},
+ {false, false, false, false, RejectRequest::RejectReason::NoSim, typeid(RejectRequest).name(), ""},
////// emergency request
// no SIM and SIM emergency number / sim inserted
@@ 76,11 77,17 @@ TEST_CASE("Emergency handling")
// no SIM emergency number / no sim inserted
{true, false, true, false, std::nullopt, typeid(CallRequest).name()},
// SIM emergency number / no sim inserted
- {true, true, false, false, Action::CallRejectNoSim, ""},
+ {true, true, false, false, RejectRequest::RejectReason::NoSim, typeid(RejectRequest).name(), ""},
// normal number / sim inserted
- {true, false, false, true, Action::CallRejectNotEmergency, ""},
+ {true, false, false, true, RejectRequest::RejectReason::NotAnEmergencyNumber, typeid(RejectRequest).name(), ""},
// normal number / no sim inserted
- {true, false, false, false, Action::CallRejectNotEmergency, ""},
+ {true,
+ false,
+ false,
+ false,
+ RejectRequest::RejectReason::NotAnEmergencyNumber,
+ typeid(RejectRequest).name(),
+ ""},
};
int idx = 0;
@@ 108,16 115,15 @@ TEST_CASE("Emergency handling")
: CellularCallRequestMessage::RequestMode::Normal,
test.insertSim ? RequestFactory::SimStatus::SimInsterted
: RequestFactory::SimStatus::SimSlotEmpty);
- auto request = requestFactory.create();
+ std::shared_ptr<IRequest> request = requestFactory.create();
- if (test.expectedAction) {
- INFO("Failed test case idx: " + std::to_string(idx));
- REQUIRE(requestFactory.getActionRequest() == test.expectedAction);
- REQUIRE(request == nullptr);
- }
- else {
- REQUIRE(requestFactory.getActionRequest() == std::nullopt);
- REQUIRE(typeid(*request.get()).name() == test.expectedType);
+ INFO("Failed test case idx: " + std::to_string(idx));
+ REQUIRE(request != nullptr);
+ REQUIRE(typeid(*request.get()).name() == test.expectedType);
+
+ if (test.expectedType == typeid(RejectRequest).name()) {
+ auto rejectRequest = std::static_pointer_cast<RejectRequest>(request);
+ REQUIRE(test.rejectReason == rejectRequest->getRejectReason());
}
if (request) {
M module-services/service-fota/FotaUrcHandler.hpp => module-services/service-fota/FotaUrcHandler.hpp +2 -1
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 25,6 25,7 @@ class FotaUrcHandler : public at::urc::UrcHandler
virtual void Handle(at::urc::Ctze &urc){};
virtual void Handle(at::urc::Cpin &urc){};
virtual void Handle(at::urc::Qiurc &urc){};
+ virtual void Handle(at::urc::Ring &urc){};
virtual void Handle(at::urc::PoweredDown &urc){};
virtual void Handle(at::urc::UrcResponse &urc){};