BLE HTM (Thermometer) by nrf51822 internal temperature sensor. I confirmed with "mbed HRM1017" and "BLE Nano kit".

Dependencies:   BLE_API mbed-src nRF51822

I reffered "BLE_HTM_HRM1017".

It can be connected from "nRF Toolbox" as "HTM" application on BLE enabled Android or iOS devices. The value is not accurate because it measures nrf51822 tip temperature.

You will need to change offset value in the main.cpp.

It requires no sensor connection. The measured value will be change when you touch the nrf51822 tip or modue. I created it to check compatibility of "mbed HRM1017" and "BLE Nano kit".

Revision:
0:1865c1b765f4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sat Dec 06 08:46:12 2014 +0000
@@ -0,0 +1,189 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2013 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mbed.h"
+#include "BLEDevice.h"
+#include "ble_hrs.h"
+#include "ble_hts.h"
+
+#include "nrf_soc.h" // for internal Thermo sensoer
+
+// nRF51822n   nrf;                               /* BLE radio driver */
+BLEDevice  ble;
+DigitalOut led1(LED1);
+DigitalOut led2(LED2);
+uint8_t cnt;
+
+#define NEED_CONSOLE_OUTPUT 0 /* Set this if you need debug messages on the console;
+                               * it will have an impact on code-size and power consumption. */
+
+#if NEED_CONSOLE_OUTPUT
+Serial  pc(USBTX, USBRX);
+#define DEBUG(...) { pc.printf(__VA_ARGS__); }
+#else
+#define DEBUG(...) /* nothing */
+#endif /* #if NEED_CONSOLE_OUTPUT */
+
+const static char  DEVICE_NAME[] = "BLEnano-HTM";
+
+/* Health Thermometer Service */ 
+/* Service:  https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.health_thermometer.xml */
+/* HTM Char: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.temperature_measurement.xml */
+uint8_t             thermTempPayload[5] = { 0, 0, 0, 0, 0 };
+
+GattCharacteristic  tempChar (GattCharacteristic::UUID_TEMPERATURE_MEASUREMENT_CHAR,
+                                thermTempPayload, sizeof(thermTempPayload), sizeof(thermTempPayload),
+                                GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE);
+GattCharacteristic *htmChars[] = {&tempChar, };
+GattService        htmService(GattService::UUID_HEALTH_THERMOMETER_SERVICE, htmChars, 
+                                sizeof(htmChars) / sizeof(GattCharacteristic *));
+/* Battery Level Service */
+uint8_t            batt = 98;     /* Battery level */
+uint8_t            read_batt = 0; /* Variable to hold battery level reads */
+static uint8_t bpm2[1] = {batt};
+GattCharacteristic battLevel   ( GattCharacteristic::UUID_BATTERY_LEVEL_CHAR, bpm2, sizeof(bpm2), sizeof(bpm2),
+                                 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY |
+                                 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
+GattCharacteristic *battChars[] = {&battLevel, };
+GattService        battService(GattService::UUID_BATTERY_SERVICE, battChars, sizeof(battChars) / sizeof(GattCharacteristic *));
+
+static const uint16_t uuid16_list[] = {GattService::UUID_HEALTH_THERMOMETER_SERVICE, GattService::UUID_BATTERY_SERVICE, GattService::UUID_HEALTH_THERMOMETER_SERVICE + 0x1000 };
+
+static volatile bool triggerSensorPolling = false; /* set to high periodically to indicate to the main thread that
+                                                    * polling is necessary. */
+static Gap::ConnectionParams_t connectionParams;
+
+uint32_t quick_ieee11073_from_float(float temperature);
+
+void Update_Values();
+
+void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason)    // Mod
+{
+    DEBUG("Disconnected handle %u!\n\r", handle);
+    DEBUG("Restarting the advertising process\n\r");
+    led2 = 0;
+    ble.startAdvertising();
+
+}
+
+void onConnectionCallback(Gap::Handle_t handle,Gap::addr_type_t peerAddrType, const Gap::address_t peerAddr, const Gap::ConnectionParams_t *params)   //Mod
+{
+    DEBUG("connected. Got handle %u\r\n", handle);
+
+    connectionParams.slaveLatency = 1;
+    led2 = 1;
+    if (ble.updateConnectionParams(handle, &connectionParams) != BLE_ERROR_NONE) {
+        DEBUG("failed to update connection paramter\r\n");
+    }
+    
+}
+
+/**
+ * Triggered periodically by the 'ticker' interrupt.
+ */
+void periodicCallback(void)
+{
+
+    led1 = !led1;
+    triggerSensorPolling = true;
+        
+    // triggerSensorPolling = true; /* Note that the periodicCallback() executes in
+    //                              * interrupt context, so it is safer to do
+    //                              * heavy-weight sensor polling from the main
+    //                              * thread.*/
+}
+
+int main(void)
+{
+    led1 = 1;
+    led2 = 1;
+    wait(3);
+
+    led1 = 0;
+    led2 = 0;
+    Ticker ticker;
+    ticker.attach(periodicCallback, 1.0 );
+    DEBUG("Initialising the nRF51822\n\r");
+    ble.init();
+    ble.onDisconnection(disconnectionCallback);
+    ble.onConnection(onConnectionCallback);
+
+    ble.getPreferredConnectionParams(&connectionParams);
+
+    /* setup advertising */
+    ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
+    ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t*)uuid16_list, sizeof(uuid16_list));
+    ble.accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_THERMOMETER);
+
+    ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
+
+    ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
+    ble.setAdvertisingInterval(160); /* 100ms; in multiples of 0.625ms. */
+    ble.startAdvertising();
+
+    ble.addService(htmService);
+    ble.addService(battService);
+
+    while (true) {
+        if (triggerSensorPolling) {
+            triggerSensorPolling = false;
+
+            Update_Values();
+            
+        } else {
+            ble.waitForEvent();
+        }
+    }
+}
+
+void Update_Values()
+{
+    /* Update the temperature. Note that we need to convert to an ieee11073 format float. */
+
+    int32_t p_temp;
+    sd_temp_get(&p_temp);
+    float temperature = float(p_temp)/4.;
+    temperature -= 16.;
+           
+    DEBUG("temp:%f\n\r", temperature);
+    uint32_t temp_ieee11073 = quick_ieee11073_from_float(temperature);
+    memcpy(thermTempPayload+1, &temp_ieee11073, 4);
+
+    /* Battery Service Update */
+    /* Update battery level */
+    //ble.getGattServer().updateValue(battLevel.handle, (uint8_t*)&batt, sizeof(batt));
+    /* Decrement the battery level. */
+    batt <=50 ? batt=100 : batt--;;
+    bpm2[0] = batt;
+
+    if (ble.getGapState().connected ) {
+        ble.updateCharacteristicValue(tempChar.getValueAttribute().getHandle(), thermTempPayload, sizeof(thermTempPayload));
+        ble.updateCharacteristicValue(battLevel.getValueAttribute().getHandle(), (uint8_t *)&batt, sizeof(batt));
+    }
+}
+
+/**
+ * @brief A very quick conversion between a float temperature and 11073-20601 FLOAT-Type.
+ * @param temperature The temperature as a float.
+ * @return The temperature in 11073-20601 FLOAT-Type format.
+ */
+uint32_t quick_ieee11073_from_float(float temperature)
+{
+    uint8_t  exponent = 0xFE; //exponent is -2
+    uint32_t mantissa = (uint32_t)(temperature*100);
+    
+    return ( ((uint32_t)exponent) << 24) | mantissa;
+}