Started initial work on the UI

This commit is contained in:
Avamander 2021-06-25 01:18:56 +03:00
parent 2736fa57bb
commit 19c9667a3d
4 changed files with 80 additions and 177 deletions

View file

@ -20,8 +20,8 @@
#include "libs/QCBOR/inc/qcbor/qcbor.h" #include "libs/QCBOR/inc/qcbor/qcbor.h"
#include "systemtask/SystemTask.h" #include "systemtask/SystemTask.h"
int WeatherCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg) { int WeatherCallback(uint16_t connHandle, uint16_t attrHandle, struct ble_gatt_access_ctxt* ctxt, void* arg) {
return static_cast<Pinetime::Controllers::WeatherService*>(arg)->OnCommand(conn_handle, attr_handle, ctxt); return static_cast<Pinetime::Controllers::WeatherService*>(arg)->OnCommand(connHandle, attrHandle, ctxt);
} }
namespace Pinetime { namespace Pinetime {
@ -39,7 +39,7 @@ namespace Pinetime {
ASSERT(res == 0); ASSERT(res == 0);
} }
int WeatherService::OnCommand(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt) { int WeatherService::OnCommand(uint16_t connHandle, uint16_t attrHandle, struct ble_gatt_access_ctxt* ctxt) {
// TODO: Detect control messages // TODO: Detect control messages
if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) { if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
const auto packetLen = OS_MBUF_PKTLEN(ctxt->om); const auto packetLen = OS_MBUF_PKTLEN(ctxt->om);
@ -167,9 +167,9 @@ namespace Pinetime {
} }
} }
getCurrentPressure(); GetCurrentPressure();
tidyTimeline(); TidyTimeline();
getTimelineLength(); GetTimelineLength();
QCBORDecode_ExitMap(&decodeContext); QCBORDecode_ExitMap(&decodeContext);
auto uErr = QCBORDecode_Finish(&decodeContext); auto uErr = QCBORDecode_Finish(&decodeContext);
@ -201,29 +201,36 @@ namespace Pinetime {
return 0; return 0;
} }
WeatherData::Location WeatherService::getCurrentLocation() const { WeatherData::Location WeatherService::GetCurrentLocation() const {
return WeatherData::Location(); return WeatherData::Location();
} }
WeatherData::Clouds WeatherService::getCurrentClouds() const {
WeatherData::Clouds WeatherService::GetCurrentClouds() const {
return WeatherData::Clouds(); return WeatherData::Clouds();
} }
WeatherData::Obscuration WeatherService::getCurrentObscuration() const {
WeatherData::Obscuration WeatherService::GetCurrentObscuration() const {
return WeatherData::Obscuration(); return WeatherData::Obscuration();
} }
WeatherData::Precipitation WeatherService::getCurrentPrecipitation() const {
WeatherData::Precipitation WeatherService::GetCurrentPrecipitation() const {
return WeatherData::Precipitation(); return WeatherData::Precipitation();
} }
WeatherData::Wind WeatherService::getCurrentWind() const {
WeatherData::Wind WeatherService::GetCurrentWind() const {
return WeatherData::Wind(); return WeatherData::Wind();
} }
WeatherData::Temperature WeatherService::getCurrentTemperature() const {
WeatherData::Temperature WeatherService::GetCurrentTemperature() const {
return WeatherData::Temperature(); return WeatherData::Temperature();
} }
WeatherData::Humidity WeatherService::getCurrentHumidity() const {
WeatherData::Humidity WeatherService::GetCurrentHumidity() const {
return WeatherData::Humidity(); return WeatherData::Humidity();
} }
WeatherData::Pressure WeatherService::getCurrentPressure() const {
uint64_t currentTimestamp = getCurrentUNIXTimestamp(); WeatherData::Pressure WeatherService::GetCurrentPressure() const {
uint64_t currentTimestamp = GetCurrentUnixTimestamp();
for (auto&& header : timeline) { for (auto&& header : timeline) {
if (header->eventType == WeatherData::eventtype::Pressure && header->timestamp + header->expires <= currentTimestamp) { if (header->eventType == WeatherData::eventtype::Pressure && header->timestamp + header->expires <= currentTimestamp) {
return WeatherData::Pressure(); return WeatherData::Pressure();
@ -232,15 +239,15 @@ namespace Pinetime {
return WeatherData::Pressure(); return WeatherData::Pressure();
} }
WeatherData::AirQuality WeatherService::getCurrentQuality() const { WeatherData::AirQuality WeatherService::GetCurrentQuality() const {
return WeatherData::AirQuality(); return WeatherData::AirQuality();
} }
size_t WeatherService::getTimelineLength() const { size_t WeatherService::GetTimelineLength() const {
return timeline.size(); return timeline.size();
} }
bool WeatherService::addEventToTimeline(std::unique_ptr<WeatherData::TimelineHeader> event) { bool WeatherService::AddEventToTimeline(std::unique_ptr<WeatherData::TimelineHeader> event) {
if (timeline.size() == timeline.max_size()) { if (timeline.size() == timeline.max_size()) {
return false; return false;
} }
@ -249,8 +256,8 @@ namespace Pinetime {
return true; return true;
} }
bool WeatherService::hasTimelineEventOfType(const WeatherData::eventtype type) const { bool WeatherService::HasTimelineEventOfType(const WeatherData::eventtype type) const {
uint64_t currentTimestamp = getCurrentUNIXTimestamp(); uint64_t currentTimestamp = GetCurrentUnixTimestamp();
for (auto&& header : timeline) { for (auto&& header : timeline) {
if (header->eventType == type && header->timestamp + header->expires <= currentTimestamp) { if (header->eventType == type && header->timestamp + header->expires <= currentTimestamp) {
// TODO: Check if its currently valid // TODO: Check if its currently valid
@ -260,7 +267,7 @@ namespace Pinetime {
return false; return false;
} }
void WeatherService::tidyTimeline() { void WeatherService::TidyTimeline() {
uint64_t timeCurrent = 0; uint64_t timeCurrent = 0;
timeline.erase(std::remove_if(std::begin(timeline), timeline.erase(std::remove_if(std::begin(timeline),
std::end(timeline), std::end(timeline),
@ -269,15 +276,15 @@ namespace Pinetime {
}), }),
std::end(timeline)); std::end(timeline));
std::sort(std::begin(timeline), std::end(timeline), compareTimelineEvents); std::sort(std::begin(timeline), std::end(timeline), CompareTimelineEvents);
} }
bool WeatherService::compareTimelineEvents(const std::unique_ptr<WeatherData::TimelineHeader>& first, bool WeatherService::CompareTimelineEvents(const std::unique_ptr<WeatherData::TimelineHeader>& first,
const std::unique_ptr<WeatherData::TimelineHeader>& second) { const std::unique_ptr<WeatherData::TimelineHeader>& second) {
return first->timestamp > second->timestamp; return first->timestamp > second->timestamp;
} }
uint64_t WeatherService::getCurrentUNIXTimestamp() const { uint64_t WeatherService::GetCurrentUnixTimestamp() const {
return std::chrono::duration_cast<std::chrono::seconds>(dateTimeController.CurrentDateTime().time_since_epoch()).count(); return std::chrono::duration_cast<std::chrono::seconds>(dateTimeController.CurrentDateTime().time_since_epoch()).count();
} }
} }

View file

@ -32,7 +32,7 @@
#include "WeatherData.h" #include "WeatherData.h"
#include <components/datetime/DateTimeController.h> #include <components/datetime/DateTimeController.h>
int WeatherCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg); int WeatherCallback(uint16_t connHandle, uint16_t attrHandle, struct ble_gatt_access_ctxt* ctxt, void* arg);
namespace Pinetime { namespace Pinetime {
namespace System { namespace System {
@ -46,20 +46,20 @@ namespace Pinetime {
void Init(); void Init();
int OnCommand(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt); int OnCommand(uint16_t connHandle, uint16_t attrHandle, struct ble_gatt_access_ctxt* ctxt);
/* /*
* Helper functions for quick access to currently valid data * Helper functions for quick access to currently valid data
*/ */
WeatherData::Location getCurrentLocation() const; WeatherData::Location GetCurrentLocation() const;
WeatherData::Clouds getCurrentClouds() const; WeatherData::Clouds GetCurrentClouds() const;
WeatherData::Obscuration getCurrentObscuration() const; WeatherData::Obscuration GetCurrentObscuration() const;
WeatherData::Precipitation getCurrentPrecipitation() const; WeatherData::Precipitation GetCurrentPrecipitation() const;
WeatherData::Wind getCurrentWind() const; WeatherData::Wind GetCurrentWind() const;
WeatherData::Temperature getCurrentTemperature() const; WeatherData::Temperature GetCurrentTemperature() const;
WeatherData::Humidity getCurrentHumidity() const; WeatherData::Humidity GetCurrentHumidity() const;
WeatherData::Pressure getCurrentPressure() const; WeatherData::Pressure GetCurrentPressure() const;
WeatherData::AirQuality getCurrentQuality() const; WeatherData::AirQuality GetCurrentQuality() const;
/* /*
* Management functions * Management functions
@ -68,16 +68,16 @@ namespace Pinetime {
* Adds an event to the timeline * Adds an event to the timeline
* @return * @return
*/ */
bool addEventToTimeline(std::unique_ptr<WeatherData::TimelineHeader> event); bool AddEventToTimeline(std::unique_ptr<WeatherData::TimelineHeader> event);
/** /**
* Gets the current timeline length * Gets the current timeline length
*/ */
size_t getTimelineLength() const; size_t GetTimelineLength() const;
/** /**
* Checks if an event of a certain type exists in the timeline * Checks if an event of a certain type exists in the timeline
* @return * @return
*/ */
bool hasTimelineEventOfType(WeatherData::eventtype type) const; bool HasTimelineEventOfType(const WeatherData::eventtype type) const;
private: private:
// 00030000-78fc-48fe-8e23-433b3a1942d0 // 00030000-78fc-48fe-8e23-433b3a1942d0
@ -125,18 +125,18 @@ namespace Pinetime {
* Cleans up the timeline of expired events * Cleans up the timeline of expired events
* @return result code * @return result code
*/ */
void tidyTimeline(); void TidyTimeline();
/** /**
* Compares two timeline events * Compares two timeline events
*/ */
static bool compareTimelineEvents(const std::unique_ptr<WeatherData::TimelineHeader>& first, static bool CompareTimelineEvents(const std::unique_ptr<WeatherData::TimelineHeader>& first,
const std::unique_ptr<WeatherData::TimelineHeader>& second); const std::unique_ptr<WeatherData::TimelineHeader>& second);
/** /**
* Returns current UNIX timestamp * Returns current UNIX timestamp
*/ */
uint64_t getCurrentUNIXTimestamp() const; uint64_t GetCurrentUnixTimestamp() const;
}; };
} }
} }

View file

@ -1,5 +1,6 @@
#include "Weather.h" #include "Weather.h"
#include <lvgl/lvgl.h> #include <lvgl/lvgl.h>
#include <components/ble/weather/WeatherService.h>
#include "../DisplayApp.h" #include "../DisplayApp.h"
#include "Label.h" #include "Label.h"
#include "Version.h" #include "Version.h"
@ -12,22 +13,14 @@
using namespace Pinetime::Applications::Screens; using namespace Pinetime::Applications::Screens;
Weather::Weather(Pinetime::Applications::DisplayApp* app, Weather::Weather(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::WeatherService& weather)
Pinetime::Controllers::DateTime& dateTimeController,
Pinetime::Controllers::Battery& batteryController,
Pinetime::Controllers::BrightnessController& brightnessController,
Pinetime::Controllers::Ble& bleController,
Pinetime::Drivers::WatchdogView& watchdog)
: Screen(app), : Screen(app),
dateTimeController {dateTimeController}, dateTimeController {dateTimeController},
batteryController {batteryController}, weatherService(weather),
brightnessController {brightnessController},
bleController {bleController},
watchdog {watchdog},
screens {app, screens {app,
0, 0,
{[this]() -> std::unique_ptr<Screen> { {[this]() -> std::unique_ptr<Screen> {
return CreateScreen1(); return CreateScreenTemperature();
}, },
[this]() -> std::unique_ptr<Screen> { [this]() -> std::unique_ptr<Screen> {
return CreateScreen2(); return CreateScreen2();
@ -64,101 +57,30 @@ bool Weather::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
return screens.OnTouchEvent(event); return screens.OnTouchEvent(event);
} }
std::unique_ptr<Screen> Weather::CreateScreen1() { std::unique_ptr<Screen> Weather::CreateScreenTemperature() {
lv_obj_t* label = lv_label_create(lv_scr_act(), nullptr); lv_obj_t* label = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_recolor(label, true); lv_label_set_recolor(label, true);
Controllers::WeatherData::Temperature current = weatherService.GetCurrentTemperature();
lv_label_set_text_fmt(label, lv_label_set_text_fmt(label,
"#FFFF00 InfiniTime#\n\n" "#FFFF00 Temperature#\n\n"
"#444444 Version# %ld.%ld.%ld\n\n" "#444444 %hd%%#°C \n\n"
"#444444 Build date#\n" "#444444 %hd#\n"
"%s\n" "%llu\n"
"%s\n", "%lu\n",
Version::Major(), current.temperature,
Version::Minor(), current.dewPoint,
Version::Patch(), current.timestamp,
__DATE__, current.expires);
__TIME__);
lv_label_set_align(label, LV_LABEL_ALIGN_CENTER); lv_label_set_align(label, LV_LABEL_ALIGN_CENTER);
lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0);
return std::unique_ptr<Screen>(new Screens::Label(0, 5, app, label)); return std::unique_ptr<Screen>(new Screens::Label(0, 5, app, label));
} }
std::unique_ptr<Screen> Weather::CreateScreen2() { std::unique_ptr<Screen> Weather::CreateScreen2() {
auto batteryPercent = static_cast<uint8_t>(batteryController.PercentRemaining());
float batteryVoltage = batteryController.Voltage();
auto resetReason = [this]() {
switch (watchdog.ResetReason()) {
case Drivers::Watchdog::ResetReasons::Watchdog:
return "wtdg";
case Drivers::Watchdog::ResetReasons::HardReset:
return "hardr";
case Drivers::Watchdog::ResetReasons::NFC:
return "nfc";
case Drivers::Watchdog::ResetReasons::SoftReset:
return "softr";
case Drivers::Watchdog::ResetReasons::CpuLockup:
return "cpulock";
case Drivers::Watchdog::ResetReasons::SystemOff:
return "off";
case Drivers::Watchdog::ResetReasons::LpComp:
return "lpcomp";
case Drivers::Watchdog::ResetReasons::DebugInterface:
return "dbg";
case Drivers::Watchdog::ResetReasons::ResetPin:
return "rst";
default:
return "?";
}
}();
// uptime // uptime
static constexpr uint32_t secondsInADay = 60 * 60 * 24;
static constexpr uint32_t secondsInAnHour = 60 * 60;
static constexpr uint32_t secondsInAMinute = 60;
uint32_t uptimeSeconds = dateTimeController.Uptime().count();
uint32_t uptimeDays = (uptimeSeconds / secondsInADay);
uptimeSeconds = uptimeSeconds % secondsInADay;
uint32_t uptimeHours = uptimeSeconds / secondsInAnHour;
uptimeSeconds = uptimeSeconds % secondsInAnHour;
uint32_t uptimeMinutes = uptimeSeconds / secondsInAMinute;
uptimeSeconds = uptimeSeconds % secondsInAMinute;
// TODO handle more than 100 days of uptime
if (batteryPercent == -1)
batteryPercent = 0;
// hack to not use the flot functions from printf
uint8_t batteryVoltageBytes[2];
batteryVoltageBytes[1] = static_cast<uint8_t>(batteryVoltage); // truncate whole numbers
batteryVoltageBytes[0] =
static_cast<uint8_t>((batteryVoltage - batteryVoltageBytes[1]) * 100); // remove whole part of flt and shift 2 places over
//
lv_obj_t* label = lv_label_create(lv_scr_act(), nullptr); lv_obj_t* label = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_recolor(label, true); lv_label_set_recolor(label, true);
lv_label_set_text_fmt(label, lv_label_set_text_fmt(label, "#444444 Date# %02d\n", dateTimeController.Day());
"#444444 Date# %02d/%02d/%04d\n"
"#444444 Time# %02d:%02d:%02d\n"
"#444444 Uptime#\n %02lud %02lu:%02lu:%02lu\n"
"#444444 Battery# %d%%/%1i.%02iv\n"
"#444444 Backlight# %s\n"
"#444444 Last reset# %s\n",
dateTimeController.Day(),
static_cast<uint8_t>(dateTimeController.Month()),
dateTimeController.Year(),
dateTimeController.Hours(),
dateTimeController.Minutes(),
dateTimeController.Seconds(),
uptimeDays,
uptimeHours,
uptimeMinutes,
uptimeSeconds,
batteryPercent,
batteryVoltageBytes[1],
batteryVoltageBytes[0],
brightnessController.ToString(),
resetReason);
lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0);
return std::unique_ptr<Screen>(new Screens::Label(1, 4, app, label)); return std::unique_ptr<Screen>(new Screens::Label(1, 4, app, label));
} }
@ -169,28 +91,11 @@ std::unique_ptr<Screen> Weather::CreateScreen3() {
lv_obj_t* label = lv_label_create(lv_scr_act(), nullptr); lv_obj_t* label = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_recolor(label, true); lv_label_set_recolor(label, true);
auto& bleAddr = bleController.Address();
lv_label_set_text_fmt(label, lv_label_set_text_fmt(label,
"#444444 BLE MAC#\n"
" %02x:%02x:%02x:%02x:%02x:%02x"
"\n"
"#444444 Memory#\n"
" #444444 used# %d (%d%%)\n"
" #444444 frag# %d%%\n" " #444444 frag# %d%%\n"
" #444444 free# %d" " #444444 free# %d",
"\n"
"#444444 Steps# %li",
bleAddr[5],
bleAddr[4],
bleAddr[3],
bleAddr[2],
bleAddr[1],
bleAddr[0],
(int) mon.total_size - mon.free_size,
mon.used_pct, mon.used_pct,
mon.frag_pct, mon.frag_pct);
(int) mon.free_biggest_size,
0);
lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0);
return std::unique_ptr<Screen>(new Screens::Label(2, 5, app, label)); return std::unique_ptr<Screen>(new Screens::Label(2, 5, app, label));
} }
@ -201,7 +106,7 @@ bool sortById(const TaskStatus_t& lhs, const TaskStatus_t& rhs) {
std::unique_ptr<Screen> Weather::CreateScreen4() { std::unique_ptr<Screen> Weather::CreateScreen4() {
TaskStatus_t tasksStatus[7]; TaskStatus_t tasksStatus[7];
lv_obj_t* infoTask = lv_table_create(lv_scr_act(), NULL); lv_obj_t* infoTask = lv_table_create(lv_scr_act(), nullptr);
lv_table_set_col_cnt(infoTask, 3); lv_table_set_col_cnt(infoTask, 3);
lv_table_set_row_cnt(infoTask, 8); lv_table_set_row_cnt(infoTask, 8);
lv_obj_set_pos(infoTask, 10, 10); lv_obj_set_pos(infoTask, 10, 10);

View file

@ -1,52 +1,43 @@
#pragma once #pragma once
#include <memory> #include <memory>
#include <components/ble/weather/WeatherService.h>
#include "Screen.h" #include "Screen.h"
#include "ScreenList.h" #include "ScreenList.h"
namespace Pinetime { namespace Pinetime {
namespace Controllers {
class DateTime;
class Battery;
class BrightnessController;
class Ble;
}
namespace Drivers {
class WatchdogView;
}
namespace Applications { namespace Applications {
class DisplayApp; class DisplayApp;
namespace Screens { namespace Screens {
class Weather : public Screen { class Weather : public Screen {
public: public:
explicit Weather(DisplayApp* app, explicit Weather(DisplayApp* app, Pinetime::Controllers::WeatherService& weather);
Pinetime::Controllers::DateTime& dateTimeController,
Pinetime::Controllers::Battery& batteryController,
Pinetime::Controllers::BrightnessController& brightnessController,
Pinetime::Controllers::Ble& bleController,
Pinetime::Drivers::WatchdogView& watchdog);
~Weather() override; ~Weather() override;
bool Refresh() override; bool Refresh() override;
bool OnButtonPushed() override; bool OnButtonPushed() override;
bool OnTouchEvent(TouchEvents event) override; bool OnTouchEvent(TouchEvents event) override;
private: private:
bool running = true; bool running = true;
Pinetime::Controllers::DateTime& dateTimeController; Pinetime::Controllers::DateTime& dateTimeController;
Pinetime::Controllers::Battery& batteryController; Controllers::WeatherService& weatherService;
Pinetime::Controllers::BrightnessController& brightnessController;
Pinetime::Controllers::Ble& bleController;
Pinetime::Drivers::WatchdogView& watchdog;
ScreenList<5> screens; ScreenList<5> screens;
std::unique_ptr<Screen> CreateScreen1();
std::unique_ptr<Screen> CreateScreenTemperature();
std::unique_ptr<Screen> CreateScreen2(); std::unique_ptr<Screen> CreateScreen2();
std::unique_ptr<Screen> CreateScreen3(); std::unique_ptr<Screen> CreateScreen3();
std::unique_ptr<Screen> CreateScreen4(); std::unique_ptr<Screen> CreateScreen4();
std::unique_ptr<Screen> CreateScreen5(); std::unique_ptr<Screen> CreateScreen5();
}; };
} }