circuitpython-fake-bme280 1.0.0__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.
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2024 Brent Rubell for Adafruit Industries
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,116 @@
1
+ Metadata-Version: 2.1
2
+ Name: circuitpython-fake-bme280
3
+ Version: 1.0.0
4
+ Summary: BME280 Driver for CircuitPython used for testing functionality with no hardware attached
5
+ Author-email: Adafruit Industries <circuitpython@adafruit.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/brentru/CircuitPython_Fake_BME280
8
+ Keywords: adafruit,blinka,circuitpython,micropython,fake_bme280,bme280,,test,,fake,,mock,,stub
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Topic :: Software Development :: Libraries
11
+ Classifier: Topic :: Software Development :: Embedded Systems
12
+ Classifier: Topic :: System :: Hardware
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Description-Content-Type: text/x-rst
16
+ License-File: LICENSE
17
+ Requires-Dist: Adafruit-Blinka
18
+ Requires-Dist: adafruit-circuitpython-busdevice
19
+ Requires-Dist: adafruit-circuitpython-register
20
+ Provides-Extra: optional
21
+
22
+ Introduction
23
+ ============
24
+
25
+
26
+
27
+
28
+ .. image:: https://img.shields.io/discord/327254708534116352.svg
29
+ :target: https://adafru.it/discord
30
+ :alt: Discord
31
+
32
+
33
+ .. image:: https://github.com/brentru/CircuitPython_Fake_BME280/workflows/Build%20CI/badge.svg
34
+ :target: https://github.com/brentru/CircuitPython_Fake_BME280/actions
35
+ :alt: Build Status
36
+
37
+
38
+ .. image:: https://img.shields.io/badge/code%20style-black-000000.svg
39
+ :target: https://github.com/psf/black
40
+ :alt: Code Style: Black
41
+
42
+ **This code is for testing purposes only!** If you are looking for a Bosch BME280 driver, please use the `Adafruit_CircuitPython_BME280 <https://github.com/adafruit/Adafruit_CircuitPython_BME280>`_.
43
+
44
+ This driver mocks the functionality of the `Adafruit_CircuitPython_BME280 <https://github.com/adafruit/Adafruit_CircuitPython_BME280>`_, allowing you to test your code without
45
+ attaching physical hardware.
46
+
47
+ Instead of using random data, weather data is instead pulled from `the OpenWeatherMaps API <https://openweathermap.org/>`_
48
+ and returned as if it were coming from the BME280 sensor properties. A free OpenWeatherMap API key is **required** to use this library (see the Usage section below for more information).
49
+
50
+ Dependencies
51
+ =============
52
+ This driver depends on:
53
+
54
+ * `Adafruit CircuitPython <https://github.com/adafruit/circuitpython>`_
55
+ * `Adafruit_CircuitPython_Requests <https://github.com/adafruit/Adafruit_CircuitPython_Requests>`_
56
+
57
+ Please ensure all dependencies are available on the CircuitPython filesystem.
58
+ This is easily achieved by downloading
59
+ `the Adafruit library and driver bundle <https://circuitpython.org/libraries>`_
60
+ or individual libraries can be installed using
61
+ `circup <https://github.com/adafruit/circup>`_.
62
+
63
+ Installing from PyPI
64
+ =====================
65
+
66
+ On supported GNU/Linux systems like the Raspberry Pi, you can install the driver locally `from
67
+ PyPI <https://pypi.org/project/circuitpython-fake-bme280/>`_.
68
+ To install for current user:
69
+
70
+ .. code-block:: shell
71
+
72
+ pip3 install circuitpython-fake-bme280
73
+
74
+ To install system-wide (this may be required in some cases):
75
+
76
+ .. code-block:: shell
77
+
78
+ sudo pip3 install circuitpython-fake-bme280
79
+
80
+ To install in a virtual environment in your current project:
81
+
82
+ .. code-block:: shell
83
+
84
+ mkdir project-name && cd project-name
85
+ python3 -m venv .venv
86
+ source .env/bin/activate
87
+ pip3 install circuitpython-fake-bme280
88
+
89
+ Usage Example
90
+ =============
91
+
92
+ To obtain an OpenWeatherMaps API key, sign up for a free account at `OpenWeatherMaps <https://openweathermap.org/>`_ and generate an API key. Then, in the root of this
93
+ project, add a file called "settings.toml" with the following information:
94
+
95
+ openweather_token = "my_api_key"
96
+ openweather_location = "New York, US"
97
+ openweather_units = "metric"
98
+
99
+
100
+ Where openweather_token is your OpenWeatherMaps API key, openweather_location is the location you want to pull weather data from, and openweather_units is the units you want the temperature to be returned in (either "metric" or "imperial").
101
+
102
+ Then, run the code within "examples/fake_bme280.py" to use the "fake" BME280 sensor.
103
+
104
+ Documentation
105
+ =============
106
+ API documentation for this library can be found on `Read the Docs <https://circuitpython-fake-bme280.readthedocs.io/>`_.
107
+
108
+ For information on building library documentation, please check out
109
+ `this guide <https://learn.adafruit.com/creating-and-sharing-a-circuitpython-library/sharing-our-docs-on-readthedocs#sphinx-5-1>`_.
110
+
111
+ Contributing
112
+ ============
113
+
114
+ Contributions are welcome! Please read our `Code of Conduct
115
+ <https://github.com/brentru/CircuitPython_Fake_BME280/blob/HEAD/CODE_OF_CONDUCT.md>`_
116
+ before contributing to help this project stay welcoming.
@@ -0,0 +1,8 @@
1
+ fake_bme280/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ fake_bme280/basic.py,sha256=50n_i9pqkRGjQDFuYuFq6ORj6tbgVu045EdCHm13QeU,9778
3
+ fake_bme280/protocol.py,sha256=56B02wVkQOt6W_sEwfSPuSKEanBTryJKpg24H8wKpgA,983
4
+ circuitpython_fake_bme280-1.0.0.dist-info/LICENSE,sha256=tXgkGXjihZP5R0fW0-IyViyV_rB8TXrzKdiLP4crJn0,1103
5
+ circuitpython_fake_bme280-1.0.0.dist-info/METADATA,sha256=l1UyzzNf_jSSOU_WztzRbaqbsEkQQbzM0e4sQSp7x_g,4590
6
+ circuitpython_fake_bme280-1.0.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
7
+ circuitpython_fake_bme280-1.0.0.dist-info/top_level.txt,sha256=zYm6UwRd0tbyREvYLz0zQcP9NY4GvkMWQ19rZYbwO0Q,12
8
+ circuitpython_fake_bme280-1.0.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: bdist_wheel (0.43.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ fake_bme280
File without changes
fake_bme280/basic.py ADDED
@@ -0,0 +1,312 @@
1
+ # SPDX-FileCopyrightText: 2017 ladyada for Adafruit Industries
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+
5
+ """
6
+ `fake_bme280.basic`
7
+ =========================================================================================
8
+
9
+ CircuitPython driver from BME280 Temperature, Humidity and Barometric
10
+ Pressure sensor
11
+
12
+ * Author(s): ladyada, Jose David M.
13
+
14
+ Implementation Notes
15
+ --------------------
16
+
17
+ **Hardware:**
18
+
19
+ * `Adafruit BME280 Temperature, Humidity and Barometric Pressure sensor
20
+ <https://www.adafruit.com/product/2652>`_ (Product ID: 2652)
21
+
22
+
23
+ **Software and Dependencies:**
24
+
25
+ * Adafruit CircuitPython firmware for the supported boards:
26
+ https://circuitpython.org/downloads
27
+ """
28
+ import math
29
+ import os
30
+ import socket as pool
31
+ import ssl
32
+ import typing # pylint: disable=unused-import
33
+ from micropython import const
34
+ import adafruit_requests
35
+ from fake_bme280.protocol import I2C_Impl, SPI_Impl
36
+
37
+ try:
38
+ from busio import I2C, SPI
39
+ from digitalio import DigitalInOut
40
+ except ImportError:
41
+ pass
42
+
43
+ __version__ = "2.6.4"
44
+ __repo__ = "https://github.com/brentru/CircuitPython_Fake_BME280.git"
45
+
46
+ # I2C ADDRESS/BITS/SETTINGS
47
+ # -----------------------------------------------------------------------
48
+
49
+ """General Information"""
50
+ _BME280_ADDRESS = const(0x77)
51
+ _BME280_CHIPID = const(0x60)
52
+ _BME280_REGISTER_CHIPID = const(0xD0)
53
+ """overscan values for temperature, pressure, and humidity"""
54
+ OVERSCAN_X1 = const(0x01)
55
+ OVERSCAN_X16 = const(0x05)
56
+ """mode values"""
57
+ _BME280_MODES = (0x00, 0x01, 0x03)
58
+ """iir_filter values"""
59
+ IIR_FILTER_DISABLE = const(0)
60
+ """
61
+ standby timeconstant values
62
+ TC_X[_Y] where X=milliseconds and Y=tenths of a millisecond
63
+ """
64
+ STANDBY_TC_125 = const(0x02) # 125ms
65
+ """mode values"""
66
+ MODE_SLEEP = const(0x00)
67
+ MODE_FORCE = const(0x01)
68
+ MODE_NORMAL = const(0x03)
69
+ """Other Registers"""
70
+ _BME280_REGISTER_SOFTRESET = const(0xE0)
71
+ _BME280_REGISTER_CTRL_HUM = const(0xF2)
72
+ _BME280_REGISTER_STATUS = const(0xF3)
73
+ _BME280_REGISTER_CTRL_MEAS = const(0xF4)
74
+ _BME280_REGISTER_CONFIG = const(0xF5)
75
+ _BME280_REGISTER_TEMPDATA = const(0xFA)
76
+ _BME280_REGISTER_HUMIDDATA = const(0xFD)
77
+
78
+ # OpenWeatherMap API
79
+ # GET weather data for a specific location
80
+ # TODO: this could be cleaned up a bit..
81
+ DATA_SOURCE = (
82
+ "http://api.openweathermap.org/data/2.5/weather?q="
83
+ + os.getenv("openweather_location")
84
+ + "&units="
85
+ + os.getenv("openweather_units")
86
+ + "&mode=json"
87
+ + "&appid="
88
+ + os.getenv("openweather_token")
89
+ )
90
+
91
+
92
+ class Adafruit_BME280:
93
+ """Driver from BME280 Temperature, Humidity and Barometric Pressure sensor
94
+
95
+ .. note::
96
+ The operational range of the BME280 is 300-1100 hPa.
97
+ Pressure measurements outside this range may not be as accurate.
98
+
99
+ """
100
+
101
+ # pylint: disable=too-many-instance-attributes
102
+ def __init__(self, bus_implementation: typing.Union[I2C_Impl, SPI_Impl]) -> None:
103
+ """Mock a BME280 sensor object that was found on an I2C bus."""
104
+ # Check device ID.
105
+ self._bus_implementation = bus_implementation
106
+ # Set some reasonable defaults.
107
+ self._iir_filter = IIR_FILTER_DISABLE
108
+ self.overscan_humidity = OVERSCAN_X1
109
+ self.overscan_temperature = OVERSCAN_X1
110
+ self.overscan_pressure = OVERSCAN_X16
111
+ self._t_standby = STANDBY_TC_125
112
+ self._mode = MODE_SLEEP
113
+ self.sea_level_pressure = 1013.25
114
+ """Pressure in hectoPascals at sea level. Used to calibrate `altitude`."""
115
+ self._t_fine = None
116
+ # Configure OpenWeather for mock data
117
+ self.openweather_token = os.getenv("OPENWEATHER_TOKEN", "default_token")
118
+ self.openweather_location = os.getenv(
119
+ "OPENWEATHER_LOCATION", "default_location"
120
+ )
121
+ # Configure a CPython adafruit_requests session
122
+ self.requests = adafruit_requests.Session(pool, ssl.create_default_context())
123
+ self._current_forcast = None
124
+ # Test call get_forecast
125
+ self.get_forecast()
126
+
127
+ def get_forecast(self):
128
+ """Fetch weather from OpenWeatherMap API"""
129
+ # print("Fetching json from", DATA_SOURCE)
130
+ response = self.requests.get(DATA_SOURCE)
131
+ self._current_forcast = response.json()
132
+ # print(self._current_forcast)
133
+
134
+ def _read_temperature(self) -> None:
135
+ # Get the OpenWeather temperature and store it in _t_fine
136
+ self.get_forecast()
137
+ self._t_fine = self._current_forcast["main"]["temp"]
138
+
139
+ @property
140
+ def mode(self) -> int:
141
+ """
142
+ Operation mode
143
+ Allowed values are the constants MODE_*
144
+ """
145
+ return self._mode
146
+
147
+ @mode.setter
148
+ def mode(self, value: int) -> None:
149
+ if not value in _BME280_MODES:
150
+ raise ValueError("Mode '%s' not supported" % (value))
151
+ self._mode = value
152
+
153
+ @property
154
+ def _config(self) -> int:
155
+ """Value to be written to the device's config register"""
156
+ config = 0
157
+ if self.mode == 0x03: # MODE_NORMAL
158
+ config += self._t_standby << 5
159
+ if self._iir_filter:
160
+ config += self._iir_filter << 2
161
+ return config
162
+
163
+ @property
164
+ def _ctrl_meas(self) -> int:
165
+ """Value to be written to the device's ctrl_meas register"""
166
+ ctrl_meas = self.overscan_temperature << 5
167
+ ctrl_meas += self.overscan_pressure << 2
168
+ ctrl_meas += self.mode
169
+ return ctrl_meas
170
+
171
+ @property
172
+ def temperature(self) -> float:
173
+ """The compensated temperature in degrees Celsius."""
174
+ self._read_temperature()
175
+ return self._t_fine
176
+
177
+ @property
178
+ def pressure(self) -> float:
179
+ """
180
+ The compensated pressure in hectoPascals.
181
+ """
182
+ self._read_temperature()
183
+ return self._current_forcast["main"]["pressure"]
184
+
185
+ @property
186
+ def relative_humidity(self) -> float:
187
+ """
188
+ The relative humidity in RH %
189
+ """
190
+ return self.humidity
191
+
192
+ @property
193
+ def humidity(self) -> float:
194
+ """
195
+ The relative humidity in RH %
196
+ """
197
+ self._read_temperature()
198
+ humidity = self._current_forcast["main"]["humidity"]
199
+ if humidity > 100:
200
+ return 100
201
+ if humidity < 0:
202
+ return 0
203
+ return humidity
204
+
205
+ @property
206
+ def altitude(self) -> float:
207
+ """The altitude based on current :attr:`pressure` versus the sea level pressure
208
+ (``sea_level_pressure``) - which you must enter ahead of time)"""
209
+ pressure = self.pressure # in Si units for hPascal
210
+ return 44330 * (1.0 - math.pow(pressure / self.sea_level_pressure, 0.1903))
211
+
212
+
213
+ class Adafruit_BME280_I2C(Adafruit_BME280):
214
+ """Driver for BME280 connected over I2C
215
+
216
+ :param ~busio.I2C i2c: The I2C bus the BME280 is connected to.
217
+ :param int address: I2C device address. Defaults to :const:`0x77`.
218
+ but another address can be passed in as an argument
219
+
220
+ .. note::
221
+ The operational range of the BMP280 is 300-1100 hPa.
222
+ Pressure measurements outside this range may not be as accurate.
223
+
224
+ **Quickstart: Importing and using the BME280**
225
+
226
+ Here is an example of using the :class:`Adafruit_BME280_I2C`.
227
+ First you will need to import the libraries to use the sensor
228
+
229
+ .. code-block:: python
230
+
231
+ import board
232
+ from adafruit_bme280 import basic as adafruit_bme280
233
+
234
+ Once this is done you can define your `board.I2C` object and define your sensor object
235
+
236
+ .. code-block:: python
237
+
238
+ i2c = board.I2C() # uses board.SCL and board.SDA
239
+ bme280 = adafruit_bme280.Adafruit_BME280_I2C(i2c)
240
+
241
+ You need to setup the pressure at sea level
242
+
243
+ .. code-block:: python
244
+
245
+ bme280.sea_level_pressure = 1013.25
246
+
247
+ Now you have access to the :attr:`temperature`, :attr:`relative_humidity`
248
+ :attr:`pressure` and :attr:`altitude` attributes
249
+
250
+ .. code-block:: python
251
+
252
+ temperature = bme280.temperature
253
+ relative_humidity = bme280.relative_humidity
254
+ pressure = bme280.pressure
255
+ altitude = bme280.altitude
256
+
257
+ """
258
+
259
+ def __init__(self, i2c: I2C, address: int = 0x77) -> None: # BME280_ADDRESS
260
+ super().__init__(I2C_Impl(i2c, address))
261
+
262
+
263
+ class Adafruit_BME280_SPI(Adafruit_BME280):
264
+ """Driver for BME280 connected over SPI
265
+
266
+ :param ~busio.SPI spi: SPI device
267
+ :param ~digitalio.DigitalInOut cs: Chip Select
268
+ :param int baudrate: Clock rate, default is 100000. Can be changed with :meth:`baudrate`
269
+
270
+ .. note::
271
+ The operational range of the BMP280 is 300-1100 hPa.
272
+ Pressure measurements outside this range may not be as accurate.
273
+
274
+ **Quickstart: Importing and using the BME280**
275
+
276
+ Here is an example of using the :class:`Adafruit_BME280_SPI` class.
277
+ First you will need to import the libraries to use the sensor
278
+
279
+ .. code-block:: python
280
+
281
+ import board
282
+ from digitalio import DigitalInOut
283
+ from adafruit_bme280 import basic as adafruit_bme280
284
+
285
+ Once this is done you can define your `board.SPI` object and define your sensor object
286
+
287
+ .. code-block:: python
288
+
289
+ cs = digitalio.DigitalInOut(board.D10)
290
+ spi = board.SPI()
291
+ bme280 = adafruit_bme280.Adafruit_BME280_SPI(spi, cs)
292
+
293
+ You need to setup the pressure at sea level
294
+
295
+ .. code-block:: python
296
+
297
+ bme280.sea_level_pressure = 1013.25
298
+
299
+ Now you have access to the :attr:`temperature`, :attr:`relative_humidity`
300
+ :attr:`pressure` and :attr:`altitude` attributes
301
+
302
+ .. code-block:: python
303
+
304
+ temperature = bme280.temperature
305
+ relative_humidity = bme280.relative_humidity
306
+ pressure = bme280.pressure
307
+ altitude = bme280.altitude
308
+
309
+ """
310
+
311
+ def __init__(self, spi: SPI, cs: DigitalInOut, baudrate: int = 100000) -> None:
312
+ super().__init__(SPI_Impl(spi, cs, baudrate))
@@ -0,0 +1,36 @@
1
+ # SPDX-FileCopyrightText: 2022 Randall Bohn (dexter)
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+ "Provides the protocol objects for I2C and SPI"
5
+
6
+ from busio import I2C, SPI
7
+ from digitalio import DigitalInOut
8
+
9
+
10
+ class I2C_Impl:
11
+ "Protocol implementation for the I2C bus."
12
+
13
+ # pylint: disable=too-few-public-methods
14
+ def __init__(self, i2c: I2C, address: int) -> None:
15
+ from adafruit_bus_device import ( # pylint: disable=import-outside-toplevel
16
+ i2c_device,
17
+ )
18
+
19
+ self._i2c = i2c_device.I2CDevice(i2c, address)
20
+
21
+
22
+ class SPI_Impl:
23
+ """Protocol implemenation for the SPI bus."""
24
+
25
+ # pylint: disable=too-few-public-methods
26
+ def __init__(
27
+ self,
28
+ spi: SPI,
29
+ chip_select: DigitalInOut,
30
+ baudrate: int = 100000,
31
+ ) -> None:
32
+ from adafruit_bus_device import ( # pylint: disable=import-outside-toplevel
33
+ spi_device,
34
+ )
35
+
36
+ self._spi = spi_device.SPIDevice(spi, chip_select, baudrate=baudrate)