circuitpython-fake-bme280 1.0.4__py3-none-any.whl → 1.2__py3-none-any.whl
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.
- {circuitpython_fake_bme280-1.0.4.dist-info → circuitpython_fake_bme280-1.2.dist-info}/METADATA +5 -4
- circuitpython_fake_bme280-1.2.dist-info/RECORD +9 -0
- {circuitpython_fake_bme280-1.0.4.dist-info → circuitpython_fake_bme280-1.2.dist-info}/WHEEL +1 -1
- fake_bme280/advanced.py +269 -0
- fake_bme280/basic.py +128 -35
- circuitpython_fake_bme280-1.0.4.dist-info/RECORD +0 -8
- {circuitpython_fake_bme280-1.0.4.dist-info → circuitpython_fake_bme280-1.2.dist-info/licenses}/LICENSE +0 -0
- {circuitpython_fake_bme280-1.0.4.dist-info → circuitpython_fake_bme280-1.2.dist-info}/top_level.txt +0 -0
{circuitpython_fake_bme280-1.0.4.dist-info → circuitpython_fake_bme280-1.2.dist-info}/METADATA
RENAMED
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: circuitpython-fake-bme280
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.2
|
|
4
4
|
Summary: BME280 Driver for CircuitPython used for testing functionality with no hardware attached
|
|
5
5
|
Author-email: Adafruit Industries <circuitpython@adafruit.com>
|
|
6
|
-
License: MIT
|
|
6
|
+
License-Expression: MIT
|
|
7
7
|
Project-URL: Homepage, https://github.com/brentru/CircuitPython_Fake_BME280
|
|
8
8
|
Keywords: adafruit,blinka,circuitpython,micropython,fake_bme280,bme280,,test,,fake,,mock,,stub
|
|
9
9
|
Classifier: Intended Audience :: Developers
|
|
10
10
|
Classifier: Topic :: Software Development :: Libraries
|
|
11
11
|
Classifier: Topic :: Software Development :: Embedded Systems
|
|
12
12
|
Classifier: Topic :: System :: Hardware
|
|
13
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
14
13
|
Classifier: Programming Language :: Python :: 3
|
|
15
14
|
Description-Content-Type: text/x-rst
|
|
16
15
|
License-File: LICENSE
|
|
@@ -19,6 +18,8 @@ Requires-Dist: adafruit-circuitpython-busdevice
|
|
|
19
18
|
Requires-Dist: adafruit-circuitpython-register
|
|
20
19
|
Requires-Dist: toml
|
|
21
20
|
Provides-Extra: optional
|
|
21
|
+
Requires-Dist: python-dotenv; extra == "optional"
|
|
22
|
+
Dynamic: license-file
|
|
22
23
|
|
|
23
24
|
Introduction
|
|
24
25
|
============
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
circuitpython_fake_bme280-1.2.dist-info/licenses/LICENSE,sha256=tXgkGXjihZP5R0fW0-IyViyV_rB8TXrzKdiLP4crJn0,1103
|
|
2
|
+
fake_bme280/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
+
fake_bme280/advanced.py,sha256=_Mx7ocLBxLe5OL80cYQDcyuKHLyQpPjUp01KEEFricw,8059
|
|
4
|
+
fake_bme280/basic.py,sha256=uSEr5wkVnJ8X_4Eq5PmalavBXvgNWj7HsC31PW_Uc-0,12502
|
|
5
|
+
fake_bme280/protocol.py,sha256=IeQ6cPpu9r7fvKwDkLHg2wLZ7QkOyCtyRjKGtIpW3ho,1017
|
|
6
|
+
circuitpython_fake_bme280-1.2.dist-info/METADATA,sha256=9mLS7tTmILM-xQge59UHNpfqB7bdSWzHbZN5gnr60Cw,4640
|
|
7
|
+
circuitpython_fake_bme280-1.2.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
8
|
+
circuitpython_fake_bme280-1.2.dist-info/top_level.txt,sha256=zYm6UwRd0tbyREvYLz0zQcP9NY4GvkMWQ19rZYbwO0Q,12
|
|
9
|
+
circuitpython_fake_bme280-1.2.dist-info/RECORD,,
|
fake_bme280/advanced.py
ADDED
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2017 ladyada for Adafruit Industries
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: MIT
|
|
4
|
+
|
|
5
|
+
"""
|
|
6
|
+
`fake_bme280.advanced`
|
|
7
|
+
=========================================================================================
|
|
8
|
+
|
|
9
|
+
CircuitPython driver from BME280 Temperature, Humidity and Barometric
|
|
10
|
+
Pressure sensor
|
|
11
|
+
|
|
12
|
+
NOTE: This is a mock. The settings exposed here are simply stored and read back.
|
|
13
|
+
|
|
14
|
+
* Author(s): ladyada, Jose David M.
|
|
15
|
+
|
|
16
|
+
Implementation Notes
|
|
17
|
+
--------------------
|
|
18
|
+
|
|
19
|
+
**Hardware:**
|
|
20
|
+
|
|
21
|
+
* `Adafruit BME280 Temperature, Humidity and Barometric Pressure sensor
|
|
22
|
+
<https://www.adafruit.com/product/2652>`_ (Product ID: 2652)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
**Software and Dependencies:**
|
|
26
|
+
|
|
27
|
+
* Adafruit CircuitPython firmware for the supported boards:
|
|
28
|
+
https://circuitpython.org/downloads
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
from micropython import const
|
|
32
|
+
|
|
33
|
+
from fake_bme280.basic import Adafruit_BME280
|
|
34
|
+
from fake_bme280.protocol import I2C_Impl
|
|
35
|
+
|
|
36
|
+
try:
|
|
37
|
+
import typing # pylint: disable=unused-import
|
|
38
|
+
|
|
39
|
+
from busio import I2C
|
|
40
|
+
except ImportError:
|
|
41
|
+
pass
|
|
42
|
+
|
|
43
|
+
__version__ = "1.2"
|
|
44
|
+
__repo__ = "https://github.com/brentru/CircuitPython_Fake_BME280.git"
|
|
45
|
+
|
|
46
|
+
# I2C ADDRESS/BITS/SETTINGS
|
|
47
|
+
# -----------------------------------------------------------------------
|
|
48
|
+
_BME280_ADDRESS = const(0x77)
|
|
49
|
+
|
|
50
|
+
"""iir_filter values"""
|
|
51
|
+
IIR_FILTER_DISABLE = const(0)
|
|
52
|
+
IIR_FILTER_X2 = const(0x01)
|
|
53
|
+
IIR_FILTER_X4 = const(0x02)
|
|
54
|
+
IIR_FILTER_X8 = const(0x03)
|
|
55
|
+
IIR_FILTER_X16 = const(0x04)
|
|
56
|
+
|
|
57
|
+
_BME280_IIR_FILTERS = (
|
|
58
|
+
IIR_FILTER_DISABLE,
|
|
59
|
+
IIR_FILTER_X2,
|
|
60
|
+
IIR_FILTER_X4,
|
|
61
|
+
IIR_FILTER_X8,
|
|
62
|
+
IIR_FILTER_X16,
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
"""overscan values for temperature, pressure, and humidity"""
|
|
66
|
+
OVERSCAN_DISABLE = const(0x00)
|
|
67
|
+
OVERSCAN_X1 = const(0x01)
|
|
68
|
+
OVERSCAN_X2 = const(0x02)
|
|
69
|
+
OVERSCAN_X4 = const(0x03)
|
|
70
|
+
OVERSCAN_X8 = const(0x04)
|
|
71
|
+
OVERSCAN_X16 = const(0x05)
|
|
72
|
+
|
|
73
|
+
_BME280_OVERSCANS = {
|
|
74
|
+
OVERSCAN_DISABLE: 0,
|
|
75
|
+
OVERSCAN_X1: 1,
|
|
76
|
+
OVERSCAN_X2: 2,
|
|
77
|
+
OVERSCAN_X4: 4,
|
|
78
|
+
OVERSCAN_X8: 8,
|
|
79
|
+
OVERSCAN_X16: 16,
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
"""mode values"""
|
|
83
|
+
MODE_SLEEP = const(0x00)
|
|
84
|
+
MODE_FORCE = const(0x01)
|
|
85
|
+
MODE_NORMAL = const(0x03)
|
|
86
|
+
|
|
87
|
+
_BME280_MODES = (MODE_SLEEP, MODE_FORCE, MODE_NORMAL)
|
|
88
|
+
"""
|
|
89
|
+
standby timeconstant values
|
|
90
|
+
TC_X[_Y] where X=milliseconds and Y=tenths of a millisecond
|
|
91
|
+
"""
|
|
92
|
+
STANDBY_TC_0_5 = const(0x00) # 0.5ms
|
|
93
|
+
STANDBY_TC_10 = const(0x06) # 10ms
|
|
94
|
+
STANDBY_TC_20 = const(0x07) # 20ms
|
|
95
|
+
STANDBY_TC_62_5 = const(0x01) # 62.5ms
|
|
96
|
+
STANDBY_TC_125 = const(0x02) # 125ms
|
|
97
|
+
STANDBY_TC_250 = const(0x03) # 250ms
|
|
98
|
+
STANDBY_TC_500 = const(0x04) # 500ms
|
|
99
|
+
STANDBY_TC_1000 = const(0x05) # 1000ms
|
|
100
|
+
|
|
101
|
+
_BME280_STANDBY_TCS = (
|
|
102
|
+
STANDBY_TC_0_5,
|
|
103
|
+
STANDBY_TC_10,
|
|
104
|
+
STANDBY_TC_20,
|
|
105
|
+
STANDBY_TC_62_5,
|
|
106
|
+
STANDBY_TC_125,
|
|
107
|
+
STANDBY_TC_250,
|
|
108
|
+
STANDBY_TC_500,
|
|
109
|
+
STANDBY_TC_1000,
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
class Adafruit_BME280_Advanced(Adafruit_BME280):
|
|
114
|
+
"""Driver from BME280 Temperature, Humidity and Barometric Pressure sensor
|
|
115
|
+
|
|
116
|
+
.. note::
|
|
117
|
+
This is a mock. The settings exposed here are simply stored and read
|
|
118
|
+
back - nothing is written to a real device.
|
|
119
|
+
|
|
120
|
+
"""
|
|
121
|
+
|
|
122
|
+
@property
|
|
123
|
+
def standby_period(self) -> int:
|
|
124
|
+
"""
|
|
125
|
+
Control the inactive period when in Normal mode
|
|
126
|
+
Allowed standby periods are the constants STANDBY_TC_*
|
|
127
|
+
"""
|
|
128
|
+
return self._t_standby
|
|
129
|
+
|
|
130
|
+
@standby_period.setter
|
|
131
|
+
def standby_period(self, value: int) -> None:
|
|
132
|
+
if not value in _BME280_STANDBY_TCS:
|
|
133
|
+
raise ValueError(f"Standby Period '{value}' not supported")
|
|
134
|
+
self._t_standby = value
|
|
135
|
+
|
|
136
|
+
@property
|
|
137
|
+
def overscan_humidity(self) -> int:
|
|
138
|
+
"""
|
|
139
|
+
Humidity Oversampling
|
|
140
|
+
Allowed values are the constants OVERSCAN_*
|
|
141
|
+
"""
|
|
142
|
+
return self._overscan_humidity
|
|
143
|
+
|
|
144
|
+
@overscan_humidity.setter
|
|
145
|
+
def overscan_humidity(self, value: int) -> None:
|
|
146
|
+
if not value in _BME280_OVERSCANS:
|
|
147
|
+
raise ValueError(f"Overscan value '{value}' not supported")
|
|
148
|
+
self._overscan_humidity = value
|
|
149
|
+
|
|
150
|
+
@property
|
|
151
|
+
def overscan_temperature(self) -> int:
|
|
152
|
+
"""
|
|
153
|
+
Temperature Oversampling
|
|
154
|
+
Allowed values are the constants OVERSCAN_*
|
|
155
|
+
"""
|
|
156
|
+
return self._overscan_temperature
|
|
157
|
+
|
|
158
|
+
@overscan_temperature.setter
|
|
159
|
+
def overscan_temperature(self, value: int) -> None:
|
|
160
|
+
if not value in _BME280_OVERSCANS:
|
|
161
|
+
raise ValueError(f"Overscan value '{value}' not supported")
|
|
162
|
+
self._overscan_temperature = value
|
|
163
|
+
|
|
164
|
+
@property
|
|
165
|
+
def overscan_pressure(self) -> int:
|
|
166
|
+
"""
|
|
167
|
+
Pressure Oversampling
|
|
168
|
+
Allowed values are the constants OVERSCAN_*
|
|
169
|
+
"""
|
|
170
|
+
return self._overscan_pressure
|
|
171
|
+
|
|
172
|
+
@overscan_pressure.setter
|
|
173
|
+
def overscan_pressure(self, value: int) -> None:
|
|
174
|
+
if not value in _BME280_OVERSCANS:
|
|
175
|
+
raise ValueError(f"Overscan value '{value}' not supported")
|
|
176
|
+
self._overscan_pressure = value
|
|
177
|
+
|
|
178
|
+
@property
|
|
179
|
+
def iir_filter(self) -> int:
|
|
180
|
+
"""
|
|
181
|
+
Controls the time constant of the IIR filter
|
|
182
|
+
Allowed values are the constants IIR_FILTER_*
|
|
183
|
+
"""
|
|
184
|
+
return self._iir_filter
|
|
185
|
+
|
|
186
|
+
@iir_filter.setter
|
|
187
|
+
def iir_filter(self, value: int) -> None:
|
|
188
|
+
if not value in _BME280_IIR_FILTERS:
|
|
189
|
+
raise ValueError(f"IIR Filter '{value}' not supported")
|
|
190
|
+
self._iir_filter = value
|
|
191
|
+
|
|
192
|
+
@property
|
|
193
|
+
def measurement_time_typical(self) -> float:
|
|
194
|
+
"""Typical time in milliseconds required to complete a measurement in normal mode"""
|
|
195
|
+
meas_time_ms = 1.0
|
|
196
|
+
if self.overscan_temperature != OVERSCAN_DISABLE:
|
|
197
|
+
meas_time_ms += 2 * _BME280_OVERSCANS.get(self.overscan_temperature)
|
|
198
|
+
if self.overscan_pressure != OVERSCAN_DISABLE:
|
|
199
|
+
meas_time_ms += 2 * _BME280_OVERSCANS.get(self.overscan_pressure) + 0.5
|
|
200
|
+
if self.overscan_humidity != OVERSCAN_DISABLE:
|
|
201
|
+
meas_time_ms += 2 * _BME280_OVERSCANS.get(self.overscan_humidity) + 0.5
|
|
202
|
+
return meas_time_ms
|
|
203
|
+
|
|
204
|
+
@property
|
|
205
|
+
def measurement_time_max(self) -> float:
|
|
206
|
+
"""Maximum time in milliseconds required to complete a measurement in normal mode"""
|
|
207
|
+
meas_time_ms = 1.25
|
|
208
|
+
if self.overscan_temperature != OVERSCAN_DISABLE:
|
|
209
|
+
meas_time_ms += 2.3 * _BME280_OVERSCANS.get(self.overscan_temperature)
|
|
210
|
+
if self.overscan_pressure != OVERSCAN_DISABLE:
|
|
211
|
+
meas_time_ms += 2.3 * _BME280_OVERSCANS.get(self.overscan_pressure) + 0.575
|
|
212
|
+
if self.overscan_humidity != OVERSCAN_DISABLE:
|
|
213
|
+
meas_time_ms += 2.3 * _BME280_OVERSCANS.get(self.overscan_humidity) + 0.575
|
|
214
|
+
return meas_time_ms
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
class Adafruit_BME280_I2C(Adafruit_BME280_Advanced):
|
|
218
|
+
"""Driver for BME280 connected over I2C
|
|
219
|
+
|
|
220
|
+
:param ~busio.I2C i2c: The I2C bus the BME280 is connected to.
|
|
221
|
+
:param int address: I2C device address. Defaults to :const:`0x77`.
|
|
222
|
+
but another address can be passed in as an argument
|
|
223
|
+
|
|
224
|
+
.. note::
|
|
225
|
+
The operational range of the BMP280 is 300-1100 hPa.
|
|
226
|
+
Pressure measurements outside this range may not be as accurate.
|
|
227
|
+
|
|
228
|
+
**Quickstart: Importing and using the BME280**
|
|
229
|
+
|
|
230
|
+
Here is an example of using the :class:`Adafruit_BME280_I2C`.
|
|
231
|
+
First you will need to import the libraries to use the sensor
|
|
232
|
+
|
|
233
|
+
.. code-block:: python
|
|
234
|
+
|
|
235
|
+
import board
|
|
236
|
+
import fake_bme280.advanced as adafruit_bme280
|
|
237
|
+
|
|
238
|
+
Once this is done you can define your `board.I2C` object and define your sensor object
|
|
239
|
+
|
|
240
|
+
.. code-block:: python
|
|
241
|
+
|
|
242
|
+
i2c = board.I2C() # uses board.SCL and board.SDA
|
|
243
|
+
bme280 = adafruit_bme280.Adafruit_BME280_I2C(i2c)
|
|
244
|
+
|
|
245
|
+
You need to setup the pressure at sea level
|
|
246
|
+
|
|
247
|
+
.. code-block:: python
|
|
248
|
+
|
|
249
|
+
bme280.sea_level_pressure = 1013.25
|
|
250
|
+
|
|
251
|
+
Now you have access to the :attr:`temperature`, :attr:`relative_humidity`
|
|
252
|
+
:attr:`pressure` and :attr:`altitude` attributes
|
|
253
|
+
|
|
254
|
+
.. code-block:: python
|
|
255
|
+
|
|
256
|
+
temperature = bme280.temperature
|
|
257
|
+
relative_humidity = bme280.relative_humidity
|
|
258
|
+
pressure = bme280.pressure
|
|
259
|
+
altitude = bme280.altitude
|
|
260
|
+
|
|
261
|
+
"""
|
|
262
|
+
|
|
263
|
+
def __init__(
|
|
264
|
+
self,
|
|
265
|
+
i2c: I2C,
|
|
266
|
+
address: int = _BME280_ADDRESS,
|
|
267
|
+
use_openweather: bool = True,
|
|
268
|
+
) -> None:
|
|
269
|
+
super().__init__(I2C_Impl(i2c, address), use_openweather=use_openweather)
|
fake_bme280/basic.py
CHANGED
|
@@ -25,15 +25,27 @@ Implementation Notes
|
|
|
25
25
|
* Adafruit CircuitPython firmware for the supported boards:
|
|
26
26
|
https://circuitpython.org/downloads
|
|
27
27
|
"""
|
|
28
|
+
|
|
28
29
|
import math
|
|
30
|
+
import os
|
|
31
|
+
import random
|
|
29
32
|
import socket as pool
|
|
30
33
|
import ssl
|
|
31
34
|
import typing # pylint: disable=unused-import
|
|
32
|
-
import toml
|
|
33
35
|
from micropython import const
|
|
34
36
|
import adafruit_requests
|
|
35
37
|
from fake_bme280.protocol import I2C_Impl, SPI_Impl
|
|
36
38
|
|
|
39
|
+
try:
|
|
40
|
+
import toml
|
|
41
|
+
except ImportError:
|
|
42
|
+
toml = None
|
|
43
|
+
|
|
44
|
+
try:
|
|
45
|
+
import dotenv
|
|
46
|
+
except ImportError:
|
|
47
|
+
dotenv = None
|
|
48
|
+
|
|
37
49
|
try:
|
|
38
50
|
from busio import I2C, SPI
|
|
39
51
|
from digitalio import DigitalInOut
|
|
@@ -75,21 +87,62 @@ _BME280_REGISTER_CONFIG = const(0xF5)
|
|
|
75
87
|
_BME280_REGISTER_TEMPDATA = const(0xFA)
|
|
76
88
|
_BME280_REGISTER_HUMIDDATA = const(0xFD)
|
|
77
89
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
# GET weather data for a specific location
|
|
83
|
-
DATA_SOURCE = (
|
|
84
|
-
"http://api.openweathermap.org/data/2.5/weather?q="
|
|
85
|
-
+ toml_config["openweather_location"]
|
|
86
|
-
+ "&units="
|
|
87
|
-
+ toml_config["openweather_units"]
|
|
88
|
-
+ "&mode=json"
|
|
89
|
-
+ "&appid="
|
|
90
|
-
+ toml_config["openweather_token"]
|
|
90
|
+
_OPENWEATHER_KEYS = (
|
|
91
|
+
"openweather_location",
|
|
92
|
+
"openweather_units",
|
|
93
|
+
"openweather_token",
|
|
91
94
|
)
|
|
92
95
|
|
|
96
|
+
_SETTINGS_TOML_PATH = "settings.toml"
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def _load_openweather_settings() -> dict:
|
|
100
|
+
"""Return OpenWeatherMap settings, trying settings.toml, then .env
|
|
101
|
+
(python-dotenv), then os.getenv, per key in that order. Raises
|
|
102
|
+
``RuntimeError`` if settings.toml is malformed or any key is missing."""
|
|
103
|
+
toml_values = {}
|
|
104
|
+
if toml is not None:
|
|
105
|
+
try:
|
|
106
|
+
toml_values = toml.load(_SETTINGS_TOML_PATH)
|
|
107
|
+
except FileNotFoundError:
|
|
108
|
+
pass
|
|
109
|
+
except toml.TomlDecodeError as err:
|
|
110
|
+
raise RuntimeError(
|
|
111
|
+
"Could not parse %s: %s" % (_SETTINGS_TOML_PATH, err)
|
|
112
|
+
) from err
|
|
113
|
+
|
|
114
|
+
dotenv_values = dotenv.dotenv_values() if dotenv is not None else {}
|
|
115
|
+
|
|
116
|
+
settings = {}
|
|
117
|
+
for key in _OPENWEATHER_KEYS:
|
|
118
|
+
value = toml_values.get(key) or dotenv_values.get(key) or os.getenv(key)
|
|
119
|
+
if value:
|
|
120
|
+
settings[key] = value
|
|
121
|
+
|
|
122
|
+
missing = [k for k in _OPENWEATHER_KEYS if k not in settings]
|
|
123
|
+
if missing:
|
|
124
|
+
raise RuntimeError(
|
|
125
|
+
"fake_bme280 is missing required OpenWeatherMap setting(s): "
|
|
126
|
+
+ ", ".join(missing)
|
|
127
|
+
+ ". Provide them via settings.toml, a .env file (python-dotenv), "
|
|
128
|
+
"or environment variables. Or construct the sensor with "
|
|
129
|
+
"use_openweather=False for random fake readings (no network)."
|
|
130
|
+
)
|
|
131
|
+
return settings
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def _build_openweather_url() -> str:
|
|
135
|
+
"""Build the OpenWeatherMap API URL from the loaded settings."""
|
|
136
|
+
config = _load_openweather_settings()
|
|
137
|
+
return (
|
|
138
|
+
"http://api.openweathermap.org/data/2.5/weather?q="
|
|
139
|
+
+ config["openweather_location"]
|
|
140
|
+
+ "&units="
|
|
141
|
+
+ config["openweather_units"]
|
|
142
|
+
+ "&mode=json&appid="
|
|
143
|
+
+ config["openweather_token"]
|
|
144
|
+
)
|
|
145
|
+
|
|
93
146
|
|
|
94
147
|
class Adafruit_BME280:
|
|
95
148
|
"""Driver from BME280 Temperature, Humidity and Barometric Pressure sensor
|
|
@@ -101,11 +154,21 @@ class Adafruit_BME280:
|
|
|
101
154
|
"""
|
|
102
155
|
|
|
103
156
|
# pylint: disable=too-many-instance-attributes
|
|
104
|
-
def __init__(
|
|
105
|
-
|
|
106
|
-
|
|
157
|
+
def __init__(
|
|
158
|
+
self,
|
|
159
|
+
bus_implementation: typing.Union[I2C_Impl, SPI_Impl],
|
|
160
|
+
use_openweather: bool = True,
|
|
161
|
+
) -> None:
|
|
162
|
+
"""Mock a BME280 sensor object that was found on an I2C bus.
|
|
163
|
+
|
|
164
|
+
:param bus_implementation: I2C or SPI implementation wrapper.
|
|
165
|
+
:param bool use_openweather: When ``True`` (default), read settings
|
|
166
|
+
from the environment (``settings.toml`` on CircuitPython,
|
|
167
|
+
environment variables on CPython) and fetch live data from the
|
|
168
|
+
OpenWeatherMap API. When ``False``, return random plausible
|
|
169
|
+
readings with no network access and no configuration required.
|
|
170
|
+
"""
|
|
107
171
|
self._bus_implementation = bus_implementation
|
|
108
|
-
# Set some reasonable defaults.
|
|
109
172
|
self._iir_filter = IIR_FILTER_DISABLE
|
|
110
173
|
self.overscan_humidity = OVERSCAN_X1
|
|
111
174
|
self.overscan_temperature = OVERSCAN_X1
|
|
@@ -115,23 +178,42 @@ class Adafruit_BME280:
|
|
|
115
178
|
self.sea_level_pressure = 1013.25
|
|
116
179
|
"""Pressure in hectoPascals at sea level. Used to calibrate `altitude`."""
|
|
117
180
|
self._t_fine = None
|
|
118
|
-
|
|
119
|
-
self.
|
|
120
|
-
self.
|
|
121
|
-
|
|
122
|
-
|
|
181
|
+
self._use_openweather = use_openweather
|
|
182
|
+
self._current_forecast = None
|
|
183
|
+
self._data_source = None
|
|
184
|
+
self.requests = None
|
|
185
|
+
if use_openweather:
|
|
186
|
+
self._data_source = _build_openweather_url()
|
|
187
|
+
self.requests = adafruit_requests.Session(
|
|
188
|
+
pool, ssl.create_default_context()
|
|
189
|
+
)
|
|
190
|
+
self.get_forecast()
|
|
191
|
+
else:
|
|
192
|
+
self._current_forecast = self._random_forecast()
|
|
193
|
+
|
|
194
|
+
@staticmethod
|
|
195
|
+
def _random_forecast() -> dict:
|
|
196
|
+
"""Generate a plausible BME280-shaped reading."""
|
|
197
|
+
return {
|
|
198
|
+
"main": {
|
|
199
|
+
"temp": round(random.uniform(18.0, 28.0), 2),
|
|
200
|
+
"pressure": round(random.uniform(1000.0, 1025.0), 2),
|
|
201
|
+
"humidity": round(random.uniform(30.0, 70.0), 2),
|
|
202
|
+
}
|
|
203
|
+
}
|
|
123
204
|
|
|
124
205
|
def get_forecast(self):
|
|
125
|
-
"""Fetch weather from OpenWeatherMap
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
206
|
+
"""Fetch weather from OpenWeatherMap (or generate fake data)."""
|
|
207
|
+
if not self._use_openweather:
|
|
208
|
+
self._current_forecast = self._random_forecast()
|
|
209
|
+
return
|
|
210
|
+
response = self.requests.get(self._data_source)
|
|
211
|
+
self._current_forecast = response.json()
|
|
130
212
|
|
|
131
213
|
def _read_temperature(self) -> None:
|
|
132
214
|
# Get the OpenWeather temperature and store it in _t_fine
|
|
133
215
|
self.get_forecast()
|
|
134
|
-
self._t_fine = self.
|
|
216
|
+
self._t_fine = self._current_forecast["main"]["temp"]
|
|
135
217
|
|
|
136
218
|
@property
|
|
137
219
|
def mode(self) -> int:
|
|
@@ -177,7 +259,7 @@ class Adafruit_BME280:
|
|
|
177
259
|
The compensated pressure in hectoPascals.
|
|
178
260
|
"""
|
|
179
261
|
self._read_temperature()
|
|
180
|
-
return self.
|
|
262
|
+
return self._current_forecast["main"]["pressure"]
|
|
181
263
|
|
|
182
264
|
@property
|
|
183
265
|
def relative_humidity(self) -> float:
|
|
@@ -192,7 +274,7 @@ class Adafruit_BME280:
|
|
|
192
274
|
The relative humidity in RH %
|
|
193
275
|
"""
|
|
194
276
|
self._read_temperature()
|
|
195
|
-
humidity = self.
|
|
277
|
+
humidity = self._current_forecast["main"]["humidity"]
|
|
196
278
|
if humidity > 100:
|
|
197
279
|
return 100
|
|
198
280
|
if humidity < 0:
|
|
@@ -253,8 +335,13 @@ class Adafruit_BME280_I2C(Adafruit_BME280):
|
|
|
253
335
|
|
|
254
336
|
"""
|
|
255
337
|
|
|
256
|
-
def __init__(
|
|
257
|
-
|
|
338
|
+
def __init__(
|
|
339
|
+
self,
|
|
340
|
+
i2c: I2C,
|
|
341
|
+
address: int = 0x77, # BME280_ADDRESS
|
|
342
|
+
use_openweather: bool = True,
|
|
343
|
+
) -> None:
|
|
344
|
+
super().__init__(I2C_Impl(i2c, address), use_openweather=use_openweather)
|
|
258
345
|
|
|
259
346
|
|
|
260
347
|
class Adafruit_BME280_SPI(Adafruit_BME280):
|
|
@@ -305,5 +392,11 @@ class Adafruit_BME280_SPI(Adafruit_BME280):
|
|
|
305
392
|
|
|
306
393
|
"""
|
|
307
394
|
|
|
308
|
-
def __init__(
|
|
309
|
-
|
|
395
|
+
def __init__(
|
|
396
|
+
self,
|
|
397
|
+
spi: SPI,
|
|
398
|
+
cs: DigitalInOut,
|
|
399
|
+
baudrate: int = 100000,
|
|
400
|
+
use_openweather: bool = True,
|
|
401
|
+
) -> None:
|
|
402
|
+
super().__init__(SPI_Impl(spi, cs, baudrate), use_openweather=use_openweather)
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
fake_bme280/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
fake_bme280/basic.py,sha256=fmvOe6RBgJjfO4rG34Wdm0V9W3LKAymMbsLcwU1Z2JE,9578
|
|
3
|
-
fake_bme280/protocol.py,sha256=IeQ6cPpu9r7fvKwDkLHg2wLZ7QkOyCtyRjKGtIpW3ho,1017
|
|
4
|
-
circuitpython_fake_bme280-1.0.4.dist-info/LICENSE,sha256=tXgkGXjihZP5R0fW0-IyViyV_rB8TXrzKdiLP4crJn0,1103
|
|
5
|
-
circuitpython_fake_bme280-1.0.4.dist-info/METADATA,sha256=Gss3h67gXetF0KN0bmP8sAzndjp0NsDOUZTYWmbPua4,4610
|
|
6
|
-
circuitpython_fake_bme280-1.0.4.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
|
7
|
-
circuitpython_fake_bme280-1.0.4.dist-info/top_level.txt,sha256=zYm6UwRd0tbyREvYLz0zQcP9NY4GvkMWQ19rZYbwO0Q,12
|
|
8
|
-
circuitpython_fake_bme280-1.0.4.dist-info/RECORD,,
|
|
File without changes
|
{circuitpython_fake_bme280-1.0.4.dist-info → circuitpython_fake_bme280-1.2.dist-info}/top_level.txt
RENAMED
|
File without changes
|