Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ bool is24Hour();
String getAddress();
void setBattery(uint8_t level, bool charging = false);
bool isCameraReady();
void syncRequest();

// notifications
int getNotificationCount();
Expand All @@ -57,6 +58,7 @@ String getWeatherCity();
String getWeatherTime();
Weather getWeatherAt(int index);
HourlyForecast getForecastHour(int hour);
WeatherLocation getWeatherLocation();

// extras
RemoteTouch getTouch();
Expand Down
14 changes: 13 additions & 1 deletion examples/watch/watch.ino
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,19 @@ void configCallback(Config config, uint32_t a, uint32_t b)
{
Serial.print("City name: ");
String city = watch.getWeatherCity(); //
Serial.print(city);
Serial.println(city);

WeatherLocation loc = watch.getWeatherLocation();
Serial.print("City: ");
Serial.println(loc.city);
Serial.print("Region: ");
Serial.println(loc.region);
Serial.print("Country: ");
Serial.println(loc.country);
Serial.print("Coordinates -> Lat: ");
Serial.print(loc.latitude, 6);
Serial.print("\tLon: ");
Serial.println(loc.longitude, 6);
}
Serial.println();
break;
Expand Down
40 changes: 39 additions & 1 deletion keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ is24Hour KEYWORD2
getAddress KEYWORD2
setBattery KEYWORD2
isCameraReady KEYWORD2
syncRequest KEYWORD2
getNotificationCount KEYWORD2
getNotificationAt KEYWORD2
clearNotifications KEYWORD2
Expand All @@ -22,13 +23,13 @@ getWeatherCity KEYWORD2
getWeatherTime KEYWORD2
getWeatherAt KEYWORD2
getForecastHour KEYWORD2
getWeatherLocation KEYWORD2
getTouch KEYWORD2
getQrAt KEYWORD2
setQr KEYWORD2
getAlarm KEYWORD2
setAlarm KEYWORD2
isAlarmActive KEYWORD2
isAlarmActive KEYWORD2
isAnyAlarmActive KEYWORD2
sendCommand KEYWORD2
musicControl KEYWORD2
Expand Down Expand Up @@ -73,6 +74,7 @@ Control LITERAL1
SleepType LITERAL1
Notification LITERAL1
Weather LITERAL1
WeatherLocation LITERAL1
HourlyForecast LITERAL1
ChronosTimer LITERAL1
ChronosData LITERAL1
Expand Down Expand Up @@ -122,6 +124,7 @@ CF_QR LITERAL1
CF_NAV_DATA LITERAL1
CF_NAV_ICON LITERAL1
CF_CONTACT LITERAL1
CF_SYNCED LITERAL1

HR_STEPS_RECORDS LITERAL1
HR_SLEEP_RECORDS LITERAL1
Expand All @@ -130,3 +133,38 @@ HR_BLOOD_OXYGEN_MEASURE LITERAL1
HR_BLOOD_PRESSURE_MEASURE LITERAL1
HR_MEASURE_ALL LITERAL1

CS_0x0_000_CFF LITERAL1
CS_240x240_130_STF LITERAL1
CS_240x240_130_STT LITERAL1
CS_80x160_096_RTF LITERAL1
CS_80x160_096_RTT LITERAL1
CS_135x240_114_RTF LITERAL1
CS_135x240_114_RTT LITERAL1
CS_240x240_128_CTF LITERAL1
CS_240x240_128_CTT LITERAL1
CS_240x288_157_RTF LITERAL1
CS_240x288_157_RTT LITERAL1
CS_240x283_172_RTF LITERAL1
CS_240x283_172_RTT LITERAL1
CS_360x360_130_CTF LITERAL1
CS_360x360_130_CTT LITERAL1
CS_320x380_177_RTF LITERAL1
CS_320x380_177_RTT LITERAL1
CS_320x385_175_RTF LITERAL1
CS_320x385_175_RTT LITERAL1
CS_320x360_160_RTF LITERAL1
CS_320x360_160_RTT LITERAL1
CS_240x296_191_RTF LITERAL1
CS_240x296_191_RTT LITERAL1
CS_412x412_145_CTF LITERAL1
CS_412x412_145_CTT LITERAL1
CS_410x494_200_RTF LITERAL1
CS_410x494_200_RTT LITERAL1
CS_466x466_143_CTF LITERAL1
CS_466x466_143_CTT LITERAL1
CF_WATCHY_200x200 LITERAL1
CF_ESP32_240x240 LITERAL1
CF_ESP32_466x466 LITERAL1
CF_WEBSCREEN_536x240 LITERAL1
CF_WAVESHARE_410x502 LITERAL1
CF_ZSWATCH_240x240 LITERAL1
2 changes: 1 addition & 1 deletion library.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ChronosESP32",
"version": "1.8.2",
"version": "1.9.0",
"keywords": "Arduino, ESP32, Time, BLE, Watch",
"description": "A library for ESP32 to interface with Chronos app over BLE",
"repository":
Expand Down
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=ChronosESP32
version=1.8.2
version=1.9.0
author=fbiego
maintainer=fbiego
sentence=Setup your ESP32 as a smartwatch and connect to Chronos app over BLE.
Expand Down
1 change: 1 addition & 0 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ src_dir = examples/watch
platform = espressif32
framework = arduino
extra_scripts = post:scripts/copy.py
monitor_speed = 115200

lib_deps =
; use src folder as library
Expand Down
2 changes: 1 addition & 1 deletion scripts/keywords.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def extract_keywords(header_file_path, library_name="ChronosESP32", output_file=
# Enum values
enum_blocks = re.findall(r"enum\s+[a-zA-Z_]\w*\s*{([^}]+)}", full_content, re.DOTALL)
for block in enum_blocks:
enum_values = re.findall(r"\b([A-Z_][A-Z0-9_]*)\b", block)
enum_values = re.findall(r"\b([A-Z_][A-Za-z0-9_]*)\b", block)
for val in enum_values:
output_lines.append(f"{val}\tLITERAL1")
output_lines.append("")
Expand Down
80 changes: 78 additions & 2 deletions src/ChronosESP32.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,14 @@ HourlyForecast ChronosESP32::getForecastHour(int hour)
return _hourlyForecast[hour % FORECAST_SIZE];
}

/*!
@brief return the weather location data
*/
WeatherLocation ChronosESP32::getWeatherLocation()
{
return _weatherLocation;
}

/*!
@brief get the alarm at the index
@param index
Expand Down Expand Up @@ -775,6 +783,15 @@ void ChronosESP32::sendBattery()
sendCommand(batCmd, 8);
}

/*!
@brief request the app to sync settings
*/
void ChronosESP32::syncRequest()
{
uint8_t syncCmd[] = {0xAB, 0x00, 0x03, 0xFE, 0x23, 0x80};
sendCommand(syncCmd, 6);
}

/*!
@brief request the battery level of the phone
*/
Expand Down Expand Up @@ -1384,6 +1401,15 @@ void ChronosESP32::dataReceived()
switch (_incomingData.data[4])
{

case 0x20:
if (_incomingData.data[3] == 0xFE)
{
if (configurationReceivedCallback != nullptr)
{
configurationReceivedCallback(CF_SYNCED, 0, 0);
}
}
break;
case 0x23:
if (configurationReceivedCallback != nullptr)
{
Expand Down Expand Up @@ -1680,11 +1706,16 @@ void ChronosESP32::dataReceived()

break;
case 0x93:
if (configurationReceivedCallback != nullptr)
{
configurationReceivedCallback(CF_TIME, 0, 0);
}

this->setTime(_incomingData.data[13], _incomingData.data[12], _incomingData.data[11], _incomingData.data[10], _incomingData.data[9], _incomingData.data[7] * 256 + _incomingData.data[8]);

if (configurationReceivedCallback != nullptr)
{
configurationReceivedCallback(CF_TIME, 0, 0);
configurationReceivedCallback(CF_TIME, 1, 0);
}
break;
case 0x9C:
Expand Down Expand Up @@ -1906,8 +1937,10 @@ void ChronosESP32::dataReceived()
}
else if (_incomingData.data[0] == 0xEA)
{
if (_incomingData.data[4] == 0x7E)
switch (_incomingData.data[4])
{
case 0x7E:
/* code */
switch (_incomingData.data[5])
{
case 0x01:
Expand Down Expand Up @@ -1948,7 +1981,50 @@ void ChronosESP32::dataReceived()
}
}
break;
} /* END switch (_incomingData.data[5]) */
break;

case 0x7F:
if (_incomingData.data[3] == 0xFE)
{
uint8_t payloadLen = _incomingData.data[6];
const uint8_t *payload = &_incomingData.data[7];

// Read coordinates (Little Endian)
float latitude;
float longitude;
memcpy(&latitude, payload, 4);
memcpy(&longitude, payload + 4, 4);

// Move pointer past coordinates
int index = 8;

// Read city (null-terminated)
String city = "";
while (index < payloadLen && payload[index] != 0x00)
city += (char)payload[index++];
index++; // skip null

// Read region (null-terminated)
String region = "";
while (index < payloadLen && payload[index] != 0x00)
region += (char)payload[index++];
index++; // skip null

// Remaining bytes = country
String country = "";
while (index < payloadLen)
country += (char)payload[index++];

// Assign to struct
_weatherLocation.city = city;
_weatherLocation.region = region;
_weatherLocation.country = country;
_weatherLocation.latitude = latitude;
_weatherLocation.longitude = longitude;
}

break;
}
}
}
44 changes: 33 additions & 11 deletions src/ChronosESP32.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@
#include <ESP32Time.h>

#define CHRONOSESP_VERSION_MAJOR 1
#define CHRONOSESP_VERSION_MINOR 8
#define CHRONOSESP_VERSION_PATCH 2
#define CHRONOSESP_VERSION_MINOR 9
#define CHRONOSESP_VERSION_PATCH 0

#define CHRONOSESP_VERSION F(CHRONOSESP_VERSION_MAJOR "." CHRONOSESP_VERSION_MINOR "." CHRONOSESP_VERSION_PATCH)

Expand Down Expand Up @@ -97,6 +97,15 @@ struct Weather
int uv;
};

struct WeatherLocation
{
String city;
String region;
String country;
float latitude;
float longitude;
};

struct HourlyForecast
{
int day; // day of forecast
Expand Down Expand Up @@ -177,7 +186,7 @@ struct DateTime

enum Config
{
CF_TIME = 0, // time -
CF_TIME = 0, // time - (a 0 = before, 1 = after setting)
CF_RTW, // raise to wake -
CF_HR24, // 24 hour mode -
CF_LANG, // watch language -
Expand All @@ -200,6 +209,7 @@ enum Config
CF_NAV_DATA, // navigation data received
CF_NAV_ICON, // navigation icon received
CF_CONTACT, // contacts data received
CF_SYNCED, // data sync completed (esp32 can go to sleep if needed)
};

enum HealthRequest
Expand Down Expand Up @@ -250,7 +260,16 @@ enum ChronosScreen
CS_410x494_200_RTF = 25, // 410x494, 2.0 inches, Rectangular, True, False
CS_410x494_200_RTT = 32, // 410x494, 2.0 inches, Rectangular, True, True
CS_466x466_143_CTF = 33, // 466x466, 1.43 inches, Round, True, False
CS_466x466_143_CTT = 34 // 466x466, 1.43 inches, Round, True, True
CS_466x466_143_CTT = 34, // 466x466, 1.43 inches, Round, True, True

// extended configurations for open source projects, used as an identifier for Chronos App
CF_WATCHY_200x200 = 0x80, // Watchy 200x200 (E_PAPER)
CF_ESP32_240x240 = 0x81, // Generic ESP32 240x240
CF_ESP32_466x466 = 0x82, // Generic ESP32 466x466 (AMOLED)
CF_WEBSCREEN_536x240 = 0x83, // Webscreen 536x240 (AMOLED)
CF_WAVESHARE_410x502 = 0x84, // Waveshare 410x502 (AMOLED)
CF_ZSWATCH_240x240 = 0x85, // ZSWatch 240x240
CF_VIEWE_28_240x320 = 0x86, // Viewe ESP32 240x320
};

class ChronosESP32 : public BLEServerCallbacks, public BLECharacteristicCallbacks, public ESP32Time
Expand All @@ -259,13 +278,13 @@ class ChronosESP32 : public BLEServerCallbacks, public BLECharacteristicCallback
public:
// library
ChronosESP32();
ChronosESP32(String name, ChronosScreen screen = CS_240x240_128_CTF); // set the BLE name
void begin(); // initializes BLE server
void stop(bool clearAll = true); // stop the BLE server
void loop(); // handles routine functions
bool isRunning(); // check whether BLE server is inited and running
void setName(String name); // set the BLE name (call before begin)
void setScreen(ChronosScreen screen); // set the screen config (call before begin)
ChronosESP32(String name, ChronosScreen screen = CF_ESP32_240x240); // set the BLE name
void begin(); // initializes BLE server
void stop(bool clearAll = true); // stop the BLE server
void loop(); // handles routine functions
bool isRunning(); // check whether BLE server is inited and running
void setName(String name); // set the BLE name (call before begin)
void setScreen(ChronosScreen screen); // set the screen config (call before begin)
void setChunkedTransfer(bool chunked);
bool isSubscribed();

Expand All @@ -276,6 +295,7 @@ class ChronosESP32 : public BLEServerCallbacks, public BLECharacteristicCallback
String getAddress();
void setBattery(uint8_t level, bool charging = false);
bool isCameraReady();
void syncRequest();

// notifications
int getNotificationCount();
Expand All @@ -288,6 +308,7 @@ class ChronosESP32 : public BLEServerCallbacks, public BLECharacteristicCallback
String getWeatherTime();
Weather getWeatherAt(int index);
HourlyForecast getForecastHour(int hour);
WeatherLocation getWeatherLocation();

// extras
RemoteTouch getTouch();
Expand Down Expand Up @@ -395,6 +416,7 @@ class ChronosESP32 : public BLEServerCallbacks, public BLECharacteristicCallback
String _weatherCity;
String _weatherTime;
int _weatherSize;
WeatherLocation _weatherLocation;

HourlyForecast _hourlyForecast[FORECAST_SIZE];

Expand Down