Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "python-awair"
version = "0.2.4"
version = "0.2.5"
description = "asyncio client for the Awair GraphQL and Local APIs"
authors = ["Andrew Hayworth <ahayworth@gmail.com>"]
license = "MIT"
Expand Down
10 changes: 9 additions & 1 deletion python_awair/client.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Wrapper class to query the Awair API."""

import json as Json
from typing import Any, Dict, NoReturn

from aiohttp import ClientResponse, ClientSession
Expand Down Expand Up @@ -33,7 +34,14 @@ async def query(self, url: str) -> Any:
if resp.status != 200:
self.__handle_non_200_error(resp)

json = await resp.json()
# Response could be from Awair Omni Ethernet backpack
# https://github.com/home-assistant/core/issues/147682
if resp.content_type == "text/html":
text = await resp.text()
json = Json.loads(text)
else:
json = await resp.json()

self.__check_errors_array(json)

return json
Expand Down
6 changes: 6 additions & 0 deletions tests/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,9 @@
"deviceUUID": "awair-element_5366",
"fw_version": "1.2.8",
}
MOCK_ELEMENT_DEVICE_C_ATTRS = {
"deviceId": 18959,
"deviceType": "awair-omni",
"deviceUUID": "awair-omni_18959",
"fw_version": "1.8.1",
}
42 changes: 42 additions & 0 deletions tests/fixtures/cassettes/latest_local_backplate.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
interactions:
- request:
body: null
headers:
Content-Type:
- application/json
authorization:
- fake_token
method: GET
uri: http://awair-omni-18959-backplate.local/settings/config/data
response:
body:
string: '{"device_uuid":"awair-omni_18959","wifi_mac":"E8:C0:01:78:16:ED","ip":"192.168.0.101","netmask":"255.255.255.0","gateway":"192.168.0.1","fw_version":"1.8.1","timezone":"America/Los_Angeles","display":"score","led":{"mode":"auto","brightness":70},"power-status":{"battery":99,"plugged":true}}'
headers:
Access-Control-Allow-Origin: '*'
Content-Type: text/html
Transfer-Encoding: chunked
status:
code: 200
message: OK
url: http://awair-omni-18959-backplate.local/settings/config/data
- request:
body: null
headers:
Content-Type:
- application/json
authorization:
- fake_token
method: GET
uri: http://awair-omni-18959-backplate.local/air-data/latest
response:
body:
string: '{"timestamp":"2025-09-20T13:24:38.359Z","score":99,"temp":22.12,"humid":51.90,"co2":424,"voc":33,"pm25":1,"lux":0.0,"spl_a":51.9}'
headers:
Access-Control-Allow-Origin: '*'
Content-Type: text/html
Transfer-Encoding: chunked
status:
code: 200
message: OK
url: http://awair-omni-18959-backplate.local/air-data/latest
version: 1
22 changes: 22 additions & 0 deletions tests/fixtures/cassettes/local_backplate.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
interactions:
- request:
body: null
headers:
Content-Type:
- application/json
authorization:
- fake_token
method: GET
uri: http://awair-omni-18959-backplate.local/settings/config/data
response:
body:
string: '{"device_uuid":"awair-omni_18959","wifi_mac":"E8:C0:01:78:16:ED","ip":"192.168.0.101","netmask":"255.255.255.0","gateway":"192.168.0.1","fw_version":"1.8.1","timezone":"America/Los_Angeles","display":"score","led":{"mode":"auto","brightness":70},"power-status":{"battery":99,"plugged":true}}'
headers:
Access-Control-Allow-Origin: '*'
Content-Type: text/html
Transfer-Encoding: chunked
status:
code: 200
message: OK
url: http://awair-omni-18959-backplate.local/settings/config/data
version: 1
43 changes: 43 additions & 0 deletions tests/test_python_awair.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
AWAIR_GEN1_ID,
MOCK_ELEMENT_DEVICE_A_ATTRS,
MOCK_ELEMENT_DEVICE_B_ATTRS,
MOCK_ELEMENT_DEVICE_C_ATTRS,
MOCK_GEN2_DEVICE_ATTRS,
MOCK_GLOW_DEVICE_ATTRS,
MOCK_MINT_DEVICE_ATTRS,
Expand Down Expand Up @@ -92,6 +93,27 @@ async def test_get_local_devices() -> Any:
assert "<AwairDevice" in str(devices[1])


async def test_get_local_backplate_devices() -> Any:
"""Test that we can get a list of devices."""
async with aiohttp.ClientSession() as session:
with VCR.use_cassette("local_backplate.yaml"):
awair = AwairLocal(
session=session,
device_addrs=[
"AWAIR-OMNI-18959-BACKPLATE.local",
],
)
devices = await awair.devices()

assert len(devices) == 1

assert devices[0].device_id == MOCK_ELEMENT_DEVICE_C_ATTRS["deviceId"]
assert devices[0].device_type == MOCK_ELEMENT_DEVICE_C_ATTRS["deviceType"]
assert devices[0].uuid == MOCK_ELEMENT_DEVICE_C_ATTRS["deviceUUID"]
assert devices[0].fw_version == MOCK_ELEMENT_DEVICE_C_ATTRS["fw_version"]
assert "<AwairDevice" in str(devices[0])


async def test_get_latest() -> Any:
"""Test that we can get the latest air data."""
target = datetime(2020, 4, 10, 10, 38, 30)
Expand Down Expand Up @@ -130,6 +152,27 @@ async def test_get_latest_local() -> Any:
assert "<AirData@2020-08-31" in str(resp)


async def test_get_latest_local_backplate() -> Any:
"""Test that we can get the latest air data."""
target = datetime(2025, 9, 20, 13, 24, 38)
async with aiohttp.ClientSession() as session:
with VCR.use_cassette("latest_local_backplate.yaml"), time_travel(target):
awair = AwairLocal(
session=session, device_addrs=["AWAIR-OMNI-18959-BACKPLATE.local"]
)
devices = await awair.devices()
assert len(devices) == 1
device = devices[0]
resp = await device.air_data_latest()

assert resp is not None
assert resp.timestamp == datetime(2025, 9, 20, 13, 24, 38, 359000)
assert resp.score == 99
assert resp.sensors["temperature"] == 22.12
assert len(resp.indices) == 0
assert "<AirData@2025-09-20" in str(resp)


async def test_get_five_minute() -> Any:
"""Test that we can get the five-minute avg air data."""
target = datetime(2020, 4, 10, 10, 38, 31, 2883)
Expand Down