aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/ble/SimpleWeatherService.h
diff options
context:
space:
mode:
authorJean-François Milants <jf@codingfield.com>2023-12-09 20:39:08 +0100
committerJF <JF002@users.noreply.github.com>2023-12-23 21:12:25 +0100
commitc94a59e7d3e0f9929171263412033a56872c168a (patch)
treef9e3d4c1915b91f57ff8d96b18e10f0fbb998aa4 /src/components/ble/SimpleWeatherService.h
parent088082d32db483ac5326bed09d5d47847fb5bf9b (diff)
SimpleWeather service : new weather implementation
This new implementation of the weather feature provides a new BLE API and a new weather service. The API uses a single characteristic that allows companion apps to write the weather conditions (current and forecast for the next 5 days). The SimpleWeather service exposes those data as std::optional fields. This new implementation replaces the previous WeahterService. The API is documented in docs/SimpleWeatherService.md.
Diffstat (limited to 'src/components/ble/SimpleWeatherService.h')
-rw-r--r--src/components/ble/SimpleWeatherService.h131
1 files changed, 131 insertions, 0 deletions
diff --git a/src/components/ble/SimpleWeatherService.h b/src/components/ble/SimpleWeatherService.h
new file mode 100644
index 00000000..46d5e187
--- /dev/null
+++ b/src/components/ble/SimpleWeatherService.h
@@ -0,0 +1,131 @@
+/* Copyright (C) 2023 Jean-François Milants
+
+ 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>
+#include <optional>
+#include <cstring>
+#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);
+
+ 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
+ };
+
+ struct CurrentWeather {
+ CurrentWeather(uint64_t timestamp, uint8_t temperature, uint8_t minTemperature, uint8_t maxTemperature,
+ uint8_t iconId, const char* location)
+ : timestamp{timestamp}, temperature{temperature}, minTemperature{minTemperature}, maxTemperature{maxTemperature},
+ iconId{iconId} {
+ std::memcpy(this->location, location, 32);
+ this->location[32] = 0;
+ }
+ uint64_t timestamp;
+ uint8_t temperature;
+ uint8_t minTemperature;
+ uint8_t maxTemperature;
+ Icons iconId;
+ char location[33]; // 32 char + \0 (end of string)
+
+ bool operator==(const CurrentWeather& other) const;
+ bool operator!=(const CurrentWeather& other) const;
+ };
+
+ struct Forecast {
+ uint64_t timestamp;
+ uint8_t nbDays;
+ struct Day {
+ uint8_t minTemperature;
+ uint8_t maxTemperature;
+ uint8_t iconId;
+ };
+ std::array<Day, 5> 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;
+ };
+ }
+}