GithubHelp home page GithubHelp logo

wave-reader's Introduction

Airthings Wave Sensor Reader

Airthings Wave is a smart Radon detector, including sensors for temperature and humidity measurements. Additionally, you can simply wave in front of the device to get a visual indication of your radon levels.

This is a project to provide users a starting point (read_wave.py and read_wave2.py) to read current sensor values from the 1st and 2nd generation Airthings Wave devices using a Raspberry Pi 3 Model B over Bluetooth Low Energy (BLE).

Table of contents

Requirements

The following tables shows a compact overview of dependencies for this project.

List of OS dependencies

OS model/version Comments
Raspbian Raspberry Pi 3 Model B Used in this project.
Linux x86 Debian Should work according to bluepy

List of linux/raspberry dependencies

package version Comments
python 2.7 or 3 Tested with python 2.7.13 and 3.7.3
python-pip pip for python2.7
python3-pip pip3 for python3
git To download this project
libglib2.0-dev For bluepy module

List of third-party Python dependencies

module version
bluepy 1.3.0

Setup Raspberry Pi

The first step is to setup the Raspberry Pi with Raspbian. An installation guide for Raspbian can be found on the Raspberry Pi website. In short: download the Raspbian image and write it to a micro SD card.

To continue, you need access to the Raspberry Pi using either a monitor and keyboard, or by connecting through WiFi or ethernet from another computer. The latter option does not require an external screen or keyboard and is called “headless” setup. To access a headless setup, you must first activate SSH on the Pi. This can be done by creating a file named ssh in the boot partition of the SD card. Connect to the Pi using SSH from a command line interface (terminal):

The default password for the pi user is raspberry.

Turn on the BLE interface

In the terminal window on your Raspberry Pi:

pi@raspberrypi:~$ bluetoothctl
[bluetooth]# power on
[bluetooth]# show
[bluetooth]# exit

After issuing the command show, a list of bluetooth settings will be printed to the Raspberry Pi terminal window. Look for Powered: yes.

Installing linux and python packages

Raspbian images usually comes with Python (2 and/or 3) pre-installed.

pi@raspberrypi:~$ python2 --version
pi@raspberrypi:~$ python3 --version

Install dependencies:

pi@raspberrypi:~$ sudo apt-get update && sudo apt-get install libglib2.0-dev git
# For Python 2
pi@raspberrypi:~$ sudo apt-get install python-pip 
pi@raspberrypi:~$ sudo pip2 install bluepy==1.3.0
# For python 3
pi@raspberrypi:~$ sudo apt-get install python3-pip
pi@raspberrypi:~$ sudo pip3 install bluepy==1.3.0

Downloading script

Downloading using git:

pi@raspberrypi:~$ sudo git clone https://github.com/Airthings/wave-reader.git

Downloading using wget:

pi@raspberrypi:~$ wget https://raw.githubusercontent.com/Airthings/wave-reader/master/read_wave.py

Usage

The general format for calling the scripts is as follows:

# For 1st Gen Wave
sudo python read_wave.py SERIAL_NUMBER SAMPLE_PERIOD [> somefile.txt]
# For 2nd Gen Wave
sudo python read_wave2.py SERIAL_NUMBER SAMPLE_PERIOD [> somefile.txt]

After a short delay, the script will print the current sensor values to the Raspberry Pi terminal window. Optionally, you may pipe the readings to a text-file using > somefile.txt. Exit the script using Ctrl+C.

Positional input arguments Type Description
SERIAL_NUMBER Integer 10-digit number found under the magnetic backplate of your Airthings product.
SAMPLE_PERIOD Integer Time in seconds between reading the current sensor values (excluding the overhead of connecting to target).
Device Serial number Script to use
Wave 1st Gen 2900xxxxxx read_wave.py
Wave 2nd Gen 2950xxxxxx read_wave2.py

Example output of a 1st Gen Wave device:

Timestamp: 2020-02-10 10:14:32, Humidity: 21.5 %rH, Temperature: 22.8 *C, Radon STA: 36 Bq/m3, Radon LTA: 27 Bq/m3
Timestamp: 2020-02-10 10:20:48, Humidity: 21.5 %rH, Temperature: 22.8 *C, Radon STA: 36 Bq/m3, Radon LTA: 27 Bq/m3
Timestamp: 2020-02-10 10:25:58, Humidity: 21.5 %rH, Temperature: 22.9 *C, Radon STA: 36 Bq/m3, Radon LTA: 27 Bq/m3
Timestamp: 2020-02-10 10:30:10, Humidity: 21.5 %rH, Temperature: 22.9 *C, Radon STA: 36 Bq/m3, Radon LTA: 27 Bq/m3
Timestamp: 2020-02-10 10:35:20, Humidity: 21.5 %rH, Temperature: 22.8 *C, Radon STA: 36 Bq/m3, Radon LTA: 27 Bq/m3

Note: The scripts require that your device is advertising. If your device is paired/connected to e.g. a phone, you need to turn off bluetooth on your phone while using the scripts.

Note on choosing a sample period: On 1st Gen Wave, temperature and humidity are updated every time we read the wave. On 2nd Gen Wave, temperature and humidity are updated every 5 minutes. On both devices, radon measurements are updated once every hour.

Sensor data description

sensor units Comments
Datetime YYYY-MM-DD HH:MM:SS Only available on 1st Gen Wave
Humidity %rH
Temperature °C
Radon short term average Bq/m3 First measurement available 1 hour after inserting batteries
Radon long term average Bq/m3 First measurement available 1 hour after inserting batteries

Contribution

Let us know how it went! If you want contribute, you can do so by posting issues or suggest enhancement here.

Release notes

Release dated 10-Feb-2020

  • Added read_wave2.py to support 2nd Gen wave devices
  • Added py3 compatibility
  • Removed tableprint dependency so all py3 versions can be used
  • Removed redundant positional argument pipe (since tableprint is removed)
  • Updated bluepy version dependency from 1.2.0 to 1.3.0

Release dated 14-Dec-2018

  • Added SAMPLE-PERIOD as an input argument.

Initial release 13-Dec-2018

wave-reader's People

Contributors

devdavidkarlsson avatar orjangj avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

wave-reader's Issues

document all values returned

I modified the read_wave2.py to print(data)
(1, 97, 19, 0, 108, 108, 2196, 65535, 65535, 65535, 0, 65535)
Humidity: 48.5 %rH, Temperature: 21.96 *C, Radon STA: 108 Bq/m3, Radon LTA: 108 Bq/m3

I understand the following:
data[1] = humidity, but the displayed value is divided by 2.0
data[4] = radon Bq/m3 Short Term Average
data[5] = radon Bq/m3 Long Term Average
data[6] = temperture in Celsius, but the displayed value is divided by 100.0

Can I have someone document:
data[0]
data[2]
data[3]
data[7]
data[8]
data[9]
data[10]
data[11]

Radon Short Time Average is not a real moving average over last 24hr

Hello,

I use a pseudo-inversing algo from numpy in order to obtain original values from a moving average series. When i use this script on movig average from randomly generated number, everyting is ok, i can obtain original values with a small error but when I use the same script on STA values from last 7 days, the result not as expected, many negative values, high volatility which makes me think that STA in not a real moving (rolling) average, but something else. Can you provide the algorithm used for obtaining STA values or can you provide the raw, instant radon values over the last hour ?

Here is the python script I use:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.ndimage import shift
import random

def reconstruct_orig(sm_x:np.ndarray, win_size:int=7):

    arr_size = sm_x.shape[0]+win_size
    # get A and its inverse     
    A = (np.tril(np.ones((arr_size,arr_size)),-1) - np.tril(np.ones((arr_size,arr_size)),-(win_size+1)))/win_size
    A = A[win_size:,:]
    pA = np.linalg.pinv(A) #pseudo inverse
    return np.dot(pA, sm_x)

if __name__=="__main__":

    data = np.loadtxt("sta.csv", delimiter=",",dtype='float')
    orig = pd.DataFrame(data)
    
    re_x = reconstruct_orig(orig, win_size=24)
    
    data = np.concatenate([np.zeros((23)), data]) # right shift 24 values  

    plt.plot(data,label='original x')
    plt.plot(re_x, label='reconstructed x')
    plt.legend()
    plt.show()

REVERSE_RND
reverse_sta

Value cannot be read after latest FW update

I have purchased two new Wave devices and connected first with the my Andround phone to test. During setup it updated the FW on the devices. Android app can read and connect to WAVE but the python script fails to do so spotting out "comerr"

I tested with gatttool to reach the characteristics and got these ones.

characteristics
handle: 0x0002, char properties: 0x02, char value handle: 0x0003, uuid: 00002a00-0000-1000-8000-00805f9b34fb
handle: 0x0004, char properties: 0x02, char value handle: 0x0005, uuid: 00002a01-0000-1000-8000-00805f9b34fb
handle: 0x0006, char properties: 0x02, char value handle: 0x0007, uuid: 00002a04-0000-1000-8000-00805f9b34fb
handle: 0x0008, char properties: 0x02, char value handle: 0x0009, uuid: 00002ac9-0000-1000-8000-00805f9b34fb
handle: 0x000c, char properties: 0x02, char value handle: 0x000d, uuid: b42e4dcc-ade7-11e4-89d3-123b93f75cba
handle: 0x000f, char properties: 0x2c, char value handle: 0x0010, uuid: b42e50d8-ade7-11e4-89d3-123b93f75cba
handle: 0x0013, char properties: 0x10, char value handle: 0x0014, uuid: b42e538a-ade7-11e4-89d3-123b93f75cba
handle: 0x0018, char properties: 0x1c, char value handle: 0x0019, uuid: f000ffc1-0451-4000-b000-000000000000
handle: 0x001c, char properties: 0x1c, char value handle: 0x001d, uuid: f000ffc2-0451-4000-b000-000000000000
handle: 0x0020, char properties: 0x14, char value handle: 0x0021, uuid: f000ffc5-0451-4000-b000-000000000000
handle: 0x0025, char properties: 0x02, char value handle: 0x0026, uuid: 00002a23-0000-1000-8000-00805f9b34fb
handle: 0x0027, char properties: 0x02, char value handle: 0x0028, uuid: 00002a24-0000-1000-8000-00805f9b34fb
handle: 0x0029, char properties: 0x02, char value handle: 0x002a, uuid: 00002a25-0000-1000-8000-00805f9b34fb
handle: 0x002b, char properties: 0x02, char value handle: 0x002c, uuid: 00002a26-0000-1000-8000-00805f9b34fb
handle: 0x002d, char properties: 0x02, char value handle: 0x002e, uuid: 00002a27-0000-1000-8000-00805f9b34fb
handle: 0x002f, char properties: 0x02, char value handle: 0x0030, uuid: 00002a29-0000-1000-8000-00805f9b34fb

None of these are present in the python code.

Have they been changed with the latest FW if so can you clarify which ones should be which so I can update in the python code?

Did the Bluetooth UUIDs change?

Hello, I bought the Airthings Wave specifically because of this project. Anyway, my unit seems to have a different set of UUIDs than the python script is looking for.

Error:

root@radon:~/wave2# python read_wave.py <SERIAL_NUMBER> 10
Traceback (most recent call last):
File "read_wave.py", line 197, in
wave.connect()
File "read_wave.py", line 150, in connect
self.datetime_char = self.periph.getCharacteristics(uuid=self.UUID_DATETIME)[0]
File "/usr/local/lib/python2.7/dist-packages/bluepy/btle.py", line 508, in getCharacteristics
rsp = self._getResp('find')
File "/usr/local/lib/python2.7/dist-packages/bluepy/btle.py", line 407, in _getResp
resp = self._waitResp(wantType + ['ntfy', 'ind'], timeout)
File "/usr/local/lib/python2.7/dist-packages/bluepy/btle.py", line 368, in _waitResp
raise BTLEGattError("Bluetooth command failed", resp)
bluepy.btle.BTLEGattError: Bluetooth command failed (code: 10, error: No attribute found within the given range)`

At first I thought something was wrong with UUID_DATETIME but after singling out each wave.read, none of them work. After picking around and trying to do my own bluetooth debugging, I think the UUIDs have changed.

root@radon:~/wave2# gatttool -I -b A4:DA:32:27:6A:34
[A4:DA:32:27:6A:34][LE]> connect
Attempting to connect to A4:DA:32:27:6A:34
Connection successful
[A4:DA:32:27:6A:34][LE]> characteristics
handle: 0x0002, char properties: 0x02, char value handle: 0x0003, uuid: 00002a00-0000-1000-8000-00805f9b34fb
handle: 0x0004, char properties: 0x02, char value handle: 0x0005, uuid: 00002a01-0000-1000-8000-00805f9b34fb
handle: 0x0006, char properties: 0x02, char value handle: 0x0007, uuid: 00002a04-0000-1000-8000-00805f9b34fb
handle: 0x0008, char properties: 0x02, char value handle: 0x0009, uuid: 00002ac9-0000-1000-8000-00805f9b34fb
handle: 0x000c, char properties: 0x02, char value handle: 0x000d, uuid: b42e4dcc-ade7-11e4-89d3-123b93f75cba
handle: 0x000f, char properties: 0x2c, char value handle: 0x0010, uuid: b42e50d8-ade7-11e4-89d3-123b93f75cba
handle: 0x0013, char properties: 0x10, char value handle: 0x0014, uuid: b42e538a-ade7-11e4-89d3-123b93f75cba
handle: 0x0018, char properties: 0x1c, char value handle: 0x0019, uuid: f000ffc1-0451-4000-b000-000000000000
handle: 0x001c, char properties: 0x1c, char value handle: 0x001d, uuid: f000ffc2-0451-4000-b000-000000000000
handle: 0x0020, char properties: 0x14, char value handle: 0x0021, uuid: f000ffc5-0451-4000-b000-000000000000
handle: 0x0025, char properties: 0x02, char value handle: 0x0026, uuid: 00002a23-0000-1000-8000-00805f9b34fb
handle: 0x0027, char properties: 0x02, char value handle: 0x0028, uuid: 00002a24-0000-1000-8000-00805f9b34fb
handle: 0x0029, char properties: 0x02, char value handle: 0x002a, uuid: 00002a25-0000-1000-8000-00805f9b34fb
handle: 0x002b, char properties: 0x02, char value handle: 0x002c, uuid: 00002a26-0000-1000-8000-00805f9b34fb
handle: 0x002d, char properties: 0x02, char value handle: 0x002e, uuid: 00002a27-0000-1000-8000-00805f9b34fb
handle: 0x002f, char properties: 0x02, char value handle: 0x0030, uuid: 00002a29-0000-1000-8000-00805f9b34fb

[A4:DA:32:27:6A:34][LE]> char-desc
handle: 0x0001, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x0002, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0003, uuid: 00002a00-0000-1000-8000-00805f9b34fb
handle: 0x0004, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0005, uuid: 00002a01-0000-1000-8000-00805f9b34fb
handle: 0x0006, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0007, uuid: 00002a04-0000-1000-8000-00805f9b34fb
handle: 0x0008, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0009, uuid: 00002ac9-0000-1000-8000-00805f9b34fb
handle: 0x000a, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x000b, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x000c, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x000d, uuid: b42e4dcc-ade7-11e4-89d3-123b93f75cba
handle: 0x000e, uuid: 00002901-0000-1000-8000-00805f9b34fb
handle: 0x000f, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0010, uuid: b42e50d8-ade7-11e4-89d3-123b93f75cba
handle: 0x0011, uuid: 00002901-0000-1000-8000-00805f9b34fb
handle: 0x0012, uuid: 00002902-0000-1000-8000-00805f9b34fb
handle: 0x0013, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0014, uuid: b42e538a-ade7-11e4-89d3-123b93f75cba
handle: 0x0015, uuid: 00002901-0000-1000-8000-00805f9b34fb
handle: 0x0016, uuid: 00002902-0000-1000-8000-00805f9b34fb
handle: 0x0017, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x0018, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0019, uuid: f000ffc1-0451-4000-b000-000000000000
handle: 0x001a, uuid: 00002902-0000-1000-8000-00805f9b34fb
handle: 0x001b, uuid: 00002901-0000-1000-8000-00805f9b34fb
handle: 0x001c, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x001d, uuid: f000ffc2-0451-4000-b000-000000000000
handle: 0x001e, uuid: 00002902-0000-1000-8000-00805f9b34fb
handle: 0x001f, uuid: 00002901-0000-1000-8000-00805f9b34fb
handle: 0x0020, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0021, uuid: f000ffc5-0451-4000-b000-000000000000
handle: 0x0022, uuid: 00002902-0000-1000-8000-00805f9b34fb
handle: 0x0023, uuid: 00002901-0000-1000-8000-00805f9b34fb
handle: 0x0024, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x0025, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0026, uuid: 00002a23-0000-1000-8000-00805f9b34fb
handle: 0x0027, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0028, uuid: 00002a24-0000-1000-8000-00805f9b34fb
handle: 0x0029, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x002a, uuid: 00002a25-0000-1000-8000-00805f9b34fb
handle: 0x002b, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x002c, uuid: 00002a26-0000-1000-8000-00805f9b34fb
handle: 0x002d, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x002e, uuid: 00002a27-0000-1000-8000-00805f9b34fb
handle: 0x002f, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0030, uuid: 00002a29-0000-1000-8000-00805f9b34fb

I know I'm "talking" to the right device:

[A4:DA:32:27:6A:34][LE]> char-read-hnd 0x0030
Characteristic value/descriptor: 41 69 72 74 68 69 6e 67 73 20 41 53
[A4:DA:32:27:6A:34][LE]> # Airthings AS <-----------------
[A4:DA:32:27:6A:34][LE]> char-read-hnd 0x002c
Characteristic value/descriptor: 47 2d 42 4c 45 2d 31 2e 32 2e 34
[A4:DA:32:27:6A:34][LE]> # G-BLE-1.2.4 <-----------------

Let me know if other details are required. I simply turned on device, paired with phone (while I'm testing, bluetooth is turned off on phone) and it went through a firmware update then rebooted.

lta in read_wave2.py is not years average

It seems that compared to read_wave.py lta value is the weekly average and not the yearly. Is it possible to correct this or an additional parameter to get the yearly value?

Not working

Any thoughts on why I get these error messages after following the guide?

from: can't read /var/mail/bluepy.btle
import-im6.q16: unable to open X server ' @ error/import.c/ImportImageCommand/358. from: can't read /var/mail/datetime import-im6.q16: unable to open X server ' @ error/import.c/ImportImageCommand/358.
import-im6.q16: unable to open X server ' @ error/import.c/ImportImageCommand/358. import-im6.q16: unable to open X server ' @ error/import.c/ImportImageCommand/358.
./read_wave.py: 40: ./read_wave.py: Syntax error: word unexpected (expecting ")")

Push to online account

Would it be possible to use this script to push to the online account instead of needing to use the phone app?

Battery Level

Hi,
Would it be possible to also display the battery level of the device? Since the App displays it, I guess it should also be one of the returned values ?
Thanks!

Error

sudo python3 read_wave.py 2930029112 60
Traceback (most recent call last):
File "read_wave.py", line 168, in
_main()
File "read_wave.py", line 161, in _main
current_values = wave.read()
File "read_wave.py", line 89, in read
rawdata = self._datetime_char.read()
AttributeError: 'NoneType' object has no attribute 'read'

What's missing?

Read multiple wave units from script

When script is running only readout from one Wave-unit. Possiblity to add several serialnumbers if user do have several Wave units to read from at same time. Or other solution.

Support for Wave Mini

Hello!
The Wave reader works just fine on my Gen2, but it does not seem to support the Wave Mini. Any chance to add support for the Mini ?
Thanks!
EDIT: I managed to get some values from the Mini, however not sure which index corresponds to what...

Imperial number output

Any way to make the output imperial versus metric?
The only issue I had with the install was getting libglib2.0-dev installed.
After much pain, the fix was simple:
sudo apt-get update

2nd generation Airthings Wave not working

I have purchased the 2nd generation Wave (model 2950) on beginning of December, with intention to integrate it in to the openHAB home automation.
Unfortunately, wave_read.py does not work with this device. I tried to troubleshoot it a bit deeper and found that UUIDs that are used to retrieve date, humidity, temperature and radon values are reported as invalid by gatttool

The device itself presents as "Airthings Wave+" (uuid: 00002a00-0000-1000-8000-00805f9b34fb).
So I tried it with read_waveplus.py script. but it does not work either.

Firmware was updated and currently is:
MSP:1.1.2 CC:1.2.4

Wave Plus Serial 293x is supported?

I bought a Wave Plus hoping I can use this project but upon trying both read_wave.py and read_wave2.py I cannot get the values. read_wave.py shows either BTLEDisconnectedError either name 'p' is not defined. read_wave2.py with SN shows BTLEDisconnectedError. Is my device supported by this library? I can tweak the code to get the values from Wave Plus?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.