diff --git a/code/nrf-connect/CMakeLists.txt b/code/nrf-connect/CMakeLists.txt index ce3ebff..7638357 100644 --- a/code/nrf-connect/CMakeLists.txt +++ b/code/nrf-connect/CMakeLists.txt @@ -13,4 +13,5 @@ target_sources(app PRIVATE src/prst/led.c src/prst/button.c src/prst/ble/ble.c + src/prst/ble/encoding.c ) diff --git a/code/nrf-connect/src/main.c b/code/nrf-connect/src/main.c index e2651ce..b9e6cc0 100644 --- a/code/nrf-connect/src/main.c +++ b/code/nrf-connect/src/main.c @@ -19,10 +19,7 @@ int main(void) { RET_IF_ERR(prst_led_flash(2)); - RET_IF_ERR(prst_ble_adv_start()); - prst_sensors_t sensors; - while (true) { RET_IF_ERR(prst_adc_batt_read(&sensors.batt)); RET_IF_ERR(prst_adc_soil_read(sensors.batt.voltage, &sensors.soil)); @@ -38,6 +35,12 @@ int main(void) { (int)sensors.shtc3.temp_c); LOG_INF("Humi: %.0f %%", 100.0 * sensors.shtc3.rel_humi); LOG_INF("--------------------------------------------------"); - k_msleep(500); + + RET_IF_ERR(prst_ble_adv_set_data(&sensors)); + RET_IF_ERR(prst_ble_adv_start()); + + k_msleep(5000); + + RET_IF_ERR(prst_ble_adv_stop()); } } diff --git a/code/nrf-connect/src/prst/ble/ble.c b/code/nrf-connect/src/prst/ble/ble.c index 21ed146..b76ebae 100644 --- a/code/nrf-connect/src/prst/ble/ble.c +++ b/code/nrf-connect/src/prst/ble/ble.c @@ -4,12 +4,16 @@ #include #include +#include "prst/ble/encoding.h" #include "prst/macros.h" LOG_MODULE_REGISTER(ble, LOG_LEVEL_DBG); +static uint8_t service_data[PRST_BLE_ENCODING_SERVICE_DATA_LEN] = {0}; + static const struct bt_data ad[] = { BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), + BT_DATA(BT_DATA_SVC_DATA16, service_data, ARRAY_SIZE(service_data)), BT_DATA_BYTES(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME), }; @@ -17,16 +21,41 @@ static const struct bt_data sd[] = { BT_DATA_BYTES(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME), }; +// bt_addr_le_t.a holds the MAC address in big-endian. +static int get_mac_addr(bt_addr_le_t *out) { + struct bt_le_oob oob; + RET_IF_ERR(bt_le_oob_get_local(BT_ID_DEFAULT, &oob)); + LOG_HEXDUMP_DBG(oob.addr.a.val, ARRAY_SIZE(oob.addr.a.val), + "Read address using bt_le_oob_get_local"); + *out = oob.addr; + + // This API doesn't seem to work here. + // static bt_addr_le_t addrs[CONFIG_BT_ID_MAX]; + // static size_t count; + // bt_id_get(addrs, &count); + // LOG_DBG("[bt_id_get] Received %d addresses", count); + + return 0; +} + int prst_ble_init() { RET_IF_ERR(bt_enable(/*bt_reader_cb_t=*/NULL)); if (IS_ENABLED(CONFIG_SETTINGS)) { RET_IF_ERR_MSG(settings_load(), "Error in settings_load()"); } + + struct bt_le_oob oob; + RET_IF_ERR(bt_le_oob_get_local(BT_ID_DEFAULT, &oob)); + LOG_INF("ADDR: "); + LOG_HEXDUMP_INF(oob.addr.a.val, 6, ":"); return 0; } int prst_ble_adv_start() { - return bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd, + // If BT_LE_ADV_NCONN_IDENTITY, this function will advertise with a static MAC + // address programmed in the chip. If BT_LE_ADV_NCONN, this function returns + // advertises with a random MAC each time. + return bt_le_adv_start(BT_LE_ADV_NCONN_IDENTITY, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); } @@ -35,5 +64,9 @@ int prst_ble_adv_stop() { } int prst_ble_adv_set_data(const prst_sensors_t *sensors) { - return 0; + bt_addr_le_t addr; + RET_IF_ERR(get_mac_addr(&addr)); + LOG_HEXDUMP_WRN(addr.a.val, ARRAY_SIZE(addr.a.val), "GOT ADDR: "); + return prst_ble_encode_service_data(sensors, &addr, service_data, + sizeof(service_data)); } \ No newline at end of file diff --git a/code/nrf-connect/src/prst/ble/encoding.c b/code/nrf-connect/src/prst/ble/encoding.c index e69de29..3970ba8 100644 --- a/code/nrf-connect/src/prst/ble/encoding.c +++ b/code/nrf-connect/src/prst/ble/encoding.c @@ -0,0 +1,54 @@ +#include "prst/ble/encoding.h" + +#include + +#include "prst/macros.h" + +LOG_MODULE_DECLARE(ble, LOG_LEVEL_DBG); + +int prst_ble_encode_service_data(const prst_sensors_t* sensors, + const bt_addr_le_t* bt_addr, uint8_t* out, + uint8_t out_len) { + RET_CHECK(out_len >= PRST_BLE_ENCODING_SERVICE_DATA_LEN, + "Buffer is not large enough"); + + // 0x181c - BTHome Service UUID. + out[0] = 0x1c; + out[1] = 0x18; + + // Soil Moisture. + // + // Four bits for the protocol version. + out[2] |= (2 << 4) & 0xf0; + + // Bit 0 of byte 0 specifies whether or not ambient light data exists in the + // payload. + out[2] |= 1; + + // 4 bits for a small wrap-around counter for deduplicating messages on the + // receiver. + // out[3] = sensors->run_counter & 0x0f; + + out[4] = sensors->batt.millivolts >> 8; + out[5] = sensors->batt.millivolts & 0xff; + + int16_t temp_centicelsius = 100 * sensors->shtc3.temp_c; + out[6] = temp_centicelsius >> 8; + out[7] = temp_centicelsius & 0xff; + + uint16_t humi = sensors->shtc3.rel_humi * UINT16_MAX; + out[8] = humi >> 8; + out[9] = humi & 0xff; + + uint16_t soil_moisture = sensors->soil.percentage * UINT16_MAX; + out[10] = soil_moisture >> 8; + out[11] = soil_moisture & 0xff; + + // MAC address in big-endian. + memcpy(out + 12, bt_addr->a.val, BT_ADDR_SIZE); + + out[18] = sensors->photo.brightness >> 8; + out[19] = sensors->photo.brightness & 0xff; + + return 0; +} \ No newline at end of file diff --git a/code/nrf-connect/src/prst/ble/encoding.h b/code/nrf-connect/src/prst/ble/encoding.h index 7de07c7..ff1e715 100644 --- a/code/nrf-connect/src/prst/ble/encoding.h +++ b/code/nrf-connect/src/prst/ble/encoding.h @@ -1,3 +1,14 @@ #ifndef _PRST_BLE_ENCODING_H_ #define _PRST_BLE_ENCODING_H_ + +#include + +#include "prst/data.h" + +#define PRST_BLE_ENCODING_SERVICE_DATA_LEN 20 + +int prst_ble_encode_service_data(const prst_sensors_t* sensors, + const bt_addr_le_t* bt_addr, uint8_t* out, + uint8_t out_len); + #endif // _PRST_BLE_ENCODING_H_ \ No newline at end of file diff --git a/code/nrf-connect/src/prst/macros.h b/code/nrf-connect/src/prst/macros.h index 816d96f..e8e5764 100644 --- a/code/nrf-connect/src/prst/macros.h +++ b/code/nrf-connect/src/prst/macros.h @@ -16,4 +16,7 @@ #define RET_IF_ERR(expr) RET_IF_ERR_MSG(expr, "") +// Checks that expr evaluates to true, otherwise return 1. +#define RET_CHECK(expr, msg) RET_IF_ERR_MSG(!(expr), msg) + #endif // _PRST_MACROS_H_ \ No newline at end of file