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 22 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
24 changes: 17 additions & 7 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 @@ -76,11 +80,17 @@ std::unique_ptr<Screen> Clock::WatchFaceAnalogScreen() {
}

std::unique_ptr<Screen> Clock::PineTimeStyleScreen() {
return std::make_unique<Screens::PineTimeStyle>(app,
dateTimeController,
batteryController,
bleController,
notificatioManager,
settingsController,
motionController);
return std::make_unique<Screens::PineTimeStyle>(
app, dateTimeController, batteryController, bleController, notificatioManager, 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
252 changes: 252 additions & 0 deletions src/displayapp/screens/WatchFaceTerminal.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
#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

connectState = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_recolor(connectState, true);
lv_label_set_text(connectState, "[STAT]#387b54 Disconnected#");
lv_obj_align(connectState, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 40);

// 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, 60);
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() {
13werwolf13 marked this conversation as resolved.
Show resolved Hide resolved
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

/*char* bleValue;*/
13werwolf13 marked this conversation as resolved.
Show resolved Hide resolved
if (bleState.IsUpdated()) {
char bleStr[24];
sprintf(bleStr, "[STAT]#387b54 %s#",bleController.IsConnected() ? "Connected" : "Disconnected");
lv_label_set_text(connectState, bleStr);
13werwolf13 marked this conversation as resolved.
Show resolved Hide resolved
}

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);

13werwolf13 marked this conversation as resolved.
Show resolved Hide resolved
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();
13werwolf13 marked this conversation as resolved.
Show resolved Hide resolved
auto dayOfWeek = static_cast<Pinetime::Controllers::DateTime::Days>(date::weekday(yearMonthDay).iso_encoding());

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

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

char hoursChar[8];

char ampmChar[3];
if (settingsController.GetClockType() == Controllers::Settings::ClockType::H24) {
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);

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);
}
13werwolf13 marked this conversation as resolved.
Show resolved Hide resolved

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);
13werwolf13 marked this conversation as resolved.
Show resolved Hide resolved
}

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
}
85 changes: 85 additions & 0 deletions src/displayapp/screens/WatchFaceTerminal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#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];
13werwolf13 marked this conversation as resolved.
Show resolved Hide resolved

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 {};
13werwolf13 marked this conversation as resolved.
Show resolved Hide resolved
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;
13werwolf13 marked this conversation as resolved.
Show resolved Hide resolved
lv_obj_t* heartbeatIcon;
lv_obj_t* heartbeatValue;
lv_obj_t* heartbeatBpm;
lv_obj_t* stepValue;
lv_obj_t* notificationIcon;
lv_obj_t* connectState;
lv_obj_t* bleValue;

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;
};
}
}
}
Loading