diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fb5e1d1e..4273becf 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -860,6 +860,7 @@ target_compile_definitions(QCBOR PUBLIC QCBOR_DISABLE_EXP_AND_MANTISSA) target_compile_definitions(QCBOR PUBLIC QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS) target_compile_definitions(QCBOR PUBLIC QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS) target_compile_definitions(QCBOR PUBLIC QCBOR_DISABLE_UNCOMMON_TAGS) +target_compile_definitions(QCBOR PUBLIC USEFULBUF_CONFIG_LITTLE_ENDIAN) set_target_properties(QCBOR PROPERTIES LINKER_LANGUAGE C) target_compile_options(QCBOR PRIVATE $<$,$>: ${COMMON_FLAGS} -O0 -g3> diff --git a/src/components/ble/NimbleController.h b/src/components/ble/NimbleController.h index a21cbe81..34f00e4e 100644 --- a/src/components/ble/NimbleController.h +++ b/src/components/ble/NimbleController.h @@ -71,6 +71,9 @@ namespace Pinetime { Pinetime::Controllers::AlertNotificationService& alertService() { return anService; }; + Pinetime::Controllers::WeatherService& weather() { + return weatherService; + }; uint16_t connHandle(); void NotifyBatteryLevel(uint8_t level); diff --git a/src/components/ble/weather/WeatherData.h b/src/components/ble/weather/WeatherData.h index 7cf68418..ee2a364d 100644 --- a/src/components/ble/weather/WeatherData.h +++ b/src/components/ble/weather/WeatherData.h @@ -248,7 +248,7 @@ namespace Pinetime { class Location : public TimelineHeader { public: /** Location name */ - std::string location; + std::unique_ptr location; /** Altitude relative to sea level in meters */ int16_t altitude; /** Latitude, EPSG:3857 (Google Maps, Openstreetmaps datum) */ @@ -309,7 +309,7 @@ namespace Pinetime { * For chemical compounds use the molecular formula e.g. "NO2", "CO2", "O3" * For pollen use the genus, e.g. "Betula" for birch or "Alternaria" for that mold's spores */ - std::string polluter; + std::unique_ptr polluter; /** * Amount of the pollution in SI units, * otherwise it's going to be difficult to create UI, alerts diff --git a/src/components/ble/weather/WeatherService.cpp b/src/components/ble/weather/WeatherService.cpp index 60e608e7..30d274b2 100644 --- a/src/components/ble/weather/WeatherService.cpp +++ b/src/components/ble/weather/WeatherService.cpp @@ -33,7 +33,7 @@ namespace Pinetime { void WeatherService::Init() { uint8_t res = 0; res = ble_gatts_count_cfg(serviceDefinition); - ASSERT(res == 0) + ASSERT(res == 0); res = ble_gatts_add_svcs(serviceDefinition); ASSERT(res == 0); @@ -64,13 +64,13 @@ namespace Pinetime { QCBORDecode_GetInt64InMapSZ(&decodeContext, "Timestamp", &tmpTimestamp); int64_t tmpExpires = 0; QCBORDecode_GetInt64InMapSZ(&decodeContext, "Expires", &tmpExpires); - if (tmpExpires > 4294967295) { + if (tmpExpires < 0 || 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)) { + if (tmpEventType < 0 || tmpEventType > static_cast(WeatherData::eventtype::Length)) { // TODO: Return better error? return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } @@ -82,7 +82,18 @@ namespace Pinetime { airquality->timestamp = tmpTimestamp; airquality->eventType = static_cast(tmpEventType); airquality->expires = tmpExpires; - + UsefulBufC String; + QCBORDecode_GetTextStringInMapSZ(&decodeContext, "Polluter", &String); + if (UsefulBuf_IsNULLOrEmptyC(String) != 0) { + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } + airquality->polluter = std::make_unique(static_cast(String.ptr), String.len); + int64_t tmpAmount = 0; + QCBORDecode_GetInt64InMapSZ(&decodeContext, "Amount", &tmpAmount); + if (tmpAmount < 0 || tmpAmount > 4294967295) { + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } + airquality->amount = tmpAmount; timeline.push_back(std::move(airquality)); break; } diff --git a/src/components/ble/weather/WeatherService.h b/src/components/ble/weather/WeatherService.h index 64a8213a..43002dc1 100644 --- a/src/components/ble/weather/WeatherService.h +++ b/src/components/ble/weather/WeatherService.h @@ -32,12 +32,6 @@ #include "WeatherData.h" #include -// 00030000-78fc-48fe-8e23-433b3a1942d0 -#define WEATHER_SERVICE_UUID_BASE \ - { 0xd0, 0x42, 0x19, 0x3a, 0x3b, 0x43, 0x23, 0x8e, 0xfe, 0x48, 0xfc, 0x78, 0x00, 0x00, 0x03, 0x00 } -#define WEATHER_SERVICE_CHAR_UUID(y, x) \ - { 0xd0, 0x42, 0x19, 0x3a, 0x3b, 0x43, 0x23, 0x8e, 0xfe, 0x48, 0xfc, 0x78, (x), (y), 0x03, 0x00 } - int WeatherCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg); namespace Pinetime { @@ -86,27 +80,37 @@ namespace Pinetime { bool hasTimelineEventOfType(WeatherData::eventtype type) const; private: - ble_uuid128_t weatherUUID {.u = {.type = BLE_UUID_TYPE_128}, .value = WEATHER_SERVICE_UUID_BASE}; + // 00030000-78fc-48fe-8e23-433b3a1942d0 + static constexpr ble_uuid128_t BaseUUID() { + return CharUUID(0x00, 0x00); + } + + // 0003yyxx-78fc-48fe-8e23-433b3a1942d0 + static constexpr ble_uuid128_t CharUUID(uint8_t x, uint8_t y) { + return ble_uuid128_t {.u = {.type = BLE_UUID_TYPE_128}, + .value = {0xd0, 0x42, 0x19, 0x3a, 0x3b, 0x43, 0x23, 0x8e, 0xfe, 0x48, 0xfc, 0x78, x, y, 0x03, 0x00}}; + } + + ble_uuid128_t weatherUUID {BaseUUID()}; /** * Just write timeline data here */ - ble_uuid128_t weatherDataCharUUID {.u = {.type = BLE_UUID_TYPE_128}, .value = WEATHER_SERVICE_CHAR_UUID(0x00, 0x01)}; + ble_uuid128_t weatherDataCharUUID {CharUUID(0x00, 0x01)}; /** * This doesn't take timeline data, * provides some control over it */ - ble_uuid128_t weatherControlCharUUID {.u = {.type = BLE_UUID_TYPE_128}, .value = WEATHER_SERVICE_CHAR_UUID(0x00, 0x02)}; + ble_uuid128_t weatherControlCharUUID {CharUUID(0x00, 0x02)}; - const struct ble_gatt_chr_def characteristicDefinition[2] = {{.uuid = &weatherDataCharUUID.u, - .access_cb = WeatherCallback, - .arg = this, - .flags = BLE_GATT_CHR_F_NOTIFY, - .val_handle = &eventHandle}, - {.uuid = &weatherControlCharUUID.u, - .access_cb = WeatherCallback, - .arg = this, - .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ}}; + const struct ble_gatt_chr_def characteristicDefinition[3] = { + {.uuid = &weatherDataCharUUID.u, + .access_cb = WeatherCallback, + .arg = this, + .flags = BLE_GATT_CHR_F_WRITE, + .val_handle = &eventHandle}, + {.uuid = &weatherControlCharUUID.u, .access_cb = WeatherCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ}, + {nullptr}}; const struct ble_gatt_svc_def serviceDefinition[2] = { {.type = BLE_GATT_SVC_TYPE_PRIMARY, .uuid = &weatherUUID.u, .characteristics = characteristicDefinition}, {0}};