-
I've been developing a simple productivity tool for PineTime that involves a stopwatch that always ticks up or down. The stopwatch starts at 9am UTC every day. When I'm studying I set the toggle to "ON" and the stopwatch ticks up. When I'm doing anything else I set the toggle to "OFF" and the stopwatch ticks down. The goal is to end the day with a positive time balance. The app compiles and runs fine on InfiniSim but when it's packaged via Problem 1-- The app does not detect the current time and instead appears to pull some junk data as its int variable. This junk data is also not retained when the app is closed and restarted. However, the variable Problem 2-- The app does not update/refresh, even when open. Potential cause-- The app gets the current time through #include <chrono>
auto p1 = std::chrono::system_clock::now();
int todaysec = std::chrono::duration_cast<std::chrono::seconds>(p1.time_since_epoch()).count() % 86400; (these are declared as global variables in the app). Maybe Chrono does not work well on actual PineTime hardware and the variables are then left uninitialised? Would also explain why the app doesn't update, because it needs Chrono to tell it when a second has ticked over. The full header file #pragma once
#include "displayapp/screens/Screen.h"
#include <lvgl/lvgl.h>
namespace Pinetime {
namespace Applications {
namespace Screens {
class OoOoApp : public Screen {
public:
OoOoApp(DisplayApp* app);
~OoOoApp() override;
void Refresh() override;
private:
lv_task_t* taskRefresh;
};
}
}
} The full code for the app #include "displayapp/screens/OoOoApp.h"
#include "displayapp/DisplayApp.h"
#include <chrono>
#include <cmath>
#include <string>
#include <lvgl/lvgl.h>
#if LV_USE_BTN
// function declaration
std::string lZ(int testValue);
void sendToDisplay();
void updateTheButton();
// creating LVGL objects
lv_obj_t* curTimeObj;
lv_obj_t* balTimeObj;
lv_obj_t* togLabela;
lv_obj_t* togBtn;
// global variables
int oState = -1; // +1 if the ticker is ON, -1 if OFF. Every second, the program adds the value of oState to the time balance.
auto p1 = std::chrono::system_clock::now();
int todaysec = std::chrono::duration_cast<std::chrono::seconds>(p1.time_since_epoch()).count() % 86400;
int launchday = std::chrono::duration_cast<std::chrono::seconds>(p1.time_since_epoch()).count() / 86400;
int balance = 32400 - todaysec; // We are starting the 1o1o baseline at 9AM GMT (32400s); it is assumed that we're in OFF until then
static void event_handler(lv_obj_t * obj, lv_event_t event)
{
if (event == LV_EVENT_CLICKED) {
oState = oState * -1; // toggles ON vs OFF (+1 → -1, -1 → -1)
updateTheButton();
}
}
using namespace Pinetime::Applications::Screens;
OoOoApp::OoOoApp(DisplayApp* app) : Screen(app) {
curTimeObj = lv_label_create(lv_scr_act(), nullptr);
balTimeObj = lv_label_create(lv_scr_act(), nullptr);
togBtn = lv_btn_create(lv_scr_act(), nullptr);
togLabela = lv_label_create(lv_scr_act(), nullptr);
// Creating styles (for big font)
static lv_style_t baltimestyle;
lv_style_init(&baltimestyle);
lv_style_set_text_font(&baltimestyle, LV_STATE_DEFAULT, &jetbrains_mono_extrabold_compressed);
static lv_style_t butlabstyle;
lv_style_init(&butlabstyle);
lv_style_set_text_font(&butlabstyle, LV_STATE_DEFAULT, &jetbrains_mono_42);
// Styling the labels (position)
lv_label_set_align(curTimeObj, LV_LABEL_ALIGN_CENTER);
lv_obj_align(curTimeObj, lv_scr_act(), LV_ALIGN_CENTER, -74, -91);
lv_label_set_align(togLabela, LV_LABEL_ALIGN_CENTER);
lv_obj_align(togLabela, lv_scr_act(), LV_ALIGN_CENTER, 0, 58);
lv_label_set_align(balTimeObj, LV_LABEL_ALIGN_CENTER);
lv_obj_align(balTimeObj, lv_scr_act(), LV_ALIGN_CENTER, -76, -45);
// Styling the labels (font size)
lv_obj_add_style(togLabela, LV_LABEL_PART_MAIN, &baltimestyle);
lv_obj_add_style(balTimeObj, LV_LABEL_PART_MAIN, &butlabstyle);
// Styling the button (colour, position)
lv_obj_align(togBtn, lv_scr_act(), LV_ALIGN_CENTER, -50, 36);
lv_obj_set_style_local_radius(togBtn, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_RADIUS_CIRCLE);
lv_obj_set_style_local_bg_color(togBtn, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0xa4,0x24,0x3b));
lv_obj_set_event_cb(togBtn, event_handler);
lv_obj_set_size(togBtn, LV_HOR_RES - 40, 80);
lv_obj_set_event_cb(togBtn, event_handler); // go to event_handler() when the button is clicked
updateTheButton(); // update visual style of button
sendToDisplay(); // turn our int (seconds) into a displayable time
taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this);
Refresh();
}
void sendToDisplay() {
// Display Balance Hour/Minute/Second
std::string balSign { " " };
if (balance < 0) { balSign = "-"; }
if (balance > 0) { balSign = "+"; }
int dbHour = std::floor(abs(balance) / 3600);
int dbMinute = std::floor(abs(balance) / 60) - dbHour * 60;
int dbSecond = abs(balance) - dbHour * 3600 - dbMinute * 60;
// Display Time Hour/Minute/Second
int dtHour = std::floor(todaysec / 3600);
int dtMinute = std::floor(todaysec / 60) - dtHour * 60;
int dtSecond = todaysec - dtHour * 3600 - dtMinute * 60;
// Output
std::string curTimeStr = lZ(dtHour) + ":" + lZ(dtMinute) + ":" + lZ(dtSecond);
std::string balTimeStr;
if (dbHour < -9 || dbHour > 9) {
balTimeStr = std::to_string(abs(dbHour)) + ":" + lZ(dbMinute) + ":" + lZ(dbSecond);
} else {
balTimeStr = balSign + std::to_string(abs(dbHour)) + ":" + lZ(dbMinute) + ":" + lZ(dbSecond);
}
// Labels for the current time and time balance
lv_label_set_text(curTimeObj, curTimeStr.c_str()); // convert the current time string to chars then set that
lv_label_set_text(balTimeObj, balTimeStr.c_str());
// Colour the time balance based on positive/negative
if (balSign == "+") {lv_obj_set_style_local_text_color(balTimeObj, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0xaa,0xf6,0x83));}
if (balSign == "-") {lv_obj_set_style_local_text_color(balTimeObj, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0xa4,0x24,0x3b));}
if (balSign == " ") {lv_obj_set_style_local_text_color(balTimeObj, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0xc0,0xc0,0xc0));}
}
void updateTheButton() {
// Updates the visual appearance of the button
if (oState == 1) {
lv_obj_set_style_local_bg_color(togBtn, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0xaa,0xf6,0x83));
lv_label_set_text(togLabela, "ON");
lv_obj_set_style_local_text_color(togLabela, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0x49,0xbd,0x00));
lv_obj_align(togLabela, lv_scr_act(), LV_ALIGN_CENTER, 0, 58);
}
if (oState == -1) {
lv_obj_set_style_local_bg_color(togBtn, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0xa4,0x24,0x3b));
lv_label_set_text(togLabela, "OFF");
lv_obj_set_style_local_text_color(togLabela, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0x77,0x00,0x15));
lv_obj_align(togLabela, lv_scr_act(), LV_ALIGN_CENTER, 0, 58);
}
}
std::string lZ(int testValue) {
// Adds a leading zero if required, to bring everything to two digits
if (testValue < 10) { return "0" + std::to_string(testValue); }
else { return std::to_string(testValue); }
}
OoOoApp::~OoOoApp() {
lv_task_del(taskRefresh);
lv_obj_clean(lv_scr_act());
}
void OoOoApp::Refresh() {
p1 = std::chrono::system_clock::now();
int newSec = std::chrono::duration_cast<std::chrono::seconds>(p1.time_since_epoch()).count() % 86400;
int newDay = std::chrono::duration_cast<std::chrono::seconds>(p1.time_since_epoch()).count() / 86400;
// Has the second ticked over since the last time we checked?
if (newSec != todaysec) {
if (newDay > launchday) {
// Automatically reset if the last time this app was loaded was yesterday. Will also activate at midnight
oState = -1;
p1 = std::chrono::system_clock::now();
todaysec = std::chrono::duration_cast<std::chrono::seconds>(p1.time_since_epoch()).count() % 86400;
launchday = newDay;
balance = 32400 - todaysec;
updateTheButton();
}
balance += oState * (newSec - todaysec); // Also accounts for if the app has been asleep
todaysec = newSec;
sendToDisplay();
}
}
#endif Changes to displayapp/fonts/fonts.json to add the O, N and F characters to the big button font (this works fine) "jetbrains_mono_extrabold_compressed": {
"sources": [
{
"file": "JetBrainsMono-ExtraBold.ttf",
"range": "0x30-0x3a, 0x46, 0x4e, 0x4f"
}
],
"bpp": 1,
"size": 80
}, |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 2 replies
-
Instead, you should try using the I also noticed that your code uses |
Beta Was this translation helpful? Give feedback.
std::chrono::system_clock
is not implemented in InfiniTime, sostd::chrono::system_clock::now()
probably return undefined values, which might be why your application does not work as expected on the PineTime, while it works on your computer (wheresystem_clock
is fully functional.Instead, you should try using the
DateTimeController
(https://github.com/InfiniTimeOrg/InfiniTime/blob/develop/src/components/datetime/DateTimeController.h) to get the date and time of the PineTime. You can take some inspirations from the existing apps and watchfaces (ex : https://github.com/InfiniTimeOrg/InfiniTime/blob/develop/src/displayapp/screens/WatchFaceDigital.cpp#L94).I also noticed that your code uses
s…