InfiniTime/src/components/ble/weather/WeatherService.cpp

518 lines
23 KiB
C++
Raw Normal View History

2021-06-09 21:44:49 +00:00
/* Copyright (C) 2021 Avamander
This file is part of InfiniTime.
InfiniTime is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
InfiniTime is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <qcbor/qcbor_spiffy_decode.h>
#include "WeatherService.h"
#include "libs/QCBOR/inc/qcbor/qcbor.h"
#include "systemtask/SystemTask.h"
2021-06-24 22:18:56 +00:00
int WeatherCallback(uint16_t connHandle, uint16_t attrHandle, struct ble_gatt_access_ctxt* ctxt, void* arg) {
return static_cast<Pinetime::Controllers::WeatherService*>(arg)->OnCommand(connHandle, attrHandle, ctxt);
2021-06-09 21:44:49 +00:00
}
namespace Pinetime {
namespace Controllers {
WeatherService::WeatherService(System::SystemTask& system, DateTime& dateTimeController)
: system(system), dateTimeController(dateTimeController) {
nullHeader = &nullTimelineheader;
2021-11-30 23:15:11 +00:00
nullTimelineheader->timestamp = 0;
2021-06-09 21:44:49 +00:00
}
void WeatherService::Init() {
uint8_t res = 0;
res = ble_gatts_count_cfg(serviceDefinition);
ASSERT(res == 0);
2021-06-09 21:44:49 +00:00
res = ble_gatts_add_svcs(serviceDefinition);
ASSERT(res == 0);
}
2021-06-24 22:18:56 +00:00
int WeatherService::OnCommand(uint16_t connHandle, uint16_t attrHandle, struct ble_gatt_access_ctxt* ctxt) {
2021-06-09 21:44:49 +00:00
if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
const uint8_t packetLen = OS_MBUF_PKTLEN(ctxt->om); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
2021-06-09 21:44:49 +00:00
if (packetLen <= 0) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
// Decode
QCBORDecodeContext decodeContext;
UsefulBufC encodedCbor = {ctxt->om->om_data, OS_MBUF_PKTLEN(ctxt->om)}; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
2021-06-16 20:31:17 +00:00
QCBORDecode_Init(&decodeContext, encodedCbor, QCBOR_DECODE_MODE_NORMAL);
// KINDLY provide us a fixed-length map
2021-06-09 21:44:49 +00:00
QCBORDecode_EnterMap(&decodeContext, nullptr);
// Always encodes to the smallest number of bytes based on the value
2021-06-16 20:31:17 +00:00
int64_t tmpTimestamp = 0;
QCBORDecode_GetInt64InMapSZ(&decodeContext, "Timestamp", &tmpTimestamp);
if (QCBORDecode_GetError(&decodeContext) != QCBOR_SUCCESS) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
2021-06-16 20:31:17 +00:00
int64_t tmpExpires = 0;
QCBORDecode_GetInt64InMapSZ(&decodeContext, "Expires", &tmpExpires);
if (QCBORDecode_GetError(&decodeContext) != QCBOR_SUCCESS || tmpExpires < 0 || tmpExpires > 4294967295) {
2021-06-16 20:31:17 +00:00
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
int64_t tmpEventType = 0;
QCBORDecode_GetInt64InMapSZ(&decodeContext, "EventType", &tmpEventType);
if (QCBORDecode_GetError(&decodeContext) != QCBOR_SUCCESS || tmpEventType < 0 ||
tmpEventType >= static_cast<int64_t>(WeatherData::eventtype::Length)) {
2021-06-16 20:31:17 +00:00
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
switch (static_cast<WeatherData::eventtype>(tmpEventType)) {
2021-06-09 21:44:49 +00:00
case WeatherData::eventtype::AirQuality: {
2021-06-16 20:31:17 +00:00
std::unique_ptr<WeatherData::AirQuality> airquality = std::make_unique<WeatherData::AirQuality>();
airquality->timestamp = tmpTimestamp;
airquality->eventType = static_cast<WeatherData::eventtype>(tmpEventType);
airquality->expires = tmpExpires;
2021-12-01 19:11:31 +00:00
UsefulBufC stringBuf; // TODO: Everything ok with lifecycle here?
QCBORDecode_GetTextStringInMapSZ(&decodeContext, "Polluter", &stringBuf);
if (UsefulBuf_IsNULLOrEmptyC(stringBuf) != 0) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
2021-12-01 19:11:31 +00:00
airquality->polluter = std::string(static_cast<const char*>(stringBuf.ptr), stringBuf.len);
int64_t tmpAmount = 0;
QCBORDecode_GetInt64InMapSZ(&decodeContext, "Amount", &tmpAmount);
if (tmpAmount < 0 || tmpAmount > 4294967295) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
airquality->amount = tmpAmount; // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions)
if (AddEventToTimeline(std::move(airquality))) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
2021-06-09 21:44:49 +00:00
break;
}
case WeatherData::eventtype::Obscuration: {
2021-06-16 20:31:17 +00:00
std::unique_ptr<WeatherData::Obscuration> obscuration = std::make_unique<WeatherData::Obscuration>();
obscuration->timestamp = tmpTimestamp;
obscuration->eventType = static_cast<WeatherData::eventtype>(tmpEventType);
obscuration->expires = tmpExpires;
int64_t tmpType = 0;
QCBORDecode_GetInt64InMapSZ(&decodeContext, "Type", &tmpType);
if (tmpType < 0 || tmpType >= static_cast<int64_t>(WeatherData::obscurationtype::Length)) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
obscuration->type = static_cast<WeatherData::obscurationtype>(tmpType);
int64_t tmpAmount = 0;
QCBORDecode_GetInt64InMapSZ(&decodeContext, "Amount", &tmpAmount);
if (tmpAmount < 0 || tmpAmount > 65535) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
obscuration->amount = tmpAmount; // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions)
if (AddEventToTimeline(std::move(obscuration))) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
2021-06-09 21:44:49 +00:00
break;
}
case WeatherData::eventtype::Precipitation: {
2021-06-16 20:31:17 +00:00
std::unique_ptr<WeatherData::Precipitation> precipitation = std::make_unique<WeatherData::Precipitation>();
precipitation->timestamp = tmpTimestamp;
precipitation->eventType = static_cast<WeatherData::eventtype>(tmpEventType);
precipitation->expires = tmpExpires;
int64_t tmpType = 0;
QCBORDecode_GetInt64InMapSZ(&decodeContext, "Type", &tmpType);
if (tmpType < 0 || tmpType >= static_cast<int64_t>(WeatherData::precipitationtype::Length)) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
precipitation->type = static_cast<WeatherData::precipitationtype>(tmpType);
int64_t tmpAmount = 0;
QCBORDecode_GetInt64InMapSZ(&decodeContext, "Amount", &tmpAmount);
if (tmpAmount < 0 || tmpAmount > 255) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
precipitation->amount = tmpAmount; // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions)
if (AddEventToTimeline(std::move(precipitation))) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
2021-06-09 21:44:49 +00:00
break;
}
case WeatherData::eventtype::Wind: {
2021-06-16 20:31:17 +00:00
std::unique_ptr<WeatherData::Wind> wind = std::make_unique<WeatherData::Wind>();
wind->timestamp = tmpTimestamp;
wind->eventType = static_cast<WeatherData::eventtype>(tmpEventType);
wind->expires = tmpExpires;
int64_t tmpMin = 0;
QCBORDecode_GetInt64InMapSZ(&decodeContext, "SpeedMin", &tmpMin);
if (tmpMin < 0 || tmpMin > 255) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
wind->speedMin = tmpMin; // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions)
int64_t tmpMax = 0;
QCBORDecode_GetInt64InMapSZ(&decodeContext, "SpeedMin", &tmpMax);
if (tmpMax < 0 || tmpMax > 255) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
wind->speedMax = tmpMax; // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions)
int64_t tmpDMin = 0;
QCBORDecode_GetInt64InMapSZ(&decodeContext, "DirectionMin", &tmpDMin);
if (tmpDMin < 0 || tmpDMin > 255) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
wind->directionMin = tmpDMin; // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions)
int64_t tmpDMax = 0;
QCBORDecode_GetInt64InMapSZ(&decodeContext, "DirectionMax", &tmpDMax);
if (tmpDMax < 0 || tmpDMax > 255) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
wind->directionMax = tmpDMax; // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions)
if (AddEventToTimeline(std::move(wind))) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
2021-06-09 21:44:49 +00:00
break;
}
case WeatherData::eventtype::Temperature: {
2021-06-16 20:31:17 +00:00
std::unique_ptr<WeatherData::Temperature> temperature = std::make_unique<WeatherData::Temperature>();
temperature->timestamp = tmpTimestamp;
temperature->eventType = static_cast<WeatherData::eventtype>(tmpEventType);
temperature->expires = tmpExpires;
int64_t tmpTemperature = 0;
QCBORDecode_GetInt64InMapSZ(&decodeContext, "Temperature", &tmpTemperature);
if (tmpTemperature < 0 || tmpTemperature > 65535) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
temperature->temperature = tmpTemperature; // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions)
int64_t tmpDewPoint = 0;
QCBORDecode_GetInt64InMapSZ(&decodeContext, "DewPoint", &tmpDewPoint);
if (tmpDewPoint < 0 || tmpDewPoint > 65535) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
temperature->dewPoint = tmpDewPoint; // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions)
if (AddEventToTimeline(std::move(temperature))) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
2021-06-09 21:44:49 +00:00
break;
}
case WeatherData::eventtype::Special: {
2021-06-16 20:31:17 +00:00
std::unique_ptr<WeatherData::Special> special = std::make_unique<WeatherData::Special>();
special->timestamp = tmpTimestamp;
special->eventType = static_cast<WeatherData::eventtype>(tmpEventType);
special->expires = tmpExpires;
int64_t tmpType = 0;
QCBORDecode_GetInt64InMapSZ(&decodeContext, "DewPoint", &tmpType);
if (tmpType < 0 || tmpType >= static_cast<int64_t>(WeatherData::specialtype::Length)) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
special->type = static_cast<WeatherData::specialtype>(tmpType);
if (AddEventToTimeline(std::move(special))) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
2021-06-09 21:44:49 +00:00
break;
}
case WeatherData::eventtype::Pressure: {
2021-06-16 20:31:17 +00:00
std::unique_ptr<WeatherData::Pressure> pressure = std::make_unique<WeatherData::Pressure>();
pressure->timestamp = tmpTimestamp;
pressure->eventType = static_cast<WeatherData::eventtype>(tmpEventType);
pressure->expires = tmpExpires;
int64_t tmpDewPoint = 0;
QCBORDecode_GetInt64InMapSZ(&decodeContext, "DewPoint", &tmpDewPoint);
if (tmpDewPoint < 0 || tmpDewPoint >= 65535) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
pressure->pressure = tmpDewPoint; // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions)
if (AddEventToTimeline(std::move(pressure))) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
2021-06-09 21:44:49 +00:00
break;
}
case WeatherData::eventtype::Location: {
2021-06-16 20:31:17 +00:00
std::unique_ptr<WeatherData::Location> location = std::make_unique<WeatherData::Location>();
location->timestamp = tmpTimestamp;
location->eventType = static_cast<WeatherData::eventtype>(tmpEventType);
location->expires = tmpExpires;
UsefulBufC stringBuf; // TODO: Everything ok with lifecycle here?
QCBORDecode_GetTextStringInMapSZ(&decodeContext, "Location", &stringBuf);
if (UsefulBuf_IsNULLOrEmptyC(stringBuf) != 0) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
location->location = std::string(static_cast<const char*>(stringBuf.ptr), stringBuf.len);
int64_t tmpAltitude = 0;
QCBORDecode_GetInt64InMapSZ(&decodeContext, "Altitude", &tmpAltitude);
if (tmpAltitude < -32768 || tmpAltitude >= 32767) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
location->altitude = static_cast<int16_t>(tmpAltitude);
int64_t tmpLatitude = 0;
QCBORDecode_GetInt64InMapSZ(&decodeContext, "Latitude", &tmpLatitude);
if (tmpLatitude < -2147483648 || tmpLatitude >= 2147483647) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
location->latitude = static_cast<int32_t>(tmpLatitude);
int64_t tmpLongitude = 0;
QCBORDecode_GetInt64InMapSZ(&decodeContext, "Longitude", &tmpLongitude);
if (tmpLongitude < -2147483648 || tmpLongitude >= 2147483647) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
location->latitude = static_cast<int32_t>(tmpLongitude);
if (AddEventToTimeline(std::move(location))) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
2021-06-09 21:44:49 +00:00
break;
}
case WeatherData::eventtype::Clouds: {
2021-06-16 20:31:17 +00:00
std::unique_ptr<WeatherData::Clouds> clouds = std::make_unique<WeatherData::Clouds>();
clouds->timestamp = tmpTimestamp;
clouds->eventType = static_cast<WeatherData::eventtype>(tmpEventType);
clouds->expires = tmpExpires;
int64_t tmpAmount = 0;
QCBORDecode_GetInt64InMapSZ(&decodeContext, "Amount", &tmpAmount);
if (tmpAmount < 0 || tmpAmount > 255) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
clouds->amount = static_cast<uint8_t>(tmpAmount);
if (AddEventToTimeline(std::move(clouds))) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
2021-06-09 21:44:49 +00:00
break;
}
2021-08-21 18:58:03 +00:00
case WeatherData::eventtype::Humidity: {
std::unique_ptr<WeatherData::Humidity> humidity = std::make_unique<WeatherData::Humidity>();
humidity->timestamp = tmpTimestamp;
humidity->eventType = static_cast<WeatherData::eventtype>(tmpEventType);
humidity->expires = tmpExpires;
int64_t tmpType = 0;
2021-12-01 16:41:01 +00:00
QCBORDecode_GetInt64InMapSZ(&decodeContext, "Humidity", &tmpType);
if (tmpType < 0 || tmpType >= 255) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
humidity->humidity = static_cast<uint8_t>(tmpType);
if (AddEventToTimeline(std::move(humidity))) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
2021-08-21 18:58:03 +00:00
break;
}
2021-06-09 21:44:49 +00:00
default: {
break;
}
}
2021-06-16 20:31:17 +00:00
2021-06-09 21:44:49 +00:00
QCBORDecode_ExitMap(&decodeContext);
GetTimelineLength();
TidyTimeline();
2021-06-09 21:44:49 +00:00
if (QCBORDecode_Finish(&decodeContext) != QCBOR_SUCCESS) {
2021-06-09 21:44:49 +00:00
return BLE_ATT_ERR_INSUFFICIENT_RES;
}
} else if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) {
// Encode
uint8_t buffer[64];
QCBOREncodeContext encodeContext;
/* TODO: This is very much still a test endpoint
* it needs a characteristic UUID check
* and actual implementations that show
* what actually has to be read.
* WARN: Consider commands not part of the API for now!
*/
2021-06-09 21:44:49 +00:00
QCBOREncode_Init(&encodeContext, UsefulBuf_FROM_BYTE_ARRAY(buffer));
QCBOREncode_OpenMap(&encodeContext);
QCBOREncode_AddTextToMap(&encodeContext, "test", UsefulBuf_FROM_SZ_LITERAL("test"));
QCBOREncode_AddInt64ToMap(&encodeContext, "test", 1ul);
QCBOREncode_CloseMap(&encodeContext);
UsefulBufC encodedEvent;
auto uErr = QCBOREncode_Finish(&encodeContext, &encodedEvent);
if (uErr != 0) {
return BLE_ATT_ERR_INSUFFICIENT_RES;
}
auto res = os_mbuf_append(ctxt->om, &buffer, sizeof(buffer));
if (res == 0) {
return BLE_ATT_ERR_INSUFFICIENT_RES;
}
return 0;
}
return 0;
}
std::unique_ptr<WeatherData::Clouds>& WeatherService::GetCurrentClouds() {
2021-08-21 18:58:03 +00:00
uint64_t currentTimestamp = GetCurrentUnixTimestamp();
for (auto&& header : this->timeline) {
if (header->eventType == WeatherData::eventtype::Clouds && isEventStillValid(header, currentTimestamp)) {
return reinterpret_cast<std::unique_ptr<WeatherData::Clouds>&>(header);
2021-08-21 18:58:03 +00:00
}
}
2021-11-30 23:15:11 +00:00
return reinterpret_cast<std::unique_ptr<WeatherData::Clouds>&>(*this->nullHeader);
2021-06-09 21:44:49 +00:00
}
2021-06-24 22:18:56 +00:00
std::unique_ptr<WeatherData::Obscuration>& WeatherService::GetCurrentObscuration() {
2021-08-21 18:58:03 +00:00
uint64_t currentTimestamp = GetCurrentUnixTimestamp();
for (auto&& header : this->timeline) {
if (header->eventType == WeatherData::eventtype::Obscuration && isEventStillValid(header, currentTimestamp)) {
return reinterpret_cast<std::unique_ptr<WeatherData::Obscuration>&>(header);
2021-08-21 18:58:03 +00:00
}
}
2021-11-30 23:15:11 +00:00
return reinterpret_cast<std::unique_ptr<WeatherData::Obscuration>&>(*this->nullHeader);
2021-06-09 21:44:49 +00:00
}
2021-06-24 22:18:56 +00:00
std::unique_ptr<WeatherData::Precipitation>& WeatherService::GetCurrentPrecipitation() {
2021-08-21 18:58:03 +00:00
uint64_t currentTimestamp = GetCurrentUnixTimestamp();
for (auto&& header : this->timeline) {
if (header->eventType == WeatherData::eventtype::Precipitation && isEventStillValid(header, currentTimestamp)) {
return reinterpret_cast<std::unique_ptr<WeatherData::Precipitation>&>(header);
2021-08-21 18:58:03 +00:00
}
}
2021-11-30 23:15:11 +00:00
return reinterpret_cast<std::unique_ptr<WeatherData::Precipitation>&>(*this->nullHeader);
2021-06-09 21:44:49 +00:00
}
2021-06-24 22:18:56 +00:00
std::unique_ptr<WeatherData::Wind>& WeatherService::GetCurrentWind() {
2021-08-21 18:58:03 +00:00
uint64_t currentTimestamp = GetCurrentUnixTimestamp();
for (auto&& header : this->timeline) {
if (header->eventType == WeatherData::eventtype::Wind && isEventStillValid(header, currentTimestamp)) {
return reinterpret_cast<std::unique_ptr<WeatherData::Wind>&>(header);
2021-08-21 18:58:03 +00:00
}
}
2021-11-30 23:15:11 +00:00
return reinterpret_cast<std::unique_ptr<WeatherData::Wind>&>(*this->nullHeader);
2021-06-09 21:44:49 +00:00
}
2021-06-24 22:18:56 +00:00
std::unique_ptr<WeatherData::Temperature>& WeatherService::GetCurrentTemperature() {
2021-08-21 18:58:03 +00:00
uint64_t currentTimestamp = GetCurrentUnixTimestamp();
for (auto&& header : this->timeline) {
if (header->eventType == WeatherData::eventtype::Temperature && isEventStillValid(header, currentTimestamp)) {
return reinterpret_cast<std::unique_ptr<WeatherData::Temperature>&>(header);
2021-08-21 18:58:03 +00:00
}
}
2021-11-30 23:15:11 +00:00
return reinterpret_cast<std::unique_ptr<WeatherData::Temperature>&>(*this->nullHeader);
2021-06-09 21:44:49 +00:00
}
2021-06-24 22:18:56 +00:00
std::unique_ptr<WeatherData::Humidity>& WeatherService::GetCurrentHumidity() {
2021-08-21 18:58:03 +00:00
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);
2021-08-21 18:58:03 +00:00
}
}
2021-11-30 23:15:11 +00:00
return reinterpret_cast<std::unique_ptr<WeatherData::Humidity>&>(*this->nullHeader);
2021-06-09 21:44:49 +00:00
}
2021-06-24 22:18:56 +00:00
std::unique_ptr<WeatherData::Pressure>& WeatherService::GetCurrentPressure() {
2021-06-24 22:18:56 +00:00
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);
2021-08-21 18:58:03 +00:00
}
}
2021-11-30 23:15:11 +00:00
return reinterpret_cast<std::unique_ptr<WeatherData::Pressure>&>(*this->nullHeader);
2021-08-21 18:58:03 +00:00
}
std::unique_ptr<WeatherData::Location>& WeatherService::GetCurrentLocation() {
2021-08-21 18:58:03 +00:00
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);
2021-06-09 21:44:49 +00:00
}
}
2021-11-30 23:15:11 +00:00
return reinterpret_cast<std::unique_ptr<WeatherData::Location>&>(*this->nullHeader);
2021-06-09 21:44:49 +00:00
}
std::unique_ptr<WeatherData::AirQuality>& WeatherService::GetCurrentQuality() {
2021-08-21 18:58:03 +00:00
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);
2021-08-21 18:58:03 +00:00
}
}
2021-11-30 23:15:11 +00:00
return reinterpret_cast<std::unique_ptr<WeatherData::AirQuality>&>(*this->nullHeader);
2021-06-09 21:44:49 +00:00
}
2021-06-24 22:18:56 +00:00
size_t WeatherService::GetTimelineLength() const {
2021-06-09 21:44:49 +00:00
return timeline.size();
}
2021-06-24 22:18:56 +00:00
bool WeatherService::AddEventToTimeline(std::unique_ptr<WeatherData::TimelineHeader> event) {
2021-06-09 21:44:49 +00:00
if (timeline.size() == timeline.max_size()) {
return false;
}
timeline.push_back(std::move(event));
return true;
}
2021-06-24 22:18:56 +00:00
bool WeatherService::HasTimelineEventOfType(const WeatherData::eventtype type) const {
uint64_t currentTimestamp = GetCurrentUnixTimestamp();
2021-06-09 21:44:49 +00:00
for (auto&& header : timeline) {
if (header->eventType == type && isEventStillValid(header, currentTimestamp)) {
2021-06-09 21:44:49 +00:00
return true;
}
}
return false;
}
2021-06-24 22:18:56 +00:00
void WeatherService::TidyTimeline() {
uint64_t timeCurrent = GetCurrentUnixTimestamp();
2021-06-09 21:44:49 +00:00
timeline.erase(std::remove_if(std::begin(timeline),
std::end(timeline),
2021-06-16 20:31:17 +00:00
[&](std::unique_ptr<WeatherData::TimelineHeader> const& header) {
2021-11-30 23:15:11 +00:00
return !isEventStillValid(header, timeCurrent);
2021-06-09 21:44:49 +00:00
}),
std::end(timeline));
2021-06-24 22:18:56 +00:00
std::sort(std::begin(timeline), std::end(timeline), CompareTimelineEvents);
2021-06-09 21:44:49 +00:00
}
2021-06-24 22:18:56 +00:00
bool WeatherService::CompareTimelineEvents(const std::unique_ptr<WeatherData::TimelineHeader>& first,
2021-06-16 20:31:17 +00:00
const std::unique_ptr<WeatherData::TimelineHeader>& second) {
2021-06-09 21:44:49 +00:00
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;
}
2021-06-24 22:18:56 +00:00
uint64_t WeatherService::GetCurrentUnixTimestamp() const {
2021-06-09 21:44:49 +00:00
return std::chrono::duration_cast<std::chrono::seconds>(dateTimeController.CurrentDateTime().time_since_epoch()).count();
}
}
2021-06-24 23:52:59 +00:00
}