async-httpd-data-collector 2.0.2__tar.gz → 2.0.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- async_httpd_data_collector-2.0.3/.github/workflows/docs.yml +40 -0
- {async_httpd_data_collector-2.0.2 → async_httpd_data_collector-2.0.3}/.github/workflows/publish.yml +8 -14
- {async_httpd_data_collector-2.0.2 → async_httpd_data_collector-2.0.3}/.github/workflows/test.yml +6 -6
- async_httpd_data_collector-2.0.3/.gitignore +45 -0
- {async_httpd_data_collector-2.0.2 → async_httpd_data_collector-2.0.3}/PKG-INFO +89 -274
- async_httpd_data_collector-2.0.3/README.md +115 -0
- async_httpd_data_collector-2.0.3/ahttpdc/__init__.py +1 -0
- {async_httpd_data_collector-2.0.2 → async_httpd_data_collector-2.0.3}/ahttpdc/read/daemon.py +3 -3
- {async_httpd_data_collector-2.0.2 → async_httpd_data_collector-2.0.3}/ahttpdc/read/database_interface.py +2 -2
- {async_httpd_data_collector-2.0.2 → async_httpd_data_collector-2.0.3}/ahttpdc/read/fetch/fetcher.py +2 -2
- {async_httpd_data_collector-2.0.2 → async_httpd_data_collector-2.0.3}/ahttpdc/read/query/interface.py +3 -3
- {async_httpd_data_collector-2.0.2 → async_httpd_data_collector-2.0.3}/ahttpdc/read/store/collector.py +3 -3
- {async_httpd_data_collector-2.0.2 → async_httpd_data_collector-2.0.3}/ahttpdc/read/store/parse/parser.py +2 -2
- async_httpd_data_collector-2.0.3/docs/analysis/index.md +197 -0
- async_httpd_data_collector-2.0.3/docs/analysis/prediction.md +161 -0
- async_httpd_data_collector-2.0.3/docs/api.md +231 -0
- async_httpd_data_collector-2.0.3/docs/architecture.md +132 -0
- async_httpd_data_collector-2.0.3/docs/getting-started.md +163 -0
- async_httpd_data_collector-2.0.3/docs/index.md +69 -0
- async_httpd_data_collector-2.0.3/mkdocs.yml +38 -0
- {async_httpd_data_collector-2.0.2 → async_httpd_data_collector-2.0.3}/pyproject.toml +8 -34
- async_httpd_data_collector-2.0.2/.gitignore +0 -165
- async_httpd_data_collector-2.0.2/README.md +0 -274
- async_httpd_data_collector-2.0.2/ahttpdc/__init__.py +0 -1
- {async_httpd_data_collector-2.0.2 → async_httpd_data_collector-2.0.3}/.yamlfmt.yml +0 -0
- {async_httpd_data_collector-2.0.2 → async_httpd_data_collector-2.0.3}/.yamllint.yml +0 -0
- {async_httpd_data_collector-2.0.2 → async_httpd_data_collector-2.0.3}/LICENSE +0 -0
- {async_httpd_data_collector-2.0.2 → async_httpd_data_collector-2.0.3}/ahttpdc/read/__init__.py +0 -0
- {async_httpd_data_collector-2.0.2 → async_httpd_data_collector-2.0.3}/ahttpdc/read/fetch/__init__.py +0 -0
- {async_httpd_data_collector-2.0.2 → async_httpd_data_collector-2.0.3}/ahttpdc/read/query/__init__.py +0 -0
- {async_httpd_data_collector-2.0.2 → async_httpd_data_collector-2.0.3}/ahttpdc/read/query/parse/data.py +0 -0
- {async_httpd_data_collector-2.0.2 → async_httpd_data_collector-2.0.3}/ahttpdc/read/store/__init__.py +0 -0
- {async_httpd_data_collector-2.0.2 → async_httpd_data_collector-2.0.3}/ahttpdc/read/store/parse/__init__.py +0 -0
- {async_httpd_data_collector-2.0.2 → async_httpd_data_collector-2.0.3}/examples/daemon_example.py +0 -0
- {async_httpd_data_collector-2.0.2 → async_httpd_data_collector-2.0.3}/examples/minima_dashboard_example.py +0 -0
- {async_httpd_data_collector-2.0.2 → async_httpd_data_collector-2.0.3}/examples/query_example.py +0 -0
- {async_httpd_data_collector-2.0.2 → async_httpd_data_collector-2.0.3}/requirements.txt +0 -0
- {async_httpd_data_collector-2.0.2 → async_httpd_data_collector-2.0.3}/tests/dev_server.py +0 -0
- {async_httpd_data_collector-2.0.2 → async_httpd_data_collector-2.0.3}/tests/read/fetch/test_fetcher.py +0 -0
- {async_httpd_data_collector-2.0.2 → async_httpd_data_collector-2.0.3}/tests/read/query/test_query.py +0 -0
- {async_httpd_data_collector-2.0.2 → async_httpd_data_collector-2.0.3}/tests/read/test_interface.py +0 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Docs
|
|
3
|
+
|
|
4
|
+
on:
|
|
5
|
+
push:
|
|
6
|
+
branches: [master]
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
pages: write
|
|
10
|
+
id-token: write
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
build-docs:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
- uses: actions/setup-python@v5
|
|
19
|
+
with:
|
|
20
|
+
python-version: '3.12'
|
|
21
|
+
|
|
22
|
+
- name: Install mkdocs-material
|
|
23
|
+
run: pip install mkdocs-material
|
|
24
|
+
|
|
25
|
+
- name: Build docs
|
|
26
|
+
run: mkdocs build
|
|
27
|
+
|
|
28
|
+
- uses: actions/upload-pages-artifact@v3
|
|
29
|
+
with:
|
|
30
|
+
path: site/
|
|
31
|
+
|
|
32
|
+
deploy:
|
|
33
|
+
needs: build-docs
|
|
34
|
+
environment:
|
|
35
|
+
name: github-pages
|
|
36
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
37
|
+
runs-on: ubuntu-latest
|
|
38
|
+
steps:
|
|
39
|
+
- uses: actions/deploy-pages@v4
|
|
40
|
+
id: deployment
|
{async_httpd_data_collector-2.0.2 → async_httpd_data_collector-2.0.3}/.github/workflows/publish.yml
RENAMED
|
@@ -1,17 +1,13 @@
|
|
|
1
1
|
---
|
|
2
|
-
# Builds,
|
|
2
|
+
# Builds, releases and publishes to PyPI
|
|
3
3
|
# .github/workflows/publish.yml
|
|
4
4
|
name: CD
|
|
5
5
|
|
|
6
|
-
# triggered when testing is finished
|
|
7
6
|
on:
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
types:
|
|
12
|
-
- completed
|
|
7
|
+
push:
|
|
8
|
+
tags:
|
|
9
|
+
- 'v*'
|
|
13
10
|
|
|
14
|
-
# add contents: write for the release
|
|
15
11
|
permissions:
|
|
16
12
|
contents: write
|
|
17
13
|
|
|
@@ -23,10 +19,10 @@ jobs:
|
|
|
23
19
|
steps:
|
|
24
20
|
|
|
25
21
|
- name: Checkout repository
|
|
26
|
-
uses: actions/checkout@
|
|
22
|
+
uses: actions/checkout@v4
|
|
27
23
|
|
|
28
24
|
- name: Set up Python
|
|
29
|
-
uses: actions/setup-python@
|
|
25
|
+
uses: actions/setup-python@v5
|
|
30
26
|
with:
|
|
31
27
|
python-version: '3.x'
|
|
32
28
|
|
|
@@ -34,20 +30,18 @@ jobs:
|
|
|
34
30
|
run: |
|
|
35
31
|
python -m pip install --upgrade pip
|
|
36
32
|
pip install build twine
|
|
37
|
-
pip install -r requirements.txt
|
|
38
33
|
|
|
39
|
-
- name: Build the
|
|
34
|
+
- name: Build the package
|
|
40
35
|
run: |
|
|
41
36
|
python -m build
|
|
42
37
|
|
|
43
38
|
- name: Release
|
|
44
39
|
uses: softprops/action-gh-release@v2
|
|
45
|
-
if: startsWith(github.ref, 'refs/tags/')
|
|
46
40
|
with:
|
|
47
41
|
files: |
|
|
48
42
|
dist/**
|
|
49
43
|
|
|
50
|
-
- name: Publish to
|
|
44
|
+
- name: Publish to PyPI
|
|
51
45
|
env:
|
|
52
46
|
TWINE_USERNAME: __token__
|
|
53
47
|
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
|
{async_httpd_data_collector-2.0.2 → async_httpd_data_collector-2.0.3}/.github/workflows/test.yml
RENAMED
|
@@ -28,7 +28,7 @@ jobs:
|
|
|
28
28
|
steps:
|
|
29
29
|
|
|
30
30
|
- name: Checkout repository
|
|
31
|
-
uses: actions/checkout@
|
|
31
|
+
uses: actions/checkout@v4
|
|
32
32
|
|
|
33
33
|
# install InfluxDB CLI to authenticate access to the database
|
|
34
34
|
- name: Install InfluxDB CLI
|
|
@@ -56,8 +56,8 @@ jobs:
|
|
|
56
56
|
--force
|
|
57
57
|
|
|
58
58
|
# save the data required for the token generation and testing
|
|
59
|
-
echo "
|
|
60
|
-
echo "
|
|
59
|
+
echo "org=${INFLUX_ORG}" >> $GITHUB_OUTPUT
|
|
60
|
+
echo "bucket=${INFLUX_BUCKET}" >> $GITHUB_OUTPUT
|
|
61
61
|
|
|
62
62
|
- name: Generate token for further authentication
|
|
63
63
|
id: auth
|
|
@@ -72,10 +72,10 @@ jobs:
|
|
|
72
72
|
--json | jq '.token')
|
|
73
73
|
|
|
74
74
|
# save the token
|
|
75
|
-
echo "
|
|
75
|
+
echo "token=${INFLUX_TOKEN}" >> $GITHUB_OUTPUT
|
|
76
76
|
|
|
77
77
|
- name: Set up Python
|
|
78
|
-
uses: actions/setup-python@
|
|
78
|
+
uses: actions/setup-python@v5
|
|
79
79
|
with:
|
|
80
80
|
python-version: '3.11'
|
|
81
81
|
|
|
@@ -92,7 +92,7 @@ jobs:
|
|
|
92
92
|
- name: Test
|
|
93
93
|
run: |-
|
|
94
94
|
|
|
95
|
-
# run the
|
|
95
|
+
# run the flask dev_server
|
|
96
96
|
export FLASK_APP="tests/dev_server"
|
|
97
97
|
flask run --host=0.0.0.0 --port=9000 &
|
|
98
98
|
sleep 5
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# project specific
|
|
2
|
+
secrets
|
|
3
|
+
*env
|
|
4
|
+
test-data
|
|
5
|
+
|
|
6
|
+
# byte-compiled / optimized
|
|
7
|
+
__pycache__/
|
|
8
|
+
*.py[cod]
|
|
9
|
+
*$py.class
|
|
10
|
+
*.so
|
|
11
|
+
|
|
12
|
+
# distribution / packaging
|
|
13
|
+
build/
|
|
14
|
+
dist/
|
|
15
|
+
*.egg-info/
|
|
16
|
+
*.egg
|
|
17
|
+
MANIFEST
|
|
18
|
+
|
|
19
|
+
# unit test / coverage
|
|
20
|
+
htmlcov/
|
|
21
|
+
.tox/
|
|
22
|
+
.nox/
|
|
23
|
+
.coverage
|
|
24
|
+
.coverage.*
|
|
25
|
+
.cache
|
|
26
|
+
.pytest_cache/
|
|
27
|
+
coverage.xml
|
|
28
|
+
|
|
29
|
+
# environments
|
|
30
|
+
.env
|
|
31
|
+
.venv
|
|
32
|
+
venv/
|
|
33
|
+
|
|
34
|
+
# mkdocs
|
|
35
|
+
/site
|
|
36
|
+
docs/analysis/img/
|
|
37
|
+
|
|
38
|
+
# mypy
|
|
39
|
+
.mypy_cache/
|
|
40
|
+
|
|
41
|
+
# ruff
|
|
42
|
+
.ruff_cache/
|
|
43
|
+
|
|
44
|
+
# logs
|
|
45
|
+
*.log
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: async-httpd-data-collector
|
|
3
|
-
Version: 2.0.
|
|
4
|
-
Summary: Gateway facilitating
|
|
3
|
+
Version: 2.0.3
|
|
4
|
+
Summary: Gateway facilitating asynchronous communication between sensory data-emitting devices, InfluxDB and the user.
|
|
5
|
+
Project-URL: Documentation, https://ahttpdc-docs.codextechnologies.org/mkdocs
|
|
5
6
|
Project-URL: Repository, https://github.com/straightchlorine/async-httpd-data-collector
|
|
6
7
|
Project-URL: Issues, https://github.com/straightchlorine/async-httpd-data-collector/issues
|
|
7
8
|
Author-email: Piotr Krzysztof Lis <piotrlis555@gmail.com>
|
|
9
|
+
Maintainer-email: Piotr Krzysztof Lis <piotrlis555@gmail.com>
|
|
8
10
|
License: GNU GENERAL PUBLIC LICENSE
|
|
9
11
|
Version 3, 29 June 2007
|
|
10
12
|
|
|
@@ -689,322 +691,135 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
|
689
691
|
Requires-Python: >=3.8
|
|
690
692
|
Requires-Dist: aiocsv
|
|
691
693
|
Requires-Dist: aiohttp
|
|
692
|
-
Requires-Dist: aiosignal
|
|
693
|
-
Requires-Dist: attrs
|
|
694
|
-
Requires-Dist: certifi
|
|
695
|
-
Requires-Dist: frozenlist
|
|
696
|
-
Requires-Dist: idna
|
|
697
694
|
Requires-Dist: influxdb-client[async]
|
|
698
|
-
Requires-Dist: multidict
|
|
699
695
|
Requires-Dist: numpy
|
|
700
696
|
Requires-Dist: pandas
|
|
701
697
|
Requires-Dist: python-dateutil
|
|
702
698
|
Requires-Dist: pytz
|
|
703
699
|
Requires-Dist: reactivex
|
|
704
|
-
|
|
705
|
-
Requires-Dist:
|
|
706
|
-
Requires-Dist: typing-extensions
|
|
707
|
-
Requires-Dist: tzdata
|
|
708
|
-
Requires-Dist: urllib3
|
|
709
|
-
Requires-Dist: yarl
|
|
700
|
+
Provides-Extra: docs
|
|
701
|
+
Requires-Dist: mkdocs-material; extra == 'docs'
|
|
710
702
|
Provides-Extra: test
|
|
711
|
-
Requires-Dist: blinker; extra == 'test'
|
|
712
|
-
Requires-Dist: charset-normalizer; extra == 'test'
|
|
713
|
-
Requires-Dist: click; extra == 'test'
|
|
714
703
|
Requires-Dist: dash; extra == 'test'
|
|
715
|
-
Requires-Dist: dash-core-components; extra == 'test'
|
|
716
|
-
Requires-Dist: dash-html-components; extra == 'test'
|
|
717
|
-
Requires-Dist: dash-table; extra == 'test'
|
|
718
704
|
Requires-Dist: flask; extra == 'test'
|
|
719
|
-
Requires-Dist: importlib-metadata; extra == 'test'
|
|
720
|
-
Requires-Dist: iniconfig; extra == 'test'
|
|
721
|
-
Requires-Dist: itsdangerous; extra == 'test'
|
|
722
|
-
Requires-Dist: jinja2; extra == 'test'
|
|
723
|
-
Requires-Dist: markupsafe; extra == 'test'
|
|
724
|
-
Requires-Dist: nest-asyncio; extra == 'test'
|
|
725
|
-
Requires-Dist: packaging; extra == 'test'
|
|
726
705
|
Requires-Dist: plotly; extra == 'test'
|
|
727
|
-
Requires-Dist: pluggy; extra == 'test'
|
|
728
706
|
Requires-Dist: pytest; extra == 'test'
|
|
729
707
|
Requires-Dist: pytest-asyncio; extra == 'test'
|
|
730
708
|
Requires-Dist: requests; extra == 'test'
|
|
731
|
-
Requires-Dist: retrying; extra == 'test'
|
|
732
|
-
Requires-Dist: tenacity; extra == 'test'
|
|
733
|
-
Requires-Dist: werkzeug; extra == 'test'
|
|
734
|
-
Requires-Dist: zipp; extra == 'test'
|
|
735
709
|
Description-Content-Type: text/markdown
|
|
736
710
|
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
Interface handling the communication between sensory data-emitting devices, InfluxDB and the user.
|
|
740
|
-
|
|
741
|
-
The most important object that a user would use is `DatabseInterface` within `ahttpdc.reads.interface` module.
|
|
742
|
-
This class facilitates the communication between the fetcher and the querying apis of InfluxDB.
|
|
711
|
+
<div align="center">
|
|
743
712
|
|
|
744
|
-
|
|
713
|
+
[](https://pypi.org/project/async-httpd-data-collector/)
|
|
714
|
+
[](https://pepy.tech/project/async-httpd-data-collector)
|
|
715
|
+
[](https://pypi.org/project/async-httpd-data-collector/)
|
|
716
|
+
</div>
|
|
745
717
|
|
|
746
|
-
|
|
747
|
-
* `interface.daemon.disable()`.
|
|
718
|
+
# async-httpd-data-collector
|
|
748
719
|
|
|
749
|
-
|
|
720
|
+
> **Note:** This is an older university project and is not actively maintained.
|
|
721
|
+
> It works as-is, but is not extensively tested.
|
|
750
722
|
|
|
751
|
-
|
|
723
|
+
A Python library that acts as an asynchronous gateway between IoT sensor
|
|
724
|
+
devices and InfluxDB. It fetches JSON readings from a device (like a
|
|
725
|
+
NodeMCU/ESP8266) over HTTP, parses them, and stores them as time-series data.
|
|
726
|
+
You can then query the data back as pandas DataFrames.
|
|
752
727
|
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
728
|
+
Started as a university project to get hands-on with async Python,
|
|
729
|
+
`asyncio`, `aiohttp`, and time-series databases. The hardware side runs on
|
|
730
|
+
an [arduino-air-state-server](https://github.com/straightchlorine/arduino-air-state-server) -
|
|
731
|
+
a NodeMCU board with air quality sensors (MQ135, BMP180, DHT22, DS18B20)
|
|
732
|
+
that exposes readings at an HTTP endpoint.
|
|
756
733
|
|
|
757
|
-
|
|
734
|
+
## Installation
|
|
758
735
|
|
|
759
|
-
|
|
736
|
+
```bash
|
|
737
|
+
pip install async-httpd-data-collector
|
|
738
|
+
```
|
|
760
739
|
|
|
740
|
+
## Quick Start
|
|
761
741
|
|
|
762
742
|
```python
|
|
763
|
-
import
|
|
764
|
-
from ahttpdc.reads.interface import DatabaseInterface
|
|
765
|
-
|
|
766
|
-
# load the secrets
|
|
767
|
-
with open('../../../secrets/secrets.json', 'r') as f:
|
|
768
|
-
secrets = json.load(f)
|
|
743
|
+
from ahttpdc.read.database_interface import DatabaseInterface
|
|
769
744
|
|
|
770
|
-
# define sensors
|
|
745
|
+
# define which sensors and parameters to track
|
|
771
746
|
sensors = {
|
|
772
|
-
'bmp180': ['altitude', 'pressure', 'seaLevelPressure'],
|
|
747
|
+
'bmp180': ['altitude', 'pressure', 'seaLevelPressure', 'temperature'],
|
|
773
748
|
'mq135': ['aceton', 'alcohol', 'co', 'co2', 'nh4', 'toulen'],
|
|
774
749
|
'ds18b20': ['temperature'],
|
|
775
|
-
'dht22': ['humidity'],
|
|
750
|
+
'dht22': ['humidity', 'temperature'],
|
|
776
751
|
}
|
|
777
752
|
|
|
778
|
-
#
|
|
753
|
+
# connect to InfluxDB and the device
|
|
779
754
|
interface = DatabaseInterface(
|
|
780
|
-
secrets['host'],
|
|
781
|
-
secrets['port'],
|
|
782
|
-
secrets['token'],
|
|
783
|
-
secrets['organization'],
|
|
784
|
-
secrets['bucket'],
|
|
785
755
|
sensors,
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
756
|
+
db_host='localhost',
|
|
757
|
+
db_port=8086,
|
|
758
|
+
db_token='your-influxdb-token',
|
|
759
|
+
db_org='your-org',
|
|
760
|
+
db_bucket='your-bucket',
|
|
761
|
+
srv_ip='192.168.1.100', # device IP
|
|
762
|
+
srv_port=80,
|
|
763
|
+
handle='circumstances', # HTTP endpoint on the device
|
|
789
764
|
)
|
|
790
|
-
```
|
|
791
765
|
|
|
792
|
-
|
|
766
|
+
# start the background daemon - fetches and stores data continuously
|
|
767
|
+
interface.daemon.enable()
|
|
793
768
|
|
|
769
|
+
# query the last 30 days of data as a DataFrame
|
|
770
|
+
df = interface.query_historical('-30d')
|
|
771
|
+
print(df.head())
|
|
794
772
|
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
import asyncio
|
|
798
|
-
from datetime import datetime, timedelta
|
|
799
|
-
from pathlib import Path
|
|
800
|
-
|
|
801
|
-
# if there is readings.csv file, load it
|
|
802
|
-
# if not - create it
|
|
803
|
-
readings_path = Path('../data/readings.csv')
|
|
804
|
-
if readings_path.is_file():
|
|
805
|
-
sensor = pd.read_csv(readings_path)
|
|
806
|
-
else:
|
|
807
|
-
sensor = await interface.query_historical('-30d')
|
|
808
|
-
sensor.to_csv(readings_path)
|
|
773
|
+
# stop the daemon when done
|
|
774
|
+
interface.daemon.disable()
|
|
809
775
|
```
|
|
810
776
|
|
|
777
|
+
## How It Works
|
|
811
778
|
|
|
812
|
-
```
|
|
813
|
-
|
|
779
|
+
```
|
|
780
|
+
NodeMCU device async-httpd-data-collector InfluxDB
|
|
781
|
+
(sensors) (storage)
|
|
782
|
+
| |
|
|
783
|
+
|--- HTTP GET /circumstances --> AsyncFetcher |
|
|
784
|
+
| | |
|
|
785
|
+
| JSONInfluxParser |
|
|
786
|
+
| | |
|
|
787
|
+
| AsyncCollector --------> |
|
|
788
|
+
| |
|
|
789
|
+
| AsyncQuery <-------- |
|
|
790
|
+
| | |
|
|
791
|
+
| DataParser |
|
|
792
|
+
| | |
|
|
793
|
+
| pandas DataFrame |
|
|
814
794
|
```
|
|
815
795
|
|
|
796
|
+
The `DatabaseInterface` is the main entry point. It manages two things:
|
|
816
797
|
|
|
798
|
+
- **DataDaemon** - a background process (via `multiprocessing`) that
|
|
799
|
+
periodically fetches sensor data from the device and stores it in InfluxDB.
|
|
800
|
+
- **AsyncQuery** - queries InfluxDB and returns results as pandas DataFrames
|
|
801
|
+
with local timezone-adjusted timestamps.
|
|
817
802
|
|
|
803
|
+
### Querying
|
|
818
804
|
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
<th>aceton</th>
|
|
826
|
-
<th>alcohol</th>
|
|
827
|
-
<th>altitude</th>
|
|
828
|
-
<th>co</th>
|
|
829
|
-
<th>co2</th>
|
|
830
|
-
<th>humidity</th>
|
|
831
|
-
<th>nh4</th>
|
|
832
|
-
<th>pressure</th>
|
|
833
|
-
<th>seaLevelPressure</th>
|
|
834
|
-
<th>temperature</th>
|
|
835
|
-
<th>toulen</th>
|
|
836
|
-
</tr>
|
|
837
|
-
</thead>
|
|
838
|
-
<tbody>
|
|
839
|
-
<tr>
|
|
840
|
-
<th>0</th>
|
|
841
|
-
<td>2024-05-16 17:43:59.196399+00:00</td>
|
|
842
|
-
<td>0.41</td>
|
|
843
|
-
<td>1.17</td>
|
|
844
|
-
<td>149.92</td>
|
|
845
|
-
<td>3.38</td>
|
|
846
|
-
<td>402.54</td>
|
|
847
|
-
<td>37.4</td>
|
|
848
|
-
<td>3.93</td>
|
|
849
|
-
<td>999.35</td>
|
|
850
|
-
<td>1017.31</td>
|
|
851
|
-
<td>24.40</td>
|
|
852
|
-
<td>0.48</td>
|
|
853
|
-
</tr>
|
|
854
|
-
<tr>
|
|
855
|
-
<th>1</th>
|
|
856
|
-
<td>2024-05-16 17:44:01.768738+00:00</td>
|
|
857
|
-
<td>0.47</td>
|
|
858
|
-
<td>1.32</td>
|
|
859
|
-
<td>149.76</td>
|
|
860
|
-
<td>3.94</td>
|
|
861
|
-
<td>402.84</td>
|
|
862
|
-
<td>30.5</td>
|
|
863
|
-
<td>4.33</td>
|
|
864
|
-
<td>997.61</td>
|
|
865
|
-
<td>1015.56</td>
|
|
866
|
-
<td>24.03</td>
|
|
867
|
-
<td>0.55</td>
|
|
868
|
-
</tr>
|
|
869
|
-
<tr>
|
|
870
|
-
<th>2</th>
|
|
871
|
-
<td>2024-05-16 17:44:03.255309+00:00</td>
|
|
872
|
-
<td>0.96</td>
|
|
873
|
-
<td>2.62</td>
|
|
874
|
-
<td>149.54</td>
|
|
875
|
-
<td>9.16</td>
|
|
876
|
-
<td>405.25</td>
|
|
877
|
-
<td>49.1</td>
|
|
878
|
-
<td>7.35</td>
|
|
879
|
-
<td>999.14</td>
|
|
880
|
-
<td>1017.08</td>
|
|
881
|
-
<td>23.16</td>
|
|
882
|
-
<td>1.15</td>
|
|
883
|
-
</tr>
|
|
884
|
-
<tr>
|
|
885
|
-
<th>3</th>
|
|
886
|
-
<td>2024-05-16 17:44:04.618203+00:00</td>
|
|
887
|
-
<td>0.30</td>
|
|
888
|
-
<td>0.86</td>
|
|
889
|
-
<td>149.38</td>
|
|
890
|
-
<td>2.32</td>
|
|
891
|
-
<td>401.94</td>
|
|
892
|
-
<td>32.9</td>
|
|
893
|
-
<td>3.10</td>
|
|
894
|
-
<td>999.09</td>
|
|
895
|
-
<td>1017.02</td>
|
|
896
|
-
<td>23.05</td>
|
|
897
|
-
<td>0.35</td>
|
|
898
|
-
</tr>
|
|
899
|
-
<tr>
|
|
900
|
-
<th>4</th>
|
|
901
|
-
<td>2024-05-16 17:44:05.954714+00:00</td>
|
|
902
|
-
<td>1.31</td>
|
|
903
|
-
<td>3.50</td>
|
|
904
|
-
<td>149.37</td>
|
|
905
|
-
<td>13.13</td>
|
|
906
|
-
<td>406.82</td>
|
|
907
|
-
<td>48.8</td>
|
|
908
|
-
<td>9.21</td>
|
|
909
|
-
<td>998.04</td>
|
|
910
|
-
<td>1015.93</td>
|
|
911
|
-
<td>23.92</td>
|
|
912
|
-
<td>1.57</td>
|
|
913
|
-
</tr>
|
|
914
|
-
<tr>
|
|
915
|
-
<th>...</th>
|
|
916
|
-
<td>...</td>
|
|
917
|
-
<td>...</td>
|
|
918
|
-
<td>...</td>
|
|
919
|
-
<td>...</td>
|
|
920
|
-
<td>...</td>
|
|
921
|
-
<td>...</td>
|
|
922
|
-
<td>...</td>
|
|
923
|
-
<td>...</td>
|
|
924
|
-
<td>...</td>
|
|
925
|
-
<td>...</td>
|
|
926
|
-
<td>...</td>
|
|
927
|
-
<td>...</td>
|
|
928
|
-
</tr>
|
|
929
|
-
<tr>
|
|
930
|
-
<th>284122</th>
|
|
931
|
-
<td>2024-05-21 14:42:57.894312+00:00</td>
|
|
932
|
-
<td>1.35</td>
|
|
933
|
-
<td>3.62</td>
|
|
934
|
-
<td>150.08</td>
|
|
935
|
-
<td>13.68</td>
|
|
936
|
-
<td>407.03</td>
|
|
937
|
-
<td>47.6</td>
|
|
938
|
-
<td>9.46</td>
|
|
939
|
-
<td>998.85</td>
|
|
940
|
-
<td>1016.81</td>
|
|
941
|
-
<td>24.35</td>
|
|
942
|
-
<td>1.63</td>
|
|
943
|
-
</tr>
|
|
944
|
-
<tr>
|
|
945
|
-
<th>284123</th>
|
|
946
|
-
<td>2024-05-21 14:42:59.277937+00:00</td>
|
|
947
|
-
<td>1.08</td>
|
|
948
|
-
<td>2.92</td>
|
|
949
|
-
<td>149.87</td>
|
|
950
|
-
<td>10.48</td>
|
|
951
|
-
<td>405.79</td>
|
|
952
|
-
<td>49.3</td>
|
|
953
|
-
<td>8.00</td>
|
|
954
|
-
<td>998.58</td>
|
|
955
|
-
<td>1016.53</td>
|
|
956
|
-
<td>23.41</td>
|
|
957
|
-
<td>1.29</td>
|
|
958
|
-
</tr>
|
|
959
|
-
<tr>
|
|
960
|
-
<th>284124</th>
|
|
961
|
-
<td>2024-05-21 14:43:00.594968+00:00</td>
|
|
962
|
-
<td>0.38</td>
|
|
963
|
-
<td>1.09</td>
|
|
964
|
-
<td>149.97</td>
|
|
965
|
-
<td>3.09</td>
|
|
966
|
-
<td>402.38</td>
|
|
967
|
-
<td>33.8</td>
|
|
968
|
-
<td>3.71</td>
|
|
969
|
-
<td>999.59</td>
|
|
970
|
-
<td>1017.54</td>
|
|
971
|
-
<td>24.88</td>
|
|
972
|
-
<td>0.44</td>
|
|
973
|
-
</tr>
|
|
974
|
-
<tr>
|
|
975
|
-
<th>284125</th>
|
|
976
|
-
<td>2024-05-21 14:43:01.918239+00:00</td>
|
|
977
|
-
<td>1.41</td>
|
|
978
|
-
<td>3.77</td>
|
|
979
|
-
<td>150.13</td>
|
|
980
|
-
<td>14.38</td>
|
|
981
|
-
<td>407.29</td>
|
|
982
|
-
<td>44.4</td>
|
|
983
|
-
<td>9.76</td>
|
|
984
|
-
<td>998.51</td>
|
|
985
|
-
<td>1016.48</td>
|
|
986
|
-
<td>23.54</td>
|
|
987
|
-
<td>1.70</td>
|
|
988
|
-
</tr>
|
|
989
|
-
<tr>
|
|
990
|
-
<th>284126</th>
|
|
991
|
-
<td>2024-05-21 14:43:03.248095+00:00</td>
|
|
992
|
-
<td>1.24</td>
|
|
993
|
-
<td>3.32</td>
|
|
994
|
-
<td>150.50</td>
|
|
995
|
-
<td>12.29</td>
|
|
996
|
-
<td>406.50</td>
|
|
997
|
-
<td>48.8</td>
|
|
998
|
-
<td>8.84</td>
|
|
999
|
-
<td>998.85</td>
|
|
1000
|
-
<td>1016.85</td>
|
|
1001
|
-
<td>22.44</td>
|
|
1002
|
-
<td>1.49</td>
|
|
1003
|
-
</tr>
|
|
1004
|
-
</tbody>
|
|
1005
|
-
</table>
|
|
1006
|
-
<p>284127 rows × 12 columns</p>
|
|
1007
|
-
</div>
|
|
805
|
+
```python
|
|
806
|
+
# latest reading
|
|
807
|
+
df = interface.query_latest()
|
|
808
|
+
|
|
809
|
+
# last 3 hours
|
|
810
|
+
df = interface.query_historical('-3h')
|
|
1008
811
|
|
|
812
|
+
# specific time range
|
|
813
|
+
df = interface.query_historical('2024-05-16T00:00:00Z', '2024-05-21T00:00:00Z')
|
|
814
|
+
|
|
815
|
+
# custom Flux query
|
|
816
|
+
df = interface.query_custom_sync('from(bucket:"my-bucket") |> range(start: -1d) |> last()')
|
|
817
|
+
```
|
|
1009
818
|
|
|
819
|
+
## Related Projects
|
|
1010
820
|
|
|
821
|
+
- [arduino-air-state-server](https://github.com/straightchlorine/arduino-air-state-server) -
|
|
822
|
+
the NodeMCU firmware that collects sensor readings and serves them over HTTP
|
|
823
|
+
- [air-quality-data-analysis](https://github.com/straightchlorine/air-quality-data-analysis) -
|
|
824
|
+
Jupyter notebooks with data analysis (heatmaps, correlations, anomaly detection)
|
|
825
|
+
and SARIMAX time-series forecasting on the collected data
|