Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,7 @@ list(APPEND SOURCE_FILES
displayapp/screens/settings/SettingChimes.cpp
displayapp/screens/settings/SettingShakeThreshold.cpp
displayapp/screens/settings/SettingBluetooth.cpp
displayapp/screens/settings/SettingActivity.cpp

## Watch faces
displayapp/screens/WatchFaceAnalog.cpp
Expand Down Expand Up @@ -453,6 +454,7 @@ list(APPEND SOURCE_FILES
components/datetime/DateTimeController.cpp
components/brightness/BrightnessController.cpp
components/motion/MotionController.cpp
components/activity/ActivityController.cpp
components/ble/NimbleController.cpp
components/ble/DeviceInformationService.cpp
components/ble/CurrentTimeClient.cpp
Expand Down Expand Up @@ -522,6 +524,7 @@ list(APPEND RECOVERY_SOURCE_FILES
components/datetime/DateTimeController.cpp
components/brightness/BrightnessController.cpp
components/motion/MotionController.cpp
components/activity/ActivityController.cpp
components/ble/NimbleController.cpp
components/ble/DeviceInformationService.cpp
components/ble/CurrentTimeClient.cpp
Expand Down Expand Up @@ -643,6 +646,7 @@ set(INCLUDE_FILES
components/datetime/DateTimeController.h
components/brightness/BrightnessController.h
components/motion/MotionController.h
components/activity/ActivityController.h
components/firmwarevalidator/FirmwareValidator.h
components/ble/BleController.h
components/ble/NotificationManager.h
Expand Down
27 changes: 27 additions & 0 deletions src/components/activity/ActivityController.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include "components/activity/ActivityController.h"

using namespace Pinetime::Controllers;

void ActivityController::UpdateSteps(uint32_t nbSteps, uint8_t minutes) {
uint8_t hourSegment = minutes * (stepHistory.Size() - 2) / 60;
if (hourSegment != prevHourSegment && prevHourSegment != UINT8_MAX) {
stepHistory++;
canNotify = true;
}
prevHourSegment = hourSegment;
stepHistory[0] = nbSteps;

if (stepHistory[0] < stepHistory[stepHistory.Size() - 1]) {
for (uint8_t i = 1; i < stepHistory.Size(); i++) {
stepHistory[i] = 0;
}
}
}

bool ActivityController::ShouldNotify(uint16_t thresh) {
if (canNotify && stepHistory[stepHistory.Size() - 1] - stepHistory[1] < thresh) {
canNotify = false;
return true;
}
return false;
}
24 changes: 24 additions & 0 deletions src/components/activity/ActivityController.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#pragma once

#include <array>
#include <cstdint>

#include "components/datetime/DateTimeController.h"
#include "components/settings/Settings.h"
#include "components/motion/MotionController.h"
#include "utility/CircularBuffer.h"

namespace Pinetime {
namespace Controllers {
class ActivityController {
public:
void UpdateSteps(uint32_t nbSteps, uint8_t minutes);
bool ShouldNotify(uint16_t thresh);

private:
Utility::CircularBuffer<uint32_t, 4> stepHistory = {};
uint8_t prevHourSegment = UINT8_MAX;
bool canNotify = false;
};
}
}
26 changes: 26 additions & 0 deletions src/components/settings/Settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ namespace Pinetime {
enum class ClockType : uint8_t { H24, H12 };
enum class Notification : uint8_t { On, Off, Sleep };
enum class ChimesOption : uint8_t { None, Hours, HalfHours };
enum class Activity : uint8_t { On, Off };
enum class WakeUpMode : uint8_t {
SingleTap = 0,
DoubleTap = 1,
Expand Down Expand Up @@ -86,6 +87,28 @@ namespace Pinetime {
return settings.chimesOption;
};

void SetActivity(Activity activity) {
if (activity != settings.activity) {
settingsChanged = true;
}
settings.activity = activity;
};

Activity GetActivity() const {
return settings.activity;
};

void SetActivityThresh(uint32_t activityThresh) {
if (activityThresh != settings.activityThresh) {
settingsChanged = true;
}
settings.activityThresh = activityThresh;
};

uint16_t GetActivityThresh() const {
return settings.activityThresh;
};

void SetPTSColorTime(Colors colorTime) {
if (colorTime != settings.PTS.ColorTime)
settingsChanged = true;
Expand Down Expand Up @@ -292,6 +315,9 @@ namespace Pinetime {
Pinetime::Applications::WatchFace watchFace = Pinetime::Applications::WatchFace::Digital;
ChimesOption chimesOption = ChimesOption::None;

Activity activity = Activity::On;
uint16_t activityThresh = 75;

PineTimeStyle PTS;

WatchFaceInfineat watchFaceInfineat;
Expand Down
1 change: 1 addition & 0 deletions src/displayapp/Apps.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ namespace Pinetime {
SettingChimes,
SettingShakeThreshold,
SettingBluetooth,
SettingActivity,
Error
};
}
Expand Down
4 changes: 4 additions & 0 deletions src/displayapp/DisplayApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
#include "displayapp/screens/settings/SettingChimes.h"
#include "displayapp/screens/settings/SettingShakeThreshold.h"
#include "displayapp/screens/settings/SettingBluetooth.h"
#include "displayapp/screens/settings/SettingActivity.h"

#include "libs/lv_conf.h"

Expand Down Expand Up @@ -500,6 +501,9 @@ void DisplayApp::LoadScreen(Apps app, DisplayApp::FullRefreshDirections directio
case Apps::SettingBluetooth:
currentScreen = std::make_unique<Screens::SettingBluetooth>(this, settingsController);
break;
case Apps::SettingActivity:
currentScreen = std::make_unique<Screens::SettingActivity>(settingsController);
break;
case Apps::BatteryInfo:
currentScreen = std::make_unique<Screens::BatteryInfo>(batteryController);
break;
Expand Down
103 changes: 103 additions & 0 deletions src/displayapp/screens/settings/SettingActivity.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#include "displayapp/screens/settings/SettingActivity.h"

#include <cstdint>
#include <cinttypes>

#include "displayapp/DisplayApp.h"
#include "displayapp/screens/Symbols.h"

using namespace Pinetime::Applications::Screens;

namespace {
void EventHandler(lv_obj_t* obj, lv_event_t event) {
SettingActivity* screen = static_cast<SettingActivity*>(obj->user_data);
screen->UpdateSelected(obj, event);
}
}

SettingActivity::SettingActivity(Controllers::Settings& settingsController) : settingsController {settingsController} {
lv_obj_t* container = lv_cont_create(lv_scr_act(), nullptr);

lv_obj_set_style_local_bg_opa(container, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP);
lv_obj_set_style_local_pad_all(container, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 10);
lv_obj_set_style_local_pad_inner(container, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 5);
lv_obj_set_style_local_border_width(container, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 0);
lv_obj_set_pos(container, 30, 60);
lv_obj_set_width(container, LV_HOR_RES - 50);
lv_obj_set_height(container, LV_VER_RES - 60);
lv_cont_set_layout(container, LV_LAYOUT_COLUMN_LEFT);

lv_obj_t* title = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_text_static(title, "Activity notifications");
lv_label_set_align(title, LV_LABEL_ALIGN_CENTER);
lv_obj_align(title, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 15, 15);

lv_obj_t* icon = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_color(icon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_ORANGE);

lv_label_set_text_static(icon, Symbols::shoe);
lv_label_set_align(icon, LV_LABEL_ALIGN_CENTER);
lv_obj_align(icon, title, LV_ALIGN_OUT_LEFT_MID, -10, 0);

enabled = lv_checkbox_create(container, nullptr);
lv_checkbox_set_text(enabled, "Enabled");
if (settingsController.GetActivity() == Controllers::Settings::Activity::On) {
lv_checkbox_set_checked(enabled, true);
}
enabled->user_data = this;
lv_obj_set_event_cb(enabled, EventHandler);

stepValue = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_font(stepValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42);
lv_label_set_text_fmt(stepValue, "%" PRIu32, settingsController.GetActivityThresh());
lv_label_set_align(stepValue, LV_LABEL_ALIGN_CENTER);
lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_CENTER, 0, 20);

btnPlus = lv_btn_create(lv_scr_act(), nullptr);
btnPlus->user_data = this;
lv_obj_set_size(btnPlus, 80, 50);
lv_obj_align(btnPlus, lv_scr_act(), LV_ALIGN_CENTER, 55, 80);
lv_obj_t* lblPlus = lv_label_create(btnPlus, nullptr);
lv_label_set_text_static(lblPlus, "+");
lv_obj_set_event_cb(btnPlus, EventHandler);

btnMinus = lv_btn_create(lv_scr_act(), nullptr);
btnMinus->user_data = this;
lv_obj_set_size(btnMinus, 80, 50);
lv_obj_set_event_cb(btnMinus, EventHandler);
lv_obj_align(btnMinus, lv_scr_act(), LV_ALIGN_CENTER, -55, 80);
lv_obj_t* lblMinus = lv_label_create(btnMinus, nullptr);
lv_label_set_text_static(lblMinus, "-");
}

SettingActivity::~SettingActivity() {
lv_obj_clean(lv_scr_act());
settingsController.SaveSettings();
}

void SettingActivity::UpdateSelected(lv_obj_t* object, lv_event_t event) {
uint16_t value = settingsController.GetActivityThresh();
if (object == btnPlus && event == LV_EVENT_PRESSED) {
value += 1;
if (value <= 15000) {
settingsController.SetActivityThresh(value);
lv_label_set_text_fmt(stepValue, "%" PRIu16, settingsController.GetActivityThresh());
lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_CENTER, 0, 20);
}
}

if (object == btnMinus && event == LV_EVENT_PRESSED) {
value -= 1;
if (value >= 1) {
settingsController.SetActivityThresh(value);
lv_label_set_text_fmt(stepValue, "%" PRIu16, settingsController.GetActivityThresh());
lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_CENTER, 0, 20);
}
}

if (object == enabled && event == LV_EVENT_VALUE_CHANGED) {
bool currentState = settingsController.GetActivity() == Controllers::Settings::Activity::On;
settingsController.SetActivity(currentState ? Controllers::Settings::Activity::Off : Controllers::Settings::Activity::On);
lv_checkbox_set_checked(enabled, !currentState);
}
}
28 changes: 28 additions & 0 deletions src/displayapp/screens/settings/SettingActivity.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#pragma once

#include <lvgl/lvgl.h>

#include "components/settings/Settings.h"
#include "displayapp/screens/Screen.h"

namespace Pinetime {
namespace Applications {
namespace Screens {
class SettingActivity : public Screen {
public:
explicit SettingActivity(Controllers::Settings& settingsController);
~SettingActivity() override;

void UpdateSelected(lv_obj_t* object, lv_event_t event);

private:
Controllers::Settings& settingsController;

lv_obj_t* enabled;
lv_obj_t* stepValue;
lv_obj_t* btnPlus;
lv_obj_t* btnMinus;
};
}
}
}
13 changes: 6 additions & 7 deletions src/displayapp/screens/settings/Settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ namespace Pinetime {
static constexpr int entriesPerScreen = 4;

// Increment this when more space is needed
static constexpr int nScreens = 3;
static constexpr int nScreens = 4;

static constexpr std::array<List::Applications, entriesPerScreen * nScreens> entries {{
{Symbols::sun, "Display", Apps::SettingDisplay},
Expand All @@ -45,13 +45,12 @@ namespace Pinetime {
{Symbols::tachometer, "Shake Calib.", Apps::SettingShakeThreshold},
{Symbols::check, "Firmware", Apps::FirmwareValidation},
{Symbols::bluetooth, "Bluetooth", Apps::SettingBluetooth},
{Symbols::list, "About", Apps::SysInfo},

// {Symbols::none, "None", Apps::None},
// {Symbols::none, "None", Apps::None},
// {Symbols::none, "None", Apps::None},
// {Symbols::none, "None", Apps::None},
{Symbols::shoe, "Activity", Apps::SettingActivity},

{Symbols::list, "About", Apps::SysInfo},
{Symbols::none, "None", Apps::None},
{Symbols::none, "None", Apps::None},
{Symbols::none, "None", Apps::None},
}};
ScreenList<nScreens> screens;
};
Expand Down
5 changes: 4 additions & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <drivers/Bma421.h>

#include "BootloaderVersion.h"
#include "components/activity/ActivityController.h"
#include "components/battery/BatteryController.h"
#include "components/ble/BleController.h"
#include "components/ble/NotificationManager.h"
Expand Down Expand Up @@ -108,6 +109,7 @@ Pinetime::Controllers::AlarmController alarmController {dateTimeController};
Pinetime::Controllers::TouchHandler touchHandler;
Pinetime::Controllers::ButtonHandler buttonHandler;
Pinetime::Controllers::BrightnessController brightnessController {};
Pinetime::Controllers::ActivityController activityController;

Pinetime::Applications::DisplayApp displayApp(lcd,
touchPanel,
Expand Down Expand Up @@ -144,7 +146,8 @@ Pinetime::System::SystemTask systemTask(spi,
heartRateApp,
fs,
touchHandler,
buttonHandler);
buttonHandler,
activityController);
int mallocFailedCount = 0;
int stackOverflowCount = 0;
extern "C" {
Expand Down
21 changes: 20 additions & 1 deletion src/systemtask/SystemTask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "BootErrors.h"

#include <memory>
#include <cstring>

using namespace Pinetime::System;

Expand Down Expand Up @@ -51,7 +52,8 @@ SystemTask::SystemTask(Drivers::SpiMaster& spi,
Pinetime::Applications::HeartRateTask& heartRateApp,
Pinetime::Controllers::FS& fs,
Pinetime::Controllers::TouchHandler& touchHandler,
Pinetime::Controllers::ButtonHandler& buttonHandler)
Pinetime::Controllers::ButtonHandler& buttonHandler,
Controllers::ActivityController& activityController)
: spi {spi},
spiNorFlash {spiNorFlash},
twiMaster {twiMaster},
Expand All @@ -72,6 +74,7 @@ SystemTask::SystemTask(Drivers::SpiMaster& spi,
fs {fs},
touchHandler {touchHandler},
buttonHandler {buttonHandler},
activityController {activityController},
nimbleController(*this,
bleController,
dateTimeController,
Expand Down Expand Up @@ -180,6 +183,22 @@ void SystemTask::Work() {
while (true) {
UpdateMotion();

activityController.UpdateSteps(motionController.NbSteps(), dateTimeController.Minutes());
if (activityController.ShouldNotify(settingsController.GetActivityThresh()) &&
settingsController.GetActivity() == Controllers::Settings::Activity::On &&
settingsController.GetNotificationStatus() == Controllers::Settings::Notification::On) {
NRF_LOG_INFO("activity");
Controllers::NotificationManager::Notification notif;
constexpr char message[] = "Low activity\0Fewer steps than threshold in last hour. Try walking around.";
constexpr size_t messageSize = std::min(sizeof message - 1, Controllers::NotificationManager::MaximumMessageSize());
std::memcpy(notif.message.data(), message, messageSize);
notif.message[messageSize] = '\0';
notif.size = messageSize;
notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert;
notificationManager.Push(std::move(notif));
PushMessage(Messages::OnNewNotification);
}

Messages msg;
if (xQueueReceive(systemTasksMsgQueue, &msg, 100) == pdTRUE) {
switch (msg) {
Expand Down
Loading