├── .github └── workflows │ └── build-deploy-ghpages.yml ├── .readthedocs.yml ├── DESCRIPTION.rst ├── LICENSE ├── README.md ├── docs ├── _static │ └── favicon.ico ├── doxygen │ ├── doxygen-awesome-css │ │ ├── .github │ │ │ └── workflows │ │ │ │ └── publish.yaml │ │ ├── .gitignore │ │ ├── .npmignore │ │ ├── Doxyfile │ │ ├── LICENSE │ │ ├── Makefile │ │ ├── README.md │ │ ├── docs │ │ │ ├── customization.md │ │ │ ├── extensions.md │ │ │ ├── img │ │ │ │ ├── darkmode_toggle.png │ │ │ │ ├── fancy_scrollbars_firefox.png │ │ │ │ ├── fancy_scrollbars_webkit.gif │ │ │ │ ├── fragment_copy_button.png │ │ │ │ ├── interactive_toc_mobile.png │ │ │ │ └── paragraph_link.png │ │ │ └── tricks.md │ │ ├── doxygen-awesome-darkmode-toggle.js │ │ ├── doxygen-awesome-fragment-copy-button.js │ │ ├── doxygen-awesome-interactive-toc.js │ │ ├── doxygen-awesome-paragraph-link.js │ │ ├── doxygen-awesome-sidebar-only-darkmode-toggle.css │ │ ├── doxygen-awesome-sidebar-only.css │ │ ├── doxygen-awesome-tabs.js │ │ ├── doxygen-awesome.css │ │ ├── doxygen-custom │ │ │ ├── custom-alternative.css │ │ │ ├── custom.css │ │ │ ├── header.html │ │ │ └── toggle-alternative-theme.js │ │ ├── img │ │ │ ├── screenshot.png │ │ │ ├── testimage.png │ │ │ ├── theme-variants-base.drawio.svg │ │ │ └── theme-variants-sidebar-only.drawio.svg │ │ ├── include │ │ │ └── MyLibrary │ │ │ │ ├── example.hpp │ │ │ │ └── subclass-example.hpp │ │ ├── logo.drawio.svg │ │ └── package.json │ ├── doxygen-config │ └── doxygen-custom │ │ ├── custom.css │ │ └── header.html ├── images │ ├── bme280-gh-banner-py.png │ └── sfe_flame.png └── requirements.txt ├── examples ├── README.md ├── qwiic_bme280_ex1.py ├── qwiic_bme280_ex4.py └── qwiic_bme280_ex5.py ├── package.json ├── pyproject.toml ├── qwiic_bme280.py └── requirements.txt /.github/workflows/build-deploy-ghpages.yml: -------------------------------------------------------------------------------- 1 | name: Build Documentation and Deploy 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | workflow_dispatch: 8 | 9 | permissions: 10 | contents: read 11 | id-token: write 12 | pages: write 13 | 14 | concurrency: 15 | group: "pages" 16 | cancel-in-progress: true 17 | 18 | jobs: 19 | # Build job 20 | build: 21 | runs-on: ubuntu-latest 22 | steps: 23 | # Checkout the repository 24 | - name: Checkout repository 25 | uses: actions/checkout@v2 26 | with: 27 | fetch-depth: 0 28 | submodules: "true" 29 | 30 | - name: Set Version 31 | run: echo "PROJECT_NUMBER = `git describe --tags`" >> ./docs/doxygen/doxygen-config 32 | 33 | - name: Build Documentation 34 | uses: mattnotmitt/doxygen-action@v1.9.5 35 | with: 36 | doxyfile-path: "./docs/doxygen/doxygen-config" 37 | 38 | # Upload the documentation as an artifact 39 | - name: Upload documentation 40 | uses: actions/upload-pages-artifact@v3.0.1 41 | with: 42 | path: ./docs/html 43 | 44 | # Deploy job 45 | deploy: 46 | # Add a dependency to the build job 47 | needs: build 48 | 49 | # Grant GITHUB_TOKEN the permissions required to make a Pages deployment 50 | permissions: 51 | pages: write # to deploy to Pages 52 | id-token: write # to verify the deployment originates from an appropriate source 53 | 54 | # Deploy to the github-pages environment 55 | environment: 56 | name: github-pages 57 | url: ${{ steps.deployment.outputs.page_url }} 58 | 59 | # Specify runner + deployment step 60 | runs-on: ubuntu-latest 61 | steps: 62 | - name: Deploy to GitHub Pages 63 | id: deployment 64 | uses: actions/deploy-pages@v4 # or specific "vX.X.X" version tag for this action 65 | -------------------------------------------------------------------------------- /.readthedocs.yml: -------------------------------------------------------------------------------- 1 | python: 2 | version: 3 3 | install: 4 | - requirements: docs/requirements.txt 5 | setup_py_install: true 6 | -------------------------------------------------------------------------------- /DESCRIPTION.rst: -------------------------------------------------------------------------------- 1 | Qwiic BME280 Sensor 2 | ========================== 3 | 4 | This package provdes support for the SparkFun qwiic BME280 sensor breakout. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2019 SparkFun Electronics 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Qwiic BME280 Python Package](docs/images/bme280-gh-banner-py.png "qwiic BME280 Python Package" ) 2 | 3 | # SparkFun Qwiic BME280 - Python Package 4 | 5 | ![PyPi Version](https://img.shields.io/pypi/v/sparkfun_qwiic_bme280) 6 | ![GitHub issues](https://img.shields.io/github/issues/sparkfun/qwiic_bme280_py) 7 | ![License](https://img.shields.io/github/license/sparkfun/qwiic_bme280_py) 8 | ![X](https://img.shields.io/twitter/follow/sparkfun) 9 | [![API](https://img.shields.io/badge/API%20Reference-blue)](https://docs.sparkfun.com/qwiic_bme280_py/classqwiic__bme280_1_1_qwiic_bme280.html) 10 | 11 | The SparkFun Qwiic BME280 Atmospheric Sensor and BME280/ENS160 Environmental Combo Breakout Boards provide a simple and cost effective solution for adding atmospheric sensing to your project. Implementing a SparkFun Qwiic I2C interface, these sensors can be rapidly added to any project with boards that are part of the SparkFun Qwiic ecosystem. 12 | 13 | This repository implements a Python package for the SparkFun Qwiic BME280. This package works with Python, MicroPython and CircuitPython. 14 | 15 | ### Contents 16 | 17 | * [About](#about-the-package) 18 | * [Installation](#installation) 19 | * [Supported Platforms](#supported-platforms) 20 | * [Documentation](https://docs.sparkfun.com/qwiic_bme280_py/classqwiic__bme280_1_1_qwiic_bme280.html) 21 | * [Examples](#example-use) 22 | 23 | ## About the Package 24 | 25 | This python package enables the user to access the features of the BME280 via a single Qwiic cable. This includes reading humidity, pressure, altitude, temperature, calibration and more. The capabilities of the BME280 are each demonstrated in the included examples. 26 | 27 | New to qwiic? Take a look at the entire [SparkFun qwiic ecosystem](https://www.sparkfun.com/qwiic). 28 | 29 | ### Supported SparkFun Products 30 | 31 | This Python package supports the following SparkFun qwiic products on Python, MicroPython and Circuit python. 32 | 33 | * [SparkFun Atmospheric Sensor Breakout - BME280](https://www.sparkfun.com/sparkfun-atmospheric-sensor-breakout-bme280-qwiic.html?gad_source=1) 34 | * [SparkFun Environmental Combo Breakout - ENS160/BME280](https://www.sparkfun.com/sparkfun-environmental-combo-breakout-ens160-bme280-qwiic.html) 35 | 36 | ### Supported Platforms 37 | 38 | | Python | Platform | Boards | 39 | |--|--|--| 40 | | Python | Linux | [Raspberry Pi](https://www.sparkfun.com/raspberry-pi-5-8gb.html) , [NVIDIA Jetson Orin Nano](https://www.sparkfun.com/nvidia-jetson-orin-nano-developer-kit.html) via the [SparkFun Qwiic SHIM](https://www.sparkfun.com/sparkfun-qwiic-shim-for-raspberry-pi.html) | 41 | | MicroPython | Raspberry Pi - RP2, ESP32 | [SparkFun Pro Micro RP2350](https://www.sparkfun.com/sparkfun-pro-micro-rp2350.html), [SparkFun IoT RedBoard ESP32](https://www.sparkfun.com/sparkfun-iot-redboard-esp32-development-board.html), [SparkFun IoT RedBoard RP2350](https://www.sparkfun.com/sparkfun-iot-redboard-rp2350.html) 42 | |CircuitPython | Raspberry Pi - RP2, ESP32 | [SparkFun Pro Micro RP2350](https://www.sparkfun.com/sparkfun-pro-micro-rp2350.html), [SparkFun IoT RedBoard ESP32](https://www.sparkfun.com/sparkfun-iot-redboard-esp32-development-board.html), [SparkFun IoT RedBoard RP2350](https://www.sparkfun.com/sparkfun-iot-redboard-rp2350.html) 43 | 44 | > [!NOTE] 45 | > The listed supported platforms and boards are the primary platform targets tested. It is fully expected that this package will work across a wide variety of Python enabled systems. 46 | 47 | ## Installation 48 | 49 | The first step to using this package is installing it on your system. The install method depends on the python platform. The following sections outline installation on Python, MicroPython and CircuitPython. 50 | 51 | ### Python 52 | 53 | #### PyPi Installation 54 | 55 | The package is primarily installed using the `pip3` command, downloading the package from the Python Index - "PyPi". 56 | 57 | Note - the below instructions outline installation on a Linux-based (Raspberry Pi) system. 58 | 59 | First, setup a virtual environment from a specific directory using venv: 60 | ```sh 61 | python3 -m venv path/to/venv 62 | ``` 63 | You can pass any path as path/to/venv, just make sure you use the same one for all future steps. For more information on venv [click here](https://docs.python.org/3/library/venv.html). 64 | 65 | Next, install the qwiic package with: 66 | ```sh 67 | path/to/venv/bin/pip3 install sparkfun-qwiic-bme280 68 | ``` 69 | Now you should be able to run any example or custom python scripts that have `import qwiic_bme280` by running e.g.: 70 | ```sh 71 | path/to/venv/bin/python3 example_script.py 72 | ``` 73 | 74 | ### MicroPython Installation 75 | If not already installed, follow the [instructions here](https://docs.micropython.org/en/latest/reference/mpremote.html) to install mpremote on your computer. 76 | 77 | Connect a device with MicroPython installed to your computer and then install the package directly to your device with mpremote mip. 78 | ```sh 79 | mpremote mip install github:sparkfun/qwiic_bme280_py 80 | ``` 81 | 82 | If you would also like to install the examples for this repository, issue the following mip command as well: 83 | ```sh 84 | mpremote mip install --target "" github:sparkfun/qwiic_bme280_py@examples 85 | ``` 86 | 87 | ### CircuitPython Installation 88 | If not already installed, follow the [instructions here](https://docs.circuitpython.org/projects/circup/en/latest/#installation) to install CircUp on your computer. 89 | 90 | Ensure that you have the latest version of the SparkFun Qwiic CircuitPython bundle. 91 | ```sh 92 | circup bundle-add sparkfun/Qwiic_Py 93 | ``` 94 | 95 | Finally, connect a device with CircuitPython installed to your computer and then install the package directly to your device with circup. 96 | ```sh 97 | circup install --py qwiic_bme280 98 | ``` 99 | 100 | If you would like to install any of the examples from this repository, issue the corresponding circup command from below. (NOTE: The below syntax assumes you are using CircUp on Windows. Linux and Mac will have different path seperators (i.e. "/" vs. "\"). See the [CircUp "example" command documentation](https://learn.adafruit.com/keep-your-circuitpython-libraries-on-devices-up-to-date-with-circup/example-command) for more information) 101 | 102 | ```sh 103 | circup example qwiic_bme280\qwiic_bme280_ex1 104 | circup example qwiic_bme280\qwiic_bme280_ex4 105 | circup example qwiic_bme280\qwiic_bme280_ex5 106 | ``` 107 | 108 | Example Use 109 | --------------- 110 | Below is a quickstart program to print humidity, pressure, altitude, and temperature read from the BME280. 111 | 112 | See the examples directory for more detailed use examples and [examples/README.md](https://github.com/sparkfun/qwiic_bme280_py/blob/main/examples/README.md) for a summary of the available examples. 113 | 114 | ```python 115 | import qwiic_bme280 116 | import time 117 | import sys 118 | 119 | def runExample(): 120 | 121 | print("\nSparkFun BME280 Sensor Example 1\n") 122 | mySensor = qwiic_bme280.QwiicBme280() 123 | 124 | if mySensor.connected == False: 125 | print("The Qwiic BME280 device isn't connected to the system. Please check your connection", \ 126 | file=sys.stderr) 127 | return 128 | 129 | mySensor.begin() 130 | 131 | while True: 132 | print("Humidity:\t%.3f" % mySensor.humidity) 133 | 134 | print("Pressure:\t%.3f" % mySensor.pressure) 135 | 136 | print("Altitude:\t%.3f" % mySensor.altitude_feet) 137 | 138 | print("Temperature:\t%.2f" % mySensor.temperature_fahrenheit) 139 | 140 | print("") 141 | 142 | time.sleep(1) 143 | ``` 144 |

145 | SparkFun - Start Something 146 |

147 | -------------------------------------------------------------------------------- /docs/_static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sparkfun/qwiic_bme280_py/c4576cc1450ffecff64535b7948d509ac690127d/docs/_static/favicon.ico -------------------------------------------------------------------------------- /docs/doxygen/doxygen-awesome-css/.github/workflows/publish.yaml: -------------------------------------------------------------------------------- 1 | name: publish 2 | on: 3 | release: 4 | types: [published] 5 | jobs: 6 | deploy: 7 | runs-on: ubuntu-20.04 8 | steps: 9 | - name: Checkout repository 10 | uses: actions/checkout@v2 11 | with: 12 | fetch-depth: 0 13 | - name: set version 14 | run: echo "PROJECT_NUMBER = `git describe --tags`" >> Doxyfile 15 | - name: Generate Documentation 16 | uses: mattnotmitt/doxygen-action@edge 17 | - name: Publish generated content to GitHub Pages 18 | uses: tsunematsu21/actions-publish-gh-pages@v1.0.2 19 | with: 20 | dir: docs/html 21 | branch: gh-pages 22 | token: ${{ secrets.ACCESS_TOKEN }} -------------------------------------------------------------------------------- /docs/doxygen/doxygen-awesome-css/.gitignore: -------------------------------------------------------------------------------- 1 | docs/html 2 | .DS_Store 3 | .idea 4 | 5 | node_modules 6 | *.tgz 7 | -------------------------------------------------------------------------------- /docs/doxygen/doxygen-awesome-css/.npmignore: -------------------------------------------------------------------------------- 1 | * 2 | !doxygen-awesome* 3 | 4 | -------------------------------------------------------------------------------- /docs/doxygen/doxygen-awesome-css/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 - 2023 jothepro 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. 22 | -------------------------------------------------------------------------------- /docs/doxygen/doxygen-awesome-css/Makefile: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2022 Andrea Pappacoda 2 | # SPDX-License-Identifier: MIT 3 | 4 | .POSIX: 5 | 6 | PROJECT = doxygen-awesome-css 7 | 8 | # Paths 9 | PREFIX = /usr/local 10 | DATADIR = share 11 | INSTALLDIR = $(DESTDIR)$(PREFIX)/$(DATADIR)/$(PROJECT) 12 | 13 | # Utilities 14 | INSTALL = install -m 644 15 | MKDIR = mkdir -p 16 | RM = rm -f 17 | 18 | # Files to be installed 19 | FILES = doxygen-awesome-darkmode-toggle.js \ 20 | doxygen-awesome-fragment-copy-button.js \ 21 | doxygen-awesome-interactive-toc.js \ 22 | doxygen-awesome-paragraph-link.js \ 23 | doxygen-awesome-sidebar-only-darkmode-toggle.css \ 24 | doxygen-awesome-sidebar-only.css \ 25 | doxygen-awesome-tabs.js \ 26 | doxygen-awesome.css 27 | 28 | # Empty targets so that `make` and `make clean` do not cause errors 29 | all: 30 | clean: 31 | 32 | install: 33 | $(MKDIR) $(INSTALLDIR) 34 | $(INSTALL) $(FILES) $(INSTALLDIR)/ 35 | 36 | uninstall: 37 | $(RM) -r $(INSTALLDIR)/ 38 | 39 | .PHONY: all clean install uninstall 40 | -------------------------------------------------------------------------------- /docs/doxygen/doxygen-awesome-css/README.md: -------------------------------------------------------------------------------- 1 | # Doxygen Awesome 2 | 3 | [![GitHub release (latest by date)](https://img.shields.io/github/v/release/jothepro/doxygen-awesome-css)](https://github.com/jothepro/doxygen-awesome-css/releases/latest) 4 | [![GitHub](https://img.shields.io/github/license/jothepro/doxygen-awesome-css)](https://github.com/jothepro/doxygen-awesome-css/blob/main/LICENSE) 5 | ![GitHub Repo stars](https://img.shields.io/github/stars/jothepro/doxygen-awesome-css) 6 | 7 |
8 | 9 | ![Screenshot of Doxygen Awesome CSS](img/screenshot.png) 10 | 11 |
12 | 13 | **Doxygen Awesome** is a custom CSS theme for Doxygen HTML documentation with lots of customization parameters. 14 | 15 | ## Motivation 16 | 17 | I really like how the Doxygen HTML documentation is structured! But IMHO it looks a bit outdated. 18 | 19 | This theme is an attempt to update the visuals of Doxygen without changing its overall layout too much. 20 | 21 | ## Features 22 | 23 | - 🌈 Clean, modern design 24 | - 🚀 Heavily customizable by adjusting CSS variables 25 | - 🧩 No changes to the HTML structure of Doxygen are required 26 | - 📱 Improved mobile usability 27 | - 🌘 Dark mode support! 28 | - 🥇 Works best with **doxygen 1.9.1** - **1.9.4** and **1.9.6** - **1.10.0** 29 | 30 | ## Examples 31 | 32 | Some websites using this theme: 33 | 34 | - [Documentation of this repository](https://jothepro.github.io/doxygen-awesome-css/) 35 | - [wxWidgets](https://docs.wxwidgets.org/3.2/) 36 | - [OpenCV 5.x](https://docs.opencv.org/5.x/) 37 | - [Zephyr](https://docs.zephyrproject.org/latest/doxygen/html/index.html) 38 | - [FELTOR](https://mwiesenberger.github.io/feltor/dg/html/modules.html) 39 | - [Spatial Audio Framework (SAF)](https://leomccormack.github.io/Spatial_Audio_Framework/index.html) 40 | - [Randolf Richardson's C++ classes](https://www.randolf.ca/c++/docs/) 41 | - [libCloudSync](https://jothepro.github.io/libCloudSync/) 42 | - [libsl3](https://a4z.github.io/libsl3/) 43 | 44 | ## Installation 45 | 46 | To use the theme when generating your documentation, bring the required CSS and JS files from this repository into your project. 47 | 48 | This can be done in several ways: 49 | 50 | - manually copying the files 51 | - adding the project as a Git submodule 52 | - adding the project as a npm/xpm dependency 53 | - installing the theme system-wide 54 | 55 | All theme files are located in the root of this repository and start with the prefix `doxygen-awesome-`. You may not need all of them. Follow the install instructions to figure out what files are required for your setup. 56 | 57 | ### Git submodule 58 | For projects that use git, add the repository as a submodule and check out the desired release: 59 | 60 | ```sh 61 | git submodule add https://github.com/jothepro/doxygen-awesome-css.git 62 | cd doxygen-awesome-css 63 | git checkout v2.3.2 64 | ``` 65 | 66 | ### npm/xpm dependency 67 | 68 | In the npm ecosystem, this project can be added as a development dependency 69 | to your project: 70 | 71 | ```sh 72 | cd your-project 73 | npm install https://github.com/jothepro/doxygen-awesome-css#v2.3.2 --save-dev 74 | 75 | ls -l node_module/@jothepro/doxygen-awesome-css 76 | ``` 77 | 78 | Similarly, in the [xPack](https://xpack.github.io) ecosystem, this project can be added 79 | as a development dependency to an [`xpm`](https://xpack.github.io/xpm/) 80 | managed project. 81 | 82 | ### System-wide 83 | 84 | You can even install the theme system-wide by running `make install`. 85 | The files will be installed to `/usr/local/share/` by default, 86 | but you can customize the install location with `make PREFIX=/my/custom/path install`. 87 | 88 | ### Choosing a layout 89 | 90 | There are two layout options. Choose one of them and configure Doxygen accordingly: 91 | 92 |
93 | 94 | - Base Theme
95 | ![](img/theme-variants-base.drawio.svg) 96 |
97 | Comes with the typical Doxygen titlebar. Optionally the treeview in the sidebar can be enabled. 98 | 99 | Required files: `doxygen-awesome.css` 100 | 101 | Required `Doxyfile` configuration: 102 | ``` 103 | GENERATE_TREEVIEW = YES # optional. Also works without treeview 104 | DISABLE_INDEX = NO 105 | FULL_SIDEBAR = NO 106 | HTML_EXTRA_STYLESHEET = doxygen-awesome-css/doxygen-awesome.css 107 | HTML_COLORSTYLE = LIGHT # required with Doxygen >= 1.9.5 108 | ``` 109 | 110 | - Sidebar-Only Theme
111 | ![](img/theme-variants-sidebar-only.drawio.svg) 112 |
113 | Hides the top titlebar to give more space to the content. The treeview must be enabled in order for this theme to work. 114 | 115 | Required files: `doxygen-awesome.css`, `doxygen-awesome-sidebar-only.css` 116 | 117 | Required `Doxyfile` configuration: 118 | ``` 119 | 120 | GENERATE_TREEVIEW = YES # required! 121 | DISABLE_INDEX = NO 122 | FULL_SIDEBAR = NO 123 | HTML_EXTRA_STYLESHEET = doxygen-awesome-css/doxygen-awesome.css \ 124 | doxygen-awesome-css/doxygen-awesome-sidebar-only.css 125 | HTML_COLORSTYLE = LIGHT # required with Doxygen >= 1.9.5 126 | ``` 127 | 128 |
129 | 130 |
131 | 132 | @warning 133 | - This theme is not compatible with the `FULL_SIDEBAR = YES` option provided by Doxygen! 134 | - `HTML_COLORSTYLE` must be set to `LIGHT` since Doxygen 1.9.5! 135 | 136 | ### Further installation instructions 137 | 138 | - [Installing extensions](docs/extensions.md) 139 | - [Customizing the theme (colors, spacing, border-radius, ...)](docs/customization.md) 140 | - [Tips and Tricks for further configuration](docs/tricks.md) 141 | 142 | ## Browser support 143 | 144 | Tested with 145 | 146 | - Chrome 119, Chrome 119 for Android, Chrome 119 for iOS 147 | - Safari 17, Safari for iOS 16 148 | - Firefox 118, Firefox 120 for Android, Firefox 119 for iOS 149 | - Edge 119 150 | - Opera 108 151 | 152 | 153 | The theme does not strive to be backward compatible with (significantly) older browser versions. 154 | 155 | 156 | ## Credits 157 | 158 | Thanks for all the bug reports and inspiring feedback on GitHub! 159 | 160 | Special thanks to all the contributors: 161 |

162 | 163 | 164 | 165 | 166 | 167 |
168 | 169 | | Read Next | 170 | |---------------------------------:| 171 | | [Extensions](docs/extensions.md) | 172 | 173 |
174 | -------------------------------------------------------------------------------- /docs/doxygen/doxygen-awesome-css/docs/customization.md: -------------------------------------------------------------------------------- 1 | # Customization 2 | 3 | [TOC] 4 | 5 | 6 | ## CSS-Variables 7 | 8 | This theme is highly customizable because a lot of things are parameterized with CSS variables. 9 | 10 | Just to give you an idea of how flexible the styling is, click this button: 11 | 12 |
Alter theme
13 | 14 |

15 | 16 | ### Setup 17 | 18 | It is recommended to add your own `custom.css` and overwrite the variables there: 19 | ``` 20 | HTML_EXTRA_STYLESHEET = doxygen-awesome.css custom.css 21 | ``` 22 | 23 | Make sure to override the variables in the correct spot. All variables should be customized where they have been defined, in the `html` tag selector: 24 | 25 | ```css 26 | html { 27 | /* override light-mode variables here */ 28 | } 29 | ``` 30 | 31 | For dark-mode overrides, you have to choose where to put them, depending on whether the dark-mode toggle extension is installed or not: 32 | 33 |
34 | 35 | - dark-mode toggle is installed 36 | ```css 37 | html.dark-mode { 38 | /* define dark-mode variable overrides here if you DO use doxygen-awesome-darkmode-toggle.js */ 39 | } 40 | ``` 41 | - dark-mode toggle is **NOT** installed 42 | The dark-mode is enabled automatically depending on the system preference: 43 | ```css 44 | @media (prefers-color-scheme: dark) { 45 | html:not(.light-mode) { 46 | /* define dark-mode variable overrides here if you DON'T use doxygen-awesome-darkmode-toggle.js */ 47 | } 48 | } 49 | ``` 50 | 51 |
52 | 53 | ### Available variables 54 | 55 | The following list gives an overview of the variables defined in [`doxygen-awesome.css`](https://github.com/jothepro/doxygen-awesome-css/blob/main/doxygen-awesome.css). 56 | 57 | The list is not complete. To explore all available variables, have a look at the CSS starting from [here](https://github.com/jothepro/doxygen-awesome-css/blob/main/doxygen-awesome.css#L30). 58 | All variables are defined at the beginning of the stylesheet. 59 | 60 | | Parameter | Default (Light) | Default (Dark) | 61 | | :---------------------------------- | :---------------------------------------------------------- | :---------------------------------------------------------- | 62 | | **Color Scheme**:
primary theme colors. This will affect the entire websites color scheme: links, arrows, labels, ... ||| 63 | | `--primary-color` | #1779c4 | #1982d2 | 64 | | `--primary-dark-color` | #335c80 | #5ca8e2 | 65 | | `--primary-light-color` | #70b1e9 | #4779ac | 66 | | **Page Colors**:
background and foreground (text-color) of the documentation. ||| 67 | | `--page-background-color` | #ffffff | #1C1D1F | 68 | | `--page-foreground-color` | #2f4153 | #d2dbde | 69 | | `--page-secondary-foreground-color` | #6f7e8e | #859399 | 70 | | **Spacing:**
default spacings. Most ui components reference these values for spacing, to provide uniform spacing on the page. ||| 71 | | `--spacing-small` | `5px` | | 72 | | `--spacing-medium` | `10px` | | 73 | | `--spacing-large` | `16px` | | 74 | | **Border Radius**:
border radius for all rounded ui components. Will affect many components, like dropdowns, memitems, codeblocks, ... ||| 75 | | `--border-radius-small` | `4px` | | 76 | | `--border-radius-medium` | `6px` | | 77 | | `--border-radius-large` | `8px` | | 78 | | **Content Width**:
The content is centered and constrained in its width. To make the content fill the whole page, set the following variable to `auto`. ||| 79 | | `--content-maxwidth` | `1000px` | | 80 | | **Code Fragment Colors**:
Color-Scheme of multiline codeblocks ||| 81 | | `--fragment-background` | #F8F9FA | #282c34 | 82 | | `--fragment-foreground` | #37474F | #dbe4eb | 83 | | **Arrow Opacity**:
By default the arrows in the sidebar are only visible on hover. You can override this behavior so they are visible all the time. ||| 84 | | `--side-nav-arrow-opacity` | `0` | | 85 | | `--side-nav-arrow-hover-opacity` | `0.9` | | 86 | | ...and many more ||| 87 | 88 | 89 | If you miss a configuration option or find a bug, please consider [opening an issue](https://github.com/jothepro/doxygen-awesome-css/issues)! 90 | 91 | ## Doxygen generator 92 | 93 | The theme overrides most colors with the `--primary-color-*` variables. 94 | 95 | But there are a few small images and graphics that the theme cannot adjust or replace. To make these blend in better with 96 | the rest, it is recommended to adjust the [doxygen color settings](https://www.doxygen.nl/manual/customize.html#minor_tweaks_colors) 97 | to something that matches the chosen color scheme. 98 | 99 | For the default color scheme, these values work out quite well: 100 | 101 | ``` 102 | # Doxyfile 103 | HTML_COLORSTYLE_HUE = 209 104 | HTML_COLORSTYLE_SAT = 255 105 | HTML_COLORSTYLE_GAMMA = 113 106 | ``` 107 | 108 | ## Share your customizations 109 | 110 | If you have customized the theme with custom colors, spacings, font-sizes, etc. and you want to share your creation with others, you can do this [here](https://github.com/jothepro/doxygen-awesome-css/discussions/13). 111 | 112 | I am always curious to learn about how you made the theme look even better! 113 | 114 | 115 |
116 | 117 | | Previous | Next | 118 | |:----------------------------|---------------------------:| 119 | | [Extensions](extensions.md) | [Tips & Tricks](tricks.md) | 120 | 121 |
-------------------------------------------------------------------------------- /docs/doxygen/doxygen-awesome-css/docs/extensions.md: -------------------------------------------------------------------------------- 1 | # Extensions 2 | 3 | [TOC] 4 | 5 | On top of the base theme provided by `doxygen-awesome.css`, this repository comes with Javascript extensions that require additional setup steps to get them running. 6 | 7 | The extensions require customizations in the header HTML template. 8 | This is how you can create the default template with Doxygen: 9 | 10 | 1. Create default header template: 11 | ```sh 12 | doxygen -w html header.html delete_me.html delete_me.css 13 | ``` 14 | 15 | 2. Reference the template in your `Doxyfile`: 16 | ``` 17 | HTML_HEADER = header.html 18 | ``` 19 | 20 | [More details on header customization](https://www.doxygen.nl/manual/customize.html#minor_tweaks_header_css) 21 | 22 | ## Dark Mode Toggle {#extension-dark-mode-toggle} 23 | 24 | Adds a button next to the search bar to enable and disable the dark theme variant manually: 25 | 26 |
27 | 28 | ![](img/darkmode_toggle.png){width=250px} 29 |
30 | 31 | ### Installation 32 | 33 | 1. Add the required resources in your `Doxyfile`: 34 | - **HTML_EXTRA_FILES:** `doxygen-awesome-darkmode-toggle.js` 35 | - **HTML_EXTRA_STYLESHEET:** `doxygen-awesome-sidebar-only-darkmode-toggle.css` 36 | (ONLY required for the sidebar-only theme variant!) 37 | 2. In the `header.html` template, include `doxygen-awesome-darkmode-toggle.js` at the end of the `` and then initialize it: 38 | ```html 39 | 40 | 41 | 42 | 43 | 46 | 47 | 48 | ``` 49 | 50 | ### Customizing 51 | 52 | Changing the tooltip of the button: 53 | ```js 54 | DoxygenAwesomeDarkModeToggle.title = "Zwischen hellem/dunklem Modus wechseln" 55 | ``` 56 | 57 | Changing Icons. Both Emoji or SVG icons are supported: 58 | ```js 59 | DoxygenAwesomeDarkModeToggle.lightModeIcon = '🌞' 60 | // icon from https://fonts.google.com/icons 61 | DoxygenAwesomeDarkModeToggle.darkModeIcon = `` 62 | ``` 63 | 64 | All customizations must be applied before calling `DoxygenAwesomeDarkModeToggle.init()`! 65 | 66 | 67 | ## Fragment Copy Button {#extension-copy-button} 68 | 69 | Shows a copy button when the user hovers over a code fragment: 70 | 71 |
72 | 73 | ![](img/fragment_copy_button.png){width=490} 74 |
75 | 76 | ### Installation 77 | 78 | 1. Add the required resources in your `Doxyfile`: 79 | - **HTML_EXTRA_FILES:** `doxygen-awesome-fragment-copy-button.js` 80 | 2. In the `header.html` template, include `doxygen-awesome-fragment-copy-button.js` at the end of the `` and then initialize it: 81 | ```html 82 | 83 | 84 | 85 | 86 | 89 | 90 | 91 | ``` 92 | 93 | ### Customizing 94 | 95 | The tooltip of the button can be changed: 96 | ```js 97 | DoxygenAwesomeFragmentCopyButton.title = "In die Zwischenablage kopieren" 98 | ``` 99 | 100 | The icon can be changed. It must be an SVG: 101 | ```js 102 | DoxygenAwesomeFragmentCopyButton.copyIcon = `` 103 | DoxygenAwesomeFragmentCopyButton.successIcon = `` 104 | ``` 105 | 106 | All customizations must be applied before calling `DoxygenAwesomeDarkModeToggle.init()`! 107 | 108 | ## Paragraph Linking {#extension-para} 109 | 110 | Provides a button on hover behind every headline to allow easy creation of a permanent link to the headline: 111 | 112 |
113 | 114 | ![](img/paragraph_link.png){width=220} 115 |
116 | 117 | Works for all headlines and for many documentation section titles. 118 | 119 | ### Installation 120 | 121 | 1. Add the required resources in your `Doxyfile`: 122 | - **HTML_EXTRA_FILES:** `doxygen-awesome-paragraph-link.js` 123 | 2. In the `header.html` template, include `doxygen-awesome-paragraph-link.js` at the end of the `` and then initialize it: 124 | ```html 125 | 126 | 127 | 128 | 129 | 132 | 133 | 134 | ``` 135 | 136 | ### Customizing 137 | 138 | The button tooltip can be changed: 139 | ```js 140 | DoxygenAwesomeParagraphLink.title = "Abschnitt verknüpfen" 141 | ``` 142 | 143 | The icon of the button can be changed. Both plain characters or SVG icons are supported: 144 | ```js 145 | DoxygenAwesomeParagraphLink.icon = "¶" 146 | ``` 147 | 148 | All customizations must be applied before calling `DoxygenAwesomeParagraphLink.init()`! 149 | 150 | ## Interactive TOC {#extension-toc} 151 | 152 | On large screens, the Table of Contents (TOC) is anchored on the top right of the page. This extension visualizes the reading progress by dynamically highlighting the currently active section. 153 | 154 | On small screens, the extension hides the TOC by default. The user can open it manually when needed: 155 | 156 | 157 |
158 | 159 | ![](img/interactive_toc_mobile.png){width=380} 160 |
161 | 162 | ### Installation 163 | 164 | 1. Add the required resources in your `Doxyfile`: 165 | - **HTML_EXTRA_FILES:** `doxygen-awesome-interactive-toc.js` 166 | 2. In the `header.html` template, include `doxygen-awesome-interactive-toc.js` at the end of the `` and then initialize it: 167 | ```html 168 | 169 | 170 | 171 | 172 | 175 | 176 | 177 | ``` 178 | 179 | ### Customizing 180 | 181 | The offset for when a headline is considered active can be changed. A smaller value means that the headline of the section must be closer to the top of the viewport before it is highlighted in the TOC: 182 | ```js 183 | DoxygenAwesomeInteractiveToc.topOffset = 45 184 | ``` 185 | 186 | Hiding the TOC on small screens can be disabled. It is still interactive and can be hidden by the user but will now be open by default: 187 | ```js 188 | DoxygenAwesomeInteractiveToc.hideMobileMenu = false 189 | ``` 190 | 191 | ## Tabs {#extension-tabs} 192 | 193 | @warning Experimental feature! Please report bugs [here](https://github.com/jothepro/doxygen-awesome-css/issues). 194 | 195 | This extension allows to arrange list content in tabs: 196 | 197 |
198 | 199 | - Tab 1 200 | This is the content of tab 1 201 | - Tab 2 202 | This is the content of tab 2 203 | 1. it has a list 204 | 2. with multiple items 205 | 206 |
207 | 208 | 209 | ### Installation 210 | 211 | 1. Add the required resources in your `Doxyfile`: 212 | - **HTML_EXTRA_FILES:** `doxygen-awesome-tabs.js` 213 | 2. In the `header.html` template, include `doxygen-awesome-tabs.js` at the end of the `` and then initialize it: 214 | ```html 215 | 216 | 217 | 218 | 219 | 222 | 223 | 224 | ``` 225 | 226 | ### Usage 227 | 228 | Each list that is supposed to be displayed as tabs has to be wrapped with the `tabbed` CSS class. 229 | Each item in the list must start with an element that has the class `tab-title`. It will then be used as tab title. 230 | 231 | ```md 232 |
233 | 234 | - Tab 1 This is the content of tab 1 235 | - Tab 2 This is the content of tab 2 236 | 237 |
238 | ``` 239 | 240 | ## Page Navigation {#extension-page-navigation} 241 | 242 | @warning Experimental feature! Please report bugs [here](https://github.com/jothepro/doxygen-awesome-css/issues). 243 | 244 | To allow the user to easily navigate from one document to another, "Next" and "Previous" buttons can be added at the end of a Markdown document. 245 | 246 | ### Installation 247 | 248 | The feature is shipped inside the default `doxygen-awesome.css`. No additional stylesheets or scripts need to be added. 249 | 250 | ### Usage 251 | 252 | The following conditions must be met for the feature to work properly: 253 | - The navigation must be inside a Markdown table with 1-2 columns. 254 | - The alignment of the column defines the alignment of the arrow on the navigation button. 255 | - the table must be wrapped inside a `
` with the class `section_buttons`. 256 | 257 |
258 | 259 | - Code 260 | ```md 261 |
262 | 263 | | Previous | Next | 264 | |:------------------|----------------------------------:| 265 | | [Home](README.md) | [Customization](customization.md) | 266 | 267 |
268 | ``` 269 | - Result 270 |
271 | | Previous | Next | 272 | |:------------------|----------------------------------:| 273 | | [Home](README.md) | [Customization](customization.md) | 274 |
275 | 276 |
277 | 278 |
279 | 280 | | Previous | Next | 281 | |:------------------|----------------------------------:| 282 | | [Home](README.md) | [Customization](customization.md) | 283 |
-------------------------------------------------------------------------------- /docs/doxygen/doxygen-awesome-css/docs/img/darkmode_toggle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sparkfun/qwiic_bme280_py/c4576cc1450ffecff64535b7948d509ac690127d/docs/doxygen/doxygen-awesome-css/docs/img/darkmode_toggle.png -------------------------------------------------------------------------------- /docs/doxygen/doxygen-awesome-css/docs/img/fancy_scrollbars_firefox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sparkfun/qwiic_bme280_py/c4576cc1450ffecff64535b7948d509ac690127d/docs/doxygen/doxygen-awesome-css/docs/img/fancy_scrollbars_firefox.png -------------------------------------------------------------------------------- /docs/doxygen/doxygen-awesome-css/docs/img/fancy_scrollbars_webkit.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sparkfun/qwiic_bme280_py/c4576cc1450ffecff64535b7948d509ac690127d/docs/doxygen/doxygen-awesome-css/docs/img/fancy_scrollbars_webkit.gif -------------------------------------------------------------------------------- /docs/doxygen/doxygen-awesome-css/docs/img/fragment_copy_button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sparkfun/qwiic_bme280_py/c4576cc1450ffecff64535b7948d509ac690127d/docs/doxygen/doxygen-awesome-css/docs/img/fragment_copy_button.png -------------------------------------------------------------------------------- /docs/doxygen/doxygen-awesome-css/docs/img/interactive_toc_mobile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sparkfun/qwiic_bme280_py/c4576cc1450ffecff64535b7948d509ac690127d/docs/doxygen/doxygen-awesome-css/docs/img/interactive_toc_mobile.png -------------------------------------------------------------------------------- /docs/doxygen/doxygen-awesome-css/docs/img/paragraph_link.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sparkfun/qwiic_bme280_py/c4576cc1450ffecff64535b7948d509ac690127d/docs/doxygen/doxygen-awesome-css/docs/img/paragraph_link.png -------------------------------------------------------------------------------- /docs/doxygen/doxygen-awesome-css/docs/tricks.md: -------------------------------------------------------------------------------- 1 | # Tips & Tricks 2 | 3 | [TOC] 4 | 5 | ## Diagrams with Graphviz {#tricks-graphviz} 6 | 7 | To get the best-looking class diagrams for your documentation, generate them with Graphviz as vector graphics with transparent background: 8 | 9 | ``` 10 | # Doxyfile 11 | HAVE_DOT = YES 12 | DOT_IMAGE_FORMAT = svg 13 | DOT_TRANSPARENT = YES 14 | ``` 15 | 16 | In case `INTERACTIVE_SVG = YES` is set in the Doxyfile, all user-defined dotgraphs must be wrapped with the `interactive_dotgraph` CSS class for them to be rendered correctly: 17 | 18 | ```md 19 |
20 | 21 | \dotfile graph.dot 22 | 23 |
24 | ``` 25 | 26 | @note Both the default overflow scrolling behavior in this theme and the interactive editor enabled by `INTERACTIVE_SVG` are unsatisfying workarounds IMHO. Consider designing your graphs to be narrow enough to fit the page to avoid scrolling. 27 | 28 | ## Disable Dark Mode {#tricks-darkmode} 29 | 30 | If you don't want the theme to automatically switch to dark mode depending on the browser preference, 31 | you can disable dark mode by adding the `light-mode` class to the HTML tag in the header template: 32 | 33 | ```html 34 | 35 | ``` 36 | 37 | The same can be done to always enable dark mode: 38 | 39 | ```html 40 | 41 | ``` 42 | 43 | 44 | @warning This only works if you don't use the dark-mode toggle extension. 45 | 46 | ## Choosing Sidebar Width {#tricks-sidebar} 47 | 48 | If you have enabled the sidebar-only theme variant, make sure to carefully choose a proper width for your sidebar. 49 | It should be wide enough to hold the icon, project title and version number. If the content is too wide, it will be 50 | cut off. 51 | 52 | ```css 53 | html { 54 | /* Make sure sidebar is wide enough to contain the page title (logo + title + version) */ 55 | --side-nav-fixed-width: 335px; 56 | } 57 | ``` 58 | 59 | The chosen width should also be set in the Doxyfile: 60 | 61 | ``` 62 | # Doxyfile 63 | TREEVIEW_WIDTH = 335 64 | ``` 65 | 66 | ## Formatting Tables {#tricks-tables} 67 | 68 | By default tables in this theme are left-aligned and as wide as required to fit their content. 69 | Those properties can be changed for individual tables. 70 | 71 | ### Centering 72 | 73 | Tables can be centered by wrapping them in the `
` HTML tag. 74 | 75 |
76 | 77 | - Code 78 | ```md 79 |
80 | | This table | is centered | 81 | |------------|----------------------| 82 | | test 1 | test 2 | 83 |
84 | ``` 85 | - Result 86 |
87 | | This table | is centered | 88 | |------------|----------------------| 89 | | test 1 | test 2 | 90 |
91 | 92 |
93 | 94 | 95 | 96 | ### Full Width 97 | 98 | To make tables span the full width of the page, no matter how wide the content is, wrap the table in the `full_width_table` CSS class. 99 | 100 | @warning Apply with caution! This breaks the overflow scrolling of the table. Content might be cut off on small screens! 101 | 102 |
103 | 104 | - Code 105 | ```md 106 |
107 | | This table | spans the full width | 108 | |------------|----------------------| 109 | | test 1 | test 2 | 110 |
111 | ``` 112 | - Result 113 |
114 | | This table | spans the full width | 115 | |------------|----------------------| 116 | | test 1 | test 2 | 117 |
118 | 119 |
120 | 121 |
122 | 123 | | Previous | Next | 124 | |:----------------------------------|---------------------------------------:| 125 | | [Customization](customization.md) | [Example](https://jothepro.github.io/doxygen-awesome-css/class_my_library_1_1_example.html) | 126 | 127 |
-------------------------------------------------------------------------------- /docs/doxygen/doxygen-awesome-css/doxygen-awesome-darkmode-toggle.js: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | Doxygen Awesome 4 | https://github.com/jothepro/doxygen-awesome-css 5 | 6 | MIT License 7 | 8 | Copyright (c) 2021 - 2023 jothepro 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all 18 | copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | 28 | */ 29 | 30 | class DoxygenAwesomeDarkModeToggle extends HTMLElement { 31 | // SVG icons from https://fonts.google.com/icons 32 | // Licensed under the Apache 2.0 license: 33 | // https://www.apache.org/licenses/LICENSE-2.0.html 34 | static lightModeIcon = `` 35 | static darkModeIcon = `` 36 | static title = "Toggle Light/Dark Mode" 37 | 38 | static prefersLightModeInDarkModeKey = "prefers-light-mode-in-dark-mode" 39 | static prefersDarkModeInLightModeKey = "prefers-dark-mode-in-light-mode" 40 | 41 | static _staticConstructor = function() { 42 | DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.userPreference) 43 | // Update the color scheme when the browsers preference changes 44 | // without user interaction on the website. 45 | window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => { 46 | DoxygenAwesomeDarkModeToggle.onSystemPreferenceChanged() 47 | }) 48 | // Update the color scheme when the tab is made visible again. 49 | // It is possible that the appearance was changed in another tab 50 | // while this tab was in the background. 51 | document.addEventListener("visibilitychange", visibilityState => { 52 | if (document.visibilityState === 'visible') { 53 | DoxygenAwesomeDarkModeToggle.onSystemPreferenceChanged() 54 | } 55 | }); 56 | }() 57 | 58 | static init() { 59 | $(function() { 60 | $(document).ready(function() { 61 | const toggleButton = document.createElement('doxygen-awesome-dark-mode-toggle') 62 | toggleButton.title = DoxygenAwesomeDarkModeToggle.title 63 | toggleButton.updateIcon() 64 | 65 | window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => { 66 | toggleButton.updateIcon() 67 | }) 68 | document.addEventListener("visibilitychange", visibilityState => { 69 | if (document.visibilityState === 'visible') { 70 | toggleButton.updateIcon() 71 | } 72 | }); 73 | 74 | $(document).ready(function(){ 75 | document.getElementById("MSearchBox").parentNode.appendChild(toggleButton) 76 | }) 77 | $(window).resize(function(){ 78 | document.getElementById("MSearchBox").parentNode.appendChild(toggleButton) 79 | }) 80 | }) 81 | }) 82 | } 83 | 84 | constructor() { 85 | super(); 86 | this.onclick=this.toggleDarkMode 87 | } 88 | 89 | /** 90 | * @returns `true` for dark-mode, `false` for light-mode system preference 91 | */ 92 | static get systemPreference() { 93 | return window.matchMedia('(prefers-color-scheme: dark)').matches 94 | } 95 | 96 | /** 97 | * @returns `true` for dark-mode, `false` for light-mode user preference 98 | */ 99 | static get userPreference() { 100 | return (!DoxygenAwesomeDarkModeToggle.systemPreference && localStorage.getItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey)) || 101 | (DoxygenAwesomeDarkModeToggle.systemPreference && !localStorage.getItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey)) 102 | } 103 | 104 | static set userPreference(userPreference) { 105 | DoxygenAwesomeDarkModeToggle.darkModeEnabled = userPreference 106 | if(!userPreference) { 107 | if(DoxygenAwesomeDarkModeToggle.systemPreference) { 108 | localStorage.setItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey, true) 109 | } else { 110 | localStorage.removeItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey) 111 | } 112 | } else { 113 | if(!DoxygenAwesomeDarkModeToggle.systemPreference) { 114 | localStorage.setItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey, true) 115 | } else { 116 | localStorage.removeItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey) 117 | } 118 | } 119 | DoxygenAwesomeDarkModeToggle.onUserPreferenceChanged() 120 | } 121 | 122 | static enableDarkMode(enable) { 123 | if(enable) { 124 | DoxygenAwesomeDarkModeToggle.darkModeEnabled = true 125 | document.documentElement.classList.add("dark-mode") 126 | document.documentElement.classList.remove("light-mode") 127 | } else { 128 | DoxygenAwesomeDarkModeToggle.darkModeEnabled = false 129 | document.documentElement.classList.remove("dark-mode") 130 | document.documentElement.classList.add("light-mode") 131 | } 132 | } 133 | 134 | static onSystemPreferenceChanged() { 135 | DoxygenAwesomeDarkModeToggle.darkModeEnabled = DoxygenAwesomeDarkModeToggle.userPreference 136 | DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.darkModeEnabled) 137 | } 138 | 139 | static onUserPreferenceChanged() { 140 | DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.darkModeEnabled) 141 | } 142 | 143 | toggleDarkMode() { 144 | DoxygenAwesomeDarkModeToggle.userPreference = !DoxygenAwesomeDarkModeToggle.userPreference 145 | this.updateIcon() 146 | } 147 | 148 | updateIcon() { 149 | if(DoxygenAwesomeDarkModeToggle.darkModeEnabled) { 150 | this.innerHTML = DoxygenAwesomeDarkModeToggle.darkModeIcon 151 | } else { 152 | this.innerHTML = DoxygenAwesomeDarkModeToggle.lightModeIcon 153 | } 154 | } 155 | } 156 | 157 | customElements.define("doxygen-awesome-dark-mode-toggle", DoxygenAwesomeDarkModeToggle); 158 | -------------------------------------------------------------------------------- /docs/doxygen/doxygen-awesome-css/doxygen-awesome-fragment-copy-button.js: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | Doxygen Awesome 4 | https://github.com/jothepro/doxygen-awesome-css 5 | 6 | MIT License 7 | 8 | Copyright (c) 2022 - 2023 jothepro 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all 18 | copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | 28 | */ 29 | 30 | class DoxygenAwesomeFragmentCopyButton extends HTMLElement { 31 | constructor() { 32 | super(); 33 | this.onclick=this.copyContent 34 | } 35 | static title = "Copy to clipboard" 36 | static copyIcon = `` 37 | static successIcon = `` 38 | static successDuration = 980 39 | static init() { 40 | $(function() { 41 | $(document).ready(function() { 42 | if(navigator.clipboard) { 43 | const fragments = document.getElementsByClassName("fragment") 44 | for(const fragment of fragments) { 45 | const fragmentWrapper = document.createElement("div") 46 | fragmentWrapper.className = "doxygen-awesome-fragment-wrapper" 47 | const fragmentCopyButton = document.createElement("doxygen-awesome-fragment-copy-button") 48 | fragmentCopyButton.innerHTML = DoxygenAwesomeFragmentCopyButton.copyIcon 49 | fragmentCopyButton.title = DoxygenAwesomeFragmentCopyButton.title 50 | 51 | fragment.parentNode.replaceChild(fragmentWrapper, fragment) 52 | fragmentWrapper.appendChild(fragment) 53 | fragmentWrapper.appendChild(fragmentCopyButton) 54 | 55 | } 56 | } 57 | }) 58 | }) 59 | } 60 | 61 | 62 | copyContent() { 63 | const content = this.previousSibling.cloneNode(true) 64 | // filter out line number from file listings 65 | content.querySelectorAll(".lineno, .ttc").forEach((node) => { 66 | node.remove() 67 | }) 68 | let textContent = content.textContent 69 | // remove trailing newlines that appear in file listings 70 | let numberOfTrailingNewlines = 0 71 | while(textContent.charAt(textContent.length - (numberOfTrailingNewlines + 1)) == '\n') { 72 | numberOfTrailingNewlines++; 73 | } 74 | textContent = textContent.substring(0, textContent.length - numberOfTrailingNewlines) 75 | navigator.clipboard.writeText(textContent); 76 | this.classList.add("success") 77 | this.innerHTML = DoxygenAwesomeFragmentCopyButton.successIcon 78 | window.setTimeout(() => { 79 | this.classList.remove("success") 80 | this.innerHTML = DoxygenAwesomeFragmentCopyButton.copyIcon 81 | }, DoxygenAwesomeFragmentCopyButton.successDuration); 82 | } 83 | } 84 | 85 | customElements.define("doxygen-awesome-fragment-copy-button", DoxygenAwesomeFragmentCopyButton) 86 | -------------------------------------------------------------------------------- /docs/doxygen/doxygen-awesome-css/doxygen-awesome-interactive-toc.js: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | Doxygen Awesome 4 | https://github.com/jothepro/doxygen-awesome-css 5 | 6 | MIT License 7 | 8 | Copyright (c) 2022 - 2023 jothepro 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all 18 | copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | 28 | */ 29 | 30 | class DoxygenAwesomeInteractiveToc { 31 | static topOffset = 38 32 | static hideMobileMenu = true 33 | static headers = [] 34 | 35 | static init() { 36 | window.addEventListener("load", () => { 37 | let toc = document.querySelector(".contents > .toc") 38 | if(toc) { 39 | toc.classList.add("interactive") 40 | if(!DoxygenAwesomeInteractiveToc.hideMobileMenu) { 41 | toc.classList.add("open") 42 | } 43 | document.querySelector(".contents > .toc > h3")?.addEventListener("click", () => { 44 | if(toc.classList.contains("open")) { 45 | toc.classList.remove("open") 46 | } else { 47 | toc.classList.add("open") 48 | } 49 | }) 50 | 51 | document.querySelectorAll(".contents > .toc > ul a").forEach((node) => { 52 | let id = node.getAttribute("href").substring(1) 53 | DoxygenAwesomeInteractiveToc.headers.push({ 54 | node: node, 55 | headerNode: document.getElementById(id) 56 | }) 57 | 58 | document.getElementById("doc-content")?.addEventListener("scroll", () => { 59 | DoxygenAwesomeInteractiveToc.update() 60 | }) 61 | }) 62 | DoxygenAwesomeInteractiveToc.update() 63 | } 64 | }) 65 | } 66 | 67 | static update() { 68 | let active = DoxygenAwesomeInteractiveToc.headers[0]?.node 69 | DoxygenAwesomeInteractiveToc.headers.forEach((header) => { 70 | let position = header.headerNode.getBoundingClientRect().top 71 | header.node.classList.remove("active") 72 | header.node.classList.remove("aboveActive") 73 | if(position < DoxygenAwesomeInteractiveToc.topOffset) { 74 | active = header.node 75 | active?.classList.add("aboveActive") 76 | } 77 | }) 78 | active?.classList.add("active") 79 | active?.classList.remove("aboveActive") 80 | } 81 | } -------------------------------------------------------------------------------- /docs/doxygen/doxygen-awesome-css/doxygen-awesome-paragraph-link.js: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | Doxygen Awesome 4 | https://github.com/jothepro/doxygen-awesome-css 5 | 6 | MIT License 7 | 8 | Copyright (c) 2022 - 2023 jothepro 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all 18 | copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | 28 | */ 29 | 30 | class DoxygenAwesomeParagraphLink { 31 | // Icon from https://fonts.google.com/icons 32 | // Licensed under the Apache 2.0 license: 33 | // https://www.apache.org/licenses/LICENSE-2.0.html 34 | static icon = `` 35 | static title = "Permanent Link" 36 | static init() { 37 | $(function() { 38 | $(document).ready(function() { 39 | document.querySelectorAll(".contents a.anchor[id], .contents .groupheader > a[id]").forEach((node) => { 40 | let anchorlink = document.createElement("a") 41 | anchorlink.setAttribute("href", `#${node.getAttribute("id")}`) 42 | anchorlink.setAttribute("title", DoxygenAwesomeParagraphLink.title) 43 | anchorlink.classList.add("anchorlink") 44 | node.classList.add("anchor") 45 | anchorlink.innerHTML = DoxygenAwesomeParagraphLink.icon 46 | node.parentElement.appendChild(anchorlink) 47 | }) 48 | }) 49 | }) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /docs/doxygen/doxygen-awesome-css/doxygen-awesome-sidebar-only-darkmode-toggle.css: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | 4 | Doxygen Awesome 5 | https://github.com/jothepro/doxygen-awesome-css 6 | 7 | MIT License 8 | 9 | Copyright (c) 2021 - 2023 jothepro 10 | 11 | Permission is hereby granted, free of charge, to any person obtaining a copy 12 | of this software and associated documentation files (the "Software"), to deal 13 | in the Software without restriction, including without limitation the rights 14 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | copies of the Software, and to permit persons to whom the Software is 16 | furnished to do so, subject to the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be included in all 19 | copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | SOFTWARE. 28 | 29 | */ 30 | 31 | @media screen and (min-width: 768px) { 32 | 33 | #MSearchBox { 34 | width: calc(var(--side-nav-fixed-width) - calc(2 * var(--spacing-medium)) - var(--searchbar-height) - 1px); 35 | } 36 | 37 | #MSearchField { 38 | width: calc(var(--side-nav-fixed-width) - calc(2 * var(--spacing-medium)) - 66px - var(--searchbar-height)); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /docs/doxygen/doxygen-awesome-css/doxygen-awesome-sidebar-only.css: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | Doxygen Awesome 4 | https://github.com/jothepro/doxygen-awesome-css 5 | 6 | MIT License 7 | 8 | Copyright (c) 2021 - 2023 jothepro 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all 18 | copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | 28 | */ 29 | 30 | html { 31 | /* side nav width. MUST be = `TREEVIEW_WIDTH`. 32 | * Make sure it is wide enough to contain the page title (logo + title + version) 33 | */ 34 | --side-nav-fixed-width: 335px; 35 | --menu-display: none; 36 | 37 | --top-height: 120px; 38 | --toc-sticky-top: -25px; 39 | --toc-max-height: calc(100vh - 2 * var(--spacing-medium) - 25px); 40 | } 41 | 42 | #projectname { 43 | white-space: nowrap; 44 | } 45 | 46 | 47 | @media screen and (min-width: 768px) { 48 | html { 49 | --searchbar-background: var(--page-background-color); 50 | } 51 | 52 | #side-nav { 53 | min-width: var(--side-nav-fixed-width); 54 | max-width: var(--side-nav-fixed-width); 55 | top: var(--top-height); 56 | overflow: visible; 57 | } 58 | 59 | #nav-tree, #side-nav { 60 | height: calc(100vh - var(--top-height)) !important; 61 | } 62 | 63 | #nav-tree { 64 | padding: 0; 65 | } 66 | 67 | #top { 68 | display: block; 69 | border-bottom: none; 70 | height: var(--top-height); 71 | margin-bottom: calc(0px - var(--top-height)); 72 | max-width: var(--side-nav-fixed-width); 73 | overflow: hidden; 74 | background: var(--side-nav-background); 75 | } 76 | #main-nav { 77 | float: left; 78 | padding-right: 0; 79 | } 80 | 81 | .ui-resizable-handle { 82 | cursor: default; 83 | width: 1px !important; 84 | background: var(--separator-color); 85 | box-shadow: 0 calc(-2 * var(--top-height)) 0 0 var(--separator-color); 86 | } 87 | 88 | #nav-path { 89 | position: fixed; 90 | right: 0; 91 | left: var(--side-nav-fixed-width); 92 | bottom: 0; 93 | width: auto; 94 | } 95 | 96 | #doc-content { 97 | height: calc(100vh - 31px) !important; 98 | padding-bottom: calc(3 * var(--spacing-large)); 99 | padding-top: calc(var(--top-height) - 80px); 100 | box-sizing: border-box; 101 | margin-left: var(--side-nav-fixed-width) !important; 102 | } 103 | 104 | #MSearchBox { 105 | width: calc(var(--side-nav-fixed-width) - calc(2 * var(--spacing-medium))); 106 | } 107 | 108 | #MSearchField { 109 | width: calc(var(--side-nav-fixed-width) - calc(2 * var(--spacing-medium)) - 65px); 110 | } 111 | 112 | #MSearchResultsWindow { 113 | left: var(--spacing-medium) !important; 114 | right: auto; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /docs/doxygen/doxygen-awesome-css/doxygen-awesome-tabs.js: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | Doxygen Awesome 4 | https://github.com/jothepro/doxygen-awesome-css 5 | 6 | MIT License 7 | 8 | Copyright (c) 2023 jothepro 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all 18 | copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | 28 | */ 29 | 30 | class DoxygenAwesomeTabs { 31 | 32 | static init() { 33 | window.addEventListener("load", () => { 34 | document.querySelectorAll(".tabbed:not(:empty)").forEach((tabbed, tabbedIndex) => { 35 | let tabLinkList = [] 36 | tabbed.querySelectorAll(":scope > ul > li").forEach((tab, tabIndex) => { 37 | tab.id = "tab_" + tabbedIndex + "_" + tabIndex 38 | let header = tab.querySelector(".tab-title") 39 | let tabLink = document.createElement("button") 40 | tabLink.classList.add("tab-button") 41 | tabLink.appendChild(header) 42 | header.title = header.textContent 43 | tabLink.addEventListener("click", () => { 44 | tabbed.querySelectorAll(":scope > ul > li").forEach((tab) => { 45 | tab.classList.remove("selected") 46 | }) 47 | tabLinkList.forEach((tabLink) => { 48 | tabLink.classList.remove("active") 49 | }) 50 | tab.classList.add("selected") 51 | tabLink.classList.add("active") 52 | }) 53 | tabLinkList.push(tabLink) 54 | if(tabIndex == 0) { 55 | tab.classList.add("selected") 56 | tabLink.classList.add("active") 57 | } 58 | }) 59 | let tabsOverview = document.createElement("div") 60 | tabsOverview.classList.add("tabs-overview") 61 | let tabsOverviewContainer = document.createElement("div") 62 | tabsOverviewContainer.classList.add("tabs-overview-container") 63 | tabLinkList.forEach((tabLink) => { 64 | tabsOverview.appendChild(tabLink) 65 | }) 66 | tabsOverviewContainer.appendChild(tabsOverview) 67 | tabbed.before(tabsOverviewContainer) 68 | 69 | function resize() { 70 | let maxTabHeight = 0 71 | tabbed.querySelectorAll(":scope > ul > li").forEach((tab, tabIndex) => { 72 | let visibility = tab.style.display 73 | tab.style.display = "block" 74 | maxTabHeight = Math.max(tab.offsetHeight, maxTabHeight) 75 | tab.style.display = visibility 76 | }) 77 | tabbed.style.height = `${maxTabHeight + 10}px` 78 | } 79 | 80 | resize() 81 | new ResizeObserver(resize).observe(tabbed) 82 | }) 83 | }) 84 | 85 | } 86 | 87 | static resize(tabbed) { 88 | 89 | } 90 | } -------------------------------------------------------------------------------- /docs/doxygen/doxygen-awesome-css/doxygen-custom/custom-alternative.css: -------------------------------------------------------------------------------- 1 | html.alternative { 2 | /* primary theme color. This will affect the entire websites color scheme: links, arrows, labels, ... */ 3 | --primary-color: #AF7FE4; 4 | --primary-dark-color: #9270E4; 5 | --primary-light-color: #7aabd6; 6 | --primary-lighter-color: #cae1f1; 7 | --primary-lightest-color: #e9f1f8; 8 | 9 | /* page base colors */ 10 | --page-background-color: white; 11 | --page-foreground-color: #2c3e50; 12 | --page-secondary-foreground-color: #67727e; 13 | 14 | 15 | --border-radius-large: 22px; 16 | --border-radius-small: 9px; 17 | --border-radius-medium: 14px; 18 | --spacing-small: 8px; 19 | --spacing-medium: 14px; 20 | --spacing-large: 19px; 21 | 22 | --top-height: 125px; 23 | 24 | --side-nav-background: #324067; 25 | --side-nav-foreground: #F1FDFF; 26 | --header-foreground: var(--side-nav-foreground); 27 | --searchbar-background: var(--side-nav-foreground); 28 | --searchbar-border-radius: var(--border-radius-medium); 29 | --header-background: var(--side-nav-background); 30 | --header-foreground: var(--side-nav-foreground); 31 | 32 | --toc-background: rgb(243, 240, 252); 33 | --toc-foreground: var(--page-foreground-color); 34 | } 35 | 36 | html.alternative.dark-mode { 37 | color-scheme: dark; 38 | 39 | --primary-color: #AF7FE4; 40 | --primary-dark-color: #9270E4; 41 | --primary-light-color: #4779ac; 42 | --primary-lighter-color: #191e21; 43 | --primary-lightest-color: #191a1c; 44 | 45 | --page-background-color: #1C1D1F; 46 | --page-foreground-color: #d2dbde; 47 | --page-secondary-foreground-color: #859399; 48 | --separator-color: #3a3246; 49 | --side-nav-background: #171D32; 50 | --side-nav-foreground: #F1FDFF; 51 | --toc-background: #20142C; 52 | --searchbar-background: var(--page-background-color); 53 | 54 | } -------------------------------------------------------------------------------- /docs/doxygen/doxygen-awesome-css/doxygen-custom/custom.css: -------------------------------------------------------------------------------- 1 | .github-corner svg { 2 | fill: var(--primary-light-color); 3 | color: var(--page-background-color); 4 | width: 72px; 5 | height: 72px; 6 | } 7 | 8 | @media screen and (max-width: 767px) { 9 | .github-corner svg { 10 | width: 50px; 11 | height: 50px; 12 | } 13 | #projectnumber { 14 | margin-right: 22px; 15 | } 16 | } 17 | 18 | .alter-theme-button { 19 | display: inline-block; 20 | cursor: pointer; 21 | background: var(--primary-color); 22 | color: var(--page-background-color) !important; 23 | border-radius: var(--border-radius-medium); 24 | padding: var(--spacing-small) var(--spacing-medium); 25 | text-decoration: none; 26 | } 27 | 28 | .alter-theme-button:hover { 29 | background: var(--primary-dark-color); 30 | } 31 | 32 | html.dark-mode .darkmode_inverted_image img, /* < doxygen 1.9.3 */ 33 | html.dark-mode .darkmode_inverted_image object[type="image/svg+xml"] /* doxygen 1.9.3 */ { 34 | filter: brightness(89%) hue-rotate(180deg) invert(); 35 | } 36 | 37 | .bordered_image { 38 | border-radius: var(--border-radius-small); 39 | border: 1px solid var(--separator-color); 40 | display: inline-block; 41 | overflow: hidden; 42 | } 43 | 44 | html.dark-mode .bordered_image img, /* < doxygen 1.9.3 */ 45 | html.dark-mode .bordered_image object[type="image/svg+xml"] /* doxygen 1.9.3 */ { 46 | border-radius: var(--border-radius-small); 47 | } 48 | 49 | .title_screenshot { 50 | filter: drop-shadow(0px 3px 10px rgba(0,0,0,0.22)); 51 | max-width: 500px; 52 | margin: var(--spacing-large) 0; 53 | } 54 | 55 | .title_screenshot .caption { 56 | display: none; 57 | } 58 | -------------------------------------------------------------------------------- /docs/doxygen/doxygen-awesome-css/doxygen-custom/header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | $projectname: $title 23 | $title 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 41 | $treeview 42 | $search 43 | $mathjax 44 | 45 | $extrastylesheet 46 | 47 | 48 | 49 | 50 | 51 | 53 | 54 | 55 |
56 | 57 | 58 |
59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 72 | 73 | 74 | 75 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 |
67 |
$projectname 68 |  $projectnumber 69 |
70 |
$projectbrief
71 |
76 |
$projectbrief
77 |
$searchbox
88 |
89 | 90 | 91 | -------------------------------------------------------------------------------- /docs/doxygen/doxygen-awesome-css/doxygen-custom/toggle-alternative-theme.js: -------------------------------------------------------------------------------- 1 | 2 | let original_theme_active = true; 3 | 4 | function toggle_alternative_theme() { 5 | if(original_theme_active) { 6 | document.documentElement.classList.add("alternative") 7 | original_theme_active = false; 8 | } else { 9 | document.documentElement.classList.remove("alternative") 10 | original_theme_active = true; 11 | } 12 | } -------------------------------------------------------------------------------- /docs/doxygen/doxygen-awesome-css/img/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sparkfun/qwiic_bme280_py/c4576cc1450ffecff64535b7948d509ac690127d/docs/doxygen/doxygen-awesome-css/img/screenshot.png -------------------------------------------------------------------------------- /docs/doxygen/doxygen-awesome-css/img/testimage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sparkfun/qwiic_bme280_py/c4576cc1450ffecff64535b7948d509ac690127d/docs/doxygen/doxygen-awesome-css/img/testimage.png -------------------------------------------------------------------------------- /docs/doxygen/doxygen-awesome-css/img/theme-variants-base.drawio.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 |
11 |
12 | Content 13 |
14 |
15 |
16 |
17 | 18 | Content 19 | 20 |
21 |
22 | 23 | 24 | 25 | 26 |
27 |
28 |
29 | Titlebar (Navigation + Search) 30 |
31 |
32 |
33 |
34 | 35 | Titlebar (Navigation + Search) 36 | 37 |
38 |
39 | 40 | 41 | 42 | 43 |
44 |
45 |
46 | Sidebar (Navigation) 47 |
48 |
49 |
50 |
51 | 52 | Sidebar (Navigation) 53 | 54 |
55 |
56 | 57 | 58 | 59 | 60 |
61 |
62 |
63 | Footer (Breadcrumps) 64 |
65 |
66 |
67 |
68 | 69 | Footer (Breadcrumps) 70 | 71 |
72 |
73 | 74 | 75 | 76 | 77 |
78 |
79 |
80 | Search 81 |
82 |
83 |
84 |
85 | 86 | Search 87 | 88 |
89 |
90 | 91 | 92 | 93 |
94 |
95 |
96 | 97 | Title 98 | 99 |
100 |
101 |
102 |
103 | 104 | Tit... 105 | 106 |
107 |
108 |
109 | 110 | 111 | 112 | 113 | Text is not SVG - cannot display 114 | 115 | 116 | 117 |
-------------------------------------------------------------------------------- /docs/doxygen/doxygen-awesome-css/img/theme-variants-sidebar-only.drawio.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 |
11 |
12 | Content 13 |
14 |
15 |
16 |
17 | 18 | Content 19 | 20 |
21 |
22 | 23 | 24 | 25 | 26 |
27 |
28 |
29 | Sidebar 30 |
31 | (Title + Navigation) 32 |
33 |
34 |
35 |
36 | 37 | Sidebar... 38 | 39 |
40 |
41 | 42 | 43 | 44 | 45 |
46 |
47 |
48 | Footer (Breadcrumps) 49 |
50 |
51 |
52 |
53 | 54 | Footer (Breadcrumps) 55 | 56 |
57 |
58 | 59 | 60 | 61 | 62 |
63 |
64 |
65 | Search 66 |
67 |
68 |
69 |
70 | 71 | Search 72 | 73 |
74 |
75 | 76 | 77 | 78 |
79 |
80 |
81 | 82 | Title 83 | 84 |
85 |
86 |
87 |
88 | 89 | Tit... 90 | 91 |
92 |
93 |
94 | 95 | 96 | 97 | 98 | Text is not SVG - cannot display 99 | 100 | 101 | 102 |
-------------------------------------------------------------------------------- /docs/doxygen/doxygen-awesome-css/include/MyLibrary/example.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace MyLibrary { 5 | 6 | enum Color { red, green, blue }; 7 | 8 | /** 9 | * @brief Example class to demonstrate the features of the custom CSS. 10 | * 11 | * @author jothepro 12 | * 13 | */ 14 | class Example { 15 | public: 16 | /** 17 | * @brief brief summary 18 | * 19 | * doxygen test documentation 20 | * 21 | * @param test this is the only parameter of this test function. It does nothing! 22 | * 23 | * # Supported elements 24 | * 25 | * These elements have been tested with the custom CSS. 26 | * 27 | * ## Tables 28 | * 29 | *
30 | * 31 | * - Basic 32 | * This theme supports normal markdown tables:
33 | * | Item | Title | Description | More | 34 | * |-----:|-------|-----------------------|--------------------------------------------| 35 | * | 1 | Foo | A placeholder | Some lorem ipsum to make this table wider. | 36 | * | 2 | Bar | Also a placeholder | More lorem ipsum. | 37 | * | 3 | Baz | The third placeholder | More lorem ipsum. | 38 | * - Centered 39 | *
40 | * A table can be centered with the `
` html tag:
41 | * | Item | Title | Description | More | 42 | * |-----:|-------|-----------------------|--------------------------------------------| 43 | * | 1 | Foo | A placeholder | Some lorem ipsum to make this table wider. | 44 | * | 2 | Bar | Also a placeholder | More lorem ipsum. | 45 | * | 3 | Baz | The third placeholder | More lorem ipsum. | 46 | *
47 | * - Stretched 48 | * A table wrapped in `
` fills the full page width. 49 | *
50 | * | Item | Title | Description | More | 51 | * |-----:|-------|-----------------------|--------------------------------------------| 52 | * | 1 | Foo | A placeholder | Some lorem ipsum to make this table wider. | 53 | * | 2 | Bar | Also a placeholder | More lorem ipsum. | 54 | * | 3 | Baz | The third placeholder | More lorem ipsum. | 55 | *
56 | * **Caution**: This will break the overflow scrolling support! 57 | * - Complex 58 | * Complex [Doxygen tables](https://www.doxygen.nl/manual/tables.html) are also supported as seen in @ref multi_row "this example":
59 | * 60 | * 61 | *
Complex table
Column 1 Column 2 Column 3 62 | *
cell row=1+2,col=1cell row=1,col=2cell row=1,col=3 63 | *
cell row=2+3,col=2 cell row=2,col=3 64 | *
cell row=3,col=1 cell row=3,col=3 65 | *
66 | * - Overflow Scrolling The table content is scrollable if the table gets too wide.
67 | * | first_column | second_column | third_column | fourth_column | fifth_column | sixth_column | seventh_column | eighth_column | ninth_column | 68 | * |--------------|---------------|--------------|---------------|--------------|--------------|----------------|---------------|--------------| 69 | * | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 70 | * - ImagesA table can contain images:
71 | * | Column 1 | Column 2 | 72 | * |---------------------------|-------------------------------------------------| 73 | * | ![doxygen](testimage.png) | ← the image should not be inverted in dark-mode | 74 | * 75 | * 76 | *
77 | * 78 | * ## Diagrams 79 | * 80 | * Graphviz diagrams support dark mode and can be scrolled once they get too wide: 81 | * 82 | * \dot Graphviz with a caption 83 | * digraph example { 84 | * node [fontsize="12"]; 85 | * rankdir="LR" 86 | * a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k; 87 | * } 88 | * \enddot 89 | * 90 | * ## Lists 91 | * 92 | * - element 1 93 | * - element 2 94 | * 95 | * 1. element 1 96 | * ``` 97 | * code in lists 98 | * ``` 99 | * 2. element 2 100 | * 101 | * ## Quotes 102 | * 103 | * > Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt 104 | * > ut labore et dolore magna aliqua. Vitae proin sagittis nisl rhoncus mattis rhoncus urna neque viverra. 105 | * > Velit sed ullamcorper morbi tincidunt ornare. 106 | * > 107 | * > Lorem ipsum dolor sit amet consectetur adipiscing elit duis. 108 | * *- jothepro* 109 | * 110 | * ## Code block 111 | * 112 | * ```cpp 113 | * auto x = "code within md fences"; 114 | * ``` 115 | * 116 | * @code{.cpp} 117 | * // code within @code block 118 | * while(true) { 119 | * auto example = std::make_shared(5); 120 | * example->test("test"); 121 | * } 122 | * @endcode 123 | * 124 | * // code within indented code block 125 | * auto test = std::shared_ptr 3 | #include "example.hpp" 4 | #include 5 | 6 | namespace MyLibrary { 7 | 8 | /** 9 | * @brief some subclass 10 | */ 11 | template 12 | class SubclassExample : public Example { 13 | public: 14 | 15 | /** 16 | * @bug second bug 17 | * @return 18 | */ 19 | int virtualfunc() override; 20 | 21 | /** 22 | * @brief Template function function 23 | */ 24 | template 25 | std::shared_ptr function_template_test(std::shared_ptr& param); 26 | 27 | /** 28 | * @brief Extra long function with lots of parameters and many template types. 29 | * 30 | * Also has a long return type. 31 | * 32 | * @param param1 first parameter 33 | * @param param2 second parameter 34 | * @param parameter3 third parameter 35 | */ 36 | template 37 | std::pair long_function_with_many_parameters(std::shared_ptr& param1, std::shared_ptr& param2, bool parameter3, Alice paramater4 Bob parameter 5) { 38 | if(true) { 39 | std::cout << "this even has some code." << std::endl; 40 | } 41 | } 42 | 43 | }; 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /docs/doxygen/doxygen-awesome-css/logo.drawio.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/doxygen/doxygen-awesome-css/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@jothepro/doxygen-awesome-css", 3 | "version": "2.3.2", 4 | "description": "Custom CSS theme for doxygen html-documentation with lots of customization parameters.", 5 | "main": "", 6 | "scripts": { 7 | "npm-pack": "npm pack", 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "https://github.com/jothepro/doxygen-awesome-css.git" 13 | }, 14 | "homepage": "https://jothepro.github.io/doxygen-awesome-css/", 15 | "bugs": { 16 | "url": "https://github.com/jothepro/doxygen-awesome-css/issues" 17 | }, 18 | "keywords": [ 19 | "doxygen", 20 | "css", 21 | "theme", 22 | "awesome" 23 | ], 24 | "author": { 25 | "name": "jothepro", 26 | "url": "https://github.com/jothepro", 27 | "git": "https://github.com/jothepro/doxygen-awesome-css" 28 | }, 29 | "license": "MIT", 30 | "config": {}, 31 | "dependencies": {}, 32 | "devDependencies": {}, 33 | "xpack": {} 34 | } 35 | -------------------------------------------------------------------------------- /docs/doxygen/doxygen-custom/custom.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --side-nav-fixed-width: 300px; 3 | } 4 | 5 | .github-corner svg { 6 | fill: var(--primary-light-color); 7 | color: var(--page-background-color); 8 | width: 72px; 9 | height: 72px; 10 | } 11 | 12 | #projectnumber { 13 | margin-right: 22px; 14 | } 15 | 16 | @media screen and (max-width: 767px) { 17 | .github-corner svg { 18 | width: 55px; 19 | height: 55px; 20 | } 21 | } -------------------------------------------------------------------------------- /docs/doxygen/doxygen-custom/header.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | $projectname: $title 25 | 26 | $title 27 | 28 | 29 | 30 | 31 | $treeview 32 | $search 33 | $mathjax 34 | 35 | $extrastylesheet 36 | 37 | 38 | 39 | 40 | 41 | 42 | 51 | 84 | 85 | 86 |
87 | 88 | 89 |
90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 105 | 106 | 107 | 108 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 |
98 |
$projectname 99 |  $projectnumber 101 |
102 | 103 |
$projectbrief
104 |
109 |
$projectbrief
110 |
$searchbox
121 |
122 | 123 | -------------------------------------------------------------------------------- /docs/images/bme280-gh-banner-py.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sparkfun/qwiic_bme280_py/c4576cc1450ffecff64535b7948d509ac690127d/docs/images/bme280-gh-banner-py.png -------------------------------------------------------------------------------- /docs/images/sfe_flame.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sparkfun/qwiic_bme280_py/c4576cc1450ffecff64535b7948d509ac690127d/docs/images/sfe_flame.png -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | m2r 2 | sparkfun-qwiic-i2c 3 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # Sparkfun BME280 Examples Reference 2 | Below is a brief summary of each of the example programs included in this repository. To report a bug in any of these examples or to request a new feature or example [submit an issue in our GitHub issues.](https://github.com/sparkfun/qwiic_bme280_py/issues). 3 | 4 | NOTE: The abnormal numbering of examples is to retain consistency with the Arduino library from which this was ported. 5 | 6 | ## Example 1: Basic Readings 7 | This example demonstrates basic bringup of the BME280 to extract humidity, pressure, altitude, and temperature. 8 | 9 | The key methods showcased by this example are: 10 | 11 | - [read_humidity()](https://docs.sparkfun.com/qwiic_bme280_py/classqwiic__bme280_1_1_qwiic_bme280.html#a601d62c86ef837f61c3e452a3f390b9d) 12 | - [read_pressure()](https://docs.sparkfun.com/qwiic_bme280_py/classqwiic__bme280_1_1_qwiic_bme280.html#af799265b51181bd65cae6983c245c513) 13 | - [get_altitude_feet()](https://docs.sparkfun.com/qwiic_bme280_py/classqwiic__bme280_1_1_qwiic_bme280.html#af5b0a1f1c2355f72d2182ed0c036ef8e) 14 | - [get_temperature_fahrenheit()](https://docs.sparkfun.com/qwiic_bme280_py/classqwiic__bme280_1_1_qwiic_bme280.html#a31603e97db007558964618800b055a61) 15 | 16 | These methods are invoked via reading their corresponding properties([humidity](https://docs.sparkfun.com/qwiic_bme280_py/classqwiic__bme280_1_1_qwiic_bme280.html#ace5c02deec66d7096a322f68bd19e35d), [pressure](https://docs.sparkfun.com/qwiic_bme280_py/classqwiic__bme280_1_1_qwiic_bme280.html#a169132f58174ba65b2ef1148858a93f7), [altitude_feet](https://docs.sparkfun.com/qwiic_bme280_py/classqwiic__bme280_1_1_qwiic_bme280.html#aa6b842360817379f6c9026767b4c51cb), and [temperature_fahrenheit](https://docs.sparkfun.com/qwiic_bme280_py/classqwiic__bme280_1_1_qwiic_bme280.html#a42eb4ab7f10b8188d9174384feb2e328)) 17 | 18 | ## Example 4: Settings 19 | This example shows how to change the various filter and oversample settings of the BME280. It sets several filtering and oversampling settings and then performs the same readings as in Example 1. 20 | 21 | The key methods showcased by this example are: 22 | 23 | - [set_filter()](https://docs.sparkfun.com/qwiic_bme280_py/classqwiic__bme280_1_1_qwiic_bme280.html#a5f32790df30c3c23c82b2aa2f43fc378) 24 | - [set_standby_time()](https://docs.sparkfun.com/qwiic_bme280_py/classqwiic__bme280_1_1_qwiic_bme280.html#ac92bbaf17893b45805678d05af28cff8) 25 | - [set_tempature_oversample()](https://docs.sparkfun.com/qwiic_bme280_py/classqwiic__bme280_1_1_qwiic_bme280.html#a4cb331d973e88bb6e85c03ead63b042f) 26 | - [set_humidity_oversample()](https://docs.sparkfun.com/qwiic_bme280_py/classqwiic__bme280_1_1_qwiic_bme280.html#a510a98a4a15cdf4d634aaacfbde6139c) 27 | - [set_mode()](https://docs.sparkfun.com/qwiic_bme280_py/classqwiic__bme280_1_1_qwiic_bme280.html#a4cb378ab043d8dfa7c3c6c48e19bab84) 28 | 29 | These methods are invoked via reading their corresponding properties ([filter](https://docs.sparkfun.com/qwiic_bme280_py/classqwiic__bme280_1_1_qwiic_bme280.html#abd7049904b69e17438de6c1bfad899b4), [standby_time](https://docs.sparkfun.com/qwiic_bme280_py/classqwiic__bme280_1_1_qwiic_bme280.html#a16991516b62efcb3400ce1a6ead3f8a3), [tempature_oversample](https://docs.sparkfun.com/qwiic_bme280_py/classqwiic__bme280_1_1_qwiic_bme280.html#aaa2c92f61e6c0360c2d480074ed73b3a), [humidity_oversample](https://docs.sparkfun.com/qwiic_bme280_py/classqwiic__bme280_1_1_qwiic_bme280.html#a7b7bf88a522fced77db96301b5fced51), [mode](https://docs.sparkfun.com/qwiic_bme280_py/classqwiic__bme280_1_1_qwiic_bme280.html#aec55ad7625fa470e5f7f4d0e415ec96e)) 30 | 31 | ## Example 5: Read All Registers 32 | This example configures the BME280 to read all measurements. It also displays the BME280's physical memory and what the driver perceives the calibration words to be. 33 | 34 | This method showcases direct I2C reads as well as the use of the [calibration property](https://docs.sparkfun.com/qwiic_bme280_py/classqwiic__bme280_1_1_qwiic_bme280.html#a61ff5a498e96023a6c82cb99ca6a093b) -------------------------------------------------------------------------------- /examples/qwiic_bme280_ex1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #----------------------------------------------------------------------------- 3 | # qwiic_env_bme280_ex1.py 4 | # 5 | # Simple Example for the Qwiic BME280 Device 6 | #------------------------------------------------------------------------ 7 | # 8 | # Written by SparkFun Electronics, May 2019 9 | # 10 | # This python library supports the SparkFun Electroncis qwiic 11 | # qwiic sensor/board ecosystem on a Raspberry Pi (and compatable) single 12 | # board computers. 13 | # 14 | # More information on qwiic is at https://www.sparkfun.com/qwiic 15 | # 16 | # Do you like this library? Help support SparkFun. Buy a board! 17 | # 18 | #================================================================================== 19 | # Copyright (c) 2019 SparkFun Electronics 20 | # 21 | # Permission is hereby granted, free of charge, to any person obtaining a copy 22 | # of this software and associated documentation files (the "Software"), to deal 23 | # in the Software without restriction, including without limitation the rights 24 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 25 | # copies of the Software, and to permit persons to whom the Software is 26 | # furnished to do so, subject to the following conditions: 27 | # 28 | # The above copyright notice and this permission notice shall be included in all 29 | # copies or substantial portions of the Software. 30 | # 31 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 32 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 33 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 34 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 35 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 36 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 37 | # SOFTWARE. 38 | #================================================================================== 39 | # Example 1 40 | # 41 | 42 | import qwiic_bme280 43 | import time 44 | import sys 45 | 46 | def runExample(): 47 | 48 | print("\nSparkFun BME280 Sensor Example 1\n") 49 | mySensor = qwiic_bme280.QwiicBme280() 50 | 51 | if mySensor.connected == False: 52 | print("The Qwiic BME280 device isn't connected to the system. Please check your connection", \ 53 | file=sys.stderr) 54 | return 55 | 56 | mySensor.begin() 57 | 58 | while True: 59 | print("Humidity:\t%.3f" % mySensor.humidity) 60 | 61 | print("Pressure:\t%.3f" % mySensor.pressure) 62 | 63 | print("Altitude:\t%.3f" % mySensor.altitude_feet) 64 | 65 | print("Temperature:\t%.2f" % mySensor.temperature_fahrenheit) 66 | 67 | print("") 68 | 69 | time.sleep(1) 70 | 71 | 72 | if __name__ == '__main__': 73 | try: 74 | runExample() 75 | except (KeyboardInterrupt, SystemExit) as exErr: 76 | print("\nEnding Example 1") 77 | sys.exit(0) 78 | 79 | 80 | -------------------------------------------------------------------------------- /examples/qwiic_bme280_ex4.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #----------------------------------------------------------------------------- 3 | # qwiic_env_bme280_ex4.py 4 | # 5 | # Simple Example for the Qwiic BME280 Device 6 | #------------------------------------------------------------------------ 7 | # 8 | # Written by SparkFun Electronics, May 2019 9 | # 10 | # This python library supports the SparkFun Electroncis qwiic 11 | # qwiic sensor/board ecosystem on a Raspberry Pi (and compatable) single 12 | # board computers. 13 | # 14 | # More information on qwiic is at https:# www.sparkfun.com/qwiic 15 | # 16 | # Do you like this library? Help support SparkFun. Buy a board! 17 | # 18 | #================================================================================== 19 | # Copyright (c) 2019 SparkFun Electronics 20 | # 21 | # Permission is hereby granted, free of charge, to any person obtaining a copy 22 | # of this software and associated documentation files (the "Software"), to deal 23 | # in the Software without restriction, including without limitation the rights 24 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 25 | # copies of the Software, and to permit persons to whom the Software is 26 | # furnished to do so, subject to the following conditions: 27 | # 28 | # The above copyright notice and this permission notice shall be included in all 29 | # copies or substantial portions of the Software. 30 | # 31 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 32 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 33 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 34 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 35 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 36 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 37 | # SOFTWARE. 38 | #================================================================================== 39 | # Example 4 - port of the Arduino example 4 40 | # 41 | 42 | import qwiic_bme280 43 | import time 44 | import sys 45 | 46 | def runExample(): 47 | 48 | print("\nSparkFun BME280 Sensor Example 4\n") 49 | mySensor = qwiic_bme280.QwiicBme280() 50 | 51 | if mySensor.connected == False: 52 | print("The Qwiic BME280 device isn't connected to the system. Please check your connection", \ 53 | file=sys.stderr) 54 | return 55 | 56 | mySensor.begin() 57 | 58 | # setup the sensor 59 | mySensor.filter = 1 # 0 to 4 is valid. Filter coefficient. See 3.4.4 60 | mySensor.standby_time = 0 # 0 to 7 valid. Time between readings. See table 27. 61 | 62 | mySensor.tempature_oversample = 1 # 0 to 16 are valid. 0 disables temp sensing. See table 24. 63 | mySensor.pressure_oversample = 1 # 0 to 16 are valid. 0 disables pressure sensing. See table 23. 64 | mySensor.humidity_oversample = 1 # 0 to 16 are valid. 0 disables humidity sensing. See table 19. 65 | mySensor.mode = mySensor.MODE_NORMAL # MODE_SLEEP, MODE_FORCED, MODE_NORMAL is valid. See 3.3 66 | 67 | while True: 68 | print("Humidity:\t%.3f" % mySensor.humidity) 69 | 70 | print("Pressure:\t%.3f" % mySensor.pressure) 71 | 72 | print("Altitude:\t%.3f" % mySensor.altitude_feet) 73 | 74 | print("Temperature:\t%.2f\n" % mySensor.temperature_fahrenheit) 75 | 76 | time.sleep(1) 77 | 78 | 79 | if __name__ == '__main__': 80 | try: 81 | runExample() 82 | except (KeyboardInterrupt, SystemExit) as exErr: 83 | print("\nEnding Example 4") 84 | sys.exit(0) 85 | 86 | 87 | -------------------------------------------------------------------------------- /examples/qwiic_bme280_ex5.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #----------------------------------------------------------------------------- 3 | # qwiic_env_bme280_ex5.py 4 | # 5 | # Simple Example for the Qwiic BME280 Device 6 | #------------------------------------------------------------------------ 7 | # 8 | # Written by SparkFun Electronics, May 2019 9 | # 10 | # This python library supports the SparkFun Electroncis qwiic 11 | # qwiic sensor/board ecosystem on a Raspberry Pi (and compatable) single 12 | # board computers. 13 | # 14 | # More information on qwiic is at https:# www.sparkfun.com/qwiic 15 | # 16 | # Do you like this library? Help support SparkFun. Buy a board! 17 | # 18 | #================================================================================== 19 | # Copyright (c) 2019 SparkFun Electronics 20 | # 21 | # Permission is hereby granted, free of charge, to any person obtaining a copy 22 | # of this software and associated documentation files (the "Software"), to deal 23 | # in the Software without restriction, including without limitation the rights 24 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 25 | # copies of the Software, and to permit persons to whom the Software is 26 | # furnished to do so, subject to the following conditions: 27 | # 28 | # The above copyright notice and this permission notice shall be included in all 29 | # copies or substantial portions of the Software. 30 | # 31 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 32 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 33 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 34 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 35 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 36 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 37 | # SOFTWARE. 38 | #================================================================================== 39 | # Example 5 - port of the Arduino example 5 40 | # 41 | 42 | import qwiic_bme280 43 | import time 44 | import sys 45 | 46 | def runExample(): 47 | 48 | print("\nSparkFun BME280 Sensor Example 5\n") 49 | mySensor = qwiic_bme280.QwiicBme280() 50 | 51 | if mySensor.connected == False: 52 | print("The Qwiic BME280 device isn't connected to the system. Please check your connection", \ 53 | file=sys.stderr) 54 | return 55 | 56 | mySensor.begin() 57 | 58 | print("ID(0xD0): 0x%.2x" % mySensor._i2c.readByte(mySensor.address, mySensor.BME280_CHIP_ID_REG)) 59 | print("Reset register(0xE0): 0x%.2x" % mySensor._i2c.readByte(mySensor.address, mySensor.BME280_RST_REG)) 60 | print("ctrl_meas(0xF4): 0x%.2x" % mySensor._i2c.readByte(mySensor.address, mySensor.BME280_CTRL_MEAS_REG)) 61 | print("ctrl_hum(0xF2): 0x%.2x\n" % mySensor._i2c.readByte(mySensor.address, mySensor.BME280_CTRL_HUMIDITY_REG)) 62 | 63 | print("Displaying all regs:") 64 | memCounter = 0x80 65 | for row in range(8,16): 66 | print("0x%.2x 0:" % row, end='') 67 | for column in range(0,16): 68 | tempReadData = mySensor._i2c.readByte(mySensor.address, memCounter) 69 | print("0x%.2x " % tempReadData, end='') 70 | 71 | memCounter += 1 72 | print("") 73 | 74 | 75 | print("Displaying concatenated calibration words:") 76 | print("dig_T1, uint16: %d" % mySensor.calibration["dig_T1"]) 77 | print("dig_T2, int16: %d" % mySensor.calibration["dig_T2"]) 78 | print("dig_T3, int16: %d" % mySensor.calibration["dig_T3"]) 79 | print("dig_P1, uint16: %d" % mySensor.calibration["dig_P1"]) 80 | print("dig_P2, int16: %d" % mySensor.calibration["dig_P2"]) 81 | print("dig_P3, int16: %d" % mySensor.calibration["dig_P3"]) 82 | print("dig_P4, int16: %d" % mySensor.calibration["dig_P4"]) 83 | print("dig_P5, int16: %d" % mySensor.calibration["dig_P5"]) 84 | print("dig_P6, int16: %d" % mySensor.calibration["dig_P6"]) 85 | print("dig_P7, int16: %d" % mySensor.calibration["dig_P7"]) 86 | print("dig_P8, int16: %d" % mySensor.calibration["dig_P8"]) 87 | print("dig_P9, int16: %d" % mySensor.calibration["dig_P9"]) 88 | print("dig_H1, uint8: %d" % mySensor.calibration["dig_H1"]) 89 | print("dig_H2, int16: %d" % mySensor.calibration["dig_H2"]) 90 | print("dig_H3, uint8: %d" % mySensor.calibration["dig_H3"]) 91 | print("dig_H4, int16: %d" % mySensor.calibration["dig_H5"]) 92 | print("dig_H6, int8: %d" % mySensor.calibration["dig_H6"]) 93 | while True: 94 | 95 | print("Humidity:\t%.3f" % mySensor.humidity) 96 | 97 | print("Pressure:\t%.3f" % mySensor.pressure) 98 | 99 | print("Altitude:\t%.3f" % mySensor.altitude_feet) 100 | 101 | print("Temperature:\t%.2f\n" % mySensor.temperature_fahrenheit) 102 | 103 | time.sleep(1) 104 | 105 | if __name__ == '__main__': 106 | try: 107 | runExample() 108 | except (KeyboardInterrupt, SystemExit) as exErr: 109 | print("\nEnding Example 5") 110 | sys.exit(0) 111 | 112 | 113 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "urls": [ 3 | ["qwiic_bme280.py", "github:sparkfun/Qwiic_BME280_Py/qwiic_bme280.py"] 4 | ], 5 | "deps": [ 6 | ["github:sparkfun/Qwiic_I2C_Py", "master"] 7 | ], 8 | "version": "2.0.0" 9 | } 10 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools"] 3 | 4 | [project] 5 | name = "sparkfun_qwiic_bme280" 6 | version = "2.0.0" 7 | description = "SparkFun Electronics Qwiic BME280" 8 | readme = "DESCRIPTION.rst" 9 | 10 | authors = [{name="Sparkfun Electronics", email="info@sparkfun.com"}] 11 | dependencies = ["sparkfun_qwiic_i2c"] 12 | 13 | classifiers=[ 14 | # How mature is this project? Common values are 15 | # 3 - Alpha 16 | # 4 - Beta 17 | # 5 - Production/Stable 18 | "Development Status :: 5 - Production/Stable", 19 | 20 | # Indicate who your project is intended for 21 | "Intended Audience :: Developers", 22 | "Topic :: Software Development :: Build Tools", 23 | 24 | # Pick your license as you wish (should match "license" above) 25 | "License :: OSI Approved :: MIT License", 26 | 27 | # Specify the Python versions you support here. In particular, ensure 28 | # that you indicate whether you support Python 2, Python 3 or both. 29 | "Programming Language :: Python :: 3.5", 30 | "Programming Language :: Python :: 3.6", 31 | "Programming Language :: Python :: 3.7", 32 | "Programming Language :: Python :: 3.8", 33 | "Programming Language :: Python :: 3.9", 34 | "Programming Language :: Python :: 3.10", 35 | "Programming Language :: Python :: 3.11", 36 | "Programming Language :: Python :: 3.12", 37 | "Programming Language :: Python :: 3.13", 38 | "Programming Language :: Python :: 3.14", 39 | "Programming Language :: Python :: Implementation :: MicroPython", 40 | # NOTE: CircuitPython is also supported, but no classifier exists for it 41 | ] 42 | 43 | keywords = ["electronics, maker"] 44 | 45 | [project.urls] 46 | homepage = "https://www.sparkfun.com/products/14348" 47 | 48 | [tool.setuptools] 49 | py-modules = ["qwiic_bme280"] 50 | -------------------------------------------------------------------------------- /qwiic_bme280.py: -------------------------------------------------------------------------------- 1 | #----------------------------------------------------------------------------- 2 | # qwiic_bme280.py 3 | # 4 | # Python library for the SparkFun qwiic BME280 sensor. 5 | # 6 | # This sensor is available on the SparkFun Environmental Combo Breakout board. 7 | # https://www.sparkfun.com/products/14348 8 | # 9 | #------------------------------------------------------------------------ 10 | # 11 | # Written by SparkFun Electronics, May 2019 12 | # 13 | # This python library supports the SparkFun Electroncis qwiic 14 | # qwiic sensor/board ecosystem 15 | # 16 | # More information on qwiic is at https:// www.sparkfun.com/qwiic 17 | # 18 | # Do you like this library? Help support SparkFun. Buy a board! 19 | #================================================================================== 20 | # Copyright (c) 2019 SparkFun Electronics 21 | # 22 | # Permission is hereby granted, free of charge, to any person obtaining a copy 23 | # of this software and associated documentation files (the "Software"), to deal 24 | # in the Software without restriction, including without limitation the rights 25 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 26 | # copies of the Software, and to permit persons to whom the Software is 27 | # furnished to do so, subject to the following conditions: 28 | # 29 | # The above copyright notice and this permission notice shall be included in all 30 | # copies or substantial portions of the Software. 31 | # 32 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 33 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 34 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 35 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 36 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 37 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 38 | # SOFTWARE. 39 | #================================================================================== 40 | # 41 | # This is mostly a port of existing Arduino functionaly, so pylint is sad. 42 | # The goal is to keep the public interface pthonic, but internal is internal 43 | # 44 | # pylint: disable=line-too-long, bad-whitespace, invalid-name, too-many-public-methods 45 | # 46 | 47 | """! 48 | qwiic_bme280 49 | ============ 50 | Python module for the qwiic bme280 sensor, which is part of the [SparkFun Qwiic Environmental Combo Breakout](https://www.sparkfun.com/products/14348) 51 | 52 | This python package is a port of the existing [SparkFun BME280 Arduino Library](https://github.com/sparkfun/SparkFun_BME280_Arduino_Library) 53 | 54 | This package can be used in conjunction with the overall [SparkFun qwiic Python Package](https://github.com/sparkfun/Qwiic_Py) 55 | 56 | New to qwiic? Take a look at the entire [SparkFun qwiic ecosystem](https://www.sparkfun.com/qwiic). 57 | """ 58 | 59 | #----------------------------------------------------------------------------- 60 | import math 61 | import time 62 | import qwiic_i2c 63 | 64 | # Define the device name and I2C addresses. These are set in the class defintion 65 | # as class variables, making them avilable without having to create a class instance. 66 | # This allows higher level logic to rapidly create a index of qwiic devices at 67 | # runtine 68 | # 69 | # The name of this device 70 | _DEFAULT_NAME = "Qwiic BME280" 71 | 72 | # Some devices have multiple availabel addresses - this is a list of these addresses. 73 | # NOTE: The first address in this list is considered the default I2C address for the 74 | # device. 75 | _AVAILABLE_I2C_ADDRESS = [0x77, 0x76] 76 | 77 | # Default Setting Values 78 | _settings = {"runMode" : 3, \ 79 | "tStandby" : 0, \ 80 | "filter" : 0, \ 81 | "tempOverSample" : 1, \ 82 | "pressOverSample" : 1, \ 83 | "humidOverSample" : 1, \ 84 | "tempCorrection" : 0.0} 85 | 86 | # define our valid chip IDs 87 | _validChipIDs = [0x58, 0x60] 88 | 89 | # define the class that encapsulates the device being created. All information associated with this 90 | # device is encapsulated by this class. The device class should be the only value exported 91 | # from this module. 92 | 93 | class QwiicBme280(object): 94 | """! 95 | QwiicBme280 96 | 97 | @param address: The I2C address to use for the device. 98 | If not provided, the default address is used. 99 | @param i2c_driver: An existing i2c driver object. If not provided 100 | a driver object is created. 101 | 102 | @return **Object** The BME280 device object. 103 | """ 104 | # Constructor 105 | device_name =_DEFAULT_NAME 106 | available_addresses = _AVAILABLE_I2C_ADDRESS 107 | 108 | # mode flags for the device - user exposed 109 | MODE_SLEEP = 0b00 110 | MODE_FORCED = 0b01 111 | MODE_NORMAL = 0b11 112 | 113 | # Register names for the BME280 114 | BME280_DIG_T1_LSB_REG = 0x88 115 | BME280_DIG_T1_MSB_REG = 0x89 116 | BME280_DIG_T2_LSB_REG = 0x8A 117 | BME280_DIG_T2_MSB_REG = 0x8B 118 | BME280_DIG_T3_LSB_REG = 0x8C 119 | BME280_DIG_T3_MSB_REG = 0x8D 120 | BME280_DIG_P1_LSB_REG = 0x8E 121 | BME280_DIG_P1_MSB_REG = 0x8F 122 | BME280_DIG_P2_LSB_REG = 0x90 123 | BME280_DIG_P2_MSB_REG = 0x91 124 | BME280_DIG_P3_LSB_REG = 0x92 125 | BME280_DIG_P3_MSB_REG = 0x93 126 | BME280_DIG_P4_LSB_REG = 0x94 127 | BME280_DIG_P4_MSB_REG = 0x95 128 | BME280_DIG_P5_LSB_REG = 0x96 129 | BME280_DIG_P5_MSB_REG = 0x97 130 | BME280_DIG_P6_LSB_REG = 0x98 131 | BME280_DIG_P6_MSB_REG = 0x99 132 | BME280_DIG_P7_LSB_REG = 0x9A 133 | BME280_DIG_P7_MSB_REG = 0x9B 134 | BME280_DIG_P8_LSB_REG = 0x9C 135 | BME280_DIG_P8_MSB_REG = 0x9D 136 | BME280_DIG_P9_LSB_REG = 0x9E 137 | BME280_DIG_P9_MSB_REG = 0x9F 138 | BME280_DIG_H1_REG = 0xA1 139 | BME280_CHIP_ID_REG = 0xD0 # Chip ID 140 | BME280_RST_REG = 0xE0 # Softreset Reg 141 | BME280_DIG_H2_LSB_REG = 0xE1 142 | BME280_DIG_H2_MSB_REG = 0xE2 143 | BME280_DIG_H3_REG = 0xE3 144 | BME280_DIG_H4_MSB_REG = 0xE4 145 | BME280_DIG_H4_LSB_REG = 0xE5 146 | BME280_DIG_H5_MSB_REG = 0xE6 147 | BME280_DIG_H6_REG = 0xE7 148 | BME280_CTRL_HUMIDITY_REG = 0xF2 # Ctrl Humidity Reg 149 | BME280_STAT_REG = 0xF3 # Status Reg 150 | BME280_CTRL_MEAS_REG = 0xF4 # Ctrl Measure Reg 151 | BME280_CONFIG_REG = 0xF5 # Configuration Reg 152 | BME280_PRESSURE_MSB_REG = 0xF7 # Pressure MSB 153 | BME280_PRESSURE_LSB_REG = 0xF8 # Pressure LSB 154 | BME280_PRESSURE_XLSB_REG = 0xF9 # Pressure XLSB 155 | BME280_TEMPERATURE_MSB_REG = 0xFA # Temperature MSB 156 | BME280_TEMPERATURE_LSB_REG = 0xFB # Temperature LSB 157 | BME280_TEMPERATURE_XLSB_REG = 0xFC # Temperature XLSB 158 | BME280_HUMIDITY_MSB_REG = 0xFD # Humidity MSB 159 | BME280_HUMIDITY_LSB_REG = 0xFE # Humidity LSB 160 | 161 | # Constructor 162 | def __init__(self, address=None, i2c_driver=None): 163 | 164 | # Did the user specify an I2C address? 165 | if address in self.available_addresses: 166 | self.address = address 167 | else: 168 | self.address = self.available_addresses[0] 169 | 170 | # load the I2C driver if one isn't provided 171 | 172 | if i2c_driver is None: 173 | self._i2c = qwiic_i2c.getI2CDriver() 174 | if self._i2c is None: 175 | print("Unable to load I2C driver for this platform.") 176 | return 177 | else: 178 | self._i2c = i2c_driver 179 | 180 | 181 | # create a dictionary to stash our calibration data for the sensor 182 | self.calibration={} 183 | 184 | self.t_fine=0 185 | 186 | self._referencePressure = 101325.0 187 | 188 | # ---------------------------------- 189 | # is_connected() 190 | # 191 | # Is an actual board connected to our system? 192 | 193 | def is_connected(self): 194 | """! 195 | Determine if a BME280 device is conntected to the system.. 196 | 197 | @return **bool** True if the device is connected, otherwise False. 198 | """ 199 | return self._i2c.isDeviceConnected(self.address) 200 | 201 | connected = property(is_connected) 202 | 203 | # ---------------------------------- 204 | # begin() 205 | # 206 | # Initialize the system/validate the board. 207 | def begin(self): 208 | """! 209 | Initialize the operation of the BME280 module 210 | 211 | @return **bool** Returns true of the initializtion was successful, otherwise False. 212 | """ 213 | # are we who we need to be? 214 | chipID = self._i2c.readByte(self.address, self.BME280_CHIP_ID_REG) 215 | if chipID not in _validChipIDs: 216 | print("Invalid Chip ID: 0x%.2X" % chipID) 217 | return False 218 | 219 | 220 | def unsigned_short_to_signed_short(n): 221 | """! 222 | Converts a 2 byte unsigned short to signed short (uint16_t -> int16_t) 223 | 224 | @param n: Unsigned short (uint16_t) to convert 225 | 226 | @return **int** Signed short (int16_t) 227 | """ 228 | assert n >= 0, "Expected number to be unsigned (uint16_t), n>=0" 229 | assert n <= 2**16 - 1,"Expected number to be short (int16_t), n <= 2^16 - 1" 230 | 231 | return n - 2**16 if n >= 2**15 else n 232 | 233 | def unsigned_char_to_signed_char(n): 234 | """! 235 | Converts an unsigned char to signed char (uint8_t -> int8_t) 236 | 237 | @param n: Unsigned char (uint8_t) to convert 238 | 239 | @return **int** Signed char (int8_t) 240 | """ 241 | assert n >= 0, "Expected number to be unsigned (uint8_t), n>=0" 242 | assert n <= 2**8 - 1,"Expected number to be char (int8_t), n <= 2^8 - 1" 243 | 244 | return n - 2**8 if n >= 2**7 else n 245 | 246 | # Reading all compensation data, range 0x88:A1, 0xE1:E7 247 | self.calibration["dig_T1"] = (self._i2c.readByte(self.address, self.BME280_DIG_T1_MSB_REG) << 8) + self._i2c.readByte(self.address, self.BME280_DIG_T1_LSB_REG) 248 | self.calibration["dig_T2"] = unsigned_short_to_signed_short((self._i2c.readByte(self.address, self.BME280_DIG_T2_MSB_REG) << 8) + self._i2c.readByte(self.address, self.BME280_DIG_T2_LSB_REG)) 249 | self.calibration["dig_T3"] = unsigned_short_to_signed_short((self._i2c.readByte(self.address, self.BME280_DIG_T3_MSB_REG) << 8) + self._i2c.readByte(self.address, self.BME280_DIG_T3_LSB_REG)) 250 | 251 | self.calibration["dig_P1"] = (self._i2c.readByte(self.address, self.BME280_DIG_P1_MSB_REG) << 8) + self._i2c.readByte(self.address, self.BME280_DIG_P1_LSB_REG) 252 | self.calibration["dig_P2"] = unsigned_short_to_signed_short((self._i2c.readByte(self.address, self.BME280_DIG_P2_MSB_REG) << 8) + self._i2c.readByte(self.address, self.BME280_DIG_P2_LSB_REG)) 253 | self.calibration["dig_P3"] = unsigned_short_to_signed_short((self._i2c.readByte(self.address, self.BME280_DIG_P3_MSB_REG) << 8) + self._i2c.readByte(self.address, self.BME280_DIG_P3_LSB_REG)) 254 | self.calibration["dig_P4"] = unsigned_short_to_signed_short((self._i2c.readByte(self.address, self.BME280_DIG_P4_MSB_REG) << 8) + self._i2c.readByte(self.address, self.BME280_DIG_P4_LSB_REG)) 255 | self.calibration["dig_P5"] = unsigned_short_to_signed_short((self._i2c.readByte(self.address, self.BME280_DIG_P5_MSB_REG) << 8) + self._i2c.readByte(self.address, self.BME280_DIG_P5_LSB_REG)) 256 | self.calibration["dig_P6"] = unsigned_short_to_signed_short((self._i2c.readByte(self.address, self.BME280_DIG_P6_MSB_REG) << 8) + self._i2c.readByte(self.address, self.BME280_DIG_P6_LSB_REG)) 257 | self.calibration["dig_P7"] = unsigned_short_to_signed_short((self._i2c.readByte(self.address, self.BME280_DIG_P7_MSB_REG) << 8) + self._i2c.readByte(self.address, self.BME280_DIG_P7_LSB_REG)) 258 | self.calibration["dig_P8"] = unsigned_short_to_signed_short((self._i2c.readByte(self.address, self.BME280_DIG_P8_MSB_REG) << 8) + self._i2c.readByte(self.address, self.BME280_DIG_P8_LSB_REG)) 259 | self.calibration["dig_P9"] = unsigned_short_to_signed_short((self._i2c.readByte(self.address, self.BME280_DIG_P9_MSB_REG) << 8) + self._i2c.readByte(self.address, self.BME280_DIG_P9_LSB_REG)) 260 | 261 | self.calibration["dig_H1"] = self._i2c.readByte(self.address, self.BME280_DIG_H1_REG) 262 | self.calibration["dig_H2"] = unsigned_short_to_signed_short((self._i2c.readByte(self.address, self.BME280_DIG_H2_MSB_REG) << 8) + self._i2c.readByte(self.address, self.BME280_DIG_H2_LSB_REG)) 263 | self.calibration["dig_H3"] = self._i2c.readByte(self.address, self.BME280_DIG_H3_REG) 264 | self.calibration["dig_H4"] = unsigned_short_to_signed_short((self._i2c.readByte(self.address, self.BME280_DIG_H4_MSB_REG) << 4) + (self._i2c.readByte(self.address, self.BME280_DIG_H4_LSB_REG) & 0x0F)) 265 | self.calibration["dig_H5"] = unsigned_short_to_signed_short((self._i2c.readByte(self.address, self.BME280_DIG_H5_MSB_REG) << 4) + ((self._i2c.readByte(self.address, self.BME280_DIG_H4_LSB_REG) >> 4) & 0x0F)) 266 | self.calibration["dig_H6"] = unsigned_char_to_signed_char(self._i2c.readByte(self.address, self.BME280_DIG_H6_REG)) 267 | 268 | # Most of the time the sensor will be init with default values 269 | # But in case user has old/deprecated code, use the _settings.x values 270 | 271 | self.set_standby_time(_settings["tStandby"]) 272 | self.set_filter(_settings["filter"]) 273 | self.set_pressure_oversample(_settings["pressOverSample"]) # Default of 1x oversample 274 | self.set_humidity_oversample(_settings["humidOverSample"]) # Default of 1x oversample 275 | self.set_tempature_oversample(_settings["tempOverSample"]) # Default of 1x oversample 276 | 277 | self.set_mode(self.MODE_NORMAL) #Go! 278 | 279 | # Wait for first measurement to come through. According to the second 280 | # equation in section 9.1 of the datasheet, it should take no longer 281 | # than 9.3ms to finish the first measurement at 1x oversampling on all 282 | # sensors. So wat 10ms to be safe 283 | time.sleep(0.01) 284 | 285 | return True 286 | 287 | #---------------------------------------------------------------- 288 | # Mode of the sensor 289 | 290 | def set_mode(self, mode): 291 | """! 292 | Set the operational mode of the sensor. 293 | 294 | @param mode: One of the class constant values. 295 | MODE_SLEEP, MODE_FORCED, MODE_NORMAL 296 | 297 | @return No return value 298 | """ 299 | if mode > 0b11: 300 | mode = 0 # Error check. Default to sleep mode 301 | 302 | controlData = self._i2c.readByte(self.address, self.BME280_CTRL_MEAS_REG) 303 | controlData &= (~( (1<<1) | (1<<0) ) ) & 0xFF # Clear the mode[1:0] bits - note we just want a byte 304 | controlData |= mode # Set 305 | self._i2c.writeByte(self.address, self.BME280_CTRL_MEAS_REG, controlData) 306 | 307 | 308 | def get_mode(self): 309 | """! 310 | Returns the operational mode of the sensor. 311 | 312 | @return **MODE_SLEEP, MODE_FORCED, or MODE_NORMAL** The current operational mode 313 | """ 314 | controlData = self._i2c.readByte(self.address, self.BME280_CTRL_MEAS_REG) 315 | return controlData & 0b00000011 316 | 317 | # Make the mode a property of this object 318 | mode = property(get_mode, set_mode) 319 | 320 | #---------------------------------------------------------------- 321 | # Set the standby bits in the config register 322 | # tStandby can be: 323 | # 0, 0.5ms 324 | # 1, 62.5ms 325 | # 2, 125ms 326 | # 3, 250ms 327 | # 4, 500ms 328 | # 5, 1000ms 329 | # 6, 10ms 330 | # 7, 20ms 331 | def set_standby_time(self, timeSetting): 332 | """! 333 | Set the standby bits in the BME280s config register 334 | 335 | @param timeSetting: The standby time bits - acceptable values 336 | 0 = 0.5ms 337 | 1 = 62.5ms 338 | 2 = 125ms 339 | 3 = 250ms 340 | 4 = 500ms 341 | 5 = 1000ms 342 | 6 = 10ms 343 | 7 = 20ms 344 | 345 | @return No return value 346 | """ 347 | 348 | if timeSetting > 0b111 : 349 | timeSetting = 0 # Error check. Default to 0.5ms 350 | 351 | controlData = self._i2c.readByte(self.address, self.BME280_CONFIG_REG) 352 | controlData &= ( ~( (1<<7) | (1<<6) | (1<<5) )) & 0xff # Clear the 7/6/5 bits 353 | controlData |= (timeSetting << 5) # Align with bits 7/6/5 354 | self._i2c.writeByte(self.address, self.BME280_CONFIG_REG, controlData) 355 | 356 | # Make standby time a property 357 | standby_time = property() 358 | standby_time = standby_time.setter(set_standby_time) 359 | 360 | #---------------------------------------------------------------- 361 | # Set the filter bits in the config register 362 | # filter can be off or number of FIR coefficients to use: 363 | # 0, filter off 364 | # 1, coefficients = 2 365 | # 2, coefficients = 4 366 | # 3, coefficients = 8 367 | # 4, coefficients = 16 368 | def set_filter(self, filterSetting): 369 | """! 370 | Set the filter bits in the BME280s config register 371 | 372 | @param filterSetting: The filter bits for the BME280. Acceptable values 373 | 0 = filter off 374 | 1 = coefficients = 2 375 | 2 = coefficients = 4 376 | 3 = coefficients = 8 377 | 4 = coefficients = 16 378 | 379 | @return No return value 380 | """ 381 | if filterSetting > 0b111 : 382 | filterSetting = 0 # Error check. Default to filter off 383 | 384 | controlData = self._i2c.readByte(self.address, self.BME280_CONFIG_REG) 385 | controlData &= (~( (1<<4) | (1<<3) | (1<<2) ) ) & 0xFF # Clear the 4/3/2 bits 386 | controlData |= (filterSetting << 2) # Align with bits 4/3/2 387 | self._i2c.writeByte(self.address, self.BME280_CONFIG_REG, controlData) 388 | 389 | filter = property() 390 | filter = filter.setter(set_filter) 391 | 392 | #---------------------------------------------------------------- 393 | # Set the temperature oversample value 394 | # 0 turns off temp sensing 395 | # 1 to 16 are valid over sampling values 396 | def set_tempature_oversample(self, overSampleAmount): 397 | """! 398 | Set the temperature oversample value 399 | 400 | @param overSampleAmount: The temperature oversample value. Acceptable values 401 | 0 = turns off temp sensing 402 | 1 to 16 are valid over sampling values 403 | 404 | @return No return value 405 | """ 406 | overSampleAmount = self.check_sample_value(overSampleAmount) # Error check 407 | 408 | originalMode = self.get_mode() # Get the current mode so we can go back to it at the end 409 | 410 | self.set_mode(self.MODE_SLEEP) # Config will only be writeable in sleep mode, so first go to sleep mode 411 | 412 | # Set the osrs_t bits (7, 6, 5) to overSampleAmount 413 | controlData = self._i2c.readByte(self.address, self.BME280_CTRL_MEAS_REG) 414 | controlData &= (~( (1<<7) | (1<<6) | (1<<5) )) & 0xFF # Clear bits 765 415 | controlData |= overSampleAmount << 5 # Align overSampleAmount to bits 7/6/5 416 | self._i2c.writeByte(self.address, self.BME280_CTRL_MEAS_REG, controlData) 417 | 418 | self.set_mode(originalMode) # Return to the original user's choice 419 | 420 | tempature_oversample = property() 421 | tempature_oversample = tempature_oversample.setter(set_tempature_oversample) 422 | 423 | # Set the pressure oversample value 424 | # 0 turns off pressure sensing 425 | # 1 to 16 are valid over sampling values 426 | def set_pressure_oversample(self, overSampleAmount): 427 | """! 428 | Set the pressure oversample value 429 | 430 | @param overSampleAmount: The pressure oversample value. Acceptable values 431 | 0 = turns off pressure sensing 432 | 1 to 16 are valid over sampling values 433 | 434 | @return No return value 435 | """ 436 | overSampleAmount = self.check_sample_value(overSampleAmount) # Error check 437 | 438 | originalMode = self.get_mode() # Get the current mode so we can go back to it at the end 439 | 440 | self.set_mode(self.MODE_SLEEP) # Config will only be writeable in sleep mode, so first go to sleep mode 441 | 442 | # Set the osrs_p bits (4, 3, 2) to overSampleAmount 443 | controlData = self._i2c.readByte(self.address, self.BME280_CTRL_MEAS_REG) 444 | controlData &= (~( (1<<4) | (1<<3) | (1<<2) )) & 0xFF # Clear bits 432 445 | controlData |= overSampleAmount << 2 # Align overSampleAmount to bits 4/3/2 446 | self._i2c.writeByte(self.address, self.BME280_CTRL_MEAS_REG, controlData) 447 | 448 | self.set_mode(originalMode) # Return to the original user's choice 449 | 450 | pressure_oversample = property() 451 | pressure_oversample = pressure_oversample.setter(set_pressure_oversample) 452 | 453 | #---------------------------------------------------------------- 454 | # Set the humidity oversample value 455 | # 0 turns off humidity sensing 456 | # 1 to 16 are valid over sampling values 457 | def set_humidity_oversample(self, overSampleAmount): 458 | """! 459 | Set the humidity oversample value 460 | 461 | @param overSampleAmount: The humidity oversample value. Acceptable values 462 | 0 = turns off humidity sensing 463 | 1 to 16 are valid over sampling values 464 | 465 | @return No return value 466 | """ 467 | overSampleAmount = self.check_sample_value(overSampleAmount) # Error check 468 | 469 | originalMode = self.get_mode() # Get the current mode so we can go back to it at the end 470 | 471 | self.set_mode(self.MODE_SLEEP) # Config will only be writeable in sleep mode, so first go to sleep mode 472 | 473 | # Set the osrs_h bits (2, 1, 0) to overSampleAmount 474 | controlData = self._i2c.readByte(self.address, self.BME280_CTRL_HUMIDITY_REG) 475 | controlData &= (~( (1<<2) | (1<<1) | (1<<0) )) & 0xFF # Clear bits 2/1/0 476 | controlData |= overSampleAmount << 0 # Align overSampleAmount to bits 2/1/0 477 | self._i2c.writeByte(self.address, self.BME280_CTRL_HUMIDITY_REG, controlData) 478 | 479 | self.set_mode(originalMode) # Return to the original user's choice 480 | 481 | humidity_oversample = property() 482 | humidity_oversample = humidity_oversample.setter(set_humidity_oversample) 483 | 484 | #---------------------------------------------------------------- 485 | # Validates an over sample value 486 | # Allowed values are 0 to 16 487 | # These are used in the humidty, pressure, and temp oversample functions 488 | # 489 | # pylint: disable=no-self-use 490 | def check_sample_value(self, userValue): 491 | """! 492 | Validates an over sample value 493 | 494 | @param userValue: The oversample value to check. 495 | Allowed values are 0 to 16 496 | These are used in the humidty, pressure, and temp oversample functions 497 | 498 | @return **int** Valid oversample value 499 | """ 500 | _valueMap = { 0: 0, 1: 1, 2: 2, 4: 3, 8: 4, 16: 5} 501 | 502 | return _valueMap[userValue] if userValue in _valueMap.keys() else 1 503 | 504 | # pylint: enable=no-self-use 505 | # Check the measuring bit and return true while device is taking measurement 506 | def is_measuring(self): 507 | """! 508 | Return if the sensor is measuring or not 509 | 510 | @return True if the sensor is measuring, else False 511 | :rvalue: boolean 512 | """ 513 | 514 | stat = self._i2c.readByte(self.address, self.BME280_STAT_REG) 515 | return True if stat & (1<<3) else False # If the measuring bit (3) is set, return true 516 | 517 | 518 | # Strictly resets. Run .begin() afterwards 519 | def reset( self ): 520 | """! 521 | Resets the sensor. If called, the begin method must be called before 522 | using the sensor. 523 | """ 524 | self._i2c.writeByte(self.address, self.BME280_RST_REG, 0xB6) 525 | 526 | # ****************************************************************************# 527 | # 528 | # Pressure Section 529 | # 530 | # ****************************************************************************# 531 | def read_pressure( self ): 532 | """! 533 | Returns pressure in Pa. 534 | 535 | @return **float** Pressure in Pa 536 | """ 537 | 538 | # Read temperature to update t_fine 539 | self.get_temperature_celsius() 540 | 541 | data_buffer = self._i2c.readBlock(self.address, self.BME280_PRESSURE_MSB_REG, 3) 542 | adc_P = (data_buffer[0] << 12) | (data_buffer[1] << 4) | ((data_buffer[2] >> 4) & 0x0F) 543 | 544 | var1 = self.t_fine - 128000 545 | var2 = var1 * var1 * self.calibration["dig_P6"] 546 | var2 = var2 + ((var1 * self.calibration["dig_P5"])<<17) 547 | var2 = var2 + (self.calibration["dig_P4"] <<35) 548 | var1 = ((var1 * var1 * self.calibration["dig_P3"])>>8) + ((var1 * self.calibration["dig_P2"])<<12) 549 | var1 = ( (1 << 47) + var1 )*(self.calibration["dig_P1"])>>33 550 | 551 | if var1 == 0: 552 | return 0 # avoid exception caused by division by zero 553 | 554 | p_acc = 1048576 - adc_P 555 | p_acc = (((p_acc<<31) - var2)*3125)//var1 556 | 557 | var1 = ((self.calibration["dig_P9"]) * (p_acc>>13) * (p_acc>>13)) >> 25 558 | var2 = ((self.calibration["dig_P8"]) * p_acc) >> 19 559 | p_acc = ((p_acc + var1 + var2) >> 8) + ((self.calibration["dig_P7"])<<4) 560 | 561 | return p_acc / 256.0 562 | 563 | pressure = property(read_pressure) 564 | 565 | #---------------------------------------------------------------- 566 | # Sets the internal variable _referencePressure so the 567 | def set_reference_pressure(self, refPressure): 568 | """! 569 | Sets the referance pressure for the sensor measurments. 570 | 571 | @param refPressure: The referance pressure to use. 572 | 573 | @return No return value 574 | """ 575 | self._referencePressure = float(refPressure) 576 | 577 | # Return the local reference pressure 578 | def get_reference_pressure(self): 579 | """! 580 | Get the current reference pressure for the sensor. 581 | 582 | @return **float** The current reference pressure. 583 | """ 584 | return self._referencePressure 585 | 586 | reference_pressure = property(get_reference_pressure, set_reference_pressure) 587 | 588 | #---------------------------------------------------------------- 589 | def get_altitude_meters( self ): 590 | """! 591 | Return the current Altitude in meters 592 | 593 | @return **float** The current altitude in meters 594 | """ 595 | 596 | return (-44330.77)*(math.pow((self.pressure/self._referencePressure), 0.190263) - 1.0) # Corrected, see issue 30 597 | 598 | altitude_meters = property(get_altitude_meters) 599 | 600 | #---------------------------------------------------------------- 601 | def get_altitude_feet( self ): 602 | """! 603 | Return the current Altitude in feet 604 | 605 | @return **float** The current altitude in feets 606 | """ 607 | return self.get_altitude_meters() * 3.28084 608 | 609 | altitude_feet = property(get_altitude_feet) 610 | 611 | 612 | # ****************************************************************************# 613 | # 614 | # Humidity Section 615 | # 616 | # ****************************************************************************# 617 | def read_humidity( self ): 618 | """! 619 | Returns humidity in %RH. 620 | 621 | @return **float** The current humidity value 622 | """ 623 | 624 | # Read temperature to update t_fine 625 | self.get_temperature_celsius() 626 | 627 | data_buffer = self._i2c.readBlock(self.address, self.BME280_HUMIDITY_MSB_REG, 2) 628 | adc_H = (data_buffer[0] << 8) | data_buffer[1] 629 | 630 | var1 = (self.t_fine - 76800) 631 | var1 = (((((adc_H << 14) - ((self.calibration["dig_H4"]) << 20) - ((self.calibration["dig_H5"]) * var1)) + \ 632 | (16384)) >> 15) * (((((((var1 * (self.calibration["dig_H6"])) >> 10) * (((var1 * (self.calibration["dig_H3"])) >> 11) + (32768))) >> 10) + (2097152)) * \ 633 | (self.calibration["dig_H2"]) + 8192) >> 14)) 634 | var1 = (var1 - (((((var1 >> 15) * (var1 >> 15)) >> 7) * (self.calibration["dig_H1"])) >> 4)) 635 | var1 = 0 if var1 < 0 else var1 636 | var1 = 419430400 if var1 > 419430400 else var1 637 | 638 | 639 | return (var1>>12) / 1024.0 640 | 641 | humidity = property(read_humidity) 642 | 643 | # ****************************************************************************# 644 | # 645 | # Temperature Section 646 | # 647 | # ****************************************************************************# 648 | 649 | def get_temperature_celsius( self ): 650 | """! 651 | Returns temperature in DegC and updates t_fine (needed for accurate 652 | pressure and humidity measurements) 653 | 654 | @return **float** The current temperature in C. 655 | """ 656 | 657 | # get the reading (adc_T); 658 | 659 | data_buffer = self._i2c.readBlock(self.address, self.BME280_TEMPERATURE_MSB_REG, 3) 660 | adc_T = (data_buffer[0] << 12) | (data_buffer[1] << 4) | ((data_buffer[2] >> 4) & 0x0F) 661 | 662 | # By datasheet, calibrate 663 | 664 | var1 = ((((adc_T>>3) - (self.calibration["dig_T1"]<<1))) * (self.calibration["dig_T2"])) >> 11 665 | var2 = (((((adc_T>>4) - (self.calibration["dig_T1"])) * ((adc_T>>4) - (self.calibration["dig_T1"]))) >> 12) * \ 666 | (self.calibration["dig_T3"])) >> 14 667 | self.t_fine = var1 + var2 668 | output = (self.t_fine * 5 + 128) >> 8 669 | 670 | return output / 100 + _settings["tempCorrection"] 671 | 672 | temperature_celsius = property(get_temperature_celsius) 673 | 674 | #---------------------------------------------------------------- 675 | def get_temperature_fahrenheit( self ): 676 | """! 677 | Returns temperature in Deg F and updates t_fine (needed for accurate 678 | pressure and humidity measurements) 679 | 680 | @return **float** The current temperature in F. 681 | """ 682 | output = self.temperature_celsius 683 | return (output * 9) / 5 + 32 684 | 685 | temperature_fahrenheit = property(get_temperature_fahrenheit) 686 | 687 | # ****************************************************************************# 688 | # 689 | # Dew point Section 690 | # 691 | # ****************************************************************************# 692 | # Returns Dew point in DegC 693 | 694 | def get_dewpoint_celsius(self): 695 | """! 696 | Returns the Dew point in degrees C. 697 | 698 | @return **float** The current dewpoint in C. 699 | """ 700 | celsius = self.get_temperature_celsius() 701 | humidity = self.read_humidity() 702 | # (1) Saturation Vapor Pressure = ESGG(T) 703 | 704 | RATIO = 373.15 / (273.15 + celsius) 705 | RHS = -7.90298 * (RATIO - 1) 706 | RHS += 5.02808 * math.log10(RATIO) 707 | RHS += -1.3816e-7 * (math.pow(10, (11.344 * (1 - 1/RATIO ))) - 1) 708 | RHS += 8.1328e-3 * (math.pow(10, (-3.49149 * (RATIO - 1))) - 1) 709 | RHS += math.log10(1013.246) 710 | # factor -3 is to adjust units - Vapor Pressure SVP * humidity 711 | VP = math.pow(10, RHS - 3) * humidity 712 | # (2) DEWPOINT = F(Vapor Pressure) 713 | T = math.log(VP/0.61078) # temp var 714 | return (241.88 * T) / (17.558 - T) 715 | 716 | dewpoint_celsius = property(get_dewpoint_celsius) 717 | 718 | #---------------------------------------------------------------- 719 | # Returns Dew point in DegF 720 | def get_dewpoint_fahrenheit(self): 721 | """! 722 | Returns the Dew point in degrees F. 723 | 724 | @return **float** The current dewpoint in F. 725 | """ 726 | return self.get_dewpoint_celsius() * 1.8 + 32 # Convert C to F 727 | 728 | dewpoint_fahrenheit = property(get_dewpoint_fahrenheit) 729 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | qwiic_i2c --------------------------------------------------------------------------------