4 |
5 |
6 |
7 | Temperature Control Interface
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/data/index.js.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thorrak/brewpi-esp8266/b6e45cd6ec49fd1e45c629d9871d0cae3060cea4/data/index.js.gz
--------------------------------------------------------------------------------
/docs/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line, and also
5 | # from the environment for the first two.
6 | SPHINXOPTS ?=
7 | SPHINXBUILD ?= sphinx-build
8 | SOURCEDIR = source
9 | BUILDDIR = _build
10 |
11 | # Put it first so that "make" without argument is like "make help".
12 | help:
13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14 |
15 | .PHONY: help Makefile
16 |
17 | # Catch-all target: route all unknown targets to Sphinx using the new
18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
19 | %: Makefile
20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
21 |
--------------------------------------------------------------------------------
/docs/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | pushd %~dp0
4 |
5 | REM Command file for Sphinx documentation
6 |
7 | if "%SPHINXBUILD%" == "" (
8 | set SPHINXBUILD=sphinx-build
9 | )
10 | set SOURCEDIR=source
11 | set BUILDDIR=_build
12 |
13 | %SPHINXBUILD% >NUL 2>NUL
14 | if errorlevel 9009 (
15 | echo.
16 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
17 | echo.installed, then set the SPHINXBUILD environment variable to point
18 | echo.to the full path of the 'sphinx-build' executable. Alternatively you
19 | echo.may add the Sphinx directory to PATH.
20 | echo.
21 | echo.If you don't have Sphinx installed, grab it from
22 | echo.https://www.sphinx-doc.org/
23 | exit /b 1
24 | )
25 |
26 | if "%1" == "" goto help
27 |
28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
29 | goto end
30 |
31 | :help
32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
33 |
34 | :end
35 | popd
36 |
--------------------------------------------------------------------------------
/docs/requirements.txt:
--------------------------------------------------------------------------------
1 | myst-parser==0.19.1
2 | sphinx==6.1.3
3 | sphinx_rtd_theme==1.2.0
4 |
--------------------------------------------------------------------------------
/docs/source/BrewPi Algorithm.md:
--------------------------------------------------------------------------------
1 | # BrewPi Algorithm
2 |
3 | BrewPi uses a (PID algorithm)[https://en.wikipedia.org/wiki/PID_controller] to control the fermentation temperature of beer very precisely. The algorithm works by adjusting the temperature setting of the fridge a fermenter is in based on the desired temperature of the beer. This is done by an automated process, similar to stationing a robot next to your fridge's thermostat and telling it to adjust the thermostat up or down based on where you think it needs to be in order to get the beer temperature correct.
4 |
5 | Just as when typically adjusting the thermostat on a refrigerator, whether or not the fridge turns on takes into account factors such as how far the current temperature is from the setpoint and how long it has been since the last cooling cycle took place (compressor protection). Heating or cooling will take place until the fridge temperature meets or surpasses the setpoint (though similar to the built in thermostat, there may be a "minimum run time" so as to protect the compressor). When using a heater the algorithm continues to simply change the fridge temperature setpoint - toggling cooling or heating depending on whether the fridge temperature is above or below the desired fridge setpoint.
6 |
7 | The BrewPi algorithm determines the optimal fridge setpoint based on the beer temperature and how historically changing the fridge thermostat has affected the beer temperature. The PID algorithm measures error in the
8 |
9 | However, the algorithm has limits, as it uses a single algorithm to control both heating and cooling. This assumption assumes that both heating and cooling will be impacted by the same degree of error which means that you will generally want to match your heating and cooling power, as well as the degree to which the heating/cooling can be picked up by the fridge sensor.
10 |
11 |
--------------------------------------------------------------------------------
/docs/source/Controller Configuration Options.md:
--------------------------------------------------------------------------------
1 | # Controller Configuration Options
2 |
3 |
4 | ## User Guide to Configuration
5 |
6 | The majority of the configuration of your BrewPi happens behind-the-scenes, either handled automatically by the controller itself or managed by Fermentrack or BrewPi Remix.
7 |
8 |
9 | ### "Low Delay" Mode
10 |
11 | BrewPi implements a number of protections designed to prevent damage to compressor-based cooling systems such as refrigerators, kegerators, or keezers. These include requiring cooling to run for a minimum period of time before being turned off, requiring a minimum amount of time to pass with the cooling off before allowing it to come back on, and requiring a minimum amount of time to pass before switching between heat & cooling. Low Delay mode reduces the delays associated with cooling
12 |
13 | | | **Normal** | **"Low Delay"** |
14 | |------------------------------------------------|------------|-----------------|
15 | | Minimum Cooling "Off" Time | 300s | 60s |
16 | | Minimum Heat "Off" Time | 300s | 300s |
17 | | Minimum Cooling "On" Time | 180s | 20s |
18 | | Minimum Heat "On" Time | 180s | 180s |
19 | | Min Cool "Off" Time (Fridge Constant Mode) | 600s | 60s |
20 | | Min time between switching between heat & cool | 600s | 600s |
21 |
22 |
23 | :::{Warning}
24 | Low Delay mode should never be used with compressor-based cooling as it may damage your equipment. Low Delay mode is intended for other types of cooling, such as glycol, chilled water pumps, fans/ice, or peltier coolers.
25 | :::
26 |
27 |
28 | ### Rotate TFT
29 |
30 | TFT-based builds (ESP32) can have the display rotated if it is inserted in the case upside down (or the manufacturer has changed the default orientation). If your screen is upside-down, toggle this on.
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/docs/source/Installing the Firmware.md:
--------------------------------------------------------------------------------
1 | # Installing the Firmware
2 |
3 | ## BrewFlasher & Fermentrack
4 |
5 | The easiest way to install the firmware is using either [BrewFlasher](http://www.brewflasher.com/), [BrewFlasher Web Edition](https://web.brewflasher.com/) or the firmware flow in [Fermentrack](http://www.fermentrack.com/).
6 |
7 | BrewFlasher is a standalone application for MacOS and Windows that allows for the firmware to be automatically downloaded & flashed to your controller. It was specifically designed to make flashing *this* project easy. For most users, this is the ideal installation method.
8 |
9 | BrewFlasher Web Edition is a browser-based version of BrewFlasher that allows you to install firmware using a compatible web browser without needing to download or install the desktop version of BrewFlasher. It supports the same list of firmware as BrewFlasher, but requires that you
10 |
11 | Fermentrack is a web interface that BrewPi controllers can connect to/be managed by. If you were already planning on using Fermentrack to manage your BrewPi controller then this is a perfect alternative to either using BrewFlasher or flashing manually.
12 |
13 |
14 | ## esptool
15 |
16 | The firmware can also be installed using esptool (which is what BrewFlasher uses behind-the-scenes). This is not recommended for most users, as you will need to craft the correct command to flash the correct files to the proper offsets, which will change depending on the specific firmware you are looking to flash.
17 |
18 |
19 |
20 | ## NodeMCU Flasher for Windows (ESP8266-only)
21 |
22 | ESP8266 modules can also be flashed using [NodeMCU-PyFlasher](https://github.com/marcelstoer/nodemcu-pyflasher).
23 |
24 | # Configuring WiFi
25 | Once you've flashed firmware to your ESP device, you'll need to configure it to connect to your WiFi network. For that purpose, the firmware creates a WiFi access point named `BrewPiAP`, with a password of `brewpiesp`. Connect to that access point and, if your device doesn't pull up a configuration page on its own, browse to `http://192.168.4.1`. Then click on **Configure WiFi,** and configure it to connect to your WiFi network.
26 |
--------------------------------------------------------------------------------
/docs/source/Selecting an ESP Board.md:
--------------------------------------------------------------------------------
1 | # Selecting a Board
2 |
3 | The BrewPi-ESP project supports a number of different microcontrollers with differing features. Supported controllers include:
4 |
5 | | **Microcontroller** | **DS18b20 Temp Sensors** | **Connected Relays** | **WiFi Support** | **LCD2004 (IIC) Support** | **TFT Screen Support** | **Kasa WiFi Relay** | **Tilt/Inkbird Bluetooth Temp Sensors** |
6 | |---------------------|--------------------------|----------------------|--------------------|---------------------------|------------------------|---------------------|-----------------------------------------|
7 | | Arduino* | :heavy_check_mark: | :heavy_check_mark: | | :heavy_check_mark:* | | | |
8 | | ESP8266 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | | |
9 | | ESP32 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
10 | | ESP32-S2 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | :heavy_check_mark: | |
11 |
12 | **Note** - "Classic" BrewPi builds are based on Arduinos, which are shown in the table above for comparison. There is an (optional) IIC-compatible build of the Arduino firmware available, but "classic" builds did not support this feature.
13 |
14 | For new builds, I recommend the ESP32 as it supports the widest range of features. The specific ESP32 board I recommend is the [LoLin D32 Pro](https://www.aliexpress.us/item/2251832696801305.html) alongside their [TFT Screen](https://www.aliexpress.us/item/2251832733414978.html) and [TFT Cable](https://www.aliexpress.us/item/2251832662518722.html).
15 |
16 | For smaller builds or builds using existing PCBs designed for the ESP8266 I recommend the [LoLin S2 Mini](https://www.aliexpress.us/item/3256802958877264.html). This is a pin-compatible replacement for the LoLin D1 Mini and can be dropped into most existing builds.
17 |
18 | I maintain a separate repo that contains all of my hardware designs on [GitHub](https://github.com/thorrak/thorrak_hardware/blob/master/BrewPi-ESP8266.md) with full BoMs and build instructions, as well as 3D-printable case designs. For a full how-to on building, take a look there.
19 |
--------------------------------------------------------------------------------
/docs/source/Solder Free BrewPi.md:
--------------------------------------------------------------------------------
1 | # Building a "Solder Free" Brewpi
2 |
3 | Through the combination of the ESP32 firmware, Bluetooth support, and Kasa WiFi Switch support, it is now possible to build a BrewPi temperature controller without the need to solder anything. Here's how to do it:
4 |
5 |
6 |
7 | ## Bill of Materials
8 |
9 | ### Controller
10 |
11 | * 1 x [LoLin D32 Pro](https://www.aliexpress.us/item/2251832696801305.html)
12 | * 1 x [LoLin TFT Screen](https://www.aliexpress.us/item/2251832733414978.html)
13 | * 1 x [LoLin TFT Cable](https://www.aliexpress.us/item/2251832662518722.html)
14 | * 1 x [Case (including screws)](https://github.com/thorrak/thorrak_hardware/tree/master/TiltBridge%20Containers/D32%20Pro%20Container)
15 |
16 | Although any ESP32 board can be used, and the screen/case are not mandatory, I find that the above hardware in combination with a 3D printed case works perfectly.
17 |
18 |
19 | ### Other Components
20 |
21 | * 1-2 x [Kasa Smart Plug](https://www.kasasmart.com/us/products/smart-plugs/kasa-smart-plug-mini-ep10) (Heat/Cool Switches)
22 | * 1 x [Inkbird IBS-TH2](https://www.amazon.com/Inkbird-Thermometer-Wireless-Bluetooth-Temperature/dp/B08S3CGZ3Q/) (Fridge Temp Sensor)
23 | * 1 x [Tilt Pro Hydrometer](https://tilthydrometer.com/products/tilt-pro-wireless-hydrometer-and-thermometer) (Beer Temp Sensor)
24 | * 1 x [Inkbird IBS-TH1 Plus](https://www.amazon.com/Inkbird-Bluetooth-Temperature-Thermometer-Hygrometer/dp/B07DQNFJVL/) (Beer Temp Sensor)
25 |
26 | You only need one of the Tilt Pro or Inkbird IBS-TH1 Plus to act as a beer temperature sensor -- The Tilt Pro is inserted directly into your beer and will measure the temperature floating on top, or you can use an Inkbird IBS-TH1 Plus which has a wired temperature sensor that can be snaked into a thermowell. Although regular, non-pro Tilts can be used, I do not recommend them as the thermometer only measures in whole-degree increments.
27 |
28 | The EP10 Mini Kasa Smart Plug linked above supports loads up to 15A sustained, which should be sufficient for most heating/cooling setups -- please be sure not to overload the switch.
29 |
30 |
31 | ## Instructions
32 |
33 | Assembly/setup generally takes 10 minutes or less. To set up your controller, simply follow these steps:
34 |
35 | 1. If using the case, secure the LoLin D32 Pro into the case bottom using the appropriate screws.
36 | 2. Plug the LoLin TFT Screen into the D32 Pro using the LoLin TFT Cable
37 | 3. If using the case, insert the screen/cable into the case, and secure the case lid to the case base using the appropriate screws
38 | 4. Flash the BrewPi-ESP WiFi firmware to your D32 Pro using [these instructions](Installing%20the%20Firmware.md)
39 | 5. Using a phone or other WiFi device, connect to the "BrewPiAP" WiFi network that your controller creates and connect it to your WiFi network
40 | 5. Connect the Kasa Smart Plug to the same WiFi network as your BrewPi by following the instructions included with the switches
41 | 6. Using a phone or other WiFi device connected to the same WiFi network, log into the web interface by typing the IP address displayed in the lower left corner of the BrewPi screen into a web browser
42 | 7. Click "Set Up Sensors/Actuators" and assign the appropriate functions to your Kasa switches, Inkbird temperature sensor, and Tilt hydrometer
43 | 8. Connect your controller to your installation of [Fermentrack](http://www.fermentrack.com/) or [BrewPi Remix](http://www.brewpiremix.com/)
44 |
45 | Enjoy your new BrewPi temperature controller!
46 |
--------------------------------------------------------------------------------
/docs/source/Supported Sensors & Actuators.md:
--------------------------------------------------------------------------------
1 | # Supported Temperature Sensors & Switches/Actuators
2 |
3 |
4 | ## Actuators (Switches/Relays)
5 |
6 | Two types of actuators are currently supported: Pin-based and Kasa WiFi Switches:
7 |
8 | ### Pin-based Actuators
9 |
10 | Pin-based actuators are the traditional type used with BrewPi where an output pin on the controller turns on/off based on whether the controller is calling for heating or cooling. This pin is typically then connected to a relay which then switches the load of the heater/cooler. The "sainsmart" style relay boards are slightly unintuitive in that the pin being "high" (on) actually results in the load being turned _off_. To resolve this, there is an "Invert Pin" option that can be set to ensure that these style of boards are properly toggled on/off.
11 |
12 | :::{important}
13 | When setting up a pin, make sure that the device is off when you expect it to be off, and is on when you expect it to be on. Setting the "invert" flag incorrectly can reverse these, resulting in frozen beer (or worse, if your heater runs indefinitely!)
14 | :::
15 |
16 | ### TPLink Kasa WiFi Smart Switches
17 |
18 | Kasa WiFi Switches are "smart" plugs which allow for your cooling/heating source to be plugged into a WiFi-enabled device that can then be toggled over your network. BrewPi-ESP detects these devices when connected to the same WiFi network, and can control them without using TP Link's cloud. Initial connection of these devices to the internet (along with initial setup) is completed in the Kasa smart phone app -- once complete, these devices should be detected by BrewPi-ESP.
19 |
20 |
21 | ## Temperature Sensors
22 |
23 | There are three types of temperature sensors supported by BrewPi-ESP: OneWire (DS18b20) temperature sensors, Inkbird bluetooth temperature sensors, and Tilt Pro hydrometers. All three types of temperature sensors allow for a calibration offset to be defined: An amount - specified in 1/16 degree C - that will be added to/subtracted from each reading.
24 |
25 |
26 | ### OneWire Sensors (DS18b20)
27 |
28 | OneWire (DS18b20) temperature sensors are the type traditionally used with BrewPi, and are hard-wired to the controller. They can often be purchased in stainless, waterproof housing, connected to several meter long cables, ready for insertion into a thermowell. Most of these sensors are powered via discrete power, but parasite power versions exist -- BrewPi-ESP will not function with parasitic sensors.
29 |
30 |
31 | ### Inkbird Bluetooth Temperature Sensors
32 |
33 | Inkbird manufactures a number of wireless bluetooth temperature sensors, several of which have been tested and work with BrewPi-ESP:
34 |
35 | * Inkbird IBS-TH1 Plus
36 | * Inkbird IBS-TH2 (both temperature only and temperature + humidity)
37 | * Inkbird IBS-TH2 Plus
38 |
39 | The "plus" versions of these sensors typically come with an extendable temperature probe that can be inserted into a thermowell, and oftentimes also include a display.
40 |
41 |
42 | ### Tilt Hydrometers
43 |
44 | Tilt hydrometers are bluetooth devices that measure both the specific gravity and temperature of your fermenting beer. There are two versions available - the Tilt and the Tilt Pro. The Tilt Pro offers temperature resolution of 0.1 F whereas the regular Tilt offers temperature resolution of whole degrees fahrenheit. The Tilt is an ideal solution for setups that lack a thermowell (or instances where the Tilt would be utilized regardless).
45 |
46 | :::{note}
47 | Due to their higher thermal mass and finer resolution, temperature control using a Tilt is only recommended with the Tilt Pro. Use of a non-Pro tilt is possible, but will result in less accurate temperature control.
48 | :::
49 |
50 |
--------------------------------------------------------------------------------
/docs/source/Web Interface.md:
--------------------------------------------------------------------------------
1 | # Using the BrewPi-ESP Web Interface
2 |
3 |
4 | ## Dashboard
5 |
6 | The dashboard contains a "virtual" LCD showing the state of the controller, as well as dashboard panels breaking out the various control points. From this panel you can also change the control mode the controller is using to manage temperatures by clicking the "Change" link on the Control Mode panel.
7 |
8 |
9 | ### Changing Control Mode
10 |
11 | After clicking the "Change" link a window will pop up allowing you to select the new control mode. There are three selectable modes from the web interface, and one mode that may appear if the controller is connected to BrewPi Remix or Fermentrack:
12 |
13 | * **Off** - Temperature control is disabled, and cooling/heating will be turned off
14 | * **Fridge Constant** - The controller will control the fridge/chamber temperature to match a setpoint
15 | * **Beer Constant** - The controller will control the beer temperature, using the fridge temperature as an input to the algorithm
16 | * **Beer Profile** - _Not selectable from the web interface_ - If the controller is connected to BrewPi Remix or Fermentrack and is currently applying a fermentation temperature profile, the controller will be placed in Beer Profile mode. Beer Profile mode is not selectable from the web interface as management of the profile is handled by Fermentrack/BrewPi Remix.
17 |
18 | When selecting Fridge Constant or Beer Constant mode you will be asked to provide a temperature setpoint to control to in the temperature units selected on the controller.
19 |
20 |
21 | ## Set up Sensors/Actuators
22 |
23 | BrewPi-ESP is designed to read temperatures from a number of different types of temperature data sources and use that to control temperature by actuating several types of switches. In order for this to work, BrewPi-ESP must be told which temperature sensors correspond with each data type (beer temp, fridge temp, or room temp) and which actuators correspond to heating/cooling. The Set Up Sensors/Actuators page allows you to see all sensors/actuators known to the controller and assign each device the relevant function.
24 |
25 | More information on supported sensors and actuators can be found in [](Supported Sensors & Actuators.md).
26 |
27 |
28 | ## Controller Settings
29 |
30 | The Controller Settings page allows you to toggle certain settings associated with the controller. A discussion of these settings can be found in [](Controller Configuration Options.md).
31 |
32 |
33 | ## About Controller
34 |
35 | The About Controller page allows you to see the controller's firmware version, the time since last reboot, some debugging information around what caused the last reboot, and the amount of free memory available on the controller.
36 |
37 |
38 | ## Technical Notes
39 |
40 | The BrewPi-ESP front end is written in JavaScript + Vue. The source files for the interface are saved to a [separate repository on GitHub](https://github.com/thorrak/brewpi_esp_ui) and are governed by a different license from BrewPi-ESP. The front end primarily speaks to the controller via a number of JSON api endpoints that were designed specifically for this purpose. Please be aware that these endpoints are not expected to remain static between firmware versions, and _will_ change without notice.
41 | s
--------------------------------------------------------------------------------
/docs/source/conf.py:
--------------------------------------------------------------------------------
1 | # Configuration file for the Sphinx documentation builder.
2 | #
3 | # For the full list of built-in configuration values, see the documentation:
4 | # https://www.sphinx-doc.org/en/master/usage/configuration.html
5 |
6 | # -- Project information -----------------------------------------------------
7 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
8 |
9 | project = 'BrewPi-ESP'
10 | copyright = '2023, John Beeler'
11 | author = 'John Beeler'
12 |
13 | # -- General configuration ---------------------------------------------------
14 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
15 |
16 | extensions = ['myst_parser']
17 |
18 | myst_enable_extensions = ["colon_fence"]
19 |
20 | templates_path = ['_templates']
21 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
22 |
23 |
24 |
25 | # -- Options for HTML output -------------------------------------------------
26 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
27 |
28 | html_theme = 'sphinx_rtd_theme'
29 | html_static_path = ['_static']
30 |
--------------------------------------------------------------------------------
/docs/source/index.md:
--------------------------------------------------------------------------------
1 | .. BrewPi-ESP documentation master file, created by
2 | sphinx-quickstart on Thu Mar 2 08:43:24 2023.
3 | You can adapt this file completely to your liking, but it should at least
4 | contain the root `toctree` directive.
5 |
6 | Welcome to BrewPi-ESP's documentation!
7 | ======================================
8 |
9 |
10 | :::{toctree}
11 | :maxdepth: 1
12 | Installing the Firmware.md
13 | Controller Configuration Options.md
14 | Selecting an ESP Board.md
15 | Solder Free BrewPi.md
16 | Web Interface.md
17 | Supported Sensors & Actuators.md
18 | :::
19 |
20 |
21 |
22 |
23 | Indices and tables
24 | ==================
25 |
26 | * :ref:`genindex`
27 | * :ref:`modindex`
28 | * :ref:`search`
29 |
--------------------------------------------------------------------------------
/lib/readme.txt:
--------------------------------------------------------------------------------
1 |
2 | This directory is intended for the project specific (private) libraries.
3 | PlatformIO will compile them to static libraries and link to executable file.
4 |
5 | The source code of each library should be placed in separate directory, like
6 | "lib/private_lib/[here are source files]".
7 |
8 | For example, see how can be organized `Foo` and `Bar` libraries:
9 |
10 | |--lib
11 | | |--Bar
12 | | | |--docs
13 | | | |--examples
14 | | | |--src
15 | | | |- Bar.c
16 | | | |- Bar.h
17 | | |--Foo
18 | | | |- Foo.c
19 | | | |- Foo.h
20 | | |- readme.txt --> THIS FILE
21 | |- platformio.ini
22 | |--src
23 | |- main.c
24 |
25 | Then in `src/main.c` you should use:
26 |
27 | #include
28 | #include
29 |
30 | // rest H/C/CPP code
31 |
32 | PlatformIO will find your libraries automatically, configure preprocessor's
33 | include paths and build them.
34 |
35 | More information about PlatformIO Library Dependency Finder
36 | - http://docs.platformio.org/en/stable/librarymanager/ldf.html
37 |
--------------------------------------------------------------------------------
/scripts/gen_version.py:
--------------------------------------------------------------------------------
1 | # Generate the Version.h file
2 | # Stitches together various bits of version information from the environment
3 |
4 | import subprocess
5 | import os
6 |
7 | # This was the value used in the static Version.h. It is unclear what merits
8 | # an increment, so it is being included unchanged.
9 | release = "0.2.4"
10 |
11 | # Get the name of the "nearest" tag (decorated with revision information if
12 | # changes have happened since that tag)
13 | # See the man page of git-describe for more details
14 | tag_name = (
15 | subprocess.check_output(["git", "describe", "--always"])
16 | .strip()
17 | .decode("utf-8")
18 | )
19 |
20 | # git revision
21 | git_rev = (
22 | subprocess.check_output(["git", "rev-parse", "--short", "HEAD"])
23 | .strip()
24 | .decode("utf-8")
25 | )
26 |
27 |
28 |
29 | template = f"""
30 | #pragma once
31 | /******************************************************************************
32 | *** **** WARNING **** ****
33 |
34 | This file is auto-generated. Any changes made here will be destroyed during
35 | the next build. To make persistent changes, edit the template in
36 | /scripts/gen_version.py
37 | ******************************************************************************/
38 |
39 | namespace Config {{
40 | namespace Version {{
41 | constexpr auto release = "{release}";
42 | constexpr auto git_tag = "{tag_name}";
43 | constexpr auto git_rev = "{git_rev}";
44 | }}
45 | }};
46 | """
47 |
48 | with open('src/Version.h', 'w') as f:
49 | f.write(template)
50 |
--------------------------------------------------------------------------------
/scripts/get_port.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 |
3 | import platform
4 | Import("env")
5 |
6 | system = platform.system()
7 | if system == "Darwin":
8 | # I'll leave it up to @thorrak to figure out how to
9 | # lay this out.
10 | env["UPLOAD_PORT"] = "/dev/cu.usbserial-*"
11 | # env["UPLOAD_PORT"] = "/dev/cu.wch*"
12 | elif system == "Windows":
13 | # Windows users don't need no silly declarations
14 | # port = "COM*"
15 | # usbc = "COM*"
16 | pass
17 | elif system == "Linux":
18 | # port = "/dev/cu.usbserial-*"
19 | # usbc = "/dev/cu.wch*"
20 | pass
21 | else:
22 | pass
23 |
--------------------------------------------------------------------------------
/src/Actuator.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Matthew McGowan
3 | * Copyright 2013 BrewPi/Elco Jacobs.
4 | *
5 | * This file is part of BrewPi.
6 | *
7 | * BrewPi is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * BrewPi is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with BrewPi. If not, see .
19 | */
20 |
21 | #include "Brewpi.h"
22 | #include "Actuator.h"
23 |
--------------------------------------------------------------------------------
/src/Actuator.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Matthew McGowan
3 | * Copyright 2013 BrewPi/Elco Jacobs.
4 | *
5 | * This file is part of BrewPi.
6 | *
7 | * BrewPi is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * BrewPi is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with BrewPi. If not, see .
19 | */
20 |
21 | #pragma once
22 |
23 | #include "Brewpi.h"
24 | #include "FastDigitalPin.h"
25 |
26 | #define ACTUATOR_VIRTUAL 1
27 |
28 | #if ACTUATOR_VIRTUAL
29 | #define ACTUATOR_METHOD virtual
30 | #define ACTUATOR_METHOD_IMPL =0
31 | #define ACTUATOR_BASE_CLASS_DECL : public Actuator
32 | #else
33 | #define ACTUATOR_METHOD inline
34 | #define ACTUATOR_METHOD_IMPL {}
35 | #define ACTUATOR_BASE_CLASS_DECL
36 | #endif
37 |
38 |
39 | /**
40 | * An actuator simply turns something on or off.
41 | */
42 | class Actuator
43 | {
44 | public:
45 | /**
46 | * Set the state of the actuator
47 | *
48 | * @param active - New state
49 | */
50 | ACTUATOR_METHOD void setActive(bool active) ACTUATOR_METHOD_IMPL;
51 |
52 | /**
53 | * Check if current actuator state is active
54 | */
55 | ACTUATOR_METHOD bool isActive() ACTUATOR_METHOD_IMPL;
56 | #if ACTUATOR_VIRTUAL
57 | virtual ~Actuator() {}
58 | #endif
59 |
60 | };
61 |
62 | /**
63 | * An actuator that simply remembers the set value.
64 | * This is primary used for testing.
65 | */
66 | class ValueActuator ACTUATOR_BASE_CLASS_DECL
67 | {
68 | public:
69 | ValueActuator() : state(false) {}
70 | ValueActuator(bool initial) : state(initial) {}
71 |
72 | ACTUATOR_METHOD void setActive(bool active) { state = active; }
73 | ACTUATOR_METHOD bool isActive() { return state; }
74 |
75 | private:
76 | bool state;
77 | };
78 |
79 |
--------------------------------------------------------------------------------
/src/ActuatorArduinoPin.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "Brewpi.h"
3 | #include "Pins.h"
4 | #include "ActuatorArduinoPin.h"
5 |
--------------------------------------------------------------------------------
/src/ActuatorArduinoPin.h:
--------------------------------------------------------------------------------
1 | /*
2 | * File: ArduinoActuator.h
3 | * Author: mat
4 | *
5 | * Created on 19 August 2013, 20:32
6 | */
7 |
8 | #pragma once
9 |
10 | #include "Actuator.h"
11 |
12 | //template
13 | //class DigitalConstantPinActuator ACTUATOR_BASE_CLASS_DECL
14 | //{
15 | // private:
16 | // bool active;
17 | //
18 | // public:
19 | // DigitalConstantPinActuator() : active(false)
20 | // {
21 | // setActive(false);
22 | // fastPinMode(pin, OUTPUT);
23 | // }
24 | //
25 | // inline ACTUATOR_METHOD void setActive(bool active) {
26 | // this->active = active;
27 | // fastDigitalWrite(pin, active^invert ? HIGH : LOW);
28 | // }
29 | //
30 | // bool isActive() { return active; }
31 | //
32 | //};
33 |
34 | class DigitalPinActuator ACTUATOR_BASE_CLASS_DECL
35 | {
36 | private:
37 | bool invert;
38 | uint8_t pin;
39 | bool active;
40 | public:
41 | DigitalPinActuator(uint8_t pin, bool invert) {
42 | this->invert = invert;
43 | this->pin = pin;
44 | setActive(false);
45 | pinMode(pin, OUTPUT);
46 | }
47 |
48 | inline ACTUATOR_METHOD void setActive(bool active_setting) {
49 | this->active = active_setting;
50 | digitalWrite(pin, active_setting^invert ? HIGH : LOW);
51 | }
52 |
53 | bool isActive() { return active; }
54 | };
55 |
--------------------------------------------------------------------------------
/src/ActuatorAutoOff.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Matthew McGowan
3 | * Copyright 2013 BrewPi/Elco Jacobs.
4 | *
5 | * This file is part of BrewPi.
6 | *
7 | * BrewPi is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * BrewPi is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with BrewPi. If not, see .
19 | */
20 |
21 | #pragma once
22 |
23 | #include "Actuator.h"
24 | #include "Ticks.h"
25 |
26 | /**
27 | * An Actuator wrapper that automaically turns the wrapped Actuator off after
28 | * an elapsed timeout
29 | */
30 | class AutoOffActuator : public Actuator {
31 |
32 | public:
33 | /**
34 | * Constructor.
35 | *
36 | * @param timeout - Number of seconds to stay on after activated
37 | * @param target - Acutuator to manage
38 | */
39 | AutoOffActuator(uint16_t timeout, Actuator* target) {
40 | this->timeout = timeout;
41 | this->target = target;
42 | }
43 |
44 | /**
45 | * \brief Set the actuator state
46 | *
47 | * @param active - New state
48 | * @see Actuator::setActive()
49 | */
50 | void setActive(bool active)
51 | {
52 | this->active = active;
53 | target->setActive(active);
54 | if (active)
55 | lastActiveTime = ticks.seconds();
56 | }
57 |
58 | /**
59 | * \brief Get actuator current state
60 | */
61 | bool isActive() {
62 | return active; //target->isActive(); - this takes 20 bytes more
63 | }
64 |
65 | /**
66 | * \brief Update the actuator state.
67 | * If the timeout period has elapsed, sets the state to false.
68 | */
69 | void update() {
70 | if (ticks.timeSince(lastActiveTime)>=timeout)
71 | setActive(false);
72 | }
73 |
74 | private:
75 | uint16_t lastActiveTime; //!< Tick count when the actuator was last made active.
76 | uint16_t timeout; //!< Length of time that the actuator should be enabled before turning off.
77 | Actuator* target; //!< Target Actuator that is being controlled.
78 |
79 | /**
80 | * \brief Current actuator state.
81 | * This effectively duplicates the state that is in the target Actuator, but
82 | * by keeping value here we avoid call overhead to get that value.
83 | */
84 | bool active;
85 | };
86 |
--------------------------------------------------------------------------------
/src/ActuatorTPLink.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "Brewpi.h"
3 | #include "Pins.h"
4 | #include "ActuatorTPLink.h"
5 | #include "tplink/TPLinkScanner.h"
6 |
7 |
8 |
9 | TPLinkActuator::TPLinkActuator(const char * deviceMAC, const char * childID) {
10 | strcpy(device_mac, deviceMAC);
11 | strcpy(child_id, childID);
12 | }
13 |
14 | void TPLinkActuator::setActive(bool active) {
15 | TPLinkPlug *tp;
16 |
17 | tp = tp_link_scanner.get_tplink_plug(device_mac, child_id);
18 |
19 | if(!tp) // Unable to find the actuator in the list, we can't set active.
20 | return;
21 |
22 | if(active && !isActive())
23 | tp->set_on();
24 | else if(!active && isActive())
25 | tp->set_off();
26 | }
27 |
28 | bool TPLinkActuator::isActive() {
29 | TPLinkPlug *tp;
30 |
31 | tp = tp_link_scanner.get_tplink_plug(device_mac, child_id);
32 |
33 | if(!tp) // Unable to find the actuator in the list, lets assume it's turned off
34 | return false;
35 |
36 | return tp->last_read_on;
37 | }
38 |
--------------------------------------------------------------------------------
/src/ActuatorTPLink.h:
--------------------------------------------------------------------------------
1 | #ifndef BREWPI_ESP_ACTUATORTPLINK_H
2 | #define BREWPI_ESP_ACTUATORTPLINK_H
3 |
4 | #include "Brewpi.h"
5 | #include "Actuator.h"
6 | // #include "tplink/TPLinkScanner.h"
7 | #include "PiLink.h"
8 |
9 | /**
10 | * An actuator that operates by communicating with a TPLink Kasa Smart Switch device.
11 | *
12 | */
13 | class TPLinkActuator : public Actuator
14 | {
15 | public:
16 |
17 | TPLinkActuator(const char * deviceMAC, const char * childID);
18 |
19 | void setActive(bool active);
20 |
21 | bool isActive();
22 |
23 |
24 |
25 | private:
26 | char device_mac[18];
27 | char child_id[3];
28 | };
29 |
30 | #endif
--------------------------------------------------------------------------------
/src/Brewpi.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 BrewPi/Elco Jacobs.
3 | * Copyright 2013 Matthew McGowan.
4 | *
5 | * This file is part of BrewPi.
6 | *
7 | * BrewPi is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * BrewPi is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with BrewPi. If not, see .
19 | */
20 |
21 | #pragma once
22 |
23 | /**
24 | * \file Brewpi.h
25 | *
26 | * \brief Defines global config for the brewpi project.
27 | *
28 | * This file is included in every file in the project to ensure conditional
29 | * compilation directives are recognized.
30 | *
31 | * ConfigDefault.h contains the default settings, and produces a standard Hex
32 | * file. To customize the build, users may add settings to Config.h, or define
33 | * symbols in the project.
34 | */
35 |
36 | // have to use two levels of macro expansion to convert a symbol to a string. see http://gcc.gnu.org/onlinedocs/cpp/Stringification.html
37 | #define stringify(s) _stringifyDo(s)
38 | #define _stringifyDo(s) #s
39 |
40 |
41 | // Most pins are only conditionally defined here, allowing definitions to be provided in Config.h for
42 | // local overrides
43 | #define BREWPI_SHIELD_DIY 0
44 | #define BREWPI_SHIELD_REV_A 1
45 | #define BREWPI_SHIELD_REV_C 2
46 |
47 | #define BREWPI_BOARD_LEONARDO 'l'
48 | #define BREWPI_BOARD_STANDARD 's'
49 | #define BREWPI_BOARD_MEGA 'm'
50 | #define BREWPI_BOARD_UNKNOWN '?'
51 | #define BREWPI_BOARD_ESP8266 'e'
52 | #define BREWPI_BOARD_ESP32 '3'
53 | #define BREWPI_BOARD_ESP32C3 'c'
54 | #define BREWPI_BOARD_ESP32S2 '2'
55 |
56 |
57 | #include "Config.h"
58 | #include "ConfigDefault.h"
59 |
60 | #include
61 |
62 | #include "Actuator.h"
63 | #include "Logger.h"
64 |
65 | extern ValueActuator alarm_actuator;
66 | extern bool toggleBacklight; // To allow us to toggle the backlight
67 |
68 |
--------------------------------------------------------------------------------
/src/BrewpiStrings.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 BrewPi/Elco Jacobs.
3 | * Copyright 2013 Matthew McGowan
4 | *
5 | * This file is part of BrewPi.
6 | *
7 | * BrewPi is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * BrewPi is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with BrewPi. If not, see .
19 | */
20 |
21 | #include "Brewpi.h"
22 | #include "BrewpiStrings.h"
23 |
24 | // some useful strings
25 | const char STR_FMT_S_RAM[] PROGMEM = "%s"; // RAM string
26 | const char STR_FMT_S_PROGMEM[] PROGMEM = "%S"; // PROGMEM string
27 | const char STR_FMT_D[] PROGMEM = "%d";
28 | const char STR_FMT_U[] PROGMEM = "%u";
29 | const char STR_6SPACES[] PROGMEM = " ";
30 |
31 |
32 |
33 | #if !indexOf_inline
34 | int8_t indexOf(const char* s, char c)
35 | {
36 | char c2;
37 | int8_t idx = -1;
38 | while ((c2=s[++idx]))
39 | {
40 | if (c==c2)
41 | return idx;
42 | }
43 | return -1;
44 | }
45 | #endif
46 |
47 |
48 |
--------------------------------------------------------------------------------
/src/BrewpiStrings.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 BrewPi/Elco Jacobs.
3 | * Copyright 2013 Matthew McGowan
4 | *
5 | * This file is part of BrewPi.
6 | *
7 | * BrewPi is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * BrewPi is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with BrewPi. If not, see .
19 | */
20 |
21 | #pragma once
22 |
23 | extern const char STR_FMT_S_RAM[];
24 | extern const char STR_FMT_S_PROGMEM[];
25 | extern const char STR_FMT_U[];
26 | extern const char STR_FMT_D[];
27 | extern const char STR_6SPACES[];
28 |
29 | #define indexOf_inline 0
30 |
31 | #if indexOf_inline
32 | inline int8_t indexOf(const char* s, char c)
33 | {
34 | char c2;
35 | int8_t idx = -1;
36 | while ((c2=s[++idx]))
37 | {
38 | if (c==c2)
39 | return idx;
40 | }
41 | return -1;
42 | }
43 | #else
44 | int8_t indexOf(const char* s, char c);
45 | #endif
46 |
--------------------------------------------------------------------------------
/src/Buzzer.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Buzzer.cpp
3 | *
4 | * Copyright 2012-2013 BrewPi.
5 | *
6 | * This file is part of BrewPi.
7 | *
8 | * BrewPi is free software: you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation, either version 3 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * BrewPi is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU General Public License
19 | * along with BrewPi. If not, see .
20 | */
21 |
22 |
23 | #include "Brewpi.h"
24 | #include "Ticks.h"
25 | #include "Pins.h"
26 | #include "Buzzer.h"
27 |
28 | // TODO - Implement
29 |
30 | #if BREWPI_BUZZER
31 | #include
32 | #include "FastDigitalPin.h"
33 |
34 | #if (alarmPin != 3)
35 | #error "Check PWM settings when you want to use a different pin for the alarm"
36 | #endif
37 |
38 | #if BREWPI_BOARD == BREWPI_BOARD_LEONARDO
39 | #define BUZZER_TIMER_REG TCCR0A
40 | #define BUZZER_TIMER_REG_FLAG COM0B1
41 | #define BUZZER_TIMER_REG_INIT (void);
42 | #elif BREWPI_BOARD == BREWPI_BOARD_STANDARD
43 | #define BUZZER_TIMER_REG TCCR2A
44 | #define BUZZER_TIMER_REG_FLAG COM2B1
45 | #elif BREWPI_BOARD == BREWPI_BOARD_MEGA
46 | #define BUZZER_TIMER_REG TCCR3A
47 | #define BUZZER_TIMER_REG_FLAG COM3C1
48 | #endif
49 |
50 | #define BEEP_ON() bitSet(BUZZER_TIMER_REG,BUZZER_TIMER_REG_FLAG);
51 | #define BEEP_OFF() bitClear(BUZZER_TIMER_REG,BUZZER_TIMER_REG_FLAG);
52 |
53 | void Buzzer::init(){
54 | // set up square wave PWM for buzzer
55 | fastPinMode(alarmPin,OUTPUT);
56 |
57 | #if BREWPI_BOARD == BREWPI_BOARD_LEONARDO
58 | // Arduino Leonardo, no further setup needed - timer already active
59 | #elif BREWPI_BOARD == BREWPI_BOARD_STANDARD
60 | // Arduino UNO, buzzer is on OC2B
61 | TCCR2A = (1<isActive()) {
77 | ValueActuator::setActive(active);
78 | if (active) {
79 | BEEP_ON();
80 | }
81 | else {
82 | BEEP_OFF();
83 | }
84 | }
85 | }
86 |
87 | void Buzzer::beep(uint8_t numBeeps, uint16_t duration){
88 | for(uint8_t beepCount = 0; beepCount.
18 | */
19 |
20 | #pragma once
21 |
22 | #include "Brewpi.h"
23 | #include "Actuator.h"
24 |
25 | #if BREWPI_BUZZER
26 | class Buzzer : public ValueActuator
27 | {
28 | public:
29 | Buzzer(){};
30 | ~Buzzer(){};
31 |
32 | void init();
33 |
34 | /**
35 | * Performs a number of beeps synchronously.
36 | * @param numBeeps The number of beeps to emit
37 | * @param duration the duration of each beep
38 | */
39 | void beep(uint8_t numBeeps, uint16_t duration);
40 |
41 | void setActive(bool active);
42 |
43 | };
44 |
45 | extern Buzzer buzzer;
46 | #endif
47 |
--------------------------------------------------------------------------------
/src/CommandProcessor.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 BrewPi/Elco Jacobs.
3 | * Copyright 2013 Matthew McGowan.
4 | * Copyright 2020 Scott Peshak
5 | *
6 | * This file is part of BrewPi.
7 | *
8 | * BrewPi is free software: you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation, either version 3 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * BrewPi is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU General Public License
19 | * along with BrewPi. If not, see .
20 | */
21 | #pragma once
22 |
23 | #include
24 |
25 | /**
26 | * \brief Functions that implement protocol commands
27 | */
28 | struct CommandProcessor {
29 | public:
30 | static void receiveCommand();
31 |
32 | private:
33 | static void invalidCommand(const char inByte);
34 | static void commandNotImplemented(const char command, const String message);
35 | static void versionInfo();
36 |
37 | static void sendControlSettings();
38 | static void sendControlConstants();
39 | static void sendControlVariables();
40 | static void sendExtendedSettings();
41 |
42 | static void setDefaultConstants();
43 | static void setDefaultSettings();
44 |
45 | static void processSettingsJson();
46 | static void processExtendedSettingsJson();
47 |
48 | static void printTemperatures();
49 | static void printRawTemperatures();
50 |
51 | // Hardware state
52 | static void setAlarmState(bool enabled);
53 | static void listDevices();
54 | static void listHardware();
55 | static void resetWiFi();
56 | static void wifiInfo();
57 | static void parseDeviceDefinition();
58 |
59 | // LCD
60 | static void toggleBacklight();
61 | static void getLcdContent();
62 |
63 | // EEPROM
64 | static void initEeprom();
65 |
66 | // Device name
67 | static void printDeviceNames();
68 | static void setDeviceNames();
69 |
70 | static void processSettingKeypair(JsonPair);
71 | };
72 |
--------------------------------------------------------------------------------
/src/DS2413.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Matthew McGowan
3 | * Copyright 2013 BrewPi/Elco Jacobs.
4 | *
5 | * This file is part of BrewPi.
6 | *
7 | * BrewPi is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * BrewPi is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with BrewPi. If not, see .
19 | */
20 |
21 | #if BREWPI_DS2413
22 | #include "Brewpi.h"
23 |
24 | #include
25 |
26 | #include "DS2413.h"
27 |
28 |
29 |
30 | /*
31 | * Read all values at once, both current state and sensed values. The read performs data-integrity checks.
32 | * Returns a negative result if the device cannot be read successfully within the given number of tries.
33 | * The lower 4-bits are the values as described under PIO ACCESSS READ [F5h] in the ds2413 datasheet:
34 | * b0: PIOA state
35 | * b1: PIOA output latch state
36 | * b2: PIOB state
37 | * b3: PIOB output latch state
38 | */
39 | byte DS2413::accessRead(uint8_t maxTries) /* const */
40 | {
41 | #define ACCESS_READ 0xF5
42 |
43 | oneWire->reset();
44 | oneWire->select(address);
45 | oneWire->write(ACCESS_READ);
46 |
47 | bool success = false;
48 | uint8_t data;
49 | do
50 | {
51 | data = oneWire->read();
52 | success = (data>>4)==(!data&0xF);
53 | data &= 0xF;
54 | } while (!success && maxTries-->0);
55 |
56 | oneWire->reset();
57 | return success ? data : data|0x80;
58 | }
59 |
60 | /*
61 | * Writes the state of all PIOs in one operation.
62 | * /param b pio data - PIOA is bit 0 (lsb), PIOB is bit 1
63 | * /param maxTries the maximum number of attempts before giving up.
64 | * /return true on success
65 | */
66 | bool DS2413::accessWrite(uint8_t b, uint8_t maxTries)
67 | {
68 | #define ACCESS_WRITE 0x5A
69 | #define ACK_SUCCESS 0xAA
70 | #define ACK_ERROR 0xFF
71 |
72 | b |= 0xFC; /* Upper 6 bits should be set to 1's */
73 | uint8_t ack = 0;
74 | do
75 | {
76 | oneWire->reset();
77 | oneWire->select(address);
78 | oneWire->write(ACCESS_WRITE);
79 | oneWire->write(b);
80 |
81 | /* data is sent again, inverted to guard against transmission errors */
82 | oneWire->write(~b);
83 | /* Acknowledgement byte, 0xAA for success, 0xFF for failure. */
84 | ack = oneWire->read();
85 |
86 | if (ack==ACK_SUCCESS)
87 | oneWire->read(); // status byte sent after ack
88 |
89 | //out.print("tries "); out.print(maxTries); out.print(" ack ");out.print(ack, HEX);out.print(" newValues ");out.print(newSettings, HEX);
90 | //out.println();
91 | } while (ack!=ACK_SUCCESS && maxTries-->0);
92 |
93 | oneWire->reset();
94 | return ack==ACK_SUCCESS;
95 | }
96 |
97 | #endif
--------------------------------------------------------------------------------
/src/DallasTempNG.cpp:
--------------------------------------------------------------------------------
1 | #include "DallasTempNG.h"
2 |
3 | typedef uint8_t ScratchPad[9];
4 |
5 | // Scratchpad locations
6 | #define TEMP_LSB 0
7 | #define TEMP_MSB 1
8 | #define HIGH_ALARM_TEMP 2
9 | #define LOW_ALARM_TEMP 3
10 | #define CONFIGURATION 4
11 | #define INTERNAL_BYTE 5
12 | #define COUNT_REMAIN 6
13 | #define COUNT_PER_C 7
14 | #define SCRATCHPAD_CRC 8
15 |
16 |
17 | bool detectedReset(DallasTemperature &sensor, const uint8_t* scratchPad) {
18 | bool reset = (scratchPad[HIGH_ALARM_TEMP]==0);
19 | return reset;
20 | }
21 |
22 | bool initConnection(DallasTemperature &sensor, const uint8_t* deviceAddress) {
23 | ScratchPad scratchPad;
24 |
25 | if (!sensor.isConnected(deviceAddress, scratchPad)) {
26 | return false;
27 | }
28 |
29 | // assume the sensor has just been powered on. So this should only be called on initializtion, or
30 | // after a device was disconnected.
31 | if (scratchPad[HIGH_ALARM_TEMP]) { // conditional to avoid wear on eeprom.
32 | scratchPad[HIGH_ALARM_TEMP] = 0;
33 | sensor.writeScratchPad(deviceAddress, scratchPad);
34 | sensor.saveScratchPad(deviceAddress); // save to eeprom
35 |
36 | // check if the write was successful (HIGH_ALARAM_TEMP == 0)
37 | if (!sensor.isConnected(deviceAddress, scratchPad) || !detectedReset(sensor, scratchPad))
38 | return false;
39 | }
40 |
41 | scratchPad[HIGH_ALARM_TEMP]=1;
42 | sensor.writeScratchPad(deviceAddress, scratchPad); // don't save to eeprom, so that it reverts to 0 on reset
43 | // from this point on, if we read a scratchpad with a 0 value in HIGH_ALARM (detectedReset() returns true)
44 | // it means the device has reset or the previous write of the scratchpad above was unsuccessful.
45 | // Either way, initConnection() should be called again
46 | return true;
47 | }
48 |
49 |
50 | int16_t getTempRaw(DallasTemperature &sensor, const uint8_t* deviceAddress)
51 | {
52 | ScratchPad scratchPad;
53 | if (sensor.isConnected(deviceAddress, scratchPad) && !detectedReset(sensor, scratchPad))
54 | return sensor.getTemp(deviceAddress) >> 3;
55 | return DEVICE_DISCONNECTED_RAW; // use a value that the sensor could not ordinarily measure
56 | }
57 |
--------------------------------------------------------------------------------
/src/DallasTempNG.h:
--------------------------------------------------------------------------------
1 | #ifndef BREWPI_ESP_DALLAS_TEMP_NG_H
2 | #define BREWPI_ESP_DALLAS_TEMP_NG_H
3 |
4 | #include
5 | #include
6 |
7 | bool initConnection(DallasTemperature &sensor, const uint8_t* deviceAddress);
8 | int16_t getTempRaw(DallasTemperature &sensor, const uint8_t* deviceAddress);
9 |
10 | #endif // BREWPI_ESP_DALLAS_TEMP_NG_H
--------------------------------------------------------------------------------
/src/DeviceNameManager.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Scott Peshak
3 | * Copyright 2013 BrewPi/Elco Jacobs.
4 | *
5 | * This file is part of BrewPi.
6 | *
7 | * BrewPi is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * BrewPi is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with BrewPi. If not, see .
19 | */
20 |
21 |
22 | #include "DeviceNameManager.h"
23 | #include "ESPEepromAccess.h" // Includes filesystem headers/definition
24 |
25 | /**
26 | * \brief Set a human readable name for a device.
27 | * \param device - The identifier for the device, most commonly the OneWire device address (in hex)
28 | * \param name - The name to set
29 | */
30 | void DeviceNameManager::setDeviceName(const char* device, const char* name)
31 | {
32 | char filename[32];
33 | DeviceNameManager::deviceNameFilename(filename, device);
34 |
35 | File f = FILESYSTEM.open(filename, "w");
36 |
37 | if (f) {
38 | f.print(name);
39 | f.close();
40 | }
41 | }
42 |
43 |
44 | /**
45 | * \brief Get the human readable name for a device.
46 | *
47 | * If no name has been registered, the device ID will be returned.
48 | * \param device - The identifier for the device, most commonly the OneWire device address (in hex)
49 | * \return The registered device name, or if none is set, the provided device ID
50 | */
51 | String DeviceNameManager::getDeviceName(const char* device) {
52 | char filename[32];
53 | DeviceNameManager::deviceNameFilename(filename, device);
54 |
55 | if (FILESYSTEM.exists(filename)) {
56 | File f = FILESYSTEM.open(filename, "r");
57 | if (f) {
58 | String res = f.readString();
59 | f.close();
60 | return res;
61 | }
62 | }
63 |
64 | return device;
65 | }
66 |
67 |
68 | /**
69 | * \brief Get the Filename that contains the device human name metadata for a given device.
70 | * \param device - The identifier for the device, most commonly the OneWire device address (in hex)
71 | */
72 | inline void DeviceNameManager::deviceNameFilename(char* filename, const char* device) {
73 | strcpy(filename, DeviceNameManager::filenamePrefix);
74 | strncat(filename, device, 32 - DeviceNameManager::prefixLength());
75 | }
76 |
77 |
78 | /**
79 | * \brief Prefix used when building device name filenames
80 | *
81 | * This helps disambiguate the name files from other data, and makes it easier
82 | * to produce a list of named probes.
83 | */
84 | const char DeviceNameManager::filenamePrefix[] = "/dn/";
85 |
86 | /**
87 | * \brief Calculate length of DeviceNameManager::filenamePrefix
88 | *
89 | * This is done as a constexpr so it can be calculated at compile time
90 | */
91 | constexpr int DeviceNameManager::prefixLength() {
92 | return strlen(DeviceNameManager::filenamePrefix);
93 | }
94 |
95 |
96 | /**
97 | * \brief Delete a configured device name
98 | * \param device - The identifier for the device, most commonly the OneWire device address (in hex)
99 | */
100 | void DeviceNameManager::deleteDeviceName(const char* device) {
101 | char filename[32];
102 | DeviceNameManager::deviceNameFilename(filename, device);
103 |
104 | FILESYSTEM.remove(filename);
105 | }
106 |
107 |
108 | #if defined(ESP32)
109 | /**
110 | * \brief Get list of configured device names
111 | */
112 | void DeviceNameManager::enumerateDeviceNames(JsonDocument& doc) {
113 | File root = FILESYSTEM.open(filenamePrefix);
114 |
115 | File file = root.openNextFile();
116 |
117 | while(file){
118 | DeviceName dn = filenameToDeviceName(file.name());
119 | doc[dn.device] = dn.name;
120 |
121 | // Move to the next file
122 | file = root.openNextFile();
123 | }
124 | }
125 |
126 | #else
127 |
128 | /**
129 | * \brief Get list of configured device names
130 | */
131 | void DeviceNameManager::enumerateDeviceNames(JsonDocument& doc) {
132 | // This is ESP8266 only
133 | Dir dir = FILESYSTEM.openDir(filenamePrefix);
134 |
135 | while (dir.next()) {
136 | DeviceName dn = filenameToDeviceName(dir.fileName());
137 | doc[dn.device] = dn.name;
138 | }
139 | }
140 | #endif
141 |
142 |
143 | /**
144 | * \brief Given a filename, get a DeviceName
145 | *
146 | * \param filename
147 | */
148 | DeviceName DeviceNameManager::filenameToDeviceName(String filename) {
149 | // strip the prefix off
150 | filename = filename.substring(prefixLength());
151 |
152 | return DeviceName(filename, getDeviceName(filename.c_str()));
153 | }
154 |
--------------------------------------------------------------------------------
/src/DeviceNameManager.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Scott Peshak
3 | * Copyright 2013 BrewPi/Elco Jacobs.
4 | *
5 | * This file is part of BrewPi.
6 | *
7 | * BrewPi is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * BrewPi is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with BrewPi. If not, see .
19 | */
20 |
21 | #pragma once
22 |
23 | #include "Brewpi.h"
24 | #include
25 |
26 | /**
27 | * \brief Tuple of device name and ID
28 | */
29 | struct DeviceName
30 | {
31 | String name; //!< Human readable name
32 | String device; //!< Device ID
33 |
34 | DeviceName(String device, String name): name(name), device(device){}
35 | };
36 |
37 |
38 |
39 | /**
40 | * \brief Class to manage human readable names for devices
41 | */
42 | class DeviceNameManager
43 | {
44 | public:
45 | static void setDeviceName(const char* device, const char* name);
46 | static String getDeviceName(const char* device);
47 | static void deleteDeviceName(const char* device);
48 |
49 | static void enumerateDeviceNames(JsonDocument& doc);
50 |
51 | private:
52 | static void deviceNameFilename(char* filename, const char* device);
53 | static DeviceName filenameToDeviceName(String filename);
54 |
55 | static const char filenamePrefix[];
56 | static constexpr int prefixLength();
57 | };
58 |
--------------------------------------------------------------------------------
/src/Display.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 BrewPi/Elco Jacobs.
3 | *
4 | * This file is part of BrewPi.
5 | *
6 | * BrewPi is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later v7ersion.
10 | *
11 | * BrewPi is dist7ributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with BrewPi. If not, see .
18 | */
19 |
20 | #include "Brewpi.h"
21 | #include
22 |
23 | #include "Display.h"
24 |
25 |
26 | #if DISPLAY_POLYMORPHIC
27 | Display::~Display() { }
28 | #endif
29 |
30 |
--------------------------------------------------------------------------------
/src/Display.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 BrewPi/Elco Jacobs.
3 | * Copyright 2013 Matthew McGowan.
4 | *
5 | * This file is part of BrewPi.
6 | *
7 | * BrewPi is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * BrewPi is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with BrewPi. If not, see .
19 | */
20 |
21 | #pragma once
22 |
23 | /**
24 | * \defgroup display LCD Display
25 | * \brief Support for different LCD display types
26 | *
27 | * \addtogroup display
28 | * @{
29 | *
30 | * \file Display.h
31 | * \brief To use the display, include this file.
32 | *
33 | * It takes care of setting DisplayType to the appropriate type of display
34 | * according to the compile-time config.
35 | */
36 |
37 | #include "DisplayBase.h"
38 | #include "DisplayLcd.h"
39 |
40 | typedef LcdDisplay DisplayType;
41 |
42 |
43 | extern DisplayType DISPLAY_REF display;
44 |
45 | /** @} */
46 |
--------------------------------------------------------------------------------
/src/DisplayLcd.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 BrewPi/Elco Jacobs.
3 | *
4 | * This file is part of BrewPi.
5 | *
6 | * BrewPi is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * BrewPi is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with BrewPi. If not, see .
18 | */
19 |
20 | #pragma once
21 |
22 | #include "Brewpi.h"
23 | #include "DisplayBase.h"
24 |
25 | // If BREWPI_TFT is set, we're going to use the DisplayTFT headers instead
26 | #ifdef BREWPI_TFT
27 | #include "DisplayTFT.h"
28 | #else
29 |
30 | /*
31 | * \addtogroup display
32 | * @{
33 | */
34 |
35 | #if BREWPI_EMULATE || !BREWPI_LCD
36 | #include "NullLcdDriver.h"
37 | typedef NullLcdDriver LcdDriver;
38 | #elif defined(BREWPI_OLED)
39 | #include "OLEDFourBit.h"
40 | typedef OLEDFourBit LcdDriver;
41 | #elif defined(BREWPI_IIC)
42 | #include "IicLcd.h"
43 | typedef IIClcd LcdDriver;
44 | #elif defined(BREWPI_SHIFT_LCD)
45 | #include "SpiLcd.h"
46 | typedef SpiLcd LcdDriver;
47 | #else
48 | #error "Wrong LCD type! Select one in Config.h."
49 | #endif
50 |
51 |
52 | /**
53 | * \brief LCD Display Content
54 | *
55 | * This class handles the content of the LCD. It dispatches to the various
56 | * hardware driver implementations to actually display the content
57 | */
58 | class LcdDisplay DISPLAY_SUPERCLASS
59 | {
60 | public:
61 | // initializes the lcd display
62 | DISPLAY_METHOD void init();
63 |
64 | /**
65 | * Print all display content
66 | */
67 | DISPLAY_METHOD void printAll() {
68 | printStationaryText();
69 | printState();
70 | printAllTemperatures();
71 | printMode();
72 | updateBacklight();
73 | }
74 |
75 | DISPLAY_METHOD void printAllTemperatures();
76 |
77 | // print the stationary text on the lcd.
78 | DISPLAY_METHOD void printStationaryText();
79 |
80 | // print mode on the right location on the first line, after Mode:
81 | DISPLAY_METHOD void printMode();
82 |
83 | DISPLAY_METHOD void setDisplayFlags(uint8_t newFlags);
84 | DISPLAY_METHOD uint8_t getDisplayFlags() { return flags; };
85 |
86 | // print beer temperature at the right place on the display
87 | DISPLAY_METHOD void printBeerTemp();
88 |
89 | // print beer temperature setting at the right place on the display
90 | DISPLAY_METHOD void printBeerSet();
91 |
92 | // print fridge temperature at the right place on the display
93 | DISPLAY_METHOD void printFridgeTemp();
94 |
95 | // print fridge temperature setting at the right place on the display
96 | DISPLAY_METHOD void printFridgeSet();
97 |
98 | // print the current state on the last line of the LCD
99 | DISPLAY_METHOD void printState();
100 |
101 | DISPLAY_METHOD void getLine(uint8_t lineNumber, char *buffer) { lcd.getLine(lineNumber, buffer); }
102 |
103 | DISPLAY_METHOD void printAt_P(uint8_t x, uint8_t y, const char *text);
104 |
105 | DISPLAY_METHOD void setBufferOnly(bool bufferOnly)
106 | {
107 | lcd.setBufferOnly(bufferOnly);
108 | }
109 |
110 | DISPLAY_METHOD void resetBacklightTimer() { lcd.resetBacklightTimer(); }
111 | DISPLAY_METHOD void updateBacklight() { lcd.updateBacklight(); }
112 |
113 | // print a temperature
114 | DISPLAY_METHOD void printTemperature(temperature temp);
115 | DISPLAY_METHOD void printTemperatureAt(uint8_t x, uint8_t y, temperature temp);
116 |
117 | // print degree sign + C/F
118 | DISPLAY_METHOD void printDegreeUnit(uint8_t x, uint8_t y);
119 |
120 | DISPLAY_METHOD void printAt(uint8_t x, uint8_t y, char *text);
121 |
122 | #ifdef ESP8266_WiFi
123 | DISPLAY_METHOD void printWiFiStartup();
124 | DISPLAY_METHOD void printWiFi();
125 | DISPLAY_METHOD void printWiFi_setup();
126 | DISPLAY_METHOD void printWiFiConnect();
127 | #endif
128 |
129 | #ifdef HAS_BLUETOOTH
130 | DISPLAY_METHOD void printBluetoothStartup();
131 | #endif
132 |
133 | DISPLAY_METHOD void clear();
134 |
135 |
136 | private:
137 | DISPLAY_FIELD LcdDriver lcd;
138 | DISPLAY_FIELD uint8_t stateOnDisplay;
139 | DISPLAY_FIELD uint8_t flags;
140 | };
141 |
142 | #endif
143 | /** @} */
144 |
--------------------------------------------------------------------------------
/src/ESPEepromAccess.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 John Beeler
3 | *
4 | * This is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this file. If not, see .
16 | */
17 |
18 | #pragma once
19 |
20 | #if defined(ESP8266)
21 | #define FILESYSTEM LittleFS
22 | #include
23 |
24 | #elif defined(ESP32S2)
25 | // #define FILESYSTEM LittleFS
26 | // #include
27 | #define FILESYSTEM SPIFFS
28 | #include
29 |
30 |
31 | #elif defined(ESP32)
32 | #define FILESYSTEM SPIFFS
33 | #include
34 |
35 | #else
36 | #error "Not supported!"
37 | #endif
38 |
39 | #include "EepromStructs.h"
40 | #include "Brewpi.h" // Only needed for Config:: below
41 |
42 |
43 | //TODO - Clean this up
44 | class ESPEepromAccess
45 | {
46 | private:
47 | static bool doesFileExist(String target_name) {
48 | return FILESYSTEM.exists(target_name);
49 | }
50 |
51 | public:
52 |
53 | static void zapData() {
54 | // This gets a bit tricky -- we can't just do FS.format because that would wipe out the mDNS name
55 | int i;
56 | if(doesFileExist(ControlConstants::filename)) FILESYSTEM.remove(ControlConstants::filename);
57 | if(doesFileExist(ControlSettings::filename)) FILESYSTEM.remove(ControlSettings::filename);
58 |
59 | char buf[20];
60 | for(i=0;i
3 |
4 | /**
5 | * \file ESP_BP_WiFi.h
6 | *
7 | * \defgroup wifi WiFi Configuration & Management
8 | * \brief WiFi configuration functions
9 | *
10 | * Various helper functions for interacting with the WiFi configuration.
11 | *
12 | * \addtogroup wifi
13 | * @{
14 | */
15 |
16 | // This library always needs to get loaded, as we're going to need to interact with the radio regardless of whether
17 | // we're using WiFi or not. If neither ESP8266 or ESP32 is defined, (properly) do nothing (though this shouldn't
18 | // actually compile for Arduino)
19 | #if defined(ESP8266)
20 | #include // For printing the IP address
21 | #elif defined(ESP32)
22 | #include // For printing the IP address
23 | #endif
24 |
25 |
26 |
27 | /**
28 | * \brief Initialize the WiFi client
29 | *
30 | * If WiFi is enabled, this sets it up. Otherwise, it disconnects the radio.
31 | */
32 | void initialize_wifi();
33 |
34 | /**
35 | * \brief Display the WiFi splash screen & trigger reconnection callback.
36 | */
37 | void display_connect_info_and_create_callback();
38 |
39 | /**
40 | * \brief Handle incoming WiFi client connections.
41 | *
42 | * This also handles WiFi network reconnects if the network was disconnected.
43 | */
44 | void wifi_connect_clients();
45 |
46 | /**
47 | * \brief Initialize the telnet server
48 | */
49 | void initWifiServer();
50 |
51 |
52 | /**
53 | * \brief Get current WiFi connection information, in JsonDocument format
54 | *
55 | * \param doc - JsonDocument to populate.
56 | */
57 | void wifi_connection_info(JsonDocument& doc);
58 |
59 | extern WiFiServer server;
60 | extern WiFiClient serverClient;
61 |
62 | /** @} */
63 |
--------------------------------------------------------------------------------
/src/EepromManager.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 BrewPi/Elco Jacobs.
3 | * Copyright 2013 Matthew McGowan
4 | *
5 | * This file is part of BrewPi.
6 | *
7 | * BrewPi is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * BrewPi is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with BrewPi. If not, see .
19 | */
20 |
21 | #pragma once
22 |
23 | #include "Brewpi.h"
24 |
25 | #include "ESPEepromAccess.h"
26 | #include "EepromStructs.h"
27 |
28 |
29 | class DeviceConfig;
30 |
31 |
32 | // todo - the Eeprom manager should avoid too frequent saves to the eeprom since it supports 100,000 writes.
33 | class EepromManager {
34 | public:
35 |
36 | EepromManager();
37 |
38 | /**
39 | * Prepare the eeprom to accept device definitions. For RevA boards, the eeprom is populated with devices for
40 | * beer/fridge temp sensor, and heating,cooling actuators and door switch.
41 | */
42 | static bool initializeEeprom();
43 |
44 | /**
45 | * Applies the settings from the eeprom
46 | */
47 | bool applySettings();
48 |
49 |
50 | DeviceConfig fetchDevice(uint8_t deviceIndex);
51 | void storeDevice(DeviceConfig& config, uint8_t deviceIndex);
52 | void deleteDeviceWithFunction(DeviceFunction function);
53 |
54 | static uint8_t saveDefaultDevices();
55 |
56 | #ifdef ESP8266_WiFi
57 | static String fetchmDNSName();
58 | static void savemDNSName(String mdns_id);
59 | #endif
60 |
61 |
62 | private:
63 | bool cache_loaded = false;
64 | void loadDevicesToCache();
65 | DeviceConfig cached_devices[Config::EepromFormat::MAX_DEVICES];
66 |
67 | };
68 |
69 |
70 | extern EepromManager eepromManager;
71 | extern ExtendedSettings extendedSettings;
72 | extern UpstreamSettings upstreamSettings;
73 |
--------------------------------------------------------------------------------
/src/Emulator.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 BrewPi/Elco Jacobs.
3 | * Copyright 2013 Matthew McGowan.
4 | *
5 | * This file is part of BrewPi.
6 | *
7 | * BrewPi is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * BrewPi is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with BrewPi. If not, see .
19 | */
20 |
21 | #include "Brewpi.h"
22 |
23 | class MockSerial : public Stream {
24 | public:
25 | void print(char c) {}
26 | void print(const char *c) {}
27 | void printNewLine() {}
28 | void println() {}
29 | int read() { return -1; }
30 | int available() { return -1; }
31 | void begin(unsigned long) {}
32 | size_t write(uint8_t w) { return 1; }
33 | int peek() { return -1; }
34 | void flush(){};
35 | operator bool() { return true; }
36 | };
37 |
38 | static MockSerial mockSerial;
39 |
--------------------------------------------------------------------------------
/src/FastDigitalPin.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 BrewPi/Elco Jacobs.
3 | * Copyright 2013 Matthew McGowan.
4 | *
5 | * This file is part of BrewPi.
6 | *
7 | * BrewPi is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * BrewPi is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with BrewPi. If not, see .
19 | */
20 |
21 | #pragma once
22 |
23 | #ifndef FAST_DIGITAL_PIN
24 | #define FAST_DIGITAL_PIN 1
25 | #endif
26 |
27 | // compiler optimization required in order to resolve pin numbers to compile time constants.
28 | #define USE_FAST_DIGITAL_PIN FAST_DIGITAL_PIN && __OPTIMIZE__
29 |
30 | #if USE_FAST_DIGITAL_PIN
31 | #include "DigitalPin.h"
32 | #else
33 | #define fastPinMode pinMode
34 | #define fastDigitalWrite digitalWrite
35 | #define fastDigitalRead digitalRead
36 | #endif
37 |
38 |
--------------------------------------------------------------------------------
/src/FilterCascaded.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 BrewPi/Elco Jacobs.
3 | *
4 | * This file is part of BrewPi.
5 | *
6 | * BrewPi is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * BrewPi is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with BrewPi. If not, see .
18 | */
19 |
20 | #include "Brewpi.h"
21 | #include "FilterFixed.h"
22 | #include "FilterCascaded.h"
23 | #include
24 | #include
25 | #include "TemperatureFormats.h"
26 |
27 | CascadedFilter::CascadedFilter() {
28 | // default to a b value of 2
29 | setCoefficients(2);
30 | }
31 |
32 | /**
33 | * \brief Set all secition coefficients to a given value
34 | *
35 | * @param bValue new coefficient value
36 | */
37 | void CascadedFilter::setCoefficients(uint8_t bValue){
38 | for(uint8_t i=0; i.
18 | */
19 |
20 | #pragma once
21 |
22 | #include "Brewpi.h"
23 |
24 | #include "TemperatureFormats.h"
25 | #include "FilterFixed.h"
26 |
27 |
28 | /**
29 | * \brief Implements a filter that consists of multiple second order sections.
30 | */
31 | class CascadedFilter {
32 | public:
33 | /**
34 | * \brief Number of filter sections to use
35 | *
36 | * Three filter sections gives excellent filtering, without adding too
37 | * much delay. For 3 sections the stop band attenuation is 3x the single
38 | * section attenuation in dB. The delay is also tripled.
39 | */
40 | constexpr static int numFilterSections = 3;
41 |
42 | /**
43 | * \brief Filter sections
44 | */
45 | FixedFilter sections[numFilterSections];
46 |
47 | public:
48 | CascadedFilter();
49 | ~CascadedFilter() {}
50 | void init(temperature val);
51 | void setCoefficients(uint8_t bValue);
52 | temperature add(temperature val);
53 | temperature_precise addDoublePrecision(temperature_precise val);
54 | temperature readInput();
55 |
56 | /**
57 | * \brief Read the output
58 | */
59 | temperature readOutput(){
60 | return sections[numFilterSections - 1].readOutput(); // return output of last section
61 | }
62 | temperature_precise readOutputDoublePrecision();
63 | temperature_precise readPrevOutputDoublePrecision();
64 |
65 | /**
66 | * \brief Do positive peak detection
67 | */
68 | temperature detectPosPeak(){
69 | return sections[numFilterSections - 1].detectPosPeak(); // detect peaks in last section
70 | }
71 |
72 | /**
73 | * \brief Do negative peak detection
74 | */
75 | temperature detectNegPeak(){
76 | return sections[numFilterSections - 1].detectNegPeak(); // detect peaks in last section
77 | }
78 | };
79 |
--------------------------------------------------------------------------------
/src/FilterFixed.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 BrewPi/Elco Jacobs.
3 | *
4 | * This file is part of BrewPi.
5 | *
6 | * BrewPi is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * BrewPi is distributed in the hope that it will be useful,
12 | *
13 | * You should have received a copy of the GNU General Public License
14 | * along with BrewPi. If not, see .
15 | */
16 | #include "Brewpi.h"
17 | #include "FilterFixed.h"
18 | #include
19 | #include
20 | #include "TemperatureFormats.h"
21 |
22 | /**
23 | * \brief Add a temperature value to the filter
24 | *
25 | * @param val - Temp value to add
26 | */
27 | temperature FixedFilter::add(temperature val){
28 | temperature_precise returnVal = addDoublePrecision(tempRegularToPrecise(val));
29 | return tempPreciseToRegular(returnVal);
30 | }
31 |
32 |
33 | /**
34 | * \brief Add a temperature value to the filter
35 | *
36 | * @param val - Temp value to add
37 | */
38 | temperature_precise FixedFilter::addDoublePrecision(temperature_precise val){
39 | xv[2] = xv[1];
40 | xv[1] = xv[0];
41 | xv[0] = val;
42 |
43 | yv[2] = yv[1];
44 | yv[1] = yv[0];
45 |
46 | /* Implementation that prevents overflow as much as possible by order of operations: */
47 | yv[0] = ((yv[1] - yv[2]) + yv[1]) // expected value + 1*
48 | - (yv[1]>>b) + (yv[2]>>b) + // expected value +0*
49 | + (xv[0]>>a) + (xv[1]>>(a-1)) + (xv[2]>>a) // expected value +(1>>(a-2))
50 | - (yv[2]>>(a-2)); // expected value -(1>>(a-2))
51 |
52 | return yv[0];
53 | }
54 |
55 |
56 | /**
57 | * \brief Initialize the filter
58 | *
59 | * @param val - Initial temp value to seed the filter with
60 | */
61 | void FixedFilter::init(temperature val){
62 | xv[0] = val;
63 | xv[0] = tempRegularToPrecise(xv[0]); // 16 extra bits are used in the filter for the fraction part
64 |
65 | xv[1] = xv[0];
66 | xv[2] = xv[0];
67 |
68 | yv[0] = xv[0];
69 | yv[1] = xv[0];
70 | yv[2] = xv[0];
71 | }
72 |
73 | /**
74 | * \brief Detect the positive peak
75 | * @return positive peak or INVALID_TEMP when no peak has been found
76 | */
77 | temperature FixedFilter::detectPosPeak(){
78 | if(yv[0] < yv[1] && yv[1] >= yv[2]){
79 | return tempPreciseToRegular(yv[1]);
80 | }
81 | else{
82 | return INVALID_TEMP;
83 | }
84 | }
85 |
86 |
87 | /**
88 | * \brief Detect the negative peak
89 | * @return negative peak or INVALID_TEMP when no peak has been found
90 | */
91 | temperature FixedFilter::detectNegPeak(){
92 | if(yv[0] > yv[1] && yv[1] <= yv[2]){
93 | return tempPreciseToRegular(yv[1]);
94 | }
95 | else{
96 | return INVALID_TEMP;
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/src/FilterFixed.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 BrewPi/Elco Jacobs.
3 | *
4 | * This file is part of BrewPi.
5 | *
6 | * BrewPi is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * BrewPi is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with BrewPi. If not, see .
18 | */
19 |
20 | #pragma once
21 |
22 | #include "Brewpi.h"
23 | #include "TemperatureFormats.h"
24 |
25 | /**
26 | * This class implements an IIR low pass filter, with the following frequency response
27 | *
28 | * \f[
29 | * H(z) = 2^{-a}
30 | * \frac{1 + 2z^{-1} + 1z^{-2}}{1 + (-2 + 2^{-b})z^{-1} + (1-2^{-b} + 4* 2^{-a})z^{-2}}
31 | * \f]
32 | *
33 | * - All filter coefficients are powers of two, so the filter can be efficiently implemented with bit shifts
34 | * - The DC gain is exactly 1.
35 | * - For real poles, and therefore no overshoot, use \f$ a <= 2b+4 \f$.
36 | * - To calculate the poles, you can use this [wolfram alpha
37 | * link](http://www.wolframalpha.com/input/?i=solve+%281++%2B+%28-2+%2B+2^-b%29z^-1++%2B+%281-2^-b+%2B+4*+2^-a%29z^-2%29+%3D+0+where+a+%3D+24+and+b+%3D+10)
38 | * - The filter has a zero at \f$z = -1\f$
39 | * - For \f$a=2b+4\f$, it has a pole at \f$z = \frac{(2^{b+1}-1)}{2^{b+1}}\f$
40 | *
41 | * Here are the specifications for a single stage filter, for values \f$a=2b+4\f$
42 | * The delay time is the time it takes to rise to 0.5 in a step response.
43 | * When cascaded filters are used, multiply the delay time by the number of cascades.
44 | *
45 | * | a | b | Delay Time |
46 | * |---|---|------------|
47 | * | 4 | 0 | 3 |
48 | * | 6 | 1 | 6 |
49 | * | 8 | 2 | 13 |
50 | * | 10 | 3 | 26 |
51 | * | 12 | 4 | 53 |
52 | * | 14 | 5 | 106 |
53 | * | 16 | 6 | 213 |
54 | *
55 | * Use this MATLAB script to visualize the filter:
56 | *
57 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
58 | * NUM_SECTIONS=1;
59 | * a=6; b=1; FS=1;
60 | * DEN = [1 , -2 + 2^-b , 1-2^-b+ 4*2^-a];
61 | * NUM = 2^(-a)*[1, 2, 1];
62 | * F=dfilt.df2(NUM,DEN);
63 | * H=F;
64 | * for i=2:NUM_SECTIONS
65 | * H=dfilt.cascade(H,F);
66 | * end
67 | * %H=F^NUM_SECTIONS;
68 | * h=fvtool(H,'Fs',FS)
69 | * zeropos = roots(NUM)
70 | * polepos = roots(DEN)
71 | * set(h,'FrequencyRange', 'Specify freq. vector');
72 | * set(h,'FrequencyScale','Log')
73 | * set(h,'FrequencyVector', logspace(-4,0,1000));
74 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
75 | *
76 | */
77 | class FixedFilter{
78 | public:
79 | // input and output arrays
80 | temperature_precise xv[3];
81 | temperature_precise yv[3];
82 | uint8_t a; //!< Filter `a` coefficient
83 | uint8_t b; //!< Filter `b` coefficient
84 |
85 | public:
86 | FixedFilter() { setCoefficients(20); /* default to a b value of 2 */ }
87 | ~FixedFilter() { }
88 | void init(temperature val);
89 |
90 | /**
91 | * \brief Set filter coefficients
92 | *
93 | * @param bValue - New b value
94 | */
95 | void setCoefficients(uint8_t bValue) {
96 | a = bValue*2+4;
97 | b = bValue;
98 | }
99 |
100 | temperature add(temperature val); // adds a value and returns the most recent filter output
101 | temperature_precise addDoublePrecision(temperature_precise val);
102 |
103 | temperature readOutput(){
104 | return yv[0]>>16; // return 16 most significant bits of most recent output
105 | }
106 |
107 | temperature readInput(){
108 | return xv[0]>>16; // return 16 most significant bits of most recent input
109 | }
110 |
111 | temperature_precise readOutputDoublePrecision(){
112 | return yv[0];
113 | }
114 |
115 | temperature_precise readPrevOutputDoublePrecision(){
116 | return yv[1];
117 | }
118 |
119 | temperature detectPosPeak();
120 | temperature detectNegPeak();
121 | };
122 |
123 |
--------------------------------------------------------------------------------
/src/IicLcd.h:
--------------------------------------------------------------------------------
1 | //YWROBOT
2 | #ifndef LiquidCrystal_I2C_h
3 | #define LiquidCrystal_I2C_h
4 |
5 | #include "Brewpi.h"
6 | #include "BrewpiStrings.h"
7 | #include
8 | #include
9 | #include "Ticks.h"
10 |
11 | // commands
12 | #define LCD_CLEARDISPLAY 0x01
13 | #define LCD_RETURNHOME 0x02
14 | #define LCD_ENTRYMODESET 0x04
15 | #define LCD_DISPLAYCONTROL 0x08
16 | #define LCD_CURSORSHIFT 0x10
17 | #define LCD_FUNCTIONSET 0x20
18 | #define LCD_SETCGRAMADDR 0x40
19 | #define LCD_SETDDRAMADDR 0x80
20 |
21 | // flags for display entry mode
22 | #define LCD_ENTRYRIGHT 0x00
23 | #define LCD_ENTRYLEFT 0x02
24 | #define LCD_ENTRYSHIFTINCREMENT 0x01
25 | #define LCD_ENTRYSHIFTDECREMENT 0x00
26 |
27 | // flags for display on/off control
28 | #define LCD_DISPLAYON 0x04
29 | #define LCD_DISPLAYOFF 0x00
30 | #define LCD_CURSORON 0x02
31 | #define LCD_CURSOROFF 0x00
32 | #define LCD_BLINKON 0x01
33 | #define LCD_BLINKOFF 0x00
34 |
35 | // flags for display/cursor shift
36 | #define LCD_DISPLAYMOVE 0x08
37 | #define LCD_CURSORMOVE 0x00
38 | #define LCD_MOVERIGHT 0x04
39 | #define LCD_MOVELEFT 0x00
40 |
41 | // flags for function set
42 | #define LCD_8BITMODE 0x10
43 | #define LCD_4BITMODE 0x00
44 | #define LCD_2LINE 0x08
45 | #define LCD_1LINE 0x00
46 | #define LCD_5x10DOTS 0x04
47 | #define LCD_5x8DOTS 0x00
48 |
49 | // flags for backlight control
50 | #define LCD_BACKLIGHT 0x08
51 | #define LCD_NOBACKLIGHT 0x00
52 |
53 | #define En B00000100 // Enable bit
54 | #define Rw B00000010 // Read/Write bit
55 | #define Rs B00000001 // Register select bit
56 |
57 | class IIClcd : public Print {
58 | public:
59 | IIClcd(uint8_t lcd_Addr, uint8_t lcd_cols, uint8_t lcd_rows);
60 | ~IIClcd() {};
61 |
62 | void init();
63 |
64 | void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS);
65 |
66 | void clear();
67 | void home();
68 |
69 | void noDisplay();
70 | void display();
71 | void noBlink();
72 | void blink();
73 | void noCursor();
74 | void cursor();
75 | void scrollDisplayLeft();
76 | void scrollDisplayRight();
77 | // void printLeft();
78 | // void printRight();
79 | void leftToRight();
80 | void rightToLeft();
81 | // void shiftIncrement();
82 | // void shiftDecrement();
83 | void noBacklight();
84 | void backlight();
85 | void autoscroll();
86 | void noAutoscroll();
87 | void scan_address();
88 |
89 | void createChar(uint8_t, uint8_t[]);
90 | void setCursor(uint8_t, uint8_t);
91 |
92 | virtual size_t write(uint8_t);
93 |
94 | #define print_P_inline 1
95 | #ifdef print_P_inline
96 | // print a string stored in PROGMEM
97 | void print_P(const char * str) {
98 | char buf[21]; // create buffer in RAM
99 | strcpy_P(buf, str); // copy string to RAM
100 | print(buf); // print from RAM
101 | }
102 | #else
103 | void print_P(const char * str);
104 | #endif
105 |
106 | void getLine(uint8_t lineNumber, char * buffer);
107 |
108 | //void readContent(void); // read the content from the display to the shadow copy buffer
109 | char readChar();
110 |
111 | void command(uint8_t);
112 |
113 | void setBufferOnly(bool bufferOnly) { _bufferOnly = bufferOnly; }
114 |
115 | void resetBacklightTimer();
116 |
117 | void updateBacklight();
118 |
119 | uint8_t getCurrPos() {
120 | return _currpos;
121 | }
122 |
123 | uint8_t getCurrLine() {
124 | return _currline;
125 | }
126 |
127 | void printSpacesToRestOfLine();
128 |
129 | using Print::write;
130 |
131 | private:
132 | void init_priv();
133 | void send(uint8_t, uint8_t);
134 | void write4bits(uint8_t);
135 | void expanderWrite(uint8_t);
136 | void pulseEnable(uint8_t);
137 | uint8_t _Addr;
138 | uint8_t _displayfunction;
139 | uint8_t _displaycontrol;
140 | uint8_t _displaymode;
141 | uint8_t _numlines;
142 | uint8_t _currline;
143 | uint8_t _currpos;
144 | uint8_t _cols;
145 | uint8_t _rows;
146 | uint8_t _backlightval;
147 | uint16_t _backlightTime;
148 | bool _bufferOnly;
149 |
150 | bool _displayFound; // Needed since writes to a non-existant display can lock I2C bus on ESP32-S2 - see: https://github.com/espressif/arduino-esp32/issues/8480#issuecomment-1708909457
151 |
152 |
153 | char content[4][21]; // always keep a copy of the display content in this variable
154 | };
155 |
156 | #endif
157 |
--------------------------------------------------------------------------------
/src/InkbirdTempSensor.cpp:
--------------------------------------------------------------------------------
1 | #ifdef HAS_BLUETOOTH
2 | #include "Brewpi.h"
3 | #include "InkbirdTempSensor.h"
4 | #include "PiLink.h" // For printBytes
5 | // #include "Ticks.h"
6 | #include "TemperatureFormats.h"
7 |
8 | #include "wireless/BTScanner.h"
9 |
10 | InkbirdTempSensor::~InkbirdTempSensor(){
11 | // delete sensor;
12 | };
13 |
14 | /**
15 | * \brief Initializes the temperature sensor.
16 | *
17 | * This method is called when the sensor is first created and also any time the
18 | * sensor reports it's disconnected. If the result is TEMP_SENSOR_DISCONNECTED
19 | * then subsequent calls to read() will also return TEMP_SENSOR_DISCONNECTED.
20 | * Clients should attempt to re-initialize the sensor by calling init() again.
21 | */
22 | bool InkbirdTempSensor::init() {
23 | if (ib==NULL) {
24 | ib = bt_scanner.get_or_create_inkbird(btAddress);
25 | if (ib==NULL) {
26 | logErrorString(ERROR_SRAM_SENSOR, btAddress.toString().c_str());
27 | }
28 | }
29 | return isConnected();
30 | }
31 |
32 |
33 | /**
34 | * \brief Read the value of the sensor
35 | *
36 | * @return TEMP_SENSOR_DISCONNECTED if sensor is not connected, constrained temp otherwise.
37 | * @see readAndConstrainTemp()
38 | */
39 | temperature InkbirdTempSensor::read(){
40 | if (!isConnected())
41 | return TEMP_SENSOR_DISCONNECTED;
42 |
43 | return readAndConstrainTemp();
44 | }
45 |
46 |
47 | /**
48 | * \brief Reads the temperature.
49 | *
50 | * If successful, constrains the temp to the range of the temperature type
51 | * and updates lastRequestTime. On successful, leaves lastRequestTime alone
52 | * and returns TEMP_SENSOR_DISCONNECTED.
53 | */
54 | temperature InkbirdTempSensor::readAndConstrainTemp()
55 | {
56 | if(!isConnected()) {
57 | return TEMP_SENSOR_DISCONNECTED;
58 | }
59 |
60 | // double rawTemp = ib->getTemp() / 1000;
61 | // temperature temp = doubleToTemp(rawTemp);
62 |
63 | // const uint8_t shift = TEMP_FIXED_POINT_BITS - sensorPrecision; // difference in precision between DS18B20 format and temperature adt
64 | // temp = constrainTemp(temp+calibrationOffset+(C_OFFSET>>shift), ((int) MIN_TEMP)>>shift, ((int) MAX_TEMP)>>shift)<getTempFixedPoint() + (calibrationOffset<<(TEMP_FIXED_POINT_BITS - TEMP_CALIBRATION_OFFSET_PRECISION)), MIN_TEMP, MAX_TEMP);
67 | return temp;
68 | }
69 | #endif
70 |
--------------------------------------------------------------------------------
/src/InkbirdTempSensor.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #ifdef HAS_BLUETOOTH
3 | #include "Brewpi.h"
4 | #include "TempSensor.h"
5 | #include "FastDigitalPin.h"
6 | #include "Ticks.h"
7 | // #include "DallasTemperature.h" // for DeviceAddress
8 | #include
9 |
10 | #include "wireless/Inkbird.h"
11 |
12 |
13 | /**
14 | * \brief An Inkbird bluetooth temperature sensor
15 | *
16 | * \ingroup hardware
17 | */
18 | class InkbirdTempSensor : public BasicTempSensor {
19 | public:
20 | /**
21 | * \brief Constructs a new Inkbird temp sensor.
22 | *
23 | * /param address The MAC address for this sensor.
24 | * /param calibration A temperature value that is added to all readings. This can be used to calibrate the sensor.
25 | */
26 | InkbirdTempSensor(NimBLEAddress address, fixed4_4 calibrationOffset) {
27 | btAddress = address;
28 |
29 | this->calibrationOffset = calibrationOffset;
30 | ib = nullptr;
31 | };
32 |
33 | ~InkbirdTempSensor();
34 |
35 | /**
36 | * \brief Check if sensor device is connected
37 | */
38 | bool isConnected(){
39 | if (ib && ib->isConnected())
40 | return true;
41 | return false;
42 | }
43 |
44 | bool init();
45 | temperature read();
46 |
47 | NimBLEAddress btAddress;
48 | inkbird *ib;
49 |
50 | private:
51 | /**
52 | * \brief The sensor precision, in bits.
53 | */
54 | // constexpr static uint8_t sensorPrecision = 4;
55 |
56 | temperature readAndConstrainTemp();
57 | // uint8_t sensorAddress[6];
58 |
59 | fixed4_4 calibrationOffset; //!< Temperature offset needed for calibration
60 |
61 | };
62 | #endif
--------------------------------------------------------------------------------
/src/JsonKeys.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Matthew McGowan
3 | * Copyright 2013 BrewPi/Elco Jacobs.
4 | * Copyright 2020 Scott Peshak
5 | *
6 | * This file is part of BrewPi.
7 | *
8 | * BrewPi is free software: you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation, either version 3 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * BrewPi is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU General Public License
19 | * along with BrewPi. If not, see .
20 | */
21 |
22 | #pragma once
23 |
24 | /**
25 | * \brief Strings used for JSON keys
26 | * \see DeviceDefinition
27 | */
28 | namespace DeviceDefinitionKeys {
29 | constexpr auto index = "i";
30 | constexpr auto chamber = "c";
31 | constexpr auto beer = "b";
32 | constexpr auto function = "f";
33 | constexpr auto hardware = "h";
34 | constexpr auto pin = "p";
35 | constexpr auto invert = "x";
36 | constexpr auto deactivated = "d";
37 | constexpr auto address = "a";
38 | constexpr auto child_id = "n";
39 | constexpr auto alias = "r"; // EXTERN_SENSOR_ACTUATOR or Bluetooth
40 | #if BREWPI_DS2413
41 | constexpr auto pio = "n";
42 | #endif
43 | constexpr auto calibrateadjust = "j";
44 |
45 | constexpr auto value = "v";
46 | constexpr auto write = "w";
47 |
48 | constexpr auto type = "t";
49 | }; // namespace DeviceDefinitionKeys
50 |
51 |
52 | /**
53 | * \brief Strings used for JSON keys
54 | * \see DeviceDisplay
55 | */
56 | namespace DeviceDisplayKeys {
57 | constexpr auto index = "i";
58 | constexpr auto value = "v";
59 | constexpr auto write = "w";
60 | constexpr auto empty = "e";
61 | }; // namespace DeviceDisplayKeys
62 |
63 |
64 |
65 | /**
66 | * \brief Strings used for JSON keys
67 | * \see EnumerateHardware
68 | */
69 | namespace EnumerateHardwareKeys {
70 | constexpr auto hardware = "h";
71 | constexpr auto pin = "p";
72 | constexpr auto values = "v";
73 | constexpr auto unused = "u";
74 | constexpr auto function = "f";
75 | }; // namespace EnumerateHardwareKeys
76 |
77 |
78 | /**
79 | * \brief Strings used for JSON keys
80 | * \see ControlSettings
81 | */
82 | namespace ControlSettingsKeys {
83 | constexpr auto beer = "beerSetting";
84 | constexpr auto fridge = "fridgeSetting";
85 | constexpr auto heatEst = "heatEstimator";
86 | constexpr auto coolEst = "coolEstimator";
87 | constexpr auto mode = "mode";
88 | };
89 |
90 |
91 | /**
92 | * \brief Strings used for JSON keys
93 | * \see ControlConstants
94 | */
95 | namespace ControlConstantsKeys {
96 | constexpr auto tempMin = "tempSettingMin";
97 | constexpr auto tempMax = "tempSettingMax";
98 | constexpr auto kp = "Kp";
99 | constexpr auto ki = "Ki";
100 | constexpr auto kd = "Kd";
101 | constexpr auto maxError = "iMaxError";
102 | constexpr auto idleHigh = "idleRangeHigh";
103 | constexpr auto idleLow = "idleRangeLow";
104 | constexpr auto heatingUpper = "heatingTargetUpper";
105 | constexpr auto heatingLower = "heatingTargetLower";
106 | constexpr auto coolingUpper = "coolingTargetUpper";
107 | constexpr auto coolingLower = "coolingTargetLower";
108 | constexpr auto maxHeatEst = "maxHeatTimeForEstimate";
109 | constexpr auto maxCoolEst = "maxCoolTimeForEstimate";
110 | constexpr auto fridgeFilterFast = "fridgeFastFilter";
111 | constexpr auto fridgeFilterSlow = "fridgeSlowFilter";
112 | constexpr auto fridgeFilterSlope = "fridgeSlopeFilter";
113 | constexpr auto beerFilterFast = "beerFastFilter";
114 | constexpr auto beerFilterSlow = "beerSlowFilter";
115 | constexpr auto beerFilterSlope = "beerSlopeFilter";
116 | constexpr auto lightHeater = "lightAsHeater";
117 | constexpr auto rotaryHalfSteps = "rotaryHalfSteps";
118 | constexpr auto pidMax = "pidMax";
119 | constexpr auto tempFormat = "tempFormat";
120 | };
121 |
122 |
123 | /**
124 | * \brief Strings used for JSON keys
125 | * \see ExtendedSettings
126 | */
127 | namespace ExtendedSettingsKeys {
128 | constexpr auto eepromReset = "confirmReset";
129 | constexpr auto invertTFT = "invertTFT";
130 | constexpr auto glycol = "glycol";
131 | constexpr auto largeTFT = "largeTFT";
132 | }; // namespace ExtendedSettingsKeys
133 |
134 |
135 | /**
136 | * \brief Strings used for JSON keys
137 | * \see UpstreamSettings
138 | */
139 | namespace UpstreamSettingsKeys {
140 | constexpr auto upstreamHost = "upstreamHost";
141 | constexpr auto upstreamPort = "upstreamPort";
142 | constexpr auto deviceID = "deviceID";
143 | }; // namespace UpstreamSettingsKeys
144 |
145 |
146 |
147 | /**
148 | * \brief Strings used for JSON keys
149 | * \see processUpdateModeJson
150 | */
151 | namespace ModeUpdateKeys {
152 | constexpr auto mode = "mode";
153 | constexpr auto setpoint = "setPoint";
154 | }; // namespace ModeUpdateKeys
155 |
156 |
157 |
--------------------------------------------------------------------------------
/src/JsonMessages.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "JsonMessages.h"
3 | #include "Brewpi.h"
4 | #include "Version.h"
5 | #include "Display.h"
6 | #include "TempControl.h"
7 | #include "TemperatureFormats.h"
8 |
9 |
10 |
11 |
12 | void versionInfoJson(DynamicJsonDocument &doc) {
13 | // v version
14 | // s shield type
15 | // y: simulator
16 | // b: board
17 | // e:
18 |
19 | doc["v"] = Config::Version::release;
20 | doc["n"] = Config::Version::git_rev;
21 | doc["c"] = Config::Version::git_tag;
22 | doc["s"] = BREWPI_STATIC_CONFIG;
23 | doc["y"] = BREWPI_SIMULATE;
24 | doc["b"] = String(BREWPI_BOARD);
25 | doc["l"] = BREWPI_LOG_MESSAGES_VERSION;
26 | doc["e"] = FIRMWARE_REVISION;
27 |
28 | }
29 |
30 |
31 | void getLcdContentJson(DynamicJsonDocument &doc) {
32 | JsonArray rootArray = doc.to();
33 | char stringBuffer[Config::Lcd::columns + 2];
34 |
35 | for (uint8_t i = 0; i < Config::Lcd::lines; i++) {
36 | display.getLine(i, stringBuffer);
37 | rootArray.add(stringBuffer);
38 | }
39 | }
40 |
41 | void printTemperaturesJson(DynamicJsonDocument &doc, const char *beerAnnotation, const char *fridgeAnnotation) {
42 |
43 | doc["BeerTemp"] = tempToDouble(tempControl.getBeerTemp(), Config::TempFormat::tempDecimals);
44 | doc["BeerSet"] = tempToDouble(tempControl.getBeerSetting(), Config::TempFormat::tempDecimals);
45 |
46 | doc["BeerAnn"] = beerAnnotation;
47 |
48 | doc["FridgeTemp"] = tempToDouble(tempControl.getFridgeTemp(), Config::TempFormat::tempDecimals);
49 | doc["FridgeSet"] = tempToDouble(tempControl.getFridgeSetting(), Config::TempFormat::tempDecimals);
50 |
51 | doc["FridgeAnn"] = fridgeAnnotation;
52 |
53 | if (tempControl.ambientSensor->isConnected()) {
54 | doc["RoomTemp"] = tempToDouble(tempControl.getRoomTemp(), Config::TempFormat::tempDecimals);
55 | } else {
56 | doc["RoomTemp"] = "";
57 | }
58 |
59 | doc["State"] = tempControl.getState();
60 |
61 | #if BREWPI_SIMULATE
62 | doc["Time"] = ticks.millis() / 1000;
63 | #endif
64 | }
65 |
66 | void printTemperaturesJson(DynamicJsonDocument &doc) {
67 | printTemperaturesJson(doc, "", "");
68 | }
69 |
70 | void getFullTemperatureControlJson(DynamicJsonDocument &doc) {
71 | DynamicJsonDocument cc(256);
72 | DynamicJsonDocument cs(256);
73 | DynamicJsonDocument cv(256);
74 | DynamicJsonDocument temp(1024);
75 |
76 | tempControl.getControlConstantsDoc(cc);
77 | tempControl.getControlSettingsDoc(cs);
78 | tempControl.getControlVariablesDoc(cv);
79 | printTemperaturesJson(temp);
80 |
81 | // For this message, we don't want to send any temperature if the sensor is not connected
82 | if(!tempControl.beerSensor->isConnected())
83 | temp["BeerTemp"] = "";
84 | if(!tempControl.fridgeSensor->isConnected())
85 | temp["FridgeTemp"] = "";
86 |
87 | doc["cc"] = cc;
88 | doc["cs"] = cs;
89 | doc["cv"] = cv;
90 | doc["temp"] = temp;
91 | }
92 |
--------------------------------------------------------------------------------
/src/JsonMessages.h:
--------------------------------------------------------------------------------
1 | #include
2 |
3 |
4 |
5 | void versionInfoJson(DynamicJsonDocument &doc);
6 | void getLcdContentJson(DynamicJsonDocument &doc);
7 | void printTemperaturesJson(DynamicJsonDocument &doc, const char *beerAnnotation, const char *fridgeAnnotation);
8 | void printTemperaturesJson(DynamicJsonDocument &doc);
9 | void getFullTemperatureControlJson(DynamicJsonDocument &doc);
10 |
11 |
--------------------------------------------------------------------------------
/src/Logger.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 BrewPi/Elco Jacobs.
3 | *
4 | * This file is part of BrewPi.
5 | *
6 | * BrewPi is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * BrewPi is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with BrewPi. If not, see .
18 | */
19 |
20 | #include "Brewpi.h"
21 | #include "BrewpiStrings.h"
22 | #include "Logger.h"
23 | #include "PiLink.h"
24 | #include "TemperatureFormats.h"
25 |
26 |
27 | /**
28 | * \brief Log a message
29 | *
30 | * \param type - Type of message
31 | * \param errorID
32 | */
33 | void Logger::logMessageVaArg(const char type, const LOG_ID_TYPE errorID, const char * varTypes, ...){
34 | DynamicJsonDocument doc(2048);
35 |
36 | va_list args;
37 | doc[F("logType")] = String(type);
38 | doc[F("logID")] = errorID;
39 | JsonArray varArray = doc.createNestedArray("V");
40 |
41 | va_start (args, varTypes);
42 | uint8_t index = 0;
43 | char buf[9];
44 | while(varTypes[index]){
45 | switch(varTypes[index]){
46 | case 'd': // integer, signed or unsigned
47 | varArray.add(va_arg(args, int));
48 | break;
49 | case 's': // string
50 | varArray.add(String(va_arg(args, char*)));
51 | break;
52 | case 't': // temperature in fixed_7_9 format
53 | varArray.add(String(tempToString(buf, va_arg(args,int), 1, 12)));
54 | break;
55 | case 'f': // fixed point value
56 | varArray.add(String(fixedPointToString(buf, (temperature) va_arg(args,int), 3, 12)));
57 | break;
58 | }
59 |
60 | index++;
61 | }
62 | va_end (args);
63 | piLink.sendJsonMessage('D', doc);
64 | }
65 |
66 | Logger logger;
67 |
--------------------------------------------------------------------------------
/src/Logger.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 BrewPi/Elco Jacobs.
3 | *
4 | * This file is part of BrewPi.
5 | *
6 | * BrewPi is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * BrewPi is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with BrewPi. If not, see .
18 | */
19 |
20 | #ifndef BREWPI_LOGGER_H
21 | #define BREWPI_LOGGER_H
22 |
23 | #include
24 | #include "TemperatureFormats.h"
25 | #include "LogMessages.h"
26 |
27 | // define error id variable type to make it easy to bump to uint16 when needed
28 | #define LOG_ID_TYPE uint8_t
29 |
30 | class Logger{
31 | public:
32 | Logger(){};
33 | ~Logger(){};
34 |
35 | static void logMessageVaArg(const char type, const LOG_ID_TYPE errorID, const char * varTypes, ...);
36 | };
37 | extern Logger logger;
38 |
39 |
40 | #if BREWPI_LOG_ERRORS
41 | inline void logError(uint8_t debugId){
42 | logger.logMessageVaArg('E', debugId, "");
43 | }
44 | inline void logErrorInt(uint8_t debugId, int val){
45 | logger.logMessageVaArg('E', debugId, "d", val);
46 | }
47 | inline void logErrorString(uint8_t debugId, const char * val){
48 | logger.logMessageVaArg('E', debugId, "s", val);
49 | }
50 | inline void logErrorTemp(uint8_t debugId, temperature temp){
51 | logger.logMessageVaArg('E', debugId, "t", temp);
52 | }
53 | inline void logErrorIntInt(uint8_t debugId, int val1, int val2){
54 | logger.logMessageVaArg('E', debugId, "dd", val1, val2);
55 | }
56 | inline void logErrorIntIntInt(uint8_t debugId, int val1, int val2, int val3){
57 | logger.logMessageVaArg('E', debugId, "ddd", val1, val2, val3);
58 | }
59 | #else
60 | #define logError(debugId) {}
61 | #define logErrorInt(debugId, val) {}
62 | #define logErrorString(debugId, val) {}
63 | #define logErrorTemp(debugId, temp) {}
64 | #define logErrorIntInt(debugId, val1, val2) {}
65 | #define logErrorIntIntInt(debugId, val1, val2, val3) {}
66 | #endif
67 |
68 | #if BREWPI_LOG_WARNINGS
69 | inline void logWarning(uint8_t debugId){
70 | logger.logMessageVaArg('W', debugId, "");
71 | }
72 | inline void logWarningInt(uint8_t debugId, int val){
73 | logger.logMessageVaArg('W', debugId, "d", val);
74 | }
75 | inline void logWarningString(uint8_t debugId, const char * val){
76 | logger.logMessageVaArg('W', debugId, "s", val);
77 | }
78 | inline void logWarningTemp(uint8_t debugId, temperature temp){
79 | logger.logMessageVaArg('W', debugId, "t", temp);
80 | }
81 | inline void logWarningIntString(uint8_t debugId, int val1, const char *val2){
82 | logger.logMessageVaArg('W', debugId, "ds", val1, val2);
83 | }
84 | #else
85 | #define logWarning(debugId) {}
86 | #define logWarningInt(debugId, val) {}
87 | #define logWarningString(debugId, val) {}
88 | #define logWarningTemp(debugId, temp) {}
89 | #define logWarningIntString(debugId, val1, val2) {}
90 | #endif
91 |
92 | #if BREWPI_LOG_INFO
93 | inline void logInfo(uint8_t debugId){
94 | logger.logMessageVaArg('I', debugId, "");
95 | }
96 | inline void logInfoInt(uint8_t debugId, int val){
97 | logger.logMessageVaArg('I', debugId, "d", val);
98 | }
99 | inline void logInfoString(uint8_t debugId, const char * val){
100 | logger.logMessageVaArg('I', debugId, "s", val);
101 | }
102 | inline void logInfoTemp(uint8_t debugId, temperature temp){
103 | logger.logMessageVaArg('I', debugId, "t", temp);
104 | }
105 | inline void logInfoIntString(uint8_t debugId, int val1, const char * val2){
106 | logger.logMessageVaArg('I', debugId, "ds", val1, val2);
107 | }
108 | inline void logInfoStringString(uint8_t debugId, const char * val1, const char * val2){
109 | logger.logMessageVaArg('I', debugId, "ss", val1, val2);
110 | }
111 | inline void logInfoIntStringTemp(uint8_t debugId, int val1, const char * val2, temperature val3){
112 | logger.logMessageVaArg('I', debugId, "dst", val1, val2, val3);
113 | }
114 | inline void logInfoTempTempFixedFixed(uint8_t debugId, temperature t1, temperature t2, temperature f1, temperature f2){
115 | logger.logMessageVaArg('I', debugId, "ttff", t1, t2, f1, f2);
116 | }
117 | #else
118 | #define logInfo(debugId) {}
119 | #define logInfoInt(debugId, val) {}
120 | #define logInfoString(debugId, val) {}
121 | #define logInfoTemp(debugId, temp) {}
122 | #define logInfoStringString(debugId, val1, val2) {}
123 | #define logInfoIntString(debugId, val1, val2) {}
124 | #define logInfoIntStringTemp(debugId, val1, val2, val3) {}
125 |
126 |
127 | #endif
128 |
129 | #if BREWPI_LOG_DEBUG
130 | #include "PiLink.h"
131 | #define logDebug(string, ...) piLink.debugMessage(PSTR(string), ##__VA_ARGS__)
132 | #else
133 | #define logDebug(string, ...) {}
134 | #endif
135 |
136 | #endif
137 |
--------------------------------------------------------------------------------
/src/Menu.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 BrewPi/Elco Jacobs.
3 | *
4 | * This file is part of BrewPi.
5 | *
6 | * BrewPi is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * BrewPi is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with BrewPi. If not, see .
18 | */
19 |
20 | #pragma once
21 |
22 | #include "Brewpi.h"
23 |
24 | #ifndef BREWPI_MENU
25 | #define BREWPI_MENU 1
26 | #endif
27 |
28 |
29 | #if BREWPI_MENU
30 |
31 | #include
32 | #include "TemperatureFormats.h"
33 |
34 | enum menuPages{
35 | MENU_TOP,
36 | MENU_PROFILE_SETTING,
37 | MENU_BEER_SETTING,
38 | MENU_FRIDGE_SETTING,
39 | MENU_PROFILE
40 | };
41 |
42 | class Menu{
43 | public:
44 | Menu(){};
45 | static void pickSettingToChange();
46 | static void pickMode();
47 | static void pickBeerSetting();
48 | static void pickFridgeSetting();
49 | static void initRotaryWithTemp(temperature oldSetting);
50 |
51 | ~Menu(){};
52 | private:
53 | static void pickSettingToChangeLoop();
54 | };
55 |
56 | extern Menu menu;
57 |
58 | #endif
59 |
--------------------------------------------------------------------------------
/src/NullLcdDriver.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 BrewPi/Elco Jacobs.
3 | *
4 | * This file is part of BrewPi.
5 | *
6 | * BrewPi is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * BrewPi is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with BrewPi. If not, see .
18 | */
19 |
20 | #include "Brewpi.h"
21 | #include
22 | #include
23 | #include
24 |
25 | #include "NullLcdDriver.h"
26 |
27 |
28 | void NullLcdDriver::init()
29 | {
30 | }
31 |
32 | void NullLcdDriver::begin(uint8_t cols, uint8_t lines) {
33 | _numlines = lines;
34 | _currline = 0;
35 | _currpos = 0;
36 |
37 | clear();
38 | home();
39 | display();
40 | }
41 |
42 | /********** high level commands, for the user! */
43 | void NullLcdDriver::clear()
44 | {
45 | for(uint8_t i = 0; i<4; i++){
46 | for(uint8_t j = 0; j<20; j++){
47 | content[i][j]=' '; // initialize on all spaces
48 | }
49 | content[i][20]='\0'; // NULL terminate string
50 | }
51 | }
52 |
53 | void NullLcdDriver::home()
54 | {
55 | _currline = 0;
56 | _currpos = 0;
57 | }
58 |
59 | void NullLcdDriver::setCursor(uint8_t col, uint8_t row)
60 | {
61 | if ( row >= _numlines ) {
62 | row = 0; //write to first line if out off bounds
63 | }
64 | _currline = row;
65 | _currpos = col;
66 | }
67 |
68 | // Turn the display on/off (quickly)
69 | void NullLcdDriver::noDisplay() {
70 | }
71 | void NullLcdDriver::display() {
72 | }
73 |
74 | // Turns the underline cursor on/off
75 | void NullLcdDriver::noCursor() {
76 | }
77 | void NullLcdDriver::cursor() {
78 | }
79 |
80 | // Turn on and off the blinking cursor
81 | void NullLcdDriver::noBlink() {
82 | }
83 | void NullLcdDriver::blink() {
84 | }
85 |
86 | // These commands scroll the display without changing the RAM
87 | void NullLcdDriver::scrollDisplayLeft() {
88 | }
89 | void NullLcdDriver::scrollDisplayRight() {
90 | }
91 |
92 | // This is for text that flows Left to Right
93 | void NullLcdDriver::leftToRight() {
94 | }
95 |
96 | // This is for text that flows Right to Left
97 | void NullLcdDriver::rightToLeft() {
98 | }
99 |
100 | // This will 'right justify' text from the cursor
101 | void NullLcdDriver::autoscroll() {
102 | }
103 |
104 | // This will 'left justify' text from the cursor
105 | void NullLcdDriver::noAutoscroll() {
106 | }
107 |
108 | // Allows us to fill the first 8 CGRAM locations
109 | // with custom characters
110 | void NullLcdDriver::createChar(uint8_t location, uint8_t charmap[]) {
111 | location &= 0x7; // we only have 8 locations 0-7
112 | for (int i=0; i<8; i++) {
113 | write(charmap[i]);
114 | }
115 | }
116 |
117 | // This resets the backlight timer and updates the SPI output
118 | void NullLcdDriver::resetBacklightTimer(){
119 | }
120 |
121 | void NullLcdDriver::updateBacklight(){
122 | }
123 |
124 | // Puts the content of one LCD line into the provided buffer.
125 | void NullLcdDriver::getLine(uint8_t lineNumber, char * buffer){
126 | const char* src = content[lineNumber];
127 | for(uint8_t i =0;i<20;i++){
128 | char c = src[i];
129 | buffer[i] = (c == 0b11011111) ? 0xB0 : c;
130 | }
131 | buffer[20] = '\0'; // NULL terminate string
132 | }
133 |
134 | /*********** mid level commands, for sending data/cmds */
135 |
136 | inline void NullLcdDriver::command(uint8_t value) {
137 | }
138 |
139 | inline size_t NullLcdDriver::write(uint8_t value) {
140 | content[_currline][_currpos] = value;
141 | _currpos++;
142 | return 1;
143 | }
144 |
145 | void NullLcdDriver::printSpacesToRestOfLine(){
146 | while(_currpos < 20){
147 | print(' ') ;
148 | }
149 | }
150 |
--------------------------------------------------------------------------------
/src/NullLcdDriver.h:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * Copyright 2013 BrewPi/Elco Jacobs.
4 | * Copyright 2013 Matthew McGowan.
5 | *
6 | * This file is part of BrewPi.
7 | *
8 | * BrewPi is free software: you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation, either version 3 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * BrewPi is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU General Public License
19 | * along with BrewPi. If not, see .
20 | */
21 |
22 | #pragma once
23 |
24 | #include "Brewpi.h"
25 | #include "BrewpiStrings.h"
26 | #include
27 | #include
28 | #include "Ticks.h"
29 |
30 | class NullLcdDriver : public Print {
31 | public:
32 | // Constants are set in initializer list of constructor
33 | NullLcdDriver(){};
34 | ~NullLcdDriver(){};
35 |
36 | void init();
37 |
38 | void begin(uint8_t cols, uint8_t rows);
39 |
40 | void clear();
41 | void home();
42 |
43 | void noDisplay();
44 | void display();
45 | void noBlink();
46 | void blink();
47 | void noCursor();
48 | void cursor();
49 | void scrollDisplayLeft();
50 | void scrollDisplayRight();
51 | void leftToRight();
52 | void rightToLeft();
53 | void autoscroll();
54 | void noAutoscroll();
55 |
56 | void createChar(uint8_t, uint8_t[]);
57 | void setCursor(uint8_t, uint8_t);
58 |
59 | virtual size_t write(uint8_t);
60 |
61 | void print_P(const char * str){ // print a string stored in PROGMEM
62 | char buf[21]; // create buffer in RAM
63 | strcpy_P(buf, str); // copy string to RAM
64 | print(buf); // print from RAM
65 | }
66 |
67 | // copy a line from the shadow copy to a string buffer and correct the degree sign
68 | void getLine(uint8_t lineNumber, char * buffer);
69 |
70 | void readContent(); // read the content from the display to the shadow copy buffer
71 |
72 | void command(uint8_t);
73 | char readChar();
74 |
75 | void setBufferOnly(bool bufferOnly) { _bufferOnly = bufferOnly; }
76 |
77 | void resetBacklightTimer();
78 |
79 | void updateBacklight();
80 |
81 | uint8_t getCurrPos(){
82 | return _currpos;
83 | }
84 | uint8_t getCurrLine(){
85 | return _currline;
86 | }
87 |
88 | // Write spaces from current position to line end.
89 | void printSpacesToRestOfLine();
90 |
91 | using Print::write;
92 |
93 | private:
94 | uint8_t _currline;
95 | uint8_t _currpos;
96 | uint8_t _numlines;
97 |
98 | bool _bufferOnly;
99 |
100 | char content[4][21]; // always keep a copy of the display content in this variable
101 |
102 | };
103 |
104 |
--------------------------------------------------------------------------------
/src/NumberFormats.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 BrewPi/Elco Jacobs.
3 | * Copyright 2013 Matthew McGowan.
4 | *
5 | * This file is part of BrewPi.
6 | *
7 | * BrewPi is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * BrewPi is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with BrewPi. If not, see .
19 | */
20 |
21 | #include "NumberFormats.h"
22 |
23 | /**
24 | * \brief Parse string into 8-bit bytes
25 | */
26 | void parseBytes(uint8_t *data, const char *s, uint8_t len) {
27 | char c;
28 | while ((c = *s++)) {
29 | uint8_t d = (c >= 'A' ? c - 'A' + 10 : c - '0') << 4;
30 | c = *s++;
31 | d |= (c >= 'A' ? c - 'A' + 10 : c - '0');
32 | *data++ = d;
33 | }
34 | }
35 |
36 | /**
37 | * \brief Render 8-bit data as hex
38 | */
39 | void printBytes(const uint8_t *data, uint8_t len, char *buf) {
40 | for (int i = 0; i < len; i++) {
41 | uint8_t b = (data[i] >> 4) & 0x0f;
42 | *buf++ = (b > 9 ? b - 10 + 'A' : b + '0');
43 | b = data[i] & 0x0f;
44 | *buf++ = (b > 9 ? b - 10 + 'A' : b + '0');
45 | }
46 | *buf = 0;
47 | }
48 |
--------------------------------------------------------------------------------
/src/NumberFormats.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 BrewPi/Elco Jacobs.
3 | * Copyright 2013 Matthew McGowan.
4 | *
5 | * This file is part of BrewPi.
6 | *
7 | * BrewPi is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * BrewPi is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with BrewPi. If not, see .
19 | */
20 | #pragma once
21 |
22 | #include
23 |
24 | void parseBytes(uint8_t *data, const char *s, uint8_t len);
25 | void printBytes(const uint8_t *data, uint8_t len, char *buf);
26 |
--------------------------------------------------------------------------------
/src/OLEDFourBit.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012 BrewPi/Elco Jacobs.
3 | *
4 | * This file is part of BrewPi.
5 | *
6 | * BrewPi is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * BrewPi is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with BrewPi. If not, see .
18 | */
19 |
20 | /* This is an adaptation of the Arduino LiquidCrystal library for the
21 | * NHD-0420DZW-AY5-ND OLED display, made by NewHaven. The display should be HD44780 compatible but isn't.
22 | * Differences are some of the control commands (cursor on/off), language setting and especially initialization sequence.
23 | */
24 |
25 | #ifndef OLEDFourBit_h
26 | #define OLEDFourBit_h
27 |
28 | #include
29 | #include "Print.h"
30 | #include "Pins.h"
31 |
32 | // commands
33 | #define LCD_CLEARDISPLAY 0x01
34 | #define LCD_RETURNHOME 0x02
35 | #define LCD_ENTRYMODESET 0x04
36 | #define LCD_DISPLAYCONTROL 0x08
37 | #define LCD_CURSORSHIFT 0x10
38 | #define LCD_FUNCTIONSET 0x28
39 | #define LCD_SETCGRAMADDR 0x40
40 | #define LCD_SETDDRAMADDR 0x80
41 |
42 | // flags for display entry mode
43 | #define LCD_ENTRYRIGHT 0x00
44 | #define LCD_ENTRYLEFT 0x02
45 | #define LCD_ENTRYSHIFTINCREMENT 0x01
46 | #define LCD_ENTRYSHIFTDECREMENT 0x00
47 |
48 | // flags for display on/off control
49 | #define LCD_DISPLAYON 0x04
50 | #define LCD_DISPLAYOFF 0x00
51 | #define LCD_CURSORON 0x02
52 | #define LCD_CURSOROFF 0x00
53 | #define LCD_BLINKON 0x01
54 | #define LCD_BLINKOFF 0x00
55 |
56 | // flags for display/cursor shift
57 | #define LCD_DISPLAYMOVE 0x08
58 | #define LCD_CURSORMOVE 0x00
59 | #define LCD_MOVERIGHT 0x04
60 | #define LCD_MOVELEFT 0x00
61 |
62 | // flags for function set
63 | #define LCD_8BITMODE 0x10
64 | #define LCD_4BITMODE 0x00
65 | #define LCD_ENGLISH_JAPANESE 0x00
66 | #define LCD_WESTERN_EUROPEAN_1 0x01
67 | #define LCD_ENGLISH_RUSSIAN 0x02
68 | #define LCD_WESTERN_EUROPEAN_2 0x03
69 |
70 | class OLEDFourBit : public Print {
71 | public:
72 | OLEDFourBit(){};
73 |
74 | #if BREWPI_STATIC_CONFIG==BREWPI_SHIELD_DIY
75 | void init() {
76 | init(DISP_RS, DISP_RW, DISP_EN, DISP_D4, DISP_D5, DISP_D6, DISP_D7); // initialize OLED with these pins
77 | }
78 | #endif
79 |
80 | void init(uint8_t rs, uint8_t rw, uint8_t enable,
81 | uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7);
82 |
83 | void begin(uint8_t cols, uint8_t rows);
84 |
85 | void clear();
86 | void home();
87 |
88 | void noDisplay();
89 | void display();
90 | void noBlink();
91 | void blink();
92 | void noCursor();
93 | void cursor();
94 | void scrollDisplayLeft();
95 | void scrollDisplayRight();
96 | void leftToRight();
97 | void rightToLeft();
98 | void autoscroll();
99 | void noAutoscroll();
100 |
101 | void createChar(uint8_t, uint8_t[]);
102 | void setCursor(uint8_t, uint8_t);
103 |
104 | virtual size_t write(uint8_t);
105 |
106 | size_t print_P(const char * str) { // print a string stored in PROGMEM
107 | char buf[21]; // create buffer in RAM
108 | strlcpy(buf, str, 20); // ESP8266 has no concept of PROGMEM - we're good
109 | return print(buf); // print from RAM
110 | }
111 |
112 | // copy a line from the shadow copy to a string buffer and correct the degree sign
113 | void getLine(uint8_t lineNumber, char * buffer);
114 |
115 | void readContent(); // read the content from the display to the shadow copy buffer
116 |
117 | void command(uint8_t);
118 | char readChar();
119 |
120 | void setBufferOnly(bool bufferOnly) {}
121 |
122 | void printSpacesToRestOfLine();
123 |
124 | void resetBacklightTimer(){ /* not implemented for OLED, doesn't have a backlight. */ }
125 |
126 | void updateBacklight(){ /* not implemented for OLED, doesn't have a backlight. */ }
127 |
128 | using Print::write;
129 |
130 | private:
131 | void send(uint8_t, uint8_t);
132 | void write4bits(uint8_t);
133 | void pulseEnable();
134 | void waitBusy();
135 |
136 | uint8_t _rs_pin; // LOW: command. HIGH: character.
137 | uint8_t _rw_pin; // LOW: write to oled. HIGH: read from oled.
138 | uint8_t _enable_pin; // activated by a HIGH pulse.
139 | uint8_t _busy_pin;
140 | uint8_t _data_pins[4];
141 |
142 | uint8_t _displayfunction;
143 | uint8_t _displaycontrol;
144 | uint8_t _displaymode;
145 | uint8_t _initialized;
146 | uint8_t _currline;
147 | uint8_t _currpos;
148 | uint8_t _numlines;
149 |
150 | char content[4][21]; // always keep a copy of the display content in this variable
151 |
152 | bool _bufferOnly;
153 |
154 | };
155 |
156 | #endif
157 |
--------------------------------------------------------------------------------
/src/OneWireActuator.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 BrewPi/Elco Jacobs.
3 | * Copyright 2013 Matthew McGowan
4 | *
5 | * This file is part of BrewPi.
6 | *
7 | * BrewPi is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * BrewPi is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with BrewPi. If not, see .
19 | */
20 |
21 | #pragma once
22 |
23 | #ifdef ARDUINO
24 |
25 | #include "Brewpi.h"
26 | #include "Actuator.h"
27 |
28 | #ifdef BREWPI_DS2413
29 | #include "DS2413.h"
30 | #endif
31 |
32 | #include "PiLink.h"
33 |
34 | /**
35 | * An actuator or sensor that operates by communicating with a DS2413 device.
36 | *
37 | */
38 | class OneWireActuator : public Actuator
39 | #if DS2413_SUPPORT_SENSE
40 | , SwitchSensor
41 | #endif
42 | {
43 | public:
44 |
45 | OneWireActuator(OneWire* bus, DeviceAddress address, pio_t pio, bool invert=true) {
46 | init(bus, address, pio, invert);
47 | }
48 |
49 | void init(OneWire* bus, DeviceAddress address, pio_t pio, bool invert=true) {
50 | this->invert = invert;
51 | this->pio = pio;
52 | device.init(bus, address);
53 | }
54 |
55 | void setActive(bool active) {
56 | device.channelWrite(pio, active^invert);
57 | }
58 |
59 | bool isActive() {
60 | return device.channelRead(pio, false);
61 | }
62 |
63 | #if DS2413_SUPPORT_SENSE
64 | bool sense() {
65 | device.channelWrite(pio, 0);
66 | return device.channelSense(pio, invert); // on device failure, default is high for invert, low for regular.
67 | }
68 | #endif
69 |
70 | private:
71 | #ifdef BREWPI_DS2413
72 | DS2413 device;
73 | #endif
74 | pio_t pio;
75 | bool invert;
76 | };
77 |
78 | #endif
--------------------------------------------------------------------------------
/src/OneWireDevices.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 BrewPi/Elco Jacobs.
3 | * Copyright 2013 Matthew McGowan
4 | *
5 | * This file is part of BrewPi.
6 | *
7 | * BrewPi is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * BrewPi is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with BrewPi. If not, see .
19 | */
20 |
21 | #include "Brewpi.h"
22 |
23 | void parseBytes(uint8_t* data, const char* s, uint8_t len);
24 | void printBytes(const uint8_t* data, uint8_t len, char* buf);
25 |
--------------------------------------------------------------------------------
/src/OneWireTempSensor.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 BrewPi/Elco Jacobs.
3 | * Copyright 2013 Matthew McGowan
4 | *
5 | * This file is part of BrewPi.
6 | *
7 | * BrewPi is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * BrewPi is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with BrewPi. If not, see .
19 | */
20 |
21 | #pragma once
22 |
23 | #include "Brewpi.h"
24 | #include "TempSensor.h"
25 | #include "FastDigitalPin.h"
26 | #include "Ticks.h"
27 |
28 | class DallasTemperature;
29 | class OneWire;
30 | typedef uint8_t DeviceAddress[8];
31 |
32 | /**
33 | * \brief A OneWire attached temperature sensor
34 | *
35 | * \ingroup hardware
36 | */
37 | class OneWireTempSensor : public BasicTempSensor {
38 | public:
39 | /**
40 | * \brief Constructs a new onewire temp sensor.
41 | *
42 | * /param bus The onewire bus this sensor is on.
43 | * /param address The onewire address for this sensor. If all bytes are 0 in the address, the first temp sensor
44 | * on the bus is used.
45 | * /param calibration A temperature value that is added to all readings. This can be used to calibrate the sensor.
46 | */
47 | OneWireTempSensor(OneWire* bus, DeviceAddress address, fixed4_4 calibrationOffset)
48 | : oneWire(bus), sensor(NULL) {
49 | connected = true; // assume connected. Transition from connected to disconnected prints a message.
50 | memcpy(sensorAddress, address, sizeof(DeviceAddress));
51 | this->calibrationOffset = calibrationOffset;
52 | };
53 |
54 | ~OneWireTempSensor();
55 |
56 | /**
57 | * \brief Check if sensor device is connected
58 | */
59 | bool isConnected(){
60 | return connected;
61 | }
62 |
63 | bool init();
64 | temperature read();
65 |
66 | private:
67 | /**
68 | * \brief The sensor precision, in bits.
69 | */
70 | constexpr static uint8_t sensorPrecision = 4;
71 |
72 | void setConnected(bool connected);
73 | bool requestConversion();
74 |
75 |
76 | /**
77 | * \brief Wait for sensor to sample the environment
78 | */
79 | void waitForConversion()
80 | {
81 | wait.millis(750);
82 | }
83 |
84 | temperature readAndConstrainTemp();
85 |
86 | OneWire * oneWire;
87 | DallasTemperature * sensor;
88 | DeviceAddress sensorAddress; //!< Sensor address
89 |
90 | fixed4_4 calibrationOffset; //!< Temperature offset needed for calibration
91 | bool connected; //!< Probe connection state
92 |
93 | };
94 |
--------------------------------------------------------------------------------
/src/PiLink.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 BrewPi/Elco Jacobs.
3 | * Copyright 2013 Matthew McGowan.
4 | * Copyright 2020 Scott Peshak
5 | *
6 | * This file is part of BrewPi.
7 | *
8 | * BrewPi is free software: you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation, either version 3 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * BrewPi is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU General Public License
19 | * along with BrewPi. If not, see .
20 | */
21 |
22 | #pragma once
23 | #include
24 | #include
25 |
26 | #include "Brewpi.h"
27 | #include "DeviceManager.h"
28 | #include "DeviceNameManager.h"
29 | #include "Logger.h"
30 | #include "PiStream.h"
31 | #include
32 | #include "JsonMessages.h"
33 |
34 | class DeviceConfig;
35 |
36 | /**
37 | * \brief Interface between brewpi controller and the outside world (Commonly a
38 | * RaspberryPi, hence the name).
39 | */
40 | template class PiLink : public PiStream {
41 | static_assert(std::is_base_of::value, "StreamType must be a Stream");
42 |
43 | public:
44 | PiLink(StreamType &stream) : PiStream(stream) {}
45 |
46 | /**
47 | * \brief Notify the Pi of the current state.
48 | *
49 | * Forcibly sends the current temperature information to cause data logging.
50 | * Optionally includes an annotation.
51 | *
52 | * \param beerAnnotation - Annotation for the beer
53 | * \param fridgeAnnotation - Annotation for the beer
54 | */
55 | void sendStateNotification(const char *beerAnnotation = nullptr, const char *fridgeAnnotation = nullptr) {
56 | printTemperatures(beerAnnotation, fridgeAnnotation);
57 | }
58 |
59 | /**
60 | * \brief Send a status message containing the current temperatures
61 | *
62 | * Can include optional annotations. The monitoring script will process
63 | * and log this data. While this is also the response to the request for
64 | * temperature ('t') command, it is used as a general purpose alert to the
65 | * controller script. (This is why it is included in PiLink, and not
66 | * CommandProcessor, despite the latter seeming to be a more logical
67 | * location
68 | * \param beerAnnotation - Annotation for the beer
69 | * \param fridgeAnnotation - Annotation for the beer
70 | */
71 | void printTemperatures(const char *beerAnnotation, const char *fridgeAnnotation) {
72 | // StaticJsonDocument<1024> doc;
73 | DynamicJsonDocument doc(1024);
74 | printTemperaturesJson(doc, beerAnnotation, fridgeAnnotation);
75 | this->sendJsonMessage('T', doc);
76 | }
77 | };
78 |
79 | #if defined(ESP32S2)
80 | extern PiLink::type> piLink;
81 | #else
82 | extern PiLink::type> piLink;
83 | #endif
84 |
--------------------------------------------------------------------------------
/src/Pins.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 BrewPi/Elco Jacobs.
3 | *
4 | * This file is part of BrewPi.
5 | *
6 | * BrewPi is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * BrewPi is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with BrewPi. If not, see .
18 | */
19 |
20 | #pragma once
21 |
22 | #include "Brewpi.h"
23 |
24 | #if BREWPI_STATIC_CONFIG==BREWPI_SHIELD_REV_A
25 | #ifndef beerSensorPin
26 | #define beerSensorPin A5 // OneWire 1
27 | #endif
28 |
29 | #ifndef fridgeSensorPin
30 | #define fridgeSensorPin A4 // OneWire 2
31 | #endif
32 |
33 | #ifndef coolingPin
34 | #define coolingPin 6
35 | #endif
36 |
37 | #ifndef heatingPin
38 | #define heatingPin 5
39 | #endif
40 |
41 | #endif
42 |
43 | #if BREWPI_STATIC_CONFIG==BREWPI_SHIELD_REV_C
44 |
45 | #ifndef oneWirePin
46 | #define oneWirePin A4
47 | #endif
48 |
49 | #ifndef actuatorPin1
50 | #define actuatorPin1 2
51 | #endif
52 |
53 | #ifndef actuatorPin2
54 | #define actuatorPin2 5
55 | #endif
56 |
57 | #ifndef actuatorPin3
58 | #define actuatorPin3 6
59 | #endif
60 |
61 | #ifndef actuatorPin4
62 | #define actuatorPin4 A5
63 | #endif
64 |
65 | #endif
66 |
67 | #if BREWPI_STATIC_CONFIG==BREWPI_SHIELD_REV_A || BREWPI_STATIC_CONFIG==BREWPI_SHIELD_REV_C
68 |
69 | #ifndef doorPin
70 | #define doorPin 4
71 | #endif
72 |
73 | #ifndef alarmPin
74 | #define alarmPin 3
75 | #endif
76 |
77 | #ifndef lcdLatchPin
78 | #define lcdLatchPin 10
79 | #endif
80 |
81 | // If you change the interrupt pins, you will also have to review the interrupt vectors of the rotary encoder
82 | #define rotarySwitchPin 7 // INT6 on leo or PCINT23 on uno
83 | #define rotaryAPin 8 // PCINT4 on leo or PCINT0 on uno
84 | #define rotaryBPin 9 // PCINT5 on leo or PCINT1 on uno
85 |
86 | #define BREWPI_INVERT_ACTUATORS 1
87 |
88 | #elif BREWPI_STATIC_CONFIG==BREWPI_SHIELD_DIY
89 |
90 | // pins
91 | #ifndef oneWirePin // So we can specify a single bus if we prefer
92 | #ifndef beerSensorPin
93 | #define beerSensorPin 10
94 | #endif
95 |
96 | #ifndef fridgeSensorPin
97 | #define fridgeSensorPin 11
98 | #endif
99 | #endif
100 | // Pay attention when changing the pins for the rotary encoder.
101 | // They should be connected to external interrupt INT0, INT1 and INT3
102 |
103 | #ifndef rotaryAPin
104 | #define rotaryAPin 2 // INT1
105 | #endif
106 |
107 | #ifndef rotaryBPin
108 | #define rotaryBPin 1 // INT3
109 | #endif
110 |
111 | #ifndef rotarySwitchPin
112 | #define rotarySwitchPin 0 // INT2
113 | #endif
114 |
115 | #ifndef coolingPin
116 | #define coolingPin 12
117 | #endif
118 |
119 | #ifndef heatingPin
120 | #define heatingPin 13
121 | #endif
122 |
123 | #ifndef doorPin
124 | #define doorPin A5
125 | #endif
126 |
127 | // TODO - Fix the code for the LCD module
128 | #define DISP_RS 9
129 | #define DISP_RW 8
130 | #define DISP_EN 7
131 | #define DISP_D4 6
132 | #define DISP_D5 5
133 | #define DISP_D6 4
134 | #define DISP_D7 3
135 |
136 | #ifndef BREWPI_INVERT_ACTUATORS
137 | #define BREWPI_INVERT_ACTUATORS 0
138 | #endif
139 |
140 |
141 | #endif
142 |
143 | // You can use the internal pull-up resistors instead of external ones for the doorPin and the rotary encoder pins
144 | #ifndef USE_INTERNAL_PULL_UP_RESISTORS
145 | #define USE_INTERNAL_PULL_UP_RESISTORS 1
146 | #endif
--------------------------------------------------------------------------------
/src/PromServer.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #ifdef ENABLE_PROMETHEUS_SERVER
3 | #include "Brewpi.h"
4 | #include "TemperatureFormats.h"
5 | #include "Ticks.h"
6 |
7 | #if defined(ESP32)
8 | #include "AsyncTCP.h"
9 | #else
10 | #include "ESPAsyncTCP.h"
11 | #endif
12 |
13 | #include "ESPAsyncWebServer.h"
14 |
15 | /**
16 | * \brief A server for handling Prometheus metrics endpoint
17 | *
18 | * Implements the Prometheus [metrics
19 | * format](https://prometheus.io/docs/instrumenting/exposition_formats/).
20 | * Allows data gathering using an industry standard metrics system. This opens
21 | * the possibility of more powerful reporting & alerting.
22 | *
23 | * Because enumerating and reading probes can take a relatively long time, this
24 | * class implements a cache so that subsequent data requests will use the
25 | * cached value. This cache only applies to the probe values, not the entire
26 | * metrics response. External code can use PromServer::invalidateCache() to
27 | * force cache updates.
28 | */
29 | class PromServer {
30 | public:
31 | void setup();
32 | static void onNotFound(AsyncWebServerRequest *request);
33 | static void metrics(AsyncWebServerRequest *request);
34 | static String templateProcessor(const String &var);
35 | static void invalidateCache();
36 |
37 | private:
38 | /**
39 | * \brief ESPAsyncWebServer connection listener.
40 | *
41 | * Handles incoming requests to the Prometheus port and dispatches to handler
42 | * methods.
43 | * \see https://github.com/me-no-dev/ESPAsyncWebServer
44 | */
45 | AsyncWebServer server = AsyncWebServer(Config::Prometheus::port);
46 | static String probeCache;
47 |
48 | /**
49 | * \brief Template string for the metrics data.
50 | *
51 | * Placeholders values (surrounded by `%` chars) are replaced at runtime using
52 | * PromServer::templateProcessor().
53 | *
54 | * \see templateProcessor()
55 | */
56 | static const char metricsTemplate[];
57 |
58 | /**
59 | * \brief Template for an individual probe value
60 | *
61 | * Used to fill the PROBE_VALUES section of metricsTemplate for each
62 | * enumerated probe.
63 | *
64 | * \see probeValues()
65 | */
66 | static const char probeTemplate[];
67 |
68 | static String formatProbeTemp(const temperature temp);
69 | static String probeValues();
70 |
71 | /**
72 | * \brief How long to cache probe readings
73 | */
74 | static constexpr auto cacheTime = 300;
75 |
76 | /**
77 | * \brief Tick count of the last time the probe cache was built.
78 | *
79 | * Used to track the expiration of the probe cache.
80 | */
81 | static ticks_seconds_t dataLastUpdate;
82 | };
83 |
84 | extern PromServer promServer;
85 | #endif // ENABLE_PROMETHEUS_SERVER
86 |
--------------------------------------------------------------------------------
/src/Random.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 BrewPi/Elco Jacobs.
3 | *
4 | * This file is part of BrewPi.
5 | *
6 | * BrewPi is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * BrewPi is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with BrewPi. If not, see .
18 | */
19 |
20 | #ifndef BREWPI_RANDOM
21 | #define BREWPI_RANDOM 1
22 | #endif
23 |
24 | #if BREWPI_RANDOM
25 | // Have to include this separately from Arduino.h, since it redefines makeWord()
26 | #include
27 |
28 | #endif
--------------------------------------------------------------------------------
/src/RotaryEncoder.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 BrewPi/Elco Jacobs.
3 | *
4 | * This file is part of BrewPi.
5 | *
6 | * BrewPi is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * BrewPi is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with BrewPi. If not, see .
18 | */
19 |
20 | #pragma once
21 |
22 | #include "Brewpi.h"
23 |
24 | // Values returned by 'process'
25 | // No complete step yet.
26 | #define DIR_NONE 0x0
27 | // Clockwise step.
28 | #define DIR_CW 0x10
29 | // Anti-clockwise step.
30 | #define DIR_CCW 0x20
31 |
32 | class RotaryEncoder
33 | {
34 | public:
35 | static void init();
36 | static void setRange(int16_t start, int16_t min, int16_t max);
37 | static void process();
38 |
39 | static bool changed(); // returns one if the value changed since the last call of changed.
40 | static int16_t read();
41 |
42 | static int16_t readsteps(){
43 | return steps;
44 | }
45 |
46 | static bool pushed(){
47 | return pushFlag;
48 | }
49 |
50 | static void resetPushed(){
51 | pushFlag = false;
52 | }
53 |
54 | static void setPushed();
55 |
56 | private:
57 |
58 | static int16_t maximum;
59 | static int16_t minimum;
60 | static volatile int16_t steps;
61 | static volatile bool pushFlag;
62 | };
63 |
64 | extern RotaryEncoder rotaryEncoder;
65 |
--------------------------------------------------------------------------------
/src/Sensor.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 BrewPi/Elco Jacobs.
3 | * Copyright 2013 Matthew McGowan.
4 | *
5 | * This file is part of BrewPi.
6 | *
7 | * BrewPi is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * BrewPi is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with BrewPi. If not, see .
19 | */
20 |
21 | #include "Brewpi.h"
22 | #include "Sensor.h"
23 |
--------------------------------------------------------------------------------
/src/Sensor.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 BrewPi/Elco Jacobs.
3 | * Copyright 2013 Matthew McGowan.
4 | *
5 | * This file is part of BrewPi.
6 | *
7 | * BrewPi is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * BrewPi is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with BrewPi. If not, see .
19 | */
20 |
21 | #pragma once
22 |
23 | #include "Brewpi.h"
24 |
25 | template class Sensor
26 | {
27 | public:
28 | virtual T sense()=0;
29 |
30 | virtual ~Sensor() {}
31 | };
32 |
33 | template
34 | class ValueSensor : public Sensor
35 | {
36 | public:
37 | ValueSensor(T initial) : value(initial) {}
38 |
39 | virtual T sense() {
40 | return (T)0;
41 | }
42 |
43 | void setValue(T _value) {
44 | value = _value;
45 | }
46 |
47 | private:
48 | T value;
49 | };
50 |
51 | typedef Sensor SwitchSensor;
52 |
53 |
54 |
--------------------------------------------------------------------------------
/src/SensorArduinoPin.h:
--------------------------------------------------------------------------------
1 | /*
2 | * File: SensorArduinoPin.h
3 | * Author: mat
4 | *
5 | * Created on 22 August 2013, 19:36
6 | */
7 |
8 | #pragma once
9 |
10 | #ifdef ARDUINO
11 |
12 | #include "Brewpi.h"
13 | #include "FastDigitalPin.h"
14 | #include "Pins.h"
15 |
16 | /* A SwitchSensor whose state is provided by a hardware pin.
17 | By using a template, the compiler can inline and optimize the call to digitalRead to a single instruction.
18 | */
19 | template
20 | class DigitalConstantPinSensor : public SwitchSensor
21 | {
22 | public:
23 | DigitalConstantPinSensor() {
24 | fastPinMode(pin, internalPullup ? INPUT_PULLUP : INPUT);
25 | }
26 |
27 | virtual bool sense() {
28 | return fastDigitalRead(pin) ^ invert;
29 | }
30 | };
31 |
32 | class DigitalPinSensor : public SwitchSensor
33 | {
34 | private:
35 | bool invert;
36 | uint8_t pin;
37 |
38 |
39 |
40 | public:
41 |
42 | DigitalPinSensor(uint8_t pin, bool invert)
43 | {
44 | pinMode(pin, USE_INTERNAL_PULL_UP_RESISTORS ? INPUT_PULLUP : INPUT);
45 | this->invert = invert;
46 | this->pin = pin;
47 | }
48 |
49 | virtual bool sense() {
50 | return digitalRead(pin) ^ invert;
51 | }
52 | };
53 |
54 | #endif
55 |
56 |
--------------------------------------------------------------------------------
/src/SettingLoader.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 BrewPi/Elco Jacobs.
3 | * Copyright 2013 Matthew McGowan.
4 | * Copyright 2020 Scott Peshak
5 | *
6 | * This file is part of BrewPi.
7 | *
8 | * BrewPi is free software: you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation, either version 3 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * BrewPi is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU General Public License
19 | * along with BrewPi. If not, see .
20 | */
21 | #pragma once
22 |
23 | #include "Brewpi.h"
24 | #include
25 |
26 | class SettingLoader {
27 | public:
28 | static void processSettingKeypair(JsonPair kv);
29 |
30 | private:
31 | static void setBeerSetting(const char *val);
32 | static void setFridgeSetting(const char *val);
33 | };
34 |
--------------------------------------------------------------------------------
/src/SettingsManager.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 BrewPi/Elco Jacobs.
3 | * Copyright 2013 Matthew McGowan.
4 | *
5 | * This file is part of BrewPi.
6 | *
7 | * BrewPi is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later v7ersion.
11 | *
12 | * BrewPi is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with BrewPi. If not, see .
19 | */
20 |
21 | #include "Brewpi.h"
22 | #include "SettingsManager.h"
23 | #include "TempControl.h"
24 | #include "PiLink.h"
25 | #include "TempSensorExternal.h"
26 |
27 | void SettingsManager::loadSettings()
28 | {
29 | logDebug("loading settings");
30 |
31 |
32 | if (!eepromManager.applySettings())
33 | {
34 | TempControl::loadDefaultSettings();
35 | TempControl::loadDefaultConstants();
36 | minTimes.setDefaults();
37 |
38 | deviceManager.setupUnconfiguredDevices();
39 |
40 | logWarning(WARNING_START_IN_SAFE_MODE);
41 | }
42 |
43 | #if (BREWPI_SIMULATE)
44 | {
45 | logDebug("Setting up simulator devices.");
46 |
47 | // temp sensors are special in the simulator - make sure they are set up even if not
48 | // configured in the eeprom
49 | DeviceConfig cfg;
50 | cfg.deviceHardware = DEVICE_HARDWARE_ONEWIRE_TEMP;
51 | cfg.chamber = 1;
52 | cfg.deviceFunction = DEVICE_CHAMBER_ROOM_TEMP;
53 | deviceManager.uninstallDevice(cfg);
54 | deviceManager.installDevice(cfg);
55 |
56 | cfg.deviceFunction = DEVICE_CHAMBER_TEMP;
57 | deviceManager.uninstallDevice(cfg);
58 | deviceManager.installDevice(cfg);
59 |
60 | cfg.beer = 1;
61 | cfg.deviceFunction = DEVICE_BEER_TEMP;
62 | deviceManager.uninstallDevice(cfg);
63 | deviceManager.installDevice(cfg);
64 |
65 | }
66 | #endif
67 |
68 | }
69 |
70 | SettingsManager settingsManager;
--------------------------------------------------------------------------------
/src/SettingsManager.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 BrewPi/Elco Jacobs.
3 | * Copyright 2013 Matthew McGowan.
4 | *
5 | * This file is part of BrewPi.
6 | *
7 | * BrewPi is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * BrewPi is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with BrewPi. If not, see .
19 | */
20 |
21 | #pragma once
22 |
23 | #include "Brewpi.h"
24 | #include
25 | #include "EepromManager.h"
26 | #include "DeviceManager.h"
27 |
28 | /**
29 | * \brief Manages the settings and devices for multiple carboys and multiple chambers.
30 | *
31 | * This is the soul of brewpi.
32 | *
33 | * The manager hides the persistence of the settings, and uses the code closest to the settings to provide
34 | * useful defaults.
35 | */
36 | class SettingsManager
37 | {
38 | public:
39 | /**
40 | * \brief Initialize settings.
41 | *
42 | * This attempts to read from persisted settings and apply settings from there.
43 | * If that's not possible, defaults are used.
44 | */
45 | static void loadSettings();
46 | };
47 |
48 | extern SettingsManager settingsManager;
49 |
--------------------------------------------------------------------------------
/src/TempSensor.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 BrewPi/Elco Jacobs.
3 | *
4 | * This file is part of BrewPi.
5 | *
6 | * BrewPi is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * BrewPi is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with BrewPi. If not, see .
18 | */
19 |
20 | #include "Brewpi.h"
21 | #include "TempSensor.h"
22 | #include "PiLink.h"
23 | #include "Ticks.h"
24 |
25 |
26 | /**
27 | * \brief Initialize temp sensor
28 | */
29 | void TempSensor::init()
30 | {
31 | logDebug("tempsensor::init - begin %d", failedReadCount);
32 | if (_sensor && _sensor->init() && (failedReadCount<0 || failedReadCount>60)) {
33 | temperature temp = _sensor->read();
34 | if (temp!=TEMP_SENSOR_DISCONNECTED) {
35 | logDebug("initializing filters with value %d", temp);
36 | fastFilter.init(temp);
37 | slowFilter.init(temp);
38 | slopeFilter.init(0);
39 | prevOutputForSlope = slowFilter.readOutputDoublePrecision();
40 | failedReadCount = 0;
41 | }
42 | }
43 | }
44 |
45 | /**
46 | * \brief Read the sensor and update the filters
47 | */
48 | void TempSensor::update()
49 | {
50 | temperature temp;
51 | if (!_sensor || (temp=_sensor->read())==TEMP_SENSOR_DISCONNECTED) {
52 | if(failedReadCount >= 0)
53 | failedReadCount++;
54 | failedReadCount = min(failedReadCount,int8_t(127)); // limit
55 | return;
56 | }
57 |
58 | fastFilter.add(temp);
59 | slowFilter.add(temp);
60 |
61 | // update slope filter every 3 samples.
62 | // averaged differences will give the slope. Use the slow filter as input
63 | updateCounter--;
64 | // initialize first read for slope filter after (255-4) seconds. This prevents an influence for the startup inaccuracy.
65 | if(updateCounter == 4){
66 | // only happens once after startup.
67 | prevOutputForSlope = slowFilter.readOutputDoublePrecision();
68 | }
69 | if(updateCounter == 0){
70 | temperature_precise slowFilterOutput = slowFilter.readOutputDoublePrecision();
71 | temperature_precise diff = slowFilterOutput - prevOutputForSlope;
72 | temperature diff_upper = diff >> 16;
73 | if(diff_upper > 27){ // limit to prevent overflow INT_MAX/1200 = 27.14
74 | diff = (27l << 16);
75 | }
76 | else if(diff_upper < -27){
77 | diff = (-27l << 16);
78 | }
79 | slopeFilter.addDoublePrecision(1200*diff); // Multiply by 1200 (1h/4s), shift to single precision
80 | prevOutputForSlope = slowFilterOutput;
81 | updateCounter = 3;
82 | }
83 | }
84 |
85 | /**
86 | * \brief Read the sensor value after processing through the fast filter
87 | */
88 | temperature TempSensor::readFastFiltered(){
89 | return fastFilter.readOutput(); //return most recent unfiltered value
90 | }
91 |
92 | /**
93 | * \brief Read the sensor value after processing through the slow filter
94 | */
95 | temperature TempSensor::readSlowFiltered(){
96 | return slowFilter.readOutput(); //return most recent unfiltered value
97 | }
98 |
99 | /**
100 | * \brief Read the sensor value after processing through the slope filter
101 | */
102 | temperature TempSensor::readSlope(){
103 | // return slope per hour.
104 | temperature_precise doublePrecision = slopeFilter.readOutputDoublePrecision();
105 | return doublePrecision>>16; // shift to single precision
106 | }
107 |
108 |
109 | /**
110 | * \brief Detect the positive peak
111 | *
112 | * Uses the detectPosPeak() method of the slow filter
113 | */
114 | temperature TempSensor::detectPosPeak(){
115 | return slowFilter.detectPosPeak();
116 | }
117 |
118 |
119 | /**
120 | * \brief Detect the negative peak
121 | *
122 | * Uses the detectNegPeak() method of the slow filter
123 | */
124 | temperature TempSensor::detectNegPeak(){
125 | return slowFilter.detectNegPeak();
126 | }
127 |
128 | /**
129 | * \brief Set the b coefficients on the fast filter
130 | *
131 | * @param b - New coefficient value
132 | */
133 | void TempSensor::setFastFilterCoefficients(uint8_t b){
134 | fastFilter.setCoefficients(b);
135 | }
136 |
137 |
138 | /**
139 | * \brief Set the b coefficients on the slow filter
140 | *
141 | * @param b - New coefficient value
142 | */
143 | void TempSensor::setSlowFilterCoefficients(uint8_t b){
144 | slowFilter.setCoefficients(b);
145 | }
146 |
147 |
148 | /**
149 | * \brief Set the b coefficients on the slope filter
150 | *
151 | * @param b - New coefficient value
152 | */
153 | void TempSensor::setSlopeFilterCoefficients(uint8_t b){
154 | slopeFilter.setCoefficients(b);
155 | }
156 |
157 | /**
158 | * \brief Get wrapped sensor
159 | */
160 | BasicTempSensor& TempSensor::sensor() {
161 | return *_sensor;
162 | }
163 |
--------------------------------------------------------------------------------
/src/TempSensor.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 BrewPi/Elco Jacobs.
3 | * Copyright 2013 Matthew McGowan.
4 | *
5 | * This file is part of BrewPi.
6 | *
7 | * BrewPi is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * BrewPi is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with BrewPi. If not, see .
19 | */
20 |
21 | #pragma once
22 |
23 | #include "Brewpi.h"
24 | #include "FilterCascaded.h"
25 | #include "TempSensorBasic.h"
26 | #include
27 |
28 | #define TEMP_SENSOR_DISCONNECTED INVALID_TEMP
29 |
30 | #ifndef TEMP_SENSOR_CASCADED_FILTER
31 | #define TEMP_SENSOR_CASCADED_FILTER 1
32 | #endif
33 |
34 | #if TEMP_SENSOR_CASCADED_FILTER
35 | typedef CascadedFilter TempSensorFilter;
36 | #else
37 | typedef FixedFilter TempSensorFilter;
38 | #endif
39 |
40 |
41 | /**
42 | * \brief Types of temp sensors, defined by their use.
43 | */
44 | enum TempSensorType {
45 | TEMP_SENSOR_TYPE_FRIDGE=1,
46 | TEMP_SENSOR_TYPE_BEER
47 | };
48 |
49 |
50 | /**
51 | * \brief General interface for all temperature sensor devices.
52 | *
53 | * Wraps up a BasicTempSensor and processes the values through several filters.
54 | * The filters are either CascadedFilter or FixedFilter implementations,
55 | * depending on the compile time value of the TEMP_SENSOR_CASCADED_FILTER
56 | * macro.
57 | */
58 | class TempSensor {
59 | public:
60 | TempSensor(TempSensorType sensorType, BasicTempSensor* sensor =NULL) {
61 | updateCounter = 255; // first update for slope filter after (255-4s)
62 | setSensor(sensor);
63 | }
64 |
65 | /**
66 | * \brief Set the underlying BasicTempSensor
67 | *
68 | * @param sensor - Temp sensor to wrap
69 | */
70 | void setSensor(BasicTempSensor* sensor) {
71 | _sensor = sensor;
72 | failedReadCount = -1;
73 | }
74 |
75 | /**
76 | * \brief Check if the sensor has a slow filter.
77 | */
78 | bool hasSlowFilter() { return true; }
79 |
80 | /**
81 | * \brief Check if the sensor has a fast filter.
82 | */
83 | bool hasFastFilter() { return true; }
84 |
85 | /**
86 | * \brief Check if the sensor has a slope filter.
87 | */
88 | bool hasSlopeFilter() { return true; }
89 |
90 | void init();
91 |
92 | /**
93 | * \brief Check if the sensor is connected.
94 | */
95 | bool isConnected() { return _sensor->isConnected(); }
96 |
97 | void update();
98 |
99 | temperature readFastFiltered();
100 |
101 | temperature readSlowFiltered();
102 |
103 | temperature readSlope();
104 |
105 | temperature detectPosPeak();
106 |
107 | temperature detectNegPeak();
108 |
109 | void setFastFilterCoefficients(uint8_t b);
110 |
111 | void setSlowFilterCoefficients(uint8_t b);
112 |
113 | void setSlopeFilterCoefficients(uint8_t b);
114 |
115 | BasicTempSensor& sensor();
116 |
117 | private:
118 | BasicTempSensor* _sensor; //!< Wrapped basic sensor
119 | TempSensorFilter fastFilter; //!< Fast reacting filter
120 | TempSensorFilter slowFilter; //!< Slow reacting filter
121 | TempSensorFilter slopeFilter; //!< Slope filter
122 | unsigned char updateCounter;
123 | temperature_precise prevOutputForSlope;
124 |
125 | /**
126 | * \brief An indication of how stale the data is in the filters.
127 | *
128 | * Each time a read fails, this value is incremented. It's used to reset the
129 | * filters after a large enough disconnect delay, and on the first init.
130 | *
131 | * `-1` for uninitialized, `>=0` afterwards.
132 | */
133 | int8_t failedReadCount;
134 |
135 | friend class ChamberManager;
136 | friend class Chamber;
137 | friend class DeviceManager;
138 | };
139 |
140 |
--------------------------------------------------------------------------------
/src/TempSensorBasic.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 BrewPi/Elco Jacobs.
3 | * Copyright 2013 Matthew McGowan.
4 | *
5 | * This file is part of BrewPi.
6 | *
7 | * BrewPi is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * BrewPi is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with BrewPi. If not, see .
19 | */
20 |
21 | #pragma once
22 |
23 | #include "TemperatureFormats.h"
24 |
25 |
26 | #define TEMP_SENSOR_DISCONNECTED INVALID_TEMP
27 |
28 |
29 | /**
30 | * Temperature sensor base
31 | * Pure virtual class.
32 | */
33 | class BasicTempSensor
34 | {
35 | public:
36 | virtual ~BasicTempSensor() { }
37 |
38 | /**
39 | * Check if sensor is connected
40 | */
41 | virtual bool isConnected() = 0;
42 |
43 | /**
44 | * Attempt to (re-)initialize the sensor.
45 | */
46 | virtual bool init() =0;
47 |
48 | /**
49 | * Fetch a new reading from the sensor
50 | */
51 | virtual temperature read() = 0;
52 | };
53 |
--------------------------------------------------------------------------------
/src/TempSensorDisconnected.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 BrewPi/Elco Jacobs.
3 | * Copyright 2013 Matthew McGowan.
4 | *
5 | * This file is part of BrewPi.
6 | *
7 | * BrewPi is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * BrewPi is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with BrewPi. If not, see .
19 | */
20 |
21 | #pragma once
22 |
23 | #include "TempSensor.h"
24 |
25 | /**
26 | * A BasicTempSensor that is always disconnected.
27 | *
28 | * This is used as a default sensor to placehold until real sensors are installed.
29 | */
30 | class DisconnectedTempSensor : public BasicTempSensor {
31 |
32 | public:
33 | bool isConnected() { return false; }
34 |
35 | bool init() {
36 | return read()!=TEMP_SENSOR_DISCONNECTED;
37 | }
38 |
39 | temperature read() {
40 | return TEMP_SENSOR_DISCONNECTED;
41 | }
42 |
43 | };
44 |
--------------------------------------------------------------------------------
/src/TempSensorExternal.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 BrewPi/Elco Jacobs.
3 | * Copyright 2013 Matthew McGowan.
4 | *
5 | * This file is part of BrewPi.
6 | *
7 | * BrewPi is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * BrewPi is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with BrewPi. If not, see .
19 | */
20 |
21 | #pragma once
22 |
23 | #include "Brewpi.h"
24 | #include "TempSensor.h"
25 |
26 | /**
27 | * A temp sensor whose value is not read from the device, but set in code.
28 | * This is used by the simulator.
29 | */
30 | class ExternalTempSensor : public BasicTempSensor
31 | {
32 | public:
33 | ExternalTempSensor(bool connected=false) : _temperature(0), _connected(false)
34 | {
35 | setConnected(connected);
36 | }
37 |
38 | void setConnected(bool connected)
39 | {
40 | this->_connected = connected;
41 | }
42 |
43 | bool isConnected() { return _connected; }
44 |
45 | bool init() {
46 | return read()!=TEMP_SENSOR_DISCONNECTED;
47 | }
48 |
49 | temperature read() {
50 | if (!isConnected())
51 | return TEMP_SENSOR_DISCONNECTED;
52 | return _temperature;
53 | }
54 |
55 | void setValue(temperature newTemp) {
56 | _temperature = newTemp;
57 | }
58 |
59 | private:
60 | temperature _temperature;
61 | bool _connected;
62 | };
63 |
--------------------------------------------------------------------------------
/src/TempSensorMock.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 BrewPi/Elco Jacobs.
3 | * Copyright 2013 Matthew McGowan.
4 | *
5 | * This file is part of BrewPi.
6 | *
7 | * BrewPi is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * BrewPi is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with BrewPi. If not, see .
19 | */
20 |
21 | #pragma once
22 |
23 | #include "Brewpi.h"
24 | #include "TempSensor.h"
25 |
26 | /**
27 | * A mock implementation of BasicTempSensor
28 | *
29 | * This is a fake temp sensor that shifts it's value on each read.
30 | */
31 | class MockTempSensor : public BasicTempSensor
32 | {
33 | public:
34 | MockTempSensor(temperature initial, temperature delta) : _temperature(initial), _delta(delta), _connected(true) { }
35 |
36 | void setConnected(bool connected)
37 | {
38 | _connected = connected;
39 | }
40 |
41 | bool isConnected() { return _connected; }
42 |
43 | bool init() {
44 | return read()!=TEMP_SENSOR_DISCONNECTED;
45 | }
46 |
47 | /**
48 | * Return the current temperature value.
49 | *
50 | * Shifts the temp value up/down (depending on tempcontrol mode) by `_delta` on each read.
51 | */
52 | temperature read()
53 | {
54 | if (!isConnected())
55 | return TEMP_SENSOR_DISCONNECTED;
56 |
57 | switch (tempControl.getMode()) {
58 | case COOLING:
59 | _temperature -= _delta;
60 | break;
61 | case HEATING:
62 | _temperature += _delta;
63 | break;
64 | }
65 |
66 | return _temperature;
67 | }
68 |
69 | private:
70 | /**
71 | * Current temperature value
72 | */
73 | temperature _temperature;
74 |
75 | /**
76 | * Delta to shift per read
77 | */
78 | temperature _delta;
79 | bool _connected;
80 | };
81 |
82 |
--------------------------------------------------------------------------------
/src/Ticks.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 BrewPi/Elco Jacobs.
3 | * Copyright 2013 Matthew McGowan.
4 | *
5 | * This file is part of BrewPi.
6 | *
7 | * BrewPi is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * BrewPi is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with BrewPi. If not, see .
19 | */
20 |
21 | #include "Brewpi.h"
22 | #include "Ticks.h"
23 |
24 | // return time that has passed since timeStamp, take overflow into account
25 | inline ticks_seconds_t timeSince(ticks_seconds_t currentTime, ticks_seconds_t previousTime){
26 | if(currentTime>=previousTime){
27 | return currentTime - previousTime;
28 | }
29 | else{
30 | // overflow has occurred
31 | return (currentTime + 1440) - (previousTime +1440); // add a day to both for calculation
32 | }
33 | }
34 |
35 | // return time that has passed since timeStamp, take overflow into account
36 | ticks_seconds_t ExternalTicks::timeSince(ticks_seconds_t previousTime){
37 | ticks_seconds_t currentTime = ticks.seconds();
38 | return ::timeSince(currentTime, previousTime);
39 | }
40 |
41 |
42 | #ifdef ARDUINO
43 |
44 | // return time that has passed since timeStamp, take overflow into account
45 | ticks_seconds_t HardwareTicks::timeSince(ticks_seconds_t previousTime){
46 | ticks_seconds_t currentTime = ticks.seconds();
47 | return ::timeSince(currentTime, previousTime);
48 | }
49 |
50 | ticks_seconds_t HardwareTicks::seconds() { return ::millis()/1000; }
51 |
52 |
53 | void HardwareDelay::millis(uint16_t millis) { ::delay(millis); }
54 |
55 | void HardwareDelay::seconds(uint16_t seconds) { millis(seconds<<10); }
56 |
57 | #endif
--------------------------------------------------------------------------------
/src/Ticks.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 BrewPi/Elco Jacobs.
3 | * Copyright 2013 Matthew McGowan.
4 | *
5 | * This file is part of BrewPi.
6 | *
7 | * BrewPi is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * BrewPi is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with BrewPi. If not, see .
19 | */
20 |
21 | #pragma once
22 |
23 | #include "Brewpi.h"
24 |
25 | typedef uint32_t ticks_millis_t;
26 | typedef uint32_t ticks_micros_t;
27 | typedef uint16_t ticks_seconds_t;
28 | typedef uint8_t ticks_seconds_tiny_t;
29 |
30 | /**
31 | * Ticks - interface to a millisecond timer
32 | *
33 | * With more code space, Ticks would have been a virtual base class, so all implementations can easily provide the same interface.
34 | * Here, the different implementations have no common (virtual) base class to save code space.
35 | * Instead, a typedef is used to compile-time select the implementation to use.
36 | * If that implementation doesn't implement the Ticks interface as expected, it will fail to compile.
37 | */
38 |
39 | /**
40 | * A Ticks implementation that increments the millis count each time it is called.
41 | * This is used for testing.
42 | */
43 | class MockTicks {
44 | public:
45 | MockTicks(uint8_t increment) : _increment(increment), _ticks(0) { }
46 |
47 | ticks_millis_t millis() { return _ticks+=_increment; }
48 | ticks_micros_t micros() { return _ticks+=_increment; }
49 | ticks_seconds_t seconds() { return millis()>>10; }
50 | ticks_seconds_t timeSince(ticks_seconds_t timeStamp) { return timeStamp-seconds(); }
51 | private:
52 |
53 | uint32_t _increment;
54 | uint32_t _ticks;
55 | };
56 |
57 | /**
58 | * Externally provided millis timer. The calling code takes care of advancing the timer by calling setMillis or incMillis.
59 | * This is used for testing and also by the simulator to provide simulated time.
60 | */
61 | class ExternalTicks {
62 | public:
63 | ExternalTicks() : _ticks(0) { }
64 |
65 | ticks_millis_t millis() { return _ticks; }
66 | ticks_micros_t micros() { return _ticks*1000; }
67 | ticks_seconds_t seconds() { return millis()/1000; }
68 | ticks_seconds_t timeSince(ticks_seconds_t timeStamp);
69 |
70 | void setMillis(ticks_millis_t now) { _ticks = now; }
71 | void incMillis(ticks_millis_t advance) { _ticks += advance; }
72 | private:
73 | ticks_millis_t _ticks;
74 | };
75 |
76 |
77 | /**
78 | * A delay class that does nothing.
79 | * In the AVR simulator, delays using millis() take a very long time. Using this class makes it possible to step through the code.
80 | */
81 | class NoOpDelay {
82 | public:
83 | void seconds(uint16_t seconds) { millis(seconds<<10); }
84 | void millis(uint32_t millis) { }
85 | void microseconds(uint32_t micros) { }
86 | };
87 |
88 | #include "TicksArduino.h"
89 |
90 | // Determine the type of Ticks needed
91 | // TICKS_IMPL_CONFIG is the code string passed to the constructor of the Ticks implementation
92 |
93 | #if BREWPI_SIMULATE
94 | /** For simulation, by the simulator - each step in the simulator advances the time by one second. */
95 | typedef ExternalTicks TicksImpl;
96 | #define TICKS_IMPL_CONFIG // no configuration of ExternalTicks necessary
97 |
98 | #elif BREWPI_EMULATE
99 | /** When debugging in AVR studio (and running normal brewpi - not the simulator), use a simple MockTicks that increments 100
100 | millis each time it's called. */
101 | typedef MockTicks TicksImpl;
102 | #define TICKS_IMPL_CONFIG 100
103 |
104 | #else // use regular hardware timer/delay
105 | typedef HardwareTicks TicksImpl;
106 | #define TICKS_IMPL_CONFIG
107 | #endif // BREWPI_EMULATE
108 |
109 | extern TicksImpl ticks;
110 |
111 | // Determine the type of delay required.
112 | // For emulation, don't delay, since time in the emulator is not real time, so the delay is meaningless.
113 | // For regular code, use the arduino delay function.
114 |
115 | #if BREWPI_EMULATE || !defined(ARDUINO)
116 | typedef NoOpDelay DelayImpl; // for emulation (avr debugger), don't bother delaying, it takes ages.
117 | #define DELAY_IMPL_CONFIG
118 | #else
119 | typedef HardwareDelay DelayImpl;
120 | #define DELAY_IMPL_CONFIG
121 | #endif
122 |
123 | extern DelayImpl wait;
124 |
--------------------------------------------------------------------------------
/src/TicksArduino.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 BrewPi/Elco Jacobs.
3 | * Copyright 2013 Matthew McGowan.
4 | *
5 | * This file is part of BrewPi.
6 | *
7 | * BrewPi is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * BrewPi is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with BrewPi. If not, see .
19 | */
20 |
21 | #pragma once
22 |
23 | #ifdef ARDUINO
24 |
25 | #include "Brewpi.h"
26 |
27 | /*
28 | * The Ticks class provides the time period since the device was powered up.
29 | */
30 | class HardwareTicks {
31 | public:
32 | ticks_millis_t millis() { return ::millis(); }
33 | ticks_micros_t micros() { return ::micros(); }
34 | ticks_seconds_t seconds();
35 |
36 | ticks_seconds_t timeSince(ticks_seconds_t timeStamp);
37 | };
38 |
39 |
40 | class HardwareDelay {
41 | public:
42 | HardwareDelay() {}
43 | void seconds(uint16_t seconds);
44 | void millis(uint16_t millis);
45 | void microseconds(uint32_t micros) { ::delayMicroseconds(micros); }
46 | };
47 |
48 | #endif
--------------------------------------------------------------------------------
/src/TiltTempSensor.cpp:
--------------------------------------------------------------------------------
1 | #ifdef HAS_BLUETOOTH
2 | #include "Brewpi.h"
3 | #include "TiltTempSensor.h"
4 | #include "PiLink.h" // For printBytes
5 | #include "TemperatureFormats.h"
6 |
7 | #include "wireless/BTScanner.h"
8 |
9 | TiltTempSensor::~TiltTempSensor(){
10 | // delete sensor;
11 | };
12 |
13 | /**
14 | * \brief Initializes the temperature sensor.
15 | *
16 | * This method is called when the sensor is first created and also any time the
17 | * sensor reports it's disconnected. If the result is TEMP_SENSOR_DISCONNECTED
18 | * then subsequent calls to read() will also return TEMP_SENSOR_DISCONNECTED.
19 | * Clients should attempt to re-initialize the sensor by calling init() again.
20 | */
21 | bool TiltTempSensor::init() {
22 | if (th==NULL) {
23 | th = bt_scanner.get_or_create_tilt(btAddress);
24 | if (th==NULL) {
25 | logErrorString(ERROR_SRAM_SENSOR, btAddress.toString().c_str());
26 | }
27 | }
28 | return isConnected();
29 | }
30 |
31 |
32 | /**
33 | * \brief Read the value of the sensor
34 | *
35 | * @return TEMP_SENSOR_DISCONNECTED if sensor is not connected, constrained temp otherwise.
36 | * @see readAndConstrainTemp()
37 | */
38 | temperature TiltTempSensor::read(){
39 | if (!isConnected())
40 | return TEMP_SENSOR_DISCONNECTED;
41 |
42 | return readAndConstrainTemp();
43 | }
44 |
45 |
46 | /**
47 | * \brief Reads the temperature.
48 | *
49 | * If successful, constrains the temp to the range of the temperature type
50 | * and updates lastRequestTime. On successful, leaves lastRequestTime alone
51 | * and returns TEMP_SENSOR_DISCONNECTED.
52 | */
53 | temperature TiltTempSensor::readAndConstrainTemp()
54 | {
55 | if(!isConnected()) {
56 | return TEMP_SENSOR_DISCONNECTED;
57 | }
58 |
59 | // double rawTemp = ib->getTemp() / 1000;
60 | // temperature temp = doubleToTemp(rawTemp);
61 |
62 | // const uint8_t shift = TEMP_FIXED_POINT_BITS - sensorPrecision; // difference in precision between DS18B20 format and temperature adt
63 | // temp = constrainTemp(temp+calibrationOffset+(C_OFFSET>>shift), ((int) MIN_TEMP)>>shift, ((int) MAX_TEMP)>>shift)<getTempFixedPoint() + (calibrationOffset<<(TEMP_FIXED_POINT_BITS - TEMP_CALIBRATION_OFFSET_PRECISION)), MIN_TEMP, MAX_TEMP);
66 | return temp;
67 | }
68 | #endif
69 |
--------------------------------------------------------------------------------
/src/TiltTempSensor.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #ifdef HAS_BLUETOOTH
3 | #include "Brewpi.h"
4 | #include "TempSensor.h"
5 | #include "FastDigitalPin.h"
6 | #include "Ticks.h"
7 | #include
8 |
9 | #include "wireless/Tilt.h"
10 |
11 |
12 | /**
13 | * \brief A Tilt bluetooth temperature sensor
14 | *
15 | * \ingroup hardware
16 | */
17 | class TiltTempSensor : public BasicTempSensor {
18 | public:
19 | /**
20 | * \brief Constructs a new Tilt temp sensor.
21 | *
22 | * /param address The MAC address for this sensor.
23 | * /param calibration A temperature value that is added to all readings. This can be used to calibrate the sensor.
24 | */
25 | TiltTempSensor(NimBLEAddress address, fixed4_4 calibrationOffset) {
26 | btAddress = address;
27 |
28 | this->calibrationOffset = calibrationOffset;
29 | th = nullptr;
30 | };
31 |
32 | ~TiltTempSensor();
33 |
34 | /**
35 | * \brief Check if sensor device is connected
36 | */
37 | bool isConnected(){
38 | if (th && th->isConnected())
39 | return true;
40 | return false;
41 | }
42 |
43 | bool init();
44 | temperature read();
45 |
46 | NimBLEAddress btAddress;
47 | tilt *th;
48 |
49 | private:
50 | /**
51 | * \brief The sensor precision, in bits.
52 | */
53 | // constexpr static uint8_t sensorPrecision = 4;
54 |
55 | temperature readAndConstrainTemp();
56 | // uint8_t sensorAddress[6];
57 |
58 | fixed4_4 calibrationOffset; //!< Temperature offset needed for calibration
59 |
60 | };
61 | #endif
--------------------------------------------------------------------------------
/src/http_server.h:
--------------------------------------------------------------------------------
1 | #ifndef BREWPI_HTTP_SERVER_H
2 | #define BREWPI_HTTP_SERVER_H
3 |
4 | #ifdef ENABLE_HTTP_INTERFACE
5 |
6 | #define WEB_SERVER_PORT 80
7 |
8 | #ifdef ESP8266
9 | #include
10 | #define WEBSERVER_IMPL ESP8266WebServer
11 | #elif defined(ESP32)
12 | #include
13 | #define WEBSERVER_IMPL WebServer
14 | #endif
15 |
16 |
17 | uint8_t processUpstreamConfigUpdateJson(const JsonDocument& json, bool triggerUpstreamUpdate = true);
18 |
19 |
20 | class httpServer {
21 | public:
22 | void init();
23 | //void handleClient();
24 | bool lcd_reinit_rqd = false;
25 | bool restart_requested = false;
26 | bool name_reset_requested = false;
27 | bool wifi_reset_requested = false;
28 | bool config_reset_requested = false;
29 | bool ota_update_requested = false;
30 | WEBSERVER_IMPL *web_server;
31 |
32 |
33 | private:
34 | void uptime();
35 | void heap();
36 | void genericServeJson(void(*jsonFunc)(DynamicJsonDocument&));
37 | void processJsonRequest(const char* uri, uint8_t (*handler)(const DynamicJsonDocument& json, bool triggerUpstreamUpdate));
38 | void serveExtendedSettings();
39 | void serveUpstreamSettings();
40 | void serveMinTimes();
41 | void reset_reason();
42 |
43 | void setStaticPages();
44 | void setJsonPages();
45 | void setJsonHandlers();
46 |
47 | String getContentType(String filename);
48 | // bool exists(String path);
49 | bool handleFileRead(String path);
50 | void redirect(const String& url);
51 |
52 | };
53 |
54 | extern httpServer http_server;
55 |
56 | #endif //ENABLE_HTTP_INTERFACE
57 |
58 | #endif //TRONBRIDGE_HTTP_SERVER_H
59 |
--------------------------------------------------------------------------------
/src/http_server_generic.cpp:
--------------------------------------------------------------------------------
1 | #ifdef ENABLE_HTTP_INTERFACE
2 |
3 | #include
4 | #include
5 | #include "ESPEepromAccess.h"
6 |
7 | #include "http_server.h"
8 |
9 |
10 |
11 | // Functions needed to serve static files
12 | String httpServer::getContentType(String filename) {
13 | if (web_server->hasArg("download")) {
14 | return "application/octet-stream";
15 | } else if (filename.endsWith(".htm")) {
16 | return "text/html";
17 | } else if (filename.endsWith(".html")) {
18 | return "text/html";
19 | } else if (filename.endsWith(".css")) {
20 | return "text/css";
21 | } else if (filename.endsWith(".js")) {
22 | return "application/javascript";
23 | } else if (filename.endsWith(".png")) {
24 | return "image/png";
25 | } else if (filename.endsWith(".gif")) {
26 | return "image/gif";
27 | } else if (filename.endsWith(".jpg")) {
28 | return "image/jpeg";
29 | } else if (filename.endsWith(".ico")) {
30 | return "image/x-icon";
31 | } else if (filename.endsWith(".xml")) {
32 | return "text/xml";
33 | } else if (filename.endsWith(".pdf")) {
34 | return "application/x-pdf";
35 | } else if (filename.endsWith(".zip")) {
36 | return "application/x-zip";
37 | } else if (filename.endsWith(".gz")) {
38 | return "application/x-gzip";
39 | } else if (filename.endsWith(".svg")) {
40 | return "image/svg+xml";
41 | }
42 | return "text/plain";
43 | }
44 |
45 | // bool httpServer::exists(String path){
46 | // bool yes = false;
47 | // File file = FILESYSTEM.open(path, "r");
48 | // if(!file.isDirectory()){
49 | // yes = true;
50 | // }
51 | // file.close();
52 | // return yes;
53 | // }
54 |
55 | bool httpServer::handleFileRead(String path) {
56 | // Serial.println("handleFileRead: " + path);
57 | if (path.endsWith("/")) {
58 | path += "index.htm";
59 | }
60 | String contentType = getContentType(path);
61 | String pathWithGz = path + ".gz";
62 | if (FILESYSTEM.exists(pathWithGz) || FILESYSTEM.exists(path)) {
63 | if (FILESYSTEM.exists(pathWithGz)) {
64 | path += ".gz";
65 | }
66 | File file = FILESYSTEM.open(path, "r");
67 | web_server->streamFile(file, contentType);
68 | file.close();
69 | return true;
70 | }
71 | return false;
72 | }
73 |
74 | void httpServer::redirect(const String& url){
75 | web_server->sendHeader("Location", url);
76 | web_server->sendHeader("Cache-Control", "no-cache");
77 | web_server->send(302);
78 | return;
79 | }
80 |
81 | #endif // ENABLE_HTTP_INTERFACE
82 |
--------------------------------------------------------------------------------
/src/resetreasons.h:
--------------------------------------------------------------------------------
1 | #ifndef _RESETREASONS_H
2 | #define _RESETREASONS_H
3 |
4 | #if defined ESP8266
5 | const char *resetReason[7] = {
6 | "REASON_DEFAULT_RST", // = 0, /* normal startup by power on */
7 | "REASON_WDT_RST", // = 1, /* hardware watch dog reset */
8 | "REASON_EXCEPTION_RST", // = 2, /* exception reset, GPIO status won’t change */
9 | "REASON_SOFT_WDT_RST", // = 3, /* software watch dog reset, GPIO status won’t change */
10 | "REASON_SOFT_RESTART", // = 4, /* software restart ,system_restart , GPIO status won’t change */
11 | "REASON_DEEP_SLEEP_AWAKE", // = 5, /* wake up from deep-sleep */
12 | "REASON_EXT_SYS_RST" // = 6 /* external system reset */
13 | };
14 |
15 | const char *resetDescription[7] = {
16 | "Normal startup by power on",
17 | "Hardware watch dog reset",
18 | "Exception reset, GPIO status won’t change",
19 | "Software watch dog reset, GPIO status won’t change",
20 | "Software restart, system_restart, GPIO status won’t change",
21 | "Wake up from deep-sleep",
22 | "External system reset"};
23 |
24 | #elif ESP32
25 |
26 | const char *resetReason[11] = {
27 | "ESP_RST_UNKNOWN", //!< Reset reason can not be determined
28 | "ESP_RST_POWERON", //!< Reset due to power-on event
29 | "ESP_RST_EXT", //!< Reset by external pin (not applicable for ESP32)
30 | "ESP_RST_SW", //!< Software reset via esp_restart
31 | "ESP_RST_PANIC", //!< Software reset due to exception/panic
32 | "ESP_RST_INT_WDT", //!< Reset (software or hardware) due to interrupt watchdog
33 | "ESP_RST_TASK_WDT", //!< Reset due to task watchdog
34 | "ESP_RST_WDT", //!< Reset due to other watchdogs
35 | "ESP_RST_DEEPSLEEP", //!< Reset after exiting deep sleep mode
36 | "ESP_RST_BROWNOUT", //!< Brownout reset (software or hardware)
37 | "ESP_RST_SDIO" //!< Reset over SDIO
38 | };
39 |
40 | const char *resetDescription[11] = {
41 | "Reset reason can not be determined",
42 | "Reset due to power-on event",
43 | "Reset by external pin (not applicable for ESP32)",
44 | "Software reset via esp_restart",
45 | "Software reset due to exception/panic",
46 | "Reset (software or hardware) due to interrupt watchdog",
47 | "Reset due to task watchdog",
48 | "Reset due to other watchdogs",
49 | "Reset after exiting deep sleep mode",
50 | "Brownout reset (software or hardware)",
51 | "Reset over SDIO"
52 | };
53 |
54 | #endif
55 |
56 | #endif // _RESETREASONS_H
57 |
--------------------------------------------------------------------------------
/src/tplink/TPLinkConnector.h:
--------------------------------------------------------------------------------
1 | #ifndef TPLINK_KASA_TPLINKCONNECTOR_H
2 | #define TPLINK_KASA_TPLINKCONNECTOR_H
3 |
4 | #include
5 | #include
6 |
7 | #define TP_LINK_INITIALIZATION_VECTOR 171
8 |
9 | class TPLinkConnector {
10 |
11 | public:
12 | // TPLinkConnector();
13 | // ~TPLinkConnector();
14 |
15 | void discover();
16 |
17 | void init_udp();
18 |
19 | void send_payload(const IPAddress host, const std::string payload, bool include_size);
20 | void broadcast_payload(std::string payload, bool include_size);
21 | std::string receive_udp();
22 | std::string receive_udp(IPAddress *udp_ip);
23 |
24 | // private:
25 | static std::string encrypt(std::string unencr, bool include_size);
26 | static std::string decrypt(std::string encr);
27 |
28 | private:
29 | //The udp library class
30 | WiFiUDP udp;
31 |
32 | };
33 |
34 |
35 | #endif //TPLINK_KASA_TPLINKCONNECTOR_H
36 |
--------------------------------------------------------------------------------
/src/tplink/TPLinkDevice.cpp:
--------------------------------------------------------------------------------
1 | #include "TPLinkDevice.h"
2 |
3 | void TPLinkDevice::send_payload(const std::string payload, bool include_size) {
4 | // This is a thin wrapper around tp_link_connector's send_payload that just adds the IP address to the send request
5 | tp_link_connector->send_payload(ip_addr, payload, include_size);
6 | }
--------------------------------------------------------------------------------
/src/tplink/TPLinkDevice.h:
--------------------------------------------------------------------------------
1 | #ifndef TPLINK_KASA_TPLINKDEVICE_H
2 | #define TPLINK_KASA_TPLINKDEVICE_H
3 |
4 | #include
5 | #include "TPLinkConnector.h"
6 | #include
7 |
8 | enum TPLinkDeviceType {
9 | TPLINK_KASA_SMARTPLUGSWITCH = 0 // e.g. HS103, KP400
10 | };
11 |
12 |
13 | class TPLinkDevice {
14 | public:
15 | IPAddress ip_addr;
16 | TPLinkDeviceType type;
17 |
18 | char device_mac[18];
19 | char device_alias[32];
20 | char device_id[41];
21 |
22 | protected:
23 | TPLinkConnector* tp_link_connector;
24 | void send_payload(const std::string payload, bool include_size);
25 | };
26 |
27 |
28 | #endif //TPLINK_KASA_TPLINKDEVICE_H
29 |
--------------------------------------------------------------------------------
/src/tplink/TPLinkPlug.h:
--------------------------------------------------------------------------------
1 | #ifndef TPLINK_KASA_TPLINKPLUG_H
2 | #define TPLINK_KASA_TPLINKPLUG_H
3 |
4 | #include
5 | #include "TPLinkDevice.h"
6 |
7 |
8 | class TPLinkPlug : public TPLinkDevice {
9 |
10 | public:
11 | TPLinkPlug(IPAddress ip, const char * deviceMAC, const char * deviceID, const char * childID, TPLinkConnector* tplink_conn);
12 | TPLinkPlug(IPAddress ip, const char * deviceMAC, const char * deviceID, const char * childID, const char * devAlias, TPLinkConnector* tplink_conn);
13 |
14 | bool last_read_on;
15 |
16 | bool set_on();
17 | bool set_off();
18 |
19 | void get_countdown();
20 | void set_countdown(uint8_t act, uint16_t secs);
21 | void set_countdown_to_off(uint16_t secs);
22 | void set_countdown_to_on(uint16_t secs);
23 | void clear_countdown();
24 |
25 | char child_id[3];
26 |
27 | };
28 |
29 |
30 | #endif //TPLINK_KASA_TPLINKPLUG_H
31 |
--------------------------------------------------------------------------------
/src/tplink/TPLinkScanner.h:
--------------------------------------------------------------------------------
1 | #ifndef TPLINK_KASA_TPLINKSCANNER_H
2 | #define TPLINK_KASA_TPLINKSCANNER_H
3 |
4 | #include
5 | #include
6 | #include "TPLinkPlug.h"
7 | #include "TPLinkConnector.h"
8 |
9 |
10 | #define TPLINK_DISCOVER_EVERY 30 // How frequently to send discovery packets (in seconds)
11 | #define TPLINK_SAFETY_TIMEOUT_REFRESH 20 // How frequently to refresh the "safety" off countdown (in seconds)
12 | #define TPLINK_SAFETY_TIMEOUT (TPLINK_SAFETY_TIMEOUT_REFRESH * 3 + 5) // How long to set the "safety" off countdown to turn the device off after
13 |
14 | class TPLinkScanner {
15 |
16 | public:
17 | TPLinkConnector tplink_connector;
18 |
19 | // Device Lists
20 | std::list lTPLinkPlugs;
21 |
22 | TPLinkPlug* get_tplink_plug(const char *deviceMAC, const char *childID);
23 | TPLinkPlug* get_or_create_tplink_plug(IPAddress ip_addr, const char *deviceMAC, const char *deviceID, const char *childID, const char *alias);
24 |
25 | void init();
26 | void process_udp_incoming();
27 | void send_discover();
28 | void send_refresh();
29 |
30 | void scan_and_refresh();
31 |
32 | uint64_t last_discover_at=0;
33 | uint64_t last_refresh_at=0;
34 | };
35 |
36 | extern TPLinkScanner tp_link_scanner;
37 |
38 | #endif //TPLINK_KASA_TPLINKSCANNER_H
39 |
--------------------------------------------------------------------------------
/src/uptime.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Lee Bussy on 12/31/20
3 | //
4 |
5 | #include "uptime.h"
6 |
7 | static int refresh = UPTIME_REFRESH * 1000;
8 | static unsigned long uptimeNow;
9 | static int days;
10 | static int hours;
11 | static int minutes;
12 | static int seconds;
13 | static int mills;
14 |
15 | void getNow()
16 | {
17 | // Set the uptime values if refresh time is expired
18 | if ((int)(millis() - uptimeNow) > refresh)
19 | {
20 | setValues();
21 | }
22 | // Reset timer for another period to avoid a really unlikely situation
23 | // where the timer expires in between grabbing two parts
24 | uptimeNow = millis();
25 | }
26 |
27 | void setValues()
28 | {
29 | // Call this only by getNow()
30 | // Using refr = true forces recalculation
31 | uptimeNow = millis();
32 | days = uptimeDays(true);
33 | hours = uptimeHours(true);
34 | minutes = uptimeMinutes(true);
35 | seconds = uptimeSeconds(true);
36 | mills = uptimeMillis(true);
37 | }
38 |
39 | const int uptimeDays(bool refr)
40 | {
41 | getNow(); // Make sure we are current
42 | if (refr)
43 | {
44 | // Calculate full days from uptime
45 | days = (int)floor(uptimeNow / DAY_MILLIS);
46 | }
47 | return days;
48 | }
49 |
50 | const int uptimeHours(bool refr)
51 | {
52 | getNow(); // Make sure we are current
53 | if (refr)
54 | {
55 | // Refresh values:
56 | // Subtract millis value for any full days via modulo
57 | // Calculate full hours from remainder
58 | hours = (int)floor((uptimeNow % DAY_MILLIS) / HOUR_MILLIS);
59 | }
60 | return hours;
61 | }
62 |
63 | const int uptimeMinutes(bool refr)
64 | {
65 | getNow(); // Make sure we are current
66 | if (refr)
67 | {
68 | // Refresh values:
69 | // Subtract millis value for any full hours via modulo
70 | // Calculate full minutes from remainder
71 | minutes = (int)floor((uptimeNow % HOUR_MILLIS) / MIN_MILLIS);
72 | }
73 | return minutes;
74 | }
75 |
76 | const int uptimeSeconds(bool refr)
77 | {
78 | getNow(); // Make sure we are current
79 | if (refr)
80 | {
81 | // Refresh values:
82 | // Subtract millis value for any full minutes via modulo
83 | // Calculate full seconds from remainder
84 | seconds = (int)floor((uptimeNow % MIN_MILLIS) / SEC_MILLIS);
85 | }
86 | return seconds;
87 | }
88 |
89 | const int uptimeMillis(bool refr)
90 | {
91 | getNow(); // Make sure we are current
92 | if (refr)
93 | {
94 | // Refresh values:
95 | // Subtract millis value for any full seconds via modulo
96 | // Return remainder millis
97 | mills = (int)floor((uptimeNow % SEC_MILLIS));
98 | }
99 | return mills;
100 | }
101 |
--------------------------------------------------------------------------------
/src/uptime.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Lee Bussy on 12/31/20
3 | //
4 |
5 | #ifndef _UPTIME_H
6 | #define _UPTIME_H
7 |
8 | #include
9 |
10 | #define UPTIME_REFRESH 1
11 |
12 | #define DAY_MILLIS 86400000
13 | #define HOUR_MILLIS 3600000
14 | #define MIN_MILLIS 60000
15 | #define SEC_MILLIS 1000
16 |
17 | void getNow();
18 | void setValues();
19 | const int uptimeDays(bool refr = false);
20 | const int uptimeHours(bool refr = false);
21 | const int uptimeMinutes(bool refr = false);
22 | const int uptimeSeconds(bool refr = false);
23 | const int uptimeMillis(bool refr = false);
24 |
25 | #endif // _UPTIME_H
26 |
--------------------------------------------------------------------------------
/src/wireless/BTScanner.h:
--------------------------------------------------------------------------------
1 | #ifndef BREWPI_BTSCANNER_H
2 | #define BREWPI_BTSCANNER_H
3 |
4 | #ifdef HAS_BLUETOOTH
5 |
6 | #include "Inkbird.h"
7 | #include "Tilt.h"
8 |
9 | #define BLE_SCAN_TIME 60 // Seconds to scan (0=continuous scanning)
10 | #define SCAN_FAIL_THRESHHOLD (5*60*1000*1000) // If we don't detect anything in 5 minutes, then the scanner failed.
11 |
12 | class btScanner
13 | {
14 | public:
15 | btScanner();
16 | void init();
17 | bool scan();
18 | void stop_scan();
19 |
20 | inkbird* get_or_create_inkbird(const NimBLEAddress devAddress);
21 | inkbird* get_inkbird(const NimBLEAddress devAddress);
22 |
23 | tilt* get_or_create_tilt(const NimBLEAddress devAddress);
24 | tilt* get_tilt(const NimBLEAddress devAddress);
25 |
26 | void purge_stale_inkbirds();
27 | void purge_stale_tilts();
28 |
29 | bool scanning_failed();
30 |
31 | bool shouldRun;
32 |
33 | uint64_t last_detected_device_at;
34 |
35 |
36 | private:
37 | uint64_t m_last_inkbird_purge_at;
38 | uint64_t m_last_tilt_purge_at;
39 |
40 | };
41 |
42 |
43 | extern btScanner bt_scanner;
44 | extern std::list lInkbirds;
45 | extern std::list lTilts;
46 |
47 |
48 | #endif // HAS_BLUETOOTH
49 |
50 | #endif //BREWPI_BTSCANNER_H
51 |
--------------------------------------------------------------------------------
/src/wireless/Inkbird.cpp:
--------------------------------------------------------------------------------
1 | #ifdef HAS_BLUETOOTH
2 | #include
3 | #include "Inkbird.h"
4 | #include "TemperatureFormats.h"
5 |
6 |
7 | void inkbird::update(int16_t temp, uint16_t hum, uint8_t bat, int16_t rssi)
8 | {
9 | rawTemp=temp;
10 | rawHumidity=hum;
11 | battery=bat;
12 | m_lastUpdate = esp_timer_get_time();
13 | hasData = true;
14 | return;
15 | }
16 |
17 | int16_t inkbird::getTemp()
18 | {
19 | return rawTemp;
20 | }
21 |
22 | uint16_t inkbird::getHumidity()
23 | {
24 | return rawHumidity;
25 | }
26 |
27 | uint8_t inkbird::getBattery()
28 | {
29 | return battery;
30 | }
31 |
32 | bool inkbird::isConnected()
33 | {
34 | return esp_timer_get_time() <= (m_lastUpdate + INKBIRD_CONNECTED_TIMEOUT) && hasData;
35 | }
36 |
37 | long_temperature inkbird::getTempFixedPoint() {
38 | long_temperature intPart = 0;
39 | long_temperature fracPart = 0;
40 |
41 | intPart = (int) rawTemp/100*TEMP_FIXED_POINT_SCALE;
42 |
43 | fracPart = rawTemp % 100;
44 | fracPart = fracPart << TEMP_FIXED_POINT_BITS; // bits for fraction part
45 |
46 | // Since we have two decimals
47 | fracPart = (fracPart + 5) / 10;
48 | fracPart = (fracPart + 5) / 10;
49 |
50 | long_temperature combinedTemp = (intPart) + fracPart + C_OFFSET;
51 | return combinedTemp;
52 | }
53 |
54 | #endif
55 |
--------------------------------------------------------------------------------
/src/wireless/Inkbird.h:
--------------------------------------------------------------------------------
1 | #ifndef BREWPI_INKBIRD_H
2 | #define BREWPI_INKBIRD_H
3 |
4 | #ifdef HAS_BLUETOOTH
5 |
6 |
7 | #include "Brewpi.h"
8 | #include "TempSensor.h"
9 | #include "FastDigitalPin.h"
10 | // #include "Ticks.h"
11 | #include
12 | #include "TemperatureFormats.h"
13 |
14 |
15 | #define INKBIRD_CONNECTED_TIMEOUT (30 * 1000 * 1000) // Time before the sensor is considered "disconnected" (in microseconds)
16 |
17 | class inkbird
18 | {
19 | public:
20 | inkbird(const NimBLEAddress devAddress, int16_t temp, uint16_t hum, uint8_t bat, int16_t rssi)
21 | :deviceAddress(devAddress), m_lastUpdate(esp_timer_get_time()), rawTemp(temp), rawHumidity(hum), battery(bat), hasData(true) {};
22 |
23 | inkbird(const NimBLEAddress devAddress)
24 | :deviceAddress(devAddress), m_lastUpdate(0), rawTemp(0), rawHumidity(0), battery(0), hasData(false) {};
25 |
26 | void update(int16_t temp, uint16_t hum, uint8_t bat, int16_t rssi);
27 | int16_t getTemp();
28 | uint16_t getHumidity();
29 | uint8_t getBattery();
30 | long_temperature getTempFixedPoint();
31 |
32 | bool isConnected();
33 |
34 | NimBLEAddress deviceAddress;
35 |
36 | uint64_t m_lastUpdate; // Keep track of when we last updated to detect disconnection
37 |
38 | bool operator == (const inkbird& dev) const { return deviceAddress == dev.deviceAddress; }
39 | bool operator != (const inkbird& dev) const { return !operator==(dev); }
40 |
41 | private:
42 | int16_t rawTemp;
43 | uint16_t rawHumidity;
44 | uint8_t battery;
45 | bool hasData;
46 |
47 | };
48 |
49 | #endif
50 | #endif //BREWPI_INKBIRD_H
51 |
--------------------------------------------------------------------------------
/src/wireless/Tilt.cpp:
--------------------------------------------------------------------------------
1 | #ifdef HAS_BLUETOOTH
2 | #include
3 | #include "Tilt.h"
4 | #include "TemperatureFormats.h"
5 |
6 |
7 | void tilt::update(TiltColor color_index, uint16_t temp, uint16_t grav, uint8_t i_tx_pwr, int16_t rssi)
8 | {
9 | if (temp == 999) { // If the temp is 999, the SG actually represents the firmware version of the Tilt.
10 | // version_code = grav;
11 | return; // This also has the (desired) side effect of not logging the 999 "temperature" and 1.00x "gravity"
12 | } else if (grav >= 5000) { // If we received a gravity over 5000 then this Tilt is high resolution (Tilt Pro)
13 | tilt_pro = true;
14 | } else if (grav < 5000) {
15 | tilt_pro = false;
16 | }
17 |
18 | if (i_tx_pwr==197)
19 | m_has_sent_197 = true;
20 | else {
21 | if (m_has_sent_197)
22 | receives_battery = true;
23 | if (receives_battery)
24 | battery_weeks = i_tx_pwr;
25 | }
26 |
27 | rawTemp=temp;
28 | rawGravity=grav;
29 | m_lastUpdate = esp_timer_get_time();
30 | hasData = true;
31 | color = color_index;
32 | return;
33 | }
34 |
35 | uint16_t tilt::getTemp()
36 | {
37 | return rawTemp;
38 | }
39 |
40 | uint16_t tilt::getGravity()
41 | {
42 | return rawGravity;
43 | }
44 |
45 | bool tilt::isConnected()
46 | {
47 | return esp_timer_get_time() <= (m_lastUpdate + TILT_CONNECTED_TIMEOUT) && hasData;
48 | }
49 |
50 | TiltColor tilt::uuid_to_color_no(std::string uuid)
51 | {
52 |
53 | if (uuid == TILT_COLOR_RED_UUID)
54 | return TiltColor::TILT_COLOR_RED;
55 | else if (uuid == TILT_COLOR_GREEN_UUID)
56 | return TiltColor::TILT_COLOR_GREEN;
57 | else if (uuid == TILT_COLOR_BLACK_UUID)
58 | return TiltColor::TILT_COLOR_BLACK;
59 | else if (uuid == TILT_COLOR_PURPLE_UUID)
60 | return TiltColor::TILT_COLOR_PURPLE;
61 | else if (uuid == TILT_COLOR_ORANGE_UUID)
62 | return TiltColor::TILT_COLOR_ORANGE;
63 | else if (uuid == TILT_COLOR_BLUE_UUID)
64 | return TiltColor::TILT_COLOR_BLUE;
65 | else if (uuid == TILT_COLOR_YELLOW_UUID)
66 | return TiltColor::TILT_COLOR_YELLOW;
67 | else if (uuid == TILT_COLOR_PINK_UUID)
68 | return TiltColor::TILT_COLOR_PINK;
69 | return TiltColor::TILT_COLOR_NONE; // Should never get here
70 | }
71 |
72 | std:: string tilt::get_color_string() {
73 |
74 | switch(color) {
75 | case TiltColor::TILT_COLOR_RED:
76 | return TiltColorNames::red;
77 | case TiltColor::TILT_COLOR_GREEN:
78 | return TiltColorNames::green;
79 | case TiltColor::TILT_COLOR_BLACK:
80 | return TiltColorNames::black;
81 | case TiltColor::TILT_COLOR_PURPLE:
82 | return TiltColorNames::purple;
83 | case TiltColor::TILT_COLOR_ORANGE:
84 | return TiltColorNames::orange;
85 | case TiltColor::TILT_COLOR_BLUE:
86 | return TiltColorNames::red;
87 | case TiltColor::TILT_COLOR_YELLOW:
88 | return TiltColorNames::yellow;
89 | case TiltColor::TILT_COLOR_PINK:
90 | return TiltColorNames::pink;
91 | default:
92 | return TiltColorNames::none;
93 | }
94 | }
95 |
96 |
97 | long_temperature tilt::getTempFixedPoint() {
98 | long_temperature fracPart = 0;
99 |
100 | // Tilts always report in Fahrenheit - convert to celsius and then split
101 | double conv_temp = ((double) rawTemp / (tilt_pro ? 10 : 1) - 32) * 5 / 9;
102 |
103 | // Split into an integer and a fractional part
104 | double intPartRaw;
105 | double fracPartRaw = modf(conv_temp, &intPartRaw);
106 |
107 | // Int part is good to go - just recast it and scale it up
108 | long_temperature intPart = static_cast(intPartRaw) * TEMP_FIXED_POINT_SCALE;
109 |
110 | // Fractional part needs to be scaled up to max precision (0.1deg F, using 0.01deg C instead)
111 | fracPart = static_cast(trunc(fracPartRaw * 100));
112 | fracPart = fracPart << TEMP_FIXED_POINT_BITS; // bits for fraction part
113 |
114 | // Since we have two decimals
115 | fracPart = (fracPart + 5) / 10;
116 | fracPart = (fracPart + 5) / 10;
117 |
118 | long_temperature combinedTemp = (intPart) + fracPart + C_OFFSET;
119 | return combinedTemp;
120 | }
121 |
122 | #endif
123 |
--------------------------------------------------------------------------------
/src/wireless/Tilt.h:
--------------------------------------------------------------------------------
1 | #ifndef BREWPI_TILT_H
2 | #define BREWPI_TILT_H
3 |
4 | #ifdef HAS_BLUETOOTH
5 |
6 |
7 | #include "Brewpi.h"
8 | #include "TempSensor.h"
9 | #include "FastDigitalPin.h"
10 | // #include "Ticks.h"
11 | #include
12 | #include "TemperatureFormats.h"
13 |
14 |
15 | #define TILT_COLOR_RED_UUID "a495bb10c5b14b44b5121370f02d74de"
16 | #define TILT_COLOR_GREEN_UUID "a495bb20c5b14b44b5121370f02d74de"
17 | #define TILT_COLOR_BLACK_UUID "a495bb30c5b14b44b5121370f02d74de"
18 | #define TILT_COLOR_PURPLE_UUID "a495bb40c5b14b44b5121370f02d74de"
19 | #define TILT_COLOR_ORANGE_UUID "a495bb50c5b14b44b5121370f02d74de"
20 | #define TILT_COLOR_BLUE_UUID "a495bb60c5b14b44b5121370f02d74de"
21 | #define TILT_COLOR_YELLOW_UUID "a495bb70c5b14b44b5121370f02d74de"
22 | #define TILT_COLOR_PINK_UUID "a495bb80c5b14b44b5121370f02d74de"
23 |
24 |
25 | /**
26 | * \brief Tilt Hydrometer color index
27 | */
28 | enum TiltColor {
29 | TILT_COLOR_NONE,
30 | TILT_COLOR_RED,
31 | TILT_COLOR_GREEN,
32 | TILT_COLOR_BLACK,
33 | TILT_COLOR_PURPLE,
34 | TILT_COLOR_ORANGE,
35 | TILT_COLOR_BLUE,
36 | TILT_COLOR_YELLOW,
37 | TILT_COLOR_PINK
38 | };
39 |
40 |
41 | /**
42 | * \brief Tilt Color Names
43 | * \see TiltColor
44 | */
45 | namespace TiltColorNames {
46 | constexpr auto none = "None";
47 | constexpr auto red = "Red";
48 | constexpr auto green = "Green";
49 | constexpr auto black = "Black";
50 | constexpr auto purple = "Purple";
51 | constexpr auto orange = "Orange";
52 | constexpr auto blue = "Blue";
53 | constexpr auto yellow = "Yellow";
54 | constexpr auto pink = "Pink";
55 | };
56 |
57 |
58 | #define TILT_CONNECTED_TIMEOUT (90 * 1000 * 1000) // Time before the sensor is considered "disconnected" (in microseconds)
59 |
60 | class tilt
61 | {
62 | public:
63 | // tilt(const NimBLEAddress devAddress, TiltColor color_index, uint16_t temp, uint16_t grav, int16_t rssi)
64 | // :deviceAddress(devAddress), color(color_index), m_lastUpdate(millis()), battery_weeks(0),
65 | // receives_battery(false), tilt_pro(false), rawTemp(temp), rawGravity(grav), hasData(true) {};
66 |
67 | // tilt(const NimBLEAddress devAddress, TiltColor color_index)
68 | // :deviceAddress(devAddress), color(color_index), m_lastUpdate(0), battery_weeks(0),
69 | // receives_battery(false), tilt_pro(false), rawTemp(0), rawGravity(0), hasData(false) {};
70 |
71 | tilt(const NimBLEAddress devAddress)
72 | :deviceAddress(devAddress), color(TiltColor::TILT_COLOR_NONE), m_lastUpdate(0), battery_weeks(0),
73 | receives_battery(false), tilt_pro(false), rawTemp(0), rawGravity(0), hasData(false) {};
74 |
75 |
76 | void update(TiltColor color_index, uint16_t temp, uint16_t grav, uint8_t i_tx_pwr, int16_t rssi);
77 |
78 | std::string get_color_string();
79 |
80 |
81 | uint16_t getTemp();
82 | uint16_t getGravity();
83 | long_temperature getTempFixedPoint();
84 | bool isConnected();
85 | static TiltColor uuid_to_color_no(std::string uuid);
86 |
87 | NimBLEAddress deviceAddress;
88 | TiltColor color;
89 | uint64_t m_lastUpdate; // Keep track of when we last updated to detect disconnection
90 | uint8_t battery_weeks; // Weeks since the last battery change (if receives_battery is true)
91 | bool receives_battery; // Tracks if this tilt sends battery life
92 | bool tilt_pro; // Tracks if this tilt is "high resolution" or not (ie. is a Tilt Pro)
93 |
94 | bool operator == (const tilt& dev) const { return (deviceAddress == dev.deviceAddress && color == dev.color); }
95 | bool operator != (const tilt& dev) const { return !operator==(dev); }
96 |
97 | private:
98 | uint16_t rawTemp;
99 | uint16_t rawGravity;
100 | bool hasData;
101 | bool m_has_sent_197; // Used to determine if the tilt sends battery life (a 197 tx_pwr followed by a non-197 tx_pwr)
102 |
103 | };
104 |
105 | #endif
106 | #endif //BREWPI_TILT_H
107 |
--------------------------------------------------------------------------------