M CMakeLists.txt => CMakeLists.txt +4 -0
@@ 22,6 22,10 @@ message("TARGET_COMPILE_DEFINITIONS: ${TARGET_COMPILE_OPTIONS}")
message("TARGET_LIBRARIES: ${TARGET_LIBRARIES}")
message("TARGET_LINKER_FLAGS: ${TARGET_LINKER_FLAGS}")
+string(REPLACE "TARGET_" "" PROJECT_TARGET_NAME ${PROJECT_TARGET})
+string(TOLOWER "${PROJECT_TARGET_NAME}" PROJECT_TARGET_NAME)
+message("Project target name: ${PROJECT_TARGET_NAME}")
+
add_executable(${PROJECT_NAME} "" )
if (NOT ${PROJECT_TARGET} STREQUAL "TARGET_RT1051")
M README.md => README.md +5 -0
@@ 37,6 37,7 @@ MuditaOS is a mobile operating system optimized for E Ink displays. Built on Fre
* [Contributing](#Contributing)
* [Discussions](#Discussions)
* [Reporting issues and feature requests](#Reporting-bugs-and-feature-requests)
+ * [Internationalization](#Internationalization)
* [Development workflow](#Development-workflow)
* [Documentation](#documentation)
* [How to generate documentation using Doxygen](#How-to-generate-documentation-using-Doxygen)
@@ 67,6 68,10 @@ For general questions and ideas regarding MuditaOS please post in the [“Mudita
You can report bugs and feature requests on [GitHub](https://github.com/mudita/MuditaOS/issues). This is also a good place to discuss architecture decisions and things that aren’t yet covered by the documentation. Please refer to the ["Contributing to MuditaOS"](./CONTRIBUTING.md) article for more details.
+### Internationalization
+
+If you want to start localizing MuditaOS interface please start from [the "Internationalization" article](./doc/i18n.md).
+
### Development workflow
When contributing code or documentation changes please follow the guidleines inside the ["Development workflow"](./doc/development_workflow.md) article.
M doc/i18n.md => doc/i18n.md +44 -1
@@ 66,7 66,50 @@ Definition for every key code used in the phone is in [the key_codes.hpp file (K
### Date and time
-MuditaOS follows [Linux `date`](https://man7.org/linux/man-pages/man1/date.1.html) to format date and time.
+MuditaOS follows [Linux `date`](https://man7.org/linux/man-pages/man1/date.1.html) to format date and time.
+
+## Font conversion
+
+MuditaOS doesn't have built-in support for ttf/otf fonts, so we generate bitmap files for fonts. The official release uses GT Pressura Typeface which is a licensed font ([more info](../LICENSE.md))
+
+MuditaOS supports the following languages (and characters) out-of-the-box:
+
+- English
+- German
+- Spanish
+- Polish
+- French
+
+For other languages there might be a need to add language-specific glyphs, build them using [fontbuilder](https://github.com/mudita/fontbuilder) and add them to the repository.
+
+[Here's a list of glyphs that are supported by GT Pressura](https://www.grillitype.com/api/storage/app/uploads/public/5b6/c52/16b/5b6c5216b40a8675629257.pdf) (our current license covers only the Latin alphapbet characters).
+
+[Here's a list of characters currently added to the build](https://github.com/mudita/fontbuilder/blob/master/charset.txt).
+
+If your characters aren't currently supported by the main font or the defualt fallback font (DeJavu Sans Bold) please know that we're working on adding a feature inside MuditaOS that would enable to render the UI in more languages with a font provided by the user.
+
+### Adding glyphs
+
+We use [fontbuilder](https://github.com/mudita/fontbuilder). It has font sets saved in files. This is not the best solution to store system presets (we should rather have it in release process). In order to do this:
+
+- feed FontBuilder headless run with preset file and build MPF (Mudita Pure Font)
+- put these fonts in build folder
+
+On Mudita Pure phone we use:
+
+- default font (`gt_pressura` font family)
+- default fallback font (DeJavu Sans Bold size 27 **Emojis only**)
+
+The `▯` glyph indicates that there is no glyph for a unicode character in the current font.
+
+#### Naming convention
+
+It’s a good practice not to rename font names - these are stored in font metadata too and metadata is used in code (**not the font file name**). Please just keep names as they are.
+
+#### Where are the files?
+
+- Source font files used for the build: `PurePhone/image/assets/fonts/`
+- Font files used at runtime (copied upon build): `PurePhone/<build_folder>/assets/fonts/`
## How to start localizing the interface
M enabled_unittests => enabled_unittests +14 -0
@@ 161,6 161,7 @@ TESTS_LIST["catch2-gui-text"]="
Text addition bounds - text widget size restricted;
Text addition bounds - text widget line size restricted;
Text addition bounds - multiple limits tests;
+ Text newline navigation and deletion tests;
RichText newline and empty lines tests;
TextBlock Ctor/Dtor ;
Text block - set/update/get text;
@@ 214,6 215,10 @@ TESTS_LIST["catch2-service-desktop"]="
Endpoint Factory test;
"
#---------
+TESTS_LIST["catch2-service-desktop-endpoint-contacts"]="
+ Endpoint Contacts Test;
+"
+#---------
TESTS_LIST["catch2-service-evtmgr"]="
ScreenLightControlFunctions;
"
@@ 254,6 259,15 @@ TESTS_LIST["catch2-utils-clipboard"]="
Clipboard;
"
#---------
+TESTS_LIST["catch2-utils-conditional-invoke-tests"]="
+ Successful global function call;
+ Failed global function call;
+ Successful class static function call;
+ Failed class static function call;
+ Successful class member function call;
+ Failed class member function call;
+"
+#---------
TESTS_LIST["catch2-utils-duration"]="
Duration - creation;
Duration - arithemtics;
M image/user/db/settings_v2_002.sql => image/user/db/settings_v2_002.sql +2 -1
@@ 21,5 21,6 @@ INSERT OR IGNORE INTO settings_tab (path, value) VALUES
('bt_state', '0'),
('bt_device_visibility', '0'),
('bt_device_name', 'PurePhone'),
- ('bt_bonded_devices', '');
+ ('bt_bonded_devices', ''),
+ ('battery_critical_level', '10');
M module-apps/Application.cpp => module-apps/Application.cpp +5 -31
@@ 84,6 84,8 @@ namespace app
connect(typeid(AppRefreshMessage),
[this](sys::Message *msg) -> sys::MessagePointer { return handleAppRefresh(msg); });
+
+ connect(sevm::BatteryStatusChangeMessage(), [&](sys::Message *) { return handleBatteryStatusChange(); });
}
Application::~Application() noexcept
@@ 129,12 131,7 @@ namespace app
// send drawing commands only when if application is in active and visible.
if (state == State::ACTIVE_FORGROUND) {
auto window = getCurrentWindow();
- if (Store::Battery::get().state == Store::Battery::State::Charging) {
- window->updateBatteryCharger(true);
- }
- else {
- window->updateBatteryLevel(Store::Battery::get().level);
- }
+ window->updateBatteryStatus();
window->setSIM();
window->updateSignalStrength();
window->updateNetworkAccessTechnology();
@@ 216,12 213,6 @@ namespace app
else if (msgl->messageType == MessageType::KBDKeyEvent) {
return handleKBDKeyEvent(msgl);
}
- else if (msgl->messageType == MessageType::EVMBatteryLevel) {
- return handleBatteryLevel(msgl);
- }
- else if (msgl->messageType == MessageType::EVMChargerPlugged) {
- return handleChargerPlugged(msgl);
- }
else if (msgl->messageType == MessageType::EVMMinuteUpdated) {
return handleMinuteUpdated(msgl);
}
@@ 299,31 290,14 @@ namespace app
return msgHandled();
}
- sys::MessagePointer Application::handleBatteryLevel(sys::Message *msgl)
+ sys::MessagePointer Application::handleBatteryStatusChange()
{
- auto msg = static_cast<sevm::BatteryLevelMessage *>(msgl);
- LOG_INFO("Battery level: %d", msg->levelPercents);
-
- if (getCurrentWindow()->updateBatteryLevel(msg->levelPercents)) {
+ if (getCurrentWindow()->updateBatteryStatus()) {
refreshWindow(gui::RefreshModes::GUI_REFRESH_FAST);
}
return msgHandled();
}
- sys::MessagePointer Application::handleChargerPlugged(sys::Message *msgl)
- {
- auto *msg = static_cast<sevm::BatteryPlugMessage *>(msgl);
- if (msg->plugged == true) {
- LOG_INFO("Charger connected");
- }
- else {
- LOG_INFO("Charger disconnected");
- }
- getCurrentWindow()->updateBatteryCharger(msg->plugged);
- refreshWindow(gui::RefreshModes::GUI_REFRESH_FAST);
- return msgHandled();
- }
-
sys::MessagePointer Application::handleMinuteUpdated(sys::Message *msgl)
{
auto *msg = static_cast<sevm::RtcMinuteAlarmMessage *>(msgl);
M module-apps/Application.hpp => module-apps/Application.hpp +1 -2
@@ 167,8 167,7 @@ namespace app
sys::MessagePointer handleNetworkAccessTechnologyUpdate(sys::Message *msgl);
sys::MessagePointer handleInputEvent(sys::Message *msgl);
sys::MessagePointer handleKBDKeyEvent(sys::Message *msgl);
- sys::MessagePointer handleBatteryLevel(sys::Message *msgl);
- sys::MessagePointer handleChargerPlugged(sys::Message *msgl);
+ sys::MessagePointer handleBatteryStatusChange();
sys::MessagePointer handleMinuteUpdated(sys::Message *msgl);
sys::MessagePointer handleAction(sys::Message *msgl);
sys::MessagePointer handleApplicationSwitch(sys::Message *msgl);
M module-apps/CMakeLists.txt => module-apps/CMakeLists.txt +5 -1
@@ 1,4 1,7 @@
-cmake_minimum_required(VERSION 3.14)
+# Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+cmake_minimum_required(VERSION 3.14)
project(module-apps VERSION 1.0
DESCRIPTION "Library with all applications.")
@@ 112,6 115,7 @@ target_link_libraries(${PROJECT_NAME}
service-db
service-evtmgr
PUBLIC
+ module-audio
module-bsp
module-os
module-sys
M module-apps/application-alarm-clock/widgets/AlarmInternalListItem.hpp => module-apps/application-alarm-clock/widgets/AlarmInternalListItem.hpp +1 -8
@@ 7,12 7,5 @@
namespace gui
{
- class AlarmInternalListItem : public ListItem
- {
- public:
- std::function<void(std::shared_ptr<AlarmsRecord> event)> onSaveCallback = nullptr;
- std::function<void(std::shared_ptr<AlarmsRecord> event)> onLoadCallback = nullptr;
- std::function<bool()> onContentChangedCallback = nullptr;
- };
-
+ using AlarmInternalListItem = ListItemWithCallbacks<AlarmsRecord>;
} /* namespace gui */
M module-apps/application-alarm-clock/widgets/AlarmItem.cpp => module-apps/application-alarm-clock/widgets/AlarmItem.cpp +4 -6
@@ 43,13 43,11 @@ namespace gui
onOffImage->setMargins(gui::Margins(style::alarmClock::window::item::imageMargin, 0, 0, 0));
setAlarm();
- }
- bool AlarmItem::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim)
- {
- hBox->setPosition(0, 0);
- hBox->setSize(newDim.w, newDim.h);
- return true;
+ dimensionChangedCallback = [&](gui::Item &, const BoundingBox &newDim) -> bool {
+ hBox->setArea({0, 0, newDim.w, newDim.h});
+ return true;
+ };
}
void AlarmItem::setAlarm()
M module-apps/application-alarm-clock/widgets/AlarmItem.hpp => module-apps/application-alarm-clock/widgets/AlarmItem.hpp +0 -2
@@ 24,7 24,5 @@ namespace gui
public:
explicit AlarmItem(std::shared_ptr<AlarmsRecord> record);
-
- bool onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) override;
};
} // namespace gui
M module-apps/application-alarm-clock/widgets/AlarmOptionsItem.cpp => module-apps/application-alarm-clock/widgets/AlarmOptionsItem.cpp +4 -6
@@ 284,13 284,11 @@ namespace gui
}
optionLabel->setText(optionsNames[actualVectorIndex]);
};
- }
- bool AlarmOptionsItem::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim)
- {
- vBox->setPosition(0, 0);
- vBox->setSize(newDim.w, newDim.h);
- return true;
+ dimensionChangedCallback = [&](gui::Item &, const BoundingBox &newDim) -> bool {
+ vBox->setArea({0, 0, newDim.w, newDim.h});
+ return true;
+ };
}
std::vector<audio::Tags> AlarmOptionsItem::getMusicFilesList()
M module-apps/application-alarm-clock/widgets/AlarmOptionsItem.hpp => module-apps/application-alarm-clock/widgets/AlarmOptionsItem.hpp +0 -2
@@ 47,8 47,6 @@ namespace gui
AlarmOptionItemName itemName,
std::function<void(const UTF8 &text)> bottomBarTemporaryMode = nullptr,
std::function<void()> bottomBarRestoreFromTemporaryMode = nullptr);
-
- bool onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) override;
};
} /* namespace gui */
M module-apps/application-alarm-clock/widgets/AlarmTimeItem.cpp => module-apps/application-alarm-clock/widgets/AlarmTimeItem.cpp +5 -7
@@ 123,6 123,11 @@ namespace gui
onInputCallback(*hourInput);
onInputCallback(*minuteInput);
+
+ dimensionChangedCallback = [&](gui::Item &, const BoundingBox &newDim) -> bool {
+ hBox->setArea({0, 0, newDim.w, newDim.h});
+ return true;
+ };
}
void AlarmTimeItem::onInputCallback(gui::Text &textItem)
@@ 203,13 208,6 @@ namespace gui
}
}
- bool AlarmTimeItem::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim)
- {
- hBox->setPosition(0, 0);
- hBox->setSize(newDim.w, newDim.h);
- return true;
- }
-
bool AlarmTimeItem::isPm(const std::string &text) const
{
return !(text == utils::localize.get(utils::time::Locale::getAM()));
M module-apps/application-alarm-clock/widgets/AlarmTimeItem.hpp => module-apps/application-alarm-clock/widgets/AlarmTimeItem.hpp +0 -3
@@ 31,9 31,6 @@ namespace gui
AlarmTimeItem(bool mode24H,
std::function<void(const UTF8 &text)> bottomBarTemporaryMode = nullptr,
std::function<void()> bottomBarRestoreFromTemporaryMode = nullptr);
-
- // virtual methods from Item
- bool onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) override;
};
} /* namespace gui */
M module-apps/application-alarm-clock/widgets/CustomCheckBoxWithLabel.cpp => module-apps/application-alarm-clock/widgets/CustomCheckBoxWithLabel.cpp +5 -6
@@ 80,6 80,11 @@ namespace gui
return false;
};
onContentChangedCallback = [&]() { return checkBox->isChecked(); };
+
+ dimensionChangedCallback = [&](gui::Item &, const BoundingBox &newDim) -> bool {
+ hBox->setArea({0, 0, newDim.w, newDim.h});
+ return true;
+ };
}
void CustomCheckBoxWithLabel::setCheckBoxes()
@@ 91,10 96,4 @@ namespace gui
}
}
- bool CustomCheckBoxWithLabel::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim)
- {
- hBox->setPosition(0, 0);
- hBox->setSize(newDim.w, newDim.h);
- return true;
- }
} // namespace gui
M module-apps/application-alarm-clock/widgets/CustomCheckBoxWithLabel.hpp => module-apps/application-alarm-clock/widgets/CustomCheckBoxWithLabel.hpp +0 -2
@@ 26,8 26,6 @@ namespace gui
public:
CustomCheckBoxWithLabel(app::Application *app, const std::string &description, const WeekDaysRepeatData &data);
- bool onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) override;
-
static const std::map<WeekDayIso, std::string> weekDays;
};
} // namespace gui
M module-apps/application-calendar/models/CustomRepeatModel.cpp => module-apps/application-calendar/models/CustomRepeatModel.cpp +1 -1
@@ 66,7 66,7 @@ std::vector<bool> CustomRepeatModel::getIsCheckedData()
{
std::vector<bool> isCheckedData;
for (auto item : internalData) {
- if (item->onContentChangeCallback && item->onContentChangeCallback()) {
+ if (item->onContentChangedCallback && item->onContentChangedCallback()) {
isCheckedData.push_back(true);
}
else {
M module-apps/application-calendar/widgets/AllEventsItem.cpp => module-apps/application-calendar/widgets/AllEventsItem.cpp +4 -6
@@ 34,13 34,11 @@ namespace gui
description->setEdges(gui::RectangleEdge::None);
description->setFont(style::window::font::bigbold);
description->setAlignment(gui::Alignment{gui::Alignment::Horizontal::Left, gui::Alignment::Vertical::Center});
- }
- bool AllEventsItem::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim)
- {
- hBox->setPosition(0, 0);
- hBox->setSize(newDim.w, newDim.h);
- return true;
+ dimensionChangedCallback = [&](gui::Item &, const BoundingBox &newDim) -> bool {
+ hBox->setArea({0, 0, newDim.w, newDim.h});
+ return true;
+ };
}
void AllEventsItem::setMarkerItem(UTF8 text)
M module-apps/application-calendar/widgets/AllEventsItem.hpp => module-apps/application-calendar/widgets/AllEventsItem.hpp +0 -3
@@ 24,9 24,6 @@ namespace gui
void setMarkerItem(UTF8 text);
[[nodiscard]] UTF8 getLabelMarker() const;
void setEvent(std::shared_ptr<EventsRecord> record);
-
- // virtual methods from Item
- bool onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) override;
};
} /* namespace gui */
M module-apps/application-calendar/widgets/CalendarListItem.hpp => module-apps/application-calendar/widgets/CalendarListItem.hpp +1 -8
@@ 7,12 7,5 @@
namespace gui
{
- class CalendarListItem : public ListItem
- {
- public:
- std::function<void(std::shared_ptr<EventsRecord> event)> onSaveCallback = nullptr;
- std::function<void(std::shared_ptr<EventsRecord> event)> onLoadCallback = nullptr;
- std::function<bool()> onContentChangeCallback = nullptr;
- };
-
+ using CalendarListItem = ListItemWithCallbacks<EventsRecord>;
} /* namespace gui */
M module-apps/application-calendar/widgets/CheckBoxWithLabelItem.cpp => module-apps/application-calendar/widgets/CheckBoxWithLabelItem.cpp +7 -9
@@ 57,7 57,7 @@ namespace gui
if (checkBoxData != nullptr) {
setCheckBoxes();
}
- onContentChangeCallback = [&]() { return checkBox->isChecked(); };
+ onContentChangedCallback = [&]() { return checkBox->isChecked(); };
}
void CheckBoxWithLabelItem::applyCallbacks()
@@ 76,11 76,16 @@ namespace gui
inputCallback = [&](gui::Item &item, const gui::InputEvent &event) {
if (checkBox->onInput(event)) {
checkBox->resizeItems();
- onContentChangeCallback = [&]() { return checkBox->isChecked(); };
+ onContentChangedCallback = [&]() { return checkBox->isChecked(); };
return true;
}
return false;
};
+
+ dimensionChangedCallback = [&](gui::Item &, const BoundingBox &newDim) -> bool {
+ hBox->setArea({0, 0, newDim.w, newDim.h});
+ return true;
+ };
}
void CheckBoxWithLabelItem::setCheckBoxes()
@@ 108,11 113,4 @@ namespace gui
}
}
- bool CheckBoxWithLabelItem::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim)
- {
- hBox->setPosition(0, 0);
- hBox->setSize(newDim.w, newDim.h);
- return true;
- }
-
} /* namespace gui */
M module-apps/application-calendar/widgets/CheckBoxWithLabelItem.hpp => module-apps/application-calendar/widgets/CheckBoxWithLabelItem.hpp +0 -3
@@ 30,9 30,6 @@ namespace gui
gui::Label *descriptionLabel = nullptr;
gui::CheckBox *checkBox = nullptr;
-
- // virtual methods from Item
- bool onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) override;
};
} /* namespace gui */
M module-apps/application-calendar/widgets/DayEventsItem.cpp => module-apps/application-calendar/widgets/DayEventsItem.cpp +5 -8
@@ 41,6 41,11 @@ namespace gui
description->setEdges(gui::RectangleEdge::None);
description->setFont(style::window::font::medium);
description->setAlignment(gui::Alignment{gui::Alignment::Horizontal::Left, gui::Alignment::Vertical::Center});
+
+ dimensionChangedCallback = [&](gui::Item &, const BoundingBox &newDim) -> bool {
+ vBox->setArea({0, 0, newDim.w, newDim.h});
+ return true;
+ };
}
void DayEventsItem::setEvent(std::shared_ptr<EventsRecord> rec)
@@ 55,12 60,4 @@ namespace gui
}
}
}
-
- bool DayEventsItem::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim)
- {
- vBox->setPosition(0, 0);
- vBox->setSize(newDim.w, newDim.h);
- return true;
- }
-
} /* namespace gui */
M module-apps/application-calendar/widgets/DayEventsItem.hpp => module-apps/application-calendar/widgets/DayEventsItem.hpp +0 -1
@@ 27,7 27,6 @@ namespace gui
// virtual methods from Item
void setEvent(std::shared_ptr<EventsRecord> record);
- bool onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) override;
};
} /* namespace gui */
M module-apps/application-calendar/widgets/DayLabel.cpp => module-apps/application-calendar/widgets/DayLabel.cpp +5 -6
@@ 86,6 86,11 @@ namespace gui
this->setPenFocusWidth(style::window::default_border_focus_w);
this->setEdges(RectangleEdge::Top | RectangleEdge::Bottom);
}
+
+ dimensionChangedCallback = [&](gui::Item &, const BoundingBox &newDim) -> bool {
+ vBox->setArea({0, 0, newDim.w, newDim.h});
+ return true;
+ };
}
uint32_t DayLabel::getDayNumber()
@@ 105,10 110,4 @@ namespace gui
}
}
- bool DayLabel::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim)
- {
- this->vBox->setPosition(0, 0);
- this->vBox->setSize(newDim.w, newDim.h);
- return true;
- }
} /* namespace gui */
M module-apps/application-calendar/widgets/DayLabel.hpp => module-apps/application-calendar/widgets/DayLabel.hpp +0 -1
@@ 25,7 25,6 @@ namespace gui
bool isDayEmpty);
~DayLabel() override = default;
- bool onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) override;
uint32_t getDayNumber();
};
M module-apps/application-calendar/widgets/EventDateItem.cpp => module-apps/application-calendar/widgets/EventDateItem.cpp +4 -6
@@ 132,13 132,11 @@ namespace gui
setOnInputCallback(*dayInput);
setOnInputCallback(*monthInput);
setOnInputCallback(*yearInput);
- }
- bool EventDateItem::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim)
- {
- vBox->setPosition(0, 0);
- vBox->setSize(newDim.w, newDim.h);
- return true;
+ dimensionChangedCallback = [&](gui::Item &, const BoundingBox &newDim) -> bool {
+ vBox->setArea({0, 0, newDim.w, newDim.h});
+ return true;
+ };
}
calendar::YearMonthDay EventDateItem::validateDate()
M module-apps/application-calendar/widgets/EventDateItem.hpp => module-apps/application-calendar/widgets/EventDateItem.hpp +0 -2
@@ 34,8 34,6 @@ namespace gui
EventDateItem();
const calendar::YearMonthDay getChosenDate();
- // virtual methods from Item
- bool onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) override;
};
} /* namespace gui */
M module-apps/application-calendar/widgets/EventDetailDescriptionItem.cpp => module-apps/application-calendar/widgets/EventDetailDescriptionItem.cpp +5 -7
@@ 64,14 64,12 @@ namespace gui
return true;
};
- descriptionHandler();
- }
+ dimensionChangedCallback = [&](gui::Item &, const BoundingBox &newDim) -> bool {
+ vBox->setArea({0, 0, newDim.w, newDim.h});
+ return true;
+ };
- bool EventDetailDescriptionItem::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim)
- {
- vBox->setPosition(0, 0);
- vBox->setSize(newDim.w, newDim.h);
- return true;
+ descriptionHandler();
}
void EventDetailDescriptionItem::descriptionHandler()
M module-apps/application-calendar/widgets/EventDetailDescriptionItem.hpp => module-apps/application-calendar/widgets/EventDetailDescriptionItem.hpp +0 -2
@@ 23,8 23,6 @@ namespace gui
virtual ~EventDetailDescriptionItem() override = default;
void descriptionHandler();
- // virtual methods from Item
- bool onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) override;
};
} /* namespace gui */
M module-apps/application-calendar/widgets/EventTimeItem.cpp => module-apps/application-calendar/widgets/EventTimeItem.cpp +5 -7
@@ 73,6 73,11 @@ namespace gui
return true;
};
+ dimensionChangedCallback = [&](gui::Item &, const BoundingBox &newDim) -> bool {
+ vBox->setArea({0, 0, newDim.w, newDim.h});
+ return true;
+ };
+
applyInputCallbacks();
prepareForTimeMode();
}
@@ 253,13 258,6 @@ namespace gui
}
}
- bool EventTimeItem::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim)
- {
- vBox->setPosition(0, 0);
- vBox->setSize(newDim.w, newDim.h);
- return true;
- }
-
void EventTimeItem::setConnectionToSecondItem(gui::EventTimeItem *item)
{
this->secondItem = item;
M module-apps/application-calendar/widgets/EventTimeItem.hpp => module-apps/application-calendar/widgets/EventTimeItem.hpp +0 -2
@@ 59,8 59,6 @@ namespace gui
void setConnectionToSecondItem(gui::EventTimeItem *item);
void setConnectionToDateItem(gui::EventDateItem *item);
- // virtual methods from Item
- bool onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) override;
};
} /* namespace gui */
M module-apps/application-calendar/widgets/RepeatAndReminderItem.cpp => module-apps/application-calendar/widgets/RepeatAndReminderItem.cpp +5 -7
@@ 89,14 89,12 @@ namespace gui
reminder->setAlignment(gui::Alignment{gui::Alignment::Horizontal::Left, gui::Alignment::Vertical::Center});
reminder->activeItem = false;
- descriptionHandler();
- }
+ dimensionChangedCallback = [&](gui::Item &, const BoundingBox &newDim) -> bool {
+ hBox->setArea({0, 0, newDim.w, newDim.h});
+ return true;
+ };
- bool RepeatAndReminderItem::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim)
- {
- hBox->setPosition(0, 0);
- hBox->setSize(newDim.w, newDim.h);
- return true;
+ descriptionHandler();
}
void RepeatAndReminderItem::descriptionHandler()
M module-apps/application-calendar/widgets/RepeatAndReminderItem.hpp => module-apps/application-calendar/widgets/RepeatAndReminderItem.hpp +0 -1
@@ 30,7 30,6 @@ namespace gui
virtual ~RepeatAndReminderItem() = default;
void descriptionHandler();
- bool onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) override;
};
} /* namespace gui */
M module-apps/application-calendar/widgets/SeveralOptionsItem.cpp => module-apps/application-calendar/widgets/SeveralOptionsItem.cpp +4 -7
@@ 218,13 218,10 @@ namespace gui
optionLabel->setText(optionsNames[actualVectorIndex]);
}
};
- }
- bool SeveralOptionsItem::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim)
- {
- vBox->setPosition(0, 0);
- vBox->setSize(newDim.w, newDim.h);
- return true;
+ dimensionChangedCallback = [&](gui::Item &, const BoundingBox &newDim) -> bool {
+ vBox->setArea({0, 0, newDim.w, newDim.h});
+ return true;
+ };
}
-
} /* namespace gui */
M module-apps/application-calendar/widgets/SeveralOptionsItem.hpp => module-apps/application-calendar/widgets/SeveralOptionsItem.hpp +0 -3
@@ 49,9 49,6 @@ namespace gui
void prepareOptionsNames();
void applyCallbacks();
uint32_t repeatOptionValue = 0;
-
- // virtual methods from Item
- bool onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) override;
};
} /* namespace gui */
M module-apps/application-calendar/widgets/TextWithLabelItem.cpp => module-apps/application-calendar/widgets/TextWithLabelItem.cpp +4 -7
@@ 63,13 63,10 @@ namespace gui
};
onLoadCallback = [&](std::shared_ptr<EventsRecord> event) { textInput->setText(event->title); };
- }
- bool TextWithLabelItem::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim)
- {
- vBox->setPosition(0, 0);
- vBox->setSize(newDim.w, newDim.h);
- return true;
+ dimensionChangedCallback = [&](gui::Item &, const BoundingBox &newDim) -> bool {
+ vBox->setArea({0, 0, newDim.w, newDim.h});
+ return true;
+ };
}
-
} /* namespace gui */
M module-apps/application-calendar/widgets/TextWithLabelItem.hpp => module-apps/application-calendar/widgets/TextWithLabelItem.hpp +0 -3
@@ 21,9 21,6 @@ namespace gui
std::function<void()> bottomBarRestoreFromTemporaryMode = nullptr,
std::function<void()> selectSpecialCharacter = nullptr);
virtual ~TextWithLabelItem() override = default;
-
- // virtual methods from Item
- bool onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) override;
};
} /* namespace gui */
M module-apps/application-calllog/widgets/CalllogItem.cpp => module-apps/application-calllog/widgets/CalllogItem.cpp +4 -7
@@ 50,14 50,11 @@ namespace gui
timestamp->setEdges(gui::RectangleEdge::None);
timestamp->setFont(style::window::font::small);
timestamp->setAlignment(gui::Alignment{gui::Alignment::Horizontal::Right, gui::Alignment::Vertical::Center});
- }
-
- bool CalllogItem::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim)
- {
- hBox->setPosition(0, 0);
- hBox->setSize(newDim.w, newDim.h);
- return true;
+ dimensionChangedCallback = [&](gui::Item &, const BoundingBox &newDim) -> bool {
+ hBox->setArea({0, 0, newDim.w, newDim.h});
+ return true;
+ };
}
void CalllogItem::setCall(std::shared_ptr<CalllogRecord> &call)
M module-apps/application-calllog/widgets/CalllogItem.hpp => module-apps/application-calllog/widgets/CalllogItem.hpp +0 -3
@@ 50,9 50,6 @@ namespace gui
{
return call != nullptr ? *call : CalllogRecord();
};
-
- // virtual methods from Item
- bool onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) override;
};
} /* namespace gui */
M module-apps/application-desktop/widgets/DesktopInputWidget.cpp => module-apps/application-desktop/widgets/DesktopInputWidget.cpp +4 -7
@@ 75,14 75,11 @@ namespace gui
replyImage->setAlignment(Alignment(gui::Alignment::Vertical::Center));
replyImage->setMargins(Margins(0, 0, 0, 0));
replyImage->activeItem = false;
- }
-
- auto DesktopInputWidget::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) -> bool
- {
- body->setPosition(0, 0);
- body->setSize(newDim.w, newDim.h);
- return true;
+ dimensionChangedCallback = [&](gui::Item &, const BoundingBox &newDim) -> bool {
+ body->setArea({0, 0, newDim.w, newDim.h});
+ return true;
+ };
}
auto DesktopInputWidget::handleRequestResize([[maybe_unused]] const Item *child,
M module-apps/application-desktop/widgets/DesktopInputWidget.hpp => module-apps/application-desktop/widgets/DesktopInputWidget.hpp +0 -1
@@ 27,7 27,6 @@ namespace gui
DesktopInputWidget(app::Application *application, Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h);
~DesktopInputWidget() override = default;
- auto onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) -> bool override;
auto handleRequestResize(const Item *, unsigned short request_w, unsigned short request_h) -> Size override;
};
M module-apps/application-messages/widgets/SMSInputWidget.cpp => module-apps/application-messages/widgets/SMSInputWidget.cpp +5 -8
@@ 97,6 97,11 @@ namespace gui
return true;
};
+
+ dimensionChangedCallback = [&](gui::Item &, const BoundingBox &newDim) -> bool {
+ body->setArea({0, 0, newDim.w, newDim.h});
+ return true;
+ };
}
void SMSInputWidget::handleDraftMessage()
@@ 151,14 156,6 @@ namespace gui
}
}
- auto SMSInputWidget::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) -> bool
- {
- body->setPosition(0, 0);
- body->setSize(newDim.w, newDim.h);
-
- return true;
- }
-
auto SMSInputWidget::handleRequestResize([[maybe_unused]] const Item *child,
unsigned short request_w,
unsigned short request_h) -> Size
M module-apps/application-messages/widgets/SMSInputWidget.hpp => module-apps/application-messages/widgets/SMSInputWidget.hpp +0 -1
@@ 33,7 33,6 @@ namespace gui
void updateDraftMessage(const UTF8 &inputText);
void displayDraftMessage() const;
- auto onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) -> bool override;
auto handleRequestResize(const Item *, unsigned short request_w, unsigned short request_h) -> Size override;
};
M module-apps/application-messages/widgets/SMSOutputWidget.cpp => module-apps/application-messages/widgets/SMSOutputWidget.cpp +9 -11
@@ 93,6 93,15 @@ namespace gui
}
return false;
};
+
+ dimensionChangedCallback = [&](gui::Item &, const BoundingBox &newDim) -> bool {
+ body->setArea({0, 0, newDim.w, newDim.h});
+
+ // We need to calculate margin between sms and timeLabel and we can do it only after sizes are set.
+ positionTimeLabel();
+
+ return true;
+ };
}
void SMSOutputWidget::positionTimeLabel() const
@@ 136,17 145,6 @@ namespace gui
body->addWidget(errorIcon);
}
- auto SMSOutputWidget::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) -> bool
- {
- body->setPosition(0, 0);
- body->setSize(newDim.w, newDim.h);
-
- // We need to calculate margin between sms and timeLabel and we can do it only after sizes are set.
- positionTimeLabel();
-
- return true;
- }
-
auto SMSOutputWidget::handleRequestResize([[maybe_unused]] const Item *child,
unsigned short request_w,
unsigned short request_h) -> Size
M module-apps/application-messages/widgets/SMSOutputWidget.hpp => module-apps/application-messages/widgets/SMSOutputWidget.hpp +0 -1
@@ 31,7 31,6 @@ namespace gui
SMSOutputWidget(app::Application *application, const std::shared_ptr<SMSRecord> &record);
virtual ~SMSOutputWidget() = default;
- auto onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) -> bool override;
auto handleRequestResize(const Item *, unsigned short request_w, unsigned short request_h) -> Size override;
};
M module-apps/application-messages/widgets/SMSTemplateItem.cpp => module-apps/application-messages/widgets/SMSTemplateItem.cpp +4 -7
@@ 17,14 17,11 @@ namespace gui
text = new gui::Label(this, 0, 0, 0, 0);
style::window::decorateOption(text);
text->setEllipsis(gui::Ellipsis::Right);
- }
-
- bool SMSTemplateItem::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim)
- {
- text->setPosition(0, 0);
- text->setSize(newDim.w, newDim.h);
- return true;
+ dimensionChangedCallback = [&](gui::Item &, const BoundingBox &newDim) -> bool {
+ text->setArea({0, 0, newDim.w, newDim.h});
+ return true;
+ };
}
void SMSTemplateItem::setTemplate(std::shared_ptr<SMSTemplateRecord> templ)
M module-apps/application-messages/widgets/SMSTemplateItem.hpp => module-apps/application-messages/widgets/SMSTemplateItem.hpp +0 -3
@@ 25,9 25,6 @@ namespace gui
SMSTemplateItem();
virtual ~SMSTemplateItem() = default;
void setTemplate(std::shared_ptr<SMSTemplateRecord>);
-
- // virtual methods from Item
- bool onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) override;
};
} /* namespace gui */
M module-apps/application-music-player/ApplicationMusicPlayer.cpp => module-apps/application-music-player/ApplicationMusicPlayer.cpp +27 -0
@@ 20,6 20,10 @@ namespace app
: Application(name, parent, startInBackground, 4096)
{
LOG_INFO("ApplicationMusicPlayer::create");
+ connect(typeid(AudioStartPlaybackResponse), [&](sys::Message *msg) {
+ handlePlayResponse(msg);
+ return sys::MessageNone{};
+ });
}
ApplicationMusicPlayer::~ApplicationMusicPlayer()
@@ 27,6 31,12 @@ namespace app
LOG_INFO("ApplicationMusicPlayer::destroy");
}
+ void ApplicationMusicPlayer::handlePlayResponse(sys::Message *msg)
+ {
+ auto startResponse = static_cast<AudioStartPlaybackResponse *>(msg);
+ currentFileToken = startResponse->token;
+ }
+
sys::MessagePointer ApplicationMusicPlayer::DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp)
{
return Application::DataReceivedHandler(msgl);
@@ 95,6 105,23 @@ namespace app
return true;
}
+ bool ApplicationMusicPlayer::pause()
+ {
+ if (currentFileToken) {
+ return AudioServiceAPI::Pause(this, currentFileToken.value());
+ }
+ return false;
+ }
+
+ bool ApplicationMusicPlayer::resume()
+ {
+ if (currentFileToken) {
+
+ return AudioServiceAPI::Resume(this, currentFileToken.value());
+ }
+ return false;
+ }
+
std::optional<audio::Tags> ApplicationMusicPlayer::getFileTags(const std::string &filePath)
{
return AudioServiceAPI::GetFileTags(this, filePath);
M module-apps/application-music-player/ApplicationMusicPlayer.hpp => module-apps/application-music-player/ApplicationMusicPlayer.hpp +3 -0
@@ 26,6 26,7 @@ namespace app
class ApplicationMusicPlayer : public Application
{
+ std::optional<audio::Token> currentFileToken;
public:
ApplicationMusicPlayer(std::string name = name_music_player,
@@ 51,6 52,8 @@ namespace app
bool resume();
bool stop();
std::optional<audio::Tags> getFileTags(const std::string &filePath);
+
+ void handlePlayResponse(sys::Message *msg);
};
template <> struct ManifestTraits<ApplicationMusicPlayer>
M module-apps/application-music-player/widgets/SongItem.cpp => module-apps/application-music-player/widgets/SongItem.cpp +4 -8
@@ 63,14 63,10 @@ namespace gui
authorText->setAlignment(Alignment(gui::Alignment::Horizontal::Left, gui::Alignment::Vertical::Center));
authorText->setEditMode(EditMode::Browse);
authorText->setText(authorName);
- }
-
- auto SongItem::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) -> bool
- {
- vBox->setPosition(0, 0);
- vBox->setSize(newDim.w, newDim.h);
- return true;
+ dimensionChangedCallback = [&](gui::Item &, const BoundingBox &newDim) -> bool {
+ vBox->setArea({0, 0, newDim.w, newDim.h});
+ return true;
+ };
}
-
} /* namespace gui */
M module-apps/application-music-player/widgets/SongItem.hpp => module-apps/application-music-player/widgets/SongItem.hpp +0 -1
@@ 19,7 19,6 @@ namespace gui
SongItem(std::string authorName, std::string songName, std::string duration);
~SongItem() override = default;
- auto onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) -> bool override;
VBox *vBox = nullptr;
HBox *firstHBox = nullptr;
HBox *secondHBox = nullptr;
M module-apps/application-phonebook/widgets/ContactListItem.hpp => module-apps/application-phonebook/widgets/ContactListItem.hpp +1 -8
@@ 7,12 7,5 @@
namespace gui
{
- class ContactListItem : public ListItem
- {
- public:
- std::function<void(std::shared_ptr<ContactRecord> contact)> onSaveCallback = nullptr;
- std::function<void(std::shared_ptr<ContactRecord> contact)> onLoadCallback = nullptr;
- std::function<bool()> onEmptyCallback = nullptr;
- };
-
+ using ContactListItem = ListItemWithCallbacks<ContactRecord>;
} /* namespace gui */
M module-apps/application-phonebook/widgets/InformationWidget.cpp => module-apps/application-phonebook/widgets/InformationWidget.cpp +5 -7
@@ 106,13 106,11 @@ namespace gui
return vBox->onInput(event);
};
- setEdges(RectangleEdge::None);
- }
+ dimensionChangedCallback = [&](gui::Item &, const BoundingBox &newDim) -> bool {
+ vBox->setArea({0, 0, newDim.w, newDim.h});
+ return true;
+ };
- auto InformationWidget::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) -> bool
- {
- vBox->setPosition(0, 0);
- vBox->setSize(newDim.w, newDim.h);
- return true;
+ setEdges(RectangleEdge::None);
}
} /* namespace gui */
M module-apps/application-phonebook/widgets/InformationWidget.hpp => module-apps/application-phonebook/widgets/InformationWidget.hpp +0 -1
@@ 19,7 19,6 @@ namespace gui
public:
InformationWidget(app::Application *app);
~InformationWidget() override = default;
- auto onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) -> bool override;
VBox *vBox = nullptr;
Label *titleLabel = nullptr;
TextWithIconsWidget *primaryNumberHBox = nullptr;
M module-apps/application-phonebook/widgets/InputBoxWithLabelAndIconWidget.cpp => module-apps/application-phonebook/widgets/InputBoxWithLabelAndIconWidget.cpp +4 -8
@@ 66,15 66,11 @@ namespace gui
applyItemNameSpecificSettings();
setEdges(gui::RectangleEdge::None);
- }
-
- auto InputBoxWithLabelAndIconWidget::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim)
- -> bool
- {
- hBox->setPosition(0, 0);
- hBox->setSize(newDim.w, newDim.h);
- return true;
+ dimensionChangedCallback = [&](gui::Item &, const BoundingBox &newDim) -> bool {
+ hBox->setArea({0, 0, newDim.w, newDim.h});
+ return true;
+ };
}
void InputBoxWithLabelAndIconWidget::applyItemNameSpecificSettings()
M module-apps/application-phonebook/widgets/InputBoxWithLabelAndIconWidget.hpp => module-apps/application-phonebook/widgets/InputBoxWithLabelAndIconWidget.hpp +0 -1
@@ 24,7 24,6 @@ namespace gui
std::function<void(const UTF8 &text)> bottomBarTemporaryMode = nullptr,
std::function<void()> bottomBarRestoreFromTemporaryMode = nullptr);
~InputBoxWithLabelAndIconWidget() override = default;
- auto onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) -> bool override;
gui::HBox *hBox = nullptr;
gui::Label *inputBoxLabel = nullptr;
gui::Label *descriptionLabel = nullptr;
M module-apps/application-phonebook/widgets/InputLinesWithLabelIWidget.cpp => module-apps/application-phonebook/widgets/InputLinesWithLabelIWidget.cpp +5 -7
@@ 80,15 80,13 @@ namespace gui
}
return result;
};
- setEdges(RectangleEdge::None);
- }
- auto InputLinesWithLabelIWidget::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) -> bool
- {
- vBox->setPosition(0, 0);
- vBox->setSize(newDim.w, newDim.h);
+ dimensionChangedCallback = [&](gui::Item &, const BoundingBox &newDim) -> bool {
+ vBox->setArea({0, 0, newDim.w, newDim.h});
+ return true;
+ };
- return true;
+ setEdges(RectangleEdge::None);
}
void InputLinesWithLabelIWidget::applyItemNameSpecificSettings()
M module-apps/application-phonebook/widgets/InputLinesWithLabelIWidget.hpp => module-apps/application-phonebook/widgets/InputLinesWithLabelIWidget.hpp +0 -1
@@ 26,7 26,6 @@ namespace gui
unsigned int lines = 1);
~InputLinesWithLabelIWidget() override = default;
- auto onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) -> bool override;
VBox *vBox = nullptr;
Label *titleLabel = nullptr;
TextFixedSize *inputText = nullptr;
M module-apps/application-phonebook/widgets/OutputLinesTextWithLabelWidget.cpp => module-apps/application-phonebook/widgets/OutputLinesTextWithLabelWidget.cpp +5 -9
@@ 46,19 46,15 @@ namespace gui
return true;
};
+ dimensionChangedCallback = [&](gui::Item &, const BoundingBox &newDim) -> bool {
+ vBox->setArea({0, 0, newDim.w, newDim.h});
+ return true;
+ };
+
this->activeItem = false;
setEdges(RectangleEdge::All);
}
- auto OutputLinesTextWithLabelWidget::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim)
- -> bool
- {
- vBox->setPosition(0, 0);
- vBox->setSize(newDim.w, newDim.h);
-
- return true;
- }
-
void OutputLinesTextWithLabelWidget::applyItemNameSpecificSettings()
{
switch (listItemName) {
M module-apps/application-phonebook/widgets/OutputLinesTextWithLabelWidget.hpp => module-apps/application-phonebook/widgets/OutputLinesTextWithLabelWidget.hpp +0 -1
@@ 20,7 20,6 @@ namespace gui
OutputLinesTextWithLabelWidget(phonebookInternals::ListItemName listItemName);
~OutputLinesTextWithLabelWidget() override = default;
- auto onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) -> bool override;
VBox *vBox = nullptr;
Label *titleLabel = nullptr;
Text *multilineText = nullptr;
M module-apps/application-phonebook/widgets/PhonebookItem.cpp => module-apps/application-phonebook/widgets/PhonebookItem.cpp +4 -6
@@ 29,13 29,11 @@ namespace gui
contactName->setAlignment(gui::Alignment{gui::Alignment::Horizontal::Left, gui::Alignment::Vertical::Center});
contactName->setMinimumHeight(phonebookStyle::contactItem::h);
contactName->setMaximumWidth(phonebookStyle::contactItem::w);
- }
- bool PhonebookItem::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim)
- {
- hBox->setPosition(0, 0);
- hBox->setSize(newDim.w, newDim.h);
- return true;
+ dimensionChangedCallback = [&](gui::Item &, const BoundingBox &newDim) -> bool {
+ hBox->setArea({0, 0, newDim.w, newDim.h});
+ return true;
+ };
}
// sets copy of alarm's
M module-apps/application-phonebook/widgets/PhonebookItem.hpp => module-apps/application-phonebook/widgets/PhonebookItem.hpp +0 -1
@@ 34,7 34,6 @@ namespace gui
void setMarkerItem(UTF8 text);
UTF8 getLabelMarker();
- bool onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) override;
void setLabelMarkerDisplayMode(LabelMarkerDisplayMode mode);
};
M module-apps/application-settings-new/widgets/ApnInputWidget.cpp => module-apps/application-settings-new/widgets/ApnInputWidget.cpp +5 -7
@@ 79,15 79,13 @@ namespace gui
}
return result;
};
- setEdges(RectangleEdge::None);
- }
- auto ApnInputWidget::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) -> bool
- {
- vBox->setPosition(0, 0);
- vBox->setSize(newDim.w, newDim.h);
+ dimensionChangedCallback = [&](gui::Item &, const BoundingBox &newDim) -> bool {
+ vBox->setArea({0, 0, newDim.w, newDim.h});
+ return true;
+ };
- return true;
+ setEdges(RectangleEdge::None);
}
void ApnInputWidget::applyItemNameSpecificSettings()
M module-apps/application-settings-new/widgets/ApnInputWidget.hpp => module-apps/application-settings-new/widgets/ApnInputWidget.hpp +0 -1
@@ 31,7 31,6 @@ namespace gui
std::function<void()> checkTextContent = nullptr;
void applyItemNameSpecificSettings();
- auto onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) -> bool override;
void nameHandler();
void apnHandler();
void usernameHandler();
M module-apps/application-settings-new/widgets/ApnListItem.hpp => module-apps/application-settings-new/widgets/ApnListItem.hpp +1 -8
@@ 7,12 7,5 @@
namespace gui
{
- class ApnListItem : public ListItem
- {
- public:
- std::function<void(std::shared_ptr<packet_data::APN::Config> apnRecord)> onSaveCallback = nullptr;
- std::function<void(std::shared_ptr<packet_data::APN::Config> apnRecord)> onLoadCallback = nullptr;
- std::function<bool()> onEmptyCallback = nullptr;
- };
-
+ using ApnListItem = ListItemWithCallbacks<packet_data::APN::Config>;
} /* namespace gui */
M module-apps/application-settings-new/widgets/QuoteWidget.cpp => module-apps/application-settings-new/widgets/QuoteWidget.cpp +5 -9
@@ 103,15 103,11 @@ namespace gui
return true;
};
- setEdges(gui::RectangleEdge::None);
- }
-
- auto QuoteWidget::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) -> bool
- {
- hBox->setPosition(0, 0);
- hBox->setSize(newDim.w, newDim.h);
+ dimensionChangedCallback = [&](gui::Item &, const BoundingBox &newDim) -> bool {
+ hBox->setArea({0, 0, newDim.w, newDim.h});
+ return true;
+ };
- return true;
+ setEdges(gui::RectangleEdge::None);
}
-
} /* namespace gui */
M module-apps/application-settings-new/widgets/QuoteWidget.hpp => module-apps/application-settings-new/widgets/QuoteWidget.hpp +0 -2
@@ 20,8 20,6 @@ namespace gui
std::function<void(const UTF8 &text)> bottomBarTemporaryMode = nullptr,
std::function<void()> bottomBarRestoreFromTemporaryMode = nullptr);
- auto onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) -> bool override;
-
[[nodiscard]] auto getQuoteData() const -> app::QuoteRecord
{
return quote;
M module-apps/application-settings/widgets/ColorTestListItem.cpp => module-apps/application-settings/widgets/ColorTestListItem.cpp +4 -6
@@ 31,13 31,11 @@ namespace gui
else {
colorLabel->setTextColor(ColorFullWhite);
}
- }
- bool ColorTestListItem::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim)
- {
- vBox->setPosition(0, 0);
- vBox->setSize(newDim.w, newDim.h);
- return true;
+ dimensionChangedCallback = [&](gui::Item &, const BoundingBox &newDim) -> bool {
+ vBox->setArea({0, 0, newDim.w, newDim.h});
+ return true;
+ };
}
bool ColorTestListItem::onInput(const InputEvent &inputEvent)
M module-apps/application-settings/widgets/ColorTestListItem.hpp => module-apps/application-settings/widgets/ColorTestListItem.hpp +0 -1
@@ 25,7 25,6 @@ namespace gui
explicit ColorTestListItem(app::Application *app, const Color color);
bool onInput(const InputEvent &inputEvent) override;
- bool onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) override;
[[nodiscard]] uint8_t getColorIntensity();
};
} /* namespace gui */
M module-apps/application-special-input/widgets/SpecialInputTableWidget.cpp => module-apps/application-special-input/widgets/SpecialInputTableWidget.cpp +5 -6
@@ 61,13 61,12 @@ namespace gui
}
return true;
};
- }
- auto SpecialInputTableWidget::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) -> bool
- {
- box->setPosition(0, 0);
- box->setSize(specialCharacterTableWidget::window_grid_w, specialCharacterTableWidget::window_grid_h);
- return true;
+ dimensionChangedCallback = [&](gui::Item &, const BoundingBox &newDim) -> bool {
+ box->setArea(
+ {0, 0, specialCharacterTableWidget::window_grid_w, specialCharacterTableWidget::window_grid_h});
+ return true;
+ };
}
void SpecialInputTableWidget::decorateActionActivated(Item *it, const std::string &str)
M module-apps/application-special-input/widgets/SpecialInputTableWidget.hpp => module-apps/application-special-input/widgets/SpecialInputTableWidget.hpp +0 -1
@@ 33,7 33,6 @@ namespace gui
public:
SpecialInputTableWidget(app::Application *app, std::list<Carrier> &&carier);
- auto onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) -> bool override;
};
} /* namespace gui */
M module-apps/windows/AppWindow.cpp => module-apps/windows/AppWindow.cpp +2 -11
@@ 73,19 73,10 @@ namespace gui
return true;
}
- bool AppWindow::updateBatteryCharger(bool charging)
+ bool AppWindow::updateBatteryStatus()
{
- topBar->updateBattery(charging);
- return true;
- }
-
- // updates battery level in the window
- bool AppWindow::updateBatteryLevel(uint32_t percentage)
- {
- // get old value of battery level, calcualte new level and comapre both
- // if they are different make a change and return true, otherwise return false;
if (topBar != nullptr) {
- return topBar->updateBattery(percentage);
+ return topBar->updateBattery();
}
return false;
}
M module-apps/windows/AppWindow.hpp => module-apps/windows/AppWindow.hpp +1 -3
@@ 62,11 62,9 @@ namespace gui
virtual bool onDatabaseMessage(sys::Message *msg);
- bool updateBatteryCharger(bool charging);
bool setSIM();
// updates battery level in the window
- bool updateBatteryLevel(uint32_t percentage);
- // updates battery level in the window
+ bool updateBatteryStatus();
bool updateSignalStrength();
bool updateNetworkAccessTechnology();
virtual bool updateTime(const UTF8 &timeStr);
M module-audio/Audio/AudioCommon.cpp => module-audio/Audio/AudioCommon.cpp +3 -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 "AudioCommon.hpp"
@@ 8,9 8,9 @@
namespace audio
{
- audio::RetCode GetDeviceError(bsp::AudioDevice::RetCode retCode)
+ audio::RetCode GetDeviceError(AudioDevice::RetCode retCode)
{
- if (retCode == bsp::AudioDevice::RetCode::Success) {
+ if (retCode == AudioDevice::RetCode::Success) {
return RetCode::Success;
}
M module-audio/Audio/AudioCommon.hpp => module-audio/Audio/AudioCommon.hpp +8 -7
@@ 1,16 1,17 @@
-// 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
+#include "AudioDevice.hpp"
+#include "Profiles/Profile.hpp"
+
+#include <Service/Message.hpp>
+#include <Utils.hpp>
+
#include <map>
#include <bitset>
-#include <bsp/audio/bsp_audio.hpp>
-#include <Utils.hpp>
#include <utility>
-#include <Service/Message.hpp>
-
-#include "Profiles/Profile.hpp"
namespace audio
{
@@ 243,7 244,7 @@ namespace audio
friend class ::audio::AudioMux;
};
- RetCode GetDeviceError(bsp::AudioDevice::RetCode retCode);
+ RetCode GetDeviceError(AudioDevice::RetCode retCode);
const std::string str(RetCode retcode);
[[nodiscard]] auto GetVolumeText(const audio::Volume &volume) -> std::string;
} // namespace audio
R module-bsp/bsp/audio/bsp_audio.hpp => module-audio/Audio/AudioDevice.hpp +14 -18
@@ 1,3 1,6 @@
+// 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 <Audio/Endpoint.hpp>
@@ 6,7 9,7 @@
#include <memory>
#include <functional>
-namespace bsp
+namespace audio
{
class AudioDevice : public audio::IOProxy
@@ 27,35 30,30 @@ namespace bsp
Bluetooth
};
+ enum class Flags
+ {
+ OutputMono = 1 << 0,
+ OutputStereo = 1 << 1,
+ InputLeft = 1 << 2,
+ InputRight = 1 << 3,
+ InputStereo = 1 << 4
+ };
+
enum class InputPath
{
Headphones,
Microphone,
- BluetoothHSP,
None
};
enum class OutputPath
{
Headphones,
- HeadphonesMono,
Earspeaker,
Loudspeaker,
- LoudspeakerMono,
- BluetoothA2DP,
- BluetoothHSP,
None
};
- enum class Flags
- {
- OutputMono = 1 << 0,
- OutputStereo = 1 << 1,
- InputLeft = 1 << 2,
- InputRight = 1 << 3,
- InputStereo = 1 << 4
- };
-
using Format = struct
{
uint32_t sampleRate_Hz = 0; /*!< Sample rate of audio data */
@@ 75,8 73,6 @@ namespace bsp
virtual ~AudioDevice() = default;
- static std::optional<std::unique_ptr<AudioDevice>> Create(Type type);
-
virtual RetCode Start(const Format &format) = 0;
virtual RetCode Stop() = 0;
@@ 116,4 112,4 @@ namespace bsp
bool isInitialized = false;
};
-} // namespace bsp
+} // namespace audio
A module-audio/Audio/AudioDeviceFactory.cpp => module-audio/Audio/AudioDeviceFactory.cpp +25 -0
@@ 0,0 1,25 @@
+// Copyright (c) 2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "AudioDeviceFactory.hpp"
+
+using namespace audio;
+
+AudioDeviceFactory::AudioDeviceFactory(Observer *observer) : _observer(observer)
+{}
+
+std::shared_ptr<AudioDevice> AudioDeviceFactory::CreateDevice(AudioDevice::Type deviceType)
+{
+ std::shared_ptr<AudioDevice> device = getDeviceFromType(deviceType);
+
+ if (_observer != nullptr && device) {
+ _observer->onDeviceCreated(device);
+ }
+
+ return device;
+}
+
+void AudioDeviceFactory::setObserver(Observer *observer) noexcept
+{
+ _observer = observer;
+}
A module-audio/Audio/AudioDeviceFactory.hpp => module-audio/Audio/AudioDeviceFactory.hpp +34 -0
@@ 0,0 1,34 @@
+// Copyright (c) 2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include "AudioDevice.hpp"
+
+#include <memory>
+
+namespace audio
+{
+
+ class AudioDeviceFactory
+ {
+ class Observer
+ {
+ public:
+ virtual void onDeviceCreated(std::shared_ptr<AudioDevice> device) = 0;
+ };
+
+ public:
+ explicit AudioDeviceFactory(Observer *observer = nullptr);
+
+ void setObserver(Observer *observer) noexcept;
+ std::shared_ptr<AudioDevice> CreateDevice(AudioDevice::Type);
+
+ protected:
+ virtual std::shared_ptr<AudioDevice> getDeviceFromType(AudioDevice::Type) = 0;
+
+ private:
+ Observer *_observer = nullptr;
+ };
+
+}; // namespace audio
A module-audio/Audio/AudioPlatform.hpp => module-audio/Audio/AudioPlatform.hpp +18 -0
@@ 0,0 1,18 @@
+// Copyright (c) 2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include "AudioDeviceFactory.hpp"
+
+#include <memory>
+
+namespace audio
+{
+ class AudioPlatform
+ {
+ public:
+ static std::unique_ptr<AudioDeviceFactory> GetDeviceFactory();
+ };
+
+}; // namespace audio
D module-audio/Audio/BluetoothProxyAudio.cpp => module-audio/Audio/BluetoothProxyAudio.cpp +0 -93
@@ 1,93 0,0 @@
-// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
-// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
-
-#include "BluetoothProxyAudio.hpp"
-#include <service-bluetooth/BluetoothMessage.hpp>
-
-namespace bsp
-{
- BluetoothProxyAudio::BluetoothProxyAudio(AudioServiceMessage::Callback callback,
- audio::Stream &dataStreamOut,
- audio::Stream &dataStreamIn,
- AudioDevice::Format &format)
- : dataStreamOut(dataStreamOut), dataStreamIn(dataStreamIn), serviceCallback(std::move(callback)),
- audioFormat(format)
- {
- LOG_DEBUG("BluetoothProxyAudio created.");
- }
-
- AudioDevice::RetCode BluetoothProxyAudio::Start(const AudioDevice::Format &format)
- {
- auto msg = BluetoothProxyStartMessage(dataStreamOut, dataStreamIn, format);
- serviceCallback(&msg);
- return AudioDevice::RetCode::Success;
- }
-
- AudioDevice::RetCode BluetoothProxyAudio::Stop()
- {
- auto msg = BluetoothProxyStopMessage(audioFormat);
- serviceCallback(&msg);
- return AudioDevice::RetCode::Success;
- }
-
- AudioDevice::RetCode BluetoothProxyAudio::OutputVolumeCtrl(float vol)
- {
- audioFormat.outputVolume = vol;
- auto msg = BluetoothProxySetVolumeMessage(audioFormat);
- serviceCallback(&msg);
- return AudioDevice::RetCode::Success;
- }
-
- AudioDevice::RetCode BluetoothProxyAudio::InputGainCtrl(float gain)
- {
- audioFormat.inputGain = gain;
- auto msg = BluetoothProxySetGainMessage(audioFormat);
- serviceCallback(&msg);
- return AudioDevice::RetCode::Success;
- }
-
- AudioDevice::RetCode BluetoothProxyAudio::OutputPathCtrl(AudioDevice::OutputPath outputPath)
- {
- audioFormat.outputPath = outputPath;
- auto msg = BluetoothProxySetOutputPathMessage(audioFormat);
- serviceCallback(&msg);
- return AudioDevice::RetCode::Success;
- }
-
- AudioDevice::RetCode BluetoothProxyAudio::InputPathCtrl(AudioDevice::InputPath inputPath)
- {
- audioFormat.inputPath = inputPath;
- auto msg = BluetoothProxySetInputPathMessage(audioFormat);
- serviceCallback(&msg);
- return AudioDevice::RetCode::Success;
- }
-
- bool BluetoothProxyAudio::IsFormatSupported(const AudioDevice::Format &format)
- {
- LOG_DEBUG("Format assumed to be supported");
- return true;
- }
-
- BluetoothProxyAudio::~BluetoothProxyAudio()
- {
- Stop();
- }
-
- void BluetoothProxyAudio::onDataReceive()
- {}
-
- void BluetoothProxyAudio::onDataSend()
- {}
-
- void BluetoothProxyAudio::enableInput()
- {}
-
- void BluetoothProxyAudio::enableOutput()
- {}
-
- void BluetoothProxyAudio::disableInput()
- {}
-
- void BluetoothProxyAudio::disableOutput()
- {}
-} // namespace bsp
D module-audio/Audio/BluetoothProxyAudio.hpp => module-audio/Audio/BluetoothProxyAudio.hpp +0 -45
@@ 1,45 0,0 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
-// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
-
-#pragma once
-
-#include "AudioCommon.hpp"
-#include "Stream.hpp"
-
-#include "bsp/audio/bsp_audio.hpp"
-
-namespace bsp
-{
- class BluetoothProxyAudio final : public AudioDevice
- {
- public:
- BluetoothProxyAudio(AudioServiceMessage::Callback callback,
- audio::Stream &dataStreamOut,
- audio::Stream &dataStreamIn,
- AudioDevice::Format &format);
-
- ~BluetoothProxyAudio() final;
-
- AudioDevice::RetCode Start(const Format &format) final;
- AudioDevice::RetCode Stop() final;
- AudioDevice::RetCode OutputVolumeCtrl(float vol) final;
- AudioDevice::RetCode InputGainCtrl(float gain) final;
- AudioDevice::RetCode OutputPathCtrl(OutputPath outputPath) final;
- AudioDevice::RetCode InputPathCtrl(InputPath inputPath) final;
- bool IsFormatSupported(const Format &format) final;
-
- void onDataReceive() final;
- void onDataSend() final;
- void enableInput() final;
- void enableOutput() final;
- void disableInput() final;
- void disableOutput() final;
-
- private:
- audio::Stream &dataStreamOut;
- audio::Stream &dataStreamIn;
- AudioServiceMessage::Callback serviceCallback;
- AudioDevice::Format audioFormat;
- };
-
-} // namespace bsp
M module-audio/Audio/Operation/IdleOperation.cpp => module-audio/Audio/Operation/IdleOperation.cpp +1 -1
@@ 10,7 10,7 @@ namespace audio
IdleOperation::IdleOperation([[maybe_unused]] const char *file) : Operation(nullptr)
{
- supportedProfiles.emplace_back(Profile::Create(Profile::Type::Idle, nullptr), true);
+ supportedProfiles.emplace_back(Profile::Create(Profile::Type::Idle), true);
currentProfile = supportedProfiles[0].profile;
}
M module-audio/Audio/Operation/Operation.cpp => module-audio/Audio/Operation/Operation.cpp +9 -7
@@ 5,15 5,15 @@
#include <algorithm>
+#include "Audio/AudioDevice.hpp"
+#include "Audio/AudioDeviceFactory.hpp"
+#include "Audio/AudioPlatform.hpp"
+
#include "IdleOperation.hpp"
#include "PlaybackOperation.hpp"
#include "RecorderOperation.hpp"
#include "RouterOperation.hpp"
-#include "Audio/BluetoothProxyAudio.hpp"
-
-#include <bsp/audio/bsp_audio.hpp>
-
namespace audio
{
std::unique_ptr<Operation> Operation::Create(Operation::Type t,
@@ 91,11 91,13 @@ namespace audio
gain = utils::getNumericValue<audio::Gain>(val.value());
}
- supportedProfiles.emplace_back(Profile::Create(profile, nullptr, volume, gain), isAvailable);
+ supportedProfiles.emplace_back(Profile::Create(profile, volume, gain), isAvailable);
}
- std::optional<std::unique_ptr<bsp::AudioDevice>> Operation::CreateDevice(bsp::AudioDevice::Type type)
+ std::shared_ptr<AudioDevice> Operation::CreateDevice(AudioDevice::Type type)
{
- return bsp::AudioDevice::Create(type).value_or(nullptr);
+ auto factory = AudioPlatform::GetDeviceFactory();
+
+ return factory->CreateDevice(type);
}
} // namespace audio
M module-audio/Audio/Operation/Operation.hpp => module-audio/Audio/Operation/Operation.hpp +2 -3
@@ 4,7 4,6 @@
#pragma once
#include <memory>
-#include <optional>
#include <functional>
#include <Audio/AudioCommon.hpp>
@@ 123,7 122,7 @@ namespace audio
};
std::shared_ptr<Profile> currentProfile;
- std::unique_ptr<bsp::AudioDevice> audioDevice;
+ std::shared_ptr<AudioDevice> audioDevice;
std::vector<SupportedProfile> supportedProfiles;
State state = State::Idle;
@@ 142,7 141,7 @@ namespace audio
virtual audio::RetCode SwitchProfile(const Profile::Type type) = 0;
std::shared_ptr<Profile> GetProfile(const Profile::Type type);
- std::optional<std::unique_ptr<bsp::AudioDevice>> CreateDevice(bsp::AudioDevice::Type type);
+ std::shared_ptr<AudioDevice> CreateDevice(AudioDevice::Type type);
};
} // namespace audio
M module-audio/Audio/Operation/PlaybackOperation.cpp => module-audio/Audio/Operation/PlaybackOperation.cpp +3 -6
@@ 163,7 163,7 @@ namespace audio
dec->stopDecodingWorker();
audioDevice.reset();
dataStreamOut.reset();
- audioDevice = CreateDevice(newProfile->GetAudioDeviceType()).value_or(nullptr);
+ audioDevice = CreateDevice(newProfile->GetAudioDeviceType());
if (audioDevice == nullptr) {
LOG_ERROR("Error creating AudioDevice");
return RetCode::Failed;
@@ 172,13 172,10 @@ namespace audio
// adjust new profile with information from file's tags
newProfile->SetSampleRate(tags->sample_rate);
if (tags->num_channel == channel::stereoSound) {
- newProfile->SetInOutFlags(static_cast<uint32_t>(bsp::AudioDevice::Flags::OutputStereo));
+ newProfile->SetInOutFlags(static_cast<uint32_t>(AudioDevice::Flags::OutputStereo));
}
else {
- newProfile->SetInOutFlags(static_cast<uint32_t>(bsp::AudioDevice::Flags::OutputMono));
- if (newProfile->GetOutputPath() == bsp::AudioDevice::OutputPath::Headphones) {
- newProfile->SetOutputPath(bsp::AudioDevice::OutputPath::HeadphonesMono);
- }
+ newProfile->SetInOutFlags(static_cast<uint32_t>(AudioDevice::Flags::OutputMono));
}
// store profile
M module-audio/Audio/Operation/RecorderOperation.cpp => module-audio/Audio/Operation/RecorderOperation.cpp +3 -2
@@ 2,8 2,9 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "RecorderOperation.hpp"
+
+#include "Audio/AudioDevice.hpp"
#include "Audio/encoder/Encoder.hpp"
-#include "bsp/audio/bsp_audio.hpp"
#include "Audio/Profiles/Profile.hpp"
#include "Audio/Profiles/ProfileRecordingHeadphones.hpp"
#include "Audio/Profiles/ProfileRecordingOnBoardMic.hpp"
@@ 157,7 158,7 @@ namespace audio
return RetCode::UnsupportedProfile;
}
- audioDevice = CreateDevice(currentProfile->GetAudioDeviceType()).value_or(nullptr);
+ audioDevice = CreateDevice(currentProfile->GetAudioDeviceType());
if (audioDevice == nullptr) {
LOG_ERROR("Error creating AudioDevice");
return RetCode::Failed;
M module-audio/Audio/Operation/RecorderOperation.hpp => module-audio/Audio/Operation/RecorderOperation.hpp +2 -2
@@ 1,11 1,11 @@
-// 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
#include "Operation.hpp"
#include <Audio/encoder/Encoder.hpp>
-#include <bsp/audio/bsp_audio.hpp>
+#include <Audio/AudioDevice.hpp>
namespace audio
{
M module-audio/Audio/Operation/RouterOperation.cpp => module-audio/Audio/Operation/RouterOperation.cpp +5 -6
@@ 3,11 3,11 @@
#include "RouterOperation.hpp"
+#include <Audio/AudioDevice.hpp>
#include <Audio/AudioCommon.hpp>
#include <Audio/Profiles/Profile.hpp>
#include <Audio/StreamFactory.hpp>
-#include <bsp_audio.hpp>
#include <log/log.hpp>
#include <mutex.hpp>
@@ 60,13 60,12 @@ namespace audio
}
// try to run devices with the format
- if (auto ret = audioDevice->Start(currentProfile->GetAudioFormat());
- ret != bsp::AudioDevice::RetCode::Success) {
+ if (auto ret = audioDevice->Start(currentProfile->GetAudioFormat()); ret != AudioDevice::RetCode::Success) {
return GetDeviceError(ret);
}
if (auto ret = audioDeviceCellular->Start(currentProfile->GetAudioFormat());
- ret != bsp::AudioDevice::RetCode::Success) {
+ ret != AudioDevice::RetCode::Success) {
return GetDeviceError(ret);
}
@@ 180,13 179,13 @@ namespace audio
Stop();
}
- audioDevice = CreateDevice(newProfile->GetAudioDeviceType()).value_or(nullptr);
+ audioDevice = CreateDevice(newProfile->GetAudioDeviceType());
if (audioDevice == nullptr) {
LOG_ERROR("Error creating AudioDevice");
return RetCode::Failed;
}
- audioDeviceCellular = CreateDevice(bsp::AudioDevice::Type::Cellular).value_or(nullptr);
+ audioDeviceCellular = CreateDevice(AudioDevice::Type::Cellular);
if (audioDeviceCellular == nullptr) {
LOG_ERROR("Error creating AudioDeviceCellular");
return RetCode::Failed;
M module-audio/Audio/Operation/RouterOperation.hpp => module-audio/Audio/Operation/RouterOperation.hpp +3 -2
@@ 5,11 5,12 @@
#include "Operation.hpp"
+#include <Audio/AudioDevice.hpp>
#include <Audio/encoder/Encoder.hpp>
#include <Audio/AudioCommon.hpp>
#include <Audio/Profiles/Profile.hpp>
#include <Audio/Endpoint.hpp>
-#include <bsp/audio/bsp_audio.hpp>
+
#include <mutex.hpp>
#include <memory>
@@ 53,7 54,7 @@ namespace audio
std::unique_ptr<Stream> dataStreamOut;
std::unique_ptr<Stream> dataStreamIn;
std::unique_ptr<Encoder> enc;
- std::unique_ptr<bsp::AudioDevice> audioDeviceCellular;
+ std::shared_ptr<AudioDevice> audioDeviceCellular;
std::unique_ptr<StreamConnection> outputConnection;
std::unique_ptr<StreamConnection> inputConnection;
};
M module-audio/Audio/Profiles/Profile.cpp => module-audio/Audio/Profiles/Profile.cpp +17 -33
@@ 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 "Profile.hpp"
@@ 24,53 24,50 @@
namespace audio
{
- std::unique_ptr<Profile> Profile::Create(const Type t,
- std::function<int32_t()> callback,
- std::optional<Volume> vol,
- std::optional<Gain> gain)
+ std::unique_ptr<Profile> Profile::Create(const Type t, std::optional<Volume> vol, std::optional<Gain> gain)
{
std::unique_ptr<Profile> inst;
switch (t) {
case Type::PlaybackHeadphones:
assert(vol);
- inst = std::make_unique<ProfilePlaybackHeadphones>(callback, vol.value());
+ inst = std::make_unique<ProfilePlaybackHeadphones>(vol.value());
break;
case Type::PlaybackLoudspeaker:
assert(vol);
- inst = std::make_unique<ProfilePlaybackLoudspeaker>(callback, vol.value());
+ inst = std::make_unique<ProfilePlaybackLoudspeaker>(vol.value());
break;
case Type::PlaybackBluetoothA2DP:
assert(vol);
- inst = std::make_unique<ProfilePlaybackBluetoothA2DP>(callback, vol.value());
+ inst = std::make_unique<ProfilePlaybackBluetoothA2DP>(vol.value());
break;
case Type::RecordingBuiltInMic:
assert(gain);
- inst = std::make_unique<ProfileRecordingOnBoardMic>(callback, gain.value());
+ inst = std::make_unique<ProfileRecordingOnBoardMic>(gain.value());
break;
case Type::RecordingHeadphones:
assert(gain);
- inst = std::make_unique<ProfileRecordingHeadphones>(callback, gain.value());
+ inst = std::make_unique<ProfileRecordingHeadphones>(gain.value());
break;
case Type::RecordingBluetoothHSP:
assert(gain);
- inst = std::make_unique<ProfileRecordingBluetoothHSP>(callback, gain.value());
+ inst = std::make_unique<ProfileRecordingBluetoothHSP>(gain.value());
break;
case Type::RoutingHeadphones:
assert(gain && vol);
- inst = std::make_unique<ProfileRoutingHeadphones>(callback, vol.value(), gain.value());
+ inst = std::make_unique<ProfileRoutingHeadphones>(vol.value(), gain.value());
break;
case Type::RoutingLoudspeaker:
assert(gain && vol);
- inst = std::make_unique<ProfileRoutingLoudspeaker>(callback, vol.value(), gain.value());
+ inst = std::make_unique<ProfileRoutingLoudspeaker>(vol.value(), gain.value());
break;
case Type::RoutingEarspeaker:
assert(gain && vol);
- inst = std::make_unique<ProfileRoutingEarspeaker>(callback, vol.value(), gain.value());
+ inst = std::make_unique<ProfileRoutingEarspeaker>(vol.value(), gain.value());
break;
case Type::RoutingBluetoothHSP:
assert(gain && vol);
- inst = std::make_unique<ProfileRoutingBluetoothHSP>(callback, vol.value(), gain.value());
+ inst = std::make_unique<ProfileRoutingBluetoothHSP>(vol.value(), gain.value());
break;
case Type::Idle:
inst = std::make_unique<ProfileIdle>();
@@ 82,42 79,29 @@ namespace audio
Profile::Profile(const std::string &name,
const Type type,
- const bsp::AudioDevice::Format &fmt,
- bsp::AudioDevice::Type devType,
- std::function<int32_t()> callback)
- : audioFormat(fmt), audioDeviceType(devType), name(name), type(type), dbAccessCallback(callback)
+ const AudioDevice::Format &fmt,
+ AudioDevice::Type devType)
+ : audioFormat(fmt), audioDeviceType(devType), name(name), type(type)
{}
void Profile::SetInputGain(Gain gain)
{
audioFormat.inputGain = gain;
- if (dbAccessCallback) {
- dbAccessCallback();
- }
}
void Profile::SetOutputVolume(Volume vol)
{
audioFormat.outputVolume = vol;
- if (dbAccessCallback) {
- dbAccessCallback();
- }
}
- void Profile::SetInputPath(bsp::AudioDevice::InputPath path)
+ void Profile::SetInputPath(AudioDevice::InputPath path)
{
audioFormat.inputPath = path;
- if (dbAccessCallback) {
- dbAccessCallback();
- }
}
- void Profile::SetOutputPath(bsp::AudioDevice::OutputPath path)
+ void Profile::SetOutputPath(AudioDevice::OutputPath path)
{
audioFormat.outputPath = path;
- if (dbAccessCallback) {
- dbAccessCallback();
- }
}
void Profile::SetInOutFlags(uint32_t flags)
M module-audio/Audio/Profiles/Profile.hpp => module-audio/Audio/Profiles/Profile.hpp +14 -21
@@ 1,14 1,14 @@
-// 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
+#include "Audio/AudioDevice.hpp"
+
#include <memory>
#include <functional>
#include <string>
-#include <bsp/audio/bsp_audio.hpp>
-
namespace audio
{
using Volume = uint32_t;
@@ 43,9 43,8 @@ namespace audio
};
static std::unique_ptr<Profile> Create(const Type t,
- std::function<int32_t()> callback = nullptr,
- std::optional<Volume> vol = 0,
- std::optional<Gain> gain = 0);
+ std::optional<Volume> vol = 0,
+ std::optional<Gain> gain = 0);
void SetOutputVolume(Volume vol);
@@ 55,9 54,9 @@ namespace audio
void SetSampleRate(uint32_t samplerate);
- void SetOutputPath(bsp::AudioDevice::OutputPath path);
+ void SetOutputPath(AudioDevice::OutputPath path);
- void SetInputPath(bsp::AudioDevice::InputPath path);
+ void SetInputPath(AudioDevice::InputPath path);
Volume GetOutputVolume() const
{
@@ 79,22 78,22 @@ namespace audio
return audioFormat.flags;
}
- bsp::AudioDevice::OutputPath GetOutputPath() const
+ AudioDevice::OutputPath GetOutputPath() const
{
return audioFormat.outputPath;
}
- bsp::AudioDevice::InputPath GetInputPath() const
+ AudioDevice::InputPath GetInputPath() const
{
return audioFormat.inputPath;
}
- bsp::AudioDevice::Type GetAudioDeviceType() const
+ AudioDevice::Type GetAudioDeviceType() const
{
return audioDeviceType;
}
- bsp::AudioDevice::Format GetAudioFormat()
+ AudioDevice::Format GetAudioFormat()
{
return audioFormat;
}
@@ 110,19 109,13 @@ namespace audio
}
protected:
- Profile(const std::string &name,
- const Type type,
- const bsp::AudioDevice::Format &fmt,
- bsp::AudioDevice::Type devType,
- std::function<int32_t()> callback);
+ Profile(const std::string &name, const Type type, const AudioDevice::Format &fmt, AudioDevice::Type devType);
- bsp::AudioDevice::Format audioFormat{};
- bsp::AudioDevice::Type audioDeviceType = bsp::AudioDevice::Type::Audiocodec;
+ AudioDevice::Format audioFormat{};
+ AudioDevice::Type audioDeviceType = AudioDevice::Type::Audiocodec;
std::string name;
Type type = Type::Idle;
-
- std::function<int32_t()> dbAccessCallback = nullptr;
};
[[nodiscard]] const std::string str(const Profile::Type &profileType);
M module-audio/Audio/Profiles/ProfileIdle.hpp => module-audio/Audio/Profiles/ProfileIdle.hpp +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
#pragma once
@@ 11,7 11,7 @@ namespace audio
class ProfileIdle : public Profile
{
public:
- ProfileIdle() : Profile("Idle", Type::Idle, bsp::AudioDevice::Format{}, bsp::AudioDevice::Type::None, nullptr)
+ ProfileIdle() : Profile("Idle", Type::Idle, AudioDevice::Format{}, AudioDevice::Type::None)
{}
};
M module-audio/Audio/Profiles/ProfilePlaybackBluetoothA2DP.hpp => module-audio/Audio/Profiles/ProfilePlaybackBluetoothA2DP.hpp +10 -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
#pragma once
@@ 11,18 11,17 @@ namespace audio
class ProfilePlaybackBluetoothA2DP : public Profile
{
public:
- ProfilePlaybackBluetoothA2DP(std::function<int32_t()> callback, Volume volume)
+ ProfilePlaybackBluetoothA2DP(Volume volume)
: Profile("Playback Bluetooth A2DP",
Type::PlaybackBluetoothA2DP,
- bsp::AudioDevice::Format{.sampleRate_Hz = 44100,
- .bitWidth = 16,
- .flags = 0,
- .outputVolume = static_cast<float>(volume),
- .inputGain = 0,
- .inputPath = bsp::AudioDevice::InputPath::None,
- .outputPath = bsp::AudioDevice::OutputPath::BluetoothA2DP},
- bsp::AudioDevice::Type::Bluetooth,
- callback)
+ AudioDevice::Format{.sampleRate_Hz = 44100,
+ .bitWidth = 16,
+ .flags = 0,
+ .outputVolume = static_cast<float>(volume),
+ .inputGain = 0,
+ .inputPath = AudioDevice::InputPath::None,
+ .outputPath = AudioDevice::OutputPath::None},
+ AudioDevice::Type::Bluetooth)
{}
};
M module-audio/Audio/Profiles/ProfilePlaybackHeadphones.hpp => module-audio/Audio/Profiles/ProfilePlaybackHeadphones.hpp +10 -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
#pragma once
@@ 10,20 10,18 @@ namespace audio
class ProfilePlaybackHeadphones : public Profile
{
public:
- ProfilePlaybackHeadphones(std::function<int32_t()> callback, Volume volume)
+ ProfilePlaybackHeadphones(Volume volume)
: Profile("Playback Headphones",
Type::PlaybackHeadphones,
- bsp::AudioDevice::Format{.sampleRate_Hz = 0,
- .bitWidth = 16,
- .flags = 0,
- .outputVolume = static_cast<float>(volume),
- .inputGain = 0,
- .inputPath = bsp::AudioDevice::InputPath::None,
- .outputPath = bsp::AudioDevice::OutputPath::Headphones},
- bsp::AudioDevice::Type::Audiocodec,
- callback)
+ AudioDevice::Format{.sampleRate_Hz = 0,
+ .bitWidth = 16,
+ .flags = 0,
+ .outputVolume = static_cast<float>(volume),
+ .inputGain = 0,
+ .inputPath = AudioDevice::InputPath::None,
+ .outputPath = AudioDevice::OutputPath::Headphones},
+ AudioDevice::Type::Audiocodec)
{}
};
} // namespace audio
-
M module-audio/Audio/Profiles/ProfilePlaybackLoudspeaker.hpp => module-audio/Audio/Profiles/ProfilePlaybackLoudspeaker.hpp +10 -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
#pragma once
@@ 11,18 11,17 @@ namespace audio
class ProfilePlaybackLoudspeaker : public Profile
{
public:
- ProfilePlaybackLoudspeaker(std::function<int32_t()> callback, Volume volume)
+ ProfilePlaybackLoudspeaker(Volume volume)
: Profile("Playback Loudspeaker",
Type::PlaybackLoudspeaker,
- bsp::AudioDevice::Format{.sampleRate_Hz = 0,
- .bitWidth = 16,
- .flags = 0,
- .outputVolume = static_cast<float>(volume),
- .inputGain = 0,
- .inputPath = bsp::AudioDevice::InputPath::None,
- .outputPath = bsp::AudioDevice::OutputPath::Loudspeaker},
- bsp::AudioDevice::Type::Audiocodec,
- callback)
+ AudioDevice::Format{.sampleRate_Hz = 0,
+ .bitWidth = 16,
+ .flags = 0,
+ .outputVolume = static_cast<float>(volume),
+ .inputGain = 0,
+ .inputPath = AudioDevice::InputPath::None,
+ .outputPath = AudioDevice::OutputPath::Loudspeaker},
+ AudioDevice::Type::Audiocodec)
{}
};
M module-audio/Audio/Profiles/ProfileRecordingBluetoothHSP.hpp => module-audio/Audio/Profiles/ProfileRecordingBluetoothHSP.hpp +13 -15
@@ 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
@@ 11,20 11,18 @@ namespace audio
class ProfileRecordingBluetoothHSP : public Profile
{
public:
- ProfileRecordingBluetoothHSP(std::function<int32_t()> callback, Gain gain)
- : Profile(
- "Recording Bluetooth HSP",
- Type::RecordingHeadphones,
- bsp::AudioDevice::Format{.sampleRate_Hz = 8000,
- .bitWidth = 16,
- .flags = static_cast<uint32_t>(
- bsp::AudioDevice::Flags::InputLeft), // microphone use left audio channel
- .outputVolume = 0,
- .inputGain = static_cast<float>(gain),
- .inputPath = bsp::AudioDevice::InputPath::BluetoothHSP,
- .outputPath = bsp::AudioDevice::OutputPath::None},
- bsp::AudioDevice::Type::Bluetooth,
- callback)
+ ProfileRecordingBluetoothHSP(Gain gain)
+ : Profile("Recording Bluetooth HSP",
+ Type::RecordingHeadphones,
+ AudioDevice::Format{.sampleRate_Hz = 8000,
+ .bitWidth = 16,
+ .flags = static_cast<uint32_t>(
+ AudioDevice::Flags::InputLeft), // microphone use left audio channel
+ .outputVolume = 0,
+ .inputGain = static_cast<float>(gain),
+ .inputPath = AudioDevice::InputPath::None,
+ .outputPath = AudioDevice::OutputPath::None},
+ AudioDevice::Type::Bluetooth)
{}
};
M module-audio/Audio/Profiles/ProfileRecordingHeadphones.hpp => module-audio/Audio/Profiles/ProfileRecordingHeadphones.hpp +13 -15
@@ 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
@@ 10,20 10,18 @@ namespace audio
class ProfileRecordingHeadphones : public Profile
{
public:
- ProfileRecordingHeadphones(std::function<int32_t()> callback, Gain gain)
- : Profile(
- "Recording Headset",
- Type::RecordingHeadphones,
- bsp::AudioDevice::Format{.sampleRate_Hz = 44100,
- .bitWidth = 16,
- .flags = static_cast<uint32_t>(
- bsp::AudioDevice::Flags::InputLeft), // microphone use left audio channel
- .outputVolume = 0,
- .inputGain = static_cast<float>(gain),
- .inputPath = bsp::AudioDevice::InputPath::Headphones,
- .outputPath = bsp::AudioDevice::OutputPath::None},
- bsp::AudioDevice::Type::Audiocodec,
- callback)
+ ProfileRecordingHeadphones(Gain gain)
+ : Profile("Recording Headset",
+ Type::RecordingHeadphones,
+ AudioDevice::Format{.sampleRate_Hz = 44100,
+ .bitWidth = 16,
+ .flags = static_cast<uint32_t>(
+ AudioDevice::Flags::InputLeft), // microphone use left audio channel
+ .outputVolume = 0,
+ .inputGain = static_cast<float>(gain),
+ .inputPath = AudioDevice::InputPath::Headphones,
+ .outputPath = AudioDevice::OutputPath::None},
+ AudioDevice::Type::Audiocodec)
{}
};
M module-audio/Audio/Profiles/ProfileRecordingOnBoardMic.hpp => module-audio/Audio/Profiles/ProfileRecordingOnBoardMic.hpp +13 -15
@@ 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
@@ 10,20 10,18 @@ namespace audio
class ProfileRecordingOnBoardMic : public Profile
{
public:
- ProfileRecordingOnBoardMic(std::function<int32_t()> callback, Gain gain)
- : Profile(
- "Recording On Board Microphone",
- Type::RecordingBuiltInMic,
- bsp::AudioDevice::Format{.sampleRate_Hz = 44100,
- .bitWidth = 16,
- .flags = static_cast<uint32_t>(
- bsp::AudioDevice::Flags::InputLeft), // microphone use left audio channel
- .outputVolume = 0,
- .inputGain = static_cast<float>(gain),
- .inputPath = bsp::AudioDevice::InputPath::Microphone,
- .outputPath = bsp::AudioDevice::OutputPath::None},
- bsp::AudioDevice::Type::Audiocodec,
- callback)
+ ProfileRecordingOnBoardMic(Gain gain)
+ : Profile("Recording On Board Microphone",
+ Type::RecordingBuiltInMic,
+ AudioDevice::Format{.sampleRate_Hz = 44100,
+ .bitWidth = 16,
+ .flags = static_cast<uint32_t>(
+ AudioDevice::Flags::InputLeft), // microphone use left audio channel
+ .outputVolume = 0,
+ .inputGain = static_cast<float>(gain),
+ .inputPath = AudioDevice::InputPath::Microphone,
+ .outputPath = AudioDevice::OutputPath::None},
+ AudioDevice::Type::Audiocodec)
{}
};
M module-audio/Audio/Profiles/ProfileRoutingBluetoothHSP.hpp => module-audio/Audio/Profiles/ProfileRoutingBluetoothHSP.hpp +15 -16
@@ 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
@@ 10,21 10,20 @@ namespace audio
class ProfileRoutingBluetoothHSP : public Profile
{
public:
- ProfileRoutingBluetoothHSP(std::function<int32_t()> callback, Volume volume, Gain gain)
- : Profile("Routing Bluetooth HSP",
- Type::RoutingBluetoothHSP,
- bsp::AudioDevice::Format{
- .sampleRate_Hz = 8000,
- .bitWidth = 16,
- .flags = static_cast<uint32_t>(
- bsp::AudioDevice::Flags::InputLeft) | // microphone use left audio channel
- static_cast<uint32_t>(bsp::AudioDevice::Flags::OutputMono),
- .outputVolume = static_cast<float>(volume),
- .inputGain = static_cast<float>(gain),
- .inputPath = bsp::AudioDevice::InputPath::BluetoothHSP,
- .outputPath = bsp::AudioDevice::OutputPath::BluetoothHSP},
- bsp::AudioDevice::Type::Bluetooth,
- callback)
+ ProfileRoutingBluetoothHSP(Volume volume, Gain gain)
+ : Profile(
+ "Routing Bluetooth HSP",
+ Type::RoutingBluetoothHSP,
+ AudioDevice::Format{.sampleRate_Hz = 8000,
+ .bitWidth = 16,
+ .flags = static_cast<uint32_t>(
+ AudioDevice::Flags::InputLeft) | // microphone use left audio channel
+ static_cast<uint32_t>(AudioDevice::Flags::OutputMono),
+ .outputVolume = static_cast<float>(volume),
+ .inputGain = static_cast<float>(gain),
+ .inputPath = AudioDevice::InputPath::None,
+ .outputPath = AudioDevice::OutputPath::None},
+ AudioDevice::Type::Bluetooth)
{}
};
M module-audio/Audio/Profiles/ProfileRoutingEarspeaker.hpp => module-audio/Audio/Profiles/ProfileRoutingEarspeaker.hpp +15 -17
@@ 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
@@ 10,23 10,21 @@ namespace audio
class ProfileRoutingEarspeaker : public Profile
{
public:
- ProfileRoutingEarspeaker(std::function<int32_t()> callback, Volume volume, Gain gain)
- : Profile("Routing Earspeaker",
- Type::RoutingEarspeaker,
- bsp::AudioDevice::Format{
- .sampleRate_Hz = 16000,
- .bitWidth = 16,
- .flags = static_cast<uint32_t>(
- bsp::AudioDevice::Flags::InputLeft) | // microphone use left audio channel
- static_cast<uint32_t>(bsp::AudioDevice::Flags::OutputMono),
- .outputVolume = static_cast<float>(volume),
- .inputGain = static_cast<float>(gain),
- .inputPath = bsp::AudioDevice::InputPath::Microphone,
- .outputPath = bsp::AudioDevice::OutputPath::Earspeaker},
- bsp::AudioDevice::Type::Audiocodec,
- callback)
+ ProfileRoutingEarspeaker(Volume volume, Gain gain)
+ : Profile(
+ "Routing Earspeaker",
+ Type::RoutingEarspeaker,
+ AudioDevice::Format{.sampleRate_Hz = 16000,
+ .bitWidth = 16,
+ .flags = static_cast<uint32_t>(
+ AudioDevice::Flags::InputLeft) | // microphone use left audio channel
+ static_cast<uint32_t>(AudioDevice::Flags::OutputMono),
+ .outputVolume = static_cast<float>(volume),
+ .inputGain = static_cast<float>(gain),
+ .inputPath = AudioDevice::InputPath::Microphone,
+ .outputPath = AudioDevice::OutputPath::Earspeaker},
+ AudioDevice::Type::Audiocodec)
{}
};
} // namespace audio
-
M module-audio/Audio/Profiles/ProfileRoutingHeadphones.hpp => module-audio/Audio/Profiles/ProfileRoutingHeadphones.hpp +15 -16
@@ 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
@@ 10,21 10,20 @@ namespace audio
class ProfileRoutingHeadphones : public Profile
{
public:
- ProfileRoutingHeadphones(std::function<int32_t()> callback, Volume volume, Gain gain)
- : Profile("Routing Headset",
- Type::RoutingHeadphones,
- bsp::AudioDevice::Format{
- .sampleRate_Hz = 16000,
- .bitWidth = 16,
- .flags = static_cast<uint32_t>(
- bsp::AudioDevice::Flags::InputLeft) | // microphone use left audio channel
- static_cast<uint32_t>(bsp::AudioDevice::Flags::OutputMono),
- .outputVolume = static_cast<float>(volume),
- .inputGain = static_cast<float>(gain),
- .inputPath = bsp::AudioDevice::InputPath::Headphones,
- .outputPath = bsp::AudioDevice::OutputPath::HeadphonesMono},
- bsp::AudioDevice::Type::Audiocodec,
- callback)
+ ProfileRoutingHeadphones(Volume volume, Gain gain)
+ : Profile(
+ "Routing Headset",
+ Type::RoutingHeadphones,
+ AudioDevice::Format{.sampleRate_Hz = 16000,
+ .bitWidth = 16,
+ .flags = static_cast<uint32_t>(
+ AudioDevice::Flags::InputLeft) | // microphone use left audio channel
+ static_cast<uint32_t>(AudioDevice::Flags::OutputMono),
+ .outputVolume = static_cast<float>(volume),
+ .inputGain = static_cast<float>(gain),
+ .inputPath = AudioDevice::InputPath::Headphones,
+ .outputPath = AudioDevice::OutputPath::Headphones},
+ AudioDevice::Type::Audiocodec)
{}
};
M module-audio/Audio/Profiles/ProfileRoutingLoudspeaker.hpp => module-audio/Audio/Profiles/ProfileRoutingLoudspeaker.hpp +15 -16
@@ 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
@@ 10,21 10,20 @@ namespace audio
class ProfileRoutingLoudspeaker : public Profile
{
public:
- ProfileRoutingLoudspeaker(std::function<int32_t()> callback, Volume volume, Gain gain)
- : Profile("Routing Speakerphone",
- Type::RoutingLoudspeaker,
- bsp::AudioDevice::Format{
- .sampleRate_Hz = 16000,
- .bitWidth = 16,
- .flags = static_cast<uint32_t>(
- bsp::AudioDevice::Flags::InputLeft) | // microphone use left audio channel
- static_cast<uint32_t>(bsp::AudioDevice::Flags::OutputMono),
- .outputVolume = static_cast<float>(volume),
- .inputGain = static_cast<float>(gain),
- .inputPath = bsp::AudioDevice::InputPath::Microphone,
- .outputPath = bsp::AudioDevice::OutputPath::LoudspeakerMono},
- bsp::AudioDevice::Type::Audiocodec,
- callback)
+ ProfileRoutingLoudspeaker(Volume volume, Gain gain)
+ : Profile(
+ "Routing Speakerphone",
+ Type::RoutingLoudspeaker,
+ AudioDevice::Format{.sampleRate_Hz = 16000,
+ .bitWidth = 16,
+ .flags = static_cast<uint32_t>(
+ AudioDevice::Flags::InputLeft) | // microphone use left audio channel
+ static_cast<uint32_t>(AudioDevice::Flags::OutputMono),
+ .outputVolume = static_cast<float>(volume),
+ .inputGain = static_cast<float>(gain),
+ .inputPath = AudioDevice::InputPath::Microphone,
+ .outputPath = AudioDevice::OutputPath::Loudspeaker},
+ AudioDevice::Type::Audiocodec)
{}
};
M module-audio/CMakeLists.txt => module-audio/CMakeLists.txt +14 -34
@@ 1,9 1,11 @@
-cmake_minimum_required(VERSION 3.12)
+# Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+cmake_minimum_required(VERSION 3.12)
project(module-audio VERSION 1.0
DESCRIPTION "Audio module library")
-
set(SOURCES
"${CMAKE_CURRENT_SOURCE_DIR}/Audio/decoder/Decoder.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Audio/decoder/DecoderWorker.cpp"
@@ 16,13 18,13 @@ set(SOURCES
"${CMAKE_CURRENT_SOURCE_DIR}/Audio/encoder/EncoderWAV.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Audio/Audio.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/Audio/AudioDeviceFactory.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Audio/AudioMux.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Audio/AudioCommon.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Audio/Endpoint.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Audio/Stream.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Audio/StreamFactory.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Audio/StreamQueuedEventsListener.cpp"
- "${CMAKE_CURRENT_SOURCE_DIR}/Audio/BluetoothProxyAudio.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Audio/Operation/Operation.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Audio/Operation/PlaybackOperation.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Audio/Operation/RecorderOperation.cpp"
@@ 31,51 33,30 @@ set(SOURCES
"${CMAKE_CURRENT_SOURCE_DIR}/Audio/Profiles/Profile.cpp"
)
-if(NOT ${PROJECT_TARGET} STREQUAL "TARGET_Linux")
- include(targets/Target_Cross.cmake)
-else()
- include(targets/Target_Linux.cmake)
-endif()
-
-
-add_library(${PROJECT_NAME} STATIC ${SOURCES} ${BOARD_SOURCES})
-
-target_include_directories( ${PROJECT_NAME} PRIVATE ${TAGLIB_INCLUDE_DIRS} )
+# include target specific rules
+set(AUDIO_BOARD_LIBRARY audio-${PROJECT_TARGET_NAME})
+add_subdirectory(board/${PROJECT_TARGET_NAME})
+target_include_directories(${AUDIO_BOARD_LIBRARY} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
-
-# Board specific compilation definitions,options,include directories and features
+add_library(${PROJECT_NAME} STATIC ${SOURCES})
+target_include_directories(${PROJECT_NAME} PRIVATE ${TAGLIB_INCLUDE_DIRS})
target_compile_definitions(${PROJECT_NAME} PUBLIC ${PROJECT_CONFIG_DEFINITIONS})
target_compile_definitions(${PROJECT_NAME} PUBLIC ${PROJECT_TARGET})
target_compile_definitions(${PROJECT_NAME} PUBLIC ${TARGET_COMPILE_DEFINITIONS})
-target_include_directories(${PROJECT_NAME} PUBLIC ${BOARD_DIR_INCLUDES})
target_include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_INCLUDES})
target_compile_features(${PROJECT_NAME} PUBLIC ${TARGET_COMPILE_FEATURES})
target_link_options(${PROJECT_NAME} PUBLIC ${TARGET_LINK_OPTIONS})
-
-target_include_directories(${PROJECT_NAME} PUBLIC "${CMAKE_CURRENT_LIST_DIR}/../module-bsp/bsp/audio")
+target_include_directories(${PROJECT_NAME} INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
# supress warning for flac decoder
set_source_files_properties(
"${CMAKE_CURRENT_SOURCE_DIR}/Audio/decoder/decoderFLAC.cpp"
PROPERTIES COMPILE_FLAGS
- "-Wno-implicit-fallthrough -Wno-error=maybe-uninitialized"
-)
-
-target_compile_definitions(${PROJECT_NAME}
-
- PUBLIC
-
-)
-
-target_include_directories(${PROJECT_NAME}
-
- PUBLIC
-
- ${CMAKE_CURRENT_SOURCE_DIR}
-
+ "-Wno-implicit-fallthrough -Wno-error=maybe-uninitialized"
)
target_link_libraries(${PROJECT_NAME}
+ ${AUDIO_BOARD_LIBRARY}
module-bsp
module-os
module-utils
@@ 86,4 67,3 @@ target_link_libraries(${PROJECT_NAME}
if (${ENABLE_TESTS})
add_subdirectory(Audio/test)
endif ()
-
A module-audio/board/linux/CMakeLists.txt => module-audio/board/linux/CMakeLists.txt +12 -0
@@ 0,0 1,12 @@
+# Copyright (c) 2021, Mudita Sp. z.o.o. All rights reserved.
+# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+set(AUDIO_LINUX_SOURCES
+ LinuxAudioPlatform.cpp
+)
+
+add_library(${AUDIO_BOARD_LIBRARY} STATIC ${AUDIO_LINUX_SOURCES})
+target_include_directories(${AUDIO_BOARD_LIBRARY} INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
+target_link_libraries(${AUDIO_BOARD_LIBRARY}
+ module-os
+)
A module-audio/board/linux/LinuxAudioPlatform.cpp => module-audio/board/linux/LinuxAudioPlatform.cpp +25 -0
@@ 0,0 1,25 @@
+// Copyright (c) 2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include <Audio/AudioPlatform.hpp>
+
+#include <memory>
+#include <utility>
+
+using audio::AudioDevice;
+using audio::AudioDeviceFactory;
+using audio::AudioPlatform;
+
+class DummyAudioFactory : public AudioDeviceFactory
+{
+ protected:
+ std::shared_ptr<AudioDevice> getDeviceFromType([[maybe_unused]] AudioDevice::Type deviceType)
+ {
+ return nullptr;
+ }
+};
+
+std::unique_ptr<AudioDeviceFactory> AudioPlatform::GetDeviceFactory()
+{
+ return std::make_unique<DummyAudioFactory>();
+}
A module-audio/board/rt1051/CMakeLists.txt => module-audio/board/rt1051/CMakeLists.txt +17 -0
@@ 0,0 1,17 @@
+# Copyright (c) 2021, Mudita Sp. z.o.o. All rights reserved.
+# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+set(AUDIO_RT1051_SOURCES
+ "SAIAudioDevice.cpp"
+ "RT1051AudioCodec.cpp"
+ "RT1051CellularAudio.cpp"
+ "RT1051DeviceFactory.cpp"
+ "RT1051Platform.cpp"
+)
+
+add_library(${AUDIO_BOARD_LIBRARY} STATIC ${AUDIO_RT1051_SOURCES})
+target_include_directories(${AUDIO_BOARD_LIBRARY} INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
+target_link_libraries(${AUDIO_BOARD_LIBRARY}
+ module-bsp
+ module-os
+)
R module-bsp/board/rt1051/bsp/audio/RT1051Audiocodec.cpp => module-audio/board/rt1051/RT1051AudioCodec.cpp +71 -94
@@ 1,43 1,68 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
-#include "RT1051Audiocodec.hpp"
+#include "RT1051AudioCodec.hpp"
#include "board.h"
#include "dma_config.h"
#include "log/log.hpp"
#include "bsp/BoardDefinitions.hpp"
+#include "board/rt1051/common/audio.hpp"
#include <mutex.hpp>
-namespace bsp
+namespace audio
{
+ sai_edma_handle_t RT1051AudioCodec::txHandle = {};
+ sai_edma_handle_t RT1051AudioCodec::rxHandle = {};
- using namespace drivers;
-
- std::shared_ptr<drivers::DriverPLL> RT1051Audiocodec::pllAudio;
- std::shared_ptr<drivers::DriverDMAMux> RT1051Audiocodec::dmamux;
- std::shared_ptr<drivers::DriverDMA> RT1051Audiocodec::dma;
- std::unique_ptr<drivers::DriverDMAHandle> RT1051Audiocodec::rxDMAHandle;
- std::unique_ptr<drivers::DriverDMAHandle> RT1051Audiocodec::txDMAHandle;
- sai_config_t RT1051Audiocodec::config = {};
- std::uint32_t RT1051Audiocodec::mclkSourceClockHz = 0;
- sai_edma_handle_t RT1051Audiocodec::txHandle = {};
- sai_edma_handle_t RT1051Audiocodec::rxHandle = {};
-
- RT1051Audiocodec::RT1051Audiocodec()
+ RT1051AudioCodec::RT1051AudioCodec()
: SAIAudioDevice(BOARD_AUDIOCODEC_SAIx, &rxHandle, &txHandle), saiInFormat{}, saiOutFormat{},
codecParams{}, codec{}
{
isInitialized = true;
}
- RT1051Audiocodec::~RT1051Audiocodec()
+ RT1051AudioCodec::~RT1051AudioCodec()
{
Stop();
}
- AudioDevice::RetCode RT1051Audiocodec::Start(const bsp::AudioDevice::Format &format)
+ CodecParamsMAX98090::InputPath RT1051AudioCodec::getCodecInputPath(const AudioDevice::Format &format)
+ {
+ switch (format.inputPath) {
+ case AudioDevice::InputPath::Headphones:
+ return CodecParamsMAX98090::InputPath::Headphones;
+
+ case AudioDevice::InputPath::Microphone:
+ return CodecParamsMAX98090::InputPath::Microphone;
+
+ default:
+ return CodecParamsMAX98090::InputPath::None;
+ };
+ }
+
+ CodecParamsMAX98090::OutputPath RT1051AudioCodec::getCodecOutputPath(const AudioDevice::Format &format)
+ {
+ auto mono = (format.flags & static_cast<std::uint32_t>(AudioDevice::Flags::OutputMono)) != 0;
+
+ switch (format.outputPath) {
+ case AudioDevice::OutputPath::Headphones:
+ return mono ? CodecParamsMAX98090::OutputPath::HeadphonesMono : CodecParamsMAX98090::OutputPath::Headphones;
+
+ case AudioDevice::OutputPath::Earspeaker:
+ return CodecParamsMAX98090::OutputPath::Earspeaker;
+
+ case AudioDevice::OutputPath::Loudspeaker:
+ return mono ? CodecParamsMAX98090::OutputPath::LoudspeakerMono
+ : CodecParamsMAX98090::OutputPath::Loudspeaker;
+
+ default:
+ return CodecParamsMAX98090::OutputPath::None;
+ }
+ }
+
+ AudioDevice::RetCode RT1051AudioCodec::Start(const AudioDevice::Format &format)
{
cpp_freertos::LockGuard lock(mutex);
@@ 78,8 103,8 @@ namespace bsp
LOG_ERROR("Unsupported sample rate");
}
- codecParams.inputPath = format.inputPath;
- codecParams.outputPath = format.outputPath;
+ codecParams.inputPath = getCodecInputPath(format);
+ codecParams.outputPath = getCodecOutputPath(format);
codecParams.outVolume = format.outputVolume;
codecParams.inGain = format.inputGain;
codec.Start(codecParams);
@@ 92,7 117,7 @@ namespace bsp
return AudioDevice::RetCode::Success;
}
- AudioDevice::RetCode RT1051Audiocodec::Stop()
+ AudioDevice::RetCode RT1051AudioCodec::Stop()
{
cpp_freertos::LockGuard lock(mutex);
@@ 111,7 136,7 @@ namespace bsp
return AudioDevice::RetCode::Success;
}
- AudioDevice::RetCode RT1051Audiocodec::OutputVolumeCtrl(float vol)
+ AudioDevice::RetCode RT1051AudioCodec::OutputVolumeCtrl(float vol)
{
currentFormat.outputVolume = vol;
CodecParamsMAX98090 params;
@@ 121,7 146,7 @@ namespace bsp
return AudioDevice::RetCode::Success;
}
- AudioDevice::RetCode RT1051Audiocodec::InputGainCtrl(float gain)
+ AudioDevice::RetCode RT1051AudioCodec::InputGainCtrl(float gain)
{
currentFormat.inputGain = gain;
CodecParamsMAX98090 params;
@@ 131,27 156,27 @@ namespace bsp
return AudioDevice::RetCode::Success;
}
- AudioDevice::RetCode RT1051Audiocodec::InputPathCtrl(InputPath inputPath)
+ AudioDevice::RetCode RT1051AudioCodec::InputPathCtrl(InputPath inputPath)
{
currentFormat.inputPath = inputPath;
CodecParamsMAX98090 params;
- params.inputPath = inputPath;
+ params.inputPath = getCodecInputPath(currentFormat);
params.opCmd = CodecParamsMAX98090::Cmd::SetInput;
codec.Ioctrl(params);
return AudioDevice::RetCode::Success;
}
- AudioDevice::RetCode RT1051Audiocodec::OutputPathCtrl(OutputPath outputPath)
+ AudioDevice::RetCode RT1051AudioCodec::OutputPathCtrl(OutputPath outputPath)
{
currentFormat.outputPath = outputPath;
CodecParamsMAX98090 params;
- params.outputPath = outputPath;
+ params.outputPath = getCodecOutputPath(currentFormat);
params.opCmd = CodecParamsMAX98090::Cmd::SetOutput;
codec.Ioctrl(params);
return AudioDevice::RetCode::Success;
}
- bool RT1051Audiocodec::IsFormatSupported(const bsp::AudioDevice::Format &format)
+ bool RT1051AudioCodec::IsFormatSupported(const AudioDevice::Format &format)
{
if (CodecParamsMAX98090::ValToSampleRate(format.sampleRate_Hz) == CodecParamsMAX98090::SampleRate::Invalid) {
@@ 159,68 184,19 @@ namespace bsp
}
return true;
}
- // INTERNALS
-
- void RT1051Audiocodec::Init()
- {
-
- pllAudio = DriverPLL::Create(static_cast<PLLInstances>(BoardDefinitions ::AUDIO_PLL), DriverPLLParams{});
- dmamux = DriverDMAMux::Create(static_cast<DMAMuxInstances>(BoardDefinitions ::AUDIOCODEC_DMAMUX),
- DriverDMAMuxParams{});
- dma = DriverDMA::Create(static_cast<DMAInstances>(BoardDefinitions ::AUDIOCODEC_DMA), DriverDMAParams{});
-
- // Enable MCLK clock
- IOMUXC_GPR->GPR1 |= BOARD_AUDIOCODEC_SAIx_MCLK_MASK;
-
- txDMAHandle = dma->CreateHandle(static_cast<uint32_t>(BoardDefinitions ::AUDIOCODEC_TX_DMA_CHANNEL));
- rxDMAHandle = dma->CreateHandle(static_cast<uint32_t>(BoardDefinitions ::AUDIOCODEC_RX_DMA_CHANNEL));
- dmamux->Enable(static_cast<uint32_t>(BoardDefinitions ::AUDIOCODEC_TX_DMA_CHANNEL),
- BSP_AUDIOCODEC_SAIx_DMA_TX_SOURCE);
- dmamux->Enable(static_cast<uint32_t>(BoardDefinitions ::AUDIOCODEC_RX_DMA_CHANNEL),
- BSP_AUDIOCODEC_SAIx_DMA_RX_SOURCE);
-
- mclkSourceClockHz = GetPerphSourceClock(PerphClock_SAI2);
-
- // Initialize SAI Tx module
- SAI_TxGetDefaultConfig(&config);
- config.masterSlave = kSAI_Slave;
- SAI_TxInit(BOARD_AUDIOCODEC_SAIx, &config);
-
- // Initialize SAI Rx module
- SAI_RxGetDefaultConfig(&config);
-
- config.masterSlave = kSAI_Slave;
- SAI_RxInit(BOARD_AUDIOCODEC_SAIx, &config);
- }
-
- void RT1051Audiocodec::Deinit()
- {
- memset(&config, 0, sizeof config);
- SAI_Deinit(BOARD_AUDIOCODEC_SAIx);
- if (dmamux) {
- dmamux->Disable(static_cast<uint32_t>(BoardDefinitions ::AUDIOCODEC_TX_DMA_CHANNEL));
- dmamux->Disable(static_cast<uint32_t>(BoardDefinitions ::AUDIOCODEC_RX_DMA_CHANNEL));
- }
-
- // force order of destruction
- txDMAHandle.reset();
- rxDMAHandle.reset();
- dma.reset();
- dmamux.reset();
- pllAudio.reset();
- }
- void RT1051Audiocodec::InStart()
+ void RT1051AudioCodec::InStart()
{
- sai_transfer_format_t sai_format = {};
+ sai_transfer_format_t sai_format;
+ auto audioCfg = bsp::AudioConfig::get();
/* Configure the audio format */
sai_format.bitWidth = saiInFormat.bitWidth;
sai_format.channel = 0U;
sai_format.sampleRate_Hz = saiInFormat.sampleRate_Hz;
- sai_format.masterClockHz = mclkSourceClockHz;
+ sai_format.masterClockHz = audioCfg->mclkSourceClockHz;
sai_format.isFrameSyncCompact = false;
- sai_format.protocol = config.protocol;
+ sai_format.protocol = audioCfg->config.protocol;
sai_format.stereo = saiInFormat.stereo;
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
sai_format.watermark = FSL_FEATURE_SAI_FIFO_COUNT / 2U;
@@ 230,10 206,10 @@ namespace bsp
&rxHandle,
rxAudioCodecCallback,
this,
- reinterpret_cast<edma_handle_t *>(rxDMAHandle->GetHandle()));
+ reinterpret_cast<edma_handle_t *>(audioCfg->rxDMAHandle->GetHandle()));
SAI_TransferRxSetFormatEDMA(
- BOARD_AUDIOCODEC_SAIx, &rxHandle, &sai_format, mclkSourceClockHz, mclkSourceClockHz);
+ BOARD_AUDIOCODEC_SAIx, &rxHandle, &sai_format, audioCfg->mclkSourceClockHz, audioCfg->mclkSourceClockHz);
DisableIRQ(BOARD_AUDIOCODEC_SAIx_RX_IRQ);
@@ 241,17 217,18 @@ namespace bsp
SAI_RxSoftwareReset(BOARD_AUDIOCODEC_SAIx, kSAI_ResetTypeSoftware);
}
- void RT1051Audiocodec::OutStart()
+ void RT1051AudioCodec::OutStart()
{
- sai_transfer_format_t sai_format = {};
+ sai_transfer_format_t sai_format;
+ auto audioCfg = bsp::AudioConfig::get();
/* Configure the audio format */
sai_format.bitWidth = saiOutFormat.bitWidth;
sai_format.channel = 0U;
sai_format.sampleRate_Hz = saiOutFormat.sampleRate_Hz;
- sai_format.masterClockHz = mclkSourceClockHz;
+ sai_format.masterClockHz = audioCfg->mclkSourceClockHz;
sai_format.isFrameSyncCompact = false;
- sai_format.protocol = config.protocol;
+ sai_format.protocol = audioCfg->config.protocol;
sai_format.stereo = saiOutFormat.stereo;
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
sai_format.watermark = FSL_FEATURE_SAI_FIFO_COUNT / 2U;
@@ 261,9 238,9 @@ namespace bsp
&txHandle,
txAudioCodecCallback,
this,
- reinterpret_cast<edma_handle_t *>(txDMAHandle->GetHandle()));
+ reinterpret_cast<edma_handle_t *>(audioCfg->txDMAHandle->GetHandle()));
SAI_TransferTxSetFormatEDMA(
- BOARD_AUDIOCODEC_SAIx, &txHandle, &sai_format, mclkSourceClockHz, mclkSourceClockHz);
+ BOARD_AUDIOCODEC_SAIx, &txHandle, &sai_format, audioCfg->mclkSourceClockHz, audioCfg->mclkSourceClockHz);
DisableIRQ(BOARD_AUDIOCODEC_SAIx_TX_IRQ);
@@ 271,7 248,7 @@ namespace bsp
SAI_TxSoftwareReset(BOARD_AUDIOCODEC_SAIx, kSAI_ResetTypeSoftware);
}
- void RT1051Audiocodec::OutStop()
+ void RT1051AudioCodec::OutStop()
{
SAI_TxDisableInterrupts(BOARD_AUDIOCODEC_SAIx, kSAI_FIFOErrorInterruptEnable);
if (txHandle.dmaHandle) {
@@ 280,7 257,7 @@ namespace bsp
memset(&txHandle, 0, sizeof(txHandle));
}
- void RT1051Audiocodec::InStop()
+ void RT1051AudioCodec::InStop()
{
SAI_RxDisableInterrupts(BOARD_AUDIOCODEC_SAIx, kSAI_FIFOErrorInterruptEnable);
if (rxHandle.dmaHandle) {
@@ 291,14 268,14 @@ namespace bsp
void rxAudioCodecCallback(I2S_Type *base, sai_edma_handle_t *handle, status_t status, void *userData)
{
- auto self = static_cast<RT1051Audiocodec *>(userData);
+ auto self = static_cast<RT1051AudioCodec *>(userData);
self->onDataReceive();
}
void txAudioCodecCallback(I2S_Type *base, sai_edma_handle_t *handle, status_t status, void *userData)
{
- auto self = static_cast<RT1051Audiocodec *>(userData);
+ auto self = static_cast<RT1051AudioCodec *>(userData);
self->onDataSend();
}
-} // namespace bsp
+} // namespace audio
R module-bsp/board/rt1051/bsp/audio/RT1051Audiocodec.hpp => module-audio/board/rt1051/RT1051AudioCodec.hpp +9 -19
@@ 10,7 10,7 @@
#include "task.h"
#include "macros.h"
-#include "CodecMAX98090.hpp"
+#include "board/rt1051/bsp/audio/CodecMAX98090.hpp"
#include "drivers/pll/DriverPLL.hpp"
#include "drivers/dmamux/DriverDMAMux.hpp"
@@ 18,24 18,21 @@
#include <mutex.hpp>
-namespace bsp
+namespace audio
{
void txAudioCodecCallback(I2S_Type *base, sai_edma_handle_t *handle, status_t status, void *userData);
void rxAudioCodecCallback(I2S_Type *base, sai_edma_handle_t *handle, status_t status, void *userData);
- class RT1051Audiocodec : public SAIAudioDevice
+ class RT1051AudioCodec : public SAIAudioDevice
{
public:
- static void Init();
- static void Deinit();
-
friend void txAudioCodecCallback(I2S_Type *base, sai_edma_handle_t *handle, status_t status, void *userData);
friend void rxAudioCodecCallback(I2S_Type *base, sai_edma_handle_t *handle, status_t status, void *userData);
- RT1051Audiocodec();
- virtual ~RT1051Audiocodec();
+ RT1051AudioCodec();
+ virtual ~RT1051AudioCodec();
AudioDevice::RetCode Start(const Format &format) override final;
AudioDevice::RetCode Stop() override final;
@@ 63,22 60,12 @@ namespace bsp
sai_mono_stereo_t stereo; /*!< Mono or stereo */
};
- static sai_config_t config;
- static std::uint32_t mclkSourceClockHz;
-
State state = State::Stopped;
SAIFormat saiInFormat;
SAIFormat saiOutFormat;
CodecParamsMAX98090 codecParams;
CodecMAX98090 codec;
- // M.P: It is important to destroy these drivers in specific order
- static std::shared_ptr<drivers::DriverPLL> pllAudio;
- static std::shared_ptr<drivers::DriverDMAMux> dmamux;
- static std::shared_ptr<drivers::DriverDMA> dma;
- static std::unique_ptr<drivers::DriverDMAHandle> rxDMAHandle;
- static std::unique_ptr<drivers::DriverDMAHandle> txDMAHandle;
-
static AT_NONCACHEABLE_SECTION_INIT(sai_edma_handle_t txHandle);
static AT_NONCACHEABLE_SECTION_INIT(sai_edma_handle_t rxHandle);
@@ 86,5 73,8 @@ namespace bsp
void InStart();
void OutStop();
void InStop();
+
+ CodecParamsMAX98090::InputPath getCodecInputPath(const AudioDevice::Format &format);
+ CodecParamsMAX98090::OutputPath getCodecOutputPath(const AudioDevice::Format &format);
};
-} // namespace bsp
+} // namespace audio
R module-bsp/board/rt1051/bsp/audio/RT1051CellularAudio.cpp => module-audio/board/rt1051/RT1051CellularAudio.cpp +5 -5
@@ 10,7 10,7 @@
#include <mutex.hpp>
-namespace bsp
+namespace audio
{
using namespace drivers;
@@ 30,7 30,7 @@ namespace bsp
Deinit();
}
- AudioDevice::RetCode RT1051CellularAudio::Start(const bsp::AudioDevice::Format &format)
+ AudioDevice::RetCode RT1051CellularAudio::Start(const AudioDevice::Format &format)
{
cpp_freertos::LockGuard lock(mutex);
@@ 118,7 118,7 @@ namespace bsp
return AudioDevice::RetCode::Success;
}
- bool RT1051CellularAudio::IsFormatSupported(const bsp::AudioDevice::Format &format)
+ bool RT1051CellularAudio::IsFormatSupported(const AudioDevice::Format &format)
{
return true;
}
@@ 203,7 203,7 @@ namespace bsp
void RT1051CellularAudio::OutStart()
{
- sai_transfer_format_t sai_format = {};
+ sai_transfer_format_t sai_format;
/* Configure the audio format */
sai_format.bitWidth = saiOutFormat.bitWidth;
@@ 263,4 263,4 @@ namespace bsp
self->onDataSend();
}
-} // namespace bsp
+} // namespace audio
R module-bsp/board/rt1051/bsp/audio/RT1051CellularAudio.hpp => module-audio/board/rt1051/RT1051CellularAudio.hpp +2 -2
@@ 17,7 17,7 @@
#include <mutex.hpp>
-namespace bsp
+namespace audio
{
void txCellularCallback(I2S_Type *base, sai_edma_handle_t *handle, status_t status, void *userData);
@@ 80,6 80,6 @@ namespace bsp
void OutStop();
void InStop();
};
-} // namespace bsp
+} // namespace audio
#endif // PUREPHONE_RT1051CELLULARAUDIO_HPP
A module-audio/board/rt1051/RT1051DeviceFactory.cpp => module-audio/board/rt1051/RT1051DeviceFactory.cpp +35 -0
@@ 0,0 1,35 @@
+// Copyright (c) 2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "RT1051DeviceFactory.hpp"
+#include "board/rt1051/RT1051AudioCodec.hpp"
+#include "board/rt1051/RT1051CellularAudio.hpp"
+
+using audio::AudioDevice;
+using audio::RT1051AudioCodec;
+using audio::RT1051CellularAudio;
+using audio::RT1051DeviceFactory;
+
+std::shared_ptr<AudioDevice> RT1051DeviceFactory::getDeviceFromType(AudioDevice::Type deviceType)
+{
+ std::shared_ptr<AudioDevice> device;
+ switch (deviceType) {
+ case AudioDevice::Type::Audiocodec: {
+ device = std::make_unique<RT1051AudioCodec>();
+ } break;
+
+ case AudioDevice::Type::Bluetooth: {
+ LOG_FATAL("Bluetooth audio is not yet supported");
+ device = nullptr;
+ } break;
+
+ case AudioDevice::Type::Cellular: {
+ device = std::make_unique<RT1051CellularAudio>();
+ } break;
+
+ default:
+ break;
+ };
+
+ return device;
+}
A module-audio/board/rt1051/RT1051DeviceFactory.hpp => module-audio/board/rt1051/RT1051DeviceFactory.hpp +17 -0
@@ 0,0 1,17 @@
+// Copyright (c) 2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <Audio/AudioDeviceFactory.hpp>
+
+namespace audio
+{
+
+ class RT1051DeviceFactory : public AudioDeviceFactory
+ {
+ protected:
+ std::shared_ptr<AudioDevice> getDeviceFromType(AudioDevice::Type deviceType) override;
+ };
+
+}; // namespace audio
A module-audio/board/rt1051/RT1051Platform.cpp => module-audio/board/rt1051/RT1051Platform.cpp +16 -0
@@ 0,0 1,16 @@
+// Copyright (c) 2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include <Audio/AudioPlatform.hpp>
+
+#include "RT1051DeviceFactory.hpp"
+
+#include <utility>
+
+using audio::AudioDeviceFactory;
+using audio::AudioPlatform;
+
+std::unique_ptr<AudioDeviceFactory> AudioPlatform::GetDeviceFactory()
+{
+ return std::make_unique<RT1051DeviceFactory>();
+}
R module-bsp/board/rt1051/bsp/audio/SAIAudioDevice.cpp => module-audio/board/rt1051/SAIAudioDevice.cpp +1 -1
@@ 3,7 3,7 @@
#include "SAIAudioDevice.hpp"
-using namespace bsp;
+using namespace audio;
SAIAudioDevice::SAIAudioDevice(I2S_Type *base, sai_edma_handle_t *rxHandle, sai_edma_handle_t *txHandle)
: AudioDevice(saiCapabilities, saiCapabilities), _base(base), rx(rxHandle), tx(txHandle)
R module-bsp/board/rt1051/bsp/audio/SAIAudioDevice.hpp => module-audio/board/rt1051/SAIAudioDevice.hpp +4 -4
@@ 3,14 3,14 @@
#pragma once
-#include "bsp/audio/bsp_audio.hpp"
+#include <Audio/AudioDevice.hpp>
#include "fsl_sai_edma.h"
-namespace bsp
+namespace audio
{
- class SAIAudioDevice : public bsp::AudioDevice
+ class SAIAudioDevice : public AudioDevice
{
public:
SAIAudioDevice(I2S_Type *base, sai_edma_handle_t *rxHandle, sai_edma_handle_t *txHandle);
@@ 34,4 34,4 @@ namespace bsp
static constexpr Capabilities saiCapabilities = {.usesDMA = true};
};
-} // namespace bsp
+} // namespace audio
D module-audio/targets/Target_Cross.cmake => module-audio/targets/Target_Cross.cmake +0 -9
@@ 1,9 0,0 @@
-set(BOARD_SOURCES
-
- CACHE INTERNAL ""
- )
-
-set(BOARD_DIR_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}/board/cross CACHE INTERNAL "")
-
-
-
D module-audio/targets/Target_Linux.cmake => module-audio/targets/Target_Linux.cmake +0 -3
@@ 1,3 0,0 @@
-set(BOARD_SOURCES CACHE INTERNAL "")
-
-set(BOARD_DIR_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}/board/linux CACHE INTERNAL "")
M module-bluetooth/Bluetooth/interface/profiles/PAN.cpp => module-bluetooth/Bluetooth/interface/profiles/PAN.cpp +4 -4
@@ 115,10 115,10 @@ namespace bluetooth
{
// name has to have storage
constexpr uint32_t size = 64;
- static char lname[size] = {0};
- snprintf(lname, size, "%s %s", name.c_str(), "00:00:00:00:00:00");
- LOG_INFO("Setting local name: %s", lname);
- gap_set_local_name(lname);
+ static std::array<char, size> lname;
+ snprintf(lname.data(), size, "%s", name.c_str());
+ LOG_INFO("Setting local name: %s", lname.data());
+ gap_set_local_name(lname.data());
return Error();
}
namespace PAN
M module-bluetooth/Bluetooth/interface/profiles/Profile.hpp => module-bluetooth/Bluetooth/interface/profiles/Profile.hpp +4 -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
#pragma once
@@ 12,13 12,13 @@ namespace bluetooth
class Profile
{
public:
- virtual ~Profile() = default;
+ virtual ~Profile() = default;
virtual auto init() -> Error::Code = 0;
- virtual void setDeviceAddress(uint8_t *addr) = 0;
+ virtual void setDeviceAddress(uint8_t *addr) = 0;
virtual void setOwnerService(const sys::Service *service) = 0;
virtual auto getStreamData() -> std::shared_ptr<BluetoothStreamData> = 0;
virtual void connect() = 0;
virtual void disconnect() = 0;
};
-} // namespace Bt
+} // namespace bluetooth
M module-bluetooth/README.md => module-bluetooth/README.md +4 -3
@@ 18,6 18,10 @@ It's meant to provide interface layer for service-bluetooth like that:

<img src="./flowchart.svg">
+## Table of content
+- [Bluetooth on/off operation](./doc/bt_on_off.md)
+- [Bluetooth scan operation](./doc/bt_scan.md)
+
# Proposal of Bluetooth settings data flow
The Bluetooth settings related data flow is directed by three main entities:
@@ 46,6 50,3 @@ Flowchart below is an example of scenario, when user opens *BluetoothWindow*, an

-# Bluetooth on/off state machine diagram
-To be able to handle all events during start up and shutting down of the Bluetooth module the following state machine has been implemented:
-
A module-bluetooth/doc/bt_on_off.md => module-bluetooth/doc/bt_on_off.md +37 -0
@@ 0,0 1,37 @@
+# Bluetooth on-off operation
+This document aims to describe the basics of the Bluetooth module power management.
+
+## Turning on the Bluetooth module
+The Bluetooth module (hereinafter referred to as BT module) is connected to the processor via UART.
+Additionally, a reset pin is available to put the BT module into a reset state, which is used in the "power on" procedure.
+UART data transfers have been made using DMA, which speeds up the data rate. To be able to properly init the BT module,
+the following steps have to be taken:
+
+- Enable and configure UART interface
+- Enable and configure DMA channels
+- Properly init the BT module
+
+Enabling and configuring UART and related DMA channels is done in the BSP (board support package) module,
+therefore there is no need to describe it here. Those BSP functions are encapsulated and used by the Bluetooth stack library.
+
+### Power on procedure
+- send `message::bluetooth::SetStatus` message with `BluetoothStatus::State::On` value
+- wait for settings change: `bluetooth::Settings::State` set to `BluetoothStatus::State::On`
+
+#### A low-level flow of what's inside
+After the `BluetoothWorker` receives `bluetooth::Command::PowerOn` (sent by `ServiceBluetooth` after receiving the state change message),
+the state machine executes driver's `init` method. After the init is done, the Bluetooth stack is prepared to be run by the `run` method of the `Driver` class -
+it's done as the next step of the init procedure. When the Bluetooth stack has been initiated, the settings holder updates the BT state in the settings.
+
+## Turning off the Bluetooth module
+Turning off the BT module is basically reversed turning on - after sending the proper message, the Bluetooth driver
+turns off the Bluetooth stack. When the Bluetooth stack is turned off, the UART with DMA channels is deinitialized and BT module is put
+to the reset state.
+
+### Power off procedure
+- send `message::bluetooth::SetStatus` message with `BluetoothStatus::State::Off` value
+- wait for settings change: `bluetooth::Settings::State` set to `BluetoothStatus::State::Off`
+
+## Bluetooth on/off state machine diagram
+To be able to handle all events during start up and shutting down of the Bluetooth module the following state machine has been implemented:
+
R module-bluetooth/bt_on_off_state_diagram.puml => module-bluetooth/doc/bt_on_off_state_diagram.puml +0 -0
R module-bluetooth/bt_on_off_state_diagram.svg => module-bluetooth/doc/bt_on_off_state_diagram.svg +0 -0
A module-bluetooth/doc/bt_scan.md => module-bluetooth/doc/bt_scan.md +17 -0
@@ 0,0 1,17 @@
+# Bluetooth scan
+To be able to send data between devices it is necessary to pair the devices, and to know the physical address
+of the BT device, there is a need to perform devices scan.
+
+## Principle of operation
+Bluetooth scan works underneath the `ServiceBluetooth` - it is done on the middle layer, in the GAP profile interface.
+When scan request is executed, GAP performs the scan and sends scanned devices to the `ApplicationSettings`. In case when the BT
+module has discovered a device without a name, it will try to fetch the device name in another request. After the name-fetching
+is complete, the `ServiceBluetooth` sends back the device to the application.
+
+### Scan flow (user point of view)
+- send `BluetoothMessage(BluetoothMessage::Request::Scan)` to the `ServiceBluetooth`
+- for each scanned device receive `BluetoothScanResultMessage`
+- process the device
+- send `BluetoothMessage(BluetoothMessage::Request::StopScan)` to the `ServiceBluetooth` to stop the scan.
+
+
A module-bluetooth/doc/bt_scan.puml => module-bluetooth/doc/bt_scan.puml +13 -0
@@ 0,0 1,13 @@
+@startuml
+
+actor User
+participant ServiceBluetooth
+==Start scan==
+activate ServiceBluetooth
+User -> ServiceBluetooth : BluetoothMessage(BluetoothMessage::Request::Scan)
+ServiceBluetooth -> User : for each device: BluetoothScanResultMessage
+deactivate ServiceBluetooth
+==Stop scan==
+User -> ServiceBluetooth : BluetoothMessage(BluetoothMessage::Request::StopScan)
+
+@enduml
A module-bluetooth/doc/bt_scan.svg => module-bluetooth/doc/bt_scan.svg +23 -0
@@ 0,0 1,23 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="366px" preserveAspectRatio="none" style="width:506px;height:366px;" version="1.1" viewBox="0 0 506 366" width="506px" zoomAndPan="magnify"><defs><filter height="300%" id="f17abn9lsdmeoc" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><rect fill="#FFFFFF" filter="url(#f17abn9lsdmeoc)" height="93.3984" style="stroke:#A80036;stroke-width:1.0;" width="10" x="421" y="98.2969"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="24" x2="24" y1="88.2969" y2="281.9609"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="426" x2="426" y1="88.2969" y2="281.9609"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="32" x="5" y="84.9951">User</text><ellipse cx="24" cy="15" fill="#FEFECE" filter="url(#f17abn9lsdmeoc)" rx="8" ry="8" style="stroke:#A80036;stroke-width:2.0;"/><path d="M24,23 L24,50 M11,31 L37,31 M24,50 L11,65 M24,50 L37,65 " fill="none" filter="url(#f17abn9lsdmeoc)" style="stroke:#A80036;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="32" x="5" y="293.9561">User</text><ellipse cx="24" cy="307.2578" fill="#FEFECE" filter="url(#f17abn9lsdmeoc)" rx="8" ry="8" style="stroke:#A80036;stroke-width:2.0;"/><path d="M24,315.2578 L24,342.2578 M11,323.2578 L37,323.2578 M24,342.2578 L11,357.2578 M24,342.2578 L37,357.2578 " fill="none" filter="url(#f17abn9lsdmeoc)" style="stroke:#A80036;stroke-width:2.0;"/><rect fill="#FEFECE" filter="url(#f17abn9lsdmeoc)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="132" x="358" y="53"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="118" x="365" y="72.9951">ServiceBluetooth</text><rect fill="#FEFECE" filter="url(#f17abn9lsdmeoc)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="132" x="358" y="280.9609"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="118" x="365" y="300.9561">ServiceBluetooth</text><rect fill="#FFFFFF" filter="url(#f17abn9lsdmeoc)" height="93.3984" style="stroke:#A80036;stroke-width:1.0;" width="10" x="421" y="98.2969"/><rect fill="#EEEEEE" filter="url(#f17abn9lsdmeoc)" height="3" style="stroke:#EEEEEE;stroke-width:1.0;" width="499" x="0" y="118.8633"/><line style="stroke:#000000;stroke-width:1.0;" x1="0" x2="499" y1="118.8633" y2="118.8633"/><line style="stroke:#000000;stroke-width:1.0;" x1="0" x2="499" y1="121.8633" y2="121.8633"/><rect fill="#EEEEEE" filter="url(#f17abn9lsdmeoc)" height="23.1328" style="stroke:#000000;stroke-width:2.0;" width="89" x="205" y="108.2969"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacing" textLength="75" x="211" y="124.3638">Start scan</text><polygon fill="#A80036" points="409,158.5625,419,162.5625,409,166.5625,413,162.5625" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="24" x2="415" y1="162.5625" y2="162.5625"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="348" x="31" y="157.4966">BluetoothMessage(BluetoothMessage::Request::Scan)</text><polygon fill="#A80036" points="35,187.6953,25,191.6953,35,195.6953,31,191.6953" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="29" x2="425" y1="191.6953" y2="191.6953"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="295" x="41" y="186.6294">for each device: BluetoothScanResultMessage</text><rect fill="#EEEEEE" filter="url(#f17abn9lsdmeoc)" height="3" style="stroke:#EEEEEE;stroke-width:1.0;" width="499" x="0" y="220.2617"/><line style="stroke:#000000;stroke-width:1.0;" x1="0" x2="499" y1="220.2617" y2="220.2617"/><line style="stroke:#000000;stroke-width:1.0;" x1="0" x2="499" y1="223.2617" y2="223.2617"/><rect fill="#EEEEEE" filter="url(#f17abn9lsdmeoc)" height="23.1328" style="stroke:#000000;stroke-width:2.0;" width="87" x="206" y="209.6953"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacing" textLength="73" x="212" y="225.7622">Stop scan</text><polygon fill="#A80036" points="414,259.9609,424,263.9609,414,267.9609,418,263.9609" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="24" x2="420" y1="263.9609" y2="263.9609"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="378" x="31" y="258.895">BluetoothMessage(BluetoothMessage::Request::StopScan)</text><!--MD5=[3e00c5d120b5619ee5a1f6367740c9a8]
+@startuml
+
+actor User
+participant ServiceBluetooth
+==Start scan==
+activate ServiceBluetooth
+User -> ServiceBluetooth : BluetoothMessage(BluetoothMessage::Request::Scan)
+ServiceBluetooth -> User : for each device: BluetoothScanResultMessage
+deactivate ServiceBluetooth
+==Stop scan==
+User -> ServiceBluetooth : BluetoothMessage(BluetoothMessage::Request::StopScan)
+
+@enduml
+
+PlantUML version 1.2021.01(Tue Feb 02 08:55:08 CET 2021)
+(GPL source distribution)
+Java Runtime: OpenJDK Runtime Environment
+JVM: OpenJDK 64-Bit Server VM
+Default Encoding: UTF-8
+Language: en
+Country: US
+--></g></svg><
\ No newline at end of file
M module-bsp/CMakeLists.txt => module-bsp/CMakeLists.txt +4 -2
@@ 1,11 1,13 @@
-cmake_minimum_required(VERSION 3.12)
+# Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+cmake_minimum_required(VERSION 3.12)
project(module-bsp VERSION 1.0
DESCRIPTION "VFS module library")
set(SOURCES
"${CMAKE_CURRENT_SOURCE_DIR}/bsp/cellular/bsp_cellular.cpp"
- "${CMAKE_CURRENT_SOURCE_DIR}/bsp/audio/bsp_audio.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/bsp/lpm/bsp_lpm.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/drivers/pll/DriverPLL.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/drivers/dmamux/DriverDMAMux.cpp"
M module-bsp/board/rt1051/bsp/audio/CodecMAX98090.cpp => module-bsp/board/rt1051/bsp/audio/CodecMAX98090.cpp +30 -30
@@ 79,7 79,7 @@ CodecRetCode CodecMAX98090::Start(const CodecParams ¶m)
i2c->Write(i2cAddr, (uint8_t *)&q_dai_setup, 1);
// OUT configuration
- if (params.outputPath != bsp::AudioDevice::OutputPath::None) {
+ if (params.outputPath != CodecParamsMAX98090::OutputPath::None) {
// Control HP performance
max98090_reg_dachp_perfmode_t dacperf = {};
@@ 90,7 90,7 @@ CodecRetCode CodecMAX98090::Start(const CodecParams ¶m)
switch (params.outputPath) {
- case bsp::AudioDevice::OutputPath::HeadphonesMono: {
+ case CodecParamsMAX98090::OutputPath::HeadphonesMono: {
max98090_reg_playback_quick_setup_t q_playback_setup = {};
q_playback_setup.dig2hp = 1;
i2cAddr.subAddress = MAX98090_REG_PLAYBACK_QUICK_SETUP;
@@ 99,12 99,12 @@ CodecRetCode CodecMAX98090::Start(const CodecParams ¶m)
// Mix left DAC channel to left&right HP output
max98090_reg_lhp_mixer_t lmixconf = {};
lmixconf.mixhpl = 1;
- i2cAddr.subAddress = MAX98090_REG_LHP_MIXER_CONF;
+ i2cAddr.subAddress = MAX98090_REG_LHP_MIXER_CONF;
i2c->Write(i2cAddr, (uint8_t *)&lmixconf, 1);
max98090_reg_rhp_mixer_t rmixconf = {};
rmixconf.mixhpr = 1;
- i2cAddr.subAddress = MAX98090_REG_RHP_MIXER_CONF;
+ i2cAddr.subAddress = MAX98090_REG_RHP_MIXER_CONF;
i2c->Write(i2cAddr, (uint8_t *)&rmixconf, 1);
// Use mixer outputs instead of direct DAC outputs
@@ 116,25 116,25 @@ CodecRetCode CodecMAX98090::Start(const CodecParams ¶m)
} break;
- case bsp::AudioDevice::OutputPath::Headphones: {
+ case CodecParamsMAX98090::OutputPath::Headphones: {
max98090_reg_playback_quick_setup_t q_playback_setup = {};
q_playback_setup.dig2hp = 1;
- i2cAddr.subAddress = MAX98090_REG_PLAYBACK_QUICK_SETUP;
+ i2cAddr.subAddress = MAX98090_REG_PLAYBACK_QUICK_SETUP;
i2c->Write(i2cAddr, (uint8_t *)&q_playback_setup, 1);
} break;
- case bsp::AudioDevice::OutputPath::Earspeaker: {
+ case CodecParamsMAX98090::OutputPath::Earspeaker: {
max98090_reg_playback_quick_setup_t q_playback_setup = {};
- q_playback_setup.dig2ear = 1;
- i2cAddr.subAddress = MAX98090_REG_PLAYBACK_QUICK_SETUP;
+ q_playback_setup.dig2ear = 1;
+ i2cAddr.subAddress = MAX98090_REG_PLAYBACK_QUICK_SETUP;
i2c->Write(i2cAddr, (uint8_t *)&q_playback_setup, 1);
} break;
- case bsp::AudioDevice::OutputPath::Loudspeaker: {
+ case CodecParamsMAX98090::OutputPath::Loudspeaker: {
max98090_reg_playback_quick_setup_t q_playback_setup = {};
- q_playback_setup.dig2spk = 1;
+ q_playback_setup.dig2spk = 1;
i2cAddr.subAddress = MAX98090_REG_PLAYBACK_QUICK_SETUP;
i2c->Write(i2cAddr, (uint8_t *)&q_playback_setup, 1);
@@ 151,10 151,10 @@ CodecRetCode CodecMAX98090::Start(const CodecParams ¶m)
} break;
- case bsp::AudioDevice::OutputPath::LoudspeakerMono: {
+ case CodecParamsMAX98090::OutputPath::LoudspeakerMono: {
max98090_reg_playback_quick_setup_t q_playback_setup = {};
q_playback_setup.dig2spk = 1;
- i2cAddr.subAddress = MAX98090_REG_PLAYBACK_QUICK_SETUP;
+ i2cAddr.subAddress = MAX98090_REG_PLAYBACK_QUICK_SETUP;
i2c->Write(i2cAddr, (uint8_t *)&q_playback_setup, 1);
// Turn off right speaker path
@@ 172,18 172,18 @@ CodecRetCode CodecMAX98090::Start(const CodecParams ¶m)
}
// IN configuration
- if (params.inputPath != bsp::AudioDevice::InputPath::None) {
+ if (params.inputPath != CodecParamsMAX98090::InputPath::None) {
// Set input path
switch (params.inputPath) {
- case bsp::AudioDevice::InputPath::Headphones: {
+ case CodecParamsMAX98090::InputPath::Headphones: {
max98090_reg_input_to_record_quick_t q_input_setup = {};
q_input_setup.in34dan = 1;
i2cAddr.subAddress = MAX98090_REG_LINE_INPUT_TO_RECORD_QUICK;
i2c->Write(i2cAddr, (uint8_t *)&q_input_setup, 1);
} break;
- case bsp::AudioDevice::InputPath::Microphone: {
+ case CodecParamsMAX98090::InputPath::Microphone: {
max98090_reg_input_to_record_quick_t q_input_setup = {};
max98090_reg_digmic_enable_t digena = {};
max98090_reg_digmic_conf_t digconf = {};
@@ 334,8 334,8 @@ CodecRetCode CodecMAX98090::SetOutputVolume(const float vol)
}
switch (currentParams.outputPath) {
- case bsp::AudioDevice::OutputPath::Headphones:
- case bsp::AudioDevice::OutputPath::HeadphonesMono: {
+ case CodecParamsMAX98090::OutputPath::Headphones:
+ case CodecParamsMAX98090::OutputPath::HeadphonesMono: {
// Scale input volume(range 0 - 100) to MAX98090 range(decibels hardcoded as specific hex values)
constexpr float scale_factor = .31f * 10.f;
uint8_t volume = static_cast<float>(vol * scale_factor);
@@ 354,7 354,7 @@ CodecRetCode CodecMAX98090::SetOutputVolume(const float vol)
} break;
- case bsp::AudioDevice::OutputPath::Earspeaker: {
+ case CodecParamsMAX98090::OutputPath::Earspeaker: {
// Scale input volume(range 0 - 100) to MAX98090 range(decibels hardcoded as specific hex values)
constexpr float scale_factor = .31f * 10.f;
uint8_t volume = static_cast<float>(vol * scale_factor);
@@ 367,8 367,8 @@ CodecRetCode CodecMAX98090::SetOutputVolume(const float vol)
i2c->Write(i2cAddr, (uint8_t *)&vol, 1);
} break;
- case bsp::AudioDevice::OutputPath::Loudspeaker:
- case bsp::AudioDevice::OutputPath::LoudspeakerMono: {
+ case CodecParamsMAX98090::OutputPath::Loudspeaker:
+ case CodecParamsMAX98090::OutputPath::LoudspeakerMono: {
// Scale input volume(range 0 - 100) to MAX98090 range(decibels hardcoded as specific hex values)
constexpr float scale_factor = .39f * 10.f;
uint8_t volume = static_cast<float>(vol * scale_factor) + 0x18;
@@ 406,16 406,16 @@ CodecRetCode CodecMAX98090::SetInputGain(const float gain)
}
max98090_reg_lrec_dig_gain_t lgain = {};
- lgain.avl = static_cast<uint8_t>(CodecParamsMAX98090::RecordPathDigitalFineGain::Gain_p3dB); // fine gain
- lgain.avlg = gainToSet * 0.7; // coarse gain (0.7 used as scaling factor)
+ lgain.avl = static_cast<uint8_t>(CodecParamsMAX98090::RecordPathDigitalFineGain::Gain_p3dB); // fine gain
+ lgain.avlg = gainToSet * 0.7; // coarse gain (0.7 used as scaling factor)
i2cAddr.subAddress = MAX98090_REG_LREC_DIG_GAIN;
i2c->Write(i2cAddr, (uint8_t *)&lgain, 1);
// coarse gain - 18dB, fine gain - 0dB
max98090_reg_rrec_dig_gain_t rgain = {};
- rgain.avr = static_cast<uint8_t>(CodecParamsMAX98090::RecordPathDigitalFineGain::Gain_p3dB); // fine gain
- rgain.avrg = gainToSet * 0.7; // coarse gain (0.7 used as scaling factor)
+ rgain.avr = static_cast<uint8_t>(CodecParamsMAX98090::RecordPathDigitalFineGain::Gain_p3dB); // fine gain
+ rgain.avrg = gainToSet * 0.7; // coarse gain (0.7 used as scaling factor)
i2cAddr.subAddress = MAX98090_REG_RREC_DIG_GAIN;
i2c->Write(i2cAddr, (uint8_t *)&rgain, 1);
@@ 566,7 566,7 @@ CodecRetCode CodecMAX98090::Reset()
return CodecRetCode::Success;
}
-CodecRetCode CodecMAX98090::SetOutputPath(const bsp::AudioDevice::OutputPath path)
+CodecRetCode CodecMAX98090::SetOutputPath(const CodecParamsMAX98090::OutputPath path)
{
Reset();
currentParams.outputPath = path;
@@ 575,7 575,7 @@ CodecRetCode CodecMAX98090::SetOutputPath(const bsp::AudioDevice::OutputPath pat
return CodecRetCode::Success;
}
-CodecRetCode CodecMAX98090::SetInputPath(const bsp::AudioDevice::InputPath path)
+CodecRetCode CodecMAX98090::SetInputPath(const CodecParamsMAX98090::InputPath path)
{
Reset();
currentParams.inputPath = path;
@@ 591,17 591,17 @@ CodecRetCode CodecMAX98090::SetMute(const bool enable)
uint8_t regl, regr = 0;
switch (currentParams.outputPath) {
- case bsp::AudioDevice::OutputPath::Headphones: {
+ case CodecParamsMAX98090::OutputPath::Headphones: {
regl = MAX98090_REG_LHP_VOL_CTRL;
regr = MAX98090_REG_RHP_VOL_CTRL;
} break;
- case bsp::AudioDevice::OutputPath::Earspeaker: {
+ case CodecParamsMAX98090::OutputPath::Earspeaker: {
regl = MAX98090_REG_RECV_VOL_CTRL;
regr = 0;
} break;
- case bsp::AudioDevice::OutputPath::Loudspeaker: {
+ case CodecParamsMAX98090::OutputPath::Loudspeaker: {
regl = MAX98090_REG_LSPK_VOL_CTRL;
regr = MAX98090_REG_RSPK_VOL_CTRL;
} break;
M module-bsp/board/rt1051/bsp/audio/CodecMAX98090.hpp => module-bsp/board/rt1051/bsp/audio/CodecMAX98090.hpp +21 -5
@@ 6,7 6,6 @@
#include "Codec.hpp"
#include "drivers/i2c/DriverI2C.hpp"
-#include "bsp/audio/bsp_audio.hpp"
class CodecParamsMAX98090 : public CodecParams
{
@@ 67,6 66,23 @@ class CodecParamsMAX98090 : public CodecParams
Gain_n12dB
};
+ enum class InputPath
+ {
+ Headphones,
+ Microphone,
+ None
+ };
+
+ enum class OutputPath
+ {
+ Headphones,
+ HeadphonesMono,
+ Earspeaker,
+ Loudspeaker,
+ LoudspeakerMono,
+ None
+ };
+
static SampleRate ValToSampleRate(uint32_t rate)
{
switch (rate) {
@@ 113,8 129,8 @@ class CodecParamsMAX98090 : public CodecParams
bool muteEnable = false;
bool resetEnable = false;
bool micBiasEnable = false;
- bsp::AudioDevice::InputPath inputPath = bsp::AudioDevice::InputPath::None;
- bsp::AudioDevice::OutputPath outputPath = bsp::AudioDevice::OutputPath::None;
+ InputPath inputPath = InputPath::None;
+ OutputPath outputPath = OutputPath::None;
SampleRate sampleRate = SampleRate ::Rate44K1Hz;
};
@@ 144,8 160,8 @@ class CodecMAX98090 : public Codec
CodecRetCode SetOutputVolume(const float vol);
CodecRetCode SetInputGain(const float gain);
CodecRetCode SetMute(const bool enable);
- CodecRetCode SetInputPath(const bsp::AudioDevice::InputPath path);
- CodecRetCode SetOutputPath(const bsp::AudioDevice::OutputPath path);
+ CodecRetCode SetInputPath(const CodecParamsMAX98090::InputPath path);
+ CodecRetCode SetOutputPath(const CodecParamsMAX98090::OutputPath path);
CodecRetCode MicBias(const bool enable);
CodecRetCode SetupEarspeakerEqualizer();
CodecRetCode SetupLoudspeakerEqualizer();
A module-bsp/board/rt1051/common/audio.cpp => module-bsp/board/rt1051/common/audio.cpp +74 -0
@@ 0,0 1,74 @@
+// Copyright (c) 2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "audio.hpp"
+
+#include "BoardDefinitions.hpp"
+
+extern "C"
+{
+#include "board.h"
+#include "dma_config.h"
+}
+
+using namespace bsp;
+using namespace drivers;
+
+bsp::AudioConfig audioConfig;
+
+void bsp::audioInit()
+{
+ audioConfig.pllAudio =
+ DriverPLL::Create(static_cast<PLLInstances>(BoardDefinitions ::AUDIO_PLL), DriverPLLParams{});
+ audioConfig.dmamux =
+ DriverDMAMux::Create(static_cast<DMAMuxInstances>(BoardDefinitions ::AUDIOCODEC_DMAMUX), DriverDMAMuxParams{});
+ audioConfig.dma =
+ DriverDMA::Create(static_cast<DMAInstances>(BoardDefinitions ::AUDIOCODEC_DMA), DriverDMAParams{});
+
+ // Enable MCLK clock
+ IOMUXC_GPR->GPR1 |= BOARD_AUDIOCODEC_SAIx_MCLK_MASK;
+
+ audioConfig.txDMAHandle =
+ audioConfig.dma->CreateHandle(static_cast<uint32_t>(BoardDefinitions ::AUDIOCODEC_TX_DMA_CHANNEL));
+ audioConfig.rxDMAHandle =
+ audioConfig.dma->CreateHandle(static_cast<uint32_t>(BoardDefinitions ::AUDIOCODEC_RX_DMA_CHANNEL));
+ audioConfig.dmamux->Enable(static_cast<uint32_t>(BoardDefinitions ::AUDIOCODEC_TX_DMA_CHANNEL),
+ BSP_AUDIOCODEC_SAIx_DMA_TX_SOURCE);
+ audioConfig.dmamux->Enable(static_cast<uint32_t>(BoardDefinitions ::AUDIOCODEC_RX_DMA_CHANNEL),
+ BSP_AUDIOCODEC_SAIx_DMA_RX_SOURCE);
+
+ audioConfig.mclkSourceClockHz = GetPerphSourceClock(PerphClock_SAI2);
+
+ // Initialize SAI Tx module
+ SAI_TxGetDefaultConfig(&audioConfig.config);
+ audioConfig.config.masterSlave = kSAI_Slave;
+ SAI_TxInit(BOARD_AUDIOCODEC_SAIx, &audioConfig.config);
+
+ // Initialize SAI Rx module
+ SAI_RxGetDefaultConfig(&audioConfig.config);
+
+ audioConfig.config.masterSlave = kSAI_Slave;
+ SAI_RxInit(BOARD_AUDIOCODEC_SAIx, &audioConfig.config);
+}
+
+void bsp::audioDeinit()
+{
+ memset(&audioConfig.config, 0, sizeof(audioConfig.config));
+ SAI_Deinit(BOARD_AUDIOCODEC_SAIx);
+ if (audioConfig.dmamux) {
+ audioConfig.dmamux->Disable(static_cast<uint32_t>(BoardDefinitions ::AUDIOCODEC_TX_DMA_CHANNEL));
+ audioConfig.dmamux->Disable(static_cast<uint32_t>(BoardDefinitions ::AUDIOCODEC_RX_DMA_CHANNEL));
+ }
+
+ // force order of destruction
+ audioConfig.txDMAHandle.reset();
+ audioConfig.rxDMAHandle.reset();
+ audioConfig.dma.reset();
+ audioConfig.dmamux.reset();
+ audioConfig.pllAudio.reset();
+}
+
+AudioConfig *bsp::AudioConfig::get()
+{
+ return &audioConfig;
+}
A module-bsp/board/rt1051/common/audio.hpp => module-bsp/board/rt1051/common/audio.hpp +32 -0
@@ 0,0 1,32 @@
+// Copyright (c) 2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include "drivers/pll/DriverPLL.hpp"
+#include "drivers/dmamux/DriverDMAMux.hpp"
+#include "drivers/dma/DriverDMA.hpp"
+
+#include "fsl_sai_edma.h"
+
+#include <memory>
+
+namespace bsp
+{
+ void audioInit();
+ void audioDeinit();
+
+ struct AudioConfig
+ {
+ sai_config_t config;
+ std::uint32_t mclkSourceClockHz;
+
+ std::shared_ptr<drivers::DriverPLL> pllAudio;
+ std::shared_ptr<drivers::DriverDMAMux> dmamux;
+ std::shared_ptr<drivers::DriverDMA> dma;
+ std::unique_ptr<drivers::DriverDMAHandle> rxDMAHandle;
+ std::unique_ptr<drivers::DriverDMAHandle> txDMAHandle;
+
+ static AudioConfig *get();
+ };
+}; // namespace bsp
M module-bsp/board/rt1051/common/board.cpp => module-bsp/board/rt1051/common/board.cpp +2 -2
@@ 10,9 10,9 @@ extern "C"
#include "fsl_lpuart.h"
#endif
}
+#include "audio.hpp"
#include "chip.hpp"
#include "irq/irq_gpio.hpp"
-#include "audio/RT1051Audiocodec.hpp"
#include <cstdint>
@@ 193,7 193,7 @@ namespace bsp
DCDC_BootIntoDCM(DCDC);
// init audio
- RT1051Audiocodec::Init();
+ audioInit();
PrintSystemClocks();
clearAndPrintBootReason();
D module-bsp/bsp/audio/bsp_audio.cpp => module-bsp/bsp/audio/bsp_audio.cpp +0 -52
@@ 1,52 0,0 @@
-#include "bsp_audio.hpp"
-
-#if defined(TARGET_RT1051)
-
-#include "board/rt1051/bsp/audio/RT1051Audiocodec.hpp"
-#include "board/rt1051/bsp/audio/RT1051CellularAudio.hpp"
-
-#endif
-
-#include <Audio/Stream.hpp>
-
-#include <cassert>
-
-namespace bsp
-{
-
- std::optional<std::unique_ptr<AudioDevice>> AudioDevice::Create(bsp::AudioDevice::Type type)
- {
- std::unique_ptr<AudioDevice> inst;
-
- switch (type) {
-
- case Type ::Audiocodec: {
-#if defined(TARGET_RT1051)
- inst = std::make_unique<bsp::RT1051Audiocodec>();
-#else
- inst = nullptr;
-#endif
-
- } break;
-
- case Type ::Bluetooth: {
- LOG_FATAL("Bluetooth audio is not yet supported");
- inst = nullptr;
- } break;
-
- case Type::Cellular: {
-#if defined(TARGET_RT1051)
- inst = std::make_unique<bsp::RT1051CellularAudio>();
-#else
- inst = nullptr;
-#endif
- } break;
- }
-
- if (inst->isInitialized) {
- return inst;
- }
-
- return {};
- }
-} // namespace bsp
M module-bsp/targets/Target_RT1051.cmake => module-bsp/targets/Target_RT1051.cmake +4 -3
@@ 1,3 1,6 @@
+# Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
include(board/rt1051/bsp/usb/usb.cmake)
set(BOARD_SOURCES ${BOARD_SOURCES}
@@ 31,6 34,7 @@ set(BOARD_SOURCES ${BOARD_SOURCES}
"${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/common/fsl_drivers/fsl_wdog.c"
"${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/common/fsl_drivers/fsl_pwm.c"
"${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/common/irq/irq_gpio.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/common/audio.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/common/board.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/common/chip.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/common/clock_config.cpp"
@@ 57,9 61,6 @@ set(BOARD_SOURCES ${BOARD_SOURCES}
"${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/bluetooth/BlueKitchen.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/bsp/rtc/rtc.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/bsp/battery-charger/battery_charger.cpp"
- "${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/bsp/audio/RT1051Audiocodec.cpp"
- "${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/bsp/audio/RT1051CellularAudio.cpp"
- "${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/bsp/audio/SAIAudioDevice.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/bsp/audio/CodecMAX98090.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/bsp/audio/qfilter.c"
"${USB_SRC}"
M module-db/Common/Query.cpp => module-db/Common/Query.cpp +20 -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 "Query.hpp"
@@ 22,7 22,12 @@ bool QueryCallback::handleQueryResponse(QueryResult *response)
}
EndpointListener::EndpointListener(EndpointQueryCallbackFunction &&_callback, parserFSM::Context &_context)
- : callback{std::move(_callback)}, context{_context}
+ : callback{std::move(_callback)}, context(_context)
+{}
+
+EndpointListenerWithPages::EndpointListenerWithPages(EndpointQueryCallbackFunctionWithPages &&_callback,
+ const parserFSM::PagedContext &_context)
+ : callback{std::move(_callback)}, context(_context)
{}
bool EndpointListener::handleQueryResponse(db::QueryResult *response)
@@ 38,6 43,19 @@ bool EndpointListener::handleQueryResponse(db::QueryResult *response)
return false;
}
+bool EndpointListenerWithPages::handleQueryResponse(db::QueryResult *response)
+{
+ if (callback) {
+ LOG_DEBUG("Executing callback...");
+ const auto ret = callback(response, context);
+ LOG_DEBUG("Callback finished");
+ return ret;
+ }
+
+ LOG_ERROR("callback is nullptr!");
+ return false;
+}
+
Query::Query(Type type) : type(type)
{}
M module-db/Common/Query.hpp => module-db/Common/Query.hpp +16 -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
#pragma once
@@ 14,7 14,7 @@ namespace db
class QueryResult; // Forward declaration
using QueryCallbackFunction = std::function<bool(db::QueryResult *)>;
using EndpointQueryCallbackFunction = std::function<bool(db::QueryResult *, parserFSM::Context &)>;
-
+ using EndpointQueryCallbackFunctionWithPages = std::function<bool(db::QueryResult *, parserFSM::PagedContext &)>;
class QueryListener
{
public:
@@ 49,6 49,20 @@ namespace db
parserFSM::Context context;
};
+ class EndpointListenerWithPages : public EndpointListener
+ {
+ public:
+ EndpointListenerWithPages() = default;
+ EndpointListenerWithPages(EndpointQueryCallbackFunctionWithPages &&_callback,
+ const parserFSM::PagedContext &_context);
+
+ bool handleQueryResponse(db::QueryResult *result) override;
+
+ private:
+ EndpointQueryCallbackFunctionWithPages callback;
+ parserFSM::PagedContext context;
+ };
+
/// virtual query input interface
class Query
{
M module-db/Interface/ContactRecord.cpp => module-db/Interface/ContactRecord.cpp +32 -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 "ContactRecord.hpp"
@@ 135,6 135,9 @@ auto ContactRecordInterface::runQuery(std::shared_ptr<db::Query> query) -> std::
if (typeid(*query) == typeid(db::query::ContactGet)) {
return getQuery(query);
}
+ else if (typeid(*query) == typeid(db::query::ContactGetWithTotalCount)) {
+ return getQueryWithTotalCount(query);
+ }
else if (typeid(*query) == typeid(db::query::ContactGetLetterMap)) {
return getLetterMapQuery(query);
}
@@ 162,7 165,7 @@ auto ContactRecordInterface::runQuery(std::shared_ptr<db::Query> query) -> std::
}
}
-auto ContactRecordInterface::getQuery(std::shared_ptr<db::Query> query) -> std::unique_ptr<db::QueryResult>
+auto ContactRecordInterface::getQueryRecords(std::shared_ptr<db::Query> query) -> std::vector<ContactRecord>
{
auto textFilter = dynamic_cast<const db::query::TextFilter *>(query.get());
assert(query != nullptr);
@@ 203,11 206,31 @@ auto ContactRecordInterface::getQuery(std::shared_ptr<db::Query> query) -> std::
for (uint32_t idx = 0; idx < static_cast<uint32_t>(ids.size()); idx++) {
result[idx].contactPosOnList = offset + idx;
}
- auto response = std::make_unique<db::query::ContactGetResult>(result);
+ return result;
+}
+
+auto ContactRecordInterface::getQuery(std::shared_ptr<db::Query> query) -> std::unique_ptr<db::QueryResult>
+{
+ auto response = std::make_unique<db::query::ContactGetResult>(getQueryRecords(query));
response->setRequestQuery(query);
return response;
}
+auto ContactRecordInterface::getQueryWithTotalCount(std::shared_ptr<db::Query> query)
+ -> std::unique_ptr<db::QueryResult>
+{
+ if (auto queryContacts = dynamic_cast<db::query::ContactGet *>(query.get())) {
+ auto querySize = std::make_shared<db::query::ContactGetSize>(queryContacts->getFilterData(),
+ queryContacts->getGroupFilterData(),
+ queryContacts->getContactDisplayMode());
+ auto response = std::make_unique<db::query::ContactGetResultWithTotalCount>(getQueryRecords(query),
+ getContactsSize(querySize));
+ response->setRequestQuery(query);
+ return response;
+ }
+ return nullptr;
+}
+
auto ContactRecordInterface::getLetterMapQuery(std::shared_ptr<db::Query> query) -> std::unique_ptr<db::QueryResult>
{
ContactsMapData result = contactDB->contacts.GetPosOfFirstLetters();
@@ 233,7 256,7 @@ auto ContactRecordInterface::getByIDQuery(std::shared_ptr<db::Query> query) -> s
return response;
}
-auto ContactRecordInterface::getSizeQuery(std::shared_ptr<db::Query> query) -> std::unique_ptr<db::QueryResult>
+auto ContactRecordInterface::getContactsSize(std::shared_ptr<db::Query> query) -> std::size_t
{
auto textFilter = dynamic_cast<const db::query::TextFilter *>(query.get());
assert(query != nullptr);
@@ 280,7 303,12 @@ auto ContactRecordInterface::getSizeQuery(std::shared_ptr<db::Query> query) -> s
else {
count = contactDB->name.GetCountByName(countQuery->getFilterData());
}
+ return count;
+}
+auto ContactRecordInterface::getSizeQuery(std::shared_ptr<db::Query> query) -> std::unique_ptr<db::QueryResult>
+{
+ auto count = getContactsSize(query);
debug_db_data("Contact count query result: %lu", static_cast<unsigned long>(count));
auto response = std::make_unique<db::query::RecordsSizeQueryResult>(count);
M module-db/Interface/ContactRecord.hpp => module-db/Interface/ContactRecord.hpp +4 -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
@@ 236,10 236,13 @@ class ContactRecordInterface : public RecordInterface<ContactRecord, ContactReco
const std::uint32_t favouritesGroupId;
auto getQuery(std::shared_ptr<db::Query> query) -> std::unique_ptr<db::QueryResult>;
+ auto getQueryRecords(std::shared_ptr<db::Query> query) -> std::vector<ContactRecord>;
+ auto getQueryWithTotalCount(std::shared_ptr<db::Query> query) -> std::unique_ptr<db::QueryResult>;
auto getForListQuery(std::shared_ptr<db::Query> query) -> std::unique_ptr<db::QueryResult>;
auto getLetterMapQuery(std::shared_ptr<db::Query> query) -> std::unique_ptr<db::QueryResult>;
auto getByIDQuery(std::shared_ptr<db::Query> query) -> std::unique_ptr<db::QueryResult>;
+ auto getContactsSize(std::shared_ptr<db::Query> query) -> std::size_t;
auto getSizeQuery(std::shared_ptr<db::Query> query) -> std::unique_ptr<db::QueryResult>;
auto addQuery(std::shared_ptr<db::Query> query) -> std::unique_ptr<db::QueryResult>;
auto updateQuery(std::shared_ptr<db::Query> query) -> std::unique_ptr<db::QueryResult>;
M module-db/Interface/ThreadRecord.cpp => module-db/Interface/ThreadRecord.cpp +3 -1
@@ 226,7 226,9 @@ std::unique_ptr<db::QueryResult> ThreadRecordInterface::markAsReadQuery(const st
ret = Update(record);
}
- return std::make_unique<db::query::MarkAsReadResult>(ret);
+ auto response = std::make_unique<db::query::MarkAsReadResult>(ret);
+ response->setRequestQuery(query);
+ return response;
}
std::unique_ptr<db::QueryResult> ThreadRecordInterface::threadsGetQuery(const std::shared_ptr<db::Query> &query)
M module-db/queries/Filter.hpp => module-db/queries/Filter.hpp +3 -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
#pragma once
@@ 95,7 95,7 @@ namespace db::query
*
* @param groupText group filter text
*/
- ContactGroupFilter(const std::uint32_t &groupId) : filterData(std::move(groupId))
+ ContactGroupFilter(std::uint32_t groupId) : filterData(groupId)
{}
[[nodiscard]] const std::uint32_t &getGroupFilterData() const noexcept
@@ 121,7 121,7 @@ namespace db::query
*
* @param mode contact display mode
*/
- ContactDisplayMode(const std::uint32_t &mode) : displayMode(std::move(mode))
+ ContactDisplayMode(std::uint32_t mode) : displayMode(mode)
{}
[[nodiscard]] const std::uint32_t &getContactDisplayMode() const noexcept
M module-db/queries/RecordQuery.cpp => module-db/queries/RecordQuery.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 "RecordQuery.hpp"
@@ 13,7 13,7 @@ using namespace db::query;
RecordQuery::RecordQuery() noexcept : Query(Query::Type::Read)
{}
-RecordQuery::RecordQuery(std::size_t offset, std::size_t limit) noexcept
+RecordQuery::RecordQuery(std::size_t limit, std::size_t offset) noexcept
: Query(Query::Type::Read), limit(limit), offset(offset)
{}
M module-db/queries/phonebook/QueryContactGet.cpp => module-db/queries/phonebook/QueryContactGet.cpp +31 -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 "QueryContactGet.hpp"
@@ 14,14 14,32 @@ ContactGet::ContactGet(const std::string &filter, const std::uint32_t &groupFilt
ContactGet::ContactGet(std::size_t limit,
std::size_t offset,
const std::string &filter,
- const std::uint32_t &groupFilter,
- const std::uint32_t &displayMode)
+ std::uint32_t groupFilter,
+ std::uint32_t displayMode)
: RecordQuery(limit, offset), TextFilter(filter), ContactGroupFilter(groupFilter), ContactDisplayMode(displayMode)
{}
+ContactGetWithTotalCount::ContactGetWithTotalCount(std::size_t limit,
+ std::size_t offset,
+ const std::string &filter,
+ std::uint32_t groupFilter,
+ std::uint32_t displayMode)
+ : ContactGet(limit, offset, filter, groupFilter, displayMode)
+{}
+
ContactGetResult::ContactGetResult(const std::vector<ContactRecord> &records) : RecordQueryResult(records)
{}
+ContactGetResultWithTotalCount::ContactGetResultWithTotalCount(const std::vector<ContactRecord> &records,
+ std::size_t allLength)
+ : ContactGetResult(records), allLength(allLength)
+{}
+
+auto ContactGetResultWithTotalCount::getAllLength() const -> std::size_t
+{
+ return allLength;
+}
+
ContactGetSize::ContactGetSize(const std::string &filter,
const std::uint32_t &groupFilter,
const std::uint32_t &displayMode)
@@ 50,11 68,21 @@ ContactGetLetterMapResult ::ContactGetLetterMapResult(ContactsMapData &LetterMap
return "ContactGet";
}
+[[nodiscard]] auto ContactGetWithTotalCount::debugInfo() const -> std::string
+{
+ return "ContactGetWithTotalCount";
+}
+
[[nodiscard]] auto ContactGetResult::debugInfo() const -> std::string
{
return "ContactGetResult";
}
+[[nodiscard]] auto ContactGetResultWithTotalCount::debugInfo() const -> std::string
+{
+ return "ContactGetResultWithTotalCount";
+}
+
[[nodiscard]] auto ContactGetSize::debugInfo() const -> std::string
{
return "ContactGetSize";
M module-db/queries/phonebook/QueryContactGet.hpp => module-db/queries/phonebook/QueryContactGet.hpp +26 -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
#pragma once
@@ 37,9 37,9 @@ namespace db::query
*/
ContactGet(std::size_t limit,
std::size_t offset,
- const std::string &filter = "",
- const std::uint32_t &groupFilter = 0,
- const std::uint32_t &displayMode = 0);
+ const std::string &filter = "",
+ std::uint32_t groupFilter = 0,
+ std::uint32_t displayMode = 0);
/**
* @brief debug info
@@ 72,6 72,17 @@ namespace db::query
[[nodiscard]] auto debugInfo() const -> std::string override;
};
+ class ContactGetResultWithTotalCount : public ContactGetResult
+ {
+ public:
+ ContactGetResultWithTotalCount(const std::vector<ContactRecord> &records, std::size_t allLength);
+ [[nodiscard]] auto debugInfo() const -> std::string override;
+ auto getAllLength() const -> std::size_t;
+
+ private:
+ std::size_t allLength;
+ };
+
/**
* @brief A query to get a number of contacts filtered with a text
*
@@ 99,6 110,17 @@ namespace db::query
[[nodiscard]] auto debugInfo() const -> std::string override;
};
+ class ContactGetWithTotalCount : public ContactGet
+ {
+ public:
+ ContactGetWithTotalCount(std::size_t limit,
+ std::size_t offset,
+ const std::string &filter = "",
+ std::uint32_t groupFilter = 0,
+ std::uint32_t displayMode = 0);
+ [[nodiscard]] auto debugInfo() const -> std::string override;
+ };
+
class ContactGetLetterMap : public RecordQuery,
public TextFilter,
public ContactGroupFilter,
M module-gui/gui/widgets/BoxLayout.cpp => module-gui/gui/widgets/BoxLayout.cpp +1 -0
@@ 551,6 551,7 @@ namespace gui
{
type = ItemType::HBOX;
}
+
HBox::HBox(Item *parent, const uint32_t &x, const uint32_t &y, const uint32_t &w, const uint32_t &h)
: BoxLayout(parent, x, y, w, h)
{
M module-gui/gui/widgets/CMakeLists.txt => module-gui/gui/widgets/CMakeLists.txt +3 -1
@@ 22,6 22,9 @@ target_sources( ${PROJECT_NAME}
"${CMAKE_CURRENT_LIST_DIR}/BoxLayoutSizeStore.cpp"
"${CMAKE_CURRENT_LIST_DIR}/TopBar.cpp"
"${CMAKE_CURRENT_LIST_DIR}/TopBar/SIM.cpp"
+ "${CMAKE_CURRENT_LIST_DIR}/TopBar/BatteryWidgetBase.cpp"
+ "${CMAKE_CURRENT_LIST_DIR}/TopBar/BatteryWidgetBar.cpp"
+ "${CMAKE_CURRENT_LIST_DIR}/TopBar/BatteryWidgetText.cpp"
"${CMAKE_CURRENT_LIST_DIR}/Text.cpp"
"${CMAKE_CURRENT_LIST_DIR}/TextBlock.cpp"
"${CMAKE_CURRENT_LIST_DIR}/TextDocument.cpp"
@@ 71,4 74,3 @@ target_sources( ${PROJECT_NAME}
"${CMAKE_CURRENT_LIST_DIR}/visitor/ItemTree.hpp"
"${CMAKE_CURRENT_LIST_DIR}/visitor/DepthFirstItemTree.hpp"
)
-
M module-gui/gui/widgets/ListItem.hpp => module-gui/gui/widgets/ListItem.hpp +8 -0
@@ 17,4 17,12 @@ namespace gui
ListItem();
};
+ template <class T> class ListItemWithCallbacks : public ListItem
+ {
+ public:
+ std::function<bool()> onEmptyCallback = nullptr;
+ std::function<bool()> onContentChangedCallback = nullptr;
+ std::function<void(std::shared_ptr<T> contact)> onSaveCallback = nullptr;
+ std::function<void(std::shared_ptr<T> contact)> onLoadCallback = nullptr;
+ };
} /* namespace gui */
M module-gui/gui/widgets/TextBlockCursor.cpp => module-gui/gui/widgets/TextBlockCursor.cpp +2 -3
@@ 267,7 267,7 @@ namespace gui
return false;
}
- if (nextBlock != blocksEnd() && nextBlock->isEmpty() && nextBlock != (--blocksEnd())) {
+ if (nextBlock != blocksEnd() && nextBlock->isEmpty()) {
debug_cursor("Next empty block removed");
document->removeBlock(nextBlock);
}
@@ 280,8 280,7 @@ namespace gui
block->removeChar(pos);
- if (block->isEmpty() && block != blocksEnd() &&
- !(prevBlock->getEnd() == TextBlock::End::Newline && nextBlock->isEmpty())) {
+ if (block->isEmpty() && block == blocksBegin()) {
debug_cursor("Current empty block removed");
document->removeBlock(block);
}
M module-gui/gui/widgets/TopBar.cpp => module-gui/gui/widgets/TopBar.cpp +14 -96
@@ 8,11 8,15 @@
#include "TopBar.hpp"
#include <time/time_conversion.hpp>
#include "Style.hpp"
-
+#include "TopBar/BatteryWidgetBar.hpp"
+#include "TopBar/BatteryWidgetText.hpp"
#include "common_data/EventStore.hpp"
namespace gui::top_bar
{
+ constexpr auto batteryWidgetAsText = false;
+ using BatteryWidgetType = std::conditional<batteryWidgetAsText, BatteryWidgetText, BatteryWidgetBar>::type;
+
namespace networkTechnology
{
constexpr uint32_t x = 80;
@@ 24,8 28,8 @@ namespace gui::top_bar
static constexpr uint32_t signalOffset = 35;
static constexpr uint32_t batteryOffset = 413;
- TopBar::TimeMode TopBar::timeMode = TimeMode::TIME_24H;
- uint32_t TopBar::time = 0;
+ TopBar::TimeMode TopBar::timeMode = TimeMode::TIME_24H;
+ uint32_t TopBar::time = 0;
void Configuration::enable(Indicator indicator)
{
@@ 74,22 78,6 @@ namespace gui::top_bar
};
}
- void TopBar::batteryShowBars(uint32_t val)
- {
- if (val > batteryBars.size()) {
- LOG_ERROR("Trying to set battery level out of scope");
- val = batteryBars.size();
- }
- for (unsigned int i = 0; i < batteryBars.size(); ++i) {
- if (configuration.isEnabled(Indicator::Battery)) {
- batteryBars[i]->setVisible(i == val);
- }
- else {
- batteryBars[i]->setVisible(false);
- }
- }
- }
-
void TopBar::prepareWidget()
{
signal[0] = new gui::Image(this, signalOffset, 17, 0, 0, "signal0");
@@ 100,24 88,7 @@ namespace gui::top_bar
signal[5] = new gui::Image(this, signalOffset, 17, 0, 0, "signal5");
updateSignalStrength();
- // icons for battery
- batteryBars = {
- new gui::Image(this, batteryOffset, 15, 0, 0, "battery_low_W_M"),
- new gui::Image(this, batteryOffset, 15, 0, 0, "battery1_W_M"),
- new gui::Image(this, batteryOffset, 15, 0, 0, "battery2_W_M"),
- new gui::Image(this, batteryOffset, 15, 0, 0, "battery3_W_M"),
- new gui::Image(this, batteryOffset, 15, 0, 0, "battery4_W_M"),
- new gui::Image(this, batteryOffset, 15, 0, 0, "battery5_W_M"),
- };
- batteryShowBars(0);
-
- batteryChargings[Store::Battery::State::Charging] =
- new gui::Image(this, batteryOffset, 15, 0, 0, "battery_charging_W_M");
- batteryChargings[Store::Battery::State::PluggedNotCharging] =
- new gui::Image(this, batteryOffset, 15, 0, 0, "battery_charging_ready_W_M");
- for (auto &el : batteryChargings) {
- el.second->setVisible(false);
- }
+ batteryWidget = new BatteryWidgetType(this, batteryOffset, 15, 60, 24);
const auto design_sim_offset = 376; // this offset is not final, but it is pixel Purefect
sim = new SIM(this, design_sim_offset, 12);
@@ 181,7 152,7 @@ namespace gui::top_bar
}
break;
case Indicator::Battery:
- showBattery(enabled);
+ batteryWidget->show(Store::Battery::get(), enabled);
break;
case Indicator::SimCard:
showSim(enabled);
@@ 192,65 163,12 @@ namespace gui::top_bar
}
}
- uint32_t TopBar::calculateBatteryBars(uint32_t percentage)
- {
- uint32_t level = 0;
- if (percentage <= 5) // level critical
- level = 0;
- else if (percentage <= 27)
- level = 1;
- else if (percentage <= 50)
- level = 2;
- else if (percentage <= 73)
- level = 3;
- else if (percentage <= 95)
- level = 4;
- else
- level = 5;
-
- if (level >= batteryBarsCount) {
- LOG_ERROR("Battery level calculations are done wrong!");
- return batteryBarsCount - 1;
- }
- return level;
- }
-
- bool TopBar::updateBattery(uint32_t percent)
+ bool TopBar::updateBattery()
{
- showBattery(configuration.isEnabled(Indicator::Battery));
+ batteryWidget->show(Store::Battery::get(), configuration.isEnabled(Indicator::Battery));
return true;
}
- bool TopBar::updateBattery(bool plugged)
- {
- showBattery(configuration.isEnabled(Indicator::Battery));
- return true;
- }
-
- void TopBar::showBattery(bool shown)
- {
- // hide battery bars icons
- for (const auto &bars : batteryBars) {
- bars->setVisible(false);
- }
- // hide battery charging icons
- for (const auto &charging : batteryChargings) {
- charging.second->setVisible(false);
- }
-
- if (shown) {
- switch (Store::Battery::get().state) {
- case Store::Battery::State::Discharging:
- batteryShowBars(calculateBatteryBars(Store::Battery::get().level));
- break;
- case Store::Battery::State::Charging:
- case Store::Battery::State::PluggedNotCharging:
- batteryChargings[Store::Battery::get().state]->setVisible(true);
- break;
- }
- }
- }
-
void TopBar::showSim(bool enabled)
{
if (!enabled) {
@@ 315,8 233,8 @@ namespace gui::top_bar
void TopBar::setTime(uint32_t value, bool mode24H)
{
setTime(utils::time::Time());
- timeMode = (mode24H ? TimeMode::TIME_24H : TimeMode::TIME_12H);
- time = value;
+ timeMode = (mode24H ? TimeMode::TIME_24H : TimeMode::TIME_12H);
+ time = value;
}
UTF8 TopBar::getTimeString()
@@ 342,4 260,4 @@ namespace gui::top_bar
{
visitor.visit(*this);
}
-} /* namespace gui */
+} // namespace gui::top_bar
M module-gui/gui/widgets/TopBar.hpp => module-gui/gui/widgets/TopBar.hpp +4 -8
@@ 7,6 7,7 @@
#include "Label.hpp"
#include "Rect.hpp"
#include "TopBar/SIM.hpp"
+#include "TopBar/BatteryWidgetBase.hpp"
#include <common_data/EventStore.hpp>
#include <vector>
@@ 82,18 83,14 @@ namespace gui::top_bar
std::map<const Store::Battery::State, Image *> batteryChargings = {
{Store::Battery::State::Charging, nullptr}, {Store::Battery::State::PluggedNotCharging, nullptr}};
gui::SIM *sim = nullptr;
+ gui::BatteryWidgetBase *batteryWidget = nullptr;
Configuration configuration;
static TimeMode timeMode;
void prepareWidget();
- /// show bars in number - 0 bars, 1 bar, 2 bars...
- void batteryShowBars(uint32_t val);
- void showBattery(bool shown);
void showSim(bool enabled);
- static uint32_t calculateBatteryBars(uint32_t percentage);
-
/**
* Sets the status of the top bar indicator.
* @param indicator Indicator
@@ 111,12 108,11 @@ namespace gui::top_bar
[[nodiscard]] auto getConfiguration() const noexcept -> const Configuration &;
/**
- * @brief Sets charge level of the battery based on percent value. This will cause appropriate image to be
+ * @brief Sets charge level of the battery. This will cause appropriate image to be
* displayed.
* @return if display should be refreshed or not
*/
- bool updateBattery(uint32_t percent);
- bool updateBattery(bool plugged);
+ bool updateBattery();
/**
* @brief updates signal strength. This will cause appropriate image to be displayed.
A module-gui/gui/widgets/TopBar/BatteryWidgetBar.cpp => module-gui/gui/widgets/TopBar/BatteryWidgetBar.cpp +67 -0
@@ 0,0 1,67 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "BatteryWidgetBar.hpp"
+#include "Style.hpp"
+#include "Utils.hpp"
+#include "visitor/GuiVisitor.hpp"
+
+namespace gui
+{
+ namespace
+ {
+ constexpr auto batteryLow = "battery_low_W_M";
+ constexpr auto batteryCharging = "battery_charging_W_M";
+ constexpr auto batteryChargingReady = "battery_charging_ready_W_M";
+ constexpr auto battery1 = "battery1_W_M";
+ constexpr auto battery2 = "battery2_W_M";
+ constexpr auto battery3 = "battery3_W_M";
+ constexpr auto battery4 = "battery4_W_M";
+ constexpr auto battery5 = "battery5_W_M";
+
+ constexpr auto level1Threshold = 5;
+ constexpr auto level2Threshold = 27;
+ constexpr auto level3Threshold = 50;
+ constexpr auto level4Threshold = 73;
+ constexpr auto level5Threshold = 95;
+ } // namespace
+
+ BatteryWidgetBar::BatteryWidgetBar(Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h)
+ : BatteryWidgetBase(parent, x, y, w, h)
+ {
+ img = new Image(this, battery1);
+ }
+
+ void BatteryWidgetBar::showBatteryLevel(std::uint32_t percentage)
+ {
+ if (percentage <= level1Threshold) {
+ img->set(batteryLow);
+ }
+ else if (percentage <= level2Threshold) {
+ img->set(battery1);
+ }
+ else if (percentage <= level3Threshold) {
+ img->set(battery2);
+ }
+ else if (percentage <= level4Threshold) {
+ img->set(battery3);
+ }
+ else if (percentage <= level5Threshold) {
+ img->set(battery4);
+ }
+ else {
+ img->set(battery5);
+ }
+ }
+
+ void BatteryWidgetBar::showBatteryCharging()
+ {
+ img->set(batteryCharging);
+ }
+
+ void BatteryWidgetBar::showBatteryPluggedNotCharging()
+ {
+ img->set(batteryChargingReady);
+ }
+
+} // namespace gui
A module-gui/gui/widgets/TopBar/BatteryWidgetBar.hpp => module-gui/gui/widgets/TopBar/BatteryWidgetBar.hpp +23 -0
@@ 0,0 1,23 @@
+// 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 "BatteryWidgetBase.hpp"
+#include "Image.hpp"
+
+namespace gui
+{
+ class BatteryWidgetBar : public BatteryWidgetBase
+ {
+ public:
+ BatteryWidgetBar(Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h);
+
+ private:
+ void showBatteryLevel(std::uint32_t percentage) override;
+ void showBatteryPluggedNotCharging() override;
+ void showBatteryCharging() override;
+
+ Image *img = nullptr;
+ };
+} // namespace gui
A module-gui/gui/widgets/TopBar/BatteryWidgetBase.cpp => module-gui/gui/widgets/TopBar/BatteryWidgetBase.cpp +35 -0
@@ 0,0 1,35 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "BatteryWidgetBase.hpp"
+#include "BoxLayout.hpp"
+
+namespace gui
+{
+ BatteryWidgetBase::BatteryWidgetBase(Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h)
+ : HBox(parent, x, y, w, h)
+ {
+ setBorderColor(gui::ColorNoColor);
+ }
+
+ void BatteryWidgetBase::show(const Store::Battery batteryContext, bool shown)
+ {
+ if (shown) {
+ setVisible(true);
+ switch (batteryContext.state) {
+ case Store::Battery::State::Discharging:
+ showBatteryLevel(batteryContext.level);
+ break;
+ case Store::Battery::State::Charging:
+ showBatteryCharging();
+ break;
+ case Store::Battery::State::PluggedNotCharging:
+ showBatteryPluggedNotCharging();
+ break;
+ }
+ }
+ else {
+ setVisible(false);
+ }
+ }
+} // namespace gui
A module-gui/gui/widgets/TopBar/BatteryWidgetBase.hpp => module-gui/gui/widgets/TopBar/BatteryWidgetBase.hpp +23 -0
@@ 0,0 1,23 @@
+// 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 "BoxLayout.hpp"
+#include <common_data/EventStore.hpp>
+
+namespace gui
+{
+ class HBox;
+
+ class BatteryWidgetBase : public HBox
+ {
+ virtual void showBatteryLevel(std::uint32_t percentage) = 0;
+ virtual void showBatteryPluggedNotCharging() = 0;
+ virtual void showBatteryCharging() = 0;
+
+ public:
+ BatteryWidgetBase(Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h);
+ void show(const Store::Battery batteryContext, bool shown);
+ };
+} // namespace gui
A module-gui/gui/widgets/TopBar/BatteryWidgetText.cpp => module-gui/gui/widgets/TopBar/BatteryWidgetText.cpp +37 -0
@@ 0,0 1,37 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "BatteryWidgetText.hpp"
+#include "Label.hpp"
+#include <Utils.hpp>
+#include <Style.hpp>
+
+namespace gui
+{
+ BatteryWidgetText::BatteryWidgetText(Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h)
+ : BatteryWidgetBase(parent, x, y, w, h)
+ {
+ label = new Label(this, 0, 0, 0, 0);
+ label->setFilled(false);
+ label->setBorderColor(gui::ColorNoColor);
+ label->setFont(style::header::font::modes);
+ label->setAlignment(gui::Alignment(gui::Alignment::Horizontal::Left, gui::Alignment::Vertical::Center));
+ label->setMaximumSize(this->getWidth(), this->getHeight());
+ }
+
+ void BatteryWidgetText::showBatteryLevel(std::uint32_t percentage)
+ {
+ label->setText(utils::to_string(percentage) + " %");
+ }
+
+ void BatteryWidgetText::showBatteryCharging()
+ {
+ label->setText(utils::localize.get("topbar_battery_charging"));
+ }
+
+ void BatteryWidgetText::showBatteryPluggedNotCharging()
+ {
+ label->setText(utils::localize.get("topbar_battery_plugged"));
+ }
+
+} // namespace gui
A module-gui/gui/widgets/TopBar/BatteryWidgetText.hpp => module-gui/gui/widgets/TopBar/BatteryWidgetText.hpp +22 -0
@@ 0,0 1,22 @@
+// 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 "BatteryWidgetBase.hpp"
+
+namespace gui
+{
+ class Label;
+ class BatteryWidgetText : public BatteryWidgetBase
+ {
+ public:
+ BatteryWidgetText(Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h);
+
+ private:
+ void showBatteryLevel(std::uint32_t percentage) override;
+ void showBatteryPluggedNotCharging() override;
+ void showBatteryCharging() override;
+ Label *label = nullptr;
+ };
+} // namespace gui
M module-gui/test/test-catch-text/test-gui-Text.cpp => module-gui/test/test-catch-text/test-gui-Text.cpp +103 -0
@@ 82,6 82,13 @@ namespace gui
return mode;
}
+ auto removeNCharacters(unsigned int n)
+ {
+ for (unsigned int i = 0; i < n; i++) {
+ removeChar();
+ }
+ }
+
auto moveCursor(NavigationDirection direction, unsigned int n)
{
cursor->moveCursor(direction, n);
@@ 1100,6 1107,102 @@ TEST_CASE("Text addition bounds - multiple limits tests")
}
}
+TEST_CASE("Text newline navigation and deletion tests")
+{
+ std::string testStringBlock1 = "Test String 1";
+ std::string testStringBlock2 = "Test String 2";
+ std::string emptyParagraph = "<p></p>";
+
+ SECTION("Empty new block at start and delete from text end")
+ {
+ mockup::fontManager();
+ using namespace gui;
+ auto text = std::make_unique<gui::TestText>();
+ text->setMaximumSize(600, 200);
+
+ text->addRichText("<text>" + emptyParagraph + testStringBlock1 + "</text>");
+
+ REQUIRE(text->linesSize() == 2);
+ REQUIRE((*text->lineGet(0)).getText(0) == "\n");
+ REQUIRE((*text->lineGet(1)).getText(0) == testStringBlock1);
+
+ text->removeNCharacters(text->getText().length());
+
+ REQUIRE(text->linesSize() == 0);
+ REQUIRE(text->linesGet().empty());
+ }
+
+ SECTION("Empty new block at start and delete from text center")
+ {
+ mockup::fontManager();
+ using namespace gui;
+ auto text = std::make_unique<gui::TestText>();
+ text->setMaximumSize(600, 200);
+
+ text->addRichText("<text>" + emptyParagraph + testStringBlock1 + emptyParagraph + testStringBlock2 + "</text>");
+
+ REQUIRE(text->linesSize() == 3);
+ REQUIRE((*text->lineGet(0)).getText(0) == "\n");
+ REQUIRE((*text->lineGet(1)).getText(0) == testStringBlock1 + "\n");
+ REQUIRE((*text->lineGet(2)).getText(0) == testStringBlock2);
+
+ text->moveCursor(gui::NavigationDirection::LEFT, testStringBlock2.length());
+ text->removeNCharacters(1);
+
+ REQUIRE(text->linesSize() == 2);
+ REQUIRE((*text->lineGet(0)).getText(0) == "\n");
+ REQUIRE((*text->lineGet(1)).getText(0) == testStringBlock1 + testStringBlock2);
+
+ text->removeNCharacters(testStringBlock1.length());
+
+ REQUIRE(text->linesSize() == 2);
+ REQUIRE((*text->lineGet(0)).getText(0) == "\n");
+ REQUIRE((*text->lineGet(1)).getText(0) == testStringBlock2);
+
+ text->removeNCharacters(1);
+
+ REQUIRE(text->linesSize() == 1);
+ REQUIRE((*text->lineGet(0)).getText(0) == testStringBlock2);
+
+ text->removeNCharacters(testStringBlock2.length());
+
+ REQUIRE(text->linesSize() == 0);
+ REQUIRE(text->linesGet().empty());
+ }
+
+ SECTION("Empty new block at start and delete from text beginning")
+ {
+ mockup::fontManager();
+ using namespace gui;
+ auto text = std::make_unique<gui::TestText>();
+ text->setCursorStartPosition(gui::CursorStartPosition::DocumentBegin);
+ text->setMaximumSize(600, 200);
+
+ text->addRichText("<text>" + emptyParagraph + testStringBlock1 + emptyParagraph + testStringBlock2 + "</text>");
+
+ REQUIRE(text->linesSize() == 3);
+ REQUIRE((*text->lineGet(0)).getText(0) == "\n");
+ REQUIRE((*text->lineGet(1)).getText(0) == testStringBlock1 + "\n");
+ REQUIRE((*text->lineGet(2)).getText(0) == testStringBlock2);
+
+ text->removeNCharacters(1);
+
+ REQUIRE(text->linesSize() == 2);
+ REQUIRE((*text->lineGet(0)).getText(0) == testStringBlock1 + "\n");
+ REQUIRE((*text->lineGet(1)).getText(0) == testStringBlock2);
+
+ text->removeNCharacters(testStringBlock1.length() + 1);
+
+ REQUIRE(text->linesSize() == 1);
+ REQUIRE((*text->lineGet(0)).getText(0) == testStringBlock2);
+
+ text->removeNCharacters(testStringBlock2.length());
+
+ REQUIRE(text->linesSize() == 0);
+ REQUIRE(text->linesGet().empty());
+ }
+}
+
TEST_CASE("RichText newline and empty lines tests")
{
std::string testStringBlock1 = "Test String 1";
M module-services/service-appmgr/model/ApplicationManager.cpp => module-services/service-appmgr/model/ApplicationManager.cpp +9 -1
@@ 107,8 107,10 @@ namespace app::manager
blockingTimer{std::make_unique<sys::Timer>(
timerBlock, this, std::numeric_limits<sys::ms>::max(), sys::Timer::Type::SingleShot)},
shutdownDelay{std::make_unique<sys::Timer>(timerShutdownDelay, this, shutdown_delay_ms)},
- settings(std::make_unique<settings::Settings>(this))
+ settings(std::make_unique<settings::Settings>(this)),
+ phoneModeObserver(std::make_unique<sys::phone_modes::Observer>())
{
+ bus.channels.push_back(sys::BusChannel::PhoneModeChanges);
registerMessageHandlers();
blockingTimer->connect([this](sys::Timer &) { onPhoneLocked(); });
}
@@ 195,6 197,12 @@ namespace app::manager
void ApplicationManager::registerMessageHandlers()
{
+ phoneModeObserver->connect(this);
+ phoneModeObserver->subscribe(
+ [](sys::phone_modes::PhoneMode phoneMode, sys::phone_modes::Tethering tetheringMode) {
+ LOG_INFO("Phone mode changed.");
+ });
+
connect(typeid(ApplicationStatusRequest), [this](sys::Message *request) {
auto msg = static_cast<ApplicationStatusRequest *>(request);
return std::make_shared<ApplicationStatusResponse>(msg->checkAppName,
M module-services/service-appmgr/service-appmgr/model/ApplicationManager.hpp => module-services/service-appmgr/service-appmgr/model/ApplicationManager.hpp +2 -0
@@ 14,6 14,7 @@
#include <Service/Message.hpp>
#include <Service/Service.hpp>
#include <Service/Timer.hpp>
+#include <PhoneModes/Observer.hpp>
#include <SwitchData.hpp>
#include <deque>
@@ 154,6 155,7 @@ namespace app::manager
std::tuple<ApplicationName, actions::ActionId, actions::ActionParamsPtr> pendingAction;
std::unique_ptr<settings::Settings> settings;
+ std::unique_ptr<sys::phone_modes::Observer> phoneModeObserver;
void displayLanguageChanged(std::string value);
void lockTimeChanged(std::string value);
void inputLanguageChanged(std::string value);
M module-services/service-audio/ServiceAudio.cpp => module-services/service-audio/ServiceAudio.cpp +1 -24
@@ 121,29 121,6 @@ std::optional<std::string> ServiceAudio::AudioServicesCallback(const sys::Messag
}
return settings_it->second;
}
- else if (const auto *btReq = dynamic_cast<const BluetoothProxyMessage *>(msg); btReq) {
- std::shared_ptr<BluetoothProxyMessage> request;
- if (const auto *btStart = dynamic_cast<const BluetoothProxyStartMessage *>(msg); btStart) {
- request = std::make_shared<BluetoothProxyStartMessage>(*btStart);
- }
- else if (const auto *btVolume = dynamic_cast<const BluetoothProxySetVolumeMessage *>(msg); btVolume) {
- request = std::make_shared<BluetoothProxySetVolumeMessage>(*btVolume);
- }
- else if (const auto *btGain = dynamic_cast<const BluetoothProxySetGainMessage *>(msg); btGain) {
- request = std::make_shared<BluetoothProxySetGainMessage>(*btGain);
- }
- else if (const auto *btOutPath = dynamic_cast<const BluetoothProxySetOutputPathMessage *>(msg); btOutPath) {
- request = std::make_shared<BluetoothProxySetOutputPathMessage>(*btOutPath);
- }
- else if (const auto *btInPath = dynamic_cast<const BluetoothProxySetInputPathMessage *>(msg); btInPath) {
- request = std::make_shared<BluetoothProxySetInputPathMessage>(*btInPath);
- }
- else {
- LOG_DEBUG("BluetoothProxyMessage not supported.");
- return std::nullopt;
- }
- bus.sendUnicast(request, service::name::bluetooth);
- }
else {
LOG_DEBUG("Message received but not handled - no effect.");
}
@@ 383,7 360,7 @@ std::unique_ptr<AudioResponseMessage> ServiceAudio::HandleStop(const std::vector
for (auto &input : audioMux.GetAllInputs()) {
const auto ¤tOperation = input.audio->GetCurrentOperation();
if (std::find(stopTypes.begin(), stopTypes.end(), currentOperation.GetPlaybackType()) != stopTypes.end()) {
- muted = true;
+ muted = true;
auto t = input.token;
retCodes.emplace_back(t, stopInput(&input));
}
M module-services/service-bluetooth/ServiceBluetooth.cpp => module-services/service-bluetooth/ServiceBluetooth.cpp +10 -0
@@ 21,6 21,8 @@
#include <utility>
#include <service-desktop/service-desktop/DesktopMessages.hpp>
#include <service-desktop/service-desktop/Constants.hpp>
+#include <service-bluetooth/messages/SetDeviceName.hpp>
+#include <BtCommand.hpp>
ServiceBluetooth::ServiceBluetooth() : sys::Service(service::name::bluetooth)
{
@@ 85,6 87,14 @@ sys::ReturnCodes ServiceBluetooth::InitHandler()
return sys::MessageNone{};
});
+ connect(typeid(message::bluetooth::SetDeviceName), [&](sys::Message *msg) {
+ auto setNameMsg = static_cast<message::bluetooth::SetDeviceName *>(msg);
+ auto newName = setNameMsg->getName();
+ bluetooth::set_name(newName);
+ settingsHolder->setValue(bluetooth::Settings::DeviceName, newName);
+ return sys::MessageNone{};
+ });
+
connect(sdesktop::developerMode::DeveloperModeRequest(), [&](sys::Message *msg) {
using namespace sdesktop::developerMode;
auto req = static_cast<DeveloperModeRequest *>(msg);
M module-services/service-bluetooth/service-bluetooth/BluetoothMessage.hpp => module-services/service-bluetooth/service-bluetooth/BluetoothMessage.hpp +0 -69
@@ 9,7 9,6 @@
#include <Service/Message.hpp>
#include <Audio/Stream.hpp>
#include <MessageType.hpp>
-#include <bsp_audio.hpp>
#include <utility>
#include <vector>
@@ 121,71 120,3 @@ class BluetoothRequestStreamResultMessage : public sys::DataMessage
private:
std::shared_ptr<BluetoothStreamData> data;
};
-
-class BluetoothProxyMessage : public sys::DataMessage
-{
- public:
- BluetoothProxyMessage(MessageType messageType, bsp::AudioDevice::Format format)
- : DataMessage(messageType), format(format){};
-
- ~BluetoothProxyMessage() override = default;
-
- bsp::AudioDevice::Format format;
-};
-
-/// Bluetooth proxy messages
-
-class BluetoothProxyStartMessage : public BluetoothProxyMessage
-{
- public:
- BluetoothProxyStartMessage(audio::Stream &streamOut, audio::Stream &streamIn, bsp::AudioDevice::Format format)
- : BluetoothProxyMessage(MessageType::BluetoothProxyStart, format), audioStreamOut(streamOut),
- audioStreamIn(streamIn){};
-
- ~BluetoothProxyStartMessage() override = default;
-
- audio::Stream &audioStreamOut;
- audio::Stream &audioStreamIn;
-};
-
-class BluetoothProxyStopMessage : public BluetoothProxyMessage
-{
- public:
- BluetoothProxyStopMessage(bsp::AudioDevice::Format format)
- : BluetoothProxyMessage(MessageType::BluetoothProxyStop, format){};
- ~BluetoothProxyStopMessage() override = default;
-};
-
-class BluetoothProxySetVolumeMessage : public BluetoothProxyMessage
-{
- public:
- BluetoothProxySetVolumeMessage(bsp::AudioDevice::Format format)
- : BluetoothProxyMessage(MessageType::BluetoothProxyOutputVolumeCtrl, format){};
- ~BluetoothProxySetVolumeMessage() override = default;
-};
-
-class BluetoothProxySetGainMessage : public BluetoothProxyMessage
-{
- public:
- BluetoothProxySetGainMessage(bsp::AudioDevice::Format format)
- : BluetoothProxyMessage(MessageType::BluetoothProxyInputGainCtrl, format){};
- ~BluetoothProxySetGainMessage() override = default;
-
- float value;
-};
-
-class BluetoothProxySetOutputPathMessage : public BluetoothProxyMessage
-{
- public:
- BluetoothProxySetOutputPathMessage(bsp::AudioDevice::Format format)
- : BluetoothProxyMessage(MessageType::BluetoothProxyOutputPathCtrl, format){};
- ~BluetoothProxySetOutputPathMessage() override = default;
-};
-
-class BluetoothProxySetInputPathMessage : public BluetoothProxyMessage
-{
- public:
- BluetoothProxySetInputPathMessage(bsp::AudioDevice::Format format)
- : BluetoothProxyMessage(MessageType::BluetoothProxyInputPathCtrl, format){};
- ~BluetoothProxySetInputPathMessage() override = default;
-};
M module-services/service-cellular/ServiceCellular.cpp => module-services/service-cellular/ServiceCellular.cpp +2 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2021, 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"
@@ 90,7 90,7 @@
const char *ServiceCellular::serviceName = "ServiceCellular";
-inline constexpr auto cellularStack = 24000UL;
+inline constexpr auto cellularStack = 25000UL;
using namespace cellular;
M module-services/service-db/agents/settings/SystemSettings.hpp => module-services/service-db/agents/settings/SystemSettings.hpp +5 -0
@@ 40,4 40,9 @@ namespace settings
constexpr inline auto apn_list = "cl_apn_list";
} // namespace Cellular
+ namespace Battery
+ {
+ constexpr inline auto batteryCriticalLevel = "battery_critical_level";
+ } // namespace Battery
+
}; // namespace settings
M module-services/service-desktop/endpoints/Context.hpp => module-services/service-desktop/endpoints/Context.hpp +84 -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
#pragma once
@@ 15,7 15,12 @@ namespace parserFSM
inline constexpr auto endpoint = "endpoint";
inline constexpr auto uuid = "uuid";
inline constexpr auto status = "status";
+ inline constexpr auto totalCount = "totalCount";
inline constexpr auto body = "body";
+ inline constexpr auto offset = "offset";
+ inline constexpr auto limit = "limit";
+ inline constexpr auto nextPage = "nextPage";
+ inline constexpr auto entries = "entries";
} // namespace json
struct endpointResponseContext
@@ 28,7 33,7 @@ namespace parserFSM
class Context
{
- private:
+ protected:
json11::Json body;
EndpointType endpoint;
uint32_t uuid;
@@ 84,8 89,9 @@ namespace parserFSM
uuid = invalidUuid;
method = http::Method::get;
}
+ virtual ~Context() noexcept = default;
- auto createSimpleResponse() -> std::string
+ virtual auto createSimpleResponse() -> std::string
{
json11::Json responseJson = json11::Json::object{{json::endpoint, static_cast<int>(getEndpoint())},
{json::status, static_cast<int>(responseContext.status)},
@@ 123,4 129,79 @@ namespace parserFSM
}
};
+ class PagedContext : public Context
+ {
+ private:
+ // from request
+ std::size_t requestedLimit, requestedOffset;
+ // set by query (during helper run)
+ std::size_t totalCount;
+ // set it before calling handle on helper
+ std::size_t pageSize;
+
+ public:
+ explicit PagedContext(json11::Json &js, size_t pageSize) : Context(js), pageSize(pageSize)
+ {}
+ PagedContext() = default;
+ void setRequestedLimit(std::size_t limit)
+ {
+ requestedLimit = limit;
+ }
+ void setRequestedOffset(std::size_t offset)
+ {
+ requestedOffset = offset;
+ }
+ void setTotalCount(std::size_t count)
+ {
+ totalCount = count;
+ }
+ std::size_t getPageSize() const
+ {
+ return pageSize;
+ }
+
+ auto createSimpleResponse() -> std::string override
+ {
+ auto elemsCount = responseContext.body.array_items().size();
+ auto newBody = json11::Json::object{{json::entries, responseContext.body},
+ {json::totalCount, static_cast<int>(totalCount)}};
+ if (requestedLimit > elemsCount) {
+ std::size_t offset = requestedOffset + elemsCount;
+ if (offset < totalCount) {
+ auto lastTableIndex = std::min(totalCount, offset + requestedLimit - elemsCount);
+ std::size_t limit = std::min(pageSize, lastTableIndex - offset);
+ auto nextPageParams = json11::Json::object{{json::offset, static_cast<int>(offset)},
+ {json::limit, static_cast<int>(limit)}};
+ newBody.insert({json::nextPage, nextPageParams});
+ }
+ }
+
+ setResponseBody(newBody);
+ return Context::createSimpleResponse();
+ }
+ };
+
+ namespace endpoint_pageing
+ {
+ inline constexpr std::size_t contactsPageSize = 10;
+ }
+
+ class ContextFactory
+ {
+ public:
+ static auto create(json11::Json &js) -> std::unique_ptr<parserFSM::Context>
+ {
+ switch (static_cast<EndpointType>(js[json::endpoint].int_value())) {
+ // enable for pagination in other endpoints
+ // case EndpointType::calendarEvents:
+ // case EndpointType::calllog:
+ case EndpointType::contacts:
+ // case EndpointType::messages:
+ return std::make_unique<PagedContext>(js, endpoint_pageing::contactsPageSize);
+ default:
+ return std::make_unique<Context>(js);
+ }
+ }
+ };
+
} // namespace parserFSM
M module-services/service-desktop/endpoints/Endpoint.hpp => module-services/service-desktop/endpoints/Endpoint.hpp +3 -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
#pragma once
@@ 10,6 10,7 @@
#include <Common/Query.hpp>
#include <Service/Service.hpp>
#include <string>
+#include <memory>
namespace parserFSM
{
@@ 20,7 21,7 @@ namespace parserFSM
public:
Endpoint(sys::Service *_ownerServicePtr) : ownerServicePtr(_ownerServicePtr){};
virtual ~Endpoint() = default;
- virtual auto handle(Context &context) -> void = 0;
+ virtual auto handle(parserFSM::Context &context) -> void = 0;
auto c_str() -> const char *
{
return debugName.c_str();
M module-services/service-desktop/endpoints/contacts/ContactHelper.cpp => module-services/service-desktop/endpoints/contacts/ContactHelper.cpp +39 -30
@@ 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 "ContactHelper.hpp"
@@ 27,6 27,7 @@
#include <memory>
#include <utility>
#include <vector>
+#include <algorithm>
using namespace parserFSM;
@@ 72,38 73,46 @@ auto ContactHelper::requestDataFromDB(Context &context) -> sys::ReturnCodes
if (context.getBody()[json::contacts::id].int_value() != 0) {
return requestContactByID(context);
}
- else if (context.getBody()[json::contacts::count].bool_value()) {
+ else if (context.getBody()[json::contacts::limit].bool_value()) {
return requestCount(context);
}
- auto limit = context.getBody()[json::contacts::count].int_value();
- auto offset = context.getBody()[json::contacts::offset].int_value();
- auto query = std::make_unique<db::query::ContactGet>(offset, limit, "");
-
- auto listener = std::make_unique<db::EndpointListener>(
- [](db::QueryResult *result, Context context) {
- if (auto contactResult = dynamic_cast<db::query::ContactGetResult *>(result)) {
-
- auto recordsPtr = std::make_unique<std::vector<ContactRecord>>(contactResult->getRecords());
- json11::Json::array contactsArray;
-
- for (auto record : *recordsPtr.get()) {
- contactsArray.emplace_back(ContactHelper::to_json(record));
+ try {
+ auto &ctx = dynamic_cast<PagedContext &>(context);
+ std::size_t limit = ctx.getBody()[json::contacts::limit].int_value();
+ std::size_t offset = ctx.getBody()[json::contacts::offset].int_value();
+ ctx.setRequestedLimit(limit);
+ ctx.setRequestedOffset(offset);
+ auto query = std::make_unique<db::query::ContactGetWithTotalCount>(std::min(ctx.getPageSize(), limit), offset);
+ auto listener = std::make_unique<db::EndpointListenerWithPages>(
+ [](db::QueryResult *result, PagedContext &context) {
+ if (auto contactResult = dynamic_cast<db::query::ContactGetResultWithTotalCount *>(result)) {
+
+ auto recordsPtr = std::make_unique<std::vector<ContactRecord>>(contactResult->getRecords());
+ context.setTotalCount(contactResult->getAllLength());
+ json11::Json::array contactsArray;
+
+ for (const auto &record : *recordsPtr.get()) {
+ contactsArray.emplace_back(ContactHelper::to_json(record));
+ }
+
+ context.setResponseBody(contactsArray);
+
+ MessageHandler::putToSendQueue(context.createSimpleResponse());
+ return true;
}
-
- context.setResponseBody(contactsArray);
- MessageHandler::putToSendQueue(context.createSimpleResponse());
- return true;
- }
- else {
- return false;
- }
- },
- context);
-
- query->setQueryListener(std::move(listener));
-
- DBServiceAPI::GetQuery(ownerServicePtr, db::Interface::Name::Contact, std::move(query));
+ else {
+ return false;
+ }
+ },
+ ctx);
+ query->setQueryListener(std::move(listener));
+ DBServiceAPI::GetQuery(ownerServicePtr, db::Interface::Name::Contact, std::move(query));
+ }
+ catch (const std::exception &e) {
+ LOG_ERROR("%s", e.what());
+ return sys::ReturnCodes::Failure;
+ }
return sys::ReturnCodes::Success;
}
@@ 118,7 127,7 @@ sys::ReturnCodes ContactHelper::requestCount(Context &context)
auto count = contactResult->getSize();
- context.setResponseBody(json11::Json::object({{json::contacts::count, static_cast<int>(count)}}));
+ context.setResponseBody(json11::Json::object({{json::contacts::limit, static_cast<int>(count)}}));
MessageHandler::putToSendQueue(context.createSimpleResponse());
return true;
}
M module-services/service-desktop/endpoints/contacts/ContactHelper.hpp => module-services/service-desktop/endpoints/contacts/ContactHelper.hpp +5 -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
#pragma once
@@ 26,8 26,10 @@ namespace parserFSM
class ContactHelper : public DBHelper
{
+
public:
- ContactHelper(sys::Service *_ownerServicePtr) : DBHelper(_ownerServicePtr){};
+ ContactHelper(sys::Service *_ownerServicePtr) : DBHelper(_ownerServicePtr)
+ {}
auto createDBEntry(Context &context) -> sys::ReturnCodes override;
auto requestDataFromDB(Context &context) -> sys::ReturnCodes override;
@@ 42,7 44,7 @@ namespace parserFSM
namespace json::contacts
{
- inline constexpr auto count = "count";
+ inline constexpr auto limit = "limit";
inline constexpr auto offset = "offset";
inline constexpr auto primaryName = "priName";
inline constexpr auto alternativeName = "altName";
M module-services/service-desktop/endpoints/contacts/ContactsEndpoint.cpp => module-services/service-desktop/endpoints/contacts/ContactsEndpoint.cpp +1 -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 "ContactHelper.hpp"
@@ 9,7 9,6 @@
#include <memory>
using namespace parserFSM;
-
auto ContactsEndpoint::handle(Context &context) -> void
{
switch (context.getMethod()) {
M module-services/service-desktop/endpoints/contacts/ContactsEndpoint.hpp => module-services/service-desktop/endpoints/contacts/ContactsEndpoint.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-services/service-desktop/endpoints/developerMode/DeveloperModeHelper.cpp => module-services/service-desktop/endpoints/developerMode/DeveloperModeHelper.cpp +3 -5
@@ 65,7 65,7 @@ auto DeveloperModeHelper::processPutRequest(Context &context) -> sys::ReturnCode
}
else if (body[json::developerMode::smsCommand].is_string()) {
if (body[json::developerMode::smsCommand].string_value() == json::developerMode::smsAdd) {
- SMSType smsType = static_cast<SMSType>(context.getBody()[json::messages::type].int_value());
+ const auto smsType = static_cast<SMSType>(context.getBody()[json::messages::messageType].int_value());
if (smsType == SMSType::DRAFT || smsType == SMSType::QUEUED || smsType == SMSType::FAILED) {
return prepareSMS(context);
}
@@ 212,11 212,9 @@ auto DeveloperModeHelper::smsRecordFromJson(json11::Json msgJson) -> SMSRecord
{
auto record = SMSRecord();
- record.type = static_cast<SMSType>(msgJson[json::messages::type].int_value());
+ record.type = static_cast<SMSType>(msgJson[json::messages::messageType].int_value());
record.date = utils::time::getCurrentTimestamp().getTime();
- utils::PhoneNumber phoneNumber(msgJson[json::messages::phoneNumber].string_value());
- record.number = phoneNumber.getView();
- record.body = UTF8(msgJson[json::messages::messageBody].string_value());
+ record.body = UTF8(msgJson[json::messages::messageBody].string_value());
return record;
}
M module-services/service-desktop/endpoints/messages/MessageHelper.cpp => module-services/service-desktop/endpoints/messages/MessageHelper.cpp +456 -337
@@ 9,16 9,13 @@
#include <BaseInterface.hpp>
#include <Common/Query.hpp>
-#include <PhoneNumber.hpp>
#include <SMSRecord.hpp>
#include <SMSTemplateRecord.hpp>
#include <Service/Common.hpp>
#include <ThreadRecord.hpp>
#include <json/json11.hpp>
#include <queries/messages/sms/QuerySMSGet.hpp>
-#include <queries/messages/sms/QuerySMSGetByContactID.hpp>
#include <queries/messages/sms/QuerySMSGetByID.hpp>
-#include <queries/messages/sms/QuerySMSGetByText.hpp>
#include <queries/messages/sms/QuerySMSGetByThreadID.hpp>
#include <queries/messages/sms/QuerySMSGetCount.hpp>
#include <queries/messages/sms/QuerySMSRemove.hpp>
@@ 28,160 25,305 @@
#include <queries/messages/templates/QuerySMSTemplateGetCount.hpp>
#include <queries/messages/templates/QuerySMSTemplateRemove.hpp>
#include <queries/messages/templates/QuerySMSTemplateUpdate.hpp>
+#include <queries/messages/threads/QueryThreadsGet.hpp>
#include <queries/messages/threads/QueryThreadMarkAsRead.hpp>
#include <service-db/DBServiceAPI.hpp>
#include <utf8/UTF8.hpp>
#include <memory>
-#include <string>
#include <utility>
-#include <vector>
+#include <module-db/queries/messages/sms/QuerySMSGetByText.hpp>
-using namespace parserFSM;
-
-auto MessageHelper::to_json(SMSRecord record) -> json11::Json
+namespace parserFSM
{
- auto recordEntry = json11::Json::object{{json::messages::contactID, static_cast<int>(record.contactID)},
- {json::messages::date, static_cast<int>(record.date)},
- {json::messages::dateSent, static_cast<int>(record.dateSent)},
- {json::messages::id, static_cast<int>(record.ID)},
- {json::messages::messageBody, record.body.c_str()},
- {json::messages::type, static_cast<int>(record.type)},
- {json::messages::threadID, static_cast<int>(record.threadID)}};
- return recordEntry;
-}
-
-auto MessageHelper::to_json(SMSTemplateRecord record) -> json11::Json
-{
+ auto MessageHelper::toJson(const SMSRecord &record) -> json11::Json
+ {
- auto recordEntry = json11::Json::object{{json::messages::id, static_cast<int>(record.ID)},
- {json::messages::templateText, record.text.c_str()}};
- return recordEntry;
-}
+ auto recordEntry = json11::Json::object{{json::messages::contactID, static_cast<int>(record.contactID)},
+ {json::messages::receivedAt, static_cast<int>(record.date)},
+ {json::messages::sentAt, static_cast<int>(record.dateSent)},
+ {json::messages::messageID, static_cast<int>(record.ID)},
+ {json::messages::messageBody, record.body.c_str()},
+ {json::messages::messageType, static_cast<int>(record.type)},
+ {json::messages::threadID, static_cast<int>(record.threadID)}};
+ return recordEntry;
+ }
-auto MessageHelper::to_json(ThreadRecord record) -> json11::Json
-{
+ auto MessageHelper::toJson(const SMSTemplateRecord &record) -> json11::Json
+ {
- auto recordEntry =
- json11::Json::object{{json::messages::contactID, static_cast<int>(record.contactID)},
- {json::messages::date, static_cast<int>(record.date)},
- {json::messages::thread::msgCount, static_cast<int>(record.msgCount)},
- {json::messages::id, static_cast<int>(record.ID)},
- {json::messages::thread::snippet, record.snippet.c_str()},
- {json::messages::isUnread, record.isUnread()},
- {json::messages::type, static_cast<int>(record.type)},
- {json::messages::thread::unreadMsgCount, static_cast<int>(record.unreadMsgCount)}};
- return recordEntry;
-}
-
-auto MessageHelper::from_json(json11::Json msgJson) -> SMSTemplateRecord
-{
- SMSTemplateRecord record;
+ auto recordEntry =
+ json11::Json::object{{json::messages::templateID, static_cast<int>(record.ID)},
+ {json::messages::templateBody, record.text.c_str()},
+ {json::messages::lastUsedAt, static_cast<int>(record.lastUsageTimestamp)}};
+ return recordEntry;
+ }
- record.text = UTF8(msgJson[json::messages::templateText].string_value());
+ auto MessageHelper::toJson(const ThreadRecord &record) -> json11::Json
+ {
- return record;
-}
+ auto recordEntry = json11::Json::object{{json::messages::contactID, static_cast<int>(record.contactID)},
+ {json::messages::numberID, static_cast<int>(record.numberID)},
+ {json::messages::lastUpdatedAt, static_cast<int>(record.date)},
+ {json::messages::messageCount, static_cast<int>(record.msgCount)},
+ {json::messages::threadID, static_cast<int>(record.ID)},
+ {json::messages::messageSnippet, record.snippet.c_str()},
+ {json::messages::isUnread, record.isUnread()},
+ {json::messages::messageType, static_cast<int>(record.type)}};
+ return recordEntry;
+ }
-auto MessageHelper::requestDataFromDB(Context &context) -> sys::ReturnCodes
-{
+ auto MessageHelper::fromJson(const json11::Json &msgJson) -> SMSTemplateRecord
+ {
+ SMSTemplateRecord record;
- if (context.getBody()[json::messages::msgTemplate].bool_value() == true) {
- return requestTemplate(context);
- }
- else {
- return requestSMS(context);
+ record.text = UTF8(msgJson[json::messages::templateBody].string_value());
+
+ return record;
}
-}
-auto MessageHelper::requestSMS(Context &context) -> sys::ReturnCodes
-{
- if (context.getBody()[json::messages::count].bool_value() == true) // get messages count
+ auto MessageHelper::requestDataFromDB(Context &context) -> sys::ReturnCodes
{
- auto query = std::make_unique<db::query::SMSGetCount>();
+ if (context.getBody()[json::messages::category].string_value() == json::messages::categoryMessage) {
+ return requestSMS(context);
+ }
+ else if (context.getBody()[json::messages::category].string_value() == json::messages::categoryTemplate) {
+ return requestTemplate(context);
+ }
+ else if (context.getBody()[json::messages::category].string_value() == json::messages::categoryThread) {
+ return requestThread(context);
+ }
+ LOG_ERROR("Category of request is missing or incorrect!");
+ context.setResponseStatus(http::Code::BadRequest);
+ MessageHandler::putToSendQueue(context.createSimpleResponse());
+ return sys::ReturnCodes::Unresolved;
+ }
- auto listener = std::make_unique<db::EndpointListener>(
- [=](db::QueryResult *result, Context context) {
- if (auto SMSResult = dynamic_cast<db::query::SMSGetCountResult *>(result)) {
- auto id = SMSResult->getResults();
+ auto MessageHelper::createDBEntry(Context &context) -> sys::ReturnCodes
+ {
+ if (context.getBody()[json::messages::category].string_value() == json::messages::categoryMessage) {
+ return createSMS(context);
+ }
+ else if (context.getBody()[json::messages::category].string_value() == json::messages::categoryTemplate) {
+ return createTemplate(context);
+ }
+ LOG_ERROR("Category of request is missing or incorrect!");
+ context.setResponseStatus(http::Code::BadRequest);
+ MessageHandler::putToSendQueue(context.createSimpleResponse());
+ return sys::ReturnCodes::Unresolved;
+ }
- context.setResponseBody(json11::Json::object{{json::messages::count, static_cast<int>(id)}});
- MessageHandler::putToSendQueue(context.createSimpleResponse());
- return true;
- }
- else {
- return false;
- }
- },
- context);
+ auto MessageHelper::updateDBEntry(Context &context) -> sys::ReturnCodes
+ {
+ if (context.getBody()[json::messages::category].string_value() == json::messages::categoryTemplate) {
+ return updateTemplate(context);
+ }
+ else if (context.getBody()[json::messages::category].string_value() == json::messages::categoryThread) {
+ return updateThread(context);
+ }
+ LOG_ERROR("Category of request is missing or incorrect!");
+ context.setResponseStatus(http::Code::BadRequest);
+ MessageHandler::putToSendQueue(context.createSimpleResponse());
+ return sys::ReturnCodes::Unresolved;
+ }
- query->setQueryListener(std::move(listener));
- DBServiceAPI::GetQuery(ownerServicePtr, db::Interface::Name::SMS, std::move(query));
+ auto MessageHelper::deleteDBEntry(Context &context) -> sys::ReturnCodes
+ {
+ if (context.getBody()[json::messages::category].string_value() == json::messages::categoryMessage) {
+ return deleteSMS(context);
+ }
+ else if (context.getBody()[json::messages::category].string_value() == json::messages::categoryTemplate) {
+ return deleteTemplate(context);
+ }
+ else if (context.getBody()[json::messages::category].string_value() == json::messages::categoryThread) {
+ return deleteThread(context);
+ }
+ LOG_ERROR("Category of request is missing or incorrect!");
+ context.setResponseStatus(http::Code::BadRequest);
+ MessageHandler::putToSendQueue(context.createSimpleResponse());
+ return sys::ReturnCodes::Unresolved;
}
- else if (context.getBody()[json::messages::id].int_value() != 0) { // messages search
- auto query = std::make_unique<db::query::SMSGetByID>(context.getBody()[json::messages::id].int_value());
+ auto MessageHelper::requestSMS(Context &context) -> sys::ReturnCodes
+ {
+ if (context.getBody()[json::messages::count].bool_value()) // get messages count
+ {
+ auto query = std::make_unique<db::query::SMSGetCount>();
+
+ auto listener = std::make_unique<db::EndpointListener>(
+ [=](db::QueryResult *result, Context context) {
+ if (auto smsResult = dynamic_cast<db::query::SMSGetCountResult *>(result)) {
+ auto id = smsResult->getResults();
+
+ context.setResponseBody(json11::Json::object{{json::messages::count, static_cast<int>(id)}});
+ MessageHandler::putToSendQueue(context.createSimpleResponse());
+ return true;
+ }
+ else {
+ return false;
+ }
+ },
+ context);
- auto listener = std::make_unique<db::EndpointListener>(
- [=](db::QueryResult *result, Context context) {
- if (auto SMSResult = dynamic_cast<db::query::SMSGetByIDResult *>(result)) {
+ query->setQueryListener(std::move(listener));
+ DBServiceAPI::GetQuery(ownerServicePtr, db::Interface::Name::SMS, std::move(query));
+ }
+ else if (context.getBody()[json::messages::messageID].int_value() != 0) { // get message by ID
- context.setResponseBody(MessageHelper::to_json(SMSResult->getResults()));
- MessageHandler::putToSendQueue(context.createSimpleResponse());
- return true;
- }
- else {
- return false;
- }
- },
- context);
+ auto query =
+ std::make_unique<db::query::SMSGetByID>(context.getBody()[json::messages::messageID].int_value());
- query->setQueryListener(std::move(listener));
- DBServiceAPI::GetQuery(ownerServicePtr, db::Interface::Name::SMS, std::move(query));
- }
- else if (context.getBody()[json::messages::contactID].int_value() != 0) {
+ auto listener = std::make_unique<db::EndpointListener>(
+ [=](db::QueryResult *result, Context context) {
+ if (auto smsResult = dynamic_cast<db::query::SMSGetByIDResult *>(result)) {
- auto query =
- std::make_unique<db::query::SMSGetByContactID>(context.getBody()[json::messages::contactID].int_value());
+ context.setResponseBody(MessageHelper::toJson(smsResult->getResults()));
+ MessageHandler::putToSendQueue(context.createSimpleResponse());
+ return true;
+ }
+ else {
+ return false;
+ }
+ },
+ context);
- auto listener = std::make_unique<db::EndpointListener>(
- [=](db::QueryResult *result, Context context) {
- if (auto SMSResult = dynamic_cast<db::query::SMSGetByContactIDResult *>(result)) {
+ query->setQueryListener(std::move(listener));
+ DBServiceAPI::GetQuery(ownerServicePtr, db::Interface::Name::SMS, std::move(query));
+ }
+ else if (context.getBody()[json::messages::threadID].int_value() != 0) { // get messages by thread ID
+
+ auto query =
+ std::make_unique<db::query::SMSGetByThreadID>(context.getBody()[json::messages::threadID].int_value(),
+ context.getBody()[json::messages::offset].int_value(),
+ context.getBody()[json::messages::limit].is_number()
+ ? context.getBody()[json::messages::limit].int_value()
+ : defaultLimit);
+
+ auto listener = std::make_unique<db::EndpointListener>(
+ [=](db::QueryResult *result, Context context) {
+ if (auto smsResult = dynamic_cast<db::query::SMSGetByThreadIDResult *>(result)) {
+
+ json11::Json::array smsArray;
+ for (const auto &record : smsResult->getResults()) {
+ smsArray.emplace_back(MessageHelper::toJson(record));
+ }
+
+ auto responseBody = json11::Json::object{
+ {json::messages::totalCount, 0},
+ {json::messages::nextPage,
+ json11::Json::object{{json::messages::offset, 0}, {json::messages::limit, 0}}},
+ {json::messages::entries, smsArray},
+ };
+
+ context.setResponseBody(responseBody);
+ MessageHandler::putToSendQueue(context.createSimpleResponse());
+ return true;
+ }
+ else {
+ return false;
+ }
+ },
+ context);
+
+ query->setQueryListener(std::move(listener));
+ DBServiceAPI::GetQuery(ownerServicePtr, db::Interface::Name::SMS, std::move(query));
+ }
+ else if (!context.getBody()[json::messages::messageBody].string_value().empty()) // get by message body
+ {
+ // not adding pagination for this request, since it is just for development and testing purposes, and it's
+ // not going to be used by Mudita Center
+ auto query = std::make_unique<db::query::SMSGetByText>(
+ context.getBody()[json::messages::messageBody].string_value());
+ if (const auto filterByNumber = !context.getBody()[json::messages::phoneNumber].string_value().empty();
+ filterByNumber) {
+ utils::PhoneNumber number{context.getBody()[json::messages::phoneNumber].string_value()};
+ query->filterByPhoneNumber(number.getView());
+ }
+
+ auto listener = std::make_unique<db::EndpointListener>(
+ [=](db::QueryResult *result, Context context) {
+ if (auto smsResult = dynamic_cast<db::query::SMSGetByTextResult *>(result)) {
- json11::Json::array SMSarray;
- for (auto record : SMSResult->getResults()) {
- SMSarray.emplace_back(MessageHelper::to_json(record));
+ json11::Json::array smsArray;
+ for (const auto &record : smsResult->getResults()) {
+ smsArray.emplace_back(MessageHelper::toJson(record));
+ }
+
+ context.setResponseBody(smsArray);
+ MessageHandler::putToSendQueue(context.createSimpleResponse());
+ return true;
+ }
+ else {
+ return false;
}
+ },
+ context);
- context.setResponseBody(SMSarray);
- MessageHandler::putToSendQueue(context.createSimpleResponse());
- return true;
- }
- else {
- return false;
- }
- },
- context);
+ query->setQueryListener(std::move(listener));
+ DBServiceAPI::GetQuery(ownerServicePtr, db::Interface::Name::SMS, std::move(query));
+ }
+ else // get messages
+ {
+ auto query = std::make_unique<db::query::SMSGet>(context.getBody()[json::messages::limit].is_number()
+ ? context.getBody()[json::messages::limit].int_value()
+ : defaultLimit,
+ context.getBody()[json::messages::offset].int_value());
+
+ auto listener = std::make_unique<db::EndpointListener>(
+ [=](db::QueryResult *result, Context context) {
+ if (auto smsResult = dynamic_cast<db::query::SMSGetResult *>(result)) {
+
+ json11::Json::array smsArray;
+ for (const auto &record : smsResult->getRecords()) {
+ smsArray.emplace_back(MessageHelper::toJson(record));
+ LOG_DEBUG("Record found!: %" PRIu32 "\n", record.ID);
+ }
+
+ auto responseBody = json11::Json::object{
+ {json::messages::totalCount, 0},
+ {json::messages::nextPage,
+ json11::Json::object{{json::messages::offset, 0}, {json::messages::limit, 0}}},
+ {json::messages::entries, smsArray},
+ };
+
+ context.setResponseBody(responseBody);
+ MessageHandler::putToSendQueue(context.createSimpleResponse());
+ return true;
+ }
+ else {
+ return false;
+ }
+ },
+ context);
- query->setQueryListener(std::move(listener));
- DBServiceAPI::GetQuery(ownerServicePtr, db::Interface::Name::SMS, std::move(query));
+ query->setQueryListener(std::move(listener));
+ DBServiceAPI::GetQuery(ownerServicePtr, db::Interface::Name::SMS, std::move(query));
+ }
+ return sys::ReturnCodes::Success;
}
- else if (context.getBody()[json::messages::threadID].int_value() != 0) {
- auto query =
- std::make_unique<db::query::SMSGetByThreadID>(context.getBody()[json::messages::threadID].int_value());
+ auto MessageHelper::createSMS(Context &context) -> sys::ReturnCodes
+ {
+ context.setResponseStatus(http::Code::InternalServerError);
+ MessageHandler::putToSendQueue(context.createSimpleResponse());
+ return sys::ReturnCodes::Success;
+ }
+ auto MessageHelper::deleteSMS(Context &context) -> sys::ReturnCodes
+ {
+ if (!context.getBody()[json::messages::messageID].is_number()) {
+ LOG_ERROR("Bad request! messageID is incorrect or missing!");
+ return sys::ReturnCodes::Unresolved;
+ }
+ auto id = context.getBody()[json::messages::messageID].int_value();
+ auto query = std::make_unique<db::query::SMSRemove>(id);
auto listener = std::make_unique<db::EndpointListener>(
[=](db::QueryResult *result, Context context) {
- if (auto SMSResult = dynamic_cast<db::query::SMSGetByThreadIDResult *>(result)) {
+ if (auto smsTemplateResult = dynamic_cast<db::query::SMSRemoveResult *>(result)) {
- json11::Json::array SMSarray;
- for (auto record : SMSResult->getResults()) {
- SMSarray.emplace_back(MessageHelper::to_json(record));
- }
-
- context.setResponseBody(SMSarray);
+ context.setResponseStatus(smsTemplateResult->getResults() ? http::Code::OK
+ : http::Code::InternalServerError);
MessageHandler::putToSendQueue(context.createSimpleResponse());
return true;
}
@@ 193,53 335,121 @@ auto MessageHelper::requestSMS(Context &context) -> sys::ReturnCodes
query->setQueryListener(std::move(listener));
DBServiceAPI::GetQuery(ownerServicePtr, db::Interface::Name::SMS, std::move(query));
+
+ return sys::ReturnCodes::Success;
}
- else if (context.getBody()[json::messages::messageBody].string_value().empty() == false) {
- auto query =
- std::make_unique<db::query::SMSGetByText>(context.getBody()[json::messages::messageBody].string_value());
- if (const auto filterByNumber = !context.getBody()[json::messages::phoneNumber].string_value().empty();
- filterByNumber) {
- utils::PhoneNumber number{context.getBody()[json::messages::phoneNumber].string_value()};
- query->filterByPhoneNumber(number.getView());
+
+ auto MessageHelper::requestTemplate(Context &context) -> sys::ReturnCodes
+ {
+ if (context.getBody()[json::messages::count].bool_value()) // get templates count
+ {
+ auto query = std::make_unique<db::query::SMSTemplateGetCount>();
+
+ auto listener = std::make_unique<db::EndpointListener>(
+ [=](db::QueryResult *result, Context context) {
+ if (auto smsResult = dynamic_cast<db::query::SMSTemplateGetCountResult *>(result)) {
+ auto id = smsResult->getResults();
+
+ context.setResponseBody(json11::Json::object{{json::messages::count, static_cast<int>(id)}});
+ MessageHandler::putToSendQueue(context.createSimpleResponse());
+ return true;
+ }
+ else {
+ return false;
+ }
+ },
+ context);
+
+ query->setQueryListener(std::move(listener));
+ DBServiceAPI::GetQuery(ownerServicePtr, db::Interface::Name::SMSTemplate, std::move(query));
}
+ else if (context.getBody()[json::messages::templateID].int_value() != 0) { // get template by ID
+ auto query = std::make_unique<db::query::SMSTemplateGetByID>(
+ context.getBody()[json::messages::templateID].int_value());
- auto listener = std::make_unique<db::EndpointListener>(
- [=](db::QueryResult *result, Context context) {
- if (auto SMSResult = dynamic_cast<db::query::SMSGetByTextResult *>(result)) {
+ auto listener = std::make_unique<db::EndpointListener>(
+ [=](db::QueryResult *result, Context context) {
+ if (auto smsTemplateResult = dynamic_cast<db::query::SMSTemplateGetByIDResult *>(result)) {
- json11::Json::array SMSarray;
- for (auto record : SMSResult->getResults()) {
- SMSarray.emplace_back(MessageHelper::to_json(record));
+ context.setResponseBody(MessageHelper::toJson(smsTemplateResult->getResults()));
+ MessageHandler::putToSendQueue(context.createSimpleResponse());
+ return true;
+ }
+ else {
+ return false;
}
+ },
+ context);
- context.setResponseBody(SMSarray);
- MessageHandler::putToSendQueue(context.createSimpleResponse());
- return true;
- }
- else {
- return false;
- }
- },
- context);
+ query->setQueryListener(std::move(listener));
+ DBServiceAPI::GetQuery(ownerServicePtr, db::Interface::Name::SMSTemplate, std::move(query));
+ }
+ else // get messages templates
+ {
+ auto query =
+ std::make_unique<db::query::SMSTemplateGet>(context.getBody()[json::messages::offset].int_value(),
+ context.getBody()[json::messages::limit].is_number()
+ ? context.getBody()[json::messages::limit].int_value()
+ : defaultLimit);
+ auto listener = std::make_unique<db::EndpointListener>(
+ [=](db::QueryResult *result, Context context) {
+ if (auto smsTemplateResult = dynamic_cast<db::query::SMSTemplateGetResult *>(result)) {
+
+ json11::Json::array smsTemplateArray;
+ for (const auto &record : smsTemplateResult->getResults()) {
+ smsTemplateArray.emplace_back(toJson(record));
+ }
+
+ auto responseBody = json11::Json::object{
+ {json::messages::totalCount, 0},
+ {json::messages::nextPage,
+ json11::Json::object{{json::messages::offset, 0}, {json::messages::limit, 0}}},
+ {json::messages::entries, smsTemplateArray},
+ };
+
+ context.setResponseBody(responseBody);
+ MessageHandler::putToSendQueue(context.createSimpleResponse());
+ return true;
+ }
+ else {
+ return false;
+ }
+ },
+ context);
- query->setQueryListener(std::move(listener));
- DBServiceAPI::GetQuery(ownerServicePtr, db::Interface::Name::SMS, std::move(query));
+ query->setQueryListener(std::move(listener));
+ DBServiceAPI::GetQuery(ownerServicePtr, db::Interface::Name::SMSTemplate, std::move(query));
+ }
+
+ return sys::ReturnCodes::Success;
}
- else // get messages
+ auto MessageHelper::updateTemplate(Context &context) -> sys::ReturnCodes
{
- auto query = std::make_unique<db::query::SMSGet>(context.getBody()[json::messages::count].int_value(),
- context.getBody()[json::messages::offset].int_value());
+ if (!context.getBody()[json::messages::templateID].is_number()) {
+ LOG_ERROR("Bad request! templateID is incorrect or missing!");
+ context.setResponseStatus(http::Code::BadRequest);
+ MessageHandler::putToSendQueue(context.createSimpleResponse());
+ return sys::ReturnCodes::Unresolved;
+ }
+
+ if (!context.getBody()[json::messages::templateBody].is_string()) {
+ LOG_ERROR("Bad request! templateBody is incorrect or missing!");
+ context.setResponseStatus(http::Code::BadRequest);
+ MessageHandler::putToSendQueue(context.createSimpleResponse());
+ return sys::ReturnCodes::Unresolved;
+ }
+
+ SMSTemplateRecord record;
+ record.ID = context.getBody()[json::messages::templateID].int_value();
+ record.text = context.getBody()[json::messages::templateBody].string_value();
+ auto query = std::make_unique<db::query::SMSTemplateUpdate>(record);
auto listener = std::make_unique<db::EndpointListener>(
[=](db::QueryResult *result, Context context) {
- if (auto SMSResult = dynamic_cast<db::query::SMSGetResult *>(result)) {
+ if (auto smsTemplateResult = dynamic_cast<db::query::SMSTemplateUpdateResult *>(result)) {
- json11::Json::array SMSarray;
- for (auto record : SMSResult->getRecords()) {
- SMSarray.emplace_back(MessageHelper::to_json(record));
- }
-
- context.setResponseBody(SMSarray);
+ context.setResponseStatus(smsTemplateResult->getResult() ? http::Code::OK
+ : http::Code::InternalServerError);
MessageHandler::putToSendQueue(context.createSimpleResponse());
return true;
}
@@ 250,24 460,29 @@ auto MessageHelper::requestSMS(Context &context) -> sys::ReturnCodes
context);
query->setQueryListener(std::move(listener));
- DBServiceAPI::GetQuery(ownerServicePtr, db::Interface::Name::SMS, std::move(query));
- }
+ DBServiceAPI::GetQuery(ownerServicePtr, db::Interface::Name::SMSTemplate, std::move(query));
- return sys::ReturnCodes::Success;
-}
+ return sys::ReturnCodes::Success;
+ }
-auto MessageHelper::requestTemplate(Context &context) -> sys::ReturnCodes
-{
- if (context.getBody()[json::messages::count].bool_value() == true) // get templates count
+ auto MessageHelper::createTemplate(Context &context) -> sys::ReturnCodes
{
- auto query = std::make_unique<db::query::SMSTemplateGetCount>();
+ if (!context.getBody()[json::messages::templateBody].is_string()) {
+ LOG_ERROR("Bad request! templateBody is incorrect or missing!");
+ context.setResponseStatus(http::Code::BadRequest);
+ MessageHandler::putToSendQueue(context.createSimpleResponse());
+ return sys::ReturnCodes::Unresolved;
+ }
+
+ SMSTemplateRecord record = fromJson(context.getBody());
+ auto query = std::make_unique<db::query::SMSTemplateAdd>(record);
auto listener = std::make_unique<db::EndpointListener>(
[=](db::QueryResult *result, Context context) {
- if (auto SMSResult = dynamic_cast<db::query::SMSTemplateGetCountResult *>(result)) {
- auto id = SMSResult->getResults();
+ if (auto smsTemplateResult = dynamic_cast<db::query::SMSTemplateAddResult *>(result)) {
- context.setResponseBody(json11::Json::object{{json::messages::count, static_cast<int>(id)}});
+ context.setResponseStatus(smsTemplateResult->getResult() ? http::Code::OK
+ : http::Code::InternalServerError);
MessageHandler::putToSendQueue(context.createSimpleResponse());
return true;
}
@@ 279,15 494,27 @@ auto MessageHelper::requestTemplate(Context &context) -> sys::ReturnCodes
query->setQueryListener(std::move(listener));
DBServiceAPI::GetQuery(ownerServicePtr, db::Interface::Name::SMSTemplate, std::move(query));
+
+ return sys::ReturnCodes::Success;
}
- else if (context.getBody()[json::messages::id].int_value() != 0) { // templates search
- auto query = std::make_unique<db::query::SMSTemplateGetByID>(context.getBody()[json::messages::id].int_value());
+ auto MessageHelper::deleteTemplate(Context &context) -> sys::ReturnCodes
+ {
+ if (!context.getBody()[json::messages::templateID].is_number()) {
+ LOG_ERROR("Bad request! templateID is incorrect or missing!");
+ context.setResponseStatus(http::Code::BadRequest);
+ MessageHandler::putToSendQueue(context.createSimpleResponse());
+ return sys::ReturnCodes::Unresolved;
+ }
+
+ auto query =
+ std::make_unique<db::query::SMSTemplateRemove>(context.getBody()[json::messages::templateID].int_value());
auto listener = std::make_unique<db::EndpointListener>(
[=](db::QueryResult *result, Context context) {
- if (auto SMSTemplateResult = dynamic_cast<db::query::SMSTemplateGetByIDResult *>(result)) {
+ if (auto smsTemplateResult = dynamic_cast<db::query::SMSTemplateRemoveResult *>(result)) {
- context.setResponseBody(MessageHelper::to_json(SMSTemplateResult->getResults()));
+ context.setResponseStatus(smsTemplateResult->getResults() ? http::Code::OK
+ : http::Code::InternalServerError);
MessageHandler::putToSendQueue(context.createSimpleResponse());
return true;
}
@@ 299,21 526,33 @@ auto MessageHelper::requestTemplate(Context &context) -> sys::ReturnCodes
query->setQueryListener(std::move(listener));
DBServiceAPI::GetQuery(ownerServicePtr, db::Interface::Name::SMSTemplate, std::move(query));
+ return sys::ReturnCodes::Success;
}
- else // get messages templates
+
+ auto MessageHelper::requestThread(Context &context) -> sys::ReturnCodes
{
- auto query = std::make_unique<db::query::SMSTemplateGet>(context.getBody()[json::messages::offset].int_value(),
- context.getBody()[json::messages::count].int_value());
+ auto query = std::make_unique<db::query::ThreadsGet>(context.getBody()[json::messages::offset].int_value(),
+ context.getBody()[json::messages::limit].is_number()
+ ? context.getBody()[json::messages::limit].int_value()
+ : defaultLimit);
+
auto listener = std::make_unique<db::EndpointListener>(
[=](db::QueryResult *result, Context context) {
- if (auto SMSTemplateResult = dynamic_cast<db::query::SMSTemplateGetResult *>(result)) {
+ if (auto threadsResults = dynamic_cast<db::query::ThreadsGetResults *>(result)) {
- json11::Json::array SMSTemplateArray;
- for (auto record : SMSTemplateResult->getResults()) {
- SMSTemplateArray.emplace_back(to_json(record));
+ json11::Json::array threadsArray;
+ for (const auto &record : threadsResults->getResults()) {
+ threadsArray.emplace_back(MessageHelper::toJson(record));
}
- context.setResponseBody(SMSTemplateArray);
+ auto responseBody = json11::Json::object{
+ {json::messages::totalCount, 0},
+ {json::messages::nextPage,
+ json11::Json::object{{json::messages::offset, 0}, {json::messages::limit, 0}}},
+ {json::messages::entries, threadsArray},
+ };
+
+ context.setResponseBody(responseBody);
MessageHandler::putToSendQueue(context.createSimpleResponse());
return true;
}
@@ 324,178 563,58 @@ auto MessageHelper::requestTemplate(Context &context) -> sys::ReturnCodes
context);
query->setQueryListener(std::move(listener));
- DBServiceAPI::GetQuery(ownerServicePtr, db::Interface::Name::SMSTemplate, std::move(query));
- }
+ DBServiceAPI::GetQuery(ownerServicePtr, db::Interface::Name::SMSThread, std::move(query));
- return sys::ReturnCodes::Success;
-}
-
-auto MessageHelper::createDBEntry(Context &context) -> sys::ReturnCodes
-{
-
- if (context.getBody()[json::messages::msgTemplate].bool_value() == true) {
- return createTemplate(context);
+ return sys::ReturnCodes::Success;
}
- else {
- return createSMS(context);
- }
-}
-auto MessageHelper::createTemplate(Context &context) -> sys::ReturnCodes
-{
- SMSTemplateRecord record = from_json(context.getBody());
+ auto MessageHelper::updateThread(Context &context) -> sys::ReturnCodes // Set thread as read/unread
+ {
+ if (!context.getBody()[json::messages::threadID].is_number()) {
+ LOG_ERROR("Bad request! threadID is incorrect or missing!");
+ context.setResponseStatus(http::Code::BadRequest);
+ MessageHandler::putToSendQueue(context.createSimpleResponse());
+ return sys::ReturnCodes::Unresolved;
+ }
- auto query = std::make_unique<db::query::SMSTemplateAdd>(record);
- auto listener = std::make_unique<db::EndpointListener>(
- [=](db::QueryResult *result, Context context) {
- if (auto SMSTemplateResult = dynamic_cast<db::query::SMSTemplateAddResult *>(result)) {
+ if (!context.getBody()[json::messages::isUnread].is_bool()) {
+ LOG_ERROR("Bad request! isUnread is incorrect or missing!");
+ context.setResponseStatus(http::Code::BadRequest);
+ MessageHandler::putToSendQueue(context.createSimpleResponse());
+ return sys::ReturnCodes::Unresolved;
+ }
- context.setResponseStatus(SMSTemplateResult->getResult() ? http::Code::OK
- : http::Code::InternalServerError);
- MessageHandler::putToSendQueue(context.createSimpleResponse());
- return true;
- }
- else {
- return false;
- }
- },
- context);
+ auto query = std::make_unique<db::query::MarkAsRead>(context.getBody()[json::messages::threadID].int_value(),
+ (context.getBody()[json::messages::isUnread].bool_value()
+ ? db::query::MarkAsRead::Read::False
+ : db::query::MarkAsRead::Read::True));
- query->setQueryListener(std::move(listener));
- DBServiceAPI::GetQuery(ownerServicePtr, db::Interface::Name::SMSTemplate, std::move(query));
+ auto listener = std::make_unique<db::EndpointListener>(
+ [=](db::QueryResult *result, Context context) {
+ if (auto threadResult = dynamic_cast<db::query::MarkAsReadResult *>(result)) {
- return sys::ReturnCodes::Success;
-}
+ context.setResponseStatus(threadResult->getResult() ? http::Code::OK
+ : http::Code::InternalServerError);
+ MessageHandler::putToSendQueue(context.createSimpleResponse());
+ return true;
+ }
+ else {
+ return false;
+ }
+ },
+ context);
-auto MessageHelper::createSMS(Context &context) -> sys::ReturnCodes
-{
- return sys::ReturnCodes::Success;
-}
+ query->setQueryListener(std::move(listener));
-auto MessageHelper::deleteDBEntry(Context &context) -> sys::ReturnCodes
-{
+ DBServiceAPI::GetQuery(ownerServicePtr, db::Interface::Name::SMSThread, std::move(query));
- if (context.getBody()[json::messages::msgTemplate].bool_value() == true) {
- return deleteTemplate(context);
- }
- else {
- return deleteSMS(context);
+ return sys::ReturnCodes::Success;
}
-}
-
-auto MessageHelper::deleteSMS(Context &context) -> sys::ReturnCodes
-{
- auto id = context.getBody()[json::messages::id].int_value();
- auto query = std::make_unique<db::query::SMSRemove>(id);
- auto listener = std::make_unique<db::EndpointListener>(
- [=](db::QueryResult *result, Context context) {
- if (auto SMSTemplateResult = dynamic_cast<db::query::SMSRemoveResult *>(result)) {
-
- context.setResponseStatus(SMSTemplateResult->getResults() ? http::Code::OK
- : http::Code::InternalServerError);
- MessageHandler::putToSendQueue(context.createSimpleResponse());
- return true;
- }
- else {
- return false;
- }
- },
- context);
- query->setQueryListener(std::move(listener));
- DBServiceAPI::GetQuery(ownerServicePtr, db::Interface::Name::SMS, std::move(query));
-
- return sys::ReturnCodes::Success;
-}
-
-auto MessageHelper::deleteTemplate(Context &context) -> sys::ReturnCodes
-{
- auto id = context.getBody()[json::messages::id].int_value();
- auto query = std::make_unique<db::query::SMSTemplateRemove>(id);
- auto listener = std::make_unique<db::EndpointListener>(
- [=](db::QueryResult *result, Context context) {
- if (auto SMSTemplateResult = dynamic_cast<db::query::SMSTemplateRemoveResult *>(result)) {
-
- context.setResponseStatus(SMSTemplateResult->getResults() ? http::Code::OK
- : http::Code::InternalServerError);
- MessageHandler::putToSendQueue(context.createSimpleResponse());
- return true;
- }
- else {
- return false;
- }
- },
- context);
-
- query->setQueryListener(std::move(listener));
- DBServiceAPI::GetQuery(ownerServicePtr, db::Interface::Name::SMSTemplate, std::move(query));
- return sys::ReturnCodes::Success;
-}
-
-auto MessageHelper::updateDBEntry(Context &context) -> sys::ReturnCodes
-{
-
- if (context.getBody()[json::messages::msgTemplate].bool_value() == true) {
- return updateTemplate(context);
- }
- else {
- return updateSMS(context);
+ auto MessageHelper::deleteThread(Context &context) -> sys::ReturnCodes
+ {
+ context.setResponseStatus(http::Code::InternalServerError);
+ MessageHandler::putToSendQueue(context.createSimpleResponse());
+ return sys::ReturnCodes::Success;
}
-}
-
-auto MessageHelper::updateSMS(Context &context) -> sys::ReturnCodes
-{
- using namespace db::query;
-
- auto query = std::make_unique<db::query::MarkAsRead>(
- context.getBody()[json::messages::threadID].int_value(),
- (context.getBody()[json::messages::isUnread].bool_value() ? MarkAsRead::Read::False : MarkAsRead::Read::True));
-
- auto listener = std::make_unique<db::EndpointListener>(
- [=](db::QueryResult *result, Context context) {
- if (auto SMSResult = dynamic_cast<db::query::MarkAsReadResult *>(result)) {
-
- context.setResponseStatus(SMSResult->getResult() ? http::Code::OK : http::Code::InternalServerError);
- MessageHandler::putToSendQueue(context.createSimpleResponse());
-
- return true;
- }
- else {
- return false;
- }
- },
- context);
-
- query->setQueryListener(std::move(listener));
-
- DBServiceAPI::GetQuery(ownerServicePtr, db::Interface::Name::SMSThread, std::move(query));
- return sys::ReturnCodes::Success;
-}
-
-auto MessageHelper::updateTemplate(Context &context) -> sys::ReturnCodes
-{
- SMSTemplateRecord record;
- record.ID = context.getBody()[json::messages::id].int_value();
- record.text = context.getBody()[json::messages::templateText].string_value();
-
- auto query = std::make_unique<db::query::SMSTemplateUpdate>(record);
- auto listener = std::make_unique<db::EndpointListener>(
- [=](db::QueryResult *result, Context context) {
- if (auto SMSTemplateResult = dynamic_cast<db::query::SMSTemplateUpdateResult *>(result)) {
-
- context.setResponseStatus(SMSTemplateResult->getResult() ? http::Code::OK
- : http::Code::InternalServerError);
- MessageHandler::putToSendQueue(context.createSimpleResponse());
- return true;
- }
- else {
- return false;
- }
- },
- context);
-
- query->setQueryListener(std::move(listener));
- DBServiceAPI::GetQuery(ownerServicePtr, db::Interface::Name::SMSTemplate, std::move(query));
-
- return sys::ReturnCodes::Success;
-}
+} // namespace parserFSM
M module-services/service-desktop/endpoints/messages/MessageHelper.hpp => module-services/service-desktop/endpoints/messages/MessageHelper.hpp +17 -41
@@ 14,9 14,6 @@
#include <ThreadRecord.hpp>
#include <json/json11.hpp>
-#include <memory>
-#include <string>
-
namespace sys
{
class Service;
@@ 29,55 26,34 @@ namespace parserFSM
class MessageHelper final : public DBHelper
{
public:
- MessageHelper(sys::Service *_ownerServicePtr) : DBHelper(_ownerServicePtr){};
+ explicit MessageHelper(sys::Service *_ownerServicePtr) : DBHelper(_ownerServicePtr){};
auto createDBEntry(Context &context) -> sys::ReturnCodes override;
auto requestDataFromDB(Context &context) -> sys::ReturnCodes override;
auto updateDBEntry(Context &context) -> sys::ReturnCodes override;
auto deleteDBEntry(Context &context) -> sys::ReturnCodes override;
- auto createTemplate(Context &context) -> sys::ReturnCodes;
- auto requestTemplate(Context &context) -> sys::ReturnCodes;
- auto updateTemplate(Context &context) -> sys::ReturnCodes;
- auto deleteTemplate(Context &context) -> sys::ReturnCodes;
+ static auto toJson(const SMSRecord &record) -> json11::Json;
+ static auto toJson(const ThreadRecord &record) -> json11::Json;
+ static auto toJson(const SMSTemplateRecord &record) -> json11::Json;
+ static auto fromJson(const json11::Json &msgJson) -> SMSTemplateRecord;
+
+ private:
+ auto requestThread(Context &context) -> sys::ReturnCodes;
+ auto updateThread(Context &context) -> sys::ReturnCodes;
+ auto deleteThread(Context &context) -> sys::ReturnCodes;
- auto createSMS(Context &context) -> sys::ReturnCodes;
auto requestSMS(Context &context) -> sys::ReturnCodes;
- auto updateSMS(Context &context) -> sys::ReturnCodes;
+ auto createSMS(Context &context) -> sys::ReturnCodes;
auto deleteSMS(Context &context) -> sys::ReturnCodes;
- // auto createSimpleResponse(Context &context) -> std::string override;
-
- static auto to_json(SMSRecord record) -> json11::Json;
- static auto to_json(ThreadRecord record) -> json11::Json;
- static auto to_json(SMSTemplateRecord record) -> json11::Json;
- static auto from_json(json11::Json msgJson) -> SMSTemplateRecord;
+ auto requestTemplate(Context &context) -> sys::ReturnCodes;
+ auto createTemplate(Context &context) -> sys::ReturnCodes;
+ auto updateTemplate(Context &context) -> sys::ReturnCodes;
+ auto deleteTemplate(Context &context) -> sys::ReturnCodes;
- private:
json11::Json receivedJson;
- };
-
- namespace messages
- {
- inline constexpr auto id = "id";
- inline constexpr auto count = "count";
- inline constexpr auto offset = "offset";
- inline constexpr auto phoneNumber = "phoneNumber";
- inline constexpr auto isUnread = "unread";
- inline constexpr auto contactID = "contactID";
- inline constexpr auto date = "date";
- inline constexpr auto dateSent = "dateSent";
- inline constexpr auto type = "type";
- inline constexpr auto threadID = "threadID";
- inline constexpr auto msgTemplate = "template";
- inline constexpr auto templateText = "text";
- namespace thread
- {
- inline constexpr auto msgCount = "msgCount";
- inline constexpr auto snippet = "snippet";
- inline constexpr auto unreadMsgCount = "unreadMsgCount";
- } // namespace thread
-
- } // namespace messages
+ const int defaultLimit = 100; // will be removed after introducing pagination
+ };
} // namespace parserFSM
M module-services/service-desktop/endpoints/messages/MessagesEndpoint.cpp => module-services/service-desktop/endpoints/messages/MessagesEndpoint.cpp +3 -3
@@ 14,11 14,11 @@ auto MessagesEndpoint::handle(Context &context) -> void
case http::Method::get:
helper->requestDataFromDB(context);
break;
- case http::Method::post: // update entry
- helper->updateDBEntry(context);
+ case http::Method::post:
+ helper->createDBEntry(context);
break;
case http::Method::put:
- helper->createDBEntry(context);
+ helper->updateDBEntry(context);
break;
case http::Method::del:
helper->deleteDBEntry(context);
M module-services/service-desktop/endpoints/messages/MessagesEndpoint.hpp => module-services/service-desktop/endpoints/messages/MessagesEndpoint.hpp +1 -1
@@ 27,7 27,7 @@ class MessagesEndpoint : public parserFSM::Endpoint
std::shared_ptr<parserFSM::MessageHelper> helper;
public:
- MessagesEndpoint(sys::Service *_ownerServicePtr) : Endpoint(_ownerServicePtr)
+ explicit MessagesEndpoint(sys::Service *_ownerServicePtr) : Endpoint(_ownerServicePtr)
{
debugName = "MessagesEndpoint";
helper = std::make_shared<parserFSM::MessageHelper>(ownerServicePtr);
M module-services/service-desktop/parser/MessageHandler.cpp => module-services/service-desktop/parser/MessageHandler.cpp +8 -8
@@ 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 "MessageHandler.hpp"
@@ 35,18 35,18 @@ MessageHandler::MessageHandler(const std::string &message, sys::Service *OwnerSe
void MessageHandler::processMessage()
{
- Context context(messageJson);
+ auto context = ContextFactory::create(messageJson);
LOG_DEBUG("[MsgHandler]\nmethod: %d\nendpoint: %d\nuuid: %" PRIu32 "\nbody: %s\n",
- static_cast<int>(context.getMethod()),
- static_cast<int>(context.getEndpoint()),
- context.getUuid(),
- context.getBody().dump().c_str());
+ static_cast<int>(context->getMethod()),
+ static_cast<int>(context->getEndpoint()),
+ context->getUuid(),
+ context->getBody().dump().c_str());
- auto handler = EndpointFactory::create(context, OwnerServicePtr);
+ auto handler = EndpointFactory::create(*context, OwnerServicePtr);
if (handler != nullptr) {
- handler->handle(context);
+ handler->handle(*context);
}
else {
LOG_ERROR("No way to handle!");
M module-services/service-desktop/parser/ParserUtils.cpp => module-services/service-desktop/parser/ParserUtils.cpp +13 -11
@@ 5,16 5,18 @@
#include <log/log.hpp>
-using namespace parserFSM;
-
-bool http::isMethodValid(uint8_t method)
+namespace parserFSM
{
- if (method == static_cast<uint8_t>(http::Method::get) || method == static_cast<uint8_t>(http::Method::post) ||
- method == static_cast<uint8_t>(http::Method::put) || method == static_cast<uint8_t>(http::Method::del)) {
- return true;
- }
- else {
- LOG_ERROR("Invalid method!");
- return false;
+
+ bool http::isMethodValid(uint8_t method)
+ {
+ if (method == static_cast<uint8_t>(http::Method::get) || method == static_cast<uint8_t>(http::Method::post) ||
+ method == static_cast<uint8_t>(http::Method::put) || method == static_cast<uint8_t>(http::Method::del)) {
+ return true;
+ }
+ else {
+ LOG_ERROR("Invalid method!");
+ return false;
+ }
}
-}
+} // namespace parserFSM
M module-services/service-desktop/parser/ParserUtils.hpp => module-services/service-desktop/parser/ParserUtils.hpp +37 -27
@@ 45,7 45,7 @@ namespace parserFSM
msg.erase(msg.begin(), msg.begin() + size_header);
}
- inline unsigned long calcPayloadLength(const std::string header)
+ inline unsigned long calcPayloadLength(const std::string &header)
{
try {
return std::stol(header.substr(1, std::string::npos));
@@ 67,10 67,12 @@ namespace parserFSM
}
inline std::string extractPayload(std::string &msg, size_t payloadLength)
{
- if (msg.size() > payloadLength)
+ if (msg.size() > payloadLength) {
return msg.substr(0, payloadLength);
- else
+ }
+ else {
return msg;
+ }
}
} // namespace message
@@ 140,9 142,9 @@ namespace parserFSM
inline constexpr auto command = "command";
namespace commands
{
- inline constexpr auto upload = "upload";
- inline constexpr auto rm = "rm";
- inline constexpr auto download = "download";
+ inline constexpr auto upload = "upload";
+ inline constexpr auto rm = "rm";
+ inline constexpr auto download = "download";
inline constexpr auto checkFile = "checkFile";
} // namespace commands
} // namespace filesystem
@@ 159,27 161,35 @@ namespace parserFSM
namespace messages
{
- inline constexpr auto id = "id";
- inline constexpr auto count = "count";
- inline constexpr auto offset = "offset";
- inline constexpr auto phoneNumber = "phoneNumber";
- inline constexpr auto messageBody = "messageBody";
- inline constexpr auto isUnread = "unread";
- inline constexpr auto contactID = "contactID";
- inline constexpr auto date = "date";
- inline constexpr auto dateSent = "dateSent";
- inline constexpr auto type = "type";
- inline constexpr auto threadID = "threadID";
- inline constexpr auto msgTemplate = "template";
- inline constexpr auto templateText = "text";
- namespace thread
- {
- inline constexpr auto msgCount = "msgCount";
- inline constexpr auto snippet = "snippet";
- inline constexpr auto unreadMsgCount = "unreadMsgCount";
-
- } // namespace thread
-
+ inline constexpr auto count = "count";
+ inline constexpr auto category = "category";
+ inline constexpr auto categoryMessage = "message";
+ inline constexpr auto categoryThread = "thread";
+ inline constexpr auto categoryTemplate = "template";
+
+ inline constexpr auto limit = "limit";
+ inline constexpr auto offset = "offset";
+ inline constexpr auto totalCount = "totalCount";
+ inline constexpr auto nextPage = "nextPage";
+ inline constexpr auto entries = "entries";
+ inline constexpr auto messageBody = "messageBody";
+ inline constexpr auto messageCount = "messageCount";
+ inline constexpr auto messageID = "messageID";
+ inline constexpr auto messageType = "messageType";
+ inline constexpr auto phoneNumber = "phoneNumber";
+ inline constexpr auto receivedAt = "receivedAt";
+ inline constexpr auto sentAt = "sentAt";
+ inline constexpr auto lastUsedAt = "lastUsedAt";
+ inline constexpr auto lastUpdatedAt = "lastUpdatedAt";
+ inline constexpr auto isUnread = "isUnread";
+ inline constexpr auto contactID = "contactID";
+ inline constexpr auto numberID = "numberID";
+ inline constexpr auto threadID = "threadID";
+ inline constexpr auto messageSnippet = "messageSnippet";
+ inline constexpr auto unreadMessageCount = "unreadMessageCount";
+ inline constexpr auto messageTemplate = "messageTemplate";
+ inline constexpr auto templateBody = "templateBody";
+ inline constexpr auto templateID = "templateID";
} // namespace messages
} // namespace json
M module-services/service-desktop/tests/CMakeLists.txt => module-services/service-desktop/tests/CMakeLists.txt +14 -0
@@ 15,3 15,17 @@ add_catch2_executable(
DEPS
PurePhone.img-target
)
+
+add_catch2_executable(
+ NAME
+ service-desktop-endpoint-contacts
+ SRCS
+ tests-main.cpp
+ test-contacts.cpp
+ LIBS
+ service-desktop
+ module-utils
+ module-apps
+ module-vfs
+ iosyscalls
+)
A module-services/service-desktop/tests/test-contacts.cpp => module-services/service-desktop/tests/test-contacts.cpp +204 -0
@@ 0,0 1,204 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include <endpoints/Endpoint.hpp>
+#include <endpoints/EndpointFactory.hpp>
+
+#include <catch2/catch.hpp>
+#include <json/json11.hpp>
+#include <purefs/filesystem_paths.hpp>
+#include <utf8/UTF8.hpp>
+#include <vfs.hpp>
+
+#include <memory>
+#include <filesystem>
+#include <string>
+#include <vector>
+
+#include <module-db/Interface/ContactRecord.hpp>
+#include <module-db/Databases/ContactsDB.hpp>
+
+class vfs vfs;
+std::unique_ptr<ContactsDB> contactsDb = nullptr;
+std::vector<std::string> messageStrings;
+
+// stubs
+std::pair<bool, std::uint64_t> DBServiceAPI::GetQuery(sys::Service *serv,
+ db::Interface::Name database,
+ std::unique_ptr<db::Query> query)
+{
+ auto queryType = query->type;
+ LOG_DEBUG("query is: %d", static_cast<uint32_t>(queryType));
+
+ ContactRecordInterface cri(contactsDb.get());
+ auto result = cri.runQuery(std::move(query));
+ auto queryListener = result->getRequestQuery()->getQueryListener();
+ queryListener->handleQueryResponse(result.get());
+
+ return std::make_pair(true, 0);
+}
+auto DBServiceAPI::ThreadGetByNumber(sys::Service *serv,
+ const utils::PhoneNumber::View &phoneNumber,
+ std::uint32_t timeout) -> std::unique_ptr<ThreadRecord>
+{
+ return nullptr;
+}
+auto DBServiceAPI::ThreadGetCount(sys::Service *serv, EntryState state) -> uint32_t
+{
+ return 0;
+}
+
+auto DBServiceAPI::GetQueryWithReply(sys::Service *serv,
+ db::Interface::Name database,
+ std::unique_ptr<db::Query> query,
+ std::uint32_t timeout) -> sys::SendResult
+{
+ return {};
+}
+
+auto DBServiceAPI::verifyContact(sys::Service *serv, const ContactRecord &rec) -> ContactVerificationResult
+{
+ return {};
+}
+auto DBServiceAPI::ContactGetByID(sys::Service *serv, uint32_t contactID) -> std::unique_ptr<std::vector<ContactRecord>>
+{
+ return nullptr;
+}
+auto DBServiceAPI::ContactGetByIDWithTemporary(sys::Service *serv, uint32_t contactID)
+ -> std::unique_ptr<std::vector<ContactRecord>>
+{
+ return nullptr;
+}
+auto DBServiceAPI::ContactGetByIDCommon(sys::Service *serv, std::shared_ptr<DBContactMessage> contactMsg)
+ -> std::unique_ptr<std::vector<ContactRecord>>
+{
+ return nullptr;
+}
+auto DBServiceAPI::ContactGetBySpeeddial(sys::Service *serv, UTF8 speeddial)
+ -> std::unique_ptr<std::vector<ContactRecord>>
+{
+ return nullptr;
+}
+auto DBServiceAPI::ContactGetByPhoneNumber(sys::Service *serv, UTF8 phoneNumber)
+ -> std::unique_ptr<std::vector<ContactRecord>>
+{
+ return nullptr;
+}
+auto DBServiceAPI::MatchContactByPhoneNumber(sys::Service *serv, const utils::PhoneNumber::View &numberView)
+ -> std::unique_ptr<ContactRecord>
+{
+ return nullptr;
+}
+auto DBServiceAPI::ContactAdd(sys::Service *serv, const ContactRecord &rec) -> bool
+{
+ return false;
+}
+auto DBServiceAPI::ContactRemove(sys::Service *serv, uint32_t id) -> bool
+{
+ return false;
+}
+auto DBServiceAPI::ContactUpdate(sys::Service *serv, const ContactRecord &rec) -> bool
+{
+ return false;
+}
+auto DBServiceAPI::ContactSearch(sys::Service *serv, UTF8 primaryName, UTF8 alternativeName, UTF8 number)
+ -> std::unique_ptr<std::vector<ContactRecord>>
+{
+ return nullptr;
+}
+auto DBServiceAPI::CalllogAdd(sys::Service *serv, const CalllogRecord &rec) -> CalllogRecord
+{
+ return {};
+}
+auto DBServiceAPI::CalllogRemove(sys::Service *serv, uint32_t id) -> bool
+{
+ return false;
+}
+auto DBServiceAPI::CalllogUpdate(sys::Service *serv, const CalllogRecord &rec) -> bool
+{
+ return false;
+}
+auto DBServiceAPI::CalllogGetCount(sys::Service *serv, EntryState state) -> uint32_t
+{
+ return 0;
+}
+auto DBServiceAPI::CalllogGetLimitOffset(sys::Service *serv, uint32_t offset, uint32_t limit) -> bool
+{
+ return false;
+}
+auto DBServiceAPI::GetCountryCodeByMCC(sys::Service *serv, uint32_t mcc) -> uint32_t
+{
+ return 0;
+}
+auto DBServiceAPI::DBBackup(sys::Service *serv, std::string backupPath) -> bool
+{
+ return false;
+}
+bool DBServiceAPI::AddSMS(sys::Service *serv, const SMSRecord &record, std::unique_ptr<db::QueryListener> &&listener)
+{
+ return false;
+}
+
+xQueueHandle parserFSM::MessageHandler::sendQueue;
+parserFSM::MessageHandler::MessageHandler(const std::string &message, sys::Service *OwnerService)
+ : OwnerServicePtr(OwnerService)
+{}
+void parserFSM::MessageHandler::processMessage()
+{}
+void parserFSM::MessageHandler::putToSendQueue(const std::string &msg)
+{
+ messageStrings.push_back(msg);
+ LOG_DEBUG("response is: %s", msg.c_str());
+}
+//~stubs
+
+TEST_CASE("Endpoint Contacts Test")
+{
+ vfs.Init();
+ Database::initialize();
+
+ const auto contactsPath = purefs::dir::getUserDiskPath() / "contacts.db";
+ std::filesystem::remove(contactsPath);
+
+ contactsDb = std::make_unique<ContactsDB>(contactsPath.c_str());
+ REQUIRE(contactsDb->isInitialized());
+ messageStrings.clear();
+
+ SECTION("Request with pages")
+ {
+ auto count = 29; // requested number of record to return
+ auto endpoint = 7;
+ auto uuid = "1103";
+ auto totalCount = contactsDb->contacts.count();
+ auto testMessage = "{\"endpoint\":" + std::to_string(endpoint) + ", \"method\":1, \"uuid\":" + uuid +
+ ", \"body\":{\"limit\":" + std::to_string(count) + ", \"offset\":20}}";
+ std::string err;
+ auto msgJson = json11::Json::parse(testMessage, err);
+ REQUIRE(err.empty());
+
+ parserFSM::PagedContext context(msgJson, 10);
+ auto handler = EndpointFactory::create(context, nullptr);
+ handler->handle(context);
+ auto pageSize = context.getPageSize();
+ REQUIRE(10 == pageSize);
+ REQUIRE(1 == messageStrings.size());
+ auto msg = messageStrings[0];
+ REQUIRE(msg.size() > 10);
+ auto retJson = json11::Json::parse(msg.substr(10), err); // string length and go to real data
+
+ REQUIRE(err.empty());
+ REQUIRE(uuid == retJson[parserFSM::json::uuid].string_value());
+ REQUIRE(endpoint == retJson[parserFSM::json::endpoint].int_value());
+
+ auto body = retJson[parserFSM::json::body];
+ REQUIRE(totalCount == static_cast<uint32_t>(body[parserFSM::json::totalCount].int_value()));
+
+ auto nextPage = body[parserFSM::json::nextPage];
+ REQUIRE(static_cast<int>(pageSize) == nextPage[parserFSM::json::limit].int_value());
+ // base offset + pageSize cause asked for 29
+ REQUIRE(30 == nextPage[parserFSM::json::offset].int_value());
+
+ auto entries = body[parserFSM::json::entries];
+ REQUIRE(pageSize == entries.array_items().size());
+ }
+}
M module-services/service-desktop/tests/unittest.cpp => module-services/service-desktop/tests/unittest.cpp +7 -7
@@ 209,24 209,24 @@ TEST_CASE("DB Helpers test - json encoding (messages)")
message->ID = 10;
message->type = SMSType::DRAFT;
- auto messageJson = helper->to_json(*message);
+ auto messageJson = helper->toJson(*message);
REQUIRE(messageJson[json::messages::messageBody] == "test message");
REQUIRE(messageJson[json::messages::contactID] == 1);
- REQUIRE(messageJson[json::messages::date] == 12345);
- REQUIRE(messageJson[json::messages::dateSent] == 54321);
+ REQUIRE(messageJson[json::messages::receivedAt] == 12345);
+ REQUIRE(messageJson[json::messages::sentAt] == 54321);
REQUIRE(messageJson[json::messages::threadID] == 1);
- REQUIRE(messageJson[json::messages::id] == 10);
+ REQUIRE(messageJson[json::messages::messageID] == 10);
auto messageTemplate = std::make_unique<SMSTemplateRecord>();
messageTemplate->text = "test template";
messageTemplate->ID = 1;
- auto messageTemplateJson = helper->to_json(*messageTemplate);
+ auto messageTemplateJson = helper->toJson(*messageTemplate);
- REQUIRE(messageTemplateJson[json::messages::templateText] == "test template");
- REQUIRE(messageTemplateJson[json::messages::id] == 1);
+ REQUIRE(messageTemplateJson[json::messages::templateBody] == "test template");
+ REQUIRE(messageTemplateJson[json::messages::templateID] == 1);
}
TEST_CASE("Context class test")
M module-services/service-evtmgr/EventManager.cpp => module-services/service-evtmgr/EventManager.cpp +32 -31
@@ 39,9 39,12 @@
#include <vector>
#include <module-apps/messages/AppMessage.hpp>
#include <SystemManager/messages/CpuFrequencyMessage.hpp>
+#include <common_data/EventStore.hpp>
+#include <SystemManager/messages/PhoneModeRequest.hpp>
EventManager::EventManager(const std::string &name)
- : sys::Service(name), screenLightControl(std::make_unique<screen_light_control::ScreenLightControl>(this))
+ : sys::Service(name), settings(std::make_shared<settings::Settings>(this)),
+ screenLightControl(std::make_unique<screen_light_control::ScreenLightControl>(settings, this))
{
LOG_INFO("[%s] Initializing", name.c_str());
alarmTimestamp = 0;
@@ 101,9 104,16 @@ sys::MessagePointer EventManager::DataReceivedHandler(sys::DataMessage *msgl, sy
auto message = std::make_shared<sevm::KbdMessage>();
message->key = msg->key;
- if (message->key.state == RawKey::State::Pressed && message->key.key_code == bsp::KeyCodes::FnRight) {
- // and state == ShutDown
- bus.sendUnicast(message, service::name::system_manager);
+ if (message->key.state == RawKey::State::Pressed) {
+ const auto code = message->key.key_code;
+ if (code == bsp::KeyCodes::FnRight) {
+ bus.sendUnicast(message, service::name::system_manager);
+ }
+ else if (code == bsp::KeyCodes::SSwitchUp || code == bsp::KeyCodes::SSwitchMid ||
+ code == bsp::KeyCodes::SSwitchDown) {
+ const auto mode = sys::SystemManager::translateSliderState(message->key);
+ bus.sendUnicast(std::make_shared<sys::PhoneModeRequest>(mode), service::name::system_manager);
+ }
}
// send key to focused application
@@ 122,32 132,6 @@ sys::MessagePointer EventManager::DataReceivedHandler(sys::DataMessage *msgl, sy
LOG_INFO("Switching focus to %s", targetApplication.c_str());
}
}
- else if (msgl->messageType == MessageType::EVMBatteryLevel && msgl->sender == this->GetName()) {
- auto *msg = static_cast<sevm::BatteryLevelMessage *>(msgl);
-
- auto message = std::make_shared<sevm::BatteryLevelMessage>(msg->levelPercents, msg->fullyCharged);
-
- if (!targetApplication.empty()) {
- bus.sendUnicast(message, targetApplication);
- }
-
- handled = true;
- }
- else if (msgl->messageType == MessageType::EVMChargerPlugged && msgl->sender == this->GetName()) {
- auto *msg = static_cast<sevm::BatteryPlugMessage *>(msgl);
-
- auto message = std::make_shared<sevm::BatteryPlugMessage>();
- message->plugged = msg->plugged;
-
- if (!message->plugged) {
- bus.sendUnicast(message, service::name::system_manager);
- }
-
- if (!targetApplication.empty()) {
- bus.sendUnicast(message, targetApplication);
- }
- handled = true;
- }
else if (msgl->messageType == MessageType::EVMMinuteUpdated && msgl->sender == this->GetName()) {
HandleAlarmTrigger(msgl);
@@ 287,6 271,23 @@ sys::ReturnCodes EventManager::InitHandler()
return msg;
});
+ connect(sevm::BatteryStatusChangeMessage(), [&](sys::Message *msgl) {
+ if (msgl->sender == this->GetName()) {
+ LOG_INFO("Battery level: %d , charging: %d",
+ Store::Battery::get().level,
+ Store::Battery::get().state == Store::Battery::State::Charging);
+
+ if (Store::Battery::get().state == Store::Battery::State::Discharging) {
+ bus.sendUnicast(std::make_shared<sevm::BatteryStatusChangeMessage>(), service::name::system_manager);
+ }
+
+ if (!targetApplication.empty()) {
+ bus.sendUnicast(std::make_shared<sevm::BatteryStatusChangeMessage>(), targetApplication);
+ }
+ }
+ return std::make_shared<sys::ResponseMessage>();
+ });
+
// initialize keyboard worker
EventWorker = std::make_unique<WorkerEvent>(this);
@@ 322,7 323,7 @@ sys::ReturnCodes EventManager::InitHandler()
list.push_back(qLightSensor);
list.push_back(qChargerDetect);
- EventWorker->init(list);
+ EventWorker->init(list, settings);
EventWorker->run();
return sys::ReturnCodes::Success;
M module-services/service-evtmgr/WorkerEvent.cpp => module-services/service-evtmgr/WorkerEvent.cpp +14 -8
@@ 93,8 93,8 @@ bool WorkerEvent::handleMessage(uint32_t queueID)
if (notification == static_cast<std::uint8_t>(bsp::battery_charger::batteryIRQSource::INTB)) {
auto topINT = bsp::battery_charger::getTopControllerINTSource();
if (topINT & static_cast<std::uint8_t>(bsp::battery_charger::topControllerIRQsource::CHGR_INT)) {
- auto message = std::make_shared<sevm::BatteryPlugMessage>();
- message->plugged = bsp::battery_charger::getChargeStatus();
+ bsp::battery_charger::getChargeStatus();
+ auto message = std::make_shared<sevm::BatteryStatusChangeMessage>();
service->bus.sendUnicast(std::move(message), service::name::evt_manager);
bsp::battery_charger::clearAllChargerIRQs();
}
@@ 107,8 107,8 @@ bool WorkerEvent::handleMessage(uint32_t queueID)
if (status & static_cast<std::uint16_t>(bsp::battery_charger::batteryINTBSource::SOCOnePercentChange)) {
bsp::battery_charger::clearFuelGuageIRQ(
static_cast<std::uint16_t>(bsp::battery_charger::batteryINTBSource::SOCOnePercentChange));
- bsp::battery_charger::StateOfCharge battLevel = bsp::battery_charger::getBatteryLevel();
- auto message = std::make_shared<sevm::BatteryLevelMessage>(battLevel, false);
+ bsp::battery_charger::getBatteryLevel();
+ auto message = std::make_shared<sevm::BatteryStatusChangeMessage>();
service->bus.sendUnicast(std::move(message), service::name::evt_manager);
battery_level_check::checkBatteryLevelCritical();
}
@@ 118,8 118,8 @@ bool WorkerEvent::handleMessage(uint32_t queueID)
static_cast<std::uint16_t>(bsp::battery_charger::batteryINTBSource::maxTemp) |
static_cast<std::uint16_t>(bsp::battery_charger::batteryINTBSource::minTemp));
bsp::battery_charger::checkTemperatureRange();
- auto message = std::make_shared<sevm::BatteryPlugMessage>();
- message->plugged = bsp::battery_charger::getChargeStatus();
+ bsp::battery_charger::getChargeStatus();
+ auto message = std::make_shared<sevm::BatteryStatusChangeMessage>();
service->bus.sendUnicast(std::move(message), service::name::evt_manager);
}
}
@@ 225,11 225,15 @@ bool WorkerEvent::init(std::list<sys::WorkerQueueInfo> queuesList)
bsp::rtc_GetCurrentTimestamp(×tamp);
bsp::rtc_SetMinuteAlarm(timestamp);
- battery_level_check::init(service);
-
return true;
}
+void WorkerEvent::init(std::list<sys::WorkerQueueInfo> queuesList, std::shared_ptr<settings::Settings> settings)
+{
+ init(queuesList);
+ battery_level_check::init(service, settings);
+}
+
bool WorkerEvent::deinit(void)
{
Worker::deinit();
@@ 241,6 245,8 @@ bool WorkerEvent::deinit(void)
bsp::eink_frontlight::deinit();
bsp::light_sensor::deinit();
+ battery_level_check::deinit();
+
return true;
}
M module-services/service-evtmgr/battery-level-check/BatteryLevelCheck.cpp => module-services/service-evtmgr/battery-level-check/BatteryLevelCheck.cpp +19 -5
@@ 4,8 4,9 @@
#include "BatteryLevelCheck.hpp"
#include "service-evtmgr/BatteryMessages.hpp"
#include "SystemManager/Constants.hpp"
-
+#include <agents/settings/SystemSettings.hpp>
#include <common_data/EventStore.hpp>
+#include <Utils.hpp>
namespace battery_level_check
{
@@ 20,12 21,12 @@ namespace battery_level_check
CheckState state = CheckState::InitialCheck;
- constexpr inline auto DEFAULT_LEVEL = 10;
-
- unsigned int batteryLevelCritical = DEFAULT_LEVEL;
+ unsigned int batteryLevelCritical = 0;
sys::Service *parentService = nullptr;
+ std::shared_ptr<settings::Settings> settings = nullptr;
+
bool isBatteryLevelCritical(unsigned int level)
{
return level < batteryLevelCritical;
@@ 44,9 45,20 @@ namespace battery_level_check
}
} // namespace
- void init(sys::Service *service)
+ void init(sys::Service *service, std::shared_ptr<settings::Settings> &setts)
{
parentService = service;
+ settings = setts;
+ settings->registerValueChange(
+ settings::Battery::batteryCriticalLevel,
+ [&](const std::string &value) { batteryLevelCritical = utils::getNumericValue<unsigned int>(value); },
+ settings::SettingsScope::Global);
+ }
+
+ void deinit()
+ {
+ settings->unregisterValueChange(settings::Battery::batteryCriticalLevel, settings::SettingsScope::Global);
+ settings.reset();
}
void checkBatteryLevelCritical()
@@ 86,6 98,8 @@ namespace battery_level_check
void setBatteryCriticalLevel(unsigned int level)
{
batteryLevelCritical = level;
+ settings->setValue(
+ settings::Battery::batteryCriticalLevel, utils::to_string(level), settings::SettingsScope::Global);
checkBatteryLevelCritical();
}
M module-services/service-evtmgr/battery-level-check/BatteryLevelCheck.hpp => module-services/service-evtmgr/battery-level-check/BatteryLevelCheck.hpp +4 -1
@@ 4,6 4,7 @@
#pragma once
#include <Service/Service.hpp>
+#include <service-db/service-db/Settings.hpp>
namespace sys
{
@@ 12,7 13,9 @@ namespace sys
namespace battery_level_check
{
- void init(sys::Service *service);
+ void init(sys::Service *service, std::shared_ptr<settings::Settings> &setts);
+
+ void deinit();
void checkBatteryLevelCritical();
A module-services/service-evtmgr/doc/battery_status_notification.md => module-services/service-evtmgr/doc/battery_status_notification.md +4 -0
@@ 0,0 1,4 @@
+# Battery Status propagation in system
+
+Battery status information is propagated according to following diagram:
+<
\ No newline at end of file
A module-services/service-evtmgr/doc/battery_status_notification.puml => module-services/service-evtmgr/doc/battery_status_notification.puml +24 -0
@@ 0,0 1,24 @@
+@startuml
+participant "Battery Charger" as bc
+participant "Worker Event" as we
+participant "Event Manager" as evm
+participant "System Manager" as sm
+participant "Current application" as ca
+participant "TopBar" as tb
+participant "Battery Widget" as bw
+participant "Event Store\nBattery" as es
+
+bc -> we : Interrupt
+we -> bc : Store status to EventStore
+bc -> es : modify()
+we -> evm : BatteryStatusChangeMessage
+group If Discharging
+ evm -> sm : BatteryStatusChangeMessage
+ sm -> sm : If State::ShutdownReady:\n state = State:Shutdown
+end
+evm -> ca : BatteryStatusChangeMessage
+ca -> tb : updateBattery()
+tb <-> es : get()
+tb -> bw : show(batteryContext)
+
+@enduml
A module-services/service-evtmgr/doc/battery_status_notification.svg => module-services/service-evtmgr/doc/battery_status_notification.svg +34 -0
@@ 0,0 1,34 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="486px" preserveAspectRatio="none" style="width:1340px;height:486px;" version="1.1" viewBox="0 0 1340 486" width="1340px" zoomAndPan="magnify"><defs><filter height="300%" id="f1uj3fz6xy4wx1" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><rect fill="#FFFFFF" filter="url(#f1uj3fz6xy4wx1)" height="103.5313" style="stroke:#000000;stroke-width:2.0;" width="468.5" x="411.5" y="190.125"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="68" x2="68" y1="56.5938" y2="427.1875"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="263" x2="263" y1="56.5938" y2="427.1875"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="481.5" x2="481.5" y1="56.5938" y2="427.1875"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="700.5" x2="700.5" y1="56.5938" y2="427.1875"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="875" x2="875" y1="56.5938" y2="427.1875"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="1001" x2="1001" y1="56.5938" y2="427.1875"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="1162.5" x2="1162.5" y1="56.5938" y2="427.1875"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="1281.5" x2="1281.5" y1="56.5938" y2="427.1875"/><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="122" x="5" y="21.2969"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="108" x="12" y="41.292">Battery Charger</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="122" x="5" y="426.1875"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="108" x="12" y="446.1826">Battery Charger</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="106" x="208" y="21.2969"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="92" x="215" y="41.292">Worker Event</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="106" x="208" y="426.1875"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="92" x="215" y="446.1826">Worker Event</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="117" x="421.5" y="21.2969"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="103" x="428.5" y="41.292">Event Manager</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="117" x="421.5" y="426.1875"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="103" x="428.5" y="446.1826">Event Manager</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="129" x="634.5" y="21.2969"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="115" x="641.5" y="41.292">System Manager</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="129" x="634.5" y="426.1875"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="115" x="641.5" y="446.1826">System Manager</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="144" x="801" y="21.2969"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="130" x="808" y="41.292">Current application</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="144" x="801" y="426.1875"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="130" x="808" y="446.1826">Current application</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="64" x="967" y="21.2969"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="50" x="974" y="41.292">TopBar</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="64" x="967" y="426.1875"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="50" x="974" y="446.1826">TopBar</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="115" x="1103.5" y="21.2969"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="101" x="1110.5" y="41.292">Battery Widget</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="115" x="1103.5" y="426.1875"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="101" x="1110.5" y="446.1826">Battery Widget</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="46.5938" style="stroke:#A80036;stroke-width:1.5;" width="94" x="1232.5" y="5"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="80" x="1239.5" y="24.9951">Event Store</text><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="49" x="1255" y="41.292">Battery</text><rect fill="#FEFECE" filter="url(#f1uj3fz6xy4wx1)" height="46.5938" style="stroke:#A80036;stroke-width:1.5;" width="94" x="1232.5" y="426.1875"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="80" x="1239.5" y="446.1826">Event Store</text><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="49" x="1255" y="462.4795">Battery</text><polygon fill="#A80036" points="251,83.7266,261,87.7266,251,91.7266,255,87.7266" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="68" x2="257" y1="87.7266" y2="87.7266"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="55" x="75" y="82.6606">Interrupt</text><polygon fill="#A80036" points="79,112.8594,69,116.8594,79,120.8594,75,116.8594" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="73" x2="262" y1="116.8594" y2="116.8594"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="171" x="85" y="111.7935">Store status to EventStore</text><polygon fill="#A80036" points="1269.5,141.9922,1279.5,145.9922,1269.5,149.9922,1273.5,145.9922" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="68" x2="1275.5" y1="145.9922" y2="145.9922"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="53" x="75" y="140.9263">modify()</text><polygon fill="#A80036" points="470,171.125,480,175.125,470,179.125,474,175.125" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="263" x2="476" y1="175.125" y2="175.125"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="195" x="270" y="170.0591">BatteryStatusChangeMessage</text><path d="M411.5,190.125 L559.5,190.125 L559.5,197.125 L549.5,207.125 L411.5,207.125 L411.5,190.125 " fill="#EEEEEE" style="stroke:#000000;stroke-width:1.0;"/><rect fill="none" height="103.5313" style="stroke:#000000;stroke-width:2.0;" width="468.5" x="411.5" y="190.125"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacing" textLength="103" x="426.5" y="203.1919">If Discharging</text><polygon fill="#A80036" points="689,224.3906,699,228.3906,689,232.3906,693,228.3906" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="482" x2="695" y1="228.3906" y2="228.3906"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="195" x="489" y="223.3247">BatteryStatusChangeMessage</text><line style="stroke:#A80036;stroke-width:1.0;" x1="701" x2="743" y1="272.6563" y2="272.6563"/><line style="stroke:#A80036;stroke-width:1.0;" x1="743" x2="743" y1="272.6563" y2="285.6563"/><line style="stroke:#A80036;stroke-width:1.0;" x1="702" x2="743" y1="285.6563" y2="285.6563"/><polygon fill="#A80036" points="712,281.6563,702,285.6563,712,289.6563,708,285.6563" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="160" x="708" y="252.4575">If State::ShutdownReady:</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="154" x="712" y="267.5903">state = State:Shutdown</text><polygon fill="#A80036" points="863,317.7891,873,321.7891,863,325.7891,867,321.7891" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="482" x2="869" y1="321.7891" y2="321.7891"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="195" x="489" y="316.7231">BatteryStatusChangeMessage</text><polygon fill="#A80036" points="989,346.9219,999,350.9219,989,354.9219,993,350.9219" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="875" x2="995" y1="350.9219" y2="350.9219"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="102" x="882" y="345.856">updateBattery()</text><polygon fill="#A80036" points="1012,376.0547,1002,380.0547,1012,384.0547,1008,380.0547" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="1269.5,376.0547,1279.5,380.0547,1269.5,384.0547,1273.5,380.0547" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="1006" x2="1275.5" y1="380.0547" y2="380.0547"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="31" x="1018" y="374.9888">get()</text><polygon fill="#A80036" points="1151,405.1875,1161,409.1875,1151,413.1875,1155,409.1875" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="1001" x2="1157" y1="409.1875" y2="409.1875"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="138" x="1008" y="404.1216">show(batteryContext)</text><!--MD5=[c6c243b94a88456e8572e27fdc18c06d]
+@startuml
+participant "Battery Charger" as bc
+participant "Worker Event" as we
+participant "Event Manager" as evm
+participant "System Manager" as sm
+participant "Current application" as ca
+participant "TopBar" as tb
+participant "Battery Widget" as bw
+participant "Event Store\nBattery" as es
+
+bc -> we : Interrupt
+we -> bc : Store status to EventStore
+bc -> es : modify()
+we -> evm : BatteryStatusChangeMessage
+group If Discharging
+ evm -> sm : BatteryStatusChangeMessage
+ sm -> sm : If State::ShutdownReady:\n state = State:Shutdown
+end
+evm -> ca : BatteryStatusChangeMessage
+ca -> tb : updateBattery()
+tb <-> es : get()
+tb -> bw : show(batteryContext)
+
+@enduml
+
+PlantUML version 1.2021.00(Sun Jan 10 11:25:05 CET 2021)
+(GPL source distribution)
+Java Runtime: OpenJDK Runtime Environment
+JVM: OpenJDK 64-Bit Server VM
+Default Encoding: UTF-8
+Language: pl
+Country: PL
+--></g></svg><
\ No newline at end of file
M module-services/service-evtmgr/screen-light-control/ScreenLightControl.cpp => module-services/service-evtmgr/screen-light-control/ScreenLightControl.cpp +2 -2
@@ 33,8 33,8 @@ namespace screen_light_control
}
} // namespace
- ScreenLightControl::ScreenLightControl(sys::Service *parent)
- : settings(std::make_unique<settings::Settings>(parent))
+ ScreenLightControl::ScreenLightControl(std::shared_ptr<settings::Settings> settings, sys::Service *parent)
+ : settings(settings)
{
controlTimer = std::make_unique<sys::Timer>("LightControlTimer", parent, CONTROL_TIMER_MS);
readoutTimer = std::make_unique<sys::Timer>("LightSensorReadoutTimer", parent, READOUT_TIMER_MS);
M module-services/service-evtmgr/screen-light-control/ScreenLightControl.hpp => module-services/service-evtmgr/screen-light-control/ScreenLightControl.hpp +2 -2
@@ 56,7 56,7 @@ namespace screen_light_control
class ScreenLightControl
{
public:
- explicit ScreenLightControl(sys::Service *parent);
+ explicit ScreenLightControl(std::shared_ptr<settings::Settings> settings, sys::Service *parent);
~ScreenLightControl();
void processRequest(Action action, const Parameters ¶ms);
@@ 98,7 98,7 @@ namespace screen_light_control
screen_light_control::ScreenLightMode automaticMode = ScreenLightMode::Manual;
bsp::eink_frontlight::BrightnessPercentage brightnessValue = 0.0;
- std::unique_ptr<settings::Settings> settings;
+ std::shared_ptr<settings::Settings> settings;
};
} // namespace screen_light_control
M module-services/service-evtmgr/service-evtmgr/BatteryMessages.hpp => module-services/service-evtmgr/service-evtmgr/BatteryMessages.hpp +2 -20
@@ 9,27 9,9 @@
namespace sevm
{
- class BatteryLevelMessage : public Message
- {
- public:
- BatteryLevelMessage(uint8_t levelPercents, bool fullyCharged)
- : Message(MessageType::EVMBatteryLevel), levelPercents(levelPercents), fullyCharged(fullyCharged)
- {
- type = Type::Data;
- }
- uint8_t levelPercents = 0;
- bool fullyCharged = false;
- };
+ class BatteryStatusChangeMessage : public sys::Message
+ {};
- class BatteryPlugMessage : public Message
- {
- public:
- BatteryPlugMessage() : Message(MessageType::EVMChargerPlugged)
- {
- type = Type::Data;
- }
- bool plugged = false;
- };
class BatterySetCriticalLevel : public sys::Message
{
public:
M module-services/service-evtmgr/service-evtmgr/EventManager.hpp => module-services/service-evtmgr/service-evtmgr/EventManager.hpp +2 -0
@@ 31,6 31,8 @@ class EventManager : public sys::Service
void GetNextAlarmTimestamp(time_t timestamp);
bool processKeypadBacklightRequest(bsp::keypad_backlight::Action act);
+ std::shared_ptr<settings::Settings> settings;
+
protected:
std::unique_ptr<WorkerEvent> EventWorker;
// application where key events are sent. This is also only application that is allowed to change keyboard long
M module-services/service-evtmgr/service-evtmgr/WorkerEvent.hpp => module-services/service-evtmgr/service-evtmgr/WorkerEvent.hpp +2 -0
@@ 70,6 70,8 @@ class WorkerEvent : public sys::Worker
virtual bool init(std::list<sys::WorkerQueueInfo> queuesList) override;
virtual bool deinit() override;
+ void init(std::list<sys::WorkerQueueInfo> queuesList, std::shared_ptr<settings::Settings> settings);
+
/**
* This method is called from thread when new message arrives in queue.
* @param queueID Index of the queue in the queues vector.
M module-sys/CMakeLists.txt => module-sys/CMakeLists.txt +2 -0
@@ 14,6 14,8 @@ set(SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/Service/Service.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Service/Timer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Service/CpuSentinel.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/PhoneModes/Subject.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/PhoneModes/Observer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/SystemManager/SystemManager.cpp
${CMAKE_CURRENT_SOURCE_DIR}/SystemManager/DependencyGraph.cpp
${CMAKE_CURRENT_SOURCE_DIR}/SystemManager/PowerManager.cpp
A module-sys/PhoneModes/Common.hpp => module-sys/PhoneModes/Common.hpp +49 -0
@@ 0,0 1,49 @@
+// 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 <Service/Message.hpp>
+
+namespace sys::phone_modes
+{
+ enum class PhoneMode
+ {
+ Connected,
+ DoNotDisturb,
+ Offline
+ };
+
+ enum class Tethering
+ {
+ Off,
+ On
+ };
+
+ class PhoneModeChanged : public DataMessage
+ {
+ public:
+ PhoneModeChanged(PhoneMode phoneMode, Tethering tetheringMode)
+ : DataMessage{MessageType::MessageTypeUninitialized}, phoneMode{phoneMode}, tethering{tetheringMode}
+ {}
+
+ [[nodiscard]] auto getPhoneMode() const noexcept
+ {
+ return phoneMode;
+ }
+ [[nodiscard]] auto getTetheringMode() const noexcept
+ {
+ return tethering;
+ }
+
+ private:
+ PhoneMode phoneMode;
+ Tethering tethering;
+ };
+
+ class PhoneModeChangedSuccessfully : public ResponseMessage
+ {};
+
+ class PhoneModeChangeFailed : public ResponseMessage
+ {};
+} // namespace sys::phone_modes
A module-sys/PhoneModes/Observer.cpp => module-sys/PhoneModes/Observer.cpp +70 -0
@@ 0,0 1,70 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "Observer.hpp"
+
+#include <Service/Service.hpp>
+
+namespace sys::phone_modes
+{
+ void Observer::connect(Service *owner)
+ {
+ owner->connect(typeid(PhoneModeChanged), [this](sys::Message *request) -> sys::MessagePointer {
+ return handlePhoneModeChange(static_cast<PhoneModeChanged *>(request));
+ });
+ }
+
+ void Observer::subscribe(OnChangeCallback &&onChange,
+ OnCompleteCallback &&onComplete,
+ OnErrorCallback &&onError) noexcept
+ {
+ onChangeCallback = std::move(onChange);
+ onCompleteCallback = std::move(onComplete);
+ onErrorCallback = std::move(onError);
+ }
+
+ bool Observer::isInMode(PhoneMode mode) const noexcept
+ {
+ return phoneMode == mode;
+ }
+
+ bool Observer::isTetheringOn() const noexcept
+ {
+ return tetheringMode == Tethering::On;
+ }
+
+ sys::MessagePointer Observer::handlePhoneModeChange(PhoneModeChanged *message)
+ {
+ phoneMode = message->getPhoneMode();
+ tetheringMode = message->getTetheringMode();
+
+ try {
+ onPhoneModeChanged();
+ }
+ catch (const std::exception &) {
+ return std::make_shared<PhoneModeChangeFailed>();
+ }
+ return std::make_shared<PhoneModeChangedSuccessfully>();
+ }
+
+ void Observer::onPhoneModeChanged()
+ {
+ if (!onChangeCallback) {
+ LOG_WARN("No subscriber on phone mode change.");
+ return;
+ }
+
+ try {
+ onChangeCallback(phoneMode, tetheringMode);
+ if (onCompleteCallback) {
+ onCompleteCallback();
+ }
+ }
+ catch (const std::exception &error) {
+ if (onErrorCallback) {
+ onErrorCallback(error);
+ }
+ throw;
+ }
+ }
+} // namespace sys::phone_modes
A module-sys/PhoneModes/Observer.hpp => module-sys/PhoneModes/Observer.hpp +43 -0
@@ 0,0 1,43 @@
+// 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 <functional>
+#include <stdexcept>
+
+#include "Common.hpp"
+
+namespace sys
+{
+ class Service; // Forward declaration
+} // namespace sys
+
+namespace sys::phone_modes
+{
+ class Observer
+ {
+ public:
+ using OnChangeCallback = std::function<void(PhoneMode, Tethering)>;
+ using OnCompleteCallback = std::function<void()>;
+ using OnErrorCallback = std::function<void(const std::exception &)>;
+
+ void connect(Service *owner);
+ void subscribe(OnChangeCallback &&onChange,
+ OnCompleteCallback &&onComplete = {},
+ OnErrorCallback &&onError = {}) noexcept;
+
+ bool isInMode(PhoneMode mode) const noexcept;
+ bool isTetheringOn() const noexcept;
+
+ private:
+ sys::MessagePointer handlePhoneModeChange(PhoneModeChanged *message);
+ void onPhoneModeChanged();
+
+ OnChangeCallback onChangeCallback;
+ OnCompleteCallback onCompleteCallback;
+ OnErrorCallback onErrorCallback;
+ PhoneMode phoneMode = PhoneMode::Connected;
+ Tethering tetheringMode = Tethering::Off;
+ };
+} // namespace sys::phone_modes
A module-sys/PhoneModes/Subject.cpp => module-sys/PhoneModes/Subject.cpp +61 -0
@@ 0,0 1,61 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "Subject.hpp"
+
+#include <Service/Service.hpp>
+
+#include <module-utils/magic_enum/include/magic_enum.hpp>
+
+#include <stdexcept>
+#include <utility>
+
+namespace sys::phone_modes
+{
+ Subject::Subject(Service *owner) : owner{owner}
+ {
+ if (owner == nullptr) {
+ throw std::invalid_argument{"Subject's owner is invalid"};
+ }
+ }
+
+ void Subject::setMode(PhoneMode _phoneMode, Tethering _tetheringMode)
+ {
+ if (const bool changed = changePhoneMode(_phoneMode) || changeTetheringMode(_tetheringMode); changed) {
+ notifyChange();
+ }
+ }
+
+ void Subject::setPhoneMode(PhoneMode mode)
+ {
+ if (const auto changed = changePhoneMode(mode); changed) {
+ notifyChange();
+ }
+ }
+
+ bool Subject::changePhoneMode(PhoneMode mode) noexcept
+ {
+ return std::exchange(phoneMode, mode) != mode;
+ }
+
+ void Subject::setTetheringMode(Tethering mode)
+ {
+ if (const auto changed = changeTetheringMode(mode); changed) {
+ notifyChange();
+ }
+ }
+
+ bool Subject::changeTetheringMode(Tethering mode) noexcept
+ {
+ return std::exchange(tetheringMode, mode) != mode;
+ }
+
+ void Subject::notifyChange()
+ {
+ LOG_INFO("Phone modes changed: Phone mode: [%s]; Tethering: [%s]. Notifying phone modes observers.",
+ magic_enum::enum_name(phoneMode).data(),
+ magic_enum::enum_name(tetheringMode).data());
+ auto message = std::make_shared<PhoneModeChanged>(phoneMode, tetheringMode);
+ owner->bus.sendMulticast(std::move(message), BusChannel::PhoneModeChanges);
+ }
+} // namespace sys::phone_modes
A module-sys/PhoneModes/Subject.hpp => module-sys/PhoneModes/Subject.hpp +33 -0
@@ 0,0 1,33 @@
+// 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 "Common.hpp"
+
+namespace sys
+{
+ class Service; // Forward declaration
+} // namespace sys
+
+namespace sys::phone_modes
+{
+ class Subject
+ {
+ public:
+ explicit Subject(Service *owner);
+
+ void setMode(PhoneMode _phoneMode, Tethering _tetheringMode);
+ void setPhoneMode(PhoneMode mode);
+ void setTetheringMode(Tethering mode);
+
+ private:
+ void notifyChange();
+ bool changePhoneMode(PhoneMode mode) noexcept;
+ bool changeTetheringMode(Tethering mode) noexcept;
+
+ Service *owner;
+ PhoneMode phoneMode = PhoneMode::Connected;
+ Tethering tetheringMode = Tethering::Off;
+ };
+} // namespace sys::phone_modes
M module-sys/Service/Common.hpp => module-sys/Service/Common.hpp +4 -1
@@ 21,7 21,8 @@ namespace sys
ServiceFotaNotifications,
AntennaNotifications,
ServiceEvtmgrNotifications,
- CalendarNotifications
+ CalendarNotifications,
+ PhoneModeChanges,
};
enum class ServicePriority
@@ 111,6 112,8 @@ inline const char *c_str(sys::BusChannel channel)
return "ServiceEvtmgrNotifications";
case sys::BusChannel::CalendarNotifications:
return "CalendarNotifications";
+ case sys::BusChannel::PhoneModeChanges:
+ return "PhoneModeChanges";
}
return "";
}
M module-sys/SystemManager/SystemManager.cpp => module-sys/SystemManager/SystemManager.cpp +37 -6
@@ 25,12 25,20 @@
#include "messages/DeviceRegistrationMessage.hpp"
#include "messages/SentinelRegistrationMessage.hpp"
#include "messages/RequestCpuFrequencyMessage.hpp"
+#include "messages/PhoneModeRequest.hpp"
#include <time/ScopedTime.hpp>
const inline size_t systemManagerStack = 4096 * 2;
namespace sys
{
+ namespace
+ {
+ const std::map<bsp::KeyCodes, phone_modes::PhoneMode> SliderStateToPhoneModeMapping = {
+ {bsp::KeyCodes::SSwitchUp, phone_modes::PhoneMode::Connected},
+ {bsp::KeyCodes::SSwitchMid, phone_modes::PhoneMode::DoNotDisturb},
+ {bsp::KeyCodes::SSwitchDown, phone_modes::PhoneMode::Offline}};
+ } // namespace
using namespace cpp_freertos;
using namespace std;
@@ 146,6 154,7 @@ namespace sys
powerManager = std::make_unique<PowerManager>();
cpuStatistics = std::make_unique<CpuStatistics>();
deviceManager = std::make_unique<DeviceManager>();
+ phoneModeSubject = std::make_unique<phone_modes::Subject>(this);
systemInit = std::move(sysInit);
userInit = std::move(appSpaceInit);
@@ 286,17 295,17 @@ namespace sys
return MessageNone{};
});
- connect(sevm::KbdMessage(), [&](Message *) {
- // we are in shutdown mode - we received that there was red key pressed -> we need to reboot
- if (state == State::Shutdown) {
- set(State::Reboot);
+ connect(sevm::BatteryStatusChangeMessage(), [&](Message *) {
+ if ((state == State::Shutdown) && (Store::Battery::get().state == Store::Battery::State::Discharging)) {
+ set(State::ShutdownReady);
}
return MessageNone{};
});
- connect(sevm::BatteryPlugMessage(), [&](Message *) {
+ connect(sevm::KbdMessage(), [&](Message *) {
+ // we are in shutdown mode - we received that there was red key pressed -> we need to reboot
if (state == State::Shutdown) {
- set(State::ShutdownReady);
+ set(State::Reboot);
}
return MessageNone{};
});
@@ 370,6 379,11 @@ namespace sys
return sys::MessageNone{};
});
+ connect(typeid(PhoneModeRequest), [this](sys::Message *message) -> sys::MessagePointer {
+ auto request = static_cast<PhoneModeRequest *>(message);
+ return handlePhoneModeRequest(request);
+ });
+
deviceManager->RegisterNewDevice(powerManager->getExternalRamDevice());
return ReturnCodes::Success;
@@ 476,6 490,23 @@ namespace sys
powerManager->UpdateCpuFrequency(cpuStatistics->GetPercentageCpuLoad());
}
+ phone_modes::PhoneMode SystemManager::translateSliderState(const RawKey &key)
+ {
+ const auto code = key.key_code;
+ if (code != bsp::KeyCodes::SSwitchUp && code != bsp::KeyCodes::SSwitchMid &&
+ code != bsp::KeyCodes::SSwitchDown) {
+ throw std::invalid_argument{"Invalid key code passed."};
+ }
+ return SliderStateToPhoneModeMapping.at(code);
+ }
+
+ MessagePointer SystemManager::handlePhoneModeRequest(PhoneModeRequest *request)
+ {
+ LOG_INFO("Phone mode change requested.");
+ phoneModeSubject->setPhoneMode(request->getPhoneMode());
+ return MessageNone{};
+ }
+
std::vector<std::shared_ptr<Service>> SystemManager::servicesList;
cpp_freertos::MutexStandard SystemManager::destroyMutex;
std::unique_ptr<PowerManager> SystemManager::powerManager;
M module-sys/SystemManager/SystemManager.hpp => module-sys/SystemManager/SystemManager.hpp +12 -0
@@ 19,6 19,8 @@
#include "Service/Service.hpp"
#include "Service/ServiceCreator.hpp"
#include "PowerManager.hpp"
+#include "PhoneModes/Subject.hpp"
+#include <common_data/RawKey.hpp>
#include "Constants.hpp"
#include "CpuStatistics.hpp"
#include "DeviceManager.hpp"
@@ 34,6 36,8 @@ namespace sys
inline constexpr std::chrono::milliseconds timerPeriodInterval{100ms};
} // namespace constants
+ class PhoneModeRequest; // Forward declaration
+
enum class Code
{
CloseSystem,
@@ 92,6 96,11 @@ namespace sys
/// @note there is no fallback
static bool DestroyService(const std::string &name, Service *caller, TickType_t timeout = 5000);
+ /// Translates a slider state into a phone mode.
+ /// \param key Slider button state
+ /// \return Phone mode.
+ static phone_modes::PhoneMode translateSliderState(const RawKey &key);
+
/// Kill service
/// @note - this is final, it straight takes service, calls it's close callback and it's gone
/// please mind that services & apps not registered in SystemManager cant be killed - these should be handled by
@@ 143,10 152,13 @@ namespace sys
/// periodic update of cpu statistics
void CpuStatisticsTimerHandler();
+ MessagePointer handlePhoneModeRequest(PhoneModeRequest *request);
+
bool cpuStatisticsTimerInit{false};
std::vector<std::unique_ptr<BaseServiceCreator>> systemServiceCreators;
std::unique_ptr<sys::Timer> cpuStatisticsTimer;
+ std::unique_ptr<phone_modes::Subject> phoneModeSubject;
InitFunction userInit;
InitFunction systemInit;
A module-sys/SystemManager/doc/PowerManagement.md => module-sys/SystemManager/doc/PowerManagement.md +65 -0
@@ 0,0 1,65 @@
+# Power Management
+
+Power management is based on the frequency control of the CPU.
+
+## CPU frequency switching
+
+The CPU frequency control is dependent on the CPU load measured from the time spent in the task Idle. This control is also influenced by requests from interested services via sentinels (`minFrequencyRequested`). By increasing the CPU frequency, we always jump to the maximum possible frequency value. On the other hand, the reduction of the CPU frequency occurs gradually one level down.
+
+
+
+## Low Power synchronization
+
+Synchronization in Low Power mode covers 3 issues:
+
+* immediate informing services about changing the CPU frequency so that they can update their resources (e.g. PWM filling)
+
+* immediate switching on of peripherals that have been turned off by Low Power control (e.g. PLL2)
+
+* request from the service of the minimum CPU frequency in order to perform a task (e.g. screen redraw, telephone conversation)
+
+### Implementation
+
+To cover these issues, several classes have been implemented.
+
+* Sentinel class
+
+Each sentinel manages the requests, i.e. when it is needed it sends messages to `CpuGovernor` with the required minimum CPU frequency to perform the task (e.g. screen redraw). Furthermore, every sentinel is informed immediately after changing the frequency. This allows it to invoke a callback to the service to update its resources (e.g. PWM filling). Every sentinel must register itself on startup to `CpuGovernor` by sending `SentinelRegistrationMessage`.
+
+* CpuGovernor class
+
+`CpuGovernor` manages all sentinels in the system and has CPU frequency requests from them (e.g. `eInkSentinel`).
+
+* Driver class
+
+Dedicated drivers control the clocks. For example, `driverLPSPI` enables/disables the clock from LPSPI.
+
+* PLL2 class
+
+DriverPLL2 controls the PLL2 bus clock and if all dependent clocks are turned off, it turns off the PLL2 bus clock.
+
+* Device class
+
+Each driver (eg LPSPI) inherits from the Device class. Therefore, we can manage all drivers. Every device must register itself on startup to `DeviceManager` by sending `DeviceRegistrationMessage`.
+
+* DeviceManager class
+
+`DeviceManager` manages all devices on the system. It can turn off all devices and thus dedicated clocks.
+
+### CPU frequency update
+
+`PowerManager` periodically checks the CPU load and queries `CpuGovernor` to determine the conditions for changing the CPU frequency.
+After changing CPU frequency, all sentinels must be synchronously updated (e.g. `eInkSentinel`, `cellularSentinel`) so that they can update their resources (e.g. PWM fill)
+
+
+
+### Resource request
+
+Below is an example of requesting resources from `service_eInk` to redraw the screen:
+
+
+
+and requesting resources from `service_cellular` to make a phone call:
+
+
+
A module-sys/SystemManager/doc/data/CpuFreqChangeAlgorithm.puml => module-sys/SystemManager/doc/data/CpuFreqChangeAlgorithm.puml +40 -0
@@ 0,0 1,40 @@
+@startuml
+start
+
+if (cpuLoad > frequencyShiftUpperThreshold) then (yes)
+ : aboveThresholdCounter++
+ belowThresholdCounter = 0;
+else (no)
+ if (cpuLoad < frequencyShiftLowerThreshold) then (yes)
+ : belowThresholdCounter++
+ aboveThresholdCounter = 0;
+ else (no)
+ : belowThresholdCounter = 0
+ aboveThresholdCounter = 0;
+ endif
+endif
+
+if (
+ aboveThresholdCounter >= maxAboveThresholdCount
+ or
+ minFrequencyRequested > currentCpuFrequency
+ ) then (yes)
+ : IncreaseCpuFrequency()
+
+ belowThresholdCounter = 0
+ aboveThresholdCounter = 0;
+else (no)
+ if (
+ belowThresholdCounter >= maxBelowThresholdCount
+ and
+ currentCpuFreq > minFrequencyRequested
+ ) then (yes)
+ : DecreaseCpuFrequency()
+
+ belowThresholdCounter = 0
+ aboveThresholdCounter = 0;
+ endif
+endif
+
+stop
+@enduml<
\ No newline at end of file
A module-sys/SystemManager/doc/data/CpuFreqChangeAlgorithm.svg => module-sys/SystemManager/doc/data/CpuFreqChangeAlgorithm.svg +52 -0
@@ 0,0 1,52 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="611px" preserveAspectRatio="none" style="width:723px;height:611px;" version="1.1" viewBox="0 0 723 611" width="723px" zoomAndPan="magnify"><defs><filter height="300%" id="f4w1gyh31egl9" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><ellipse cx="289.75" cy="20" fill="#000000" filter="url(#f4w1gyh31egl9)" rx="10" ry="10" style="stroke: none; stroke-width: 1.0;"/><polygon fill="#FEFECE" filter="url(#f4w1gyh31egl9)" points="171.25,50,408.25,50,420.25,62,408.25,74,171.25,74,159.25,62,171.25,50" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="237" x="171.25" y="65.8081">cpuLoad > frequencyShiftUpperThreshold</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="20" x="139.25" y="59.4058">yes</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="14" x="420.25" y="59.4058">no</text><rect fill="#FEFECE" filter="url(#f4w1gyh31egl9)" height="47.9375" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="194" x="10" y="84"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="170" x="24" y="105.1387">aboveThresholdCounter++</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="174" x="20" y="119.1074">belowThresholdCounter = 0</text><polygon fill="#FEFECE" filter="url(#f4w1gyh31egl9)" points="354,84,591,84,603,96,591,108,354,108,342,96,354,84" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="237" x="354" y="99.8081">cpuLoad < frequencyShiftLowerThreshold</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="20" x="322" y="93.4058">yes</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="14" x="603" y="93.4058">no</text><rect fill="#FEFECE" filter="url(#f4w1gyh31egl9)" height="47.9375" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="196" x="234" y="118"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="168" x="248" y="139.1387">belowThresholdCounter++</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="176" x="244" y="153.1074">aboveThresholdCounter = 0</text><rect fill="#FEFECE" filter="url(#f4w1gyh31egl9)" height="47.9375" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="198" x="514" y="118"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="174" x="528" y="139.1387">belowThresholdCounter = 0</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="176" x="524" y="153.1074">aboveThresholdCounter = 0</text><polygon fill="#FEFECE" filter="url(#f4w1gyh31egl9)" points="472.5,171.9375,484.5,183.9375,472.5,195.9375,460.5,183.9375,472.5,171.9375" style="stroke: #A80036; stroke-width: 1.5;"/><polygon fill="#FEFECE" filter="url(#f4w1gyh31egl9)" points="289.75,201.9375,301.75,213.9375,289.75,225.9375,277.75,213.9375,289.75,201.9375" style="stroke: #A80036; stroke-width: 1.5;"/><polygon fill="#FEFECE" filter="url(#f4w1gyh31egl9)" points="134.75,245.9375,444.75,245.9375,456.75,277.9492,444.75,309.9609,134.75,309.9609,122.75,277.9492,134.75,245.9375" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="0" x="138.75" y="256.1479"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="310" x="134.75" y="268.9526">aboveThresholdCounter >= maxAboveThresholdCount</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="12" x="134.75" y="281.7573">or</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="277" x="134.75" y="294.562">minFrequencyRequested > currentCpuFrequency</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="0" x="138.75" y="307.3667"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="20" x="102.75" y="275.355">yes</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="14" x="456.75" y="275.355">no</text><rect fill="#FEFECE" filter="url(#f4w1gyh31egl9)" height="75.875" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="196" x="14.75" y="319.9609"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="153" x="28.75" y="341.0996">IncreaseCpuFrequency()</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="0" x="28.75" y="355.0684"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="174" x="24.75" y="369.0371">belowThresholdCounter = 0</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="176" x="24.75" y="383.0059">aboveThresholdCounter = 0</text><rect fill="#FEFECE" filter="url(#f4w1gyh31egl9)" height="75.875" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="196" x="368.75" y="408.3867"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="159" x="382.75" y="429.5254">DecreaseCpuFrequency()</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="0" x="382.75" y="443.4941"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="174" x="378.75" y="457.4629">belowThresholdCounter = 0</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="176" x="378.75" y="471.4316">aboveThresholdCounter = 0</text><polygon fill="#FEFECE" filter="url(#f4w1gyh31egl9)" points="312.25,319.9609,621.25,319.9609,633.25,351.9727,621.25,383.9844,312.25,383.9844,300.25,351.9727,312.25,319.9609" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="20" x="470.75" y="394.1948">yes</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="0" x="316.25" y="330.1714"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="309" x="312.25" y="342.9761">belowThresholdCounter >= maxBelowThresholdCount</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="21" x="312.25" y="355.7808">and</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="244" x="312.25" y="368.5854">currentCpuFreq > minFrequencyRequested</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="0" x="316.25" y="381.3901"/><polygon fill="#FEFECE" filter="url(#f4w1gyh31egl9)" points="466.75,504.2617,478.75,516.2617,466.75,528.2617,454.75,516.2617,466.75,504.2617" style="stroke: #A80036; stroke-width: 1.5;"/><polygon fill="#FEFECE" filter="url(#f4w1gyh31egl9)" points="289.75,534.2617,301.75,546.2617,289.75,558.2617,277.75,546.2617,289.75,534.2617" style="stroke: #A80036; stroke-width: 1.5;"/><ellipse cx="289.75" cy="589.2617" fill="#FFFFFF" filter="url(#f4w1gyh31egl9)" rx="11" ry="11" style="stroke: #000000; stroke-width: 1.0;"/><ellipse cx="289.75" cy="589.2617" fill="#000000" rx="6" ry="6" style="stroke: #7F7F7F; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="342" x2="332" y1="96" y2="96"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="332" x2="332" y1="96" y2="118"/><polygon fill="#A80036" points="328,108,332,118,336,108,332,112" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="603" x2="613" y1="96" y2="96"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="613" x2="613" y1="96" y2="118"/><polygon fill="#A80036" points="609,108,613,118,617,108,613,112" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="332" x2="332" y1="165.9375" y2="183.9375"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="332" x2="460.5" y1="183.9375" y2="183.9375"/><polygon fill="#A80036" points="450.5,179.9375,460.5,183.9375,450.5,187.9375,454.5,183.9375" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="613" x2="613" y1="165.9375" y2="183.9375"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="613" x2="484.5" y1="183.9375" y2="183.9375"/><polygon fill="#A80036" points="494.5,179.9375,484.5,183.9375,494.5,187.9375,490.5,183.9375" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="159.25" x2="107" y1="62" y2="62"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="107" x2="107" y1="62" y2="84"/><polygon fill="#A80036" points="103,74,107,84,111,74,107,78" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="420.25" x2="472.5" y1="62" y2="62"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="472.5" x2="472.5" y1="62" y2="84"/><polygon fill="#A80036" points="468.5,74,472.5,84,476.5,74,472.5,78" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="107" x2="107" y1="131.9375" y2="213.9375"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="107" x2="277.75" y1="213.9375" y2="213.9375"/><polygon fill="#A80036" points="267.75,209.9375,277.75,213.9375,267.75,217.9375,271.75,213.9375" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="472.5" x2="472.5" y1="195.9375" y2="213.9375"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="472.5" x2="301.75" y1="213.9375" y2="213.9375"/><polygon fill="#A80036" points="311.75,209.9375,301.75,213.9375,311.75,217.9375,307.75,213.9375" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="289.75" x2="289.75" y1="30" y2="50"/><polygon fill="#A80036" points="285.75,40,289.75,50,293.75,40,289.75,44" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="466.75" x2="466.75" y1="383.9844" y2="408.3867"/><polygon fill="#A80036" points="462.75,398.3867,466.75,408.3867,470.75,398.3867,466.75,402.3867" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="633.25" x2="645.25" y1="351.9727" y2="351.9727"/><polygon fill="#A80036" points="641.25,426.3184,645.25,436.3184,649.25,426.3184,645.25,430.3184" style="stroke: #A80036; stroke-width: 1.5;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="645.25" x2="645.25" y1="351.9727" y2="516.2617"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="645.25" x2="478.75" y1="516.2617" y2="516.2617"/><polygon fill="#A80036" points="488.75,512.2617,478.75,516.2617,488.75,520.2617,484.75,516.2617" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="466.75" x2="466.75" y1="484.2617" y2="504.2617"/><polygon fill="#A80036" points="462.75,494.2617,466.75,504.2617,470.75,494.2617,466.75,498.2617" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="122.75" x2="112.75" y1="277.9492" y2="277.9492"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="112.75" x2="112.75" y1="277.9492" y2="319.9609"/><polygon fill="#A80036" points="108.75,309.9609,112.75,319.9609,116.75,309.9609,112.75,313.9609" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="456.75" x2="466.75" y1="277.9492" y2="277.9492"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="466.75" x2="466.75" y1="277.9492" y2="319.9609"/><polygon fill="#A80036" points="462.75,309.9609,466.75,319.9609,470.75,309.9609,466.75,313.9609" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="112.75" x2="112.75" y1="395.8359" y2="546.2617"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="112.75" x2="277.75" y1="546.2617" y2="546.2617"/><polygon fill="#A80036" points="267.75,542.2617,277.75,546.2617,267.75,550.2617,271.75,546.2617" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="466.75" x2="466.75" y1="528.2617" y2="546.2617"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="466.75" x2="301.75" y1="546.2617" y2="546.2617"/><polygon fill="#A80036" points="311.75,542.2617,301.75,546.2617,311.75,550.2617,307.75,546.2617" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="289.75" x2="289.75" y1="225.9375" y2="245.9375"/><polygon fill="#A80036" points="285.75,235.9375,289.75,245.9375,293.75,235.9375,289.75,239.9375" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.5;" x1="289.75" x2="289.75" y1="558.2617" y2="578.2617"/><polygon fill="#A80036" points="285.75,568.2617,289.75,578.2617,293.75,568.2617,289.75,572.2617" style="stroke: #A80036; stroke-width: 1.0;"/><!--MD5=[ee2983799085d65f96fa6af7dcfc3842]
+@startuml
+start
+
+if (cpuLoad > frequencyShiftUpperThreshold) then (yes)
+: aboveThresholdCounter++
+belowThresholdCounter = 0;
+else (no)
+if (cpuLoad < frequencyShiftLowerThreshold) then (yes)
+: belowThresholdCounter++
+aboveThresholdCounter = 0;
+else (no)
+: belowThresholdCounter = 0
+aboveThresholdCounter = 0;
+endif
+endif
+
+if (
+aboveThresholdCounter >= maxAboveThresholdCount
+or
+minFrequencyRequested > currentCpuFrequency
+) then (yes)
+: IncreaseCpuFrequency()
+
+belowThresholdCounter = 0
+aboveThresholdCounter = 0;
+else (no)
+if (
+belowThresholdCounter >= maxBelowThresholdCount
+and
+currentCpuFreq > minFrequencyRequested
+) then (yes)
+: DecreaseCpuFrequency()
+
+belowThresholdCounter = 0
+aboveThresholdCounter = 0;
+endif
+endif
+
+stop
+@enduml
+
+PlantUML version 1.2019.11(Sun Sep 22 12:02:15 CEST 2019)
+(EPL source distribution)
+Java Runtime: OpenJDK Runtime Environment
+JVM: OpenJDK 64-Bit Server VM
+Java Version: 14.0.2+12-46
+Operating System: Linux
+Default Encoding: UTF-8
+Language: pl
+Country: PL
+--></g></svg><
\ No newline at end of file
A module-sys/SystemManager/doc/data/CpuFrequencyUpdate.puml => module-sys/SystemManager/doc/data/CpuFrequencyUpdate.puml +19 -0
@@ 0,0 1,19 @@
+@startuml
+
+PowerManager -> CpuGovernor : GetMinimumFrequencyRequested
+CpuGovernor --> PowerManager : minimumFrequency
+
+...CPU frequency change...
+
+PowerManager -> CpuGovernor : CpuFrequencyHasChanged
+
+CpuGovernor -> cellularSentinel : CpuFrequencyHasChanged
+
+CpuGovernor -> eInkSentinel : CpuFrequencyHasChanged
+eInkSentinel -> DriverPWM : updatePWM
+note right
+Critical section!
+mutex necessary
+end note
+
+@enduml
A module-sys/SystemManager/doc/data/CpuFrequencyUpdate.svg => module-sys/SystemManager/doc/data/CpuFrequencyUpdate.svg +31 -0
@@ 0,0 1,31 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="339px" preserveAspectRatio="none" style="width:883px;height:339px;" version="1.1" viewBox="0 0 883 339" width="883px" zoomAndPan="magnify"><defs><filter height="300%" id="f4w29l22zrjdz" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><line style="stroke: #A80036; stroke-width: 1.0;" x1="68" x2="68" y1="38.2969" y2="106.5625"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,4.0;" x1="68" x2="68" y1="106.5625" y2="147.3672"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="68" x2="68" y1="147.3672" y2="299.0313"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="308.5" x2="308.5" y1="38.2969" y2="106.5625"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,4.0;" x1="308.5" x2="308.5" y1="106.5625" y2="147.3672"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="308.5" x2="308.5" y1="147.3672" y2="299.0313"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="505.5" x2="505.5" y1="38.2969" y2="106.5625"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,4.0;" x1="505.5" x2="505.5" y1="106.5625" y2="147.3672"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="505.5" x2="505.5" y1="147.3672" y2="299.0313"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="627.5" x2="627.5" y1="38.2969" y2="106.5625"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,4.0;" x1="627.5" x2="627.5" y1="106.5625" y2="147.3672"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="627.5" x2="627.5" y1="147.3672" y2="299.0313"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="735.5" x2="735.5" y1="38.2969" y2="106.5625"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,4.0;" x1="735.5" x2="735.5" y1="106.5625" y2="147.3672"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="735.5" x2="735.5" y1="147.3672" y2="299.0313"/><rect fill="#FEFECE" filter="url(#f4w29l22zrjdz)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="117" x="8" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="103" x="15" y="22.9951">PowerManager</text><rect fill="#FEFECE" filter="url(#f4w29l22zrjdz)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="117" x="8" y="298.0313"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="103" x="15" y="318.0264">PowerManager</text><rect fill="#FEFECE" filter="url(#f4w29l22zrjdz)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="106" x="253.5" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="92" x="260.5" y="22.9951">CpuGovernor</text><rect fill="#FEFECE" filter="url(#f4w29l22zrjdz)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="106" x="253.5" y="298.0313"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="92" x="260.5" y="318.0264">CpuGovernor</text><rect fill="#FEFECE" filter="url(#f4w29l22zrjdz)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="118" x="444.5" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="104" x="451.5" y="22.9951">cellularSentinel</text><rect fill="#FEFECE" filter="url(#f4w29l22zrjdz)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="118" x="444.5" y="298.0313"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="104" x="451.5" y="318.0264">cellularSentinel</text><rect fill="#FEFECE" filter="url(#f4w29l22zrjdz)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="99" x="576.5" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="85" x="583.5" y="22.9951">eInkSentinel</text><rect fill="#FEFECE" filter="url(#f4w29l22zrjdz)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="99" x="576.5" y="298.0313"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="85" x="583.5" y="318.0264">eInkSentinel</text><rect fill="#FEFECE" filter="url(#f4w29l22zrjdz)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="88" x="689.5" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="74" x="696.5" y="22.9951">DriverPWM</text><rect fill="#FEFECE" filter="url(#f4w29l22zrjdz)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="88" x="689.5" y="298.0313"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="74" x="696.5" y="318.0264">DriverPWM</text><polygon fill="#A80036" points="296.5,65.4297,306.5,69.4297,296.5,73.4297,300.5,69.4297" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="68.5" x2="302.5" y1="69.4297" y2="69.4297"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="216" x="75.5" y="64.3638">GetMinimumFrequencyRequested</text><polygon fill="#A80036" points="79.5,94.5625,69.5,98.5625,79.5,102.5625,75.5,98.5625" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 2.0,2.0;" x1="73.5" x2="307.5" y1="98.5625" y2="98.5625"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="127" x="85.5" y="93.4966">minimumFrequency</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="128" x="338" y="130.7729">CPU frequency change</text><polygon fill="#A80036" points="296.5,164.5,306.5,168.5,296.5,172.5,300.5,168.5" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="68.5" x2="302.5" y1="168.5" y2="168.5"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="173" x="75.5" y="163.4341">CpuFrequencyHasChanged</text><polygon fill="#A80036" points="493.5,193.6328,503.5,197.6328,493.5,201.6328,497.5,197.6328" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="308.5" x2="499.5" y1="197.6328" y2="197.6328"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="173" x="315.5" y="192.5669">CpuFrequencyHasChanged</text><polygon fill="#A80036" points="616,222.7656,626,226.7656,616,230.7656,620,226.7656" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="308.5" x2="622" y1="226.7656" y2="226.7656"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="173" x="315.5" y="221.6997">CpuFrequencyHasChanged</text><polygon fill="#A80036" points="723.5,264.4648,733.5,268.4648,723.5,272.4648,727.5,268.4648" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="628" x2="729.5" y1="268.4648" y2="268.4648"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="75" x="635" y="263.3989">updatePWM</text><path d="M740,239.7656 L740,279.7656 L871,279.7656 L871,249.7656 L861,239.7656 L740,239.7656 " fill="#FBFB77" filter="url(#f4w29l22zrjdz)" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M861,239.7656 L861,249.7656 L871,249.7656 L861,239.7656 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="98" x="746" y="256.8325">Critical section!</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="110" x="746" y="271.9653">mutex necessary</text><!--MD5=[6c4788b841e800cf870b69c0ce829c52]
+@startuml
+
+PowerManager -> CpuGovernor : GetMinimumFrequencyRequested
+CpuGovernor - -> PowerManager : minimumFrequency
+
+...CPU frequency change...
+
+PowerManager -> CpuGovernor : CpuFrequencyHasChanged
+
+CpuGovernor -> cellularSentinel : CpuFrequencyHasChanged
+
+CpuGovernor -> eInkSentinel : CpuFrequencyHasChanged
+eInkSentinel -> DriverPWM : updatePWM
+note right
+Critical section!
+mutex necessary
+end note
+
+@enduml
+
+PlantUML version 1.2019.11(Sun Sep 22 12:02:15 CEST 2019)
+(EPL source distribution)
+Java Runtime: OpenJDK Runtime Environment
+JVM: OpenJDK 64-Bit Server VM
+Java Version: 14.0.2+12-46
+Operating System: Linux
+Default Encoding: UTF-8
+Language: pl
+Country: PL
+--></g></svg><
\ No newline at end of file
A module-sys/SystemManager/doc/data/ResourceRequest.puml => module-sys/SystemManager/doc/data/ResourceRequest.puml +70 -0
@@ 0,0 1,70 @@
+@startuml
+
+service_eInk -> eInkSentinel : SetFrequencyValueRequest
+eInkSentinel -> PowerManager : RequestCpuFrequencyMessage
+
+PowerManager -> CpuGovernor : SetCpuFrequencyRequest
+
+service_eInk -> EinkDisplay : powerOn
+EinkDisplay -> driverLPSPI : Enable
+
+driverLPSPI -> driverPLL2 : Pll2ClockEnable
+note right
+Critical section!
+mutex necessary
+end note
+
+driverLPSPI -> clock_config : LPSPIClockEnable
+
+...screen redraw...
+
+EinkDisplay -> driverLPSPI : Disable
+
+driverLPSPI -> clock_config : LPSPIClockDisable
+
+driverLPSPI -> driverPLL2 : Pll2ClockDisable
+note right
+Critical section!
+mutex necessary
+end note
+
+service_eInk -> eInkSentinel : ResetCpuFrequencyRequest
+eInkSentinel -> PowerManager : RequestCpuFrequencyMessage
+
+PowerManager -> CpuGovernor : ResetCpuFrequencyRequest
+
+@enduml
+
+
+
+
+@startuml
+
+service_cellular -> cellularSentinel : SetFrequencyValueRequest
+cellularSentinel -> PowerManager : RequestCpuFrequencyMessage
+
+PowerManager -> CpuGovernor : SetCpuFrequencyRequest
+
+service_cellular -> bsp_cellular : wakeUp
+bsp_cellular -> driverUART : Enable
+
+driverUART -> clock_config : ExternalOscillatorEnable
+note right
+Critical section!
+mutex necessary
+end note
+
+driverUART -> clock_config : UARTClockEnable
+
+...call ended...
+
+bsp_cellular -> driverUART : Disable
+
+driverUART -> clock_config : UARTClockDisable
+
+service_cellular -> cellularSentinel : ResetCpuFrequencyRequest
+cellularSentinel -> PowerManager : RequestCpuFrequencyMessage
+
+PowerManager -> CpuGovernor : ResetCpuFrequencyRequest
+
+@enduml
A module-sys/SystemManager/doc/data/cellularResourceRequest.svg => module-sys/SystemManager/doc/data/cellularResourceRequest.svg +42 -0
@@ 0,0 1,42 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="514px" preserveAspectRatio="none" style="width:1246px;height:514px;" version="1.1" viewBox="0 0 1246 514" width="1246px" zoomAndPan="magnify"><defs><filter height="300%" id="f1tv0e0kd571ez" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><line style="stroke: #A80036; stroke-width: 1.0;" x1="69" x2="69" y1="38.2969" y2="277.3594"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,4.0;" x1="69" x2="69" y1="277.3594" y2="318.1641"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="69" x2="69" y1="318.1641" y2="473.8281"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="272" x2="272" y1="38.2969" y2="277.3594"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,4.0;" x1="272" x2="272" y1="277.3594" y2="318.1641"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="272" x2="272" y1="318.1641" y2="473.8281"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="495.5" x2="495.5" y1="38.2969" y2="277.3594"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,4.0;" x1="495.5" x2="495.5" y1="277.3594" y2="318.1641"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="495.5" x2="495.5" y1="318.1641" y2="473.8281"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="699" x2="699" y1="38.2969" y2="277.3594"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,4.0;" x1="699" x2="699" y1="277.3594" y2="318.1641"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="699" x2="699" y1="318.1641" y2="473.8281"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="813" x2="813" y1="38.2969" y2="277.3594"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,4.0;" x1="813" x2="813" y1="277.3594" y2="318.1641"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="813" x2="813" y1="318.1641" y2="473.8281"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="920" x2="920" y1="38.2969" y2="277.3594"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,4.0;" x1="920" x2="920" y1="277.3594" y2="318.1641"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="920" x2="920" y1="318.1641" y2="473.8281"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="1097.5" x2="1097.5" y1="38.2969" y2="277.3594"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,4.0;" x1="1097.5" x2="1097.5" y1="277.3594" y2="318.1641"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="1097.5" x2="1097.5" y1="318.1641" y2="473.8281"/><rect fill="#FEFECE" filter="url(#f1tv0e0kd571ez)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="118" x="8" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="104" x="15" y="22.9951">service_cellular</text><rect fill="#FEFECE" filter="url(#f1tv0e0kd571ez)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="118" x="8" y="472.8281"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="104" x="15" y="492.8232">service_cellular</text><rect fill="#FEFECE" filter="url(#f1tv0e0kd571ez)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="118" x="211" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="104" x="218" y="22.9951">cellularSentinel</text><rect fill="#FEFECE" filter="url(#f1tv0e0kd571ez)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="118" x="211" y="472.8281"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="104" x="218" y="492.8232">cellularSentinel</text><rect fill="#FEFECE" filter="url(#f1tv0e0kd571ez)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="117" x="435.5" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="103" x="442.5" y="22.9951">PowerManager</text><rect fill="#FEFECE" filter="url(#f1tv0e0kd571ez)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="117" x="435.5" y="472.8281"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="103" x="442.5" y="492.8232">PowerManager</text><rect fill="#FEFECE" filter="url(#f1tv0e0kd571ez)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="106" x="644" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="92" x="651" y="22.9951">CpuGovernor</text><rect fill="#FEFECE" filter="url(#f1tv0e0kd571ez)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="106" x="644" y="472.8281"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="92" x="651" y="492.8232">CpuGovernor</text><rect fill="#FEFECE" filter="url(#f1tv0e0kd571ez)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="95" x="764" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="81" x="771" y="22.9951">bsp_cellular</text><rect fill="#FEFECE" filter="url(#f1tv0e0kd571ez)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="95" x="764" y="472.8281"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="81" x="771" y="492.8232">bsp_cellular</text><rect fill="#FEFECE" filter="url(#f1tv0e0kd571ez)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="90" x="873" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="76" x="880" y="22.9951">driverUART</text><rect fill="#FEFECE" filter="url(#f1tv0e0kd571ez)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="90" x="873" y="472.8281"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="76" x="880" y="492.8232">driverUART</text><rect fill="#FEFECE" filter="url(#f1tv0e0kd571ez)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="99" x="1046.5" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="85" x="1053.5" y="22.9951">clock_config</text><rect fill="#FEFECE" filter="url(#f1tv0e0kd571ez)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="99" x="1046.5" y="472.8281"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="85" x="1053.5" y="492.8232">clock_config</text><polygon fill="#A80036" points="260,65.4297,270,69.4297,260,73.4297,264,69.4297" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="69" x2="266" y1="69.4297" y2="69.4297"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="176" x="76" y="64.3638">SetFrequencyValueRequest</text><polygon fill="#A80036" points="484,94.5625,494,98.5625,484,102.5625,488,98.5625" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="272" x2="490" y1="98.5625" y2="98.5625"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="200" x="279" y="93.4966">RequestCpuFrequencyMessage</text><polygon fill="#A80036" points="687,123.6953,697,127.6953,687,131.6953,691,127.6953" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="496" x2="693" y1="127.6953" y2="127.6953"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="165" x="503" y="122.6294">SetCpuFrequencyRequest</text><polygon fill="#A80036" points="801.5,152.8281,811.5,156.8281,801.5,160.8281,805.5,156.8281" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="69" x2="807.5" y1="156.8281" y2="156.8281"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="50" x="76" y="151.7622">wakeUp</text><polygon fill="#A80036" points="908,181.9609,918,185.9609,908,189.9609,912,185.9609" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="813.5" x2="914" y1="185.9609" y2="185.9609"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="43" x="820.5" y="180.895">Enable</text><polygon fill="#A80036" points="1086,223.6602,1096,227.6602,1086,231.6602,1090,227.6602" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="920" x2="1092" y1="227.6602" y2="227.6602"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="154" x="927" y="222.5942">ExternalOscillatorEnable</text><path d="M1103,198.9609 L1103,238.9609 L1234,238.9609 L1234,208.9609 L1224,198.9609 L1103,198.9609 " fill="#FBFB77" filter="url(#f1tv0e0kd571ez)" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M1224,198.9609 L1224,208.9609 L1234,208.9609 L1224,198.9609 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="98" x="1109" y="216.0278">Critical section!</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="110" x="1109" y="231.1606">mutex necessary</text><polygon fill="#A80036" points="1086,265.3594,1096,269.3594,1086,273.3594,1090,269.3594" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="920" x2="1092" y1="269.3594" y2="269.3594"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="111" x="927" y="264.2935">UARTClockEnable</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="58" x="554.5" y="301.5698">call ended</text><polygon fill="#A80036" points="908,335.2969,918,339.2969,908,343.2969,912,339.2969" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="813.5" x2="914" y1="339.2969" y2="339.2969"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="47" x="820.5" y="334.231">Disable</text><polygon fill="#A80036" points="1086,364.4297,1096,368.4297,1086,372.4297,1090,368.4297" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="920" x2="1092" y1="368.4297" y2="368.4297"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="115" x="927" y="363.3638">UARTClockDisable</text><polygon fill="#A80036" points="260,393.5625,270,397.5625,260,401.5625,264,397.5625" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="69" x2="266" y1="397.5625" y2="397.5625"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="179" x="76" y="392.4966">ResetCpuFrequencyRequest</text><polygon fill="#A80036" points="484,422.6953,494,426.6953,484,430.6953,488,426.6953" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="272" x2="490" y1="426.6953" y2="426.6953"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="200" x="279" y="421.6294">RequestCpuFrequencyMessage</text><polygon fill="#A80036" points="687,451.8281,697,455.8281,687,459.8281,691,455.8281" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="496" x2="693" y1="455.8281" y2="455.8281"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="179" x="503" y="450.7622">ResetCpuFrequencyRequest</text><!--MD5=[6fcf4d81c1fbb048db22def46a2b620c]
+@startuml
+
+service_cellular -> cellularSentinel : SetFrequencyValueRequest
+cellularSentinel -> PowerManager : RequestCpuFrequencyMessage
+
+PowerManager -> CpuGovernor : SetCpuFrequencyRequest
+
+service_cellular -> bsp_cellular : wakeUp
+bsp_cellular -> driverUART : Enable
+
+driverUART -> clock_config : ExternalOscillatorEnable
+note right
+Critical section!
+mutex necessary
+end note
+
+driverUART -> clock_config : UARTClockEnable
+
+...call ended...
+
+bsp_cellular -> driverUART : Disable
+
+driverUART -> clock_config : UARTClockDisable
+
+service_cellular -> cellularSentinel : ResetCpuFrequencyRequest
+cellularSentinel -> PowerManager : RequestCpuFrequencyMessage
+
+PowerManager -> CpuGovernor : ResetCpuFrequencyRequest
+
+@enduml
+
+PlantUML version 1.2019.11(Sun Sep 22 12:02:15 CEST 2019)
+(EPL source distribution)
+Java Runtime: OpenJDK Runtime Environment
+JVM: OpenJDK 64-Bit Server VM
+Java Version: 14.0.2+12-46
+Operating System: Linux
+Default Encoding: UTF-8
+Language: pl
+Country: PL
+--></g></svg><
\ No newline at end of file
A module-sys/SystemManager/doc/data/eInkResourceRequest.svg => module-sys/SystemManager/doc/data/eInkResourceRequest.svg +48 -0
@@ 0,0 1,48 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="568px" preserveAspectRatio="none" style="width:1198px;height:568px;" version="1.1" viewBox="0 0 1198 568" width="1198px" zoomAndPan="magnify"><defs><filter height="300%" id="fcbnkjoqvuo08" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><line style="stroke: #A80036; stroke-width: 1.0;" x1="59" x2="59" y1="38.2969" y2="277.3594"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,4.0;" x1="59" x2="59" y1="277.3594" y2="318.1641"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="59" x2="59" y1="318.1641" y2="528.0938"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="262" x2="262" y1="38.2969" y2="277.3594"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,4.0;" x1="262" x2="262" y1="277.3594" y2="318.1641"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="262" x2="262" y1="318.1641" y2="528.0938"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="486" x2="486" y1="38.2969" y2="277.3594"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,4.0;" x1="486" x2="486" y1="277.3594" y2="318.1641"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="486" x2="486" y1="318.1641" y2="528.0938"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="689.5" x2="689.5" y1="38.2969" y2="277.3594"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,4.0;" x1="689.5" x2="689.5" y1="277.3594" y2="318.1641"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="689.5" x2="689.5" y1="318.1641" y2="528.0938"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="802.5" x2="802.5" y1="38.2969" y2="277.3594"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,4.0;" x1="802.5" x2="802.5" y1="277.3594" y2="318.1641"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="802.5" x2="802.5" y1="318.1641" y2="528.0938"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="906.5" x2="906.5" y1="38.2969" y2="277.3594"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,4.0;" x1="906.5" x2="906.5" y1="277.3594" y2="318.1641"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="906.5" x2="906.5" y1="318.1641" y2="528.0938"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="1034" x2="1034" y1="38.2969" y2="277.3594"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,4.0;" x1="1034" x2="1034" y1="277.3594" y2="318.1641"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="1034" x2="1034" y1="318.1641" y2="528.0938"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="1139" x2="1139" y1="38.2969" y2="277.3594"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 1.0,4.0;" x1="1139" x2="1139" y1="277.3594" y2="318.1641"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="1139" x2="1139" y1="318.1641" y2="528.0938"/><rect fill="#FEFECE" filter="url(#fcbnkjoqvuo08)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="99" x="8" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="85" x="15" y="22.9951">service_eInk</text><rect fill="#FEFECE" filter="url(#fcbnkjoqvuo08)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="99" x="8" y="527.0938"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="85" x="15" y="547.0889">service_eInk</text><rect fill="#FEFECE" filter="url(#fcbnkjoqvuo08)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="99" x="211" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="85" x="218" y="22.9951">eInkSentinel</text><rect fill="#FEFECE" filter="url(#fcbnkjoqvuo08)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="99" x="211" y="527.0938"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="85" x="218" y="547.0889">eInkSentinel</text><rect fill="#FEFECE" filter="url(#fcbnkjoqvuo08)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="117" x="426" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="103" x="433" y="22.9951">PowerManager</text><rect fill="#FEFECE" filter="url(#fcbnkjoqvuo08)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="117" x="426" y="527.0938"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="103" x="433" y="547.0889">PowerManager</text><rect fill="#FEFECE" filter="url(#fcbnkjoqvuo08)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="106" x="634.5" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="92" x="641.5" y="22.9951">CpuGovernor</text><rect fill="#FEFECE" filter="url(#fcbnkjoqvuo08)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="106" x="634.5" y="527.0938"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="92" x="641.5" y="547.0889">CpuGovernor</text><rect fill="#FEFECE" filter="url(#fcbnkjoqvuo08)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="92" x="754.5" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="78" x="761.5" y="22.9951">EinkDisplay</text><rect fill="#FEFECE" filter="url(#fcbnkjoqvuo08)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="92" x="754.5" y="527.0938"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="78" x="761.5" y="547.0889">EinkDisplay</text><rect fill="#FEFECE" filter="url(#fcbnkjoqvuo08)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="89" x="860.5" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="75" x="867.5" y="22.9951">driverLPSPI</text><rect fill="#FEFECE" filter="url(#fcbnkjoqvuo08)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="89" x="860.5" y="527.0938"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="75" x="867.5" y="547.0889">driverLPSPI</text><rect fill="#FEFECE" filter="url(#fcbnkjoqvuo08)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="84" x="990" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="70" x="997" y="22.9951">driverPLL2</text><rect fill="#FEFECE" filter="url(#fcbnkjoqvuo08)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="84" x="990" y="527.0938"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="70" x="997" y="547.0889">driverPLL2</text><rect fill="#FEFECE" filter="url(#fcbnkjoqvuo08)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="99" x="1088" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="85" x="1095" y="22.9951">clock_config</text><rect fill="#FEFECE" filter="url(#fcbnkjoqvuo08)" height="30.2969" style="stroke: #A80036; stroke-width: 1.5;" width="99" x="1088" y="527.0938"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="85" x="1095" y="547.0889">clock_config</text><polygon fill="#A80036" points="250.5,65.4297,260.5,69.4297,250.5,73.4297,254.5,69.4297" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="59.5" x2="256.5" y1="69.4297" y2="69.4297"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="176" x="66.5" y="64.3638">SetFrequencyValueRequest</text><polygon fill="#A80036" points="474.5,94.5625,484.5,98.5625,474.5,102.5625,478.5,98.5625" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="262.5" x2="480.5" y1="98.5625" y2="98.5625"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="200" x="269.5" y="93.4966">RequestCpuFrequencyMessage</text><polygon fill="#A80036" points="677.5,123.6953,687.5,127.6953,677.5,131.6953,681.5,127.6953" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="486.5" x2="683.5" y1="127.6953" y2="127.6953"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="165" x="493.5" y="122.6294">SetCpuFrequencyRequest</text><polygon fill="#A80036" points="790.5,152.8281,800.5,156.8281,790.5,160.8281,794.5,156.8281" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="59.5" x2="796.5" y1="156.8281" y2="156.8281"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="56" x="66.5" y="151.7622">powerOn</text><polygon fill="#A80036" points="895,181.9609,905,185.9609,895,189.9609,899,185.9609" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="802.5" x2="901" y1="185.9609" y2="185.9609"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="43" x="809.5" y="180.895">Enable</text><polygon fill="#A80036" points="1022,223.6602,1032,227.6602,1022,231.6602,1026,227.6602" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="907" x2="1028" y1="227.6602" y2="227.6602"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="99" x="914" y="222.5942">Pll2ClockEnable</text><path d="M1039,198.9609 L1039,238.9609 L1170,238.9609 L1170,208.9609 L1160,198.9609 L1039,198.9609 " fill="#FBFB77" filter="url(#fcbnkjoqvuo08)" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M1160,198.9609 L1160,208.9609 L1170,208.9609 L1160,198.9609 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="98" x="1045" y="216.0278">Critical section!</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="110" x="1045" y="231.1606">mutex necessary</text><polygon fill="#A80036" points="1127.5,265.3594,1137.5,269.3594,1127.5,273.3594,1131.5,269.3594" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="907" x2="1133.5" y1="269.3594" y2="269.3594"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="112" x="914" y="264.2935">LPSPIClockEnable</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="83" x="558" y="301.5698">screen redraw</text><polygon fill="#A80036" points="895,335.2969,905,339.2969,895,343.2969,899,339.2969" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="802.5" x2="901" y1="339.2969" y2="339.2969"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="47" x="809.5" y="334.231">Disable</text><polygon fill="#A80036" points="1127.5,364.4297,1137.5,368.4297,1127.5,372.4297,1131.5,368.4297" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="907" x2="1133.5" y1="368.4297" y2="368.4297"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="116" x="914" y="363.3638">LPSPIClockDisable</text><polygon fill="#A80036" points="1022,406.1289,1032,410.1289,1022,414.1289,1026,410.1289" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="907" x2="1028" y1="410.1289" y2="410.1289"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="103" x="914" y="405.063">Pll2ClockDisable</text><path d="M1039,381.4297 L1039,421.4297 L1170,421.4297 L1170,391.4297 L1160,381.4297 L1039,381.4297 " fill="#FBFB77" filter="url(#fcbnkjoqvuo08)" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M1160,381.4297 L1160,391.4297 L1170,391.4297 L1160,381.4297 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="98" x="1045" y="398.4966">Critical section!</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="110" x="1045" y="413.6294">mutex necessary</text><polygon fill="#A80036" points="250.5,447.8281,260.5,451.8281,250.5,455.8281,254.5,451.8281" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="59.5" x2="256.5" y1="451.8281" y2="451.8281"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="179" x="66.5" y="446.7622">ResetCpuFrequencyRequest</text><polygon fill="#A80036" points="474.5,476.9609,484.5,480.9609,474.5,484.9609,478.5,480.9609" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="262.5" x2="480.5" y1="480.9609" y2="480.9609"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="200" x="269.5" y="475.895">RequestCpuFrequencyMessage</text><polygon fill="#A80036" points="677.5,506.0938,687.5,510.0938,677.5,514.0938,681.5,510.0938" style="stroke: #A80036; stroke-width: 1.0;"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="486.5" x2="683.5" y1="510.0938" y2="510.0938"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="179" x="493.5" y="505.0278">ResetCpuFrequencyRequest</text><!--MD5=[b2ae224b2d638e53bd7e0f72551ef878]
+@startuml
+
+service_eInk -> eInkSentinel : SetFrequencyValueRequest
+eInkSentinel -> PowerManager : RequestCpuFrequencyMessage
+
+PowerManager -> CpuGovernor : SetCpuFrequencyRequest
+
+service_eInk -> EinkDisplay : powerOn
+EinkDisplay -> driverLPSPI : Enable
+
+driverLPSPI -> driverPLL2 : Pll2ClockEnable
+note right
+Critical section!
+mutex necessary
+end note
+
+driverLPSPI -> clock_config : LPSPIClockEnable
+
+...screen redraw...
+
+EinkDisplay -> driverLPSPI : Disable
+
+driverLPSPI -> clock_config : LPSPIClockDisable
+
+driverLPSPI -> driverPLL2 : Pll2ClockDisable
+note right
+Critical section!
+mutex necessary
+end note
+
+service_eInk -> eInkSentinel : ResetCpuFrequencyRequest
+eInkSentinel -> PowerManager : RequestCpuFrequencyMessage
+
+PowerManager -> CpuGovernor : ResetCpuFrequencyRequest
+
+@enduml
+
+PlantUML version 1.2019.11(Sun Sep 22 12:02:15 CEST 2019)
+(EPL source distribution)
+Java Runtime: OpenJDK Runtime Environment
+JVM: OpenJDK 64-Bit Server VM
+Java Version: 14.0.2+12-46
+Operating System: Linux
+Default Encoding: UTF-8
+Language: pl
+Country: PL
+--></g></svg><
\ No newline at end of file
A module-sys/SystemManager/messages/PhoneModeRequest.hpp => module-sys/SystemManager/messages/PhoneModeRequest.hpp +25 -0
@@ 0,0 1,25 @@
+// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <module-sys/PhoneModes/Common.hpp>
+
+namespace sys
+{
+ class PhoneModeRequest : public sys::DataMessage
+ {
+ public:
+ explicit PhoneModeRequest(phone_modes::PhoneMode mode)
+ : sys::DataMessage(MessageType::MessageTypeUninitialized), mode{mode}
+ {}
+
+ [[nodiscard]] auto getPhoneMode() const noexcept -> phone_modes::PhoneMode
+ {
+ return mode;
+ }
+
+ private:
+ phone_modes::PhoneMode mode;
+ };
+} // namespace sys
M module-utils/test/CMakeLists.txt => module-utils/test/CMakeLists.txt +9 -0
@@ 1,5 1,14 @@
cmake_minimum_required(VERSION 3.12)
+add_catch2_executable(
+ NAME
+ utils-conditional-invoke-tests
+ SRCS
+ test-Utility-ConditionalInvoke.cpp
+ LIBS
+ module-utils
+)
+
# Phone number tests
add_catch2_executable(
NAME
A module-utils/test/test-Utility-ConditionalInvoke.cpp => module-utils/test/test-Utility-ConditionalInvoke.cpp +203 -0
@@ 0,0 1,203 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#define CATCH_CONFIG_MAIN
+#include <catch2/catch.hpp>
+
+#include <module-utils/utility/Utility.hpp>
+
+struct SomeStruct
+{
+ int value;
+};
+
+class ExampleClass
+{
+ public:
+ int function1(int x, const SomeStruct &s)
+ {
+ return x + s.value;
+ }
+
+ void function2()
+ {}
+
+ int function3(int x, SomeStruct &s)
+ {
+ return x + s.value;
+ }
+
+ static int static_function1(int x, const SomeStruct &s)
+ {
+ return x + s.value;
+ }
+
+ static void static_function2()
+ {}
+
+ static int static_function3(int x, SomeStruct &s)
+ {
+ return x + s.value;
+ }
+};
+
+int global_function1(int x, const SomeStruct &s)
+{
+ return x + s.value;
+}
+
+void global_function2()
+{}
+
+int global_function3(int x, SomeStruct &s)
+{
+ return x + s.value;
+}
+
+TEST_CASE("Successful global function call")
+{
+ const auto guard = []() { return true; };
+
+ const auto [called1, ret1] = utility::conditionally_invoke(guard, &global_function1, 10, SomeStruct{5});
+ REQUIRE(called1 == true);
+ REQUIRE(ret1 == 15);
+
+ int x = 10;
+ SomeStruct s1{10};
+ const auto [called2, ret2] = utility::conditionally_invoke(guard, &global_function1, x, s1);
+ REQUIRE(called2 == true);
+ REQUIRE(ret2 == 20);
+
+ const auto called3 = utility::conditionally_invoke(guard, &global_function2);
+ REQUIRE(called3 == true);
+
+ SomeStruct s2{15};
+ const auto [called4, ret4] = utility::conditionally_invoke(guard, &global_function3, 10, std::ref(s2));
+ REQUIRE(called4 == true);
+ REQUIRE(ret4 == 25);
+}
+
+TEST_CASE("Failed global function call")
+{
+ const auto guard = []() { return false; };
+
+ const auto [called1, ret1] = utility::conditionally_invoke(guard, &global_function1, 10, SomeStruct{5});
+ REQUIRE(called1 == false);
+ REQUIRE(ret1 == 0);
+
+ int x = 10;
+ SomeStruct s1{10};
+ const auto [called2, ret2] = utility::conditionally_invoke(guard, &global_function1, x, s1);
+ REQUIRE(called2 == false);
+ REQUIRE(ret2 == 0);
+
+ const auto called3 = utility::conditionally_invoke(guard, &global_function2);
+ REQUIRE(called3 == false);
+
+ SomeStruct s2{15};
+ const auto [called4, ret4] = utility::conditionally_invoke(guard, &global_function3, 10, std::ref(s2));
+ REQUIRE(called4 == false);
+ REQUIRE(ret4 == 0);
+}
+
+TEST_CASE("Successful class static function call")
+{
+ const auto guard = []() { return true; };
+
+ const auto [called1, ret1] =
+ utility::conditionally_invoke(guard, &ExampleClass::static_function1, 10, SomeStruct{5});
+ REQUIRE(called1 == true);
+ REQUIRE(ret1 == 15);
+
+ int x = 10;
+ SomeStruct s1{10};
+ const auto [called2, ret2] = utility::conditionally_invoke(guard, &ExampleClass::static_function1, x, s1);
+ REQUIRE(called2 == true);
+ REQUIRE(ret2 == 20);
+
+ const auto called3 = utility::conditionally_invoke(guard, &ExampleClass::static_function2);
+ REQUIRE(called3 == true);
+
+ SomeStruct s2{15};
+ const auto [called4, ret4] =
+ utility::conditionally_invoke(guard, &ExampleClass::static_function3, 10, std::ref(s2));
+ REQUIRE(called4 == true);
+ REQUIRE(ret4 == 25);
+}
+
+TEST_CASE("Failed class static function call")
+{
+ const auto guard = []() { return false; };
+
+ const auto [called1, ret1] =
+ utility::conditionally_invoke(guard, &ExampleClass::static_function1, 10, SomeStruct{5});
+ REQUIRE(called1 == false);
+ REQUIRE(ret1 == 0);
+
+ int x = 10;
+ SomeStruct s1{10};
+ const auto [called2, ret2] = utility::conditionally_invoke(guard, &ExampleClass::static_function1, x, s1);
+ REQUIRE(called2 == false);
+ REQUIRE(ret2 == 0);
+
+ const auto called3 = utility::conditionally_invoke(guard, &ExampleClass::static_function2);
+ REQUIRE(called3 == false);
+
+ SomeStruct s2{15};
+ const auto [called4, ret4] =
+ utility::conditionally_invoke(guard, &ExampleClass::static_function3, 10, std::ref(s2));
+ REQUIRE(called4 == false);
+ REQUIRE(ret4 == 0);
+}
+
+TEST_CASE("Successful class member function call")
+{
+ ExampleClass instance;
+ const auto guard = []() { return true; };
+
+ const auto [called1, ret1] =
+ utility::conditionally_invoke(guard, instance, &ExampleClass::function1, 10, SomeStruct{5});
+ REQUIRE(called1 == true);
+ REQUIRE(ret1 == 15);
+
+ int x = 10;
+ SomeStruct s1{10};
+ const auto [called2, ret2] = utility::conditionally_invoke(guard, instance, &ExampleClass::function1, x, s1);
+ REQUIRE(called2 == true);
+ REQUIRE(ret2 == 20);
+
+ const auto called3 = utility::conditionally_invoke(guard, instance, &ExampleClass::function2);
+ REQUIRE(called3 == true);
+
+ SomeStruct s2{15};
+ const auto [called4, ret4] =
+ utility::conditionally_invoke(guard, instance, &ExampleClass::function3, 10, std::ref(s2));
+ REQUIRE(called4 == true);
+ REQUIRE(ret4 == 25);
+}
+
+TEST_CASE("Failed class member function call")
+{
+ ExampleClass instance;
+ const auto guard = []() { return false; };
+
+ const auto [called1, ret1] =
+ utility::conditionally_invoke(guard, instance, &ExampleClass::function1, 10, SomeStruct{5});
+ REQUIRE(called1 == false);
+ REQUIRE(ret1 == 0);
+
+ int x = 10;
+ SomeStruct s1{10};
+ const auto [called2, ret2] = utility::conditionally_invoke(guard, instance, &ExampleClass::function1, x, s1);
+ REQUIRE(called2 == false);
+ REQUIRE(ret2 == 0);
+
+ const auto called3 = utility::conditionally_invoke(guard, instance, &ExampleClass::function2);
+ REQUIRE(called3 == false);
+
+ SomeStruct s2{15};
+ const auto [called4, ret4] =
+ utility::conditionally_invoke(guard, instance, &ExampleClass::function3, 10, std::ref(s2));
+ REQUIRE(called4 == false);
+ REQUIRE(ret4 == 0);
+}
A module-utils/utility/Utility.hpp => module-utils/utility/Utility.hpp +87 -0
@@ 0,0 1,87 @@
+// 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 <functional>
+#include <utility>
+#include <type_traits>
+
+namespace utility
+{
+ using Guard = std::function<bool()>;
+
+ /// Invokes a function if specified conditions are met.
+ /// \tparam F Function signature
+ /// \tparam Args Function arguments
+ /// \param guard Conditions to be met
+ /// \param func Callable object
+ /// \param args Function arguments
+ /// \return If the function returns void - a flag indicating whether the conditions were met and the function has
+ /// been called. If the function returns a type - a pair of: a flag indicating whether the conditions were met, and
+ /// a function's return value.
+ template <typename F, typename... Args>
+ auto conditionally_invoke(const Guard &guard,
+ const F &func,
+ Args... args) noexcept(std::is_nothrow_invocable_v<F, Args...>)
+ {
+ using ResultType = typename std::invoke_result_t<F, Args...>;
+ constexpr auto isVoidFunction = std::is_void_v<ResultType>;
+ if (!guard()) {
+ if constexpr (isVoidFunction) {
+ return false;
+ }
+ else {
+ return std::pair(false, ResultType{});
+ }
+ }
+
+ if constexpr (isVoidFunction) {
+ std::invoke(func, std::forward<Args>(args)...);
+ return true;
+ }
+ else {
+ return std::pair(true, std::invoke(func, std::forward<Args>(args)...));
+ }
+ }
+
+ /// Invokes a member function if specified conditions are met.
+ /// \tparam T Class which contains the member function F
+ /// \tparam F Function signature
+ /// \tparam Args Function arguments
+ /// \param guard Conditions to be met
+ /// \param self Pointer to the class T instance
+ /// \param func Callable object
+ /// \param args Function arguments
+ /// \return If the function returns void - a flag indicating whether the conditions were met and the function has
+ /// been called. If the function returns a type - a pair of: a flag indicating whether the conditions were met, and
+ /// a function's return value.
+ template <class T,
+ typename F,
+ typename... Args,
+ typename std::enable_if_t<std::is_invocable_v<F, T, Args...>, bool> = false>
+ auto conditionally_invoke(const Guard &guard,
+ T &&self,
+ const F &func,
+ Args... args) noexcept(std::is_nothrow_invocable_v<F, T, Args...>)
+ {
+ using ResultType = typename std::invoke_result_t<F, T, Args...>;
+ constexpr auto isVoidFunction = std::is_void_v<ResultType>;
+ if (!guard()) {
+ if constexpr (isVoidFunction) {
+ return false;
+ }
+ else {
+ return std::pair(false, ResultType{});
+ }
+ }
+
+ if constexpr (isVoidFunction) {
+ std::invoke(func, std::forward<T>(self), std::forward<Args>(args)...);
+ return true;
+ }
+ else {
+ return std::pair(true, std::invoke(func, std::forward<T>(self), std::forward<Args>(args)...));
+ }
+ }
+} // namespace utility
M source/MessageType.hpp => source/MessageType.hpp +0 -3
@@ 173,9 173,6 @@ enum class MessageType
SystemManagerCpuFrequency,
SystemManagerRegistration,
- // battery charger messages
- EVMBatteryLevel,
- EVMChargerPlugged,
// rtc messages
EVMMinuteUpdated, ///< This message is send to current focused application on every minute time change.
EVMTimeUpdated, ///< This message is send on every time update.
R test/pytest/service-desktop/test_calllog.py => test/pytest/service-desktop/disabled_test_calllog.py +0 -0
R test/pytest/service-desktop/test_messages.py => test/pytest/service-desktop/disabled_test_messages.py +25 -24
@@ 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
import pytest
@@ 8,50 8,51 @@ from harness.interface.defs import status
@pytest.mark.service_desktop_test
def test_messages(harness):
# getting the messages count
- body = {"count": True}
+ body = {"category": "message", "count": True}
ret = harness.endpoint_request("messages", "get", body)
assert ret["status"] == status["OK"]
count = ret["body"]["count"]
if count == 0:
- pytest.skip("No contacts entries, skipping")
+ pytest.skip("No messages entries, skipping")
# getting all the messages
- body = {"count": count}
+ body = {"category": "message", "limit": count, "offset": 0}
ret = harness.endpoint_request("messages", "get", body)
assert ret["status"] == status["OK"]
- messages = ret["body"]
+ messages = ret["body"]["entries"] # getting entries
messages_count = len(messages)
assert messages_count == count
- # remove message
- sms_to_remove = messages[0]
- body = {"id": sms_to_remove["id"]}
- ret = harness.endpoint_request("messages", "del", body)
- assert ret["status"] == status["OK"]
-
- # getting the messages count again
- body = {"count": True}
+ # getting a number of messages
+ number_of_requested_messages = 3
+ body = {"category": "message", "limit": number_of_requested_messages, "offset": 0}
ret = harness.endpoint_request("messages", "get", body)
assert ret["status"] == status["OK"]
- assert ret["body"]["count"] == count - 1
+ messages = ret["body"]["entries"] # getting entries
+ messages_count = len(messages)
+ assert messages_count == number_of_requested_messages
- # getting messages binded to contactID
- contact_id = 2 # in test dataset this one has some messages
- body = {"contactID": contact_id}
+ # getting messages binded to threadID
+ thread_id = 1
+ body = {"category": "message", "threadID": thread_id, "limit": 10, "offset": 0}
ret = harness.endpoint_request("messages", "get", body)
assert ret["status"] == status["OK"]
- for message in ret["body"]:
- assert message["contactID"] == contact_id
+ for message in ret["body"]["entries"]:
+ assert message["threadID"] == thread_id
- # getting messages binded to threadID
- thread_id = 1
- body = {"threadID": thread_id, "count": 10}
+ # remove message
+ sms_to_remove = messages[0]
+ body = {"category": "message", "messageID": sms_to_remove["messageID"]}
+ ret = harness.endpoint_request("messages", "del", body)
+ assert ret["status"] == status["OK"]
+
+ # getting the messages count again
+ body = {"category": "message", "count": True}
ret = harness.endpoint_request("messages", "get", body)
assert ret["status"] == status["OK"]
- for message in ret["body"]:
- assert message["threadID"] == thread_id
+ assert ret["body"]["count"] == count - 1
M test/pytest/service-desktop/test_contacts.py => test/pytest/service-desktop/test_contacts.py +16 -16
@@ 7,49 7,49 @@ from harness.interface.defs import status
@pytest.mark.service_desktop_test
def test_contacts(harness):
# getting the contacts count
- body = {"count": True}
+ body = {"limit": True}
ret = harness.endpoint_request("contacts", "get", body)
assert ret["status"] == status["OK"]
- count = ret["body"]["count"]
+ count = ret["body"]["limit"]
if count == 0:
pytest.skip("No contacts entries, skipping")
# getting all contacts
- batch_size = 30
+ batch_size = 10
divider = int(count / batch_size)
reminder = count % batch_size
contacts = []
for i in range(divider):
- body = {"count": batch_size, "offset": batch_size*i}
+ body = {"limit": batch_size, "offset": batch_size*i}
ret = harness.endpoint_request("contacts", "get", body)
assert ret["status"] == status["OK"]
- contacts = contacts + ret["body"]
+ contacts = contacts + ret["body"]["entries"]
- body = {"count": reminder, "offset": count-reminder}
+ body = {"limit": reminder, "offset": count-reminder}
ret = harness.endpoint_request("contacts", "get", body)
assert ret["status"] == status["OK"]
- contacts = contacts + ret["body"]
+ contacts = contacts + ret["body"]["entries"]
contacts_length = len(contacts)
assert contacts_length
assert contacts_length == count
# try to get more than available
- batch_size = 30
+ batch_size = 10
divider = int((count+10) / batch_size)
reminder = (count+10) % batch_size
contacts = []
for i in range(divider):
- body = {"count": batch_size, "offset": batch_size * i}
+ body = {"limit": batch_size, "offset": batch_size * i}
ret = harness.endpoint_request("contacts", "get", body)
assert ret["status"] == status["OK"]
- contacts = contacts + ret["body"]
+ contacts = contacts + ret["body"]["entries"]
- body = {"count": reminder, "offset": (count+10)-reminder}
+ body = {"limit": reminder, "offset": (count+10)-reminder}
ret = harness.endpoint_request("contacts", "get", body)
assert ret["status"] == status["OK"]
- contacts = contacts + ret["body"]
+ contacts = contacts + ret["body"]["entries"]
contacts_length = len(contacts)
assert contacts_length
@@ 78,10 78,10 @@ def test_contacts(harness):
assert ret["status"] == status["NotAcceptable"]
# checking count after adding
- body = {"count": True}
+ body = {"limit": True}
ret = harness.endpoint_request("contacts", "get", body)
assert ret["status"] == status["OK"]
- assert ret["body"]["count"] == count + 1
+ assert ret["body"]["limit"] == count + 1
# updating existing contact
body = {"address": "6 Czeczota St.\n02600 Warsaw",
@@ 112,8 112,8 @@ def test_contacts(harness):
assert ret["status"] == status["OK"]
# verifying count
- body = {"count": True}
+ body = {"limit": True}
ret = harness.endpoint_request("contacts", "get", body)
assert ret["status"] == status["OK"]
- assert ret["body"]["count"] == count
+ assert ret["body"]["limit"] == count
M test/pytest/service-desktop/test_templates.py => test/pytest/service-desktop/test_templates.py +33 -17
@@ 1,62 1,78 @@
-# 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
import pytest
from harness.interface.defs import status
@pytest.mark.service_desktop_test
-def test_messages(harness):
+def test_templates(harness):
# getting the templates count
- body = {"template": True, "count": True}
+ body = {"category": "template", "count": True}
ret = harness.endpoint_request("messages", "get", body)
assert ret["status"] == status["OK"]
count = ret["body"]["count"]
if count == 0:
- body = {"template": True, "text": "first template"}
- ret = harness.endpoint_request("messages", "put", body)
+ body = {"category": "template", "templateBody": "first template"}
+ ret = harness.endpoint_request("messages", "post", body)
assert ret["status"] == status["OK"]
- body = {"template": True, "count": True}
+ body = {"category": "template", "count": True}
ret = harness.endpoint_request("messages", "get", body)
assert ret["status"] == status["OK"]
count = ret["body"]["count"]
assert count
# getting all templates
- body = {"template": True, "count": count}
+ body = {"category": "template", "limit": count}
+ ret = harness.endpoint_request("messages", "get", body)
+ assert ret["status"] == status["OK"]
+ assert len(ret["body"]["entries"]) == count
+
+ # getting a number of templates
+ number_of_requested_templates = 3
+ body = {"category": "template", "limit": number_of_requested_templates, "offset": 0}
+ ret = harness.endpoint_request("messages", "get", body)
+ assert ret["status"] == status["OK"]
+
+ templates = ret["body"]["entries"] # getting entries
+ templates_count = len(templates)
+ assert templates_count == number_of_requested_templates
+
+ # getting template by ID
+ body = {"category": "template", "templateID": 1}
ret = harness.endpoint_request("messages", "get", body)
assert ret["status"] == status["OK"]
- assert len(ret["body"]) == count
# adding new template
- body = {"template": True, "text": "test template"}
- ret = harness.endpoint_request("messages", "put", body)
+ body = {"category": "template", "templateBody": "test template"}
+ ret = harness.endpoint_request("messages", "post", body)
assert ret["status"] == status["OK"]
# getting the templates count again
- body = {"template": True, "count": True}
+ body = {"category": "template", "count": True}
ret = harness.endpoint_request("messages", "get", body)
assert ret["status"] == status["OK"]
assert ret["body"]["count"] == count + 1
# getting template to remove
- body = {"template": True, "count": count + 1}
+ body = {"category": "template", "limit": count + 1}
ret = harness.endpoint_request("messages", "get", body)
assert ret["status"] == status["OK"]
- for template in ret["body"]:
- if template["text"] == "test template":
- id = template["id"]
+ templateid = 0
+ for template in ret["body"]["entries"]:
+ if template["templateBody"] == "test template":
+ templateid = template["templateID"]
break
# removing template
- body = {"template": True, "id": id}
+ body = {"category": "template", "templateID": templateid}
ret = harness.endpoint_request("messages", "del", body)
assert ret["status"] == status["OK"]
# getting the templates count again
- body = {"template": True, "count": True}
+ body = {"category": "template", "count": True}
ret = harness.endpoint_request("messages", "get", body)
assert ret["status"] == status["OK"]
assert ret["body"]["count"] == count
A test/pytest/service-desktop/test_threads.py => test/pytest/service-desktop/test_threads.py +27 -0
@@ 0,0 1,27 @@
+# Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+import pytest
+from harness.interface.defs import status
+
+
+@pytest.mark.service_desktop_test
+def test_threads(harness):
+ # getting all threads
+ body = {"category": "thread"}
+ ret = harness.endpoint_request("messages", "get", body)
+ assert ret["status"] == status["OK"]
+
+ # getting a number of threads
+ number_of_requested_threads = 3
+ body = {"category": "thread", "limit": number_of_requested_threads, "offset": 0}
+ ret = harness.endpoint_request("messages", "get", body)
+ assert ret["status"] == status["OK"]
+
+ threads = ret["body"]["entries"] # getting entries
+ threads_count = len(threads)
+ assert threads_count == number_of_requested_threads
+
+ # set thread as read
+ body = {"category": "thread", "threadID": 1, "isUnread": False}
+ ret = harness.endpoint_request("messages", "put", body)
+ assert ret["status"] == status["OK"]
M test/pytest/test_search_sms.py => test/pytest/test_search_sms.py +2 -1
@@ 5,9 5,10 @@ import pytest
from harness.interface.defs import key_codes
+
@pytest.mark.rt1051
@pytest.mark.usefixtures("phone_unlocked")
def test_search_sms(harness, sms_text, phone_number):
- body = {"messageBody": sms_text, "phoneNumber": str(phone_number)}
+ body = {"category": "message", "messageBody": sms_text, "phoneNumber": str(phone_number)}
messages = harness.endpoint_request("messages", "get", body)["body"]
assert len(messages) != 0
M test/pytest/test_send_message.py => test/pytest/test_send_message.py +10 -10
@@ 9,27 9,27 @@ from harness.interface.CDCSerial import Keytype
def erase_all_templates(harness):
# getting the templates count
- body = {"template": True, "count": True}
+ body = {"category": "template", "count": True}
ret = harness.endpoint_request("messages", "get", body)
assert ret["status"] == status["OK"]
count = ret["body"]["count"]
# getting all templates
- body = {"template": True, "count": count}
+ body = {"category": "template", "limit": count}
ret = harness.endpoint_request("messages", "get", body)
assert ret["status"] == status["OK"]
- assert len(ret["body"]) == count
+ assert len(ret["body"][1][1]) == count
- for template in ret["body"]:
- body = {"template": True, "id": template["id"]}
+ for template in ret["body"][1][1]:
+ body = {"category": "template", "templateID": template["templateID"]}
del_res = harness.endpoint_request("messages", "del", body)
assert del_res["status"] == status["OK"]
def add_new_template(harness, template_text: str):
# adding new template
- body = {"template": True, "text": template_text}
- ret = harness.endpoint_request("messages", "put", body)
+ body = {"category": "template", "templateBody": template_text}
+ ret = harness.endpoint_request("messages", "post", body)
assert ret["status"] == status["OK"]
@@ 72,19 72,19 @@ def erase_contacts_by_name(harness, name):
def get_message_by_text(harness, message: str, phone_number: str):
- body = {"messageBody": message, "phoneNumber": phone_number}
+ body = {"category": "message", "messageBody": message, "phoneNumber": phone_number}
return harness.endpoint_request("messages", "get", body)["body"]
# default sms type is draft
def prepare_sms(harness, message: str, phone_number: str, sms_type: int = 1):
body = {"smsCommand": "smsAdd", "messageBody": message, "phoneNumber": phone_number, "type": sms_type}
- return harness.endpoint_request("developerMode", "put", body)
+ return harness.endpoint_request("developerMode", "post", body)
def prepare_sms_template(harness, message: str, phone_number: str):
body = {"template": True, "messageBody": message, "phoneNumber": phone_number}
- return harness.endpoint_request("developerMode", "put", body)
+ return harness.endpoint_request("developerMode", "post", body)
def compare_messages(old_messages, new_messages, sms_type: SMSType = SMSType.OUTBOX):
M test/search_sms.py => test/search_sms.py +1 -2
@@ 14,7 14,7 @@ from harness.interface.error import TestError, Error
def search_sms(harness, message: str, phone_number: str):
@harness.with_phone_unlocked
def do_it(connection):
- body = {"messageBody": message, "phoneNumber": phone_number}
+ body = {"category": "message", "messageBody": message, "phoneNumber": phone_number}
messages = harness.endpoint_request("messages", "get", body)["body"]
print(f'Found {len(messages)} messages')
@@ 49,4 49,3 @@ if __name__ == "__main__":
except TestError as err:
log.error(err)
exit(err.get_error_code())
-