Skeleton of the receiving logic
This commit is contained in:
parent
eb27813c18
commit
6e16584816
|
@ -39,7 +39,7 @@ namespace Pinetime {
|
||||||
None = 0,
|
None = 0,
|
||||||
/** Water particles suspended in the air; low visibility; does not fall */
|
/** Water particles suspended in the air; low visibility; does not fall */
|
||||||
Fog = 1,
|
Fog = 1,
|
||||||
/** Extremely small, dry particles in the air; invisible to the eye; opalescent */
|
/** Tiny, dry particles in the air; invisible to the eye; opalescent */
|
||||||
Haze = 2,
|
Haze = 2,
|
||||||
/** Small fire-created particles suspended in the air */
|
/** Small fire-created particles suspended in the air */
|
||||||
Smoke = 3,
|
Smoke = 3,
|
||||||
|
@ -51,6 +51,7 @@ namespace Pinetime {
|
||||||
Sand = 6,
|
Sand = 6,
|
||||||
/** Water particles suspended in the air; low-ish visibility; temperature is near dewpoint */
|
/** Water particles suspended in the air; low-ish visibility; temperature is near dewpoint */
|
||||||
Mist = 7,
|
Mist = 7,
|
||||||
|
Length
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -82,7 +83,8 @@ namespace Pinetime {
|
||||||
/** Frozen drizzle; very small snow crystals */
|
/** Frozen drizzle; very small snow crystals */
|
||||||
SnowGrains = 8,
|
SnowGrains = 8,
|
||||||
/** Needles; columns or plates of ice. Sometimes described as "diamond dust". In very cold regions */
|
/** Needles; columns or plates of ice. Sometimes described as "diamond dust". In very cold regions */
|
||||||
IceCrystals = 9
|
IceCrystals = 9,
|
||||||
|
Length
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -99,6 +101,7 @@ namespace Pinetime {
|
||||||
Fire = 3,
|
Fire = 3,
|
||||||
/** Thunder and/or lightning */
|
/** Thunder and/or lightning */
|
||||||
Thunder = 4,
|
Thunder = 4,
|
||||||
|
Length
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -111,7 +114,8 @@ namespace Pinetime {
|
||||||
/** This wipes the entire timeline */
|
/** This wipes the entire timeline */
|
||||||
DelTimeline = 1,
|
DelTimeline = 1,
|
||||||
/** There's a currently valid timeline event with the given type */
|
/** There's a currently valid timeline event with the given type */
|
||||||
HasValidEvent = 3
|
HasValidEvent = 3,
|
||||||
|
Length
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -137,19 +141,20 @@ namespace Pinetime {
|
||||||
Location = 7,
|
Location = 7,
|
||||||
/** @see cloud */
|
/** @see cloud */
|
||||||
Clouds = 8,
|
Clouds = 8,
|
||||||
|
Length
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Valid event query
|
* Valid event query
|
||||||
*/
|
*/
|
||||||
class valideventquery {
|
class ValidEventQuery {
|
||||||
public:
|
public:
|
||||||
static constexpr controlcodes code = controlcodes::HasValidEvent;
|
static constexpr controlcodes code = controlcodes::HasValidEvent;
|
||||||
eventtype eventType;
|
eventtype eventType;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** The header used for further parsing */
|
/** The header used for further parsing */
|
||||||
class timelineheader {
|
class TimelineHeader {
|
||||||
public:
|
public:
|
||||||
/** UNIX timestamp */
|
/** UNIX timestamp */
|
||||||
uint64_t timestamp;
|
uint64_t timestamp;
|
||||||
|
@ -168,23 +173,23 @@ namespace Pinetime {
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Specifies how cloudiness is stored */
|
/** Specifies how cloudiness is stored */
|
||||||
class clouds : public timelineheader {
|
class Clouds : public TimelineHeader {
|
||||||
public:
|
public:
|
||||||
/** Cloud coverage in percentage, 0-100% */
|
/** Cloud coverage in percentage, 0-100% */
|
||||||
uint8_t amount;
|
uint8_t amount;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Specifies how obscuration is stored */
|
/** Specifies how obscuration is stored */
|
||||||
class obscuration : public timelineheader {
|
class Obscuration : public TimelineHeader {
|
||||||
public:
|
public:
|
||||||
/** Type */
|
/** Type */
|
||||||
obscurationtype type;
|
obscurationtype type;
|
||||||
/** Visibility distance in meters */
|
/** Visibility distance in meters */
|
||||||
uint8_t amount;
|
uint16_t amount;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Specifies how precipitation is stored */
|
/** Specifies how precipitation is stored */
|
||||||
class precipitation : public timelineheader {
|
class Precipitation : public TimelineHeader {
|
||||||
public:
|
public:
|
||||||
/** Type */
|
/** Type */
|
||||||
precipitationtype type;
|
precipitationtype type;
|
||||||
|
@ -201,7 +206,7 @@ namespace Pinetime {
|
||||||
* As direction can fluctuate wildly and some watchfaces might wish to display it nicely,
|
* As direction can fluctuate wildly and some watchfaces might wish to display it nicely,
|
||||||
* we're following the aerospace industry weather report option of specifying a range.
|
* we're following the aerospace industry weather report option of specifying a range.
|
||||||
*/
|
*/
|
||||||
class wind : public timelineheader {
|
class Wind : public TimelineHeader {
|
||||||
public:
|
public:
|
||||||
/** Meters per second */
|
/** Meters per second */
|
||||||
uint8_t speedMin;
|
uint8_t speedMin;
|
||||||
|
@ -221,7 +226,7 @@ namespace Pinetime {
|
||||||
*
|
*
|
||||||
* We don't do floats, microdegrees are not useful. Make sure to multiply.
|
* We don't do floats, microdegrees are not useful. Make sure to multiply.
|
||||||
*/
|
*/
|
||||||
class temperature : public timelineheader {
|
class Temperature : public TimelineHeader {
|
||||||
public:
|
public:
|
||||||
/** Temperature °C but multiplied by 100 (e.g. -12.50°C becomes -1250) */
|
/** Temperature °C but multiplied by 100 (e.g. -12.50°C becomes -1250) */
|
||||||
int16_t temperature;
|
int16_t temperature;
|
||||||
|
@ -240,7 +245,7 @@ namespace Pinetime {
|
||||||
* or daylight calculations, should those be required.
|
* or daylight calculations, should those be required.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class location : public timelineheader {
|
class Location : public TimelineHeader {
|
||||||
public:
|
public:
|
||||||
/** Location name */
|
/** Location name */
|
||||||
std::string location;
|
std::string location;
|
||||||
|
@ -255,7 +260,7 @@ namespace Pinetime {
|
||||||
/**
|
/**
|
||||||
* How humidity is stored
|
* How humidity is stored
|
||||||
*/
|
*/
|
||||||
class humidity : public timelineheader {
|
class Humidity : public TimelineHeader {
|
||||||
public:
|
public:
|
||||||
/** Relative humidity, 0-100% */
|
/** Relative humidity, 0-100% */
|
||||||
uint8_t humidity;
|
uint8_t humidity;
|
||||||
|
@ -264,7 +269,7 @@ namespace Pinetime {
|
||||||
/**
|
/**
|
||||||
* How air pressure is stored
|
* How air pressure is stored
|
||||||
*/
|
*/
|
||||||
class pressure : public timelineheader {
|
class Pressure : public TimelineHeader {
|
||||||
public:
|
public:
|
||||||
/** Air pressure in hectopascals (hPa) */
|
/** Air pressure in hectopascals (hPa) */
|
||||||
int16_t pressure;
|
int16_t pressure;
|
||||||
|
@ -273,7 +278,7 @@ namespace Pinetime {
|
||||||
/**
|
/**
|
||||||
* How special events are stored
|
* How special events are stored
|
||||||
*/
|
*/
|
||||||
class special : public timelineheader {
|
class Special : public TimelineHeader {
|
||||||
public:
|
public:
|
||||||
/** Special event's type */
|
/** Special event's type */
|
||||||
specialtype type;
|
specialtype type;
|
||||||
|
@ -288,7 +293,7 @@ namespace Pinetime {
|
||||||
*
|
*
|
||||||
* If this needs further enforced standardization, pull requests are welcome
|
* If this needs further enforced standardization, pull requests are welcome
|
||||||
*/
|
*/
|
||||||
class airquality : public timelineheader {
|
class AirQuality : public TimelineHeader {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* The name of the pollution
|
* The name of the pollution
|
||||||
|
|
|
@ -40,58 +40,125 @@ namespace Pinetime {
|
||||||
}
|
}
|
||||||
|
|
||||||
int WeatherService::OnCommand(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt) {
|
int WeatherService::OnCommand(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt) {
|
||||||
|
// TODO: Detect control messages
|
||||||
if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
|
if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
|
||||||
getCurrentPressure();
|
|
||||||
tidyTimeline();
|
|
||||||
getTimelineLength();
|
|
||||||
const auto packetLen = OS_MBUF_PKTLEN(ctxt->om);
|
const auto packetLen = OS_MBUF_PKTLEN(ctxt->om);
|
||||||
if (packetLen <= 0) {
|
if (packetLen <= 0) {
|
||||||
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
|
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
|
||||||
}
|
}
|
||||||
// Decode
|
// Decode
|
||||||
QCBORDecodeContext decodeContext;
|
QCBORDecodeContext decodeContext;
|
||||||
UsefulBufC EncodedCBOR;
|
UsefulBufC encodedCbor;
|
||||||
// TODO: Check uninit fine
|
// TODO: Check, uninit fine?
|
||||||
QCBORDecode_Init(&decodeContext, EncodedCBOR, QCBOR_DECODE_MODE_NORMAL);
|
|
||||||
|
QCBORDecode_Init(&decodeContext, encodedCbor, QCBOR_DECODE_MODE_NORMAL);
|
||||||
QCBORDecode_EnterMap(&decodeContext, nullptr);
|
QCBORDecode_EnterMap(&decodeContext, nullptr);
|
||||||
WeatherData::timelineheader timelineHeader {};
|
|
||||||
// Always encodes to the smallest number of bytes based on the value
|
// Always encodes to the smallest number of bytes based on the value
|
||||||
QCBORDecode_GetInt64InMapSZ(&decodeContext, "Timestamp", reinterpret_cast<int64_t*>(&(timelineHeader.timestamp)));
|
int64_t tmpVersion = 0;
|
||||||
QCBORDecode_GetInt64InMapSZ(&decodeContext, "Expires", reinterpret_cast<int64_t*>(&(timelineHeader.expires)));
|
QCBORDecode_GetInt64InMapSZ(&decodeContext, "Version", &tmpVersion);
|
||||||
QCBORDecode_GetInt64InMapSZ(&decodeContext, "EventType", reinterpret_cast<int64_t*>(&(timelineHeader.eventType)));
|
if (tmpVersion != 1) {
|
||||||
switch (timelineHeader.eventType) {
|
// TODO: Return better error?
|
||||||
|
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
|
||||||
|
}
|
||||||
|
int64_t tmpTimestamp = 0;
|
||||||
|
QCBORDecode_GetInt64InMapSZ(&decodeContext, "Timestamp", &tmpTimestamp);
|
||||||
|
int64_t tmpExpires = 0;
|
||||||
|
QCBORDecode_GetInt64InMapSZ(&decodeContext, "Expires", &tmpExpires);
|
||||||
|
if (tmpExpires > 4294967295) {
|
||||||
|
// TODO: Return better error?
|
||||||
|
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
|
||||||
|
}
|
||||||
|
int64_t tmpEventType = 0;
|
||||||
|
QCBORDecode_GetInt64InMapSZ(&decodeContext, "EventType", &tmpEventType);
|
||||||
|
if (tmpEventType > static_cast<int64_t>(WeatherData::eventtype::Length)) {
|
||||||
|
// TODO: Return better error?
|
||||||
|
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (static_cast<WeatherData::eventtype>(tmpEventType)) {
|
||||||
// TODO: Populate
|
// TODO: Populate
|
||||||
case WeatherData::eventtype::AirQuality: {
|
case WeatherData::eventtype::AirQuality: {
|
||||||
|
std::unique_ptr<WeatherData::AirQuality> airquality = std::make_unique<WeatherData::AirQuality>();
|
||||||
|
airquality->timestamp = tmpTimestamp;
|
||||||
|
airquality->eventType = static_cast<WeatherData::eventtype>(tmpEventType);
|
||||||
|
airquality->expires = tmpExpires;
|
||||||
|
|
||||||
|
timeline.push_back(std::move(airquality));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WeatherData::eventtype::Obscuration: {
|
case WeatherData::eventtype::Obscuration: {
|
||||||
|
std::unique_ptr<WeatherData::Obscuration> obscuration = std::make_unique<WeatherData::Obscuration>();
|
||||||
|
obscuration->timestamp = tmpTimestamp;
|
||||||
|
obscuration->eventType = static_cast<WeatherData::eventtype>(tmpEventType);
|
||||||
|
obscuration->expires = tmpExpires;
|
||||||
|
|
||||||
|
timeline.push_back(std::move(obscuration));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WeatherData::eventtype::Precipitation: {
|
case WeatherData::eventtype::Precipitation: {
|
||||||
|
std::unique_ptr<WeatherData::Precipitation> precipitation = std::make_unique<WeatherData::Precipitation>();
|
||||||
|
precipitation->timestamp = tmpTimestamp;
|
||||||
|
precipitation->eventType = static_cast<WeatherData::eventtype>(tmpEventType);
|
||||||
|
precipitation->expires = tmpExpires;
|
||||||
|
timeline.push_back(std::move(precipitation));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WeatherData::eventtype::Wind: {
|
case WeatherData::eventtype::Wind: {
|
||||||
|
std::unique_ptr<WeatherData::Wind> wind = std::make_unique<WeatherData::Wind>();
|
||||||
|
wind->timestamp = tmpTimestamp;
|
||||||
|
wind->eventType = static_cast<WeatherData::eventtype>(tmpEventType);
|
||||||
|
wind->expires = tmpExpires;
|
||||||
|
timeline.push_back(std::move(wind));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WeatherData::eventtype::Temperature: {
|
case WeatherData::eventtype::Temperature: {
|
||||||
|
std::unique_ptr<WeatherData::Temperature> temperature = std::make_unique<WeatherData::Temperature>();
|
||||||
|
temperature->timestamp = tmpTimestamp;
|
||||||
|
temperature->eventType = static_cast<WeatherData::eventtype>(tmpEventType);
|
||||||
|
temperature->expires = tmpExpires;
|
||||||
|
timeline.push_back(std::move(temperature));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WeatherData::eventtype::Special: {
|
case WeatherData::eventtype::Special: {
|
||||||
|
std::unique_ptr<WeatherData::Special> special = std::make_unique<WeatherData::Special>();
|
||||||
|
special->timestamp = tmpTimestamp;
|
||||||
|
special->eventType = static_cast<WeatherData::eventtype>(tmpEventType);
|
||||||
|
special->expires = tmpExpires;
|
||||||
|
timeline.push_back(std::move(special));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WeatherData::eventtype::Pressure: {
|
case WeatherData::eventtype::Pressure: {
|
||||||
|
std::unique_ptr<WeatherData::Pressure> pressure = std::make_unique<WeatherData::Pressure>();
|
||||||
|
pressure->timestamp = tmpTimestamp;
|
||||||
|
pressure->eventType = static_cast<WeatherData::eventtype>(tmpEventType);
|
||||||
|
pressure->expires = tmpExpires;
|
||||||
|
timeline.push_back(std::move(pressure));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WeatherData::eventtype::Location: {
|
case WeatherData::eventtype::Location: {
|
||||||
|
std::unique_ptr<WeatherData::Location> location = std::make_unique<WeatherData::Location>();
|
||||||
|
location->timestamp = tmpTimestamp;
|
||||||
|
location->eventType = static_cast<WeatherData::eventtype>(tmpEventType);
|
||||||
|
location->expires = tmpExpires;
|
||||||
|
timeline.push_back(std::move(location));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WeatherData::eventtype::Clouds: {
|
case WeatherData::eventtype::Clouds: {
|
||||||
|
std::unique_ptr<WeatherData::Clouds> clouds = std::make_unique<WeatherData::Clouds>();
|
||||||
|
clouds->timestamp = tmpTimestamp;
|
||||||
|
clouds->eventType = static_cast<WeatherData::eventtype>(tmpEventType);
|
||||||
|
clouds->expires = tmpExpires;
|
||||||
|
timeline.push_back(std::move(clouds));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getCurrentPressure();
|
||||||
|
tidyTimeline();
|
||||||
|
getTimelineLength();
|
||||||
QCBORDecode_ExitMap(&decodeContext);
|
QCBORDecode_ExitMap(&decodeContext);
|
||||||
|
|
||||||
auto uErr = QCBORDecode_Finish(&decodeContext);
|
auto uErr = QCBORDecode_Finish(&decodeContext);
|
||||||
|
@ -99,8 +166,6 @@ namespace Pinetime {
|
||||||
return BLE_ATT_ERR_INSUFFICIENT_RES;
|
return BLE_ATT_ERR_INSUFFICIENT_RES;
|
||||||
}
|
}
|
||||||
} else if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) {
|
} else if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) {
|
||||||
// TODO: Detect control messages
|
|
||||||
|
|
||||||
// Encode
|
// Encode
|
||||||
uint8_t buffer[64];
|
uint8_t buffer[64];
|
||||||
QCBOREncodeContext encodeContext;
|
QCBOREncodeContext encodeContext;
|
||||||
|
@ -125,46 +190,46 @@ namespace Pinetime {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
WeatherData::location WeatherService::getCurrentLocation() const {
|
WeatherData::Location WeatherService::getCurrentLocation() const {
|
||||||
return WeatherData::location();
|
return WeatherData::Location();
|
||||||
}
|
}
|
||||||
WeatherData::clouds WeatherService::getCurrentClouds() const {
|
WeatherData::Clouds WeatherService::getCurrentClouds() const {
|
||||||
return WeatherData::clouds();
|
return WeatherData::Clouds();
|
||||||
}
|
}
|
||||||
WeatherData::obscuration WeatherService::getCurrentObscuration() const {
|
WeatherData::Obscuration WeatherService::getCurrentObscuration() const {
|
||||||
return WeatherData::obscuration();
|
return WeatherData::Obscuration();
|
||||||
}
|
}
|
||||||
WeatherData::precipitation WeatherService::getCurrentPrecipitation() const {
|
WeatherData::Precipitation WeatherService::getCurrentPrecipitation() const {
|
||||||
return WeatherData::precipitation();
|
return WeatherData::Precipitation();
|
||||||
}
|
}
|
||||||
WeatherData::wind WeatherService::getCurrentWind() const {
|
WeatherData::Wind WeatherService::getCurrentWind() const {
|
||||||
return WeatherData::wind();
|
return WeatherData::Wind();
|
||||||
}
|
}
|
||||||
WeatherData::temperature WeatherService::getCurrentTemperature() const {
|
WeatherData::Temperature WeatherService::getCurrentTemperature() const {
|
||||||
return WeatherData::temperature();
|
return WeatherData::Temperature();
|
||||||
}
|
}
|
||||||
WeatherData::humidity WeatherService::getCurrentHumidity() const {
|
WeatherData::Humidity WeatherService::getCurrentHumidity() const {
|
||||||
return WeatherData::humidity();
|
return WeatherData::Humidity();
|
||||||
}
|
}
|
||||||
WeatherData::pressure WeatherService::getCurrentPressure() const {
|
WeatherData::Pressure WeatherService::getCurrentPressure() const {
|
||||||
uint64_t currentTimestamp = getCurrentUNIXTimestamp();
|
uint64_t currentTimestamp = getCurrentUNIXTimestamp();
|
||||||
for (auto&& header : timeline) {
|
for (auto&& header : timeline) {
|
||||||
if (header->eventType == WeatherData::eventtype::Pressure && header->timestamp + header->expires <= currentTimestamp) {
|
if (header->eventType == WeatherData::eventtype::Pressure && header->timestamp + header->expires <= currentTimestamp) {
|
||||||
return WeatherData::pressure();
|
return WeatherData::Pressure();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return WeatherData::pressure();
|
return WeatherData::Pressure();
|
||||||
}
|
}
|
||||||
|
|
||||||
WeatherData::airquality WeatherService::getCurrentQuality() const {
|
WeatherData::AirQuality WeatherService::getCurrentQuality() const {
|
||||||
return WeatherData::airquality();
|
return WeatherData::AirQuality();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t WeatherService::getTimelineLength() const {
|
size_t WeatherService::getTimelineLength() const {
|
||||||
return timeline.size();
|
return timeline.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WeatherService::addEventToTimeline(std::unique_ptr<WeatherData::timelineheader> event) {
|
bool WeatherService::addEventToTimeline(std::unique_ptr<WeatherData::TimelineHeader> event) {
|
||||||
if (timeline.size() == timeline.max_size()) {
|
if (timeline.size() == timeline.max_size()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -188,7 +253,7 @@ namespace Pinetime {
|
||||||
uint64_t timeCurrent = 0;
|
uint64_t timeCurrent = 0;
|
||||||
timeline.erase(std::remove_if(std::begin(timeline),
|
timeline.erase(std::remove_if(std::begin(timeline),
|
||||||
std::end(timeline),
|
std::end(timeline),
|
||||||
[&](std::unique_ptr<WeatherData::timelineheader> const& header) {
|
[&](std::unique_ptr<WeatherData::TimelineHeader> const& header) {
|
||||||
return header->timestamp + header->expires > timeCurrent;
|
return header->timestamp + header->expires > timeCurrent;
|
||||||
}),
|
}),
|
||||||
std::end(timeline));
|
std::end(timeline));
|
||||||
|
@ -196,8 +261,8 @@ namespace Pinetime {
|
||||||
std::sort(std::begin(timeline), std::end(timeline), compareTimelineEvents);
|
std::sort(std::begin(timeline), std::end(timeline), compareTimelineEvents);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WeatherService::compareTimelineEvents(const std::unique_ptr<WeatherData::timelineheader>& first,
|
bool WeatherService::compareTimelineEvents(const std::unique_ptr<WeatherData::TimelineHeader>& first,
|
||||||
const std::unique_ptr<WeatherData::timelineheader>& second) {
|
const std::unique_ptr<WeatherData::TimelineHeader>& second) {
|
||||||
return first->timestamp > second->timestamp;
|
return first->timestamp > second->timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,15 +57,15 @@ namespace Pinetime {
|
||||||
/*
|
/*
|
||||||
* Helper functions for quick access to currently valid data
|
* Helper functions for quick access to currently valid data
|
||||||
*/
|
*/
|
||||||
WeatherData::location getCurrentLocation() const;
|
WeatherData::Location getCurrentLocation() const;
|
||||||
WeatherData::clouds getCurrentClouds() const;
|
WeatherData::Clouds getCurrentClouds() const;
|
||||||
WeatherData::obscuration getCurrentObscuration() const;
|
WeatherData::Obscuration getCurrentObscuration() const;
|
||||||
WeatherData::precipitation getCurrentPrecipitation() const;
|
WeatherData::Precipitation getCurrentPrecipitation() const;
|
||||||
WeatherData::wind getCurrentWind() const;
|
WeatherData::Wind getCurrentWind() const;
|
||||||
WeatherData::temperature getCurrentTemperature() const;
|
WeatherData::Temperature getCurrentTemperature() const;
|
||||||
WeatherData::humidity getCurrentHumidity() const;
|
WeatherData::Humidity getCurrentHumidity() const;
|
||||||
WeatherData::pressure getCurrentPressure() const;
|
WeatherData::Pressure getCurrentPressure() const;
|
||||||
WeatherData::airquality getCurrentQuality() const;
|
WeatherData::AirQuality getCurrentQuality() const;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Management functions
|
* Management functions
|
||||||
|
@ -74,7 +74,7 @@ namespace Pinetime {
|
||||||
* Adds an event to the timeline
|
* Adds an event to the timeline
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
bool addEventToTimeline(std::unique_ptr<WeatherData::timelineheader> event);
|
bool addEventToTimeline(std::unique_ptr<WeatherData::TimelineHeader> event);
|
||||||
/**
|
/**
|
||||||
* Gets the current timeline length
|
* Gets the current timeline length
|
||||||
*/
|
*/
|
||||||
|
@ -86,37 +86,36 @@ namespace Pinetime {
|
||||||
bool hasTimelineEventOfType(WeatherData::eventtype type) const;
|
bool hasTimelineEventOfType(WeatherData::eventtype type) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ble_uuid128_t msUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = WEATHER_SERVICE_UUID_BASE};
|
ble_uuid128_t weatherUUID {.u = {.type = BLE_UUID_TYPE_128}, .value = WEATHER_SERVICE_UUID_BASE};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Just write timeline data here
|
* Just write timeline data here
|
||||||
*/
|
*/
|
||||||
ble_uuid128_t wDataCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = WEATHER_SERVICE_CHAR_UUID(0x00, 0x01)};
|
ble_uuid128_t weatherDataCharUUID {.u = {.type = BLE_UUID_TYPE_128}, .value = WEATHER_SERVICE_CHAR_UUID(0x00, 0x01)};
|
||||||
/**
|
/**
|
||||||
* This doesn't take timeline data
|
* This doesn't take timeline data,
|
||||||
* but provides some control over it
|
* provides some control over it
|
||||||
*/
|
*/
|
||||||
ble_uuid128_t wControlCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = WEATHER_SERVICE_CHAR_UUID(0x00, 0x02)};
|
ble_uuid128_t weatherControlCharUUID {.u = {.type = BLE_UUID_TYPE_128}, .value = WEATHER_SERVICE_CHAR_UUID(0x00, 0x02)};
|
||||||
|
|
||||||
const struct ble_gatt_chr_def characteristicDefinition[2] = {{.uuid = reinterpret_cast<ble_uuid_t*>(&wDataCharUuid),
|
const struct ble_gatt_chr_def characteristicDefinition[2] = {{.uuid = &weatherDataCharUUID.u,
|
||||||
.access_cb = WeatherCallback,
|
.access_cb = WeatherCallback,
|
||||||
.arg = this,
|
.arg = this,
|
||||||
.flags = BLE_GATT_CHR_F_NOTIFY,
|
.flags = BLE_GATT_CHR_F_NOTIFY,
|
||||||
.val_handle = &eventHandle},
|
.val_handle = &eventHandle},
|
||||||
{.uuid = reinterpret_cast<ble_uuid_t*>(&wControlCharUuid),
|
{.uuid = &weatherControlCharUUID.u,
|
||||||
.access_cb = WeatherCallback,
|
.access_cb = WeatherCallback,
|
||||||
.arg = this,
|
.arg = this,
|
||||||
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ}};
|
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ}};
|
||||||
const struct ble_gatt_svc_def serviceDefinition[2] = {
|
const struct ble_gatt_svc_def serviceDefinition[2] = {
|
||||||
{.type = BLE_GATT_SVC_TYPE_PRIMARY, .uuid = reinterpret_cast<ble_uuid_t*>(&msUuid), .characteristics = characteristicDefinition},
|
{.type = BLE_GATT_SVC_TYPE_PRIMARY, .uuid = &weatherUUID.u, .characteristics = characteristicDefinition}, {0}};
|
||||||
{0}};
|
|
||||||
|
|
||||||
uint16_t eventHandle {};
|
uint16_t eventHandle {};
|
||||||
|
|
||||||
Pinetime::System::SystemTask& system;
|
Pinetime::System::SystemTask& system;
|
||||||
Pinetime::Controllers::DateTime& dateTimeController;
|
Pinetime::Controllers::DateTime& dateTimeController;
|
||||||
|
|
||||||
std::vector<std::unique_ptr<WeatherData::timelineheader>> timeline;
|
std::vector<std::unique_ptr<WeatherData::TimelineHeader>> timeline;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cleans up the timeline of expired events
|
* Cleans up the timeline of expired events
|
||||||
|
@ -127,11 +126,11 @@ namespace Pinetime {
|
||||||
/**
|
/**
|
||||||
* Compares two timeline events
|
* Compares two timeline events
|
||||||
*/
|
*/
|
||||||
static bool compareTimelineEvents(const std::unique_ptr<WeatherData::timelineheader>& first,
|
static bool compareTimelineEvents(const std::unique_ptr<WeatherData::TimelineHeader>& first,
|
||||||
const std::unique_ptr<WeatherData::timelineheader>& second);
|
const std::unique_ptr<WeatherData::TimelineHeader>& second);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Returns current UNIX timestamp
|
||||||
*/
|
*/
|
||||||
uint64_t getCurrentUNIXTimestamp() const;
|
uint64_t getCurrentUNIXTimestamp() const;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue