Giter Site home page Giter Site logo

netmanchris / pyawair Goto Github PK

View Code? Open in Web Editor NEW
16.0 5.0 3.0 77 KB

python wrapper for Awair Air Quality Sensor

License: Apache License 2.0

Python 100.00%
awair air aqi sensor python air-quality smarthome homeautomation home-automation home-assistant

pyawair's Introduction

Python Wrapper for Awair Air Quality Sensor

Build Status Coverage Status This project is a alpha wrapper for the Awair Air Quality Sensor API.

https://www.getawair.com

Using the Library

The Awair Developer program is currently under beta. You may request a personal token with the awair team.

Creating yor Auth object

Once you get the token create a new object of the AwairAuth type by passing in the token from the Awair Dev site as a str.

>>> auth = AwairAuth('''My_Token''')

>>> auth.token
My_Token'

This object of type AwairAuth must be passed into all API calls to ensure that you can successfully pass your authentication request to the Awair API.

Example Functions

The following functions shows some basic examples of working with the Awair Python binding to gather data from the Awair API.

Getting you User Data

Issue the following command to get your user data

 >>> from pyawair.devices import *
 >>> get_user_data(auth)
 Out[10]: 
[{'deviceId': 0,
  'deviceType': 'awair',
  'latitude': 123.4567,
  'locationName': 'My Home',
  'longitude': 123.4567,
  'name': 'Bedroom',
  'preference': 'GENERAL',
  'spaceType': 'HOME',
  'timezone': 'US/Pacific'}]

Issue the following command to get all devices registered to your account

get_all_devices(auth)
Out[4]: 
Out[11]: 
[{'deviceId': 0,
  'deviceType': 'awair',
  'latitude': 123.4567,
  'locationName': 'My Home',
  'longitude': 123.4567,
  'name': 'Bedroom',
  'preference': 'GENERAL',
  'spaceType': 'HOME',
  'timezone': 'US/Pacific'}]

We've also created a helper function to allow you to request just the data on the a single Awair device by specifying the name of the device

The following command will get the details for a device named Bedroom_Awair

get_dev_details(auth, device_name='Bedroom')
Out[12]: 
{'deviceId': 0,
 'deviceType': 'awair',
 'latitude': 123.4567,
 'locationName': 'My Home',
 'longitude': 123.4567,
 'name': 'Bedroom',
 'preference': 'GENERAL',
 'spaceType': 'HOME',
 'timezone': 'US/Pacific'}

Getting Device Data

To access device data functions, you must first import the data module into your coding environment

from pyawair.data import *
Get Current Air Data
get_current_air_data(auth, device_name='Bedroom')
Out[21]: 
[{'indices': [{'comp': 'TEMP', 'value': 0.0},
   {'comp': 'HUMID', 'value': 0.0},
   {'comp': 'CO2', 'value': 0.0},
   {'comp': 'VOC', 'value': 0.0},
   {'comp': 'PM10', 'value': 0.0},
   {'comp': 'PM25', 'value': 0.0}],
  'score': 100.0,
  'sensors': [{'comp': 'TEMP', 'value': 100.0},
   {'comp': 'HUMID', 'value': 100.0},
   {'comp': 'CO2', 'value': 100.0},
   {'comp': 'VOC', 'value': 100.0},
   {'comp': 'PM10', 'value': 100.0},
   {'comp': 'PM25', 'value': 100.0}],
  'timestamp': '1970-01-01T00:00:00.000Z'}]
Get 5 Minute Average
get_5_min_average(auth, device_name='Bedroom')
Out[22]: 
[{'indices': [{'comp': 'TEMP', 'value': 0.0},
   {'comp': 'HUMID', 'value': 0.0},
   {'comp': 'CO2', 'value': 0.0},
   {'comp': 'VOC', 'value': 0.0},
   {'comp': 'PM10', 'value': 0.0},
   {'comp': 'PM25', 'value': 0.0}],
  'score': 100.0,
  'sensors': [{'comp': 'TEMP', 'value': 100.0},
   {'comp': 'HUMID', 'value': 100.0},
   {'comp': 'CO2', 'value': 100.0},
   {'comp': 'VOC', 'value': 100.0},
   {'comp': 'PM10', 'value': 100.0},
   {'comp': 'PM25', 'value': 100.0}],
  'timestamp': '1970-01-01T00:00:00.000Z'}]
Get 15 minute average
get_15_min_average(auth, device_name='Bedroom')
Out[23]: 
[{'indices': [{'comp': 'TEMP', 'value': 0.0},
   {'comp': 'HUMID', 'value': 0.0},
   {'comp': 'CO2', 'value': 0.0},
   {'comp': 'VOC', 'value': 0.0},
   {'comp': 'PM10', 'value': 0.0},
   {'comp': 'PM25', 'value': 0.0}],
  'score': 100.0,
  'sensors': [{'comp': 'TEMP', 'value': 100.0},
   {'comp': 'HUMID', 'value': 100.0},
   {'comp': 'CO2', 'value': 100.0},
   {'comp': 'VOC', 'value': 100.0},
   {'comp': 'PM10', 'value': 100.0},
   {'comp': 'PM25', 'value': 100.0}],
  'timestamp': '1970-01-01T00:00:00.000Z'}]
Get Raw Data
get_raw_data(auth, device_name='Bedroom')
Out[24]: 
[{'indices': [{'comp': 'TEMP', 'value': 0.0},
   {'comp': 'HUMID', 'value': 0.0},
   {'comp': 'CO2', 'value': 0.0},
   {'comp': 'VOC', 'value': 0.0},
   {'comp': 'PM10', 'value': 0.0},
   {'comp': 'PM25', 'value': 0.0}],
  'score': 100.0,
  'sensors': [{'comp': 'TEMP', 'value': 100.0},
   {'comp': 'HUMID', 'value': 100.0},
   {'comp': 'CO2', 'value': 100.0},
   {'comp': 'VOC', 'value': 100.0},
   {'comp': 'PM10', 'value': 100.0},
   {'comp': 'PM25', 'value': 100.0}],
  'timestamp': '1970-01-01T00:00:00.000Z'}]

AwairDev Class

The AwairDev class has been provided as a way to interface with an Awair Air quality device in an object oriented manner. The primary use-case for the AwairDev class is to provide the base for building device driver support for the Home-Assistant project (HassIO). If you are interested in exposing your Awair Device to your Home-Assistant instance, you can see an early example of this work here

*thanks to @danielsjf for this work!

from pyawair.objects import AwairDev
my_awair = AwairDev('Bedroom', auth)
my_awair.type()
Out[27]: 'awair'
my_awair.get_state('score')
Out[29]: 100.0
my_awair.get_state('humid')
Out[30]: 100.0

pyawair's People

Contributors

cajaks2 avatar danielsjf avatar netmanchris avatar

Stargazers

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

Watchers

 avatar  avatar  avatar  avatar  avatar

pyawair's Issues

Backwards Compatibility

@danielsjf Hit a snag - Looks like you're using the python variable annotations function which is available in Python 3.6.

I just tried this out on a Python 3.5 box and was given a SyntaxError.

Although I like the annotations, I don't see it as having enough value to prevent us from backwards compatibility.

I haven't used this new feature though. Is there a specific reason that you used these in the objects module? I'm thinking of pulling them out to unbreak backwards compatibility but I wanted to discuss this before making the change.

Is there a specific reason you added these in? What's the gain?

thanks!

Chris

Add a poller class

I'm almost finished with a first implementation of the home assistant component. In the current implementation, the API calls will be a serious limitation though.

The problem is in the way how it is implemented in home assistant. I have to create a class for each monitored condition. Currently the API is implemented as functions. Each of the sensors will call the API once. Since you can monitor up to 6 conditions (score and the 5 sensors), this means that just an hourly poll will mean 24 * 6 = 144 calls/day.

The solution would be to move the calls to a poller. This poller would have an argument for the polling frequency. I would give the same object to all the sensor classes, but the polling logic would be in the polling class. It would also have a get_state function with arguments like: temp, voc, dust, ... . This would always give the most recent polled state.

What do you think of the idea? If you are willing to add it to your code, I will try to implement something. Would you accept pull requests?

Current data is suddenly a RAW type

Apparently the API was not working for me anymore the last two days. This is because I suddenly get an error message when calling the current data endpoint.

@deanlyoung is this supposed to happen?

@netmanchris for now I have solved it by adding an aggregate_type argument in the AwairDev class. The default option is now '15-minute'. I'll open a pull request where we can further discuss the changes and if and how you would like to integrate them.

broken tests

Hey @danielsjf

Looks like the last couple of merges have broken some of the tests. Can you please take a look and let me know what you see on your end?

Fix querying

These references for the ['sensors'] should be dynamic instead of purely the order (0-6), which might be wrong when sensors are missing for some devices.

pyawair/pyawair/objects.py

Lines 113 to 126 in 85a1bdb

if "temp" in DEVICE_SENSORS[self._type]:
self._data['temp'] = data[-1]['sensors'][0]['value']
if "humid" in DEVICE_SENSORS[self._type]:
self._data['humid'] = data[-1]['sensors'][1]['value']
if "co2" in DEVICE_SENSORS[self._type]:
self._data['co2'] = data[-1]['sensors'][2]['value']
if "voc" in DEVICE_SENSORS[self._type]:
self._data['voc'] = data[-1]['sensors'][3]['value']
if "dust" in DEVICE_SENSORS[self._type]:
self._data['dust'] = data[-1]['sensors'][4]['value']
if "pm25" in DEVICE_SENSORS[self._type]:
self._data['pm25'] = data[-1]['sensors'][5]['value']
if "pm10" in DEVICE_SENSORS[self._type]:
self._data['pm10'] = data[-1]['sensors'][6]['value']

The average functions don't give the average

I expected the 5 and 15 minute average data to give me the average of the last 5 and 15 minutes. This in contrast to the current data which can spike for some measurements like dust. Instead it seems to give me all the averages of the last month. This is more a problem of the Awair API, but maybe we could rename the function. Another idea is to add an argument for timeperiod which could have an unmodifiable "last month" as default.

This is more to open a discussion.

Error getting deviceType:

I get the following error when trying to use the latest version of pyawair:
Traceback (most recent call last): File "/srv/homeassistant/lib/python3.6/site-packages/homeassistant/helpers/entity_platform.py", line 129, in _async_setup_platform SLOW_SETUP_MAX_WAIT, loop=hass.loop) File "/usr/local/lib/python3.6/asyncio/tasks.py", line 358, in wait_for return fut.result() File "/usr/local/lib/python3.6/concurrent/futures/thread.py", line 56, in run result = self.fn(*self.args, **self.kwargs) File "/home/homeassistant/.homeassistant/custom_components/sensor/awair.py", line 60, in setup_platform awair_poller = AwairDev(name, awair_auth, refresh_rate) File "/srv/homeassistant/lib/python3.6/site-packages/pyawair/objects.py", line 32, in __init__ False)['deviceType'] # get the device type TypeError: 'bool' object is not subscriptable

Prints remain in data functions

While printing the urls might be useful from a debug point of view, it would be cleaner to remove them in production. If necessary, you can leave them in the code, but only enable them with a boolean somewhere.

Tests fail again

@deanlyoung it seems that the test break again due to a change in the API. Everything works fine for my own API key, but when I use one of the test keys, it fails with the following message.

Status code 404. Message: 'Could not decode Tier ENTERPRISE'.

The problem can be reproduced with the following code.

from pyawair.auth import AwairAuth
from pyawair.objects import AwairDev
from pyawair.data import get_15_min_average

enterprise_dev = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiRFVNTVktRU5URVJQUklTRSJ9.bOM9rcABF9HKFHtxzF9kx8h9fv3CfvUIzveLFDRGrXs'

token = enterprise_dev

awair_auth = AwairAuth(token)
name = "Living room"
data = get_15_min_average(awair_auth,name)

The url:
http://developer-apis.awair.is/v1/users/self/devices

The headers:

{'Accept': 'application/json', 'Content-Type': 'application/json', 'Accept-encoding': 'application/json', 'Authorization': 'Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiRFVNTVktRU5URVJQUklTRSJ9.bOM9rcABF9HKFHtxzF9kx8h9fv3CfvUIzveLFDRGrXs'}

Do you know of any changes that might have caused this?

Documentation on API calls and input handling

I saw that some functions for the data (e.g. get_current_air_data) have up to 3 API calls. It could be good to specify this in the documentation. I don't know to what extend the API lends itself to directly call a function based upon the name (instead of type and ID).

On a side note, you could also explain how the name or the type + ID is necessary in the docs. You could also do a quick test to see which parameters are supplied. For instance, if all three are reported, throw an error. Only if name or (type and ID) are supplied it should return something.

Test failing for Awair Glow

Some of the tests are failing when attempting to get data from an Awair Glow device. Opening issue in case anyone's hitting this. Will work to fix it and post updates as time permits.

Update Pypi

Can you please update the version on PyPI when you get a chance? Thanks!

discussion: Home-Assistant support

@danielsjf Saw your message on another python Awair API project. I've been working with @deanlyoung on this python wrapper for the Awair API. Wondering if you might consider using this for the Home-Assistant project.

Plan is to stay in compliance with the official API so, by necessity, there will be some functionality that will not be exposed until Awair adds it to the API.

This is currently available on Pypi

Thoughts?

Functions missing in pipy package

@netmanchris I think that the init.py file might be missing in the pyawair folder. When I check with dir, it seems that there are no exported functions in your package on pipy. Have you tried to install the package already via pipy?

Correct data sensors

@deanlyoung, I've made an internal list of which device has which sensors. This to avoid querying sensors that don't exist. Since I couldn't find a list of all the names in the documentation, I've made them up for those that I didn't have. Could you kindly provide me with the full list? The specific commit with the list is 85a1bdb.

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.