Bunch of bugs fixed, improved error handling, debug UI addition
This commit is contained in:
parent
48beb7c3b1
commit
c870f8ed30
|
@ -28,6 +28,7 @@ namespace Pinetime {
|
||||||
namespace Controllers {
|
namespace Controllers {
|
||||||
WeatherService::WeatherService(System::SystemTask& system, DateTime& dateTimeController)
|
WeatherService::WeatherService(System::SystemTask& system, DateTime& dateTimeController)
|
||||||
: system(system), dateTimeController(dateTimeController) {
|
: system(system), dateTimeController(dateTimeController) {
|
||||||
|
nullHeader = &nullTimelineheader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WeatherService::Init() {
|
void WeatherService::Init() {
|
||||||
|
@ -42,7 +43,7 @@ namespace Pinetime {
|
||||||
int WeatherService::OnCommand(uint16_t connHandle, uint16_t attrHandle, 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 uint8_t packetLen = OS_MBUF_PKTLEN(ctxt->om);
|
||||||
if (packetLen <= 0) {
|
if (packetLen <= 0) {
|
||||||
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
|
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
|
||||||
}
|
}
|
||||||
|
@ -56,30 +57,28 @@ namespace Pinetime {
|
||||||
// Always encodes to the smallest number of bytes based on the value
|
// Always encodes to the smallest number of bytes based on the value
|
||||||
int64_t tmpTimestamp = 0;
|
int64_t tmpTimestamp = 0;
|
||||||
QCBORDecode_GetInt64InMapSZ(&decodeContext, "Timestamp", &tmpTimestamp);
|
QCBORDecode_GetInt64InMapSZ(&decodeContext, "Timestamp", &tmpTimestamp);
|
||||||
if (QCBORDecode_GetError(&decodeContext) != QCBOR_SUCCESS) {
|
uint8_t err = QCBORDecode_GetError(&decodeContext);
|
||||||
|
if (err != QCBOR_SUCCESS) {
|
||||||
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
|
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
|
||||||
}
|
}
|
||||||
int64_t tmpExpires = 0;
|
int64_t tmpExpires = 0;
|
||||||
QCBORDecode_GetInt64InMapSZ(&decodeContext, "Expires", &tmpExpires);
|
QCBORDecode_GetInt64InMapSZ(&decodeContext, "Expires", &tmpExpires);
|
||||||
if (tmpExpires < 0 || tmpExpires > 4294967295) {
|
if (tmpExpires < 0 || tmpExpires > 4294967295) {
|
||||||
// TODO: Return better error?
|
|
||||||
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
|
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
|
||||||
}
|
}
|
||||||
int64_t tmpEventType = 0;
|
int64_t tmpEventType = 0;
|
||||||
QCBORDecode_GetInt64InMapSZ(&decodeContext, "EventType", &tmpEventType);
|
QCBORDecode_GetInt64InMapSZ(&decodeContext, "EventType", &tmpEventType);
|
||||||
if (tmpEventType < 0 || tmpEventType > static_cast<int64_t>(WeatherData::eventtype::Length)) {
|
if (tmpEventType < 0 || tmpEventType > static_cast<int64_t>(WeatherData::eventtype::Length)) {
|
||||||
// TODO: Return better error?
|
|
||||||
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
|
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (static_cast<WeatherData::eventtype>(tmpEventType)) {
|
switch (static_cast<WeatherData::eventtype>(tmpEventType)) {
|
||||||
// TODO: Populate
|
|
||||||
case WeatherData::eventtype::AirQuality: {
|
case WeatherData::eventtype::AirQuality: {
|
||||||
std::unique_ptr<WeatherData::AirQuality> airquality = std::make_unique<WeatherData::AirQuality>();
|
std::unique_ptr<WeatherData::AirQuality> airquality = std::make_unique<WeatherData::AirQuality>();
|
||||||
airquality->timestamp = tmpTimestamp;
|
airquality->timestamp = tmpTimestamp;
|
||||||
airquality->eventType = static_cast<WeatherData::eventtype>(tmpEventType);
|
airquality->eventType = static_cast<WeatherData::eventtype>(tmpEventType);
|
||||||
airquality->expires = tmpExpires;
|
airquality->expires = tmpExpires;
|
||||||
UsefulBufC String;
|
UsefulBufC String; // TODO: Everything ok with lifecycle here?
|
||||||
QCBORDecode_GetTextStringInMapSZ(&decodeContext, "Polluter", &String);
|
QCBORDecode_GetTextStringInMapSZ(&decodeContext, "Polluter", &String);
|
||||||
if (UsefulBuf_IsNULLOrEmptyC(String) != 0) {
|
if (UsefulBuf_IsNULLOrEmptyC(String) != 0) {
|
||||||
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
|
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
|
||||||
|
@ -172,10 +171,9 @@ namespace Pinetime {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GetCurrentPressure();
|
|
||||||
TidyTimeline();
|
|
||||||
GetTimelineLength();
|
|
||||||
QCBORDecode_ExitMap(&decodeContext);
|
QCBORDecode_ExitMap(&decodeContext);
|
||||||
|
GetTimelineLength();
|
||||||
|
TidyTimeline();
|
||||||
|
|
||||||
if (QCBORDecode_Finish(&decodeContext) != QCBOR_SUCCESS) {
|
if (QCBORDecode_Finish(&decodeContext) != QCBOR_SUCCESS) {
|
||||||
return BLE_ATT_ERR_INSUFFICIENT_RES;
|
return BLE_ATT_ERR_INSUFFICIENT_RES;
|
||||||
|
@ -205,94 +203,103 @@ namespace Pinetime {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
WeatherData::Clouds WeatherService::GetCurrentClouds() const {
|
std::unique_ptr<WeatherData::Clouds>& WeatherService::GetCurrentClouds() {
|
||||||
uint64_t currentTimestamp = GetCurrentUnixTimestamp();
|
uint64_t currentTimestamp = GetCurrentUnixTimestamp();
|
||||||
for (auto&& header : timeline) {
|
for (auto&& header : this->timeline) {
|
||||||
if (header->eventType == WeatherData::eventtype::Clouds && header->timestamp + header->expires <= currentTimestamp) {
|
if (header->eventType == WeatherData::eventtype::Clouds && isEventStillValid(header, currentTimestamp)) {
|
||||||
return reinterpret_cast<const WeatherData::Clouds&>(header);
|
return reinterpret_cast<std::unique_ptr<WeatherData::Clouds>&>(header);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
WeatherData::Obscuration WeatherService::GetCurrentObscuration() const {
|
return reinterpret_cast<std::unique_ptr<WeatherData::Clouds>&>(this->nullHeader);
|
||||||
uint64_t currentTimestamp = GetCurrentUnixTimestamp();
|
|
||||||
for (auto&& header : timeline) {
|
|
||||||
if (header->eventType == WeatherData::eventtype::Obscuration && header->timestamp + header->expires <= currentTimestamp) {
|
|
||||||
return reinterpret_cast<const WeatherData::Obscuration&>(header);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WeatherData::Precipitation WeatherService::GetCurrentPrecipitation() const {
|
std::unique_ptr<WeatherData::Obscuration>& WeatherService::GetCurrentObscuration() {
|
||||||
uint64_t currentTimestamp = GetCurrentUnixTimestamp();
|
uint64_t currentTimestamp = GetCurrentUnixTimestamp();
|
||||||
for (auto&& header : timeline) {
|
for (auto&& header : this->timeline) {
|
||||||
if (header->eventType == WeatherData::eventtype::Precipitation && header->timestamp + header->expires <= currentTimestamp) {
|
if (header->eventType == WeatherData::eventtype::Obscuration && isEventStillValid(header, currentTimestamp)) {
|
||||||
return reinterpret_cast<const WeatherData::Precipitation&>(header);
|
return reinterpret_cast<std::unique_ptr<WeatherData::Obscuration>&>(header);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
WeatherData::Wind WeatherService::GetCurrentWind() const {
|
return reinterpret_cast<std::unique_ptr<WeatherData::Obscuration>&>(this->nullHeader);
|
||||||
uint64_t currentTimestamp = GetCurrentUnixTimestamp();
|
|
||||||
for (auto&& header : timeline) {
|
|
||||||
if (header->eventType == WeatherData::eventtype::Wind && header->timestamp + header->expires <= currentTimestamp) {
|
|
||||||
return reinterpret_cast<const WeatherData::Wind&>(header);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WeatherData::Temperature WeatherService::GetCurrentTemperature() const {
|
std::unique_ptr<WeatherData::Precipitation>& WeatherService::GetCurrentPrecipitation() {
|
||||||
uint64_t currentTimestamp = GetCurrentUnixTimestamp();
|
uint64_t currentTimestamp = GetCurrentUnixTimestamp();
|
||||||
for (auto&& header : timeline) {
|
for (auto&& header : this->timeline) {
|
||||||
if (header->eventType == WeatherData::eventtype::Temperature && header->timestamp + header->expires <= currentTimestamp) {
|
if (header->eventType == WeatherData::eventtype::Precipitation && isEventStillValid(header, currentTimestamp)) {
|
||||||
return reinterpret_cast<const WeatherData::Temperature&>(header);
|
return reinterpret_cast<std::unique_ptr<WeatherData::Precipitation>&>(header);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
WeatherData::Humidity WeatherService::GetCurrentHumidity() const {
|
return reinterpret_cast<std::unique_ptr<WeatherData::Precipitation>&>(this->nullHeader);
|
||||||
uint64_t currentTimestamp = GetCurrentUnixTimestamp();
|
|
||||||
for (auto&& header : timeline) {
|
|
||||||
if (header->eventType == WeatherData::eventtype::Humidity && header->timestamp + header->expires <= currentTimestamp) {
|
|
||||||
return reinterpret_cast<const WeatherData::Humidity&>(header);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WeatherData::Pressure WeatherService::GetCurrentPressure() const {
|
std::unique_ptr<WeatherData::Wind>& WeatherService::GetCurrentWind() {
|
||||||
uint64_t currentTimestamp = GetCurrentUnixTimestamp();
|
uint64_t currentTimestamp = GetCurrentUnixTimestamp();
|
||||||
for (auto&& header : timeline) {
|
for (auto&& header : this->timeline) {
|
||||||
if (header->eventType == WeatherData::eventtype::Pressure && header->timestamp + header->expires <= currentTimestamp) {
|
if (header->eventType == WeatherData::eventtype::Wind && isEventStillValid(header, currentTimestamp)) {
|
||||||
return reinterpret_cast<const WeatherData::Pressure&>(header);
|
return reinterpret_cast<std::unique_ptr<WeatherData::Wind>&>(header);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
WeatherData::Location WeatherService::GetCurrentLocation() const {
|
return reinterpret_cast<std::unique_ptr<WeatherData::Wind>&>(this->nullHeader);
|
||||||
uint64_t currentTimestamp = GetCurrentUnixTimestamp();
|
|
||||||
for (auto&& header : timeline) {
|
|
||||||
if (header->eventType == WeatherData::eventtype::Location && header->timestamp + header->expires <= currentTimestamp) {
|
|
||||||
return reinterpret_cast<const WeatherData::Location&>(header);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WeatherData::AirQuality WeatherService::GetCurrentQuality() const {
|
std::unique_ptr<WeatherData::Temperature>& WeatherService::GetCurrentTemperature() {
|
||||||
uint64_t currentTimestamp = GetCurrentUnixTimestamp();
|
uint64_t currentTimestamp = GetCurrentUnixTimestamp();
|
||||||
for (auto&& header : timeline) {
|
for (auto&& header : this->timeline) {
|
||||||
if (header->eventType == WeatherData::eventtype::AirQuality && header->timestamp + header->expires <= currentTimestamp) {
|
if (header->eventType == WeatherData::eventtype::Temperature && isEventStillValid(header, currentTimestamp)) {
|
||||||
return reinterpret_cast<const WeatherData::AirQuality&>(header);
|
return reinterpret_cast<std::unique_ptr<WeatherData::Temperature>&>(header);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {};
|
|
||||||
|
return reinterpret_cast<std::unique_ptr<WeatherData::Temperature>&>(this->nullHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<WeatherData::Humidity>& WeatherService::GetCurrentHumidity() {
|
||||||
|
uint64_t currentTimestamp = GetCurrentUnixTimestamp();
|
||||||
|
for (auto&& header : this->timeline) {
|
||||||
|
if (header->eventType == WeatherData::eventtype::Humidity && isEventStillValid(header, currentTimestamp)) {
|
||||||
|
return reinterpret_cast<std::unique_ptr<WeatherData::Humidity>&>(header);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return reinterpret_cast<std::unique_ptr<WeatherData::Humidity>&>(this->nullHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<WeatherData::Pressure>& WeatherService::GetCurrentPressure() {
|
||||||
|
uint64_t currentTimestamp = GetCurrentUnixTimestamp();
|
||||||
|
for (auto&& header : this->timeline) {
|
||||||
|
if (header->eventType == WeatherData::eventtype::Pressure && isEventStillValid(header, currentTimestamp)) {
|
||||||
|
return reinterpret_cast<std::unique_ptr<WeatherData::Pressure>&>(header);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return reinterpret_cast<std::unique_ptr<WeatherData::Pressure>&>(this->nullHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<WeatherData::Location>& WeatherService::GetCurrentLocation() {
|
||||||
|
uint64_t currentTimestamp = GetCurrentUnixTimestamp();
|
||||||
|
for (auto&& header : this->timeline) {
|
||||||
|
if (header->eventType == WeatherData::eventtype::Location && isEventStillValid(header, currentTimestamp)) {
|
||||||
|
return reinterpret_cast<std::unique_ptr<WeatherData::Location>&>(header);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return reinterpret_cast<std::unique_ptr<WeatherData::Location>&>(this->nullHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<WeatherData::AirQuality>& WeatherService::GetCurrentQuality() {
|
||||||
|
uint64_t currentTimestamp = GetCurrentUnixTimestamp();
|
||||||
|
for (auto&& header : this->timeline) {
|
||||||
|
if (header->eventType == WeatherData::eventtype::AirQuality && isEventStillValid(header, currentTimestamp)) {
|
||||||
|
return reinterpret_cast<std::unique_ptr<WeatherData::AirQuality>&>(header);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return reinterpret_cast<std::unique_ptr<WeatherData::AirQuality>&>(this->nullHeader);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t WeatherService::GetTimelineLength() const {
|
size_t WeatherService::GetTimelineLength() const {
|
||||||
|
@ -311,8 +318,7 @@ namespace Pinetime {
|
||||||
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 && isEventStillValid(header, currentTimestamp)) {
|
||||||
// TODO: Check if its currently valid
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -320,11 +326,11 @@ namespace Pinetime {
|
||||||
}
|
}
|
||||||
|
|
||||||
void WeatherService::TidyTimeline() {
|
void WeatherService::TidyTimeline() {
|
||||||
uint64_t timeCurrent = 0;
|
uint64_t timeCurrent = GetCurrentUnixTimestamp();
|
||||||
timeline.erase(std::remove_if(std::begin(timeline),
|
timeline.erase(std::remove_if(std::begin(timeline),
|
||||||
std::end(timeline),
|
std::end(timeline),
|
||||||
[&](std::unique_ptr<WeatherData::TimelineHeader> const& header) {
|
[&](std::unique_ptr<WeatherData::TimelineHeader> const& header) {
|
||||||
return header->timestamp + header->expires > timeCurrent;
|
return isEventStillValid(header, timeCurrent);
|
||||||
}),
|
}),
|
||||||
std::end(timeline));
|
std::end(timeline));
|
||||||
|
|
||||||
|
@ -336,6 +342,11 @@ namespace Pinetime {
|
||||||
return first->timestamp > second->timestamp;
|
return first->timestamp > second->timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WeatherService::isEventStillValid(const std::unique_ptr<WeatherData::TimelineHeader>& header, const uint64_t currentTimestamp) {
|
||||||
|
// Not getting timestamp in isEventStillValid for more speed
|
||||||
|
return header->timestamp + header->expires <= currentTimestamp;
|
||||||
|
}
|
||||||
|
|
||||||
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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,15 +51,15 @@ namespace Pinetime {
|
||||||
/*
|
/*
|
||||||
* Helper functions for quick access to currently valid data
|
* Helper functions for quick access to currently valid data
|
||||||
*/
|
*/
|
||||||
WeatherData::Location GetCurrentLocation() const;
|
std::unique_ptr<WeatherData::Location>& GetCurrentLocation();
|
||||||
WeatherData::Clouds GetCurrentClouds() const;
|
std::unique_ptr<WeatherData::Clouds>& GetCurrentClouds();
|
||||||
WeatherData::Obscuration GetCurrentObscuration() const;
|
std::unique_ptr<WeatherData::Obscuration>& GetCurrentObscuration();
|
||||||
WeatherData::Precipitation GetCurrentPrecipitation() const;
|
std::unique_ptr<WeatherData::Precipitation>& GetCurrentPrecipitation();
|
||||||
WeatherData::Wind GetCurrentWind() const;
|
std::unique_ptr<WeatherData::Wind>& GetCurrentWind();
|
||||||
WeatherData::Temperature GetCurrentTemperature() const;
|
std::unique_ptr<WeatherData::Temperature>& GetCurrentTemperature();
|
||||||
WeatherData::Humidity GetCurrentHumidity() const;
|
std::unique_ptr<WeatherData::Humidity>& GetCurrentHumidity();
|
||||||
WeatherData::Pressure GetCurrentPressure() const;
|
std::unique_ptr<WeatherData::Pressure>& GetCurrentPressure();
|
||||||
WeatherData::AirQuality GetCurrentQuality() const;
|
std::unique_ptr<WeatherData::AirQuality>& GetCurrentQuality();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Management functions
|
* Management functions
|
||||||
|
@ -123,7 +123,6 @@ namespace Pinetime {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cleans up the timeline of expired events
|
* Cleans up the timeline of expired events
|
||||||
* @return result code
|
|
||||||
*/
|
*/
|
||||||
void TidyTimeline();
|
void TidyTimeline();
|
||||||
|
|
||||||
|
@ -137,6 +136,18 @@ namespace Pinetime {
|
||||||
* Returns current UNIX timestamp
|
* Returns current UNIX timestamp
|
||||||
*/
|
*/
|
||||||
uint64_t GetCurrentUnixTimestamp() const;
|
uint64_t GetCurrentUnixTimestamp() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the event hasn't gone past and expired
|
||||||
|
*
|
||||||
|
* @param header timeline event to check
|
||||||
|
* @param currentTimestamp what's the time right now
|
||||||
|
* @return if the event is valid
|
||||||
|
*/
|
||||||
|
static bool isEventStillValid(const std::unique_ptr<WeatherData::TimelineHeader>& uniquePtr, const uint64_t timestamp);
|
||||||
|
|
||||||
|
std::unique_ptr<WeatherData::TimelineHeader> nullTimelineheader = std::make_unique<WeatherData::TimelineHeader>();
|
||||||
|
std::unique_ptr<WeatherData::TimelineHeader>* nullHeader;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ namespace Pinetime {
|
||||||
Metronome,
|
Metronome,
|
||||||
Motion,
|
Motion,
|
||||||
Steps,
|
Steps,
|
||||||
|
Weather,
|
||||||
QuickSettings,
|
QuickSettings,
|
||||||
Settings,
|
Settings,
|
||||||
SettingWatchFace,
|
SettingWatchFace,
|
||||||
|
|
|
@ -35,16 +35,16 @@ Weather::Weather(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers:
|
||||||
return CreateScreenTemperature();
|
return CreateScreenTemperature();
|
||||||
},
|
},
|
||||||
[this]() -> std::unique_ptr<Screen> {
|
[this]() -> std::unique_ptr<Screen> {
|
||||||
return CreateScreen2();
|
return CreateScreenAir();
|
||||||
},
|
},
|
||||||
[this]() -> std::unique_ptr<Screen> {
|
[this]() -> std::unique_ptr<Screen> {
|
||||||
return CreateScreen3();
|
return CreateScreenClouds();
|
||||||
},
|
},
|
||||||
[this]() -> std::unique_ptr<Screen> {
|
[this]() -> std::unique_ptr<Screen> {
|
||||||
return CreateScreen4();
|
return CreateScreenPrecipitation();
|
||||||
},
|
},
|
||||||
[this]() -> std::unique_ptr<Screen> {
|
[this]() -> std::unique_ptr<Screen> {
|
||||||
return CreateScreen5();
|
return CreateScreenHumidity();
|
||||||
}},
|
}},
|
||||||
Screens::ScreenListModes::UpDown} {
|
Screens::ScreenListModes::UpDown} {
|
||||||
}
|
}
|
||||||
|
@ -71,78 +71,108 @@ bool Weather::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
|
||||||
std::unique_ptr<Screen> Weather::CreateScreenTemperature() {
|
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();
|
std::unique_ptr<Controllers::WeatherData::Temperature>& current = weatherService.GetCurrentTemperature();
|
||||||
|
if (current->timestamp == 0) {
|
||||||
|
// Do not use the data, it's invalid
|
||||||
|
} else {
|
||||||
lv_label_set_text_fmt(label,
|
lv_label_set_text_fmt(label,
|
||||||
"#FFFF00 Temperature#\n\n"
|
"#FFFF00 Temperature#\n\n"
|
||||||
"#444444 %hd%%#°C \n\n"
|
"#444444 %hd%%#°C \n\n"
|
||||||
"#444444 %hd#\n"
|
"#444444 %hd#\n\n"
|
||||||
"%llu\n"
|
"%llu\n"
|
||||||
"%lu\n",
|
"%lu\n",
|
||||||
current.temperature,
|
current->temperature,
|
||||||
current.dewPoint,
|
current->dewPoint,
|
||||||
current.timestamp,
|
current->timestamp,
|
||||||
current.expires);
|
current->expires);
|
||||||
|
}
|
||||||
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::CreateScreenAir() {
|
||||||
// uptime
|
|
||||||
lv_obj_t* label = lv_label_create(lv_scr_act(), nullptr);
|
|
||||||
lv_label_set_recolor(label, true);
|
|
||||||
lv_label_set_text_fmt(label, "#444444 Date# %02d\n", dateTimeController.Day());
|
|
||||||
lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0);
|
|
||||||
return std::unique_ptr<Screen>(new Screens::Label(1, 4, app, label));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<Screen> Weather::CreateScreen3() {
|
|
||||||
lv_mem_monitor_t mon;
|
|
||||||
lv_mem_monitor(&mon);
|
|
||||||
|
|
||||||
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);
|
||||||
|
std::unique_ptr<Controllers::WeatherData::AirQuality>& current = weatherService.GetCurrentQuality();
|
||||||
|
if (current->timestamp == 0) {
|
||||||
|
// Do not use the data, it's invalid
|
||||||
|
} else {
|
||||||
lv_label_set_text_fmt(label,
|
lv_label_set_text_fmt(label,
|
||||||
" #444444 frag# %d%%\n"
|
"#FFFF00 Air quality#\n\n"
|
||||||
" #444444 free# %d",
|
"#444444 %s#\n"
|
||||||
mon.used_pct,
|
"#444444 %lu#\n\n"
|
||||||
mon.frag_pct);
|
"%llu\n"
|
||||||
lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0);
|
"%lu\n",
|
||||||
return std::unique_ptr<Screen>(new Screens::Label(2, 5, app, label));
|
current->polluter.c_str(),
|
||||||
|
current->amount,
|
||||||
|
current->timestamp,
|
||||||
|
current->expires);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sortById(const TaskStatus_t& lhs, const TaskStatus_t& rhs) {
|
|
||||||
return lhs.xTaskNumber < rhs.xTaskNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<Screen> Weather::CreateScreen4() {
|
|
||||||
lv_obj_t* infoTask = lv_table_create(lv_scr_act(), nullptr);
|
|
||||||
lv_table_set_col_cnt(infoTask, 3);
|
|
||||||
lv_table_set_row_cnt(infoTask, 8);
|
|
||||||
lv_obj_set_pos(infoTask, 10, 10);
|
|
||||||
|
|
||||||
lv_table_set_cell_value(infoTask, 0, 0, "#");
|
|
||||||
lv_table_set_col_width(infoTask, 0, 50);
|
|
||||||
lv_table_set_cell_value(infoTask, 0, 1, "Task");
|
|
||||||
lv_table_set_col_width(infoTask, 1, 80);
|
|
||||||
lv_table_set_cell_value(infoTask, 0, 2, "Free");
|
|
||||||
lv_table_set_col_width(infoTask, 2, 90);
|
|
||||||
|
|
||||||
return std::unique_ptr<Screen>(new Screens::Label(3, 5, app, infoTask));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<Screen> Weather::CreateScreen5() {
|
|
||||||
lv_obj_t* label = lv_label_create(lv_scr_act(), nullptr);
|
|
||||||
lv_label_set_recolor(label, true);
|
|
||||||
lv_label_set_text_static(label,
|
|
||||||
"Software Licensed\n"
|
|
||||||
"under the terms of\n"
|
|
||||||
"the GNU General\n"
|
|
||||||
"Public License v3\n"
|
|
||||||
"#444444 Source code#\n"
|
|
||||||
"#FFFF00 https://github.com/#\n"
|
|
||||||
"#FFFF00 JF002/InfiniTime#");
|
|
||||||
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(4, 5, app, label));
|
return std::unique_ptr<Screen>(new Screens::Label(0, 5, app, label));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Screen> Weather::CreateScreenClouds() {
|
||||||
|
lv_obj_t* label = lv_label_create(lv_scr_act(), nullptr);
|
||||||
|
lv_label_set_recolor(label, true);
|
||||||
|
std::unique_ptr<Controllers::WeatherData::Clouds>& current = weatherService.GetCurrentClouds();
|
||||||
|
if (current->timestamp == 0) {
|
||||||
|
// Do not use the data, it's invalid
|
||||||
|
} else {
|
||||||
|
lv_label_set_text_fmt(label,
|
||||||
|
"#FFFF00 Clouds#\n\n"
|
||||||
|
"#444444 %hhu%%#\n\n"
|
||||||
|
"%llu\n"
|
||||||
|
"%lu\n",
|
||||||
|
current->amount,
|
||||||
|
current->timestamp,
|
||||||
|
current->expires);
|
||||||
|
}
|
||||||
|
lv_label_set_align(label, LV_LABEL_ALIGN_CENTER);
|
||||||
|
lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0);
|
||||||
|
return std::unique_ptr<Screen>(new Screens::Label(0, 5, app, label));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Screen> Weather::CreateScreenPrecipitation() {
|
||||||
|
lv_obj_t* label = lv_label_create(lv_scr_act(), nullptr);
|
||||||
|
lv_label_set_recolor(label, true);
|
||||||
|
std::unique_ptr<Controllers::WeatherData::Precipitation>& current = weatherService.GetCurrentPrecipitation();
|
||||||
|
if (current->timestamp == 0) {
|
||||||
|
// Do not use the data, it's invalid
|
||||||
|
} else {
|
||||||
|
lv_label_set_text_fmt(label,
|
||||||
|
"#FFFF00 Precipitation#\n\n"
|
||||||
|
"#444444 %hhu%%#\n\n"
|
||||||
|
"%llu\n"
|
||||||
|
"%lu\n",
|
||||||
|
current->amount,
|
||||||
|
current->timestamp,
|
||||||
|
current->expires);
|
||||||
|
}
|
||||||
|
lv_label_set_align(label, LV_LABEL_ALIGN_CENTER);
|
||||||
|
lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0);
|
||||||
|
return std::unique_ptr<Screen>(new Screens::Label(0, 5, app, label));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Screen> Weather::CreateScreenHumidity() {
|
||||||
|
lv_obj_t* label = lv_label_create(lv_scr_act(), nullptr);
|
||||||
|
lv_label_set_recolor(label, true);
|
||||||
|
std::unique_ptr<Controllers::WeatherData::Humidity>& current = weatherService.GetCurrentHumidity();
|
||||||
|
if (current->timestamp == 0) {
|
||||||
|
// Do not use the data, it's invalid
|
||||||
|
} else {
|
||||||
|
lv_label_set_text_fmt(label,
|
||||||
|
"#FFFF00 Humidity#\n\n"
|
||||||
|
"#444444 %hhu%%#\n\n"
|
||||||
|
"%llu\n"
|
||||||
|
"%lu\n",
|
||||||
|
current->humidity,
|
||||||
|
current->timestamp,
|
||||||
|
current->expires);
|
||||||
|
}
|
||||||
|
lv_label_set_align(label, LV_LABEL_ALIGN_CENTER);
|
||||||
|
lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0);
|
||||||
|
return std::unique_ptr<Screen>(new Screens::Label(0, 5, app, label));
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,13 +32,13 @@ namespace Pinetime {
|
||||||
|
|
||||||
std::unique_ptr<Screen> CreateScreenTemperature();
|
std::unique_ptr<Screen> CreateScreenTemperature();
|
||||||
|
|
||||||
std::unique_ptr<Screen> CreateScreen2();
|
std::unique_ptr<Screen> CreateScreenAir();
|
||||||
|
|
||||||
std::unique_ptr<Screen> CreateScreen3();
|
std::unique_ptr<Screen> CreateScreenClouds();
|
||||||
|
|
||||||
std::unique_ptr<Screen> CreateScreen4();
|
std::unique_ptr<Screen> CreateScreenPrecipitation();
|
||||||
|
|
||||||
std::unique_ptr<Screen> CreateScreen5();
|
std::unique_ptr<Screen> CreateScreenHumidity();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue