Skip to content

Commit 495a3f2

Browse files
Merge pull request #3 from olek-osikowicz/projects
Update Sleep Breeze Project
2 parents 23f9b64 + 2532bb8 commit 495a3f2

File tree

1 file changed

+42
-13
lines changed

1 file changed

+42
-13
lines changed

_projects/sleep_breeze.md

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,20 @@ description: Bluetooth wake-up light mobile app
55
img: assets/img/sleep_breeze/video.gif
66
importance: 1
77
category: work
8-
tags: [React Native, Expo, Bluetooth Low Energy]
8+
tags: [ReactNative, Expo, BluetoothLowEnergy]
99
related_blog_posts: false
1010
---
1111

12-
<div class="row">
13-
<div class="col-12 col-md-8">
12+
<div class="row align-items-center">
13+
<div class="col-12 col-md-8 d-flex flex-column justify-content-center">
1414
<p>
1515
I am the developer behind <a href="https://sleepbreeze.eu/">SleepBreeze</a>, a sunrise alarm lamp designed to simulate natural daylight and support a gentle wake-up experience. The lamp gradually increases brightness and color temperature in the minutes leading up to the alarm.
1616
</p>
1717
<p>
18-
I designed and implemented a production-ready, cross-platform mobile application in React Native (Expo) that controls the device over Bluetooth Low Energy (BLE). The app supports both iOS and Android and is currently available on the Polish market.
18+
I designed and implemented a production-ready, cross-platform mobile application in React Native (Expo) that controls the device over Bluetooth Low Energy (BLE). The app supports both iOS and Android and has been shipped to first users on the Polish market.
1919
</p>
2020
</div>
21-
<div class="col-6 col-md-4">
21+
<div class="col-12 col-md-4">
2222
{% include video.liquid path="assets/img/sleep_breeze/sunrise_video_cropped.mp4"
2323
class="img-fluid rounded z-depth-1"
2424
controls=true autoplay=true %}
@@ -28,7 +28,7 @@ related_blog_posts: false
2828
</div>
2929
</div>
3030

31-
## Key features
31+
# Key features
3232

3333
- Bluetooth LE device discovery, pairing, and reconnection
3434
- Full light control: power, brightness, color temperature, and RGB (where supported)
@@ -53,14 +53,43 @@ related_blog_posts: false
5353
Selected screens from the Android and iOS applications.
5454
</div>
5555

56-
## Technical highlights
57-
58-
- Reverse-engineered the BLE communication protocol of the smart bulb, including service/characteristic discovery and low-level byte-level command encoding
59-
- Built custom native modules for Android and iOS to ensure reliable alarm execution despite OS-level battery optimizations and background execution limits
60-
- Designed a robust app architecture supporting unreliable BLE connections and device state recovery
61-
62-
## Links
56+
# Links
6357

6458
- 🌐 [Official website](https://sleepbreeze.eu/)
6559
- 📱 [App store listing](https://apps.apple.com/pl/app/sleep-breeze/id6744585835)
6660
- 📸 [Instagram](https://www.instagram.com/sleepbreeze.eu/)
61+
62+
# Tech stack
63+
64+
- React Native `0.79`
65+
- Expo SDK `53`
66+
- react-native-ble-plx `3.2.1` for connecting with Bluetooth LE devices
67+
- Lightbulb: Philips HUE, RGB, White-Ambience, Warm-white models
68+
69+
---
70+
71+
# Retrospective
72+
73+
### Bluetooth Low Energy integration
74+
75+
Working with undocumented BLE devices like Philips HUE, with no official documentation of communication protocols is never a pleasure. To understand inner workings of peripheral devices, I had to reverse-engineer the BLE protocols by sniffing Bluetooth packets and analysing them in [Wireshark](https://www.wireshark.org/).
76+
77+
This experience thought me a lot about the BLE protocol itself, reverse engineering and low-level communication with IoT devices in general.
78+
79+
### Implementing robust alarm functionality
80+
81+
One of the clients requirements was to have a reliable sound alarm functionality that would trigger along the sunrise alarm. I didn't expect this to be such big of a challenge, but quickly realised that mobile OS-es are quite restrictive when it comes to background task execution. Especially developing a React Native app adds another layer of complexity and abstractions from the native APIs.
82+
83+
As the platforms don't expose native APIs to schedule built in alarms from 3rd party apps, I had to find some working solutions.
84+
One of the initial approaches was to use repeated notifications (either local or push) with sound to wake up user on time. However, one of the clients requirements was to have the alarm sound gradually increase in volume for a longer period of time (e.g., 3 minutes) for a gentle wake-up experience. Unfortunately notification don't support either long sound playback or volume control, and could be easly muted by the user.
85+
86+
Therefore, I resorted to media playback in the background as the music apps do. This would allow playing arbitrary sound files and provide volume control. However problem remains of having reliable background trigger to play the sound at the right time.
87+
88+
On iOS, I noticed that the JS runtime doesn't get suspended if there is an active audio playback session.
89+
This key observation allowed me to implement a workaround: When user sets the alarm, the app immediately starts playing a "sleep music" audio file at very low volume in the background. This keeps the JS runtime active and allows to use plain `setTimeout` to schedule the proper alarm playback at the right time.
90+
91+
On Android however this approach didn't work as JS runtime gets suspended more aggressively and the OS battery optimization [depends on the manufacturer](https://dontkillmyapp.com/).
92+
Fortunately there is Android specific API of foreground services, which allows to run long-running background tasks. This is used by the apps like Uber to give you notifications about your ride even when the app is not in the foreground.
93+
Therefore I used that to implement a foreground service that gets started when user sets the alarm. Then I set a callback task to be executed at the alarm time, which starts the gradual sound playback and notifies the user.
94+
95+
To summarize, implementing reliable alarm functionality was more challenging that I expected, but I am happy with the final result.

0 commit comments

Comments
 (0)