-
Notifications
You must be signed in to change notification settings - Fork 70
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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 <[email protected]>
- Loading branch information
1 parent
39b9b17
commit d6cc458
Showing
9 changed files
with
246 additions
and
786 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Submodule InfiniTime
updated
66 files
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
}; | ||
} | ||
} |
Oops, something went wrong.