From 6e165848161b72d1afa43af6807c654d3fc23d03 Mon Sep 17 00:00:00 2001 From: Avamander Date: Wed, 16 Jun 2021 23:31:17 +0300 Subject: Skeleton of the receiving logic --- src/components/ble/weather/WeatherService.cpp | 139 +++++++++++++++++++------- 1 file changed, 102 insertions(+), 37 deletions(-) (limited to 'src/components/ble/weather/WeatherService.cpp') diff --git a/src/components/ble/weather/WeatherService.cpp b/src/components/ble/weather/WeatherService.cpp index 006fc6c1..60e608e7 100644 --- a/src/components/ble/weather/WeatherService.cpp +++ b/src/components/ble/weather/WeatherService.cpp @@ -40,58 +40,125 @@ namespace Pinetime { } 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) { - getCurrentPressure(); - tidyTimeline(); - getTimelineLength(); const auto packetLen = OS_MBUF_PKTLEN(ctxt->om); if (packetLen <= 0) { return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } // Decode QCBORDecodeContext decodeContext; - UsefulBufC EncodedCBOR; - // TODO: Check uninit fine - QCBORDecode_Init(&decodeContext, EncodedCBOR, QCBOR_DECODE_MODE_NORMAL); + UsefulBufC encodedCbor; + // TODO: Check, uninit fine? + + QCBORDecode_Init(&decodeContext, encodedCbor, QCBOR_DECODE_MODE_NORMAL); QCBORDecode_EnterMap(&decodeContext, nullptr); - WeatherData::timelineheader timelineHeader {}; // Always encodes to the smallest number of bytes based on the value - QCBORDecode_GetInt64InMapSZ(&decodeContext, "Timestamp", reinterpret_cast(&(timelineHeader.timestamp))); - QCBORDecode_GetInt64InMapSZ(&decodeContext, "Expires", reinterpret_cast(&(timelineHeader.expires))); - QCBORDecode_GetInt64InMapSZ(&decodeContext, "EventType", reinterpret_cast(&(timelineHeader.eventType))); - switch (timelineHeader.eventType) { - // TODO: Populate + int64_t tmpVersion = 0; + QCBORDecode_GetInt64InMapSZ(&decodeContext, "Version", &tmpVersion); + if (tmpVersion != 1) { + // 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(WeatherData::eventtype::Length)) { + // TODO: Return better error? + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } + + switch (static_cast(tmpEventType)) { + // TODO: Populate case WeatherData::eventtype::AirQuality: { + std::unique_ptr airquality = std::make_unique(); + airquality->timestamp = tmpTimestamp; + airquality->eventType = static_cast(tmpEventType); + airquality->expires = tmpExpires; + + timeline.push_back(std::move(airquality)); break; } case WeatherData::eventtype::Obscuration: { + std::unique_ptr obscuration = std::make_unique(); + obscuration->timestamp = tmpTimestamp; + obscuration->eventType = static_cast(tmpEventType); + obscuration->expires = tmpExpires; + + timeline.push_back(std::move(obscuration)); break; } case WeatherData::eventtype::Precipitation: { + std::unique_ptr precipitation = std::make_unique(); + precipitation->timestamp = tmpTimestamp; + precipitation->eventType = static_cast(tmpEventType); + precipitation->expires = tmpExpires; + timeline.push_back(std::move(precipitation)); break; } case WeatherData::eventtype::Wind: { + std::unique_ptr wind = std::make_unique(); + wind->timestamp = tmpTimestamp; + wind->eventType = static_cast(tmpEventType); + wind->expires = tmpExpires; + timeline.push_back(std::move(wind)); break; } case WeatherData::eventtype::Temperature: { + std::unique_ptr temperature = std::make_unique(); + temperature->timestamp = tmpTimestamp; + temperature->eventType = static_cast(tmpEventType); + temperature->expires = tmpExpires; + timeline.push_back(std::move(temperature)); break; } case WeatherData::eventtype::Special: { + std::unique_ptr special = std::make_unique(); + special->timestamp = tmpTimestamp; + special->eventType = static_cast(tmpEventType); + special->expires = tmpExpires; + timeline.push_back(std::move(special)); break; } case WeatherData::eventtype::Pressure: { + std::unique_ptr pressure = std::make_unique(); + pressure->timestamp = tmpTimestamp; + pressure->eventType = static_cast(tmpEventType); + pressure->expires = tmpExpires; + timeline.push_back(std::move(pressure)); break; } case WeatherData::eventtype::Location: { + std::unique_ptr location = std::make_unique(); + location->timestamp = tmpTimestamp; + location->eventType = static_cast(tmpEventType); + location->expires = tmpExpires; + timeline.push_back(std::move(location)); break; } case WeatherData::eventtype::Clouds: { + std::unique_ptr clouds = std::make_unique(); + clouds->timestamp = tmpTimestamp; + clouds->eventType = static_cast(tmpEventType); + clouds->expires = tmpExpires; + timeline.push_back(std::move(clouds)); break; } default: { break; } } + + getCurrentPressure(); + tidyTimeline(); + getTimelineLength(); QCBORDecode_ExitMap(&decodeContext); auto uErr = QCBORDecode_Finish(&decodeContext); @@ -99,8 +166,6 @@ namespace Pinetime { return BLE_ATT_ERR_INSUFFICIENT_RES; } } else if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) { - // TODO: Detect control messages - // Encode uint8_t buffer[64]; QCBOREncodeContext encodeContext; @@ -125,46 +190,46 @@ namespace Pinetime { return 0; } - WeatherData::location WeatherService::getCurrentLocation() const { - return WeatherData::location(); + WeatherData::Location WeatherService::getCurrentLocation() const { + return WeatherData::Location(); } - WeatherData::clouds WeatherService::getCurrentClouds() const { - return WeatherData::clouds(); + WeatherData::Clouds WeatherService::getCurrentClouds() const { + return WeatherData::Clouds(); } - WeatherData::obscuration WeatherService::getCurrentObscuration() const { - return WeatherData::obscuration(); + WeatherData::Obscuration WeatherService::getCurrentObscuration() const { + return WeatherData::Obscuration(); } - WeatherData::precipitation WeatherService::getCurrentPrecipitation() const { - return WeatherData::precipitation(); + WeatherData::Precipitation WeatherService::getCurrentPrecipitation() const { + return WeatherData::Precipitation(); } - WeatherData::wind WeatherService::getCurrentWind() const { - return WeatherData::wind(); + WeatherData::Wind WeatherService::getCurrentWind() const { + return WeatherData::Wind(); } - WeatherData::temperature WeatherService::getCurrentTemperature() const { - return WeatherData::temperature(); + WeatherData::Temperature WeatherService::getCurrentTemperature() const { + return WeatherData::Temperature(); } - WeatherData::humidity WeatherService::getCurrentHumidity() const { - return WeatherData::humidity(); + WeatherData::Humidity WeatherService::getCurrentHumidity() const { + return WeatherData::Humidity(); } - WeatherData::pressure WeatherService::getCurrentPressure() const { + WeatherData::Pressure WeatherService::getCurrentPressure() const { uint64_t currentTimestamp = getCurrentUNIXTimestamp(); for (auto&& header : timeline) { 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 { - return WeatherData::airquality(); + WeatherData::AirQuality WeatherService::getCurrentQuality() const { + return WeatherData::AirQuality(); } size_t WeatherService::getTimelineLength() const { return timeline.size(); } - bool WeatherService::addEventToTimeline(std::unique_ptr event) { + bool WeatherService::addEventToTimeline(std::unique_ptr event) { if (timeline.size() == timeline.max_size()) { return false; } @@ -188,7 +253,7 @@ namespace Pinetime { uint64_t timeCurrent = 0; timeline.erase(std::remove_if(std::begin(timeline), std::end(timeline), - [&](std::unique_ptr const& header) { + [&](std::unique_ptr const& header) { return header->timestamp + header->expires > timeCurrent; }), std::end(timeline)); @@ -196,8 +261,8 @@ namespace Pinetime { std::sort(std::begin(timeline), std::end(timeline), compareTimelineEvents); } - bool WeatherService::compareTimelineEvents(const std::unique_ptr& first, - const std::unique_ptr& second) { + bool WeatherService::compareTimelineEvents(const std::unique_ptr& first, + const std::unique_ptr& second) { return first->timestamp > second->timestamp; } -- cgit v1.2.3-70-g09d2