
© 2019 NXP B.V.
PRELIMINARY
NXP IoT – Weather Station Developer Guide
1. Introduction
NXP’s Rapid IoT prototyping kit is a comprehensive,
secure and optimized IoT end node solution with a
user-friendly development environment that enables
anyone to quickly take their idea to a proof-of-concept.
Its architecture is built upon two controllers:
• Kinetis K64F for the main application, powered by
an ARM® Cortex®-M4 core
• Kinetis KW41Z for wireless connectivity, powered
by an ARM® Cortex®-M0+ core
It includes:
• 10-axis motion sensing, thanks to a combo
accelerometer / magneto-meter
• Gyroscope
• Pressure sensor for altitude measurement
• Environmental sensing via temperature/humidity,
ambient light and air quality sensors
• Display capabilities with low-power color screen
• Authentication, identification
• User interfaces with LEDs, buzzer and touch plus
push buttons
• Additional memory for data storage
• Rechargeable battery
The factory application includes USB and
Bluetooth/Thread bootloaders to program your own
firmware without external tool, and several IoT
Weather station – Developer
Guide
1. Introduction ..................................................................... 1
2. Mobile applications.......................................................... 3
Development setup ............................................... 4
Applications architecture ...................................... 4
Implementation of the main functional blocks ...... 5
3. Cloud application ........................................................... 27
Development setup ............................................. 27
Application architecture ...................................... 28
How to add a new measurement to the database . 40
Plotting measurements in graphs ........................ 42
4. Broker application.......................................................... 43
JSON structure .................................................... 46
How to process a measurement and store it in the
database 46
Revision history ..................................................................... 51

Introduction
NXP IoT – Weather Station Developer Guide
2 PRELIMINARY NXP Semiconductors
application use-cases leveraging components on
board.
In order to allow any user to evaluate this product, NXP has created the “NXP IoT – Weather station”
applications. This is a set of applications consisting of a mobile application (available in Android and
iOS), a cloud application and a demo FW for the Rapid IoT device.
The usage of the mobile and cloud applications is described in detail in the User Guide document. The
main purpose of this document is to guide a developer through the mobile and cloud applications in
order to being able to retrieve data from the sensors, sent it to the cloud application, process and plot it
in graphs.
Before using the Rapid IoT devices with the provided applications, it is necessary to flash them with the
corresponding firmware. The instructions to flash are:
- Connect one end of the provided USB cable to the computer and the other end to the micro USB
type-B connector of the SLN-RPK-NODE
- Keep SW3 button pressed while briefly pushing SW5/Reset button,
- Wait 1-2s for RGB LED to blink Green then release SW3 button
Figure 1. Instructions for USB Mass Storage Device Programming

Mobile applications
NXP IoT – Weather Station Developer Guide
NXP Semiconductors PRELIMINARY 3
RGB LED will blink green and your computer will detect a new Mass Storage drive and automatically
install the appropriate drivers.
- From your computer file explorer, drag-n-drop or copy-paste into the Mass Storage drive the Weather
station demo binary file.
Figure 2. Instructions for pushing a new application through USB
Bootloader will automatically identify the MCU target to reprogram, thanks to the binary file signature.
RGB LED will blink purple during download and blink blue during serial flash programming.
RGB LED will blink green during K64F internal flash (re)programming with the new application (read
from Serial Flash memory) and automatically reset, when ready.
Figure 3. USB Programming LED
Table 1. K64F USB Programming LED
Sequence
More information about the Rapid IoT kit can be found in NXP’s website:
https://www.nxp.com/support/developer-resources/rapid-prototyping/nxp-rapid-iot-prototyping-kit:IOTPROTOTYPING
2. Mobile applications
The Weather Station platform relies on a mobile application that can be used to connect to the
RapidIoT kit, extract the data and post it to the Cloud. This application is developed for mobile phones

Mobile applications
NXP IoT – Weather Station Developer Guide
4 PRELIMINARY NXP Semiconductors
supporting both Android and iOS operative systems. In the present section we will explain how these
applications were implemented and describe the relevant parts of the code so other developers can use
it as a guide to help them build their systems based in the RapidIoT.
The source code of both versions of the mobile application can be found in the following links:
- Android app: https://bitbucket.org/mobileknowledge/weather_station_demo-
androidapp/src/master/
- iOS app: https://bitbucket.org/mobileknowledge/weather_station_demo-iosapp/src/master/
Development setup
2.1.1.
Android application
For the Android application development, Android studio version 3.2.1 has been used as IDE. This IDE
is widely used for Android development and has extensive documentation available in the official
Android website. Link for download: https://developer.android.com/studio/ (latest version 3.2.1 at the
time this developer guide was written).
The application is programmed in Java programming language.
2.1.2.
iOS application
For the iOS application development, XCode version 10.1 has been used as IDE. In order to download
this IDE, please go to App Store in MAC OS and type “XCode”. The iOS application has been created
using Swift 4 as programming language.
Applications architecture
2.2.1.
Android and iOS application
The mobile applications are built in a layered structure, following the “Model-Business-Presentation”
design pattern. A simple diagram of the relationship between layers can be found in Figure 4.

Mobile applications
NXP IoT – Weather Station Developer Guide
NXP Semiconductors PRELIMINARY 5
Figure 4. Mobile applications architecture
In order to have a consistent structure for the Android and iOS source codes, the packages structure in
both applications should be the following:
- Presentation: This package contains the files related to the UI, i.e., Activities (Android) and View
Controllers (iOS).
- Business Logic: This package contains the files related to the application logic: BLE connectivity,
Internet connectivity, JSON generation, Data validation, etc.
- Data model: This package contains the files related to the data model, i.e., Device class or
Measurement class.
- Persistent: This package will contain the files related to the persistent data storage, i.e., shared
preferences (Android), UserDefaults (iOS).
Implementation of the main functional blocks
For the sake of a clear structure and a practical use of the present document, we will analyze the
applications code from a functional point of view. This way, we will address the operations that should
be interesting for a developer willing to implement an application to obtain data from the RapidIoT
device and use it in a backend system.
2.3.1.
Connecting to the RapidIoT
RapidIoT BLE configuration
The RapidIoT BLE interface is configured to provide the user with a set of BLE services and
characteristics to ease access to the information retrieved from the sensors integrated in the device.
Each sensor in the device has its own BLE characteristic where the microcontroller posts the
information, so the user can filter the information he will be notified about.

Mobile applications
NXP IoT – Weather Station Developer Guide
6 PRELIMINARY NXP Semiconductors
The RapidIoT follow the UUID characteristics convention for the main Bluetooth sensor types that are
included in the Bluetooth specifications. In the following table, you can find the UUID used for the
service and characteristics used.
0ab5b670-c2ce-c4ab-e711-6ccbaa65c888
00002A6D-0000-1000-8000-00805F9B34FB
Temperature characteristic
00002A1C-0000-1000-8000-00805F9B34FB
00002A6F-0000-1000-8000-00805F9B34FB
0ab5b672-c2ce-c4ab-e711-6ccbaa65c888
MAC Address characteristic
0e1bb826-612e-aca9-0e49-88f712ec1cb7
The pressure, temperature and humidity data use the UUIDs defined in the Bluetooth specifications
while the light sensor information is posted to a non-standard UUID. The sensors characteristics have
Notify and Read properties so the user can read one data asynchronously or ‘subscribe’ to the
characteristic and receive updates with the sensor information. The RapidIoT kit also includes a
characteristic to obtain the device MAC address.
2.3.2.
Collecting data from the sensors
Implementation in Android
The Android application implements a Singleton class called WSDBleManager to manage the
connection to the RapidIoT device. This class includes methods to scan for devices in range, trigger the
connection/disconnection to a certain device, or the definition of the BleManager callbacks for Android.
The WSDBleManager makes use of a third party library that is included in the dependencies section
from the build.gradle file of the app. This way, the WSDBleManager extends the BleManager and
BleManagerCallbacks from this library:
public class WSDBleManager extends BleManager<BleManagerCallbacks> {
Figure 5. ‘WSDBleManager’ class header in Android app
The ‘BleManagerCallbacks’ includes methods that are called depending on the state that the
connection goes through. We can highlight the following methods:

Mobile applications
NXP IoT – Weather Station Developer Guide
NXP Semiconductors PRELIMINARY 7
void onDeviceConnected(final BluetoothDevice device);
void onDeviceDisconnected(final BluetoothDevice device);
void onDeviceReady(final BluetoothDevice device);
void onBondingRequired(final BluetoothDevice device);
void onBonded(final BluetoothDevice device);
Figure 6. ‘BLEManagerCallbacks’ in Android app
The ‘BleManagerCallbacks’ can be overwritten at any moment by using the method ‘setGattCallbacks’
from the ‘BleManager’ class.
Scanning for devices
The method used to start scanning for devices is called ‘scanAvailableDevices’. This method is present
in the ‘WSDBleManager’ and requires as input an object that implements the ‘WSDBleScanListerner’
interface. This interface defines two methods: the ‘onDeviceScanned’ and the ‘onDeviceScanTimeout’.
The first will be called when a new device is discovered and the second when the scanning has
reached its timeout. They are used in the main activity to show the newly discovered devices to the
user.
public void scanAvailableDevices(WSDBleScanListener wsdBleScanListener) {..}
Figure 7. ‘scanAvailableDevices’ method in Android
In the ‘scanAvailableDevices’ method we configure the settings that we are going to use for the
scanning and include a filter so we will only look for devices with our Service UUID:
final ScanSettings scanSettings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_BALANCED)
// Refresh the devices list continuously
.setReportDelay(0)
// Hardware filtering has some issues on selected devices
.setUseHardwareBatchingIfSupported(false)
.build();
ScanFilter scanFilterDES = new ScanFilter.Builder()
.setServiceUuid(ParcelUuid.fromString(WSDemoUUID.toString()))
.build();
Figure 8. Set scan settings in Android app
Once the settings and filter are configured, it starts scanning:
bluetoothLeScanner.startScan(filterList, scanSettings, scanCallback);
Figure 9. Start scan in Android app

Mobile applications
NXP IoT – Weather Station Developer Guide
8 PRELIMINARY NXP Semiconductors
The ‘WSDBleManager’ holds a list with the devices that have been scanned in the ArrayList
‘scanListDevices’. Whenever a device is scanned, we check that it has not been discovered previously
and then process it as a new one, calling the ‘onDeviceScanned’ method from the
‘WSDBleScanListerner’.
Connecting to a device
When the user selects one of the devices from the list, we trigger the connection to that device by
calling the ‘initConnection’ from the ‘WSDBleManager’:
showConnectingDialog();
getBLEManager().initConnection (deviceClicked);
getBLEManager().stopScan();
Figure 10. Start a connection to a device in the Android app
The ‘initConnection’ method needs as input an object of the ‘DeviceModel’ type. This object holds
information that will be used by the underlying library to identify the device we want to connect to.
public void initConnection(DeviceModel bleDevice) {
List<ParcelUuid> serviceUuidList = bleDevice.getServiceUuidList();
mDevice = bleDevice;
for(int i=0; i< serviceUuidList.size(); i++){
if(serviceUuidList.get(i).getUuid().equals(WSDemoUUID)){
mDevice.setDeviceType("WSDDemoUUID");
}
}
connect(mDevice.getDevice());
}
Figure 11. ‘initConnection’ in Android app
In the ‘initConnection’ method, before starting the connection, we check that the UUID from the
RapidIoT service is among the ones available in the specified device.
When the connection to the device is successfully established, the method ‘onDeviceReady’ is called. It
is important to remark that the first time a phone is connected to a RapidIoT kit, it might ask for a PIN to
verify the connection. The process is called bonding. In this case, the ‘onBondingRequired’ method is
called. You can use this method to display a message to the user saying that he needs to introduce the
PIN to finish the connection. Once the user correctly introduces the PIN, the ‘onBonded’ method is
called.
Below we can see the ‘onBondingRequired’, ‘onBonded’ and ‘onDeviceReady’ methods from the
application:
@Override
public void onBondingRequired(BluetoothDevice device) {
super.onBondingRequired(device);
bondingRequired = true;
Toast.makeText(getApplicationContext(), "Please follow pairing instructions in
Notification Bar", Toast.LENGTH_LONG).show();
}

Mobile applications
NXP IoT – Weather Station Developer Guide
NXP Semiconductors PRELIMINARY 9
Figure 12. ‘onBondingRequired’ method in Android app
@Override
public void onBonded(BluetoothDevice device) {
super.onBonded(device);
//If the connecting dialog is shown we close it
if(connectingDialog.isShowing()) {
connectingDialog.dismiss();
}
getBLEManager().generateSessionID(); // We generate a sessionID
if(bondingRequired) {
if(MeasurementManager.getInstance().isCloudPostingEnabled(ctx))
MeasurementManager.getInstance().startPostDataService(ctx);
goToDataDisplayActivity(); // we move to the DataDisplay screen
}
}
Figure 13. ‘onBonded’ method in Android app
@Override
public void onDeviceReady(BluetoothDevice device) {
super.onDeviceReady(device);
getBLEManager().generateSessionID(); // We generate a sessionID
if(connectingDialog.isShowing()) {
connectingDialog.dismiss();
}
if(!bondingRequired) {
if(MeasurementManager.getInstance().isCloudPostingEnabled(ctx))
MeasurementManager.getInstance().startPostDataService(ctx);
goToDataDisplayActivity();
}
else{
bondingRequired = false;
}
}
Figure 14. ‘onDeviceReady’ method in Android app
If the bonding procedure is required, we set the Boolean ‘bondingRequired’ to true. In that case, we will
redirect the user to the next screen (data display screen) when the device is bonded. In case the
RapidIoT device is already known by the app and no bonding is needed, we will redirect when the
‘onDeviceReady’ method is called.
After the connection is successfully achieved, the ‘BleManager’ executes the ‘initGatt’ method from the
‘BleManagerGattCallback’. This method should be overwritten with all requests needed to initialize the
profile. In our case, we will use it to request the ‘subscription’ to all notifications from the sensors
characteristics:

Mobile applications
NXP IoT – Weather Station Developer Guide
10 PRELIMINARY NXP Semiconductors
private final BleManagerGattCallback mGattCallback = new BleManagerGattCallback()
{
@Override
protected Deque<Request> initGatt(final BluetoothGatt gatt) {
final LinkedList<Request> requests = new LinkedList<>();
// We enqueue the notification request for every sensor characteristic
requests.push(Request.newEnableNotificationsRequest(
mPressureCharacteristic));
requests.push(Request.newEnableNotificationsRequest(
mHumidityCharacteristic));
requests.push(Request.newEnableNotificationsRequest(
mTemperatureCharacteristic));
requests.push(Request.newEnableNotificationsRequest(
mLightCharacteristic));
return requests;
}
Figure 15. ‘initGatt’ method in Android app
Processing data from the sensors
Once we have requested notifications from a sensor characteristic, we will receive a message every
time the RapidIoT delivers a new measurement from that sensor. This message is received through the
‘onCharacteristicNotified’ method from the ‘BleManagerGattCallback’. As an example, we will look at
the case of a measurement coming from the Pressure sensor:
@Override
public void onCharacteristicNotified(final BluetoothGatt gatt,
final BluetoothGattCharacteristic characteristic){
if(characteristic.getUuid().equals(PressureUUID)){
byte[] rawpressure = characteristic.getValue();
MeasurementModel measurement = new MeasurementModel(
MeasurementUtils.getPressureMeasurement(rawpressure));
if(fitsRefreshRate(MeasurementManager.TYPE_PRESSURE)){
getMeasurementManager().addPressure(measurement);
}
}
Figure 16. Read characteristic value and process it in Android app
As can be seen from the snippet above, we check the characteristic of the notification received to
identify the sensor it comes from. Once we know the type of measurement we need to convert the data
to float and create with it a ‘MeasurementModel’ type object:
byte[] rawpressure = characteristic.getValue();
MeasurementModel measurement = new MeasurementModel(
MeasurementUtils.getPressureMeasurement(rawpressure));

Mobile applications
NXP IoT – Weather Station Developer Guide
NXP Semiconductors PRELIMINARY 11
Figure 17. Process raw measure in Android app
To perform the conversion we rely on the ‘MeasurementUtil’ static class which basically operates with
the payload bytes to extract the value depending on the notation followed for every sensor.
In case the timings fit the refresh rate selected by the user (i.e., the time difference with the last
measurement processed is above the refresh rate selected) the measurement is stored using the
‘addPressure’ method from ‘MeasurementManager’:
if(fitsRefreshRate(MeasurementManager.TYPE_PRESSURE)){
getMeasurementManager().addPressure(measurement);
}
Figure 18. Add Pressure measurement in Android app
The ‘MeasurementManager’ is a singleton class used to store and handle the data extracted from the
RapidIoT kit. On it we define four ArrayLists to store the latest measurements of every type:
// We declare the four ArrayList that store the latest measurements for every type
private ArrayList<MeasurementModel> arrayTemperature = new ArrayList<>();
private ArrayList<MeasurementModel> arrayHumidity = new ArrayList<>();
private ArrayList<MeasurementModel> arrayPressure = new ArrayList<>();
private ArrayList<MeasurementModel> arrayLight = new ArrayList<>();
Figure 19. Measurements arrays in Android app
The most important methods that the ‘MeasurementManager’ class implements are the following:
public void addTemperature(MeasurementModel measurement){..}
public void addHumidity(MeasurementModel measurement){..}
public void addPressure(MeasurementModel measurement){..}
public void addLight(MeasurementModel measurement){..}
public void startPostDataService(Context mContext){..}
public void stopPostDataService(Context mContext){..}
public ArrayList<MeasurementModel> getSelectedMeasurementArray(){..}
Figure 20. ‘MeasurementManager’ class in Android app
The methods ‘addTemperature’, ‘addHumidity’, ‘addPressure’ and ‘addLight’ add a measurement to the
corresponding ArrayList. The ‘getSelectedMeasurementArray’ returns the ArrayList with the last four
measurements so they can be printed in the table displayed to the user. The ‘startPostDataService’ and
‘stopPostDataService’ start and stop the background service that is in charge of posting the data to the
server.
Implementation in iOS
Similar to the Android application, there is a singleton object for the BLE communication. This object is
called ‘sharedBLEInstance’ and is created as follows in the ‘BLEManager’ class:

Mobile applications
NXP IoT – Weather Station Developer Guide
12 PRELIMINARY NXP Semiconductors
static let sharedBLEInstance = BLEManager()
Figure 21. Getting the singleton instance for the BLEManager in iOS
The ‘BLEManager’ class implements several delegates which are used in the different phases of the
Bluetooth communication. You can find a list of these delegate methods in Figure 22.
protocol BLEDelegate {
func bleDidUpdateState(state: CBManagerState)
func bleDidConnectToPeripheral(peripheral: CBPeripheral?)
func bleDidFailConnectToPeripheral()
func bleDidDisconnectFromPeripheral()
func bleDidReceiveData(char: String, data: Data?)
func bleDidDiscoverDevice(peripheral: CBPeripheral?, advertisementLocalName: String?)
}
Figure 22. BLEManager delegate methods
The Rapid IoT device in the iOS application is another Singleton object, so it can be accessed
anywhere through the application. This object is updated each time a new Rapid IoT device is
connected/disconnected. It contains 4 arrays of four elements, one for each measurement. The ‘Device’
class definition can be found in Figure 23.
class Device : NSObject{
private var name: String?
private var bleMACAddress: String?
private var temperatureData : Array<Measurement> = Array<Measurement>(repeating:
Measurement(value: nil,timestamp: nil), count: 4)
private var pressureData : Array<Measurement> = Array<Measurement>(repeating:
Measurement(value: nil,timestamp: nil), count: 4)
private var humidityData : Array<Measurement> = Array<Measurement>(repeating:
Measurement(value: nil,timestamp: nil), count: 4)
private var lightData : Array<Measurement> = Array<Measurement>(repeating: Measurement(value:
nil,timestamp: nil), count: 4)
//The device object follows the singleton pattern, we will access this instance throughout the whole
application.
static let deviceInstance = Device()
[…]
Figure 23. ‘Device’ class in iOS app
Scanning for devices
Right after initializing the application, the BLEManager starts scanning for Rapid IoT devices. This is
done in the ‘WelcomeViewController’ class inside the ‘viewWillAppear’ method as shown in Figure 24.

Mobile applications
NXP IoT – Weather Station Developer Guide
NXP Semiconductors PRELIMINARY 13
if(BLEManager.sharedBLEInstance.getBLEState() == CBManagerState.poweredOn){
if(!BLEManager.sharedBLEInstance.isBLEScanning())
{
BLEManager.sharedBLEInstance.startScan()
}
}
Figure 24. Start scanning for new Bluetooth devices
Before starting the scanning, we check that the BLE adapter state is powered on and there is no active
scanning already ongoing. In order to scan only for Rapid IoT devices, we need to perform a
configuration in the ‘startScan’ method. This is shown in Figure 25. We include only the service UUID
we are interested in, in this case the Rapid IoT service UUID.
func startScan() {
if !isBLEAvailable() {
print("[ERROR] Couldn´t start scanning, BLE not available")
return
}
isScanning = true
let services:[CBUUID] = [CBUUID(string: Constants.WEATHER_SERVICE_UUID)]
self.centralManager!.scanForPeripherals(withServices: services, options:
[CBCentralManagerScanOptionAllowDuplicatesKey: true])
}
Figure 25. ‘startScan’ method in iOS app
When a new device is scanned, the ‘bleDidDiscoverDevice’ callback in the ‘WelcomeViewController’
class is called. This can be seen in Figure 26. Every time a new device is discovered, it is necessary to
check that it is not null and that the device is not already contained in the ‘bleDevicesList’.
The Rapid IoT devices stored in the ‘bleDevicesList’ have a field called ‘lastUpdate’. This field is
updated each time a device is discovered via BLE and every time the ‘devicesTable’ is reloaded we
check if the device has not been found in the last 2 seconds. In case the device has not been found in
the last 2 seconds, we remove it from the ‘devicesTable,’ as we consider it is not available to connect.

Mobile applications
NXP IoT – Weather Station Developer Guide
14 PRELIMINARY NXP Semiconductors
func bleDidDiscoverDevice(peripheral: CBPeripheral?, advertisementLocalName: String?){
if let mPeripheral = peripheral?.name{
print("Discovered device: " + mPeripheral)
}
else {
print("Couldnt get name of discovered device")
}
if(peripheral?.name != nil && advertisementLocalName != nil &&
!(bleDevicesList.map{$0.0}).contains(peripheral!)){
bleDevicesList.append((peripheral!, advertisementLocalName!, Date()))
}
else if let i = bleDevicesList.index(where: ({$0.peripheral === peripheral})){
bleDevicesList[i].lastUpdate = Date()
}
//Update devices table to show the user the new discovered device (if any)
devicesTable.reloadData()
}
Figure 26. Discover new Bluetooth devices in iOS app
Connecting to a device
When the user taps on any device in the ‘devicesTable’ list the connection procedure starts. This is
shown in Figure 27.
As can be observed in the comments inside the code snippet, there are three options when the user
taps on any device in the table:
1- The device tapped in the table is a new device and we are connected to another device. In this
case we display a pop up warning the user if he wants to disconnect from the old device and
connect to the new one.
2- The device tapped is the same we are currently connected to. In this case we just move to the
Data display screen and nothing in the Bluetooth connection changes.
3- There is no device connected in the application and the user taps in a device. In this case we
just start the connection with the new device.

Mobile applications
NXP IoT – Weather Station Developer Guide
NXP Semiconductors PRELIMINARY 15
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.devicesTable.deselectRow(at: indexPath, animated: true)
//When the user taps a cell there are three different options:
// 1 - The device tapped is not the same device it is connected to the app, in this case show a dialog
to warn the user if he wants to switch devices
// 2 - The device tapped is the same device connected to the app, take the user to the Data display
view
// 3 - There are no devices connected to the app, in this case stops the bluetooth scanning and
begins the connection procedure with the selected device
if(BLEManager.sharedBLEInstance.isConnected() && (bleDevicesList[indexPath.row].advName !=
BLEManager.sharedBLEInstance.getCurrentPeripheralName())){
showDisconnectDialog(indexPath: indexPath)
}
else if (BLEManager.sharedBLEInstance.isConnected() && (bleDevicesList[indexPath.row].advName
== BLEManager.sharedBLEInstance.getCurrentPeripheralName())){
self.performSegue(withIdentifier: "ShowView", sender: self)
}
else{
BLEManager.sharedBLEInstance.stopScan()
BLEManager.sharedBLEInstance.connectToPeripheral(peripheral:
bleDevicesList[indexPath.row].peripheral)
selectedIndexPath = indexPath
}
}
Figure 27. Connect to a device in iOS app
As previously explained, the ‘BLEManager’ class is in charge of managing the Bluetooth
communications. When a new device is connected, the ‘didConnect’ callback is called. Right after we
get a valid connection we stop scanning for new devices and proceed to discover the services and
characteristics of the new connected device.
The characteristics we are looking for appear in section 2.3.1, we need to subscribe to those
characteristics in order to get notifications each time they are written with a new value. This can be
found in Figure 28.

Mobile applications
NXP IoT – Weather Station Developer Guide
16 PRELIMINARY NXP Semiconductors
//CBPeripheral delegate
//When the services have been discovered we call the chracteristics of that service.
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
if error != nil {
print("[ERROR] Error discovering services. \(error!.localizedDescription)")
return
}
for service in peripheral.services! {
peripheral.discoverCharacteristics(nil, for: service)
}
}
//When the device services have been read we need to read all the chracteristics from the MAC
address and sensors data
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error:
Error?) {
if error != nil {
print("[ERROR] Error discovering characteristics. \(error!.localizedDescription)")
return
}
for characteristic in service.characteristics! {
self.characteristics[characteristic.uuid.uuidString] = characteristic
if(characteristic.uuid.uuidString == Constants.MAC_ADDRESS_CHAR_READ_UUID){
self.readMACAddressCharacteristic()
self.enableNotificationsTemp(enable: true)
self.enableNotificationsHumidity(enable: true)
self.enableNotificationsPressure(enable: true)
self.enableNotificationsLight(enable: true)
}
}
}
Figure 28. Discover services and characteristics in iOS app
Processing data from the sensors
Once we are subscribed to the Bluetooth notifications to receive the measurements in their
corresponding characteristics, let’s see how to process and store them in the application.
Every time the ‘BLEManager’ receives a new value for any subscribed characteristic, the
‘didUpdateValueFor’ callback method is called. We check what measurement the characteristic that
has been written corresponds to and call a delegate method to notify the controller. This is shown in
Figure 29.