circuitpython-fake-bme280 1.0.4__tar.gz → 1.1__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.
Files changed (39) hide show
  1. {circuitpython_fake_bme280-1.0.4 → circuitpython_fake_bme280-1.1}/.pre-commit-config.yaml +4 -4
  2. {circuitpython_fake_bme280-1.0.4 → circuitpython_fake_bme280-1.1}/.readthedocs.yaml +4 -1
  3. {circuitpython_fake_bme280-1.0.4 → circuitpython_fake_bme280-1.1}/PKG-INFO +5 -4
  4. {circuitpython_fake_bme280-1.0.4 → circuitpython_fake_bme280-1.1}/circuitpython_fake_bme280.egg-info/PKG-INFO +5 -4
  5. {circuitpython_fake_bme280-1.0.4 → circuitpython_fake_bme280-1.1}/circuitpython_fake_bme280.egg-info/requires.txt +1 -0
  6. {circuitpython_fake_bme280-1.0.4 → circuitpython_fake_bme280-1.1}/fake_bme280/basic.py +128 -35
  7. {circuitpython_fake_bme280-1.0.4 → circuitpython_fake_bme280-1.1}/optional_requirements.txt +3 -0
  8. {circuitpython_fake_bme280-1.0.4 → circuitpython_fake_bme280-1.1}/pyproject.toml +2 -3
  9. {circuitpython_fake_bme280-1.0.4 → circuitpython_fake_bme280-1.1}/.github/PULL_REQUEST_TEMPLATE/adafruit_circuitpython_pr.md +0 -0
  10. {circuitpython_fake_bme280-1.0.4 → circuitpython_fake_bme280-1.1}/.github/workflows/build.yml +0 -0
  11. {circuitpython_fake_bme280-1.0.4 → circuitpython_fake_bme280-1.1}/.github/workflows/failure-help-text.yml +0 -0
  12. {circuitpython_fake_bme280-1.0.4 → circuitpython_fake_bme280-1.1}/.github/workflows/release_gh.yml +0 -0
  13. {circuitpython_fake_bme280-1.0.4 → circuitpython_fake_bme280-1.1}/.github/workflows/release_pypi.yml +0 -0
  14. {circuitpython_fake_bme280-1.0.4 → circuitpython_fake_bme280-1.1}/.gitignore +0 -0
  15. {circuitpython_fake_bme280-1.0.4 → circuitpython_fake_bme280-1.1}/.pylintrc +0 -0
  16. {circuitpython_fake_bme280-1.0.4 → circuitpython_fake_bme280-1.1}/LICENSE +0 -0
  17. {circuitpython_fake_bme280-1.0.4 → circuitpython_fake_bme280-1.1}/LICENSES/CC-BY-4.0.txt +0 -0
  18. {circuitpython_fake_bme280-1.0.4 → circuitpython_fake_bme280-1.1}/LICENSES/MIT.txt +0 -0
  19. {circuitpython_fake_bme280-1.0.4 → circuitpython_fake_bme280-1.1}/LICENSES/Unlicense.txt +0 -0
  20. {circuitpython_fake_bme280-1.0.4 → circuitpython_fake_bme280-1.1}/README.rst +0 -0
  21. {circuitpython_fake_bme280-1.0.4 → circuitpython_fake_bme280-1.1}/README.rst.license +0 -0
  22. {circuitpython_fake_bme280-1.0.4 → circuitpython_fake_bme280-1.1}/circuitpython_fake_bme280.egg-info/SOURCES.txt +0 -0
  23. {circuitpython_fake_bme280-1.0.4 → circuitpython_fake_bme280-1.1}/circuitpython_fake_bme280.egg-info/dependency_links.txt +0 -0
  24. {circuitpython_fake_bme280-1.0.4 → circuitpython_fake_bme280-1.1}/circuitpython_fake_bme280.egg-info/top_level.txt +0 -0
  25. {circuitpython_fake_bme280-1.0.4 → circuitpython_fake_bme280-1.1}/docs/_static/favicon.ico +0 -0
  26. {circuitpython_fake_bme280-1.0.4 → circuitpython_fake_bme280-1.1}/docs/_static/favicon.ico.license +0 -0
  27. {circuitpython_fake_bme280-1.0.4 → circuitpython_fake_bme280-1.1}/docs/api.rst +0 -0
  28. {circuitpython_fake_bme280-1.0.4 → circuitpython_fake_bme280-1.1}/docs/api.rst.license +0 -0
  29. {circuitpython_fake_bme280-1.0.4 → circuitpython_fake_bme280-1.1}/docs/conf.py +0 -0
  30. {circuitpython_fake_bme280-1.0.4 → circuitpython_fake_bme280-1.1}/docs/examples.rst +0 -0
  31. {circuitpython_fake_bme280-1.0.4 → circuitpython_fake_bme280-1.1}/docs/examples.rst.license +0 -0
  32. {circuitpython_fake_bme280-1.0.4 → circuitpython_fake_bme280-1.1}/docs/index.rst +0 -0
  33. {circuitpython_fake_bme280-1.0.4 → circuitpython_fake_bme280-1.1}/docs/index.rst.license +0 -0
  34. {circuitpython_fake_bme280-1.0.4 → circuitpython_fake_bme280-1.1}/docs/requirements.txt +0 -0
  35. {circuitpython_fake_bme280-1.0.4 → circuitpython_fake_bme280-1.1}/examples/fake_bme280_simpletest.py +0 -0
  36. {circuitpython_fake_bme280-1.0.4 → circuitpython_fake_bme280-1.1}/fake_bme280/__init__.py +0 -0
  37. {circuitpython_fake_bme280-1.0.4 → circuitpython_fake_bme280-1.1}/fake_bme280/protocol.py +0 -0
  38. {circuitpython_fake_bme280-1.0.4 → circuitpython_fake_bme280-1.1}/requirements.txt +0 -0
  39. {circuitpython_fake_bme280-1.0.4 → circuitpython_fake_bme280-1.1}/setup.cfg +0 -0
@@ -4,21 +4,21 @@
4
4
 
5
5
  repos:
6
6
  - repo: https://github.com/python/black
7
- rev: 23.3.0
7
+ rev: 26.3.1
8
8
  hooks:
9
9
  - id: black
10
10
  - repo: https://github.com/fsfe/reuse-tool
11
- rev: v1.1.2
11
+ rev: v6.2.0
12
12
  hooks:
13
13
  - id: reuse
14
14
  - repo: https://github.com/pre-commit/pre-commit-hooks
15
- rev: v4.4.0
15
+ rev: v6.0.0
16
16
  hooks:
17
17
  - id: check-yaml
18
18
  - id: end-of-file-fixer
19
19
  - id: trailing-whitespace
20
20
  - repo: https://github.com/pycqa/pylint
21
- rev: v2.17.4
21
+ rev: v4.0.5
22
22
  hooks:
23
23
  - id: pylint
24
24
  name: pylint (library code)
@@ -8,8 +8,11 @@
8
8
  # Required
9
9
  version: 2
10
10
 
11
+ sphinx:
12
+ configuration: docs/conf.py
13
+
11
14
  build:
12
- os: ubuntu-20.04
15
+ os: ubuntu-lts-latest
13
16
  tools:
14
17
  python: "3"
15
18
 
@@ -1,16 +1,15 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: circuitpython-fake-bme280
3
- Version: 1.0.4
3
+ Version: 1.1
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
  ============
@@ -1,16 +1,15 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: circuitpython-fake-bme280
3
- Version: 1.0.4
3
+ Version: 1.1
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
  ============
@@ -4,3 +4,4 @@ adafruit-circuitpython-register
4
4
  toml
5
5
 
6
6
  [optional]
7
+ python-dotenv
@@ -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
- # Load the settings.toml file
79
- toml_config = toml.load("settings.toml")
80
-
81
- # OpenWeatherMap API
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__(self, bus_implementation: typing.Union[I2C_Impl, SPI_Impl]) -> None:
105
- """Mock a BME280 sensor object that was found on an I2C bus."""
106
- # Check device ID.
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
- # Configure a CPython adafruit_requests session
119
- self.requests = adafruit_requests.Session(pool, ssl.create_default_context())
120
- self._current_forcast = None
121
- # Test call get_forecast
122
- self.get_forecast()
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 API"""
126
- # print("Fetching json from", DATA_SOURCE)
127
- response = self.requests.get(DATA_SOURCE)
128
- self._current_forcast = response.json()
129
- # print(self._current_forcast)
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._current_forcast["main"]["temp"]
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._current_forcast["main"]["pressure"]
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._current_forcast["main"]["humidity"]
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__(self, i2c: I2C, address: int = 0x77) -> None: # BME280_ADDRESS
257
- super().__init__(I2C_Impl(i2c, address))
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__(self, spi: SPI, cs: DigitalInOut, baudrate: int = 100000) -> None:
309
- super().__init__(SPI_Impl(spi, cs, baudrate))
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,3 +1,6 @@
1
1
  # SPDX-FileCopyrightText: 2022 Alec Delaney, for Adafruit Industries
2
2
  #
3
3
  # SPDX-License-Identifier: Unlicense
4
+
5
+ # Optional: load OpenWeatherMap settings from a .env file on CPython.
6
+ python-dotenv
@@ -13,7 +13,7 @@ requires = [
13
13
  [project]
14
14
  name = "circuitpython-fake-bme280"
15
15
  description = "BME280 Driver for CircuitPython used for testing functionality with no hardware attached"
16
- version = "1.0.4"
16
+ version = "1.1"
17
17
  readme = "README.rst"
18
18
  authors = [
19
19
  {name = "Adafruit Industries", email = "circuitpython@adafruit.com"}
@@ -31,13 +31,12 @@ keywords = [
31
31
  "mock,",
32
32
  "stub",
33
33
  ]
34
- license = {text = "MIT"}
34
+ license = "MIT"
35
35
  classifiers = [
36
36
  "Intended Audience :: Developers",
37
37
  "Topic :: Software Development :: Libraries",
38
38
  "Topic :: Software Development :: Embedded Systems",
39
39
  "Topic :: System :: Hardware",
40
- "License :: OSI Approved :: MIT License",
41
40
  "Programming Language :: Python :: 3",
42
41
  ]
43
42
  dynamic = ["dependencies", "optional-dependencies"]