Changing UUID in Bluetooth: Peripheral HT sample

Hi,

I have successfully flashed the Zephyr Bluetooth: Peripheral HT sample to my nRF52833 DK.

I would like to change the service used for temperature indications from the currently used Health Thermometer service to the Environmental Sensing Service, and I would also like to change the characteristic UUID. This requires changing the attribute table in the following file: samples/bluetooth/peripheral_ht/src/hts.c.

When I change the characteristic UUID to BT_UUID_TEMPERATURE, the temperature measurements (in decimal) received on my phone (using nRF Connect app) are incorrect but they appear correct in hexadecimal. I don't have this issue when the characteristic UUID is BT_UUID_HTS_MEASUREMENT. Why does this happen when I change the UUID? I have attached a snippet of the altered attribute table in this file.

Thanks,

Adam

BT_GATT_SERVICE_DEFINE(ess_svc,
	BT_GATT_PRIMARY_SERVICE(BT_UUID_ESS), 

	BT_GATT_CHARACTERISTIC(BT_UUID_TEMPERATURE, BT_GATT_CHRC_INDICATE, //BT_UUID_HTS_MEASUREMENT
			       BT_GATT_PERM_NONE, NULL, NULL, NULL),

	BT_GATT_CCC(htmc_ccc_cfg_changed,
		    BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),
	
	BT_GATT_CHARACTERISTIC(BT_UUID_HUMIDITY, BT_GATT_CHRC_INDICATE, 
			       BT_GATT_PERM_NONE, NULL, NULL, NULL),
);

  • Hi Adam,

    I have been assigned this ticket. I will have a look into the case and come back to you.

    Regards,

    Naeem

  • Hi Adam,

    Thank you for your patience.

    So basically you wanted to use ESS service for temperature indication. You started with Peripheral_HT sample, as a starting point. This sample uses HTS service for temperature indication, and as per your provided code I could see your modifications.

    The modifications you have done are:
    1) Updating the name of service (from hts_svc to ess_svc). Two things here: either this is not required as it is just a name of your service defination, or you need to update the name in all instances (for example see the gatt_indicate section of the code in hts.c)

    2) Modifying the primary service from BT_UUID_HTS to BT_UUID_ESS. That is how we intend to use a different service. In this case Environment Sensing Service. Thats fine.

    3) Modifying Gatt Characteristic by using BT_UUID_TEMPERATURE instead of BT_UUID_HTS_MEASUREMENT. Here, HTS_MEASUREMENT is a "Temperature Measurement" characteristics and TEMPERATURE is "Temperature" characteristics. There is difference between their structure. I recommend going through the details in GATT Specifications.

    Temperature characteristic is single (fixed length) field containing temperature value field while the Temperature Measurement characteristic is variable length structure containing flags, values, and other fields. Also, their data types (of temperature values) are different (int vs float).

    Therefore, just changing the characteristic from BT_UUID_HTS_MEASUREMENT to BT_UUID_TEMPERATURE would not suffice.

    Have at look at the gatt_indicate section at the bottom of the hts.c. You can see some data/value manipulations / packing. There are related to the HTS_MEASUREMENT characteristic. You will have to modify/update this section to incorporate your proffered characteristic.

    I would also recommend to have a look at peripheral_esp sample that uses ESS service along with temperature characteristic. That can also help in understanding the required modifications.

    Hope it helps.

    Regards,
    Naeem

  • Thank you Naeem,

    I had a loom at the peripheral ESP sample. I am still not sure how I should change the formatting so that it prints temperature values correctly. Also, the SIG specification on the environmental service doesn't seem to explain how temperature values must be formatted either. Any suggestions as to how I should format the data?

    It looks like these lines are being used in the hts.c file for formatting the hts temperature data:

    mantissa = (uint32_t)(temperature * 100);
    exponent = (uint8_t)-2;
    
    htm[0] = 0; /* temperature in celcius */
    sys_put_le24(mantissa, (uint8_t *)&htm[1]);
    htm[4] = exponent;

    Regards,

    Adam

  • Hi Adam,

    Thank you for your patience.

    In the peripheral_esp sample, there is main.c and in the peripheral_ht there is hts.c that we need to see / compare to get how to modify / update.

    In the main.c file, in the service define, we have:

    BT_GATT_CHARACTERISTIC(BT_UUID_TEMPERATURE, 
                            BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_READ,
                            read_u16, NULL, &sensor_1.temp_value)

    while in the hts.c file, in the service define, we have:

    BT_GATT_CHARACTERISTIC(BT_UUID_TEMPERATURE, BT_GATT_CHRC_INDICATE,
                            BT_GATT_PERM_NONE, NULL, NULL, NULL)

    In the first case (main.c), there is a function read_u16 associated with the characteristic to do the operation, while in the second case (hts.c), that kind of operation is done at the end of the file (in the code you have pointed out).

    Now lets see inside read_u16:

    static ssize_t read_u16(struct bt_conn *conn, const struct bt_gatt_attr *attr,
                            void *buf, uint16_t len, uint16_t offset)
    {
        const uint16_t *u16 = attr->user_data;
        uint16_t value = sys_cpu_to_le16(*u16);
        return bt_gatt_attr_read(conn, attr, buf, len, offset, &value, sizeof(value));
    }

    And in case of hts.c:

    mantissa = (uint32_t)(temperature * 100);
    exponent = (uint8_t)-2;
    htm[0] = 0; /* temperature in celsius */
    
    sys_put_le24(mantissa, (uint8_t *)&htm[1]);
    htm[4] = exponent;

    using "Temperature" characteristic, we need a single value (please see GATT Specifications for details), and that of the type int (16 bit). Now relate it to read_u16 function: we have u16 that is integer pointer, and we are arranging in Little Endian format using sys_cpu_to_le16.

    using "Temperature Measurement" characteristic, we need variable length structure containing flags, values and other fields. You can see in hts.c that we have htm array to store multiple values; for example htm[0]=0 was to set the flag that the temperature is in Centigrade units.

    As you want to use "Temperature" characteristic with ESS service, you will need only one value.

    Hope it helps.
    Regards,
    Naeem

Related