From 3b104cdf24f71859b1b3e60573c3e2e822ac9be0 Mon Sep 17 00:00:00 2001 From: rbaron Date: Tue, 29 Nov 2022 20:05:41 +0100 Subject: [PATCH] Implements BTHome v1 and v2 encodings for ble sample --- code/nrf-connect/prstlib/src/adc.c | 3 +- code/nrf-connect/prstlib/src/button.c | 2 +- code/nrf-connect/prstlib/src/led.c | 2 +- code/nrf-connect/prstlib/src/sensors.c | 2 +- code/nrf-connect/prstlib/src/shtc3.c | 2 +- code/nrf-connect/samples/ble/Kconfig | 10 ++- code/nrf-connect/samples/ble/prj.conf | 16 ++-- code/nrf-connect/samples/ble/src/ble.c | 19 ++-- code/nrf-connect/samples/ble/src/encoding.c | 96 ++++++++++++++++++++- 9 files changed, 123 insertions(+), 29 deletions(-) diff --git a/code/nrf-connect/prstlib/src/adc.c b/code/nrf-connect/prstlib/src/adc.c index 249831d..285d3db 100644 --- a/code/nrf-connect/prstlib/src/adc.c +++ b/code/nrf-connect/prstlib/src/adc.c @@ -8,7 +8,7 @@ #include "prstlib/macros.h" -LOG_MODULE_REGISTER(adc, LOG_LEVEL_DBG); +LOG_MODULE_REGISTER(adc, LOG_LEVEL_WRN); // PWM spec for square wave. Input to the soil sensing circuit. static const struct pwm_dt_spec soil_pwm_dt = @@ -115,6 +115,5 @@ int prst_adc_photo_read(float battery_voltage, prst_adc_photo_sensor_t* out) { const float lux_sun = 10000.0f; const float current = out->adc_read.voltage / phototransistor_resistor; out->brightness = MAX(0, MIN(lux_sun * current / current_sun, UINT16_MAX)); - return 0; } diff --git a/code/nrf-connect/prstlib/src/button.c b/code/nrf-connect/prstlib/src/button.c index c6a28f0..d9e352d 100644 --- a/code/nrf-connect/prstlib/src/button.c +++ b/code/nrf-connect/prstlib/src/button.c @@ -6,7 +6,7 @@ #include "prstlib/led.h" #include "prstlib/macros.h" -LOG_MODULE_REGISTER(button, LOG_LEVEL_DBG); +LOG_MODULE_REGISTER(button, LOG_LEVEL_WRN); static struct gpio_dt_spec button = GPIO_DT_SPEC_GET(DT_NODELABEL(button0), gpios); diff --git a/code/nrf-connect/prstlib/src/led.c b/code/nrf-connect/prstlib/src/led.c index cec9acc..8b16afd 100644 --- a/code/nrf-connect/prstlib/src/led.c +++ b/code/nrf-connect/prstlib/src/led.c @@ -4,7 +4,7 @@ #include "prstlib/macros.h" -LOG_MODULE_REGISTER(led, LOG_LEVEL_DBG); +LOG_MODULE_REGISTER(led, LOG_LEVEL_WRN); struct gpio_dt_spec led = GPIO_DT_SPEC_GET(DT_NODELABEL(led0), gpios); diff --git a/code/nrf-connect/prstlib/src/sensors.c b/code/nrf-connect/prstlib/src/sensors.c index b352f39..0522679 100644 --- a/code/nrf-connect/prstlib/src/sensors.c +++ b/code/nrf-connect/prstlib/src/sensors.c @@ -6,7 +6,7 @@ #include "prstlib/led.h" #include "prstlib/macros.h" -LOG_MODULE_REGISTER(sensors, LOG_LEVEL_DBG); +LOG_MODULE_REGISTER(sensors, LOG_LEVEL_WRN); int prst_sensors_read_all(prst_sensors_t *sensors) { RET_IF_ERR(prst_adc_batt_read(&sensors->batt)); diff --git a/code/nrf-connect/prstlib/src/shtc3.c b/code/nrf-connect/prstlib/src/shtc3.c index 56b8844..a0476a8 100644 --- a/code/nrf-connect/prstlib/src/shtc3.c +++ b/code/nrf-connect/prstlib/src/shtc3.c @@ -6,7 +6,7 @@ #include "prstlib/macros.h" -LOG_MODULE_REGISTER(shtc3, LOG_LEVEL_INF); +LOG_MODULE_REGISTER(shtc3, LOG_LEVEL_WRN); static const struct i2c_dt_spec shtc3 = I2C_DT_SPEC_GET(DT_NODELABEL(shtc3)); diff --git a/code/nrf-connect/samples/ble/Kconfig b/code/nrf-connect/samples/ble/Kconfig index 8ab20c9..ffe5478 100644 --- a/code/nrf-connect/samples/ble/Kconfig +++ b/code/nrf-connect/samples/ble/Kconfig @@ -34,8 +34,11 @@ choice PRST_BLE_ENCODING config PRST_BLE_ENCODING_BPARASITE_V2 bool "Uses the custom b-parasite protocol v2 for encoding advertising packets" -config PRST_BLE_ENCODING_BTHOME - bool "Uses the BTHome (bthome.io) BLE encoding" +config PRST_BLE_ENCODING_BTHOME_V1 + bool "Uses the BTHome (bthome.io) BLE encoding (v1)" + +config PRST_BLE_ENCODING_BTHOME_V2 + bool "Uses the BTHome (bthome.io) BLE encoding (v2)" endchoice # PRST_BLE_ENCODING @@ -44,4 +47,5 @@ config PRST_BLE_ENCODING_SERVICE_DATA_LEN help Size of the service data buffer default 20 if PRST_BLE_ENCODING_BPARASITE_V2 - default 18 if PRST_BLE_ENCODING_BTHOME + default 18 if PRST_BLE_ENCODING_BTHOME_V1 + default 19 if PRST_BLE_ENCODING_BTHOME_V2 diff --git a/code/nrf-connect/samples/ble/prj.conf b/code/nrf-connect/samples/ble/prj.conf index 0a748eb..20f937b 100644 --- a/code/nrf-connect/samples/ble/prj.conf +++ b/code/nrf-connect/samples/ble/prj.conf @@ -1,5 +1,5 @@ # Enabling log has a big impact in power consumption. Only enable it while debugging. -CONFIG_LOG=n +CONFIG_LOG=y CONFIG_PWM=y CONFIG_CBPRINTF_FP_SUPPORT=y CONFIG_I2C=y @@ -8,10 +8,7 @@ CONFIG_GPIO=y CONFIG_BT=y CONFIG_BT_PERIPHERAL=y -CONFIG_BT_DEBUG_LOG=n CONFIG_BT_DEVICE_NAME="prst" -CONFIG_BT_SETTINGS=n -CONFIG_SETTINGS=n CONFIG_BT_CTLR_TX_PWR_PLUS_8=y CONFIG_SERIAL=n @@ -21,8 +18,13 @@ CONFIG_PM_DEVICE=y CONFIG_USE_SEGGER_RTT=y CONFIG_CONSOLE=n -CONFIG_RTT_CONSOLE=n -CONFIG_PINCTRL=y +# Otherwise a weird float multiplication error? +CONFIG_NEWLIB_LIBC=y +CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y -CONFIG_PRST_SLEEP_DURATION_SEC=600 \ No newline at end of file +# Application config. + +# See all options in Kconfig. +# CONFIG_PRST_SLEEP_DURATION_SEC=600 +# CONFIG_PRST_BLE_ENCODING_BTHOME_V2=y diff --git a/code/nrf-connect/samples/ble/src/ble.c b/code/nrf-connect/samples/ble/src/ble.c index 2d912d2..bc24249 100644 --- a/code/nrf-connect/samples/ble/src/ble.c +++ b/code/nrf-connect/samples/ble/src/ble.c @@ -7,7 +7,7 @@ #include "encoding.h" -LOG_MODULE_REGISTER(ble, LOG_LEVEL_DBG); +LOG_MODULE_REGISTER(ble, LOG_LEVEL_INF); static uint8_t service_data[CONFIG_PRST_BLE_ENCODING_SERVICE_DATA_LEN] = {0}; @@ -17,16 +17,17 @@ static const struct bt_data ad[] = { BT_DATA_BYTES(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME), }; -static const struct bt_data sd[] = { - BT_DATA_BYTES(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME), -}; +static const struct bt_data sd[] = {}; + +static bt_addr_le_t mac_addr; // 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"); + const uint8_t *addr = oob.addr.a.val; + LOG_INF("MAC Address: %02x:%02x:%02x:%02x:%02x:%02x", + addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]); *out = oob.addr; return 0; } @@ -36,6 +37,8 @@ int prst_ble_init() { if (IS_ENABLED(CONFIG_SETTINGS)) { RET_IF_ERR_MSG(settings_load(), "Error in settings_load()"); } + + RET_IF_ERR(get_mac_addr(&mac_addr)); return 0; } @@ -52,8 +55,6 @@ int prst_ble_adv_stop() { } int prst_ble_adv_set_data(const prst_sensors_t *sensors) { - bt_addr_le_t addr; - RET_IF_ERR(get_mac_addr(&addr)); - return prst_ble_encode_service_data(sensors, &addr, service_data, + return prst_ble_encode_service_data(sensors, &mac_addr, service_data, sizeof(service_data)); } \ No newline at end of file diff --git a/code/nrf-connect/samples/ble/src/encoding.c b/code/nrf-connect/samples/ble/src/encoding.c index 528413f..45f69e0 100644 --- a/code/nrf-connect/samples/ble/src/encoding.c +++ b/code/nrf-connect/samples/ble/src/encoding.c @@ -3,7 +3,7 @@ #include #include -LOG_MODULE_DECLARE(ble, LOG_LEVEL_DBG); +LOG_MODULE_DECLARE(ble, LOG_LEVEL_INF); int prst_ble_encode_service_data(const prst_sensors_t* sensors, const bt_addr_le_t* bt_addr, uint8_t* out, @@ -38,10 +38,98 @@ int prst_ble_encode_service_data(const prst_sensors_t* sensors, memcpy(out + 12, bt_addr->a.val, BT_ADDR_SIZE); out[18] = sensors->photo.brightness >> 8; out[19] = sensors->photo.brightness & 0xff; -#elif CONFIG_PRST_BLE_ENCODING_BTHOME - // TODO. - memset(out, 0xab, out_len); + +// https://bthome.io/v1/ +#elif CONFIG_PRST_BLE_ENCODING_BTHOME_V1 + + out[0] = 0x1c; + out[1] = 0x18; + + // 1. Soil moisture. + // uint16_t. + out[2] = (0b000 << 5) | 3; + // Type of measurement - Moisture. + out[3] = 0x14; + // Value. Factor of 0.01, so we need to multiply our the value in 100% by + // 1/0.01 = 100. + uint16_t soil_val = 10000 * sensors->soil.percentage; + out[4] = soil_val & 0xff; + out[5] = soil_val >> 8; + + // 2. Temp. + // int16_t. + out[6] = (0b001 << 5) | 3; + // Type of measurement - temperature. + out[7] = 0x02; + // Value. Factor 0.01. + int16_t temp_val = 100 * sensors->shtc3.temp_c; + out[8] = temp_val & 0xff; + out[9] = temp_val >> 8; + + // 3. Humidity + // uint16_t. + out[10] = (0b000 << 5) | 3; + // Type - humidity. + out[11] = 0x03; + // Value. Factor 0.01, over 100%. + uint16_t humi_val = 10000 * sensors->shtc3.rel_humi; + out[12] = humi_val & 0xff; + out[13] = humi_val >> 8; + + // 4. Battery voltage. + // uint16_t. + out[14] = (0b000 << 5) | 3; + // Type - voltage. + out[15] = 0x0c; + // Value. Factor of 0.001. + uint16_t batt_val = sensors->batt.millivolts; + out[16] = batt_val & 0xff; + out[17] = batt_val >> 8; + +// https://bthome.io/format/ +#elif CONFIG_PRST_BLE_ENCODING_BTHOME_V2 + // 0xfcd2 - bthome.io service UUID. + out[0] = 0xd2; + out[1] = 0xfc; + + // Service header - no encryption, bt home v2. + out[2] = 0x40; + + // Soil moisture. + out[3] = 0x14; + // Factor of 0.01, so we need to multiply our the value in 100% by 1/0.01 = 100. + uint16_t soil_val = 10000 * sensors->soil.percentage; + out[4] = soil_val & 0xff; + out[5] = soil_val >> 8; + + // Temperature. + out[6] = 0x02; + int16_t temp_val = 100 * sensors->shtc3.temp_c; + out[7] = temp_val & 0xff; + out[8] = temp_val >> 8; + + // Humidity. + out[9] = 0x03; + // Value. Factor 0.01, over 100%. + uint16_t humi_val = 10000 * sensors->shtc3.rel_humi; + out[10] = humi_val & 0xff; + out[11] = humi_val >> 8; + + // Battery voltage. + out[12] = 0x0c; + // Value. Factor of 0.001. + uint16_t batt_val = sensors->batt.millivolts; + out[13] = batt_val & 0xff; + out[14] = batt_val >> 8; + + // Illuminance. + out[15] = 0x05; + out[16] = sensors->photo.brightness >> 16; + out[17] = (sensors->photo.brightness >> 8) & 0xff; + out[18] = sensors->photo.brightness & 0xff; + #endif // Enccoding protocols + LOG_HEXDUMP_DBG(out, out_len, "Encoded BLE adv: "); return 0; } \ No newline at end of file