Skip to content

Commit 0d397ea

Browse files
committed
v1.1.0
- add volume control commands #1 - add ringer callback function - remove setLogging() - add screen configuration - add high & low temperature for weather - restructured internal data handling
1 parent e3bb1a4 commit 0d397ea

File tree

8 files changed

+503
-267
lines changed

8 files changed

+503
-267
lines changed

ChronosESP32.cpp

Lines changed: 328 additions & 244 deletions
Large diffs are not rendered by default.

ChronosESP32.h

Lines changed: 71 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,18 @@
4040
#define NOTIF_SIZE 10
4141
#define WEATHER_SIZE 7
4242
#define ALARM_SIZE 8
43+
#define DATA_SIZE 512
4344

4445
#define MUSIC_PLAY 0x9D00
4546
#define MUSIC_PAUSE 0x9D01
4647
#define MUSIC_PREVIOUS 0x9D02
4748
#define MUSIC_NEXT 0x9D03
4849
#define MUSIC_TOGGLE 0x9900
4950

51+
#define VOLUME_UP 0x99A1
52+
#define VOLUME_DOWN 0x99A2
53+
#define VOLUME_MUTE 0x99A3
54+
5055
struct Notification
5156
{
5257
int icon;
@@ -60,15 +65,23 @@ struct Weather
6065
int icon;
6166
int day;
6267
int temp;
68+
int high;
69+
int low;
6370
};
6471

65-
struct ChronosESP32Timer
72+
struct ChronosTimer
6673
{
6774
unsigned long time;
6875
long duration = 5000;
6976
bool active;
7077
};
7178

79+
struct ChronosData
80+
{
81+
int length;
82+
uint8_t data[DATA_SIZE];
83+
};
84+
7285
struct Alarm
7386
{
7487
uint8_t hour;
@@ -98,15 +111,55 @@ enum Config
98111
CF_CAMERA // camera config, (ready state)
99112
};
100113

114+
/*
115+
The screen configurations below is only used for identification on the Chronos app.
116+
Under the watch tab, when you click on watch info you can see the detected screen configuration.
117+
The primary purpose of this configuration is to aid in loading watchfaces on supported watches with the correct resolution.
118+
ChronosESP32 library is implementing this for future development
119+
*/
120+
enum ChronosScreen
121+
{
122+
// Resolution(240x240), Size in inches(1.3), Type(0 - Round [C], 1 - Square [S], 2 - Rectangular [R])
123+
CS_0x0_000_CFF = 0, // default no config
124+
CS_240x240_130_STF = 1, // 240x240, 1.3 inches, Square, True, False
125+
CS_240x240_130_STT = 2, // 240x240, 1.3 inches, Square, True, True
126+
CS_80x160_096_RTF = 3, // 80x160, 0.96 inches, Rectangular, True, False
127+
CS_80x160_096_RTT = 4, // 80x160, 0.96 inches, Rectangular, True, True
128+
CS_135x240_114_RTF = 5, // 135x240, 1.14 inches, Rectangular, True, False
129+
CS_135x240_114_RTT = 6, // 135x240, 1.14 inches, Rectangular, True, True
130+
CS_240x240_128_CTF = 7, // 240x240, 1.28 inches, Round, True, False
131+
CS_240x240_128_CTT = 8, // 240x240, 1.28 inches, Round, True, True
132+
CS_240x288_157_RTF = 9, // 240x288, 1.57 inches, Rectangular, True, False
133+
CS_240x288_157_RTT = 10, // 240x288, 1.57 inches, Rectangular, True, True
134+
CS_240x283_172_RTF = 11, // 240x283, 1.72 inches, Rectangular, True, False
135+
CS_240x283_172_RTT = 12, // 240x283, 1.72 inches, Rectangular, True, True
136+
CS_360x360_130_CTF = 13, // 360x360, 1.3 inches, Round, True, False
137+
CS_360x360_130_CTT = 14, // 360x360, 1.3 inches, Round, True, True
138+
CS_320x380_177_RTF = 15, // 320x380, 1.77 inches, Rectangular, True, False
139+
CS_320x380_177_RTT = 16, // 320x380, 1.77 inches, Rectangular, True, True
140+
CS_320x385_175_RTF = 17, // 320x385, 1.75 inches, Rectangular, True, False
141+
CS_320x385_175_RTT = 18, // 320x385, 1.75 inches, Rectangular, True, True
142+
CS_320x360_160_RTF = 19, // 320x360, 1.6 inches, Rectangular, True, False
143+
CS_320x360_160_RTT = 20, // 320x360, 1.6 inches, Rectangular, True, True
144+
CS_240x296_191_RTF = 21, // 240x296, 1.91 inches, Rectangular, True, False
145+
CS_240x296_191_RTT = 22, // 240x296, 1.91 inches, Rectangular, True, True
146+
CS_412x412_145_CTF = 23, // 412x412, 1.45 inches, Round, True, False
147+
CS_412x412_145_CTT = 24, // 412x412, 1.45 inches, Round, True, True
148+
CS_410x494_200_RTF = 25, // 410x494, 2.0 inches, Rectangular, True, False
149+
CS_410x494_200_RTT = 32, // 410x494, 2.0 inches, Rectangular, True, True
150+
CS_466x466_143_CTF = 33, // 466x466, 1.43 inches, Round, True, False
151+
CS_466x466_143_CTT = 34 // 466x466, 1.43 inches, Round, True, True
152+
};
153+
154+
101155
class ChronosESP32 : public BLEServerCallbacks, public BLECharacteristicCallbacks, public ESP32Time
102156
{
103157

104158
public:
105159
ChronosESP32();
106-
ChronosESP32(String name); // set the BLE name
160+
ChronosESP32(String name, ChronosScreen screen = CS_240x240_128_CTF); // set the BLE name
107161
void begin(); // initializes BLE
108162
void loop(); // handles routine functions
109-
void setLogging(bool state); // to view raw data receive over BLE
110163

111164
// watch
112165
bool isConnected();
@@ -134,6 +187,7 @@ class ChronosESP32 : public BLEServerCallbacks, public BLECharacteristicCallback
134187
// control
135188
void sendCommand(uint8_t *command, size_t length);
136189
void musicControl(uint16_t command);
190+
void setVolume(uint8_t level);
137191
bool capturePhoto();
138192
void findPhone(bool state);
139193

@@ -145,24 +199,22 @@ class ChronosESP32 : public BLEServerCallbacks, public BLECharacteristicCallback
145199
// callbacks
146200
void setConnectionCallback(void (*callback)(bool));
147201
void setNotificationCallback(void (*callback)(Notification));
202+
void setRingerCallback(void (*callback)(String, bool));
148203
void setConfigurationCallback(void (*callback)(Config, uint32_t, uint32_t));
149204
void setDataCallback(void (*callback)(uint8_t *, int));
205+
void setRawDataCallback(void (*callback)(uint8_t *, int));
150206

151207
private:
152208
String watchName = "Chronos ESP32";
153209
String address;
154210
uint8_t batteryLevel;
155211
bool connected;
156212
bool batteryChanged;
157-
bool logging;
158213
bool hour24;
159214
bool cameraReady;
160215

161-
bool receiving;
162-
163216
Notification notifications[NOTIF_SIZE];
164217
int notificationIndex;
165-
int msgLen = 0;
166218

167219
Weather weather[WEATHER_SIZE];
168220
String weatherCity;
@@ -171,13 +223,20 @@ class ChronosESP32 : public BLEServerCallbacks, public BLECharacteristicCallback
171223

172224
Alarm alarms[ALARM_SIZE];
173225

174-
ChronosESP32Timer infoTimer;
175-
ChronosESP32Timer findTimer;
226+
ChronosTimer infoTimer;
227+
ChronosTimer findTimer;
228+
ChronosTimer ringerTimer;
229+
230+
ChronosData incomingData;
231+
232+
ChronosScreen screenConf = CS_240x240_128_CTF;
176233

177234
void (*connectionChangeCallback)(bool) = nullptr;
178235
void (*notificationReceivedCallback)(Notification) = nullptr;
236+
void (*ringerAlertCallback)(String, bool) = nullptr;
179237
void (*configurationReceivedCallback)(Config, uint32_t, uint32_t) = nullptr;
180238
void (*dataReceivedCallback)(uint8_t *, int) = nullptr;
239+
void (*rawDataReceivedCallback)(uint8_t *, int) = nullptr;
181240

182241
void sendInfo();
183242
void sendBattery();
@@ -190,6 +249,9 @@ class ChronosESP32 : public BLEServerCallbacks, public BLECharacteristicCallback
190249

191250
// from BLECharacteristicCallbacks
192251
virtual void onWrite(BLECharacteristic *pCharacteristic);
252+
253+
void dataReceived();
254+
193255
};
194256

195257
#endif

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ Setup your ESP32 as a smartwatch and connect to Chronos app over BLE.
2424
```
2525
ChronosESP32();
2626
ChronosESP32(String name); // set the BLE name
27+
ChronosESP32(String name, ChronosScreen screen); // set the BLE name and screen configuration
2728
void begin(); // initializes BLE
2829
void loop(); // handles routine functions
29-
void setLogging(bool state); // to view raw data receive over BLE
3030
3131
// watch
3232
bool isConnected();
@@ -54,6 +54,7 @@ void setAlarm(int index, Alarm alarm);
5454
// control
5555
void sendCommand(uint8_t *command, size_t length);
5656
void musicControl(uint16_t command);
57+
void setVolume(uint8_t level);
5758
bool capturePhoto();
5859
void findPhone(bool state);
5960
@@ -67,6 +68,7 @@ void setConnectionCallback(void (*callback)(bool));
6768
void setNotificationCallback(void (*callback)(Notification));
6869
void setConfigurationCallback(void (*callback)(Config, uint32_t, uint32_t));
6970
void setDataCallback(void (*callback)(uint8_t *, int));
71+
void setRawDataCallback(void (*callback)(uint8_t *, int));
7072
```
7173

7274
## Dependencies

examples/control/control.ino

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,11 @@ void loop()
8181
{
8282
buttonPressed = false;
8383
// music control,
84-
watch.musicControl(MUSIC_TOGGLE); // MUSIC_PLAY, MUSIC_PAUSE, MUSIC_PREVIOUS, MUSIC_NEXT, MUSIC_TOGGLE
84+
watch.musicControl(MUSIC_TOGGLE); // MUSIC_PLAY, MUSIC_PAUSE, MUSIC_PREVIOUS, MUSIC_NEXT, MUSIC_TOGGLE, VOLUME_UP, VOLUME_DOWN, VOLUME_MUTE
8585
Serial.println("Sent music command");
8686

87+
// watch.setVolume(50); // set the music volume [0-100] (expreimental)
88+
8789
// find phone
8890
// watch.findPhone(true); // true -> ring the phone, false -> stop the ringing, the ringing will also be stopped automatically after 10 seconds;
8991
}

examples/watch/watch.ino

Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434

3535
ChronosESP32 watch;
3636
// ChronosESP32 watch("Chronos Watch"); // set the bluetooth name
37+
// ChronosESP32 watch("Chronos Watch", CS_360x360_130_CTF); // set the bluetooth name and screen configuration
3738

3839
void connectionCallback(bool state)
3940
{
@@ -48,12 +49,25 @@ void notificationCallback(Notification notification)
4849
Serial.println(notification.time);
4950
Serial.print("From: ");
5051
Serial.print(notification.app);
51-
Serial.print("\t Icon->");
52+
Serial.print("\tIcon: ");
5253
Serial.println(notification.icon);
5354
Serial.println(notification.message);
5455
// see loop on how to access notifications
5556
}
5657

58+
void ringerCallback(String caller, bool state)
59+
{
60+
if (state)
61+
{
62+
Serial.print("Ringer: Incoming call from ");
63+
Serial.println(caller);
64+
}
65+
else
66+
{
67+
Serial.println("Ringer dismissed");
68+
}
69+
}
70+
5771
void configCallback(Config config, uint32_t a, uint32_t b)
5872
{
5973
switch (config)
@@ -197,11 +211,38 @@ void configCallback(Config config, uint32_t a, uint32_t b)
197211
break;
198212
case CF_WEATHER:
199213
// weather is saved
200-
Serial.print("Weather received: ");
214+
Serial.println("Weather received");
201215
if (a)
202216
{
203-
Serial.print("Forecast");
204-
// see loop for weather details
217+
// if a == 1, high & low temperature values might not yet be updated
218+
if (a == 2)
219+
{
220+
int n = watch.getWeatherCount();
221+
String updateTime = watch.getWeatherTime();
222+
Serial.print("Weather Count: ");
223+
Serial.print(n);
224+
Serial.print("\tUpdated at: ");
225+
Serial.println(updateTime);
226+
227+
for (int i = 0; i < n; i++)
228+
{
229+
// iterate through available notifications, index 0 is the latest received notification
230+
Weather w = watch.getWeatherAt(i);
231+
Serial.print("Day:"); // day of the week (0 - 6)
232+
Serial.print(w.day);
233+
Serial.print("\tIcon:");
234+
Serial.print(w.icon);
235+
Serial.print("\t");
236+
Serial.print(w.temp);
237+
Serial.print("°C");
238+
Serial.print("\tHigh:");
239+
Serial.print(w.high);
240+
Serial.print("°C");
241+
Serial.print("\tLow:");
242+
Serial.print(w.low);
243+
Serial.println("°C");
244+
}
245+
}
205246
}
206247
if (b)
207248
{
@@ -228,9 +269,10 @@ void setup()
228269
{
229270
Serial.begin(115200);
230271

231-
watch.setLogging(false); // to view the raw received data over BLE (use the data callback instead)
272+
// set the callbacks before calling begin funtion
232273
watch.setConnectionCallback(connectionCallback);
233274
watch.setNotificationCallback(notificationCallback);
275+
watch.setRingerCallback(ringerCallback);
234276
watch.setConfigurationCallback(configCallback);
235277
watch.setDataCallback(dataCallback);
236278

@@ -242,8 +284,10 @@ void setup()
242284

243285
watch.setBattery(80); // set the battery level, will be synced to the app
244286

287+
// watch.clearNotifications();
288+
245289
watch.set24Hour(true); // the 24 hour mode will be overwritten when the command is received from the app
246-
// this modifies the return of
290+
// this modifies the return of the functions below
247291
watch.getAmPmC(true); // 12 hour mode false->(am/pm), true->(AM/PM), if 24 hour mode returns empty string ("")
248292
watch.getHourC(); // (0-12), (0-23)
249293
watch.getHourZ(); // zero padded hour (00-12), (00-23)
@@ -313,7 +357,13 @@ void loop()
313357
Serial.print(w.icon);
314358
Serial.print("\t");
315359
Serial.print(w.temp);
316-
Serial.println("C");
360+
Serial.print("°C");
361+
Serial.print("\tHigh: ");
362+
Serial.print(w.high);
363+
Serial.print("°C");
364+
Serial.print("\tLow: ");
365+
Serial.print(w.low);
366+
Serial.println("°C");
317367
}
318368
*/
319369
}

keywords.txt

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@ getAlarm KEYWORD2
1515
setAlarm KEYWORD2
1616
setConnectionCallback KEYWORD2
1717
setNotificationCallback KEYWORD2
18+
setRingerCallback KEYWORD2
1819
setConfigurationCallback KEYWORD2
1920
setDataCallback KEYWORD2
20-
setLogging KEYWORD2
21+
setRawDataCallback KEYWORD2
22+
setVolume KEYWORD2
2123
setBattery KEYWORD2
2224
set24Hour KEYWORD2
2325
getAmPmC KEYWORD2
@@ -30,13 +32,18 @@ capturePhoto KEYWORD2
3032
Notification LITERAL1
3133
Alarm LITERAL1
3234
Weather LITERAL1
33-
ChronosESP32Timer LITERAL1
35+
ChronosTimer LITERAL1
36+
ChronosData LITERAL1
37+
ChronosScreen LITERAL1
3438

3539
MUSIC_PLAY LITERAL1
3640
MUSIC_PAUSE LITERAL1
3741
MUSIC_PREVIOUS LITERAL1
3842
MUSIC_NEXT LITERAL1
3943
MUSIC_TOGGLE LITERAL1
44+
VOLUME_UP LITERAL1
45+
VOLUME_DOWN LITERAL1
46+
VOLUME_MUTE LITERAL1
4047

4148
CF_TIME LITERAL1
4249
CF_RTW LITERAL1
@@ -54,4 +61,33 @@ CF_SLEEP LITERAL1
5461
CF_QUIET LITERAL1
5562
CF_WATER LITERAL1
5663
CF_WEATHER LITERAL1
57-
CF_CAMERA LITERAL1
64+
CF_CAMERA LITERAL1
65+
66+
CS_0x0_000_CFF LITERAL1
67+
CS_240x240_130_STF LITERAL1
68+
CS_240x240_130_STT LITERAL1
69+
CS_80x160_096_RTF LITERAL1
70+
CS_80x160_096_RTT LITERAL1
71+
CS_135x240_114_RTF LITERAL1
72+
CS_135x240_114_RTT LITERAL1
73+
CS_240x240_128_CTF LITERAL1
74+
CS_240x240_128_CTT LITERAL1
75+
CS_240x288_157_RTF LITERAL1
76+
CS_240x288_157_RTT LITERAL1
77+
CS_240x283_172_RTF LITERAL1
78+
CS_240x283_172_RTT LITERAL1
79+
CS_360x360_130_CTT LITERAL1
80+
CS_320x380_177_RTF LITERAL1
81+
CS_320x380_177_RTT LITERAL1
82+
CS_320x385_175_RTF LITERAL1
83+
CS_320x385_175_RTT LITERAL1
84+
CS_320x360_160_RTF LITERAL1
85+
CS_320x360_160_RTT LITERAL1
86+
CS_240x296_191_RTF LITERAL1
87+
CS_240x296_191_RTT LITERAL1
88+
CS_412x412_145_CTF LITERAL1
89+
CS_412x412_145_CTT LITERAL1
90+
CS_410x494_200_RTF LITERAL1
91+
CS_410x494_200_RTT LITERAL1
92+
CS_466x466_143_CTF LITERAL1
93+
CS_466x466_143_CTT LITERAL1

0 commit comments

Comments
 (0)