Skip to content

Commit 2f6288d

Browse files
committed
SimpleWeatherService: Add sunrise and sunset data
1 parent a266202 commit 2f6288d

11 files changed

+70
-18
lines changed

CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.10)
22

33
set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose Debug or Release")
44

5-
project(pinetime VERSION 1.14.0 LANGUAGES C CXX ASM)
5+
project(pinetime VERSION 1.15.0 LANGUAGES C CXX ASM)
66

77
set(CMAKE_C_STANDARD 99)
88
set(CMAKE_CXX_STANDARD 20)

doc/SimpleWeatherService.md

+9-5
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,25 @@ The host uses this characteristic to update the current weather information and
1717

1818
This characteristics accepts a byte array with the following 2-Bytes header:
1919

20-
- [0] Message Type :
20+
- [0] Message Type :
2121
- `0` : Current weather
2222
- `1` : Forecast
23-
- [1] Message Version : Version `0` is currently supported. Other versions might be added in future releases
23+
- [1] Message Version :
24+
- `0` : Currently supported
25+
- `1` : Adds support for sunrise and sunset
2426

25-
### Current Weather
27+
### Current Weather
2628

2729
The byte array must contain the following data:
2830

2931
- [0] : Message type = `0`
30-
- [1] : Message version = `0`
32+
- [1] : Message version = `1`
3133
- [2][3][4][5][6][7][8][9] : Timestamp (64 bits UNIX timestamp, number of seconds elapsed since 1 JAN 1970) in local time (the same timezone as the one used to set the time)
3234
- [10, 11] : Current temperature (°C * 100)
3335
- [12, 13] : Minimum temperature (°C * 100)
3436
- [14, 15] : Maximum temperature (°C * 100)
3537
- [16]..[47] : location (string, unused characters should be set to `0`)
36-
- [48] : icon ID
38+
- [48] : icon ID
3739
- 0 = Sun, clear sky
3840
- 1 = Few clouds
3941
- 2 = Clouds
@@ -43,6 +45,8 @@ The byte array must contain the following data:
4345
- 6 = Thunderstorm
4446
- 7 = Snow
4547
- 8 = Mist, smog
48+
- [49][50][51][52][53][54][55][56] : Sunrise timestamp (64 bits UNIX timestamp, number of seconds elapsed since 1 JAN 1970) in local time (the same timezone as the one used to set the time)
49+
- [57][58][59][60][61][62][63][64] : Sunset timestamp (64 bits UNIX timestamp, number of seconds elapsed since 1 JAN 1970) in local time (the same timezone as the one used to set the time)
4650

4751
### Forecast
4852

src/components/ble/SimpleWeatherService.cpp

+30-3
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,20 @@ namespace {
4141
SimpleWeatherService::Location cityName;
4242
std::memcpy(cityName.data(), &dataBuffer[16], 32);
4343
cityName[32] = '\0';
44+
uint64_t sunrise = 0;
45+
uint64_t sunset = 0;
46+
if (dataBuffer[1] > 0) {
47+
sunrise = ToUInt64(&dataBuffer[49]);
48+
sunset = ToUInt64(&dataBuffer[57]);
49+
}
4450
return SimpleWeatherService::CurrentWeather(ToUInt64(&dataBuffer[2]),
4551
ToInt16(&dataBuffer[10]),
4652
ToInt16(&dataBuffer[12]),
4753
ToInt16(&dataBuffer[14]),
4854
SimpleWeatherService::Icons {dataBuffer[16 + 32]},
49-
std::move(cityName));
55+
std::move(cityName),
56+
sunrise,
57+
sunset);
5058
}
5159

5260
SimpleWeatherService::Forecast CreateForecast(const uint8_t* dataBuffer) {
@@ -94,7 +102,7 @@ int SimpleWeatherService::OnCommand(struct ble_gatt_access_ctxt* ctxt) {
94102

95103
switch (GetMessageType(dataBuffer)) {
96104
case MessageType::CurrentWeather:
97-
if (GetVersion(dataBuffer) == 0) {
105+
if (GetVersion(dataBuffer) <= 1) {
98106
currentWeather = CreateCurrentWeather(dataBuffer);
99107
NRF_LOG_INFO("Current weather :\n\tTimestamp : %d\n\tTemperature:%d\n\tMin:%d\n\tMax:%d\n\tIcon:%d\n\tLocation:%s",
100108
currentWeather->timestamp,
@@ -103,6 +111,9 @@ int SimpleWeatherService::OnCommand(struct ble_gatt_access_ctxt* ctxt) {
103111
currentWeather->maxTemperature,
104112
currentWeather->iconId,
105113
currentWeather->location.data());
114+
if (GetVersion(dataBuffer) == 1) {
115+
NRF_LOG_INFO("Sunrise: %d\n\tSunset: %d", currentWeather->sunrise, currentWeather->sunset);
116+
}
106117
}
107118
break;
108119
case MessageType::Forecast:
@@ -153,10 +164,26 @@ std::optional<SimpleWeatherService::Forecast> SimpleWeatherService::GetForecast(
153164
return {};
154165
}
155166

167+
bool SimpleWeatherService::IsNight() const {
168+
if (currentWeather && currentWeather->sunrise > 0 && currentWeather->sunset > 0) {
169+
auto currentTime = dateTimeController.CurrentDateTime().time_since_epoch();
170+
171+
auto sunriseSecond = std::chrono::seconds {currentWeather->sunrise};
172+
auto sunsetSecond = std::chrono::seconds {currentWeather->sunset};
173+
174+
auto sunrise = std::chrono::duration_cast<std::chrono::seconds>(sunriseSecond);
175+
auto sunset = std::chrono::duration_cast<std::chrono::seconds>(sunsetSecond);
176+
177+
return currentTime < sunrise || currentTime > sunset;
178+
}
179+
180+
return false;
181+
}
182+
156183
bool SimpleWeatherService::CurrentWeather::operator==(const SimpleWeatherService::CurrentWeather& other) const {
157184
return this->iconId == other.iconId && this->temperature == other.temperature && this->timestamp == other.timestamp &&
158185
this->maxTemperature == other.maxTemperature && this->minTemperature == other.maxTemperature &&
159-
std::strcmp(this->location.data(), other.location.data()) == 0;
186+
std::strcmp(this->location.data(), other.location.data()) == 0 && this->sunrise == other.sunrise && this->sunset == other.sunset;
160187
}
161188

162189
bool SimpleWeatherService::Forecast::Day::operator==(const SimpleWeatherService::Forecast::Day& other) const {

src/components/ble/SimpleWeatherService.h

+10-2
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,17 @@ namespace Pinetime {
6969
int16_t minTemperature,
7070
int16_t maxTemperature,
7171
Icons iconId,
72-
Location&& location)
72+
Location&& location,
73+
uint64_t sunrise,
74+
uint64_t sunset)
7375
: timestamp {timestamp},
7476
temperature {temperature},
7577
minTemperature {minTemperature},
7678
maxTemperature {maxTemperature},
7779
iconId {iconId},
78-
location {std::move(location)} {
80+
location {std::move(location)},
81+
sunrise {sunrise},
82+
sunset {sunset} {
7983
}
8084

8185
uint64_t timestamp;
@@ -84,6 +88,8 @@ namespace Pinetime {
8488
int16_t maxTemperature;
8589
Icons iconId;
8690
Location location;
91+
uint64_t sunrise;
92+
uint64_t sunset;
8793

8894
bool operator==(const CurrentWeather& other) const;
8995
};
@@ -108,6 +114,8 @@ namespace Pinetime {
108114
std::optional<CurrentWeather> Current() const;
109115
std::optional<Forecast> GetForecast() const;
110116

117+
bool IsNight() const;
118+
111119
static int16_t CelsiusToFahrenheit(int16_t celsius) {
112120
return celsius * 9 / 5 + 3200;
113121
}

src/displayapp/fonts/fonts.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
"sources": [
6969
{
7070
"file": "FontAwesome5-Solid+Brands+Regular.woff",
71-
"range": "0xf185, 0xf6c4, 0xf743, 0xf740, 0xf75f, 0xf0c2, 0xf05e, 0xf73b, 0xf0e7, 0xf2dc"
71+
"range": "0xf185, 0xf186, 0xf6c3, 0xf6c4, 0xf73c, 0xf743, 0xf740, 0xf75f, 0xf0c2, 0xf05e, 0xf73b, 0xf0e7, 0xf2dc"
7272
}
7373
],
7474
"bpp": 1,

src/displayapp/screens/Symbols.h

+3
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,11 @@ namespace Pinetime {
4242

4343
// fontawesome_weathericons.c
4444
// static constexpr const char* sun = "\xEF\x86\x85";
45+
static constexpr const char* moon = "\xEF\x86\x86"; // 0xf186
4546
static constexpr const char* cloudSun = "\xEF\x9B\x84";
47+
static constexpr const char* cloudMoon = "\xEF\x9B\x83"; // 0xf6c3
4648
static constexpr const char* cloudSunRain = "\xEF\x9D\x83";
49+
static constexpr const char* cloudMoonRain = "\xEF\x9C\xBC"; // 0xf73c
4750
static constexpr const char* cloudShowersHeavy = "\xEF\x9D\x80";
4851
static constexpr const char* smog = "\xEF\x9D\x9F";
4952
static constexpr const char* cloud = "\xEF\x83\x82";

src/displayapp/screens/WatchFaceDigital.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ void WatchFaceDigital::Refresh() {
182182
}
183183
temp = temp / 100 + (temp % 100 >= 50 ? 1 : 0);
184184
lv_label_set_text_fmt(temperature, "%d°%c", temp, tempUnit);
185-
lv_label_set_text(weatherIcon, Symbols::GetSymbol(optCurrentWeather->iconId));
185+
lv_label_set_text(weatherIcon, Symbols::GetSymbol(optCurrentWeather->iconId, weatherService.IsNight()));
186186
} else {
187187
lv_label_set_text_static(temperature, "");
188188
lv_label_set_text(weatherIcon, "");

src/displayapp/screens/WatchFacePineTimeStyle.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,7 @@ void WatchFacePineTimeStyle::Refresh() {
549549
}
550550
temp = temp / 100 + (temp % 100 >= 50 ? 1 : 0);
551551
lv_label_set_text_fmt(temperature, "%d°", temp);
552-
lv_label_set_text(weatherIcon, Symbols::GetSymbol(optCurrentWeather->iconId));
552+
lv_label_set_text(weatherIcon, Symbols::GetSymbol(optCurrentWeather->iconId, weatherService.IsNight()));
553553
} else {
554554
lv_label_set_text(temperature, "--");
555555
lv_label_set_text(weatherIcon, Symbols::ban);

src/displayapp/screens/Weather.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ void Weather::Refresh() {
131131
maxTemp = Controllers::SimpleWeatherService::CelsiusToFahrenheit(maxTemp);
132132
tempUnit = 'F';
133133
}
134-
lv_label_set_text(icon, Symbols::GetSymbol(optCurrentWeather->iconId));
134+
lv_label_set_text(icon, Symbols::GetSymbol(optCurrentWeather->iconId, weatherService.IsNight()));
135135
lv_label_set_text(condition, Symbols::GetCondition(optCurrentWeather->iconId));
136136
lv_label_set_text_fmt(temperature, "%d°%c", RoundTemperature(temp), tempUnit);
137137
lv_label_set_text_fmt(minTemperature, "%d°", RoundTemperature(minTemp));
@@ -169,7 +169,7 @@ void Weather::Refresh() {
169169
minTemp = RoundTemperature(minTemp);
170170
const char* dayOfWeek = Controllers::DateTime::DayOfWeekShortToStringLow(static_cast<Controllers::DateTime::Days>(wday));
171171
lv_table_set_cell_value(forecast, 0, i, dayOfWeek);
172-
lv_table_set_cell_value(forecast, 1, i, Symbols::GetSymbol(optCurrentForecast->days[i].iconId));
172+
lv_table_set_cell_value(forecast, 1, i, Symbols::GetSymbol(optCurrentForecast->days[i].iconId, weatherService.IsNight()));
173173
// Pad cells based on the largest number of digits on each column
174174
char maxPadding[3] = " ";
175175
char minPadding[3] = " ";

src/displayapp/screens/WeatherSymbols.cpp

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
#include "displayapp/screens/WeatherSymbols.h"
22

3-
const char* Pinetime::Applications::Screens::Symbols::GetSymbol(const Pinetime::Controllers::SimpleWeatherService::Icons icon) {
3+
const char* Pinetime::Applications::Screens::Symbols::GetSymbol(const Pinetime::Controllers::SimpleWeatherService::Icons icon,
4+
const bool isNight) {
45
switch (icon) {
56
case Pinetime::Controllers::SimpleWeatherService::Icons::Sun:
7+
if (isNight) {
8+
return Symbols::moon;
9+
}
610
return Symbols::sun;
711
break;
812
case Pinetime::Controllers::SimpleWeatherService::Icons::CloudsSun:
13+
if (isNight) {
14+
return Symbols::cloudMoon;
15+
}
916
return Symbols::cloudSun;
1017
break;
1118
case Pinetime::Controllers::SimpleWeatherService::Icons::Clouds:
@@ -24,6 +31,9 @@ const char* Pinetime::Applications::Screens::Symbols::GetSymbol(const Pinetime::
2431
return Symbols::cloudShowersHeavy;
2532
break;
2633
case Pinetime::Controllers::SimpleWeatherService::Icons::CloudSunRain:
34+
if (isNight) {
35+
return Symbols::cloudMoonRain;
36+
}
2737
return Symbols::cloudSunRain;
2838
break;
2939
case Pinetime::Controllers::SimpleWeatherService::Icons::Smog:

src/displayapp/screens/WeatherSymbols.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace Pinetime {
66
namespace Applications {
77
namespace Screens {
88
namespace Symbols {
9-
const char* GetSymbol(const Pinetime::Controllers::SimpleWeatherService::Icons icon);
9+
const char* GetSymbol(const Pinetime::Controllers::SimpleWeatherService::Icons icon, const bool isNight);
1010
const char* GetCondition(const Pinetime::Controllers::SimpleWeatherService::Icons icon);
1111
}
1212
}

0 commit comments

Comments
 (0)