Skip to content
This repository was archived by the owner on Jun 7, 2021. It is now read-only.

Commit efb3fff

Browse files
authored
Merge pull request #3 from jtc42/w3c-compat
W3c compat
2 parents 4d9a47d + a61e28b commit efb3fff

28 files changed

Lines changed: 2131 additions & 1593 deletions

.flake8

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[flake8]
2+
ignore = E203, E266, E501, W503
3+
max-line-length = 88
4+
max-complexity = 18
5+
select = B,C,E,F,W,T4

.github/workflows/build.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ jobs:
1414
strategy:
1515
matrix:
1616
python-version: [
17-
2.7,
1817
3.5,
1918
3.6,
2019
3.7,

.gitignore

Lines changed: 137 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,138 @@
1-
*.egg
2-
*.egg-info/
3-
*.py[cod]
4-
*.swp
5-
*~
6-
/build/
7-
/dist/
8-
/requirements.txt
1+
# Byte-compiled / optimized / DLL files
92
__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+
downloads/
15+
eggs/
16+
.eggs/
17+
lib/
18+
lib64/
19+
parts/
20+
sdist/
21+
var/
22+
wheels/
23+
pip-wheel-metadata/
24+
share/python-wheels/
25+
*.egg-info/
26+
.installed.cfg
27+
*.egg
28+
MANIFEST
29+
# We use poetry, so should ignore the generated setup.py
30+
/setup.py
31+
32+
# PyInstaller
33+
# Usually these files are written by a python script from a template
34+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
35+
*.manifest
36+
*.spec
37+
38+
# Installer logs
39+
pip-log.txt
40+
pip-delete-this-directory.txt
41+
42+
# Unit test / coverage reports
43+
htmlcov/
44+
coverage_html_report/
45+
.tox/
46+
.nox/
47+
.coverage
48+
.coverage.*
49+
.cache
50+
nosetests.xml
51+
coverage.xml
52+
*.cover
53+
*.py,cover
54+
.hypothesis/
55+
.pytest_cache/
56+
coverage_html_report/
57+
prof/
58+
59+
# Translations
60+
*.mo
61+
*.pot
62+
63+
# Django stuff:
64+
*.log
65+
local_settings.py
66+
db.sqlite3
67+
db.sqlite3-journal
68+
69+
# Flask stuff:
70+
instance/
71+
.webassets-cache
72+
73+
# Scrapy stuff:
74+
.scrapy
75+
76+
# Sphinx documentation
77+
docs/_build/
78+
79+
# PyBuilder
80+
target/
81+
82+
# Jupyter Notebook
83+
.ipynb_checkpoints
84+
85+
# IPython
86+
profile_default/
87+
ipython_config.py
88+
89+
# pyenv
90+
.python-version
91+
92+
# pipenv
93+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
94+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
95+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
96+
# install all needed dependencies.
97+
#Pipfile.lock
98+
99+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
100+
__pypackages__/
101+
102+
# Celery stuff
103+
celerybeat-schedule
104+
celerybeat.pid
105+
106+
# SageMath parsed files
107+
*.sage.py
108+
109+
# Environments
110+
.env*
111+
.venv*
112+
env/
113+
venv/
114+
ENV/
115+
env.bak/
116+
venv.bak/
117+
118+
# Spyder project settings
119+
.spyderproject
120+
.spyproject
121+
122+
# Rope project settings
123+
.ropeproject
124+
125+
# mkdocs documentation
126+
/site
127+
128+
# mypy
129+
.mypy_cache/
130+
.dmypy.json
131+
dmypy.json
132+
133+
# Pyre type checker
134+
.pyre/
135+
136+
# IDE files
137+
.vscode/*
138+
.idea/*

MANIFEST.in

Lines changed: 0 additions & 1 deletion
This file was deleted.

README.rst

Lines changed: 46 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ webthing
88
.. image:: https://img.shields.io/badge/license-MPL--2.0-blue.svg
99
:target: https://github.com/mozilla-iot/webthing-python/blob/master/LICENSE.txt
1010

11-
Implementation of an HTTP `Web Thing <https://iot.mozilla.org/wot/>`_. This library is compatible with Python 2.7 and 3.5+.
11+
Implementation of an HTTP `Web Thing <https://iot.mozilla.org/wot/>`_. This library is compatible with Python 3.5+.
1212

1313
Installation
1414
============
@@ -63,15 +63,15 @@ First we create a new Thing:
6363
6464
Now we can add the required properties.
6565

66-
The ``on`` property reports and sets the on/off state of the light. For this, we need to have a ``Value`` object which holds the actual state and also a method to turn the light on/off. For our purposes, we just want to log the new state if the light is switched on/off.
66+
The on property reports and sets the on/off state of the light. For this, we need to have a Value object which holds the actual state and also a method to turn the light on/off. For our purposes, we just want to log the new state if the light is switched on/off.
6767

6868
.. code:: python
6969
7070
light.add_property(
7171
Property(
7272
light,
7373
'on',
74-
Value(True, lambda v: print('On-State is now', v)),
74+
Value(True, None, lambda x: print(x)),
7575
metadata={
7676
'@type': 'OnOffProperty',
7777
'title': 'On/Off',
@@ -87,7 +87,7 @@ The ``brightness`` property reports the brightness level of the light and sets t
8787
Property(
8888
light,
8989
'brightness',
90-
Value(50, lambda v: print('Brightness is now', v)),
90+
Value(50, None, lambda x: print(x)),
9191
metadata={
9292
'@type': 'BrightnessProperty',
9393
'title': 'Brightness',
@@ -102,9 +102,7 @@ Now we can add our newly created thing to the server and start it:
102102

103103
.. code:: python
104104
105-
# If adding more than one thing, use MultipleThings() with a name.
106-
# In the single thing case, the thing's name will be broadcast.
107-
server = WebThingServer(SingleThing(light), port=8888)
105+
server = WebThingServer(light, port=8888)
108106
109107
try:
110108
server.start()
@@ -134,33 +132,51 @@ First we create a new Thing:
134132
'A web connected humidity sensor'
135133
)
136134
137-
Then we create and add the appropriate property:
135+
Then we create and add the appropriate property.
138136

139-
* ``level``: tells us what the sensor is actually reading
137+
Contrary to the light, the value cannot be set via an API call, as it wouldn't make much sense, to SET what a sensor is reading. Therefore, we are creating a **readOnly** property.
140138

141-
- Contrary to the light, the value cannot be set via an API call, as it wouldn't make much sense, to SET what a sensor is reading. Therefore, we are creating a **readOnly** property.
139+
.. code:: python
140+
141+
sensor.add_property(
142+
Property(
143+
sensor,
144+
'level',
145+
Value(None, self.read_from_gpio, None),
146+
metadata={
147+
'@type': 'LevelProperty',
148+
'title': 'Humidity',
149+
'type': 'number',
150+
'description': 'The current humidity in %',
151+
'minimum': 0,
152+
'maximum': 100,
153+
'unit': 'percent',
154+
'readOnly': True,
155+
}))
142156
143-
.. code:: python
157+
In this example, we pass a `readproperty` method that will read and return the sensor value every time it is requested.
144158

145-
level = Value(0.0);
159+
Alternatively, we can create a thread that queries the physical sensor every few seconds. We first remove the `readproperty` argument from our Property.
146160

147-
sensor.add_property(
148-
Property(
149-
sensor,
150-
'level',
151-
level,
152-
metadata={
153-
'@type': 'LevelProperty',
154-
'title': 'Humidity',
155-
'type': 'number',
156-
'description': 'The current humidity in %',
157-
'minimum': 0,
158-
'maximum': 100,
159-
'unit': 'percent',
160-
'readOnly': True,
161-
}))
161+
.. code:: python
162+
163+
sensor.add_property(
164+
Property(
165+
sensor,
166+
'level',
167+
Value(0.0),
168+
metadata={
169+
'@type': 'LevelProperty',
170+
'title': 'Humidity',
171+
'type': 'number',
172+
'description': 'The current humidity in %',
173+
'minimum': 0,
174+
'maximum': 100,
175+
'unit': 'percent',
176+
'readOnly': True,
177+
}))
162178
163-
Now we have a sensor that constantly reports 0%. To make it usable, we need a thread or some kind of input when the sensor has a new reading available. For this purpose we start a thread that queries the physical sensor every few seconds. For our purposes, it just calls a fake method.
179+
We then create our looping function to periodically query the sensor and set the property value.
164180

165181
.. code:: python
166182
@@ -171,13 +187,12 @@ Now we have a sensor that constantly reports 0%. To make it usable, we need a th
171187
try:
172188
while True:
173189
await sleep(3)
174-
new_level = self.read_from_gpio()
190+
sensor.properties["level"].value.set(self.read_from_gpio())
175191
logging.debug('setting new humidity level: %s', new_level)
176-
self.level.notify_of_external_update(new_level)
177192
except CancelledError:
178193
pass
179194
180-
This will update our ``Value`` object with the sensor readings via the ``self.level.notify_of_external_update(read_from_gpio())`` call. The ``Value`` object now notifies the property and the thing that the value has changed, which in turn notifies all websocket listeners.
195+
This will update our ``Value`` object with the sensor readings via the ``sensor.properties["level"].value.set(self.read_from_gpio())`` call. The ``Value`` object now notifies the property and the thing that the value has changed, which in turn notifies all websocket listeners.
181196

182197
Adding to Gateway
183198
=================

0 commit comments

Comments
 (0)