SimpleWeather service : new weather implementation

Fix recovery firmware and code formatting.
This commit is contained in:
Jean-François Milants 2023-12-09 21:05:50 +01:00 committed by JF
parent c94a59e7d3
commit 50c679023f
5 changed files with 93 additions and 62 deletions

View file

@ -22,45 +22,45 @@
using namespace Pinetime::Controllers; using namespace Pinetime::Controllers;
namespace { namespace {
enum class MessageType { enum class MessageType { CurrentWeather, Forecast, Unknown };
CurrentWeather,
Forecast,
Unknown
};
SimpleWeatherService::CurrentWeather CreateCurrentWeather(const uint8_t* dataBuffer) { SimpleWeatherService::CurrentWeather CreateCurrentWeather(const uint8_t* dataBuffer) {
char cityName[33]; char cityName[33];
std::memcpy(&cityName[0], &dataBuffer[13], 32); std::memcpy(&cityName[0], &dataBuffer[13], 32);
cityName[32] = '\0'; cityName[32] = '\0';
return SimpleWeatherService::CurrentWeather{dataBuffer[2] + (dataBuffer[3] << 8) + (dataBuffer[4] << 16) + (dataBuffer[5] << 24) + return SimpleWeatherService::CurrentWeather {dataBuffer[2] + (dataBuffer[3] << 8) + (dataBuffer[4] << 16) + (dataBuffer[5] << 24) +
((uint64_t) dataBuffer[6] << 32) + ((uint64_t) dataBuffer[7] << 40) + ((uint64_t) dataBuffer[8] << 48) + ((uint64_t) dataBuffer[6] << 32) + ((uint64_t) dataBuffer[7] << 40) +
((uint64_t) dataBuffer[9] << 54), ((uint64_t) dataBuffer[8] << 48) + ((uint64_t) dataBuffer[9] << 54),
dataBuffer[10], dataBuffer[10],
dataBuffer[11], dataBuffer[11],
dataBuffer[12], dataBuffer[12],
dataBuffer[13 + 32], dataBuffer[13 + 32],
cityName}; cityName};
} }
SimpleWeatherService::Forecast CreateForecast(const uint8_t* dataBuffer) { SimpleWeatherService::Forecast CreateForecast(const uint8_t* dataBuffer) {
uint64_t timestamp = static_cast<uint64_t>(dataBuffer[2] + (dataBuffer[3] << 8) + (dataBuffer[4] << 16) + (dataBuffer[5] << 24) + uint64_t timestamp = static_cast<uint64_t>(dataBuffer[2] + (dataBuffer[3] << 8) + (dataBuffer[4] << 16) + (dataBuffer[5] << 24) +
((uint64_t) dataBuffer[6] << 32) + ((uint64_t) dataBuffer[7] << 40) + ((uint64_t) dataBuffer[8] << 48) + ((uint64_t) dataBuffer[6] << 32) + ((uint64_t) dataBuffer[7] << 40) +
((uint64_t) dataBuffer[9] << 54)); ((uint64_t) dataBuffer[8] << 48) + ((uint64_t) dataBuffer[9] << 54));
uint8_t nbDays = dataBuffer[10]; uint8_t nbDays = dataBuffer[10];
std::array<SimpleWeatherService::Forecast::Day, 5> days; std::array<SimpleWeatherService::Forecast::Day, 5> days;
for (int i = 0; i < nbDays; i++) { for (int i = 0; i < nbDays; i++) {
days[i] = SimpleWeatherService::Forecast::Day {dataBuffer[11 + (i * 3)], days[i] = SimpleWeatherService::Forecast::Day {dataBuffer[11 + (i * 3)], dataBuffer[12 + (i * 3)], dataBuffer[13 + (i * 3)]};
dataBuffer[12 + (i * 3)],
dataBuffer[13 + (i * 3)]};
} }
return SimpleWeatherService::Forecast {timestamp, nbDays, days}; return SimpleWeatherService::Forecast {timestamp, nbDays, days};
} }
MessageType GetMessageType(const uint8_t* dataBuffer) { MessageType GetMessageType(const uint8_t* dataBuffer) {
switch(dataBuffer[0]) { switch (dataBuffer[0]) {
case 0: return MessageType::CurrentWeather; break; case 0:
case 1: return MessageType::Forecast; break; return MessageType::CurrentWeather;
default: return MessageType::Unknown; break; break;
case 1:
return MessageType::Forecast;
break;
default:
return MessageType::Unknown;
break;
} }
} }
@ -74,7 +74,6 @@ int WeatherCallback(uint16_t /*connHandle*/, uint16_t /*attrHandle*/, struct ble
} }
SimpleWeatherService::SimpleWeatherService(const DateTime& dateTimeController) : dateTimeController(dateTimeController) { SimpleWeatherService::SimpleWeatherService(const DateTime& dateTimeController) : dateTimeController(dateTimeController) {
} }
void SimpleWeatherService::Init() { void SimpleWeatherService::Init() {
@ -86,9 +85,9 @@ int SimpleWeatherService::OnCommand(struct ble_gatt_access_ctxt* ctxt) {
const auto* buffer = ctxt->om; const auto* buffer = ctxt->om;
const auto* dataBuffer = buffer->om_data; const auto* dataBuffer = buffer->om_data;
switch(GetMessageType(dataBuffer)) { switch (GetMessageType(dataBuffer)) {
case MessageType::CurrentWeather: case MessageType::CurrentWeather:
if(GetVersion(dataBuffer) == 0) { if (GetVersion(dataBuffer) == 0) {
currentWeather = CreateCurrentWeather(dataBuffer); currentWeather = CreateCurrentWeather(dataBuffer);
NRF_LOG_INFO("Current weather :\n\tTimestamp : %d\n\tTemperature:%d\n\tMin:%d\n\tMax:%d\n\tIcon:%d\n\tLocation:%s", NRF_LOG_INFO("Current weather :\n\tTimestamp : %d\n\tTemperature:%d\n\tMin:%d\n\tMax:%d\n\tIcon:%d\n\tLocation:%s",
currentWeather->timestamp, currentWeather->timestamp,
@ -100,11 +99,15 @@ int SimpleWeatherService::OnCommand(struct ble_gatt_access_ctxt* ctxt) {
} }
break; break;
case MessageType::Forecast: case MessageType::Forecast:
if(GetVersion(dataBuffer) == 0) { if (GetVersion(dataBuffer) == 0) {
forecast = CreateForecast(dataBuffer); forecast = CreateForecast(dataBuffer);
NRF_LOG_INFO("Forecast : Timestamp : %d", forecast->timestamp); NRF_LOG_INFO("Forecast : Timestamp : %d", forecast->timestamp);
for(int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
NRF_LOG_INFO("\t[%d] Min: %d - Max : %d - Icon : %d", i, forecast->days[i].minTemperature, forecast->days[i].maxTemperature, forecast->days[i].iconId); NRF_LOG_INFO("\t[%d] Min: %d - Max : %d - Icon : %d",
i,
forecast->days[i].minTemperature,
forecast->days[i].maxTemperature,
forecast->days[i].iconId);
} }
} }
break; break;
@ -116,13 +119,13 @@ int SimpleWeatherService::OnCommand(struct ble_gatt_access_ctxt* ctxt) {
} }
std::optional<SimpleWeatherService::CurrentWeather> SimpleWeatherService::Current() const { std::optional<SimpleWeatherService::CurrentWeather> SimpleWeatherService::Current() const {
if(currentWeather) { if (currentWeather) {
auto currentTime = dateTimeController.UTCDateTime().time_since_epoch(); auto currentTime = dateTimeController.UTCDateTime().time_since_epoch();
auto weatherTpSecond = std::chrono::seconds{currentWeather->timestamp}; auto weatherTpSecond = std::chrono::seconds {currentWeather->timestamp};
auto weatherTp = std::chrono::duration_cast<std::chrono::seconds>(weatherTpSecond); auto weatherTp = std::chrono::duration_cast<std::chrono::seconds>(weatherTpSecond);
auto delta = currentTime - weatherTp; auto delta = currentTime - weatherTp;
if(delta < std::chrono::hours{24}) { if (delta < std::chrono::hours {24}) {
return currentWeather; return currentWeather;
} }
} }
@ -130,13 +133,13 @@ std::optional<SimpleWeatherService::CurrentWeather> SimpleWeatherService::Curren
} }
std::optional<SimpleWeatherService::Forecast> SimpleWeatherService::GetForecast() const { std::optional<SimpleWeatherService::Forecast> SimpleWeatherService::GetForecast() const {
if(forecast) { if (forecast) {
auto currentTime = dateTimeController.UTCDateTime().time_since_epoch(); auto currentTime = dateTimeController.UTCDateTime().time_since_epoch();
auto weatherTpSecond = std::chrono::seconds{forecast->timestamp}; auto weatherTpSecond = std::chrono::seconds {forecast->timestamp};
auto weatherTp = std::chrono::duration_cast<std::chrono::seconds>(weatherTpSecond); auto weatherTp = std::chrono::duration_cast<std::chrono::seconds>(weatherTpSecond);
auto delta = currentTime - weatherTp; auto delta = currentTime - weatherTp;
if(delta < std::chrono::hours{24}) { if (delta < std::chrono::hours {24}) {
return this->forecast; return this->forecast;
} }
} }

View file

@ -47,12 +47,12 @@ namespace Pinetime {
int OnCommand(struct ble_gatt_access_ctxt* ctxt); int OnCommand(struct ble_gatt_access_ctxt* ctxt);
enum class Icons : uint8_t { enum class Icons : uint8_t {
Sun = 0, // ClearSky Sun = 0, // ClearSky
CloudsSun = 1, // FewClouds CloudsSun = 1, // FewClouds
Clouds = 2, // Scattered clouds Clouds = 2, // Scattered clouds
BrokenClouds = 3, BrokenClouds = 3,
CloudShowerHeavy = 4, // shower rain CloudShowerHeavy = 4, // shower rain
CloudSunRain = 5, // rain CloudSunRain = 5, // rain
Thunderstorm = 6, Thunderstorm = 6,
Snow = 7, Snow = 7,
Smog = 8, // Mist Smog = 8, // Mist
@ -60,13 +60,21 @@ namespace Pinetime {
}; };
struct CurrentWeather { struct CurrentWeather {
CurrentWeather(uint64_t timestamp, uint8_t temperature, uint8_t minTemperature, uint8_t maxTemperature, CurrentWeather(uint64_t timestamp,
uint8_t iconId, const char* location) uint8_t temperature,
: timestamp{timestamp}, temperature{temperature}, minTemperature{minTemperature}, maxTemperature{maxTemperature}, uint8_t minTemperature,
iconId{iconId} { 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); std::memcpy(this->location, location, 32);
this->location[32] = 0; this->location[32] = 0;
} }
uint64_t timestamp; uint64_t timestamp;
uint8_t temperature; uint8_t temperature;
uint8_t minTemperature; uint8_t minTemperature;
@ -81,18 +89,19 @@ namespace Pinetime {
struct Forecast { struct Forecast {
uint64_t timestamp; uint64_t timestamp;
uint8_t nbDays; uint8_t nbDays;
struct Day { struct Day {
uint8_t minTemperature; uint8_t minTemperature;
uint8_t maxTemperature; uint8_t maxTemperature;
uint8_t iconId; uint8_t iconId;
}; };
std::array<Day, 5> days; std::array<Day, 5> days;
}; };
std::optional<CurrentWeather> Current() const; std::optional<CurrentWeather> Current() const;
std::optional<Forecast> GetForecast() const; std::optional<Forecast> GetForecast() const;
private: private:
// 00050000-78fc-48fe-8e23-433b3a1942d0 // 00050000-78fc-48fe-8e23-433b3a1942d0
static constexpr ble_uuid128_t BaseUuid() { static constexpr ble_uuid128_t BaseUuid() {
@ -109,13 +118,12 @@ namespace Pinetime {
ble_uuid128_t weatherDataCharUuid {CharUuid(0x00, 0x01)}; ble_uuid128_t weatherDataCharUuid {CharUuid(0x00, 0x01)};
const struct ble_gatt_chr_def characteristicDefinition[2] = { const struct ble_gatt_chr_def characteristicDefinition[2] = {{.uuid = &weatherDataCharUuid.u,
{.uuid = &weatherDataCharUuid.u, .access_cb = WeatherCallback,
.access_cb = WeatherCallback, .arg = this,
.arg = this, .flags = BLE_GATT_CHR_F_WRITE,
.flags = BLE_GATT_CHR_F_WRITE, .val_handle = &eventHandle},
.val_handle = &eventHandle}, {0}};
{0}};
const struct ble_gatt_svc_def serviceDefinition[2] = { const struct ble_gatt_svc_def serviceDefinition[2] = {
{.type = BLE_GATT_SVC_TYPE_PRIMARY, .uuid = &weatherUuid.u, .characteristics = characteristicDefinition}, {.type = BLE_GATT_SVC_TYPE_PRIMARY, .uuid = &weatherUuid.u, .characteristics = characteristicDefinition},
{0}}; {0}};

View file

@ -122,7 +122,7 @@ void DisplayApp::PushMessage(Display::Messages msg) {
void DisplayApp::Register(Pinetime::System::SystemTask* /*systemTask*/) { void DisplayApp::Register(Pinetime::System::SystemTask* /*systemTask*/) {
} }
void DisplayApp::Register(Pinetime::Controllers::WeatherService* /*weatherService*/) { void DisplayApp::Register(Pinetime::Controllers::SimpleWeatherService* /*weatherService*/) {
} }
void DisplayApp::Register(Pinetime::Controllers::MusicService* /*musicService*/) { void DisplayApp::Register(Pinetime::Controllers::MusicService* /*musicService*/) {

View file

@ -34,7 +34,7 @@ namespace Pinetime {
class AlarmController; class AlarmController;
class BrightnessController; class BrightnessController;
class FS; class FS;
class WeatherService; class SimpleWeatherService;
class MusicService; class MusicService;
class NavigationService; class NavigationService;
} }
@ -69,7 +69,7 @@ namespace Pinetime {
void PushMessage(Pinetime::Applications::Display::Messages msg); void PushMessage(Pinetime::Applications::Display::Messages msg);
void Register(Pinetime::System::SystemTask* systemTask); void Register(Pinetime::System::SystemTask* systemTask);
void Register(Pinetime::Controllers::WeatherService* weatherService); void Register(Pinetime::Controllers::SimpleWeatherService* weatherService);
void Register(Pinetime::Controllers::MusicService* musicService); void Register(Pinetime::Controllers::MusicService* musicService);
void Register(Pinetime::Controllers::NavigationService* NavigationService); void Register(Pinetime::Controllers::NavigationService* NavigationService);

View file

@ -45,16 +45,36 @@ namespace {
const char* GetIcon(const Pinetime::Controllers::SimpleWeatherService::Icons icon) { const char* GetIcon(const Pinetime::Controllers::SimpleWeatherService::Icons icon) {
switch (icon) { switch (icon) {
case Pinetime::Controllers::SimpleWeatherService::Icons::Sun: return Symbols::sun; break; case Pinetime::Controllers::SimpleWeatherService::Icons::Sun:
case Pinetime::Controllers::SimpleWeatherService::Icons::CloudsSun: return Symbols::cloudSun; break; return Symbols::sun;
case Pinetime::Controllers::SimpleWeatherService::Icons::Clouds: return Symbols::cloud; break; break;
case Pinetime::Controllers::SimpleWeatherService::Icons::BrokenClouds: return Symbols::cloud; break; // TODO missing symbol case Pinetime::Controllers::SimpleWeatherService::Icons::CloudsSun:
case Pinetime::Controllers::SimpleWeatherService::Icons::Thunderstorm: return Symbols::cloud; break; // TODO missing symbol return Symbols::cloudSun;
case Pinetime::Controllers::SimpleWeatherService::Icons::Snow: return Symbols::cloud; break; // TODO missing symbol break;
case Pinetime::Controllers::SimpleWeatherService::Icons::CloudShowerHeavy: return Symbols::cloudShowersHeavy; break; case Pinetime::Controllers::SimpleWeatherService::Icons::Clouds:
case Pinetime::Controllers::SimpleWeatherService::Icons::CloudSunRain: return Symbols::cloudSunRain; break; return Symbols::cloud;
case Pinetime::Controllers::SimpleWeatherService::Icons::Smog: return Symbols::smog; break; break;
default: return Symbols::ban; break; case Pinetime::Controllers::SimpleWeatherService::Icons::BrokenClouds:
return Symbols::cloud;
break; // TODO missing symbol
case Pinetime::Controllers::SimpleWeatherService::Icons::Thunderstorm:
return Symbols::cloud;
break; // TODO missing symbol
case Pinetime::Controllers::SimpleWeatherService::Icons::Snow:
return Symbols::cloud;
break; // TODO missing symbol
case Pinetime::Controllers::SimpleWeatherService::Icons::CloudShowerHeavy:
return Symbols::cloudShowersHeavy;
break;
case Pinetime::Controllers::SimpleWeatherService::Icons::CloudSunRain:
return Symbols::cloudSunRain;
break;
case Pinetime::Controllers::SimpleWeatherService::Icons::Smog:
return Symbols::smog;
break;
default:
return Symbols::ban;
break;
} }
} }
} }