diff options
Diffstat (limited to 'src/components/ble/weather')
-rw-r--r-- | src/components/ble/weather/WeatherService.cpp | 127 | ||||
-rw-r--r-- | src/components/ble/weather/WeatherService.h | 31 |
2 files changed, 90 insertions, 68 deletions
diff --git a/src/components/ble/weather/WeatherService.cpp b/src/components/ble/weather/WeatherService.cpp index 42302610..4ec57d00 100644 --- a/src/components/ble/weather/WeatherService.cpp +++ b/src/components/ble/weather/WeatherService.cpp @@ -28,6 +28,7 @@ namespace Pinetime { namespace Controllers { WeatherService::WeatherService(System::SystemTask& system, DateTime& dateTimeController) : system(system), dateTimeController(dateTimeController) { + nullHeader = &nullTimelineheader; } void WeatherService::Init() { @@ -42,7 +43,7 @@ namespace Pinetime { int WeatherService::OnCommand(uint16_t connHandle, uint16_t attrHandle, struct ble_gatt_access_ctxt* ctxt) { // TODO: Detect control messages 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) { 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 int64_t tmpTimestamp = 0; 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; } int64_t tmpExpires = 0; QCBORDecode_GetInt64InMapSZ(&decodeContext, "Expires", &tmpExpires); if (tmpExpires < 0 || tmpExpires > 4294967295) { - // TODO: Return better error? return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } int64_t tmpEventType = 0; QCBORDecode_GetInt64InMapSZ(&decodeContext, "EventType", &tmpEventType); if (tmpEventType < 0 || tmpEventType > static_cast<int64_t>(WeatherData::eventtype::Length)) { - // TODO: Return better error? return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } switch (static_cast<WeatherData::eventtype>(tmpEventType)) { - // TODO: Populate case WeatherData::eventtype::AirQuality: { std::unique_ptr<WeatherData::AirQuality> airquality = std::make_unique<WeatherData::AirQuality>(); airquality->timestamp = tmpTimestamp; airquality->eventType = static_cast<WeatherData::eventtype>(tmpEventType); airquality->expires = tmpExpires; - UsefulBufC String; + UsefulBufC String; // TODO: Everything ok with lifecycle here? QCBORDecode_GetTextStringInMapSZ(&decodeContext, "Polluter", &String); if (UsefulBuf_IsNULLOrEmptyC(String) != 0) { return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; @@ -172,10 +171,9 @@ namespace Pinetime { } } - GetCurrentPressure(); - TidyTimeline(); - GetTimelineLength(); QCBORDecode_ExitMap(&decodeContext); + GetTimelineLength(); + TidyTimeline(); if (QCBORDecode_Finish(&decodeContext) != QCBOR_SUCCESS) { return BLE_ATT_ERR_INSUFFICIENT_RES; @@ -205,94 +203,103 @@ namespace Pinetime { return 0; } - WeatherData::Clouds WeatherService::GetCurrentClouds() const { + std::unique_ptr<WeatherData::Clouds>& WeatherService::GetCurrentClouds() { uint64_t currentTimestamp = GetCurrentUnixTimestamp(); - for (auto&& header : timeline) { - if (header->eventType == WeatherData::eventtype::Clouds && header->timestamp + header->expires <= currentTimestamp) { - return reinterpret_cast<const WeatherData::Clouds&>(header); + for (auto&& header : this->timeline) { + if (header->eventType == WeatherData::eventtype::Clouds && isEventStillValid(header, currentTimestamp)) { + return reinterpret_cast<std::unique_ptr<WeatherData::Clouds>&>(header); } } - return {}; + + return reinterpret_cast<std::unique_ptr<WeatherData::Clouds>&>(this->nullHeader); } - WeatherData::Obscuration WeatherService::GetCurrentObscuration() const { + std::unique_ptr<WeatherData::Obscuration>& WeatherService::GetCurrentObscuration() { 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); + for (auto&& header : this->timeline) { + if (header->eventType == WeatherData::eventtype::Obscuration && isEventStillValid(header, currentTimestamp)) { + return reinterpret_cast<std::unique_ptr<WeatherData::Obscuration>&>(header); } } - return {}; + + return reinterpret_cast<std::unique_ptr<WeatherData::Obscuration>&>(this->nullHeader); } - WeatherData::Precipitation WeatherService::GetCurrentPrecipitation() const { + std::unique_ptr<WeatherData::Precipitation>& WeatherService::GetCurrentPrecipitation() { uint64_t currentTimestamp = GetCurrentUnixTimestamp(); - for (auto&& header : timeline) { - if (header->eventType == WeatherData::eventtype::Precipitation && header->timestamp + header->expires <= currentTimestamp) { - return reinterpret_cast<const WeatherData::Precipitation&>(header); + for (auto&& header : this->timeline) { + if (header->eventType == WeatherData::eventtype::Precipitation && isEventStillValid(header, currentTimestamp)) { + return reinterpret_cast<std::unique_ptr<WeatherData::Precipitation>&>(header); } } - return {}; + + return reinterpret_cast<std::unique_ptr<WeatherData::Precipitation>&>(this->nullHeader); } - WeatherData::Wind WeatherService::GetCurrentWind() const { + std::unique_ptr<WeatherData::Wind>& WeatherService::GetCurrentWind() { 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); + for (auto&& header : this->timeline) { + if (header->eventType == WeatherData::eventtype::Wind && isEventStillValid(header, currentTimestamp)) { + return reinterpret_cast<std::unique_ptr<WeatherData::Wind>&>(header); } } - return {}; + + return reinterpret_cast<std::unique_ptr<WeatherData::Wind>&>(this->nullHeader); } - WeatherData::Temperature WeatherService::GetCurrentTemperature() const { + std::unique_ptr<WeatherData::Temperature>& WeatherService::GetCurrentTemperature() { uint64_t currentTimestamp = GetCurrentUnixTimestamp(); - for (auto&& header : timeline) { - if (header->eventType == WeatherData::eventtype::Temperature && header->timestamp + header->expires <= currentTimestamp) { - return reinterpret_cast<const WeatherData::Temperature&>(header); + for (auto&& header : this->timeline) { + if (header->eventType == WeatherData::eventtype::Temperature && isEventStillValid(header, currentTimestamp)) { + return reinterpret_cast<std::unique_ptr<WeatherData::Temperature>&>(header); } } - return {}; + + return reinterpret_cast<std::unique_ptr<WeatherData::Temperature>&>(this->nullHeader); } - WeatherData::Humidity WeatherService::GetCurrentHumidity() const { + std::unique_ptr<WeatherData::Humidity>& WeatherService::GetCurrentHumidity() { 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); + for (auto&& header : this->timeline) { + if (header->eventType == WeatherData::eventtype::Humidity && isEventStillValid(header, currentTimestamp)) { + return reinterpret_cast<std::unique_ptr<WeatherData::Humidity>&>(header); } } - return {}; + + return reinterpret_cast<std::unique_ptr<WeatherData::Humidity>&>(this->nullHeader); } - WeatherData::Pressure WeatherService::GetCurrentPressure() const { + std::unique_ptr<WeatherData::Pressure>& WeatherService::GetCurrentPressure() { uint64_t currentTimestamp = GetCurrentUnixTimestamp(); - for (auto&& header : timeline) { - if (header->eventType == WeatherData::eventtype::Pressure && header->timestamp + header->expires <= currentTimestamp) { - return reinterpret_cast<const WeatherData::Pressure&>(header); + for (auto&& header : this->timeline) { + if (header->eventType == WeatherData::eventtype::Pressure && isEventStillValid(header, currentTimestamp)) { + return reinterpret_cast<std::unique_ptr<WeatherData::Pressure>&>(header); } } - return {}; + + return reinterpret_cast<std::unique_ptr<WeatherData::Pressure>&>(this->nullHeader); } - WeatherData::Location WeatherService::GetCurrentLocation() const { + std::unique_ptr<WeatherData::Location>& WeatherService::GetCurrentLocation() { 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); + for (auto&& header : this->timeline) { + if (header->eventType == WeatherData::eventtype::Location && isEventStillValid(header, currentTimestamp)) { + return reinterpret_cast<std::unique_ptr<WeatherData::Location>&>(header); } } - return {}; + + return reinterpret_cast<std::unique_ptr<WeatherData::Location>&>(this->nullHeader); } - WeatherData::AirQuality WeatherService::GetCurrentQuality() const { + std::unique_ptr<WeatherData::AirQuality>& WeatherService::GetCurrentQuality() { uint64_t currentTimestamp = GetCurrentUnixTimestamp(); - for (auto&& header : timeline) { - if (header->eventType == WeatherData::eventtype::AirQuality && header->timestamp + header->expires <= currentTimestamp) { - return reinterpret_cast<const WeatherData::AirQuality&>(header); + for (auto&& header : this->timeline) { + if (header->eventType == WeatherData::eventtype::AirQuality && isEventStillValid(header, currentTimestamp)) { + return reinterpret_cast<std::unique_ptr<WeatherData::AirQuality>&>(header); } } - return {}; + + return reinterpret_cast<std::unique_ptr<WeatherData::AirQuality>&>(this->nullHeader); } size_t WeatherService::GetTimelineLength() const { @@ -311,8 +318,7 @@ namespace Pinetime { bool WeatherService::HasTimelineEventOfType(const WeatherData::eventtype type) const { uint64_t currentTimestamp = GetCurrentUnixTimestamp(); for (auto&& header : timeline) { - if (header->eventType == type && header->timestamp + header->expires <= currentTimestamp) { - // TODO: Check if its currently valid + if (header->eventType == type && isEventStillValid(header, currentTimestamp)) { return true; } } @@ -320,11 +326,11 @@ namespace Pinetime { } void WeatherService::TidyTimeline() { - uint64_t timeCurrent = 0; + uint64_t timeCurrent = GetCurrentUnixTimestamp(); timeline.erase(std::remove_if(std::begin(timeline), std::end(timeline), [&](std::unique_ptr<WeatherData::TimelineHeader> const& header) { - return header->timestamp + header->expires > timeCurrent; + return isEventStillValid(header, timeCurrent); }), std::end(timeline)); @@ -336,6 +342,11 @@ namespace Pinetime { 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 { return std::chrono::duration_cast<std::chrono::seconds>(dateTimeController.CurrentDateTime().time_since_epoch()).count(); } diff --git a/src/components/ble/weather/WeatherService.h b/src/components/ble/weather/WeatherService.h index 43b2ee28..7accc49e 100644 --- a/src/components/ble/weather/WeatherService.h +++ b/src/components/ble/weather/WeatherService.h @@ -51,15 +51,15 @@ namespace Pinetime { /* * Helper functions for quick access to currently valid data */ - WeatherData::Location GetCurrentLocation() const; - WeatherData::Clouds GetCurrentClouds() const; - WeatherData::Obscuration GetCurrentObscuration() const; - WeatherData::Precipitation GetCurrentPrecipitation() const; - WeatherData::Wind GetCurrentWind() const; - WeatherData::Temperature GetCurrentTemperature() const; - WeatherData::Humidity GetCurrentHumidity() const; - WeatherData::Pressure GetCurrentPressure() const; - WeatherData::AirQuality GetCurrentQuality() const; + std::unique_ptr<WeatherData::Location>& GetCurrentLocation(); + std::unique_ptr<WeatherData::Clouds>& GetCurrentClouds(); + std::unique_ptr<WeatherData::Obscuration>& GetCurrentObscuration(); + std::unique_ptr<WeatherData::Precipitation>& GetCurrentPrecipitation(); + std::unique_ptr<WeatherData::Wind>& GetCurrentWind(); + std::unique_ptr<WeatherData::Temperature>& GetCurrentTemperature(); + std::unique_ptr<WeatherData::Humidity>& GetCurrentHumidity(); + std::unique_ptr<WeatherData::Pressure>& GetCurrentPressure(); + std::unique_ptr<WeatherData::AirQuality>& GetCurrentQuality(); /* * Management functions @@ -123,7 +123,6 @@ namespace Pinetime { /** * Cleans up the timeline of expired events - * @return result code */ void TidyTimeline(); @@ -137,6 +136,18 @@ namespace Pinetime { * Returns current UNIX timestamp */ 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; }; } } |