Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add terminal watchface #932

Closed
wants to merge 38 commits into from
Closed
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
88f0190
add terminal watchface
13werwolf13 Jan 12, 2022
6dfa141
typo fix
Jan 12, 2022
1808a78
typo fix
13werwolf13 Jan 12, 2022
79273fe
typo fix
13werwolf13 Jan 12, 2022
4c58476
typo fix
13werwolf13 Jan 12, 2022
7288301
add menue item
13werwolf13 Jan 12, 2022
e540d10
add patch
13werwolf13 Jan 13, 2022
d3fd348
time format
13werwolf13 Jan 13, 2022
471a4c9
time format
13werwolf13 Jan 13, 2022
3afedca
time format
13werwolf13 Jan 13, 2022
ebbb31a
typo fix
13werwolf13 Jan 14, 2022
fc246be
typo fix
13werwolf13 Jan 15, 2022
e2f7e31
typo fix
13werwolf13 Jan 17, 2022
d684988
Update src/displayapp/screens/WatchFaceTerminal.cpp
13werwolf13 Jan 18, 2022
477a3a7
Update src/displayapp/screens/WatchFaceTerminal.cpp
13werwolf13 Jan 18, 2022
0ed45a9
typo fix
13werwolf13 Jan 18, 2022
68d3d9b
add ble state text output
13werwolf13 Jan 20, 2022
fda1c08
add ble state text output
13werwolf13 Jan 20, 2022
eb8bd4d
add ble state text output
13werwolf13 Jan 20, 2022
1e4a676
no errors, no warnings, no work..
13werwolf13 Jan 21, 2022
74eea9f
some fixes
13werwolf13 Jan 22, 2022
bba34f6
some fixes
13werwolf13 Jan 22, 2022
6853166
Update src/displayapp/screens/WatchFaceTerminal.cpp
13werwolf13 Feb 2, 2022
471a843
Update src/displayapp/screens/WatchFaceTerminal.cpp
13werwolf13 Feb 2, 2022
b4669be
Update src/displayapp/screens/WatchFaceTerminal.cpp
13werwolf13 Feb 2, 2022
265fec5
Update src/displayapp/screens/WatchFaceTerminal.cpp
13werwolf13 Feb 2, 2022
342ce8c
Update src/displayapp/screens/WatchFaceTerminal.cpp
13werwolf13 Feb 2, 2022
e6c0f32
Update src/displayapp/screens/WatchFaceTerminal.h
13werwolf13 Feb 2, 2022
12e1b0f
Update src/displayapp/screens/WatchFaceTerminal.cpp
13werwolf13 Feb 2, 2022
25fdafc
Update src/displayapp/screens/WatchFaceTerminal.cpp
13werwolf13 Feb 2, 2022
6bc6c1a
Update src/displayapp/screens/WatchFaceTerminal.h
13werwolf13 Feb 2, 2022
af483be
Update src/displayapp/screens/WatchFaceTerminal.cpp
13werwolf13 Feb 2, 2022
4d85028
Update src/displayapp/screens/WatchFaceTerminal.cpp
13werwolf13 Feb 2, 2022
6959d8c
Update src/displayapp/screens/WatchFaceTerminal.cpp
13werwolf13 Feb 2, 2022
60b6b4e
Update src/displayapp/screens/WatchFaceTerminal.cpp
13werwolf13 Feb 2, 2022
757ca2d
Update src/displayapp/screens/WatchFaceTerminal.cpp
13werwolf13 Feb 2, 2022
3515616
Update src/displayapp/screens/WatchFaceTerminal.cpp
13werwolf13 Feb 2, 2022
138a655
Update src/displayapp/screens/WatchFaceTerminal.h
13werwolf13 Feb 2, 2022
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
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,7 @@ list(APPEND SOURCE_FILES
displayapp/icons/bg_clock.c
displayapp/screens/WatchFaceAnalog.cpp
displayapp/screens/WatchFaceDigital.cpp
displayapp/screens/WatchFaceTerminal.cpp
displayapp/screens/PineTimeStyle.cpp

##
Expand Down
15 changes: 15 additions & 0 deletions src/displayapp/screens/Clock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "components/settings/Settings.h"
#include "displayapp/DisplayApp.h"
#include "displayapp/screens/WatchFaceDigital.h"
#include "displayapp/screens/WatchFaceTerminal.h"
#include "displayapp/screens/WatchFaceAnalog.h"
#include "displayapp/screens/PineTimeStyle.h"

Expand Down Expand Up @@ -41,6 +42,9 @@ Clock::Clock(DisplayApp* app,
case 2:
return PineTimeStyleScreen();
break;
case 3:
return WatchFaceTerminalScreen();
break;
}
return WatchFaceDigitalScreen();
}()} {
Expand Down Expand Up @@ -84,3 +88,14 @@ std::unique_ptr<Screen> Clock::PineTimeStyleScreen() {
settingsController,
motionController);
}

std::unique_ptr<Screen> Clock::WatchFaceTerminalScreen() {
return std::make_unique<Screens::WatchFaceTerminal>(app,
dateTimeController,
batteryController,
bleController,
notificatioManager,
settingsController,
heartRateController,
motionController);
}
1 change: 1 addition & 0 deletions src/displayapp/screens/Clock.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ namespace Pinetime {
std::unique_ptr<Screen> WatchFaceDigitalScreen();
std::unique_ptr<Screen> WatchFaceAnalogScreen();
std::unique_ptr<Screen> PineTimeStyleScreen();
std::unique_ptr<Screen> WatchFaceTerminalScreen();
};
}
}
Expand Down
245 changes: 245 additions & 0 deletions src/displayapp/screens/WatchFaceTerminal.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
#include "WatchFaceTerminal.h"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use includes relative to the src directory, helps me greatly with the simulator

Suggested change
#include "WatchFaceTerminal.h"
#include "displayapp/screens/WatchFaceTerminal.h"


#include <date/date.h>
#include <lvgl/lvgl.h>
#include <cstdio>
#include "displayapp/screens/BatteryIcon.h"
#include "displayapp/screens/BleIcon.h"
#include "displayapp/screens/NotificationIcon.h"
#include "displayapp/screens/Symbols.h"
#include "components/battery/BatteryController.h"
#include "components/ble/BleController.h"
#include "components/ble/NotificationManager.h"
#include "components/heartrate/HeartRateController.h"
#include "components/motion/MotionController.h"
#include "components/settings/Settings.h"

using namespace Pinetime::Applications::Screens;

WatchFaceTerminal::WatchFaceTerminal(DisplayApp* app,
Controllers::DateTime& dateTimeController,
Controllers::Battery& batteryController,
Controllers::Ble& bleController,
Controllers::NotificationManager& notificatioManager,
Controllers::Settings& settingsController,
Controllers::HeartRateController& heartRateController,
Controllers::MotionController& motionController)
: Screen(app),
currentDateTime {{}},
dateTimeController {dateTimeController},
batteryController {batteryController},
bleController {bleController},
notificatioManager {notificatioManager},
settingsController {settingsController},
heartRateController {heartRateController},
motionController {motionController} {
settingsController.SetClockFace(3);

displayedChar[0] = 0;
displayedChar[1] = 0;
displayedChar[2] = 0;
displayedChar[3] = 0;
displayedChar[4] = 0;
displayedChar[5] = 0;

13werwolf13 marked this conversation as resolved.
Show resolved Hide resolved
batteryIcon = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_text(batteryIcon, Symbols::batteryFull);
lv_obj_align(batteryIcon, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, -5, 2);

batteryPlug = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_text(batteryPlug, Symbols::plug);
lv_obj_align(batteryPlug, batteryIcon, LV_ALIGN_OUT_LEFT_MID, -5, 0);

batteryPercent = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_recolor(batteryPercent, true);
lv_obj_align(batteryPercent, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -20);
13werwolf13 marked this conversation as resolved.
Show resolved Hide resolved

bleIcon = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_text(bleIcon, Symbols::bluetooth);
lv_obj_align(bleIcon, batteryPlug, LV_ALIGN_OUT_LEFT_MID, -5, 0);

notificationIcon = lv_label_create(lv_scr_act(), NULL);
lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(false));
lv_obj_align(notificationIcon, nullptr, LV_ALIGN_IN_TOP_LEFT, 10, 0);

label_date = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_recolor(label_date, true);
lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -40);

label_prompt_1 = lv_label_create(lv_scr_act(), nullptr);
lv_obj_align(label_prompt_1, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -80);
lv_label_set_text(label_prompt_1, "user@watch:~ $ now");

label_prompt_2 = lv_label_create(lv_scr_act(), nullptr);
lv_obj_align(label_prompt_2, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 40);
lv_label_set_text(label_prompt_2, "user@watch:~ $");

label_time = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_recolor(label_time, true);
lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -60);

backgroundLabel = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_click(backgroundLabel, true);
lv_label_set_long_mode(backgroundLabel, LV_LABEL_LONG_CROP);
lv_obj_set_size(backgroundLabel, 240, 240);
lv_obj_set_pos(backgroundLabel, 0, 0);
lv_label_set_text(backgroundLabel, "");

heartbeatValue = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_recolor(heartbeatValue, true);
lv_label_set_text(heartbeatValue, "[L_HR]#ee3311 0 bpm#");
lv_obj_align(heartbeatValue, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 20);

stepValue = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_recolor(stepValue, true);
lv_label_set_text(stepValue, "[STEP]#ee3377 0 steps#");
lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 0);

taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this);
Refresh();
}

WatchFaceTerminal::~WatchFaceTerminal() {
lv_task_del(taskRefresh);
lv_obj_clean(lv_scr_act());
}

void WatchFaceTerminal::Refresh() {
batteryPercentRemaining = batteryController.PercentRemaining();
if (batteryPercentRemaining.IsUpdated()) {
auto batteryPercent = batteryPercentRemaining.Get();
lv_label_set_text(batteryIcon, BatteryIcon::GetBatteryIcon(batteryPercent));
auto isCharging = batteryController.IsCharging() || batteryController.IsPowerPresent();
lv_label_set_text(batteryPlug, BatteryIcon::GetPlugIcon(isCharging));
13werwolf13 marked this conversation as resolved.
Show resolved Hide resolved
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other battery label should be set here, also called batteryPercent

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry i don't understand

bleState = bleController.IsConnected();
if (bleState.IsUpdated()) {
if(bleState.Get() == true) {
lv_label_set_text(bleIcon, BleIcon::GetIcon(true));
} else {
lv_label_set_text(bleIcon, BleIcon::GetIcon(false));
}
}
lv_obj_align(batteryIcon, lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, -5, 5);
lv_obj_align(batteryPlug, batteryIcon, LV_ALIGN_OUT_LEFT_MID, -5, 0);
lv_obj_align(bleIcon, batteryPlug, LV_ALIGN_OUT_LEFT_MID, -5, 0);

notificationState = notificatioManager.AreNewNotificationsAvailable();
if(notificationState.IsUpdated()) {
if(notificationState.Get() == true)
lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(true));
else
lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(false));
}

currentDateTime = dateTimeController.CurrentDateTime();

if(currentDateTime.IsUpdated()) {
auto newDateTime = currentDateTime.Get();

auto dp = date::floor<date::days>(newDateTime);
auto time = date::make_time(newDateTime-dp);
auto yearMonthDay = date::year_month_day(dp);

auto year = (int)yearMonthDay.year();
auto month = static_cast<Pinetime::Controllers::DateTime::Months>((unsigned)yearMonthDay.month());
auto day = (unsigned)yearMonthDay.day();
auto dayOfWeek = static_cast<Pinetime::Controllers::DateTime::Days>(date::weekday(yearMonthDay).iso_encoding());

auto hour = time.hours().count();
13werwolf13 marked this conversation as resolved.
Show resolved Hide resolved
auto minute = time.minutes().count();
auto second = time.seconds().count();

char minutesChar[6];
sprintf(minutesChar, "%02d", static_cast<int>(minute));

char hoursChar[8];

char ampmChar[3];
if (settingsController.GetClockType() == Controllers::Settings::ClockType::H24) {
13werwolf13 marked this conversation as resolved.
Show resolved Hide resolved
sprintf(hoursChar, "%02d", hour);
} else {
if (hour == 0 && hour != 12) {
hour = 12;
sprintf(ampmChar, "AM");
} else if (hour == 12 && hour != 0) {
hour = 12;
sprintf(ampmChar, "PM");
} else if (hour < 12 && hour != 0) {
sprintf(ampmChar, "AM");
} else if (hour > 12 && hour != 0) {
hour = hour - 12;
sprintf(ampmChar, "PM");
}
sprintf(hoursChar, "%02d", hour);
}

char secondsChar[5];
sprintf(secondsChar, "%02d", static_cast<int>(second));

auto batteryValue = static_cast<uint8_t>(batteryController.PercentRemaining());

char battStr[24];
sprintf(battStr, "[BATT]#387b54 %d%\%#", batteryValue);
lv_label_set_text(batteryPercent, battStr);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be moved up to where I left the other comment. Inside if (batteryPercentRemaining.IsUpdated())

The other battery label should be set here, also called batteryPercent

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried, so not going.
and it seems today I finally broke everything, now after firmware the clock immediately drops to the previous one..

if(hoursChar[0] != displayedChar[0] ||
hoursChar[1] != displayedChar[1] ||
minutesChar[0] != displayedChar[2] ||
minutesChar[1] != displayedChar[3] ||
secondsChar[0] != displayedChar[4] ||
secondsChar[1] != displayedChar[5]) {
displayedChar[0] = hoursChar[0];
displayedChar[1] = hoursChar[1];
displayedChar[2] = minutesChar[0];
displayedChar[3] = minutesChar[1];
displayedChar[4] = secondsChar[0];
displayedChar[5] = secondsChar[1];

if (settingsController.GetClockType() == Controllers::Settings::ClockType::H12) {
if (hoursChar[0] == '0') {
hoursChar[0] = ' ';
}
}

char timeStr[42];
sprintf(timeStr, "[TIME]#11cc55 %c%c:%c%c:%c%c %s#", hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1], secondsChar[0], secondsChar[1], ampmChar);

lv_label_set_text(label_time, timeStr);
}

if ((year != currentYear) || (month != currentMonth) || (dayOfWeek != currentDayOfWeek) || (day != currentDay)) {

char dateStr[38];
sprintf(dateStr, "[DATE]#007fff %04d.%02d.%02d#", short(year), char(month), char(day));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggesting to use - instead of . for the iso-date-string. That would be the ISO 8601 format that pythons date.isoformat() returns

Suggested change
sprintf(dateStr, "[DATE]#007fff %04d.%02d.%02d#", short(year), char(month), char(day));
sprintf(dateStr, "[DATE]#007fff %04d-%02d-%02d#", short(year), char(month), char(day));

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, please, no...
it will not look so aesthetically pleasing and authentic

lv_label_set_text(label_date, dateStr);
13werwolf13 marked this conversation as resolved.
Show resolved Hide resolved


currentYear = year;
currentMonth = month;
currentDayOfWeek = dayOfWeek;
currentDay = day;
}
}

heartbeat = heartRateController.HeartRate();
heartbeatRunning = heartRateController.State() != Controllers::HeartRateController::States::Stopped;
if(heartbeat.IsUpdated() || heartbeatRunning.IsUpdated()) {
char heartbeatBuffer[28];
if(heartbeatRunning.Get())
sprintf(heartbeatBuffer, "[L_HR]#ee3311 %d bpm#", heartbeat.Get());
else
sprintf(heartbeatBuffer, "[L_HR]#ee3311 ---#");

lv_label_set_text(heartbeatValue, heartbeatBuffer);
}

stepCount = motionController.NbSteps();
motionSensorOk = motionController.IsSensorOk();
char stepString[34];
if (stepCount.IsUpdated() || motionSensorOk.IsUpdated()) {
sprintf(stepString, "[STEP]#ee3377 %lu steps#", stepCount.Get());
lv_label_set_text(stepValue, stepString);
}
13werwolf13 marked this conversation as resolved.
Show resolved Hide resolved
}
83 changes: 83 additions & 0 deletions src/displayapp/screens/WatchFaceTerminal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#pragma once

#include <lvgl/src/lv_core/lv_obj.h>
#include <chrono>
#include <cstdint>
#include <memory>
#include "displayapp/screens/Screen.h"
#include "components/datetime/DateTimeController.h"

namespace Pinetime {
namespace Controllers {
class Settings;
class Battery;
class Ble;
class NotificationManager;
class HeartRateController;
class MotionController;
}

namespace Applications {
namespace Screens {

class WatchFaceTerminal : public Screen {
public:
WatchFaceTerminal(DisplayApp* app,
Controllers::DateTime& dateTimeController,
Controllers::Battery& batteryController,
Controllers::Ble& bleController,
Controllers::NotificationManager& notificatioManager,
Controllers::Settings& settingsController,
Controllers::HeartRateController& heartRateController,
Controllers::MotionController& motionController);
~WatchFaceTerminal() override;

void Refresh() override;

void OnObjectEvent(lv_obj_t *pObj, lv_event_t i);

private:
char displayedChar[8];

uint16_t currentYear = 1970;
Pinetime::Controllers::DateTime::Months currentMonth = Pinetime::Controllers::DateTime::Months::Unknown;
Pinetime::Controllers::DateTime::Days currentDayOfWeek = Pinetime::Controllers::DateTime::Days::Unknown;
uint8_t currentDay = 0;

DirtyValue<int> batteryPercentRemaining {};
DirtyValue<bool> bleState {};
DirtyValue<std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>> currentDateTime{};
DirtyValue<bool> motionSensorOk {};
DirtyValue<uint32_t> stepCount {};
DirtyValue<uint8_t> heartbeat {};
DirtyValue<bool> heartbeatRunning {};
DirtyValue<bool> notificationState {};

lv_obj_t* label_time;
lv_obj_t* label_date;
lv_obj_t* label_prompt_1;
lv_obj_t* label_prompt_2;
lv_obj_t* backgroundLabel;
lv_obj_t* batteryIcon;
lv_obj_t* bleIcon;
lv_obj_t* batteryPlug;
lv_obj_t* batteryPercent;
lv_obj_t* heartbeatIcon;
lv_obj_t* heartbeatValue;
lv_obj_t* heartbeatBpm;
lv_obj_t* stepValue;
lv_obj_t* notificationIcon;

Controllers::DateTime& dateTimeController;
Controllers::Battery& batteryController;
Controllers::Ble& bleController;
Controllers::NotificationManager& notificatioManager;
Controllers::Settings& settingsController;
Controllers::HeartRateController& heartRateController;
Controllers::MotionController& motionController;

lv_task_t* taskRefresh;
};
}
}
}
2 changes: 1 addition & 1 deletion src/displayapp/screens/settings/SettingWatchFace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace {
}
}

constexpr std::array<const char*, 3> SettingWatchFace::options;
constexpr std::array<const char*, 4> SettingWatchFace::options;

SettingWatchFace::SettingWatchFace(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::Settings& settingsController)
: Screen(app), settingsController {settingsController} {
Expand Down
2 changes: 1 addition & 1 deletion src/displayapp/screens/settings/SettingWatchFace.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ namespace Pinetime {
void UpdateSelected(lv_obj_t* object, lv_event_t event);

private:
static constexpr std::array<const char*, 3> options = {" Digital face", " Analog face", " PineTimeStyle"};
static constexpr std::array<const char*, 4> options = {" Digital face", " Analog face", " PineTimeStyle", " Terminal"};
Controllers::Settings& settingsController;

lv_obj_t* cbOption[options.size()];
Expand Down