summaryrefslogtreecommitdiff
path: root/src/components/ble/weather/WeatherService.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/ble/weather/WeatherService.h')
-rw-r--r--src/components/ble/weather/WeatherService.h172
1 files changed, 172 insertions, 0 deletions
diff --git a/src/components/ble/weather/WeatherService.h b/src/components/ble/weather/WeatherService.h
new file mode 100644
index 00000000..eca70cbd
--- /dev/null
+++ b/src/components/ble/weather/WeatherService.h
@@ -0,0 +1,172 @@
+/* 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 "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);
+ };
+ }
+}