Bars and discos in Switzerland have to make sure their sound level stays below 100 dB(A). In this project we only collect the A-weighting loudness, but the subjective perception of the noise exposure can differ for each person.


We used the battery powered Bluetooth sound level meter UNI-T UT353 BT found on aliexpress, which can be powered by 5v. Thankfully the device has mode to stay awake.

A Raspberry Pi connects to the meter via BLE, polls the data and publishes it to the cloud.

The offial iOS app for UNI-T UT353 BT iENV

Reverse engineering UNI-T UT353

We choose the Bluetooth meter because it uses BLE and has an Android app. The decompiled Android app revealed that it is just a slightly modified heart rate monitor. It waits for the polling command 0x5e on characteristic FF01, on receive it publishes the current values and active buttons to the notify characteristic FF02.

jadx GUI

To decompile an APK open bin/jadx-gui from this Zip file with jadx-0.9.0-b648-bcadc282 and aptool

We could not figure out everything based on the decompiled source. To find out the purpose of all bytes in the sent command we needed to capture the Bluetooth HCI packets and analyze them with Wireshark. iOS 13 also added support to capture Bluetooth packets.

Publishing the data to Google Cloud

Publishing the data to Google IoT Core was very easy thanks to an exiting package by vaelen. From there it was just a matter of setting up a dashboard with BigQuery as datasource.

p := IoTPayload{
  DB:        float32(f),
  Timestamp: time.Now().Unix(),
payload, _ := json.Marshal(p)
err := thing.PublishEvent(ctx, payload)
if err != nil {
  log.Println("failed to send payload", err)

Grafana Dashboard

Next steps

  • Adding a big display to show when the noise level is too high.
  • Send the values of a lower power network.
  • Sending an alert when the noise level crosses a threshold.
  • Recording frequencies instead to determine the subjective noise.

sound meter with lora