Skip to content

Commit 6db15dd

Browse files
committed
refactored
restructured
1 parent a827cf2 commit 6db15dd

9 files changed

+283
-99
lines changed

.gitignore

+148
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
# Byte-compiled / optimized / DLL files
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
6+
# C extensions
7+
*.so
8+
9+
# Distribution / packaging
10+
.Python
11+
build/
12+
develop-eggs/
13+
**/dist/
14+
eggs/
15+
.eggs/
16+
lib/
17+
lib64/
18+
parts/
19+
sdist/
20+
var/
21+
wheels/
22+
tmp/
23+
share/python-wheels/
24+
*.egg-info/
25+
.installed.cfg
26+
*.egg
27+
MANIFEST
28+
29+
# PyInstaller
30+
# Usually these files are written by a python script from a template
31+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
32+
*.manifest
33+
*.spec
34+
35+
# Installer logs
36+
pip-log.txt
37+
pip-delete-this-directory.txt
38+
39+
# Unit test / coverage reports
40+
htmlcov/
41+
.tox/
42+
.nox/
43+
.coverage
44+
.coverage.*
45+
.cache
46+
nosetests.xml
47+
coverage.xml
48+
*.cover
49+
*.py,cover
50+
.hypothesis/
51+
.pytest_cache/
52+
cover/
53+
54+
# Translations
55+
*.mo
56+
*.pot
57+
58+
# Scrapy stuff:
59+
.scrapy
60+
61+
# Sphinx documentation
62+
docs/_build/
63+
64+
# PyBuilder
65+
.pybuilder/
66+
target/
67+
68+
# Jupyter Notebook
69+
.ipynb_checkpoints
70+
71+
# IPython
72+
profile_default/
73+
ipython_config.py
74+
75+
# pyenv
76+
# For a library or package, you might want to ignore these files since the code is
77+
# intended to run in multiple environments; otherwise, check them in:
78+
# .python-version
79+
80+
# pipenv
81+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
82+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
83+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
84+
# install all needed dependencies.
85+
#Pipfile.lock
86+
87+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
88+
__pypackages__/
89+
90+
# Celery stuff
91+
celerybeat-schedule
92+
celerybeat.pid
93+
94+
# SageMath parsed files
95+
*.sage.py
96+
97+
# Environments
98+
.venv
99+
env/
100+
venv/
101+
ENV/
102+
env.bak/
103+
venv.bak/
104+
105+
# Spyder project settings
106+
.spyderproject
107+
.spyproject
108+
109+
# Rope project settings
110+
.ropeproject
111+
112+
# mkdocs documentation
113+
/site
114+
115+
# mypy
116+
.mypy_cache/
117+
.dmypy.json
118+
dmypy.json
119+
120+
# Pyre type checker
121+
.pyre/
122+
123+
# pytype static type analyzer
124+
.pytype/
125+
126+
# Cython debug symbols
127+
cython_debug/
128+
129+
# intellij
130+
.idea/
131+
132+
**/.env
133+
134+
# Visual Studio Code
135+
.vscode/
136+
.history
137+
138+
# for vscode dev container
139+
local_home/
140+
.devcontainer
141+
142+
143+
# Editor Related
144+
.idea/*
145+
*.iml
146+
147+
# Profiler
148+
fil-result

Makefile

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
test:
2+
python -m pytest -s -v --doctest-modules

ambientweather.py

-57
This file was deleted.

ambientweather_test.py

-42
This file was deleted.

conftest.py

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
"""
2+
Tests run from the project root folder.
3+
But the python code expects to run inside server folder.
4+
5+
So for tests we add server folder to sys.path.
6+
7+
This file is loaded first by py.test therefore we change sys.path for all other python files.
8+
"""
9+
import os.path
10+
import sys
11+
12+
13+
sys.path.append(os.path.join(os.path.dirname(__file__), 'src'))

src/ambientweather.py

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import requests
2+
from lxml import html
3+
from datetime import datetime
4+
5+
6+
TITLE = 'LiveData' # HTML live data page title
7+
8+
9+
class SensorData(object):
10+
"""
11+
time
12+
temp
13+
humidity
14+
abs_press
15+
rel_press
16+
battery ('Normal')
17+
"""
18+
19+
def parse(self, live_data_html):
20+
"""
21+
Extract sensor's data from html (LiveData.html from your ObserverIP)
22+
Returns touple with (sensor1, sensor2 -> SensorData)
23+
"""
24+
25+
tree = html.fromstring(live_data_html)
26+
title = tree.xpath('//title/text()')
27+
if title[0] != TITLE:
28+
raise ValueError(f'Wrong html page. Good one have to have title {TITLE}')
29+
30+
in_sensor = SensorData()
31+
time_str = tree.xpath('//input[@name="CurrTime"]/@value')[0]
32+
in_sensor.time = datetime.strptime(time_str, '%H:%M %m/%d/%Y')
33+
in_sensor.temp = float(tree.xpath('//input[@name="inTemp"]/@value')[0])
34+
in_sensor.humidity = float(tree.xpath('//input[@name="inHumi"]/@value')[0])
35+
in_sensor.abs_press = float(tree.xpath('//input[@name="AbsPress"]/@value')[0])
36+
in_sensor.rel_press = float(tree.xpath('//input[@name="RelPress"]/@value')[0])
37+
in_sensor.battery = tree.xpath('//input[@name="inBattSta"]/@value')[0]
38+
39+
out_sensor = SensorData()
40+
out_sensor.time = in_sensor.time
41+
out_sensor.temp = float(tree.xpath('//input[@name="outTemp"]/@value')[0])
42+
out_sensor.humidity = float(tree.xpath('//input[@name="outHumi"]/@value')[0])
43+
out_sensor.abs_press = in_sensor.abs_press
44+
out_sensor.rel_press = in_sensor.rel_press
45+
out_sensor.battery = tree.xpath('//input[@name="outBattSta2"]/@value')[0]
46+
47+
return in_sensor, out_sensor
48+
49+
def get(self, url):
50+
"""
51+
Load ObserverIP live data page from the URL and parse it
52+
53+
Returns touple with (sensor1, sensor2 -> SensorData)
54+
"""
55+
56+
page = requests.get(url).content
57+
return self.parse(page)

tests/conftest.py

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from pathlib import Path
2+
import pytest
3+
4+
5+
def _get_repo_root_dir() -> str:
6+
"""
7+
:return: path to the project folder.
8+
`tests/` should be in the same folder and this file should be in the root of `tests/`.
9+
"""
10+
return str(Path(__file__).parent.parent)
11+
12+
13+
ROOT_DIR = _get_repo_root_dir()
14+
RESOURCES = Path(f"{ROOT_DIR}/tests/resources")
15+
16+
@pytest.fixture(
17+
scope="function",
18+
params=[
19+
"LiveData.html",
20+
],
21+
)
22+
def ambientweather_data(request) -> str:
23+
with (RESOURCES / request.param).open("r", encoding="utf8") as data:
24+
return data.read()
File renamed without changes.

tests/test_ambientweather_data.py

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
from ambientweather import SensorData
2+
from datetime import datetime
3+
4+
5+
def test_ambientweather_data(ambientweather_data: str):
6+
sensor_data = SensorData()
7+
in_sensor, out_sensor = sensor_data.parse(ambientweather_data)
8+
9+
print(f'Time: {in_sensor.time}\n')
10+
print('''Indoor\n{delimiter}\nTemperature: {temp}\nHumidity: {humidity}
11+
Absolute preassure: {abs_press}\nRelative preassure: {rel_press}\nBattery status: {battery}\n'''.format(
12+
delimiter='='*20,
13+
temp=in_sensor.temp,
14+
humidity=in_sensor.humidity,
15+
abs_press=in_sensor.abs_press,
16+
rel_press=in_sensor.rel_press,
17+
battery=in_sensor.battery
18+
))
19+
print('''Outdoor\n{delimiter}\nTemperature: {temp}\nHumidity: {humidity}
20+
Battery status: {battery}\n'''.format(
21+
delimiter='='*20,
22+
temp=in_sensor.temp,
23+
humidity=in_sensor.humidity,
24+
battery=in_sensor.battery
25+
))
26+
27+
assert in_sensor.time == datetime.strptime('2017/10/06 13:55:00', '%Y/%m/%d %H:%M:%S')
28+
assert in_sensor.temp == 21.9
29+
assert in_sensor.humidity == 50.0
30+
assert in_sensor.abs_press == 744.29
31+
assert in_sensor.rel_press == 728.31
32+
assert in_sensor.battery == 'Normal'
33+
assert out_sensor.temp == 10.1
34+
assert out_sensor.humidity == 71.0
35+
assert out_sensor.battery == 'Normal'
36+
37+
38+
39+

0 commit comments

Comments
 (0)