Skip to content

Commit e030011

Browse files
authored
Merge branch 'main' into main
2 parents 1c1f0d0 + 6572b50 commit e030011

32 files changed

+443
-139
lines changed

CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
cmake_minimum_required(VERSION 3.10)
22

33
set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose Debug or Release")
4+
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
45

5-
project(pinetime VERSION 1.15.0 LANGUAGES C CXX ASM)
6+
project(pinetime VERSION 1.16.0 LANGUAGES C CXX ASM)
67

78
set(CMAKE_C_STANDARD 99)
89
set(CMAKE_CXX_STANDARD 20)

doc/SimpleWeatherService.md

Lines changed: 14 additions & 5 deletions
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,13 @@ The byte array must contain the following data:
4345
- 6 = Thunderstorm
4446
- 7 = Snow
4547
- 8 = Mist, smog
48+
- [49, 50] : Sunrise (number of minutes elapsed since midnight)
49+
- `0` sun already up when day starts
50+
- `-1` unknown
51+
- `-2` no sunrise (e.g. polar night)
52+
- [51, 52] : Sunset (number of minutes elapsed since midnight)
53+
- `-1` unknown
54+
- `-2` no sunset (e.g. polar day)
4655

4756
### Forecast
4857

doc/buildWithDocker.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,3 +87,9 @@ Here's an example for `pinetime-app`:
8787
```sh
8888
docker run --rm -it -v ${PWD}:/sources --user $(id -u):$(id -g) infinitime-build /opt/build.sh pinetime-app
8989
```
90+
91+
If you want to change the apps and/or watchfaces built in the project, you can pass `ENABLE_USERAPPS` and `ENABLE_WATCHFACES` as environment variables like so:
92+
93+
```sh
94+
docker run --rm -it -v ${PWD}:/sources -e ENABLE_USERAPPS="Apps::Alarm,Apps::Timer,Apps::Steps,Apps::HeartRate,Apps::Music,Apps::Navigation" infinitime-build
95+
```

doc/code/Intro.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ This page is meant to guide you through the source code, so you can find the rel
77
Infinitime is based on FreeRTOS, a real-time operating system.
88
FreeRTOS provides several quality of life abstractions (for example easy software timers)
99
and most importantly supports multiple tasks.
10-
If you want to read up on real-time operating systems, you can look [here](https://www.freertos.org/implementation/a00002.html) and [here](https://www.freertos.org/features.html).
10+
If you want to read up on real-time operating systems, you can look [here](https://www.freertos.org/Documentation/01-FreeRTOS-quick-start/01-Beginners-guide/01-RTOS-fundamentals) and [here](https://www.freertos.org/features.html).
1111
The main "process" creates at least one task and then starts the FreeRTOS task scheduler.
1212
This main "process" is the standard main() function inside [main.cpp](/src/main.cpp).
1313
The task scheduler is responsible for giving every task enough cpu time.

docker/build.sh

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,14 +77,19 @@ GetNrfSdk() {
7777
}
7878

7979
CmakeGenerate() {
80+
CMAKE_ARGS=()
81+
[ -n "$ENABLE_USERAPPS" ] && CMAKE_ARGS+=("-DENABLE_USERAPPS=$ENABLE_USERAPPS")
82+
[ -n "$ENABLE_WATCHFACES" ] && CMAKE_ARGS+=("-DENABLE_WATCHFACES=$ENABLE_WATCHFACES")
83+
8084
cmake -G "Unix Makefiles" \
8185
-S "$SOURCES_DIR" \
8286
-B "$BUILD_DIR" \
8387
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
8488
-DARM_NONE_EABI_TOOLCHAIN_PATH="$TOOLS_DIR/$GCC_ARM_PATH" \
8589
-DNRF5_SDK_PATH="$TOOLS_DIR/$NRF_SDK_VER" \
8690
-DBUILD_DFU=1 \
87-
-DBUILD_RESOURCES=1
91+
-DBUILD_RESOURCES=1 \
92+
${CMAKE_ARGS[@]}
8893
}
8994

9095
CmakeBuild() {

src/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,6 @@ list(APPEND SOURCE_FILES
431431
displayapp/screens/WatchFaceCasioStyleG7710.cpp
432432
displayapp/screens/WatchFaceCasioStyleAE21W.cpp
433433
displayapp/screens/WatchFacePrideFlag.cpp
434-
displayapp/screens/WatchFaceCasioStyleAE21W.cpp
435434

436435
##
437436

src/components/ble/SimpleWeatherService.cpp

Lines changed: 68 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,48 @@ namespace {
4141
SimpleWeatherService::Location cityName;
4242
std::memcpy(cityName.data(), &dataBuffer[16], 32);
4343
cityName[32] = '\0';
44+
int16_t sunrise = -1;
45+
int16_t sunset = -1;
46+
if (dataBuffer[1] > 0) {
47+
int16_t bufferSunrise = ToInt16(&dataBuffer[49]);
48+
int16_t bufferSunset = ToInt16(&dataBuffer[51]);
49+
50+
// Sunrise/sunset format
51+
52+
// Assume sun is down at minute 0 / midnight
53+
54+
// 0<=x<1440 sunrise happens this many minutes into the day
55+
// (0 day starts with sun up)
56+
// -1 unknown
57+
// -2 sun not rising today
58+
59+
// 0<x<1440 sunset happens this many minutes into the day
60+
// -1 unknown
61+
// -2 sun not setting today
62+
63+
// Check if the weather data is well formed
64+
// Disable boolean simplification suggestion, as simplifying it makes it unreadable
65+
if (!( // NOLINT(readability-simplify-boolean-expr)
66+
// Fail if either unknown
67+
(bufferSunrise == -1 || bufferSunset == -1)
68+
// Cannot be out of range
69+
|| (bufferSunrise < -2 || bufferSunrise > 1439 || bufferSunset < -2 || bufferSunset > 1439)
70+
// Cannot have sunset without sunrise
71+
|| (bufferSunrise == -2 && bufferSunset != -2)
72+
// Cannot have sunset before sunrise
73+
|| (bufferSunrise >= bufferSunset && bufferSunrise >= 0 && bufferSunset >= 0))) {
74+
sunrise = bufferSunrise;
75+
sunset = bufferSunset;
76+
}
77+
}
4478
return SimpleWeatherService::CurrentWeather(ToUInt64(&dataBuffer[2]),
4579
SimpleWeatherService::Temperature(ToInt16(&dataBuffer[10])),
4680
SimpleWeatherService::Temperature(ToInt16(&dataBuffer[12])),
4781
SimpleWeatherService::Temperature(ToInt16(&dataBuffer[14])),
4882
SimpleWeatherService::Icons {dataBuffer[16 + 32]},
49-
std::move(cityName));
83+
std::move(cityName),
84+
sunrise,
85+
sunset);
5086
}
5187

5288
SimpleWeatherService::Forecast CreateForecast(const uint8_t* dataBuffer) {
@@ -94,7 +130,7 @@ int SimpleWeatherService::OnCommand(struct ble_gatt_access_ctxt* ctxt) {
94130

95131
switch (GetMessageType(dataBuffer)) {
96132
case MessageType::CurrentWeather:
97-
if (GetVersion(dataBuffer) == 0) {
133+
if (GetVersion(dataBuffer) <= 1) {
98134
currentWeather = CreateCurrentWeather(dataBuffer);
99135
NRF_LOG_INFO("Current weather :\n\tTimestamp : %d\n\tTemperature:%d\n\tMin:%d\n\tMax:%d\n\tIcon:%d\n\tLocation:%s",
100136
currentWeather->timestamp,
@@ -103,6 +139,9 @@ int SimpleWeatherService::OnCommand(struct ble_gatt_access_ctxt* ctxt) {
103139
currentWeather->maxTemperature.PreciseCelsius(),
104140
currentWeather->iconId,
105141
currentWeather->location.data());
142+
if (GetVersion(dataBuffer) == 1) {
143+
NRF_LOG_INFO("Sunrise: %d\n\tSunset: %d", currentWeather->sunrise, currentWeather->sunset);
144+
}
106145
}
107146
break;
108147
case MessageType::Forecast:
@@ -153,10 +192,36 @@ std::optional<SimpleWeatherService::Forecast> SimpleWeatherService::GetForecast(
153192
return {};
154193
}
155194

195+
bool SimpleWeatherService::IsNight() const {
196+
if (currentWeather && currentWeather->sunrise != -1 && currentWeather->sunset != -1) {
197+
auto currentTime = dateTimeController.CurrentDateTime().time_since_epoch();
198+
199+
// Get timestamp for last midnight
200+
auto midnight = std::chrono::floor<std::chrono::days>(currentTime);
201+
202+
// Calculate minutes since midnight
203+
auto currentMinutes = std::chrono::duration_cast<std::chrono::minutes>(currentTime - midnight).count();
204+
205+
// Sun not rising today => night all hours
206+
if (currentWeather->sunrise == -2) {
207+
return true;
208+
}
209+
// Sun not setting today => check before sunrise
210+
if (currentWeather->sunset == -2) {
211+
return currentMinutes < currentWeather->sunrise;
212+
}
213+
214+
// Before sunrise or after sunset
215+
return currentMinutes < currentWeather->sunrise || currentMinutes >= currentWeather->sunset;
216+
}
217+
218+
return false;
219+
}
220+
156221
bool SimpleWeatherService::CurrentWeather::operator==(const SimpleWeatherService::CurrentWeather& other) const {
157222
return this->iconId == other.iconId && this->temperature == other.temperature && this->timestamp == other.timestamp &&
158223
this->maxTemperature == other.maxTemperature && this->minTemperature == other.maxTemperature &&
159-
std::strcmp(this->location.data(), other.location.data()) == 0;
224+
std::strcmp(this->location.data(), other.location.data()) == 0 && this->sunrise == other.sunrise && this->sunset == other.sunset;
160225
}
161226

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

src/components/ble/SimpleWeatherService.h

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
#include "components/datetime/DateTimeController.h"
3535
#include <lvgl/lvgl.h>
3636
#include "displayapp/InfiniTimeTheme.h"
37+
#include "utility/Math.h"
38+
3739

3840
int WeatherCallback(uint16_t connHandle, uint16_t attrHandle, struct ble_gatt_access_ctxt* ctxt, void* arg);
3941

@@ -77,11 +79,23 @@ namespace Pinetime {
7779
}
7880

7981
[[nodiscard]] int16_t Celsius() const {
80-
return (PreciseCelsius() + 50) / 100;
82+
return Utility::RoundedDiv(PreciseCelsius(), static_cast<int16_t>(100));
8183
}
8284

8385
[[nodiscard]] int16_t Fahrenheit() const {
84-
return (PreciseFahrenheit() + 50) / 100;
86+
return Utility::RoundedDiv(PreciseFahrenheit(), static_cast<int16_t>(100));
87+
}
88+
89+
[[nodiscard]] lv_color_t Color() const {
90+
int16_t celsius = Celsius();
91+
if (celsius <= 0) { // freezing
92+
return Colors::blue;
93+
} else if (celsius <= 4) { // ice
94+
return LV_COLOR_CYAN;
95+
} else if (celsius >= 27) { // hot
96+
return Colors::deepOrange;
97+
}
98+
return Colors::orange; // normal
8599
}
86100

87101
[[nodiscard]] lv_color_t Color() const {
@@ -112,13 +126,17 @@ namespace Pinetime {
112126
Temperature minTemperature,
113127
Temperature maxTemperature,
114128
Icons iconId,
115-
Location&& location)
129+
Location&& location,
130+
int16_t sunrise,
131+
int16_t sunset)
116132
: timestamp {timestamp},
117133
temperature {temperature},
118134
minTemperature {minTemperature},
119135
maxTemperature {maxTemperature},
120136
iconId {iconId},
121-
location {std::move(location)} {
137+
location {std::move(location)},
138+
sunrise {sunrise},
139+
sunset {sunset} {
122140
}
123141

124142
uint64_t timestamp;
@@ -127,6 +145,8 @@ namespace Pinetime {
127145
Temperature maxTemperature;
128146
Icons iconId;
129147
Location location;
148+
int16_t sunrise;
149+
int16_t sunset;
130150

131151
bool operator==(const CurrentWeather& other) const;
132152
};
@@ -151,6 +171,8 @@ namespace Pinetime {
151171
std::optional<CurrentWeather> Current() const;
152172
std::optional<Forecast> GetForecast() const;
153173

174+
[[nodiscard]] bool IsNight() const;
175+
154176
private:
155177
// 00050000-78fc-48fe-8e23-433b3a1942d0
156178
static constexpr ble_uuid128_t BaseUuid() {

src/components/motor/MotorController.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ void MotorController::StopRinging() {
3434
nrf_gpio_pin_set(PinMap::Motor);
3535
}
3636

37+
bool MotorController::IsRinging() {
38+
return (xTimerIsTimerActive(longVib) == pdTRUE);
39+
}
40+
3741
void MotorController::StopMotor(TimerHandle_t /*xTimer*/) {
3842
nrf_gpio_pin_set(PinMap::Motor);
3943
}

src/components/motor/MotorController.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ namespace Pinetime {
1515
void RunForDuration(uint8_t motorDuration);
1616
void StartRinging();
1717
void StopRinging();
18+
bool IsRinging();
1819

1920
private:
2021
static void Ring(TimerHandle_t xTimer);

0 commit comments

Comments
 (0)