🌡️

How to measure temperature and humidity by iOS App

2023/01/09に公開

This article is an English version of the following link.
https://qiita.com/tanakadaichi_1989/items/57fb3be60e6151421792

What to write in this article

  • How to measure temperature and humidity by iOS App with IoT device "MESH".

The reason why I want to measure temperature and humidity

To take measure infection and heat stroke.

I know that it is important to control temperature and humidity to prevent infection and heat stroke, but I didn't kow actual temperature and humidity data.

I had taken part of the project to develop an iOS app that can connect to sensors with Bluetooth.

To remember that experience, I took on the challenge of developing iOS app.

Development Environment

PC
MacBook Air (2020,M1) Memory: 16GB Storage: 1TB

Language
Swift

Framework
SwiftUI

MESH
Temperature/Humidity Block

Measurable temperature range: -10°C to 50°C
Humidity range: 0% to 100%.
Charging: Micro-USB

https://meshprj.com/jp/products/blocks/MESH-100TH.html

App Requerement

  • Connect a iOS App and a MESH device using BLE communication
  • The MESH device sends temperature and humidity measurement data to PC every 0.5 seconds after connection
  • Check the current temperature and humidity with the iOS app
  • In this case, a iOS device is the central unit and the MESH device is the peripheral unit (*Central peripherals are described later)

What is BLE communication ?

  • A power-saving version of Bluetooth, a short-range wireless communication standard.
  • Devices such as PCs and smartphones that correspond to the parent device for communication are called central.
  • A device corresponding to a child device of communication such as MESH or a lost-and-found tag is called a peripheral.

BLE Communication Flow

This is a simplified version for the sake of clarity.

  1. when a peripheral is waiting for communication, it sends a radio signal to an unspecified number of surrounding devices (advertise)
    Central receives advertisements by performing a scan.
  2. Central requests a connection from a peripheral with which it wishes to communicate on a one-to-one basis
  3. Peripheral receives connection request from Central and switches to one-to-one communication (GATT communication)
  4. peripheral sends communication data to Central * 1.
  5. Central requests the peripheral to disconnect.

Features of GATT communication

  • exchange measurement data as service and characteristic

Point I feel difficult

When the connection to the sensor is established, set the delegate of the peripheral.

  • I didn't realize that I needed to put peripheral.delegate = self and wasted a lot of time.
DeviceManager.swift
  func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
        guard let peripheral = devices.first?.peripheral else { return }
        peripheral.delegate = self
        peripheral.discoverServices(services)
        print("centralManager did connect peripheral: \(peripheral.name?.description ?? "unnnamed")")
    }

Send commands to peripherals to enable block function, set temperature, humidity, and measurement frequency

  • Knowledge required: Little-endian and hexadecimal addition (required to calculate checksum values)
  • Hexadecimal addition: supported by the "Calculator" app pre-installed on the MacBook Air
DeviceManager.swift
    func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
        let byteArray: [UInt8] = [ 0x00, 0x02, 0x01, 0x03]
        let data = Data(byteArray)
        let batteryLevelArray: [UInt8] = [0x00,0x03,0x00,0x03]
        let batteryLevelData = Data(batteryLevelArray)
        
        let modeSettingArray: [UInt8] = [0x01,0x00,0x01,0xF4,0x01,0xFF,0x9C,0x64,0x00,0x00,0x00,0x11,0x11,0x20,0x38]
        let modeSettingData = Data(modeSettingArray)
        
        guard let characteristics = service.characteristics else { return }
        
        for characteristic in characteristics {
            peripheral.setNotifyValue(true, for: characteristic)
            peripheral.writeValue(data, for: characteristic, type: .withResponse)
            peripheral.writeValue(data, for: characteristic, type: .withoutResponse)
        }
        print("did Discover Characteristics for executed")
        
        for characteristic in characteristics {
            peripheral.setNotifyValue(true, for: characteristic)
            peripheral.writeValue(batteryLevelData, for: characteristic, type: .withResponse)
            peripheral.writeValue(batteryLevelData, for: characteristic, type: .withoutResponse)
        }
        
        for characteristic in characteristics {
            peripheral.setNotifyValue(true, for: characteristic)
            peripheral.writeValue(modeSettingData, for: characteristic, type: .withResponse)
            peripheral.writeValue(modeSettingData, for: characteristic, type: .withoutResponse)
        }
        
    }

Running the actual application

YouTube
This video is recorded how to connect this app and a MESH device.
https://www.youtube.com/watch?v=cFE443btEac

When moved throughout the day, the indoor humidity was found to fluctuate around 10-20% per day.

Especially in the morning, when the humidity tends to be below 40%, which increases the risk of infection, I cloud take measures such as drying laundry in the room, boiling water, etc.

(Depending on the size of the room and the number of people in the room, maybe you don't have to bother buying a humidifier ... )

FYI

GitHub
https://github.com/tanakadaichi1989/Thermometer-Hygrometer

App Store
You can get this app from App Store.
(launched in 2023/01/09 🎉)
https://apps.apple.com/us/app/thermometer-hygrometer/id1663445896

MESH Technical Documents
https://developer.meshprj.com/hc/ja

Discussion