Integration of Simple Weather Service (#135)
* Integration of Simple Weather Service Replace the old WeatherService by the new Simple Weather Service.= * Update InfiniTime to after SimpleWeatherService got merged --------- Co-authored-by: Reinhold Gschweicher <pyro4hell@gmail.com>
This commit is contained in:
		
							parent
							
								
									39b9b17625
								
							
						
					
					
						commit
						d6cc458ea2
					
				@ -124,8 +124,8 @@ target_sources(infinisim PUBLIC
 | 
			
		||||
  sim/components/ble/NavigationService.cpp
 | 
			
		||||
  sim/components/ble/NimbleController.h
 | 
			
		||||
  sim/components/ble/NimbleController.cpp
 | 
			
		||||
  sim/components/ble/weather/WeatherService.h
 | 
			
		||||
  sim/components/ble/weather/WeatherService.cpp
 | 
			
		||||
  sim/components/ble/SimpleWeatherService.h
 | 
			
		||||
  sim/components/ble/SimpleWeatherService.cpp
 | 
			
		||||
  sim/components/brightness/BrightnessController.h
 | 
			
		||||
  sim/components/brightness/BrightnessController.cpp
 | 
			
		||||
  sim/components/firmwarevalidator/FirmwareValidator.h
 | 
			
		||||
 | 
			
		||||
@ -1 +1 @@
 | 
			
		||||
Subproject commit e6b96c286376454b0aeab3c1444f4d106d755b94
 | 
			
		||||
Subproject commit ca7d8a668d37d3377aeb38d122a9eccafdd6822d
 | 
			
		||||
@ -11,10 +11,10 @@ using namespace Pinetime::Controllers;
 | 
			
		||||
//constexpr ble_uuid16_t AlertNotificationService::ansCharUuid;
 | 
			
		||||
//constexpr ble_uuid128_t AlertNotificationService::notificationEventUuid;
 | 
			
		||||
 | 
			
		||||
int AlertNotificationCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg) {
 | 
			
		||||
  auto anService = static_cast<AlertNotificationService*>(arg);
 | 
			
		||||
  return anService->OnAlert(conn_handle, attr_handle, ctxt);
 | 
			
		||||
}
 | 
			
		||||
//int AlertNotificationCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg) {
 | 
			
		||||
//auto anService = static_cast<AlertNotificationService*>(arg);
 | 
			
		||||
//  return anService->OnAlert(conn_handle, attr_handle, ctxt);
 | 
			
		||||
//}
 | 
			
		||||
 | 
			
		||||
void AlertNotificationService::Init() {
 | 
			
		||||
//  int res;
 | 
			
		||||
 | 
			
		||||
@ -44,7 +44,7 @@ NimbleController::NimbleController(Pinetime::System::SystemTask& systemTask,
 | 
			
		||||
//    alertNotificationClient {systemTask, notificationManager},
 | 
			
		||||
//    currentTimeService {dateTimeController},
 | 
			
		||||
    musicService {systemTask},
 | 
			
		||||
    weatherService {systemTask, dateTimeController},
 | 
			
		||||
    weatherService {dateTimeController},
 | 
			
		||||
    navService {systemTask} {
 | 
			
		||||
//    batteryInformationService {batteryController},
 | 
			
		||||
//    immediateAlertService {systemTask, notificationManager},
 | 
			
		||||
 | 
			
		||||
@ -20,7 +20,7 @@
 | 
			
		||||
#include "components/ble/NavigationService.h"
 | 
			
		||||
//#include "components/ble/ServiceDiscovery.h"
 | 
			
		||||
//#include "components/ble/MotionService.h"
 | 
			
		||||
#include "components/ble/weather/WeatherService.h"
 | 
			
		||||
#include "components/ble/SimpleWeatherService.h"
 | 
			
		||||
#include "components/fs/FS.h"
 | 
			
		||||
//#include "components/ble/FSService.h"
 | 
			
		||||
 | 
			
		||||
@ -78,7 +78,7 @@ namespace Pinetime {
 | 
			
		||||
      Pinetime::Controllers::AlertNotificationService& alertService() {
 | 
			
		||||
        return anService;
 | 
			
		||||
      };
 | 
			
		||||
      Pinetime::Controllers::WeatherService& weather() {
 | 
			
		||||
      Pinetime::Controllers::SimpleWeatherService& weather() {
 | 
			
		||||
        return weatherService;
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
@ -111,7 +111,7 @@ namespace Pinetime {
 | 
			
		||||
//      AlertNotificationClient alertNotificationClient;
 | 
			
		||||
//      CurrentTimeService currentTimeService;
 | 
			
		||||
      MusicService musicService;
 | 
			
		||||
      WeatherService weatherService;
 | 
			
		||||
      SimpleWeatherService weatherService;
 | 
			
		||||
      NavigationService navService;
 | 
			
		||||
//      BatteryInformationService batteryInformationService;
 | 
			
		||||
//      ImmediateAlertService immediateAlertService;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										110
									
								
								sim/components/ble/SimpleWeatherService.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								sim/components/ble/SimpleWeatherService.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,110 @@
 | 
			
		||||
#include "components/ble/SimpleWeatherService.h"
 | 
			
		||||
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <array>
 | 
			
		||||
#include <cstring>
 | 
			
		||||
#include <nrf_log.h>
 | 
			
		||||
 | 
			
		||||
using namespace Pinetime::Controllers;
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
enum class MessageType : uint8_t { CurrentWeather, Forecast, Unknown };
 | 
			
		||||
 | 
			
		||||
uint64_t ToUInt64(const uint8_t* data) {
 | 
			
		||||
  return data[0] + (data[1] << 8) + (data[2] << 16) + (data[3] << 24) + (static_cast<uint64_t>(data[4]) << 32) +
 | 
			
		||||
         (static_cast<uint64_t>(data[5]) << 40) + (static_cast<uint64_t>(data[6]) << 48) + (static_cast<uint64_t>(data[7]) << 56);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int16_t ToInt16(const uint8_t* data) {
 | 
			
		||||
  return data[0] + (data[1] << 8);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SimpleWeatherService::CurrentWeather CreateCurrentWeather(const uint8_t* dataBuffer) {
 | 
			
		||||
  SimpleWeatherService::Location cityName;
 | 
			
		||||
  std::memcpy(cityName.data(), &dataBuffer[16], 32);
 | 
			
		||||
  cityName[32] = '\0';
 | 
			
		||||
  return SimpleWeatherService::CurrentWeather(ToUInt64(&dataBuffer[2]),
 | 
			
		||||
                                              ToInt16(&dataBuffer[10]),
 | 
			
		||||
                                              ToInt16(&dataBuffer[12]),
 | 
			
		||||
                                              ToInt16(&dataBuffer[14]),
 | 
			
		||||
                                              SimpleWeatherService::Icons {dataBuffer[16 + 32]},
 | 
			
		||||
                                              std::move(cityName));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SimpleWeatherService::Forecast CreateForecast(const uint8_t* dataBuffer) {
 | 
			
		||||
  auto timestamp = static_cast<uint64_t>(ToUInt64(&dataBuffer[2]));
 | 
			
		||||
 | 
			
		||||
  std::array<SimpleWeatherService::Forecast::Day, SimpleWeatherService::MaxNbForecastDays> days;
 | 
			
		||||
  const uint8_t nbDaysInBuffer = dataBuffer[10];
 | 
			
		||||
  const uint8_t nbDays = std::min(SimpleWeatherService::MaxNbForecastDays, nbDaysInBuffer);
 | 
			
		||||
  for (int i = 0; i < nbDays; i++) {
 | 
			
		||||
    days[i] = SimpleWeatherService::Forecast::Day {ToInt16(&dataBuffer[11 + (i * 5)]),
 | 
			
		||||
                                                  ToInt16(&dataBuffer[13 + (i * 5)]),
 | 
			
		||||
                                                  SimpleWeatherService::Icons {dataBuffer[15 + (i * 5)]}};
 | 
			
		||||
  }
 | 
			
		||||
  return SimpleWeatherService::Forecast {timestamp, nbDays, days};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MessageType GetMessageType(const uint8_t* data) {
 | 
			
		||||
  auto messageType = static_cast<MessageType>(*data);
 | 
			
		||||
  if (messageType > MessageType::Unknown) {
 | 
			
		||||
    return MessageType::Unknown;
 | 
			
		||||
  }
 | 
			
		||||
  return messageType;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t GetVersion(const uint8_t* dataBuffer) {
 | 
			
		||||
  return dataBuffer[1];
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int WeatherCallback(uint16_t /*connHandle*/, uint16_t /*attrHandle*/, struct ble_gatt_access_ctxt* ctxt, void* arg) {
 | 
			
		||||
  return static_cast<Pinetime::Controllers::SimpleWeatherService*>(arg)->OnCommand(ctxt);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SimpleWeatherService::SimpleWeatherService(const DateTime& dateTimeController) : dateTimeController(dateTimeController) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SimpleWeatherService::Init() {
 | 
			
		||||
  //ble_gatts_count_cfg(serviceDefinition);
 | 
			
		||||
  //ble_gatts_add_svcs(serviceDefinition);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int SimpleWeatherService::OnCommand(struct ble_gatt_access_ctxt* ctxt) {
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::optional<SimpleWeatherService::CurrentWeather> SimpleWeatherService::Current() const {
 | 
			
		||||
  if (currentWeather) {
 | 
			
		||||
    auto currentTime = dateTimeController.UTCDateTime().time_since_epoch();
 | 
			
		||||
    auto weatherTpSecond = std::chrono::seconds {currentWeather->timestamp};
 | 
			
		||||
    auto weatherTp = std::chrono::duration_cast<std::chrono::seconds>(weatherTpSecond);
 | 
			
		||||
    auto delta = currentTime - weatherTp;
 | 
			
		||||
 | 
			
		||||
    if (delta < std::chrono::hours {24}) {
 | 
			
		||||
      return currentWeather;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return {};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::optional<SimpleWeatherService::Forecast> SimpleWeatherService::GetForecast() const {
 | 
			
		||||
  if (forecast) {
 | 
			
		||||
    auto currentTime = dateTimeController.UTCDateTime().time_since_epoch();
 | 
			
		||||
    auto weatherTpSecond = std::chrono::seconds {forecast->timestamp};
 | 
			
		||||
    auto weatherTp = std::chrono::duration_cast<std::chrono::seconds>(weatherTpSecond);
 | 
			
		||||
    auto delta = currentTime - weatherTp;
 | 
			
		||||
 | 
			
		||||
    if (delta < std::chrono::hours {24}) {
 | 
			
		||||
      return this->forecast;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return {};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool SimpleWeatherService::CurrentWeather::operator==(const SimpleWeatherService::CurrentWeather& other) const {
 | 
			
		||||
  return this->iconId == other.iconId && this->temperature == other.temperature && this->timestamp == other.timestamp &&
 | 
			
		||||
         this->maxTemperature == other.maxTemperature && this->minTemperature == other.maxTemperature &&
 | 
			
		||||
         std::strcmp(this->location.data(), other.location.data()) == 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										125
									
								
								sim/components/ble/SimpleWeatherService.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								sim/components/ble/SimpleWeatherService.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,125 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <cstdint>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <memory>
 | 
			
		||||
 | 
			
		||||
//#define min // workaround: nimble's min/max macros conflict with libstdc++
 | 
			
		||||
//#define max
 | 
			
		||||
//#include <host/ble_gap.h>
 | 
			
		||||
//#include <host/ble_uuid.h>
 | 
			
		||||
#include <optional>
 | 
			
		||||
#include <cstring>
 | 
			
		||||
#include <array>
 | 
			
		||||
//#undef max
 | 
			
		||||
//#undef min
 | 
			
		||||
 | 
			
		||||
#include "components/datetime/DateTimeController.h"
 | 
			
		||||
 | 
			
		||||
int WeatherCallback(uint16_t connHandle, uint16_t attrHandle, struct ble_gatt_access_ctxt* ctxt, void* arg);
 | 
			
		||||
 | 
			
		||||
namespace Pinetime {
 | 
			
		||||
namespace Controllers {
 | 
			
		||||
 | 
			
		||||
class SimpleWeatherService {
 | 
			
		||||
public:
 | 
			
		||||
  explicit SimpleWeatherService(const DateTime& dateTimeController);
 | 
			
		||||
 | 
			
		||||
  void Init();
 | 
			
		||||
 | 
			
		||||
  int OnCommand(struct ble_gatt_access_ctxt* ctxt);
 | 
			
		||||
 | 
			
		||||
  static constexpr uint8_t MaxNbForecastDays = 5;
 | 
			
		||||
 | 
			
		||||
  enum class Icons : uint8_t {
 | 
			
		||||
    Sun = 0,       // ClearSky
 | 
			
		||||
    CloudsSun = 1, // FewClouds
 | 
			
		||||
    Clouds = 2,    // Scattered clouds
 | 
			
		||||
    BrokenClouds = 3,
 | 
			
		||||
    CloudShowerHeavy = 4, // shower rain
 | 
			
		||||
    CloudSunRain = 5,     // rain
 | 
			
		||||
    Thunderstorm = 6,
 | 
			
		||||
    Snow = 7,
 | 
			
		||||
    Smog = 8, // Mist
 | 
			
		||||
    Unknown = 255
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  using Location = std::array<char, 33>; // 32 char + \0 (end of string)
 | 
			
		||||
 | 
			
		||||
  struct CurrentWeather {
 | 
			
		||||
    CurrentWeather(uint64_t timestamp,
 | 
			
		||||
                   int16_t temperature,
 | 
			
		||||
                   int16_t minTemperature,
 | 
			
		||||
                   int16_t maxTemperature,
 | 
			
		||||
                   Icons iconId,
 | 
			
		||||
                   Location&& location)
 | 
			
		||||
        : timestamp {timestamp},
 | 
			
		||||
          temperature {temperature},
 | 
			
		||||
          minTemperature {minTemperature},
 | 
			
		||||
          maxTemperature {maxTemperature},
 | 
			
		||||
          iconId {iconId},
 | 
			
		||||
          location {std::move(location)} {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uint64_t timestamp;
 | 
			
		||||
    int16_t temperature;
 | 
			
		||||
    int16_t minTemperature;
 | 
			
		||||
    int16_t maxTemperature;
 | 
			
		||||
    Icons iconId;
 | 
			
		||||
    Location location;
 | 
			
		||||
 | 
			
		||||
    bool operator==(const CurrentWeather& other) const;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  struct Forecast {
 | 
			
		||||
    uint64_t timestamp;
 | 
			
		||||
    uint8_t nbDays;
 | 
			
		||||
 | 
			
		||||
    struct Day {
 | 
			
		||||
      int16_t minTemperature;
 | 
			
		||||
      int16_t maxTemperature;
 | 
			
		||||
      Icons iconId;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    std::array<Day, MaxNbForecastDays> days;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  std::optional<CurrentWeather> Current() const;
 | 
			
		||||
  std::optional<Forecast> GetForecast() const;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  // 00050000-78fc-48fe-8e23-433b3a1942d0
 | 
			
		||||
  //static constexpr ble_uuid128_t BaseUuid() {
 | 
			
		||||
  //  return CharUuid(0x00, 0x00);
 | 
			
		||||
  //}
 | 
			
		||||
 | 
			
		||||
  // 0005yyxx-78fc-48fe-8e23-433b3a1942d0
 | 
			
		||||
  //static constexpr ble_uuid128_t CharUuid(uint8_t x, uint8_t y) {
 | 
			
		||||
  //  return ble_uuid128_t {.u = {.type = BLE_UUID_TYPE_128},
 | 
			
		||||
  //                       .value = {0xd0, 0x42, 0x19, 0x3a, 0x3b, 0x43, 0x23, 0x8e, 0xfe, 0x48, 0xfc, 0x78, y, x, 0x05, 0x00}};
 | 
			
		||||
  //}
 | 
			
		||||
 | 
			
		||||
  //ble_uuid128_t weatherUuid {BaseUuid()};
 | 
			
		||||
 | 
			
		||||
  //ble_uuid128_t weatherDataCharUuid {CharUuid(0x00, 0x01)};
 | 
			
		||||
 | 
			
		||||
  //const struct ble_gatt_chr_def characteristicDefinition[2] = {{.uuid = &weatherDataCharUuid.u,
 | 
			
		||||
  //                                                              .access_cb = WeatherCallback,
 | 
			
		||||
  //                                                              .arg = this,
 | 
			
		||||
  //                                                              .flags = BLE_GATT_CHR_F_WRITE,
 | 
			
		||||
  //                                                              .val_handle = &eventHandle},
 | 
			
		||||
  //                                                             {0}};
 | 
			
		||||
  //const struct ble_gatt_svc_def serviceDefinition[2] = {
 | 
			
		||||
  //   {.type = BLE_GATT_SVC_TYPE_PRIMARY, .uuid = &weatherUuid.u, .characteristics = characteristicDefinition},
 | 
			
		||||
  //    {0}};
 | 
			
		||||
 | 
			
		||||
  uint16_t eventHandle {};
 | 
			
		||||
 | 
			
		||||
  const Pinetime::Controllers::DateTime& dateTimeController;
 | 
			
		||||
 | 
			
		||||
  std::optional<CurrentWeather> currentWeather;
 | 
			
		||||
  std::optional<Forecast> forecast;
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
@ -1,603 +0,0 @@
 | 
			
		||||
/*  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 "components/ble/weather/WeatherService.h"
 | 
			
		||||
//#include "libs/QCBOR/inc/qcbor/qcbor.h"
 | 
			
		||||
#include "systemtask/SystemTask.h"
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
 | 
			
		||||
using namespace Pinetime::Controllers;
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    WeatherService::WeatherService(System::SystemTask& system, DateTime& dateTimeController)
 | 
			
		||||
      : system(system), dateTimeController(dateTimeController) {
 | 
			
		||||
      nullHeader = &nullTimelineheader;
 | 
			
		||||
      nullTimelineheader->timestamp = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void WeatherService::Init() {
 | 
			
		||||
//      uint8_t res = 0;
 | 
			
		||||
//      res = ble_gatts_count_cfg(serviceDefinition);
 | 
			
		||||
//      ASSERT(res == 0);
 | 
			
		||||
//
 | 
			
		||||
//      res = ble_gatts_add_svcs(serviceDefinition);
 | 
			
		||||
//      ASSERT(res == 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int WeatherService::OnCommand(uint16_t connHandle, uint16_t attrHandle, struct ble_gatt_access_ctxt* ctxt) {
 | 
			
		||||
 //     if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
 | 
			
		||||
 //       const uint8_t packetLen = OS_MBUF_PKTLEN(ctxt->om); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
 | 
			
		||||
 //       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)
 | 
			
		||||
 | 
			
		||||
 //       QCBORDecode_Init(&decodeContext, encodedCbor, QCBOR_DECODE_MODE_NORMAL);
 | 
			
		||||
 //       // KINDLY provide us a fixed-length map
 | 
			
		||||
 //       QCBORDecode_EnterMap(&decodeContext, nullptr);
 | 
			
		||||
 //       // 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) {
 | 
			
		||||
 //         CleanUpQcbor(&decodeContext);
 | 
			
		||||
 //         return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
 | 
			
		||||
 //       }
 | 
			
		||||
 //       int64_t tmpExpires = 0;
 | 
			
		||||
 //       QCBORDecode_GetInt64InMapSZ(&decodeContext, "Expires", &tmpExpires);
 | 
			
		||||
 //       if (QCBORDecode_GetError(&decodeContext) != QCBOR_SUCCESS || tmpExpires < 0 || tmpExpires > 4294967295) {
 | 
			
		||||
 //         CleanUpQcbor(&decodeContext);
 | 
			
		||||
 //         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)) {
 | 
			
		||||
 //         CleanUpQcbor(&decodeContext);
 | 
			
		||||
 //         return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
 | 
			
		||||
 //       }
 | 
			
		||||
 | 
			
		||||
 //       switch (static_cast<WeatherData::eventtype>(tmpEventType)) {
 | 
			
		||||
 //         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 stringBuf; // TODO: Everything ok with lifecycle here?
 | 
			
		||||
 //           QCBORDecode_GetTextStringInMapSZ(&decodeContext, "Polluter", &stringBuf);
 | 
			
		||||
 //           if (UsefulBuf_IsNULLOrEmptyC(stringBuf) != 0) {
 | 
			
		||||
 //             CleanUpQcbor(&decodeContext);
 | 
			
		||||
 //             return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
 | 
			
		||||
 //           }
 | 
			
		||||
 //           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) {
 | 
			
		||||
 //             CleanUpQcbor(&decodeContext);
 | 
			
		||||
 //             return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
 | 
			
		||||
 //           }
 | 
			
		||||
 //           airquality->amount = tmpAmount; // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions)
 | 
			
		||||
 | 
			
		||||
 //           if (!AddEventToTimeline(std::move(airquality))) {
 | 
			
		||||
 //             CleanUpQcbor(&decodeContext);
 | 
			
		||||
 //             return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
 | 
			
		||||
 //           }
 | 
			
		||||
 //           break;
 | 
			
		||||
 //         }
 | 
			
		||||
 //         case WeatherData::eventtype::Obscuration: {
 | 
			
		||||
 //           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)) {
 | 
			
		||||
 //             CleanUpQcbor(&decodeContext);
 | 
			
		||||
 //             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) {
 | 
			
		||||
 //             CleanUpQcbor(&decodeContext);
 | 
			
		||||
 //             return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
 | 
			
		||||
 //           }
 | 
			
		||||
 //           obscuration->amount = tmpAmount; // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions)
 | 
			
		||||
 | 
			
		||||
 //           if (!AddEventToTimeline(std::move(obscuration))) {
 | 
			
		||||
 //             CleanUpQcbor(&decodeContext);
 | 
			
		||||
 //             return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
 | 
			
		||||
 //           }
 | 
			
		||||
 //           break;
 | 
			
		||||
 //         }
 | 
			
		||||
 //         case WeatherData::eventtype::Precipitation: {
 | 
			
		||||
 //           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)) {
 | 
			
		||||
 //             CleanUpQcbor(&decodeContext);
 | 
			
		||||
 //             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) {
 | 
			
		||||
 //             CleanUpQcbor(&decodeContext);
 | 
			
		||||
 //             return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
 | 
			
		||||
 //           }
 | 
			
		||||
 //           precipitation->amount = tmpAmount; // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions)
 | 
			
		||||
 | 
			
		||||
 //           if (!AddEventToTimeline(std::move(precipitation))) {
 | 
			
		||||
 //             CleanUpQcbor(&decodeContext);
 | 
			
		||||
 //             return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
 | 
			
		||||
 //           }
 | 
			
		||||
 //           break;
 | 
			
		||||
 //         }
 | 
			
		||||
 //         case WeatherData::eventtype::Wind: {
 | 
			
		||||
 //           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) {
 | 
			
		||||
 //             CleanUpQcbor(&decodeContext);
 | 
			
		||||
 //             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) {
 | 
			
		||||
 //             CleanUpQcbor(&decodeContext);
 | 
			
		||||
 //             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) {
 | 
			
		||||
 //             CleanUpQcbor(&decodeContext);
 | 
			
		||||
 //             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) {
 | 
			
		||||
 //             CleanUpQcbor(&decodeContext);
 | 
			
		||||
 //             return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
 | 
			
		||||
 //           }
 | 
			
		||||
 //           wind->directionMax = tmpDMax; // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions)
 | 
			
		||||
 | 
			
		||||
 //           if (!AddEventToTimeline(std::move(wind))) {
 | 
			
		||||
 //             CleanUpQcbor(&decodeContext);
 | 
			
		||||
 //             return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
 | 
			
		||||
 //           }
 | 
			
		||||
 //           break;
 | 
			
		||||
 //         }
 | 
			
		||||
 //         case WeatherData::eventtype::Temperature: {
 | 
			
		||||
 //           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 < -32768 || tmpTemperature > 32767) {
 | 
			
		||||
 //             CleanUpQcbor(&decodeContext);
 | 
			
		||||
 //             return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
 | 
			
		||||
 //           }
 | 
			
		||||
 //           temperature->temperature =
 | 
			
		||||
 //             static_cast<int16_t>(tmpTemperature); // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions)
 | 
			
		||||
 | 
			
		||||
 //           int64_t tmpDewPoint = 0;
 | 
			
		||||
 //           QCBORDecode_GetInt64InMapSZ(&decodeContext, "DewPoint", &tmpDewPoint);
 | 
			
		||||
 //           if (tmpDewPoint < -32768 || tmpDewPoint > 32767) {
 | 
			
		||||
 //             CleanUpQcbor(&decodeContext);
 | 
			
		||||
 //             return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
 | 
			
		||||
 //           }
 | 
			
		||||
 //           temperature->dewPoint =
 | 
			
		||||
 //             static_cast<int16_t>(tmpDewPoint); // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions)
 | 
			
		||||
 | 
			
		||||
 //           if (!AddEventToTimeline(std::move(temperature))) {
 | 
			
		||||
 //             CleanUpQcbor(&decodeContext);
 | 
			
		||||
 //             return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
 | 
			
		||||
 //           }
 | 
			
		||||
 //           break;
 | 
			
		||||
 //         }
 | 
			
		||||
 //         case WeatherData::eventtype::Special: {
 | 
			
		||||
 //           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, "Type", &tmpType);
 | 
			
		||||
 //           if (tmpType < 0 || tmpType >= static_cast<int64_t>(WeatherData::specialtype::Length)) {
 | 
			
		||||
 //             CleanUpQcbor(&decodeContext);
 | 
			
		||||
 //             return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
 | 
			
		||||
 //           }
 | 
			
		||||
 //           special->type = static_cast<WeatherData::specialtype>(tmpType);
 | 
			
		||||
 | 
			
		||||
 //           if (!AddEventToTimeline(std::move(special))) {
 | 
			
		||||
 //             CleanUpQcbor(&decodeContext);
 | 
			
		||||
 //             return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
 | 
			
		||||
 //           }
 | 
			
		||||
 //           break;
 | 
			
		||||
 //         }
 | 
			
		||||
 //         case WeatherData::eventtype::Pressure: {
 | 
			
		||||
 //           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 tmpPressure = 0;
 | 
			
		||||
 //           QCBORDecode_GetInt64InMapSZ(&decodeContext, "Pressure", &tmpPressure);
 | 
			
		||||
 //           if (tmpPressure < 0 || tmpPressure >= 65535) {
 | 
			
		||||
 //             CleanUpQcbor(&decodeContext);
 | 
			
		||||
 //             return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
 | 
			
		||||
 //           }
 | 
			
		||||
 //           pressure->pressure = tmpPressure; // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions)
 | 
			
		||||
 | 
			
		||||
 //           if (!AddEventToTimeline(std::move(pressure))) {
 | 
			
		||||
 //             CleanUpQcbor(&decodeContext);
 | 
			
		||||
 //             return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
 | 
			
		||||
 //           }
 | 
			
		||||
 //           break;
 | 
			
		||||
 //         }
 | 
			
		||||
 //         case WeatherData::eventtype::Location: {
 | 
			
		||||
 //           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) {
 | 
			
		||||
 //             CleanUpQcbor(&decodeContext);
 | 
			
		||||
 //             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) {
 | 
			
		||||
 //             CleanUpQcbor(&decodeContext);
 | 
			
		||||
 //             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) {
 | 
			
		||||
 //             CleanUpQcbor(&decodeContext);
 | 
			
		||||
 //             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) {
 | 
			
		||||
 //             CleanUpQcbor(&decodeContext);
 | 
			
		||||
 //             return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
 | 
			
		||||
 //           }
 | 
			
		||||
 //           location->latitude = static_cast<int32_t>(tmpLongitude);
 | 
			
		||||
 | 
			
		||||
 //           if (!AddEventToTimeline(std::move(location))) {
 | 
			
		||||
 //             CleanUpQcbor(&decodeContext);
 | 
			
		||||
 //             return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
 | 
			
		||||
 //           }
 | 
			
		||||
 //           break;
 | 
			
		||||
 //         }
 | 
			
		||||
 //         case WeatherData::eventtype::Clouds: {
 | 
			
		||||
 //           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) {
 | 
			
		||||
 //             CleanUpQcbor(&decodeContext);
 | 
			
		||||
 //             return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
 | 
			
		||||
 //           }
 | 
			
		||||
 //           clouds->amount = static_cast<uint8_t>(tmpAmount);
 | 
			
		||||
 | 
			
		||||
 //           if (!AddEventToTimeline(std::move(clouds))) {
 | 
			
		||||
 //             CleanUpQcbor(&decodeContext);
 | 
			
		||||
 //             return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
 | 
			
		||||
 //           }
 | 
			
		||||
 //           break;
 | 
			
		||||
 //         }
 | 
			
		||||
 //         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;
 | 
			
		||||
 //           QCBORDecode_GetInt64InMapSZ(&decodeContext, "Humidity", &tmpType);
 | 
			
		||||
 //           if (tmpType < 0 || tmpType >= 255) {
 | 
			
		||||
 //             CleanUpQcbor(&decodeContext);
 | 
			
		||||
 //             return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
 | 
			
		||||
 //           }
 | 
			
		||||
 //           humidity->humidity = static_cast<uint8_t>(tmpType);
 | 
			
		||||
 | 
			
		||||
 //           if (!AddEventToTimeline(std::move(humidity))) {
 | 
			
		||||
 //             CleanUpQcbor(&decodeContext);
 | 
			
		||||
 //             return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
 | 
			
		||||
 //           }
 | 
			
		||||
 //           break;
 | 
			
		||||
 //         }
 | 
			
		||||
 //         default: {
 | 
			
		||||
 //           CleanUpQcbor(&decodeContext);
 | 
			
		||||
 //           return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
 | 
			
		||||
 //         }
 | 
			
		||||
 //       }
 | 
			
		||||
 | 
			
		||||
 //       QCBORDecode_ExitMap(&decodeContext);
 | 
			
		||||
 //       GetTimelineLength();
 | 
			
		||||
 //       TidyTimeline();
 | 
			
		||||
 | 
			
		||||
 //       if (QCBORDecode_Finish(&decodeContext) != QCBOR_SUCCESS) {
 | 
			
		||||
 //         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!
 | 
			
		||||
 //        */
 | 
			
		||||
 //       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() {
 | 
			
		||||
      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);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return reinterpret_cast<std::unique_ptr<WeatherData::Clouds>&>(*this->nullHeader);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::unique_ptr<WeatherData::Obscuration>& WeatherService::GetCurrentObscuration() {
 | 
			
		||||
      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);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return reinterpret_cast<std::unique_ptr<WeatherData::Obscuration>&>(*this->nullHeader);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::unique_ptr<WeatherData::Precipitation>& WeatherService::GetCurrentPrecipitation() {
 | 
			
		||||
      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);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return reinterpret_cast<std::unique_ptr<WeatherData::Precipitation>&>(*this->nullHeader);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::unique_ptr<WeatherData::Wind>& WeatherService::GetCurrentWind() {
 | 
			
		||||
      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);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return reinterpret_cast<std::unique_ptr<WeatherData::Wind>&>(*this->nullHeader);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::unique_ptr<WeatherData::Temperature>& WeatherService::GetCurrentTemperature() {
 | 
			
		||||
      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);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      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 {
 | 
			
		||||
      return timeline.size();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool WeatherService::AddEventToTimeline(std::unique_ptr<WeatherData::TimelineHeader> event) {
 | 
			
		||||
      if (timeline.size() == timeline.max_size()) {
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      timeline.push_back(std::move(event));
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool WeatherService::HasTimelineEventOfType(const WeatherData::eventtype type) const {
 | 
			
		||||
      uint64_t currentTimestamp = GetCurrentUnixTimestamp();
 | 
			
		||||
      for (auto&& header : timeline) {
 | 
			
		||||
        if (header->eventType == type && IsEventStillValid(header, currentTimestamp)) {
 | 
			
		||||
          return true;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void WeatherService::TidyTimeline() {
 | 
			
		||||
      uint64_t timeCurrent = GetCurrentUnixTimestamp();
 | 
			
		||||
      timeline.erase(std::remove_if(std::begin(timeline),
 | 
			
		||||
                                    std::end(timeline),
 | 
			
		||||
                                    [&](std::unique_ptr<WeatherData::TimelineHeader> const& header) {
 | 
			
		||||
                                      return !IsEventStillValid(header, timeCurrent);
 | 
			
		||||
                                    }),
 | 
			
		||||
                     std::end(timeline));
 | 
			
		||||
 | 
			
		||||
      std::sort(std::begin(timeline), std::end(timeline), CompareTimelineEvents);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool WeatherService::CompareTimelineEvents(const std::unique_ptr<WeatherData::TimelineHeader>& first,
 | 
			
		||||
                                               const std::unique_ptr<WeatherData::TimelineHeader>& second) {
 | 
			
		||||
      return first->timestamp > second->timestamp;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool WeatherService::IsEventStillValid(const std::unique_ptr<WeatherData::TimelineHeader>& uniquePtr, const uint64_t timestamp) {
 | 
			
		||||
      // Not getting timestamp in isEventStillValid for more speed
 | 
			
		||||
      return uniquePtr->timestamp + uniquePtr->expires >= timestamp;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uint64_t WeatherService::GetCurrentUnixTimestamp() const {
 | 
			
		||||
      return std::chrono::duration_cast<std::chrono::seconds>(dateTimeController.CurrentDateTime().time_since_epoch()).count();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int16_t WeatherService::GetTodayMinTemp() const {
 | 
			
		||||
      uint64_t currentTimestamp = GetCurrentUnixTimestamp();
 | 
			
		||||
      uint64_t currentDayEnd = currentTimestamp - ((24 - dateTimeController.Hours()) * 60 * 60) -
 | 
			
		||||
                               ((60 - dateTimeController.Minutes()) * 60) - (60 - dateTimeController.Seconds());
 | 
			
		||||
      int16_t result = -32768;
 | 
			
		||||
      for (auto&& header : this->timeline) {
 | 
			
		||||
        if (header->eventType == WeatherData::eventtype::Temperature && IsEventStillValid(header, currentTimestamp) &&
 | 
			
		||||
            header->timestamp < currentDayEnd &&
 | 
			
		||||
            reinterpret_cast<const std::unique_ptr<WeatherData::Temperature>&>(header)->temperature != -32768) {
 | 
			
		||||
          int16_t temperature = reinterpret_cast<const std::unique_ptr<WeatherData::Temperature>&>(header)->temperature;
 | 
			
		||||
          if (result == -32768) {
 | 
			
		||||
            result = temperature;
 | 
			
		||||
          } else if (result > temperature) {
 | 
			
		||||
            result = temperature;
 | 
			
		||||
          } else {
 | 
			
		||||
            // The temperature in this item is higher than the lowest we've found
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int16_t WeatherService::GetTodayMaxTemp() const {
 | 
			
		||||
      uint64_t currentTimestamp = GetCurrentUnixTimestamp();
 | 
			
		||||
      uint64_t currentDayEnd = currentTimestamp - ((24 - dateTimeController.Hours()) * 60 * 60) -
 | 
			
		||||
                               ((60 - dateTimeController.Minutes()) * 60) - (60 - dateTimeController.Seconds());
 | 
			
		||||
      int16_t result = -32768;
 | 
			
		||||
      for (auto&& header : this->timeline) {
 | 
			
		||||
        if (header->eventType == WeatherData::eventtype::Temperature && IsEventStillValid(header, currentTimestamp) &&
 | 
			
		||||
            header->timestamp < currentDayEnd &&
 | 
			
		||||
            reinterpret_cast<const std::unique_ptr<WeatherData::Temperature>&>(header)->temperature != -32768) {
 | 
			
		||||
          int16_t temperature = reinterpret_cast<const std::unique_ptr<WeatherData::Temperature>&>(header)->temperature;
 | 
			
		||||
          if (result == -32768) {
 | 
			
		||||
            result = temperature;
 | 
			
		||||
          } else if (result < temperature) {
 | 
			
		||||
            result = temperature;
 | 
			
		||||
          } else {
 | 
			
		||||
            // The temperature in this item is lower than the highest we've found
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
//    void WeatherService::CleanUpQcbor(QCBORDecodeContext* decodeContext) {
 | 
			
		||||
//      QCBORDecode_ExitMap(decodeContext);
 | 
			
		||||
//      QCBORDecode_Finish(decodeContext);
 | 
			
		||||
//    }
 | 
			
		||||
@ -1,172 +0,0 @@
 | 
			
		||||
/*  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/>.
 | 
			
		||||
*/
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <cstdint>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <memory>
 | 
			
		||||
 | 
			
		||||
//#define min // workaround: nimble's min/max macros conflict with libstdc++
 | 
			
		||||
//#define max
 | 
			
		||||
//#include <host/ble_gap.h>
 | 
			
		||||
//#include <host/ble_uuid.h>
 | 
			
		||||
//#undef max
 | 
			
		||||
//#undef min
 | 
			
		||||
 | 
			
		||||
#include "components/ble/weather/WeatherData.h"
 | 
			
		||||
//#include "libs/QCBOR/inc/qcbor/qcbor.h"
 | 
			
		||||
#include "components/datetime/DateTimeController.h"
 | 
			
		||||
 | 
			
		||||
//int WeatherCallback(uint16_t connHandle, uint16_t attrHandle, struct ble_gatt_access_ctxt* ctxt, void* arg);
 | 
			
		||||
 | 
			
		||||
namespace Pinetime {
 | 
			
		||||
  namespace System {
 | 
			
		||||
    class SystemTask;
 | 
			
		||||
  }
 | 
			
		||||
  namespace Controllers {
 | 
			
		||||
 | 
			
		||||
    class WeatherService {
 | 
			
		||||
    public:
 | 
			
		||||
      explicit WeatherService(System::SystemTask& system, DateTime& dateTimeController);
 | 
			
		||||
 | 
			
		||||
      void Init();
 | 
			
		||||
 | 
			
		||||
      int OnCommand(uint16_t connHandle, uint16_t attrHandle, struct ble_gatt_access_ctxt* ctxt);
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
       * Helper functions for quick access to currently valid data
 | 
			
		||||
       */
 | 
			
		||||
      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();
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * Searches for the current day's maximum temperature
 | 
			
		||||
       * @return -32768 if there's no data, degrees Celsius times 100 otherwise
 | 
			
		||||
       */
 | 
			
		||||
      int16_t GetTodayMaxTemp() const;
 | 
			
		||||
      /**
 | 
			
		||||
       * Searches for the current day's minimum temperature
 | 
			
		||||
       * @return -32768 if there's no data, degrees Celsius times 100 otherwise
 | 
			
		||||
       */
 | 
			
		||||
      int16_t GetTodayMinTemp() const;
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
       * Management functions
 | 
			
		||||
       */
 | 
			
		||||
      /**
 | 
			
		||||
       * Adds an event to the timeline
 | 
			
		||||
       * @return
 | 
			
		||||
       */
 | 
			
		||||
      bool AddEventToTimeline(std::unique_ptr<WeatherData::TimelineHeader> event);
 | 
			
		||||
      /**
 | 
			
		||||
       * Gets the current timeline length
 | 
			
		||||
       */
 | 
			
		||||
      size_t GetTimelineLength() const;
 | 
			
		||||
      /**
 | 
			
		||||
       * Checks if an event of a certain type exists in the timeline
 | 
			
		||||
       */
 | 
			
		||||
      bool HasTimelineEventOfType(WeatherData::eventtype type) const;
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
      // 00040000-78fc-48fe-8e23-433b3a1942d0
 | 
			
		||||
//      static constexpr ble_uuid128_t BaseUuid() {
 | 
			
		||||
//        return CharUuid(0x00, 0x00);
 | 
			
		||||
//      }
 | 
			
		||||
 | 
			
		||||
//      // 0004yyxx-78fc-48fe-8e23-433b3a1942d0
 | 
			
		||||
//      static constexpr ble_uuid128_t CharUuid(uint8_t x, uint8_t y) {
 | 
			
		||||
//        return ble_uuid128_t {.u = {.type = BLE_UUID_TYPE_128},
 | 
			
		||||
//                              .value = {0xd0, 0x42, 0x19, 0x3a, 0x3b, 0x43, 0x23, 0x8e, 0xfe, 0x48, 0xfc, 0x78, y, x, 0x04, 0x00}};
 | 
			
		||||
//      }
 | 
			
		||||
 | 
			
		||||
//      ble_uuid128_t weatherUuid {BaseUuid()};
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * Just write timeline data here.
 | 
			
		||||
       *
 | 
			
		||||
       * See {@link WeatherData.h} for more information.
 | 
			
		||||
       */
 | 
			
		||||
//      ble_uuid128_t weatherDataCharUuid {CharUuid(0x00, 0x01)};
 | 
			
		||||
      /**
 | 
			
		||||
       * This doesn't take timeline data, provides some control over it.
 | 
			
		||||
       *
 | 
			
		||||
       * NOTE: Currently not supported. Companion app implementer feedback required.
 | 
			
		||||
       * There's very little point in solidifying an API before we know the needs.
 | 
			
		||||
       */
 | 
			
		||||
//      ble_uuid128_t weatherControlCharUuid {CharUuid(0x00, 0x02)};
 | 
			
		||||
 | 
			
		||||
//      const struct ble_gatt_chr_def characteristicDefinition[3] = {
 | 
			
		||||
//        {.uuid = &weatherDataCharUuid.u,
 | 
			
		||||
//         .access_cb = WeatherCallback,
 | 
			
		||||
//         .arg = this,
 | 
			
		||||
//         .flags = BLE_GATT_CHR_F_WRITE,
 | 
			
		||||
//         .val_handle = &eventHandle},
 | 
			
		||||
//        {.uuid = &weatherControlCharUuid.u, .access_cb = WeatherCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ},
 | 
			
		||||
//        {nullptr}};
 | 
			
		||||
//      const struct ble_gatt_svc_def serviceDefinition[2] = {
 | 
			
		||||
//        {.type = BLE_GATT_SVC_TYPE_PRIMARY, .uuid = &weatherUuid.u, .characteristics = characteristicDefinition}, {0}};
 | 
			
		||||
 | 
			
		||||
      uint16_t eventHandle {};
 | 
			
		||||
 | 
			
		||||
      Pinetime::System::SystemTask& system;
 | 
			
		||||
      Pinetime::Controllers::DateTime& dateTimeController;
 | 
			
		||||
 | 
			
		||||
      std::vector<std::unique_ptr<WeatherData::TimelineHeader>> timeline;
 | 
			
		||||
      std::unique_ptr<WeatherData::TimelineHeader> nullTimelineheader = std::make_unique<WeatherData::TimelineHeader>();
 | 
			
		||||
      std::unique_ptr<WeatherData::TimelineHeader>* nullHeader;
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * Cleans up the timeline of expired events
 | 
			
		||||
       */
 | 
			
		||||
      void TidyTimeline();
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * Compares two timeline events
 | 
			
		||||
       */
 | 
			
		||||
      static bool CompareTimelineEvents(const std::unique_ptr<WeatherData::TimelineHeader>& first,
 | 
			
		||||
                                        const std::unique_ptr<WeatherData::TimelineHeader>& second);
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * 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);
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * This is a helper function that closes a QCBOR map and decoding context cleanly
 | 
			
		||||
       */
 | 
			
		||||
//      void CleanUpQcbor(QCBORDecodeContext* decodeContext);
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user