124 Commits

Author SHA1 Message Date
a5f7f0f8a4 Updated release notes for beta 2 2022-07-29 08:37:34 +02:00
7826e56d8a GitHub Action Build 2022-07-27 22:03:51 +00:00
353d6d77e1 Minor fixes for new features 2022-07-27 23:58:25 +02:00
437873489e Added ver and build into templating 2022-07-27 13:11:17 +02:00
e34e73fae2 GitHub Action Build 2022-07-27 06:49:27 +00:00
69a4c5607c Merge branch 'dev' of https://github.com/mp-se/gravitymon into dev 2022-07-27 08:44:48 +02:00
d980fdae1a Adding sw ver to template engine 2022-07-27 08:44:32 +02:00
272e349375 GitHub Action Build 2022-07-27 06:18:09 +00:00
34d46ef768 Updated error message 2022-07-27 08:12:44 +02:00
588ff2d1e0 GitHub Action Build 2022-07-27 06:07:51 +00:00
5d1811d240 Updated config view 2022-07-27 08:02:19 +02:00
85e602d29b GitHub Action Build 2022-07-27 05:56:41 +00:00
8ee882c522 Adjusted error handling and formula deviation 2022-07-27 07:52:03 +02:00
51e7ee6867 GitHub Action Build 2022-07-27 05:48:54 +00:00
70858ef841 Updated error msg 2022-07-27 07:45:02 +02:00
83bd80ba28 GitHub Action Build 2022-07-27 05:43:50 +00:00
d33576b2df Increase size of buffer 2022-07-27 07:39:31 +02:00
5c9525c0c5 GitHub Action Build 2022-07-26 19:28:17 +00:00
ad8704fc20 Changed error message in formula validation 2022-07-26 21:23:50 +02:00
f1c1958f88 Merge branch 'dev' of https://github.com/mp-se/gravitymon into dev 2022-07-26 21:11:24 +02:00
e5394113e4 Updated HA integration 2022-07-26 21:11:16 +02:00
6d4e713da8 GitHub Action Build 2022-07-23 07:08:20 +00:00
36a858af2d Merge branch 'dev' of https://github.com/mp-se/gravitymon into dev 2022-07-23 09:00:46 +02:00
77d2c15e39 Updated docs for v1.1 beta 2 2022-07-23 08:58:48 +02:00
9df072cc78 GitHub Action Build 2022-07-07 10:25:06 +00:00
bedbda4662 Made cal temp adjustable in UI 2022-07-07 11:11:45 +02:00
76702dfc95 Fix #90 2022-07-07 10:13:17 +02:00
789eb32aa8 Merge branch 'dev' of https://github.com/mp-se/gravitymon into dev 2022-07-06 09:44:11 +02:00
c0db4dd8da Precommit format 2022-07-06 09:43:48 +02:00
cb677e10ae GitHub Action Build 2022-07-06 07:14:25 +00:00
b4c7566a08 Bump docs version 2022-07-06 09:10:23 +02:00
70f391fa1a Moved code for storage mode to apply in loop 2022-07-06 09:10:10 +02:00
542beffe4c Added brewblox format template 2022-07-06 09:09:18 +02:00
1a42bd332f Merge branch 'dev' of https://github.com/mp-se/gravitymon into dev 2022-07-05 18:11:22 +02:00
c16108352c GitHub Action Build 2022-07-05 16:07:32 +00:00
4b5df951de Precommit fix 2022-07-05 18:02:47 +02:00
6bbb904427 Fixed header case 2022-07-05 18:00:45 +02:00
66c6c44a38 precommit fixes 2022-07-05 17:58:14 +02:00
e2fee1fb35 Updated esp32 fwk 2022-07-05 17:55:05 +02:00
ae595ff50c Updated one wire 2022-07-05 17:50:51 +02:00
50257e2805 Updated mpu libraries 2022-07-05 17:50:33 +02:00
c503ad88a9 Removed serial debug 2022-07-05 17:43:59 +02:00
5b7290c991 Remove warning 2022-07-04 09:51:49 +02:00
f7c43dad55 Checked in wifi libs to remove unwanted deps. 2022-07-04 09:47:49 +02:00
95654bac66 Updated docs 2022-07-04 09:46:31 +02:00
ffa7ac294d Set limits on voltage config 2022-07-04 09:14:10 +02:00
79a3274286 Made config voltage configurable 2022-07-03 23:46:44 +02:00
0c936cfb88 merge master 2022-07-03 19:50:22 +02:00
f366b78cb3 merge master 2022-07-03 19:49:28 +02:00
702eba515d Updated history 2022-07-03 19:44:56 +02:00
a992e90bc3 Fix #84 2022-07-03 13:20:24 +02:00
8b4b89ba20 Fixed storage deep sleep for esp32 2022-07-02 10:45:10 +02:00
361d287a22 Updated brewblox integration 2022-07-02 09:52:14 +02:00
8e36453b13 Merge branch 'dev' of https://github.com/mp-se/gravitymon into dev 2022-07-01 21:11:42 +02:00
ded06d15a1 Added storage mode 2022-07-01 21:11:10 +02:00
67f60b817e Attempting to fix broken docs build 2022-07-01 09:42:25 +02:00
6373923506 Doc build pip upgrade 2022-07-01 09:30:16 +02:00
bf3a3de207 Added brewblox 2022-07-01 09:22:16 +02:00
e6fd027d51 GitHub Action Build 2022-06-11 14:03:00 +00:00
0cba58a0dd Bump library versions 2022-06-11 15:56:38 +02:00
fd71a2d428 Create stale.yaml 2022-06-04 14:40:20 +02:00
907e33ce2d Updated ubidots docs 2022-05-26 08:55:25 +02:00
18ba0b225f Merge branch 'dev' of https://github.com/mp-se/gravitymon into dev 2022-05-26 08:38:37 +02:00
2a9472b453 GitHub Action Build 2022-05-25 20:42:49 +00:00
0b23a0f69e Updated rel notes 2022-05-25 22:39:46 +02:00
9cba1db4e5 Merge branch 'dev' of https://github.com/mp-se/gravitymon into dev 2022-05-25 22:38:23 +02:00
9d5d6a5a58 Added brewfather ispindle copy format 2022-05-25 22:38:11 +02:00
58fe408803 GitHub Action Build 2022-05-25 18:54:46 +00:00
c2ae70bb1a #64 fix format, bump ver 2022-05-25 20:50:22 +02:00
7a3b048d80 Fixed errors in docs 2022-05-18 07:12:37 +02:00
ad3fbb7270 Merge branch 'master' into dev 2022-05-16 19:20:14 +02:00
02df656343 Added qa on formula creation 2022-05-16 19:19:00 +02:00
f73f63fec3 GitHub Action Build 2022-05-16 06:09:36 +00:00
bb09072520 Upd pre-commit 2022-05-16 08:04:26 +02:00
5875ee83d8 GitHub Action Build 2022-05-15 08:31:09 +00:00
6185d67d12 Fix pre-commit fail 2022-05-15 10:26:21 +02:00
00f82f5c37 Added pre-commit action 2022-05-15 10:24:02 +02:00
59ad285bb8 Updated pre-commit hooks 2022-05-15 10:23:01 +02:00
bc09d617fc Force g0 to water 2022-05-15 10:22:49 +02:00
a71f54b99f Brewpiless docs 2022-05-15 10:05:06 +02:00
152ff89bf6 Set rfd grav to 1 2022-05-15 09:55:01 +02:00
d9fb8291f4 Merge branch 'master' of https://github.com/mp-se/gravitymon 2022-05-10 18:43:22 +02:00
030746e982 Updated readme 2022-05-10 18:42:19 +02:00
d4260c6380 GitHub Action Build 2022-05-10 10:11:48 +00:00
50725407ea Bump v1.0 2022-05-10 12:06:05 +02:00
b4bac17114 Update issue templates 2022-05-09 20:44:42 +02:00
cb433a4a91 GitHub Action Build 2022-05-09 17:23:12 +00:00
095c1dc6a7 Adding http to keep-alive 2022-05-09 19:18:44 +02:00
43e2d165f5 Fix link error 2022-05-08 09:59:39 +02:00
fca7294b61 Updated docs 2022-05-08 09:58:26 +02:00
390c0882d1 Applied pre-commit on v1.0 source 2022-05-08 09:54:25 +02:00
5e9e705b96 #6 contribution 2022-05-08 09:50:45 +02:00
d67f72f123 #6 added contribution 2022-05-08 09:50:27 +02:00
f09aadaf66 #69 added schema for esp32 2022-05-08 09:22:52 +02:00
c68f67a558 GitHub Action Build 2022-05-06 16:11:31 +00:00
299e915bd2 Merge branch 'dev' of https://github.com/mp-se/gravitymon into dev 2022-05-06 18:06:25 +02:00
06a1541090 Updated docs for 1.0 2022-05-06 18:05:52 +02:00
a8b87140b2 #76 formula creation 2022-05-06 17:39:54 +02:00
1d738a14dd GitHub Action Build 2022-05-06 14:56:02 +00:00
4e37b9329c Updated esp32 code 2022-05-06 16:48:42 +02:00
9712e13c78 Updated release notes 2022-05-05 19:12:56 +02:00
1b11e49883 GitHub Action Build 2022-05-05 16:49:10 +00:00
cc6fecbdf8 Merge branch 'dev' of https://github.com/mp-se/gravitymon into dev 2022-05-05 18:44:35 +02:00
971b210438 Fixed error message 2022-05-05 18:44:16 +02:00
7b2a99c8a3 #73 add support for MPU6500 2022-05-05 17:52:26 +02:00
d6f8ff67a3 GitHub Action Build 2022-05-04 14:42:28 +00:00
f173b205ae Fix compiler error for esp32 2022-05-04 16:38:39 +02:00
e0312ab3c5 Update web pages 2022-05-04 16:31:49 +02:00
7678bb1f43 Remove zero length files at startup 2022-05-04 16:31:20 +02:00
403ed1d350 #72 lost wifi config 2022-05-04 16:31:02 +02:00
ced4c9f8fc GitHub Action Build 2022-05-01 16:11:44 +00:00
7e1862390e Merge branch 'dev' of https://github.com/mp-se/gravitymon into dev 2022-05-01 18:07:22 +02:00
a3cd3217ab #63 tilt validation 2022-05-01 18:07:16 +02:00
7ede9a6d19 Reserved point for water 2022-04-30 19:37:30 +02:00
f27e8ac79f Added function to collect support cfg 2022-04-30 19:30:09 +02:00
7874f1bcf2 Bump to beta2 2022-04-30 17:46:55 +02:00
9f87bf5432 Adjust advanced settings 2022-04-30 17:46:32 +02:00
5bbb7ebfaa Hide wifi pass2 2022-04-30 17:46:09 +02:00
328e7e71ae Added mqtt errors to docs 2022-04-30 07:09:08 +02:00
2912749f19 GitHub Action Build 2022-04-29 18:14:13 +00:00
43b6881477 Upd release notes 2022-04-29 20:08:58 +02:00
3a4cfb1ca5 Pre update of docs for v1.0 2022-04-29 20:08:02 +02:00
a40c3528d4 Update release notes 2022-04-29 19:10:49 +02:00
87036d56e5 Moved sensor bits to loop 2022-04-29 19:07:48 +02:00
93 changed files with 6896 additions and 578 deletions

31
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,31 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. ...
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Software:**
- Platform (esp8266, esp32)
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.

View File

@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

17
.github/stale.yaml vendored Normal file
View File

@ -0,0 +1,17 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 60
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 14
# Issues with these labels will never be considered stale
exemptLabels:
- on-hold
- security
# Label to use when marking an issue as stale
staleLabel: wontfix
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false

View File

@ -16,8 +16,12 @@ jobs:
with:
docs-folder: "src_docs/"
pre-build-command: |
pip install sphinx_rtd_theme
pip install furo
pip install --upgrade pip
pip install sphinx==4.3.2
pip install docutils==0.16
pip install pygments==2.11.1
pip install furo==2022.1.2
pip list
build-command: "sphinx-build -b html ./source ../docs"
- name: Commit documentation changes

19
.github/workflows/pre-commit.yaml vendored Normal file
View File

@ -0,0 +1,19 @@
name: pre-commit
on:
pull_request:
push:
branches:
- master
- dev
jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
- name: clang format support
run: |
sudo apt install clang-format cppcheck
- uses: pre-commit/action@v2.0.3

View File

@ -4,7 +4,10 @@ repos:
hooks:
- id: clang-format
files: ^src/
exclude: 'lib/'
- id: cpplint
files: ^src/
exclude: 'lib/'
- id: cppcheck
files: ^src/
exclude: 'lib/'

35
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,35 @@
## How to contribute to GravityMon
#### **Did you find a bug?**
* **Ensure the bug was not already reported** by searching on GitHub under [Issues](https://github.com/mp-se/gravitymon/issues). Dont forget to look under closed issues. There might be a fix but not yet included in the released version.
* If you're unable to find an open issue addressing the problem, [open a new one](https://github.com/mp-se/gravitymon/issues/new). Be sure to include a **title and clear description**, as much relevant information as possible, Use the function on the device to extract configuration and device information (does not contain any sensitive data). This can help to pinpoint the issue.
#### **Did you write a patch that fixes a bug?**
* Open a new GitHub pull request with the patch.
* Ensure the PR description clearly describes the problem and solution. Include the relevant issue number if applicable.
* Before submitting, please use `pre-commit` to validate that your code contribution complies with the formatting standards for C++ and C.
* Check the contribution section under the documentation for additional information.
#### **Do you intend to add a new feature or change an existing one?**
* Suggest your change in the [Discussion forums](https://github.com/mp-se/gravitymon/discussions) and start writing code.
* Do not open an issue on GitHub until you have collected positive feedback about the change. GitHub issues are primarily intended for bug reports and fixes.
#### **Do you have questions about the source software?**
* Start a discussion in the [Discussion forums](https://github.com/mp-se/gravitymon/discussions) and start writing code.
#### **Do you want to contribute to the documentation?**
* Open a new GitHub pull request with the updated documentation changes.
* Ensure the PR description clearly describes the problem and solution. Include the relevant issue number if applicable.
Thanks!

View File

@ -12,9 +12,11 @@ GravityMon is a replacement firmware for the iSpindle firmware. It's 100% compat
Now also works with ESP32 (use ESP32 d1 mini which is compatible with ESP8266)
Installation can be made using https://www.brewflasher.com
Installation can be made using https://www.brewflasher.com or https://web.brewflasher.com
Note! If its being flagged as malware, try the older version.
The documenation can be found here: https://mp-se.github.io/gravitymon/index.html
Note! If Brewflasher being flagged as malware by your antivirus software, try the web version.
The main differences:
---------------------
@ -23,17 +25,14 @@ The main differences:
* Efficient software, long lifespan (+45 days with 5min update frequencey)
* Send data to multiple endpoints (http-post, http-get, influxdb v2, mqtt)
* Instructions for service such as; Brewfather, Fermentrack, Ubidots, Home Assistant, Brewers Friend, Brewspy, Thingspeak, Blynk.
* SSL support in standard HTTP and MQTT connections.
* SSL support for all remote endpoints
* ESP32 support with Bluetooth push
* Customize data format to be pushed
* Automatic temperature adjustment of gravity when enabled
* Use the temperature sensor in gyro instead of DS18B20
* Built in function to create gravity formulas, no need for additional software, just enter tilt/gravity.
* Visual graph showing how gravity formula will be interpreted
* OTA support
* Built in performance measurements (used to optimise code)
* REST API for scripting
* OTA support or firmware upload via web interface
* REST API for scripting
No code has been reused from the iSpindle project.
The documenation can be found here: https://mp-se.github.io/gravitymon/index.html

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
{ "project":"gravmon", "version":"1.0.0", "html": [ ] }
{ "project":"gravmon", "version":"1.1.0", "html": [ ] }

View File

@ -97,7 +97,8 @@
<div class="row mb-3">
<label for="angle1" class="col-sm-1 col-form-label">1.</label>
<div class="col-sm-4"><input type="number" min="0" max="90" step="0.001" class="form-control" name="a1" id="a1" data-bs-toggle="tooltip" title="Enter the angle for the gravity. Zero value will be ignored"></div>
<div class="col-sm-4"><input type="number" min="0" max="26" step="0.0001" class="form-control" name="g1" id="g1" data-bs-toggle="tooltip" title="Enter the gravity for the angle."></div>
<input hidden type="number" name="g1" id="g1">
<div class="col-sm-4"><input disabled type="number" class="form-control" name="g1a" id="g1a" data-bs-toggle="tooltip" title="The first value is reserved for water gravity."></div>
</div>
<div class="row mb-3">
@ -369,6 +370,7 @@
if(isPlato()) {
$("#gravity-header").text("Gravity (Plato):");
$("#g1").val( parseFloat(cfg["g1"]).toFixed(1) );
$("#g1a").val( "0.0" );
$("#g2").val( parseFloat(cfg["g2"]).toFixed(1) );
$("#g3").val( parseFloat(cfg["g3"]).toFixed(1) );
$("#g4").val( parseFloat(cfg["g4"]).toFixed(1) );
@ -381,6 +383,7 @@
} else {
$("#gravity-header").text("Gravity (SG):");
$("#g1").val( parseFloat(cfg["g1"]).toFixed(4) );
$("#g1a").val( "1.0000" );
$("#g2").val( parseFloat(cfg["g2"]).toFixed(4) );
$("#g3").val( parseFloat(cfg["g3"]).toFixed(4) );
$("#g4").val( parseFloat(cfg["g4"]).toFixed(4) );

File diff suppressed because one or more lines are too long

View File

@ -105,15 +105,15 @@
<input type="text" name="id" id="id1" hidden>
<div class="row mb-3">
<label for="mdns" class="col-sm-2 col-form-label">Device name:</label>
<label for="mdns" class="col-sm-2 col-form-label">Device name</label>
<div class="col-sm-3">
<input type="text" maxlength="12" class="form-control" name="mdns" id="mdns" data-bs-toggle="tooltip" title="Name of the device. Will be used for identifying the device when pushing data and on the local network.">
<input type="text" maxlength="63" class="form-control" name="mdns" id="mdns" placeholder="gravmon" data-bs-toggle="tooltip" title="Name of the device. Will be used for identifying the device when pushing data and on the local network.">
</div>
</div>
<div class="row mb-3">
<fieldset class="form-group row">
<legend class="col-form-label col-sm-2 float-sm-left pt-0">Temperature Format:</legend>
<legend class="col-form-label col-sm-2 float-sm-left pt-0">Temperature Format</legend>
<div class="col-sm-4">
<div class="form-check">
<input class="form-check-input" type="radio" name="temp-format" id="temp-format-c" value="C" checked data-bs-toggle="tooltip" title="Temperature format used with displaying data">
@ -121,16 +121,16 @@
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="temp-format" id="temp-format-f" value="F" data-bs-toggle="tooltip" title="Temperature format used with displaying data">
<label class="form-check-label" for="temp-format-f">Farenheight</label>
<label class="form-check-label" for="temp-format-f">Fahrenheit</label>
</div>
</div>
</fieldset>
</div>
<div class="row mb-3">
<label for="sleep-interval" class="col-sm-2 col-form-label">Interval (seconds):</label>
<label for="sleep-interval" class="col-sm-2 col-form-label">Interval (seconds)</label>
<div class="col-sm-2">
<input type="number" min="10" max="3600" class="form-control" name="sleep-interval" id="sleep-interval" data-bs-toggle="tooltip" title="The number of seconds that the device will sleep between gravity readings. Recommended value is 300s">
<input type="number" min="10" max="3600" class="form-control" name="sleep-interval" id="sleep-interval" placeholder="300" data-bs-toggle="tooltip" title="The number of seconds that the device will sleep between gravity readings. Recommended value is 300s">
</div>
<label for="sleep-interval" class="col-sm-4 col-form-label" id="sleep-interval-info"></label>
</div>
@ -145,7 +145,7 @@
<hr class="my-2">
<div class="row mb-3">
<label for="calibrate-btn" class="col-sm-2 col-form-label">Current calibration:</label>
<label for="calibrate-btn" class="col-sm-2 col-form-label">Current calibration</label>
<label for="calibrate-btn" class="col-sm-2 col-form-label" id="gyro-calibration-data">Loading...</label>
<label for="gyro-calibration-data" class="col-sm-2 col-form-label" id="angle">Loading...</label>
<div class="col-sm-8 offset-sm-2">
@ -174,7 +174,7 @@
<input type="text" name="http-push2-h2" id="http-push2-h2" hidden>
<div class="row mb-3">
<label for="http-push" class="col-sm-2 col-form-label">HTTP 1 (POST):</label>
<label for="http-push" class="col-sm-2 col-form-label">HTTP 1 (POST)</label>
<div class="col-sm-8">
<input type="url" maxlength="120" class="form-control" name="http-push" id="http-push" placeholder="http://www.internet.com/path" data-bs-toggle="tooltip" title="URL to push target, use format http://servername.com/resource (Supports http and https)">
</div>
@ -184,7 +184,7 @@
</div>
<div class="row mb-3">
<label for="http-push2" class="col-sm-2 col-form-label">HTTP 2 (POST):</label>
<label for="http-push2" class="col-sm-2 col-form-label">HTTP 2 (POST)</label>
<div class="col-sm-8">
<input type="url" maxlength="120" class="form-control" name="http-push2" id="http-push2" placeholder="http://www.internet.com/path" data-bs-toggle="tooltip" title="URL to push target, use format http://servername.com/resource (Supports http and https)">
</div>
@ -194,21 +194,21 @@
</div>
<div class="row mb-3">
<label for="token" class="col-sm-2 col-form-label">Token:</label>
<label for="token" class="col-sm-2 col-form-label">Token</label>
<div class="col-sm-4">
<input type="text" maxlength="50" class="form-control" name="token" id="token" data-bs-toggle="tooltip" title="Token can be used in the format template as a variable, some services use this for authentication">
</div>
</div>
<div class="row mb-3">
<label for="http-push3" class="col-sm-2 col-form-label">HTTP 3 (GET):</label>
<label for="http-push3" class="col-sm-2 col-form-label">HTTP 3 (GET)</label>
<div class="col-sm-8">
<input type="url" maxlength="120" class="form-control" name="http-push3" id="http-push3" placeholder="http://www.internet.com/path" data-bs-toggle="tooltip" title="URL to push target, use format http://servername.com/resource (Supports http and https). Do not add the query string, that will be added via the format template">
</div>
</div>
<div class="row mb-3">
<label for="token2" class="col-sm-2 col-form-label">Token 2:</label>
<label for="token2" class="col-sm-2 col-form-label">Token 2</label>
<div class="col-sm-4">
<input type="text" maxlength="50" class="form-control" name="token2" id="token2" data-bs-toggle="tooltip" title="Token can be used in the format template as a variable, some services use this for authentication">
</div>
@ -246,28 +246,28 @@
<input type="text" name="section" value="collapsePush2" hidden>
<div class="row mb-3">
<label for="influxdb2-push" class="col-sm-2 col-form-label">InfluxDB v2 URL:</label>
<label for="influxdb2-push" class="col-sm-2 col-form-label">InfluxDB v2 URL</label>
<div class="col-sm-8">
<input type="url" maxlength="40" class="form-control" name="influxdb2-push" placeholder="http://www.internet.com" id="influxdb2-push" data-bs-toggle="tooltip" title="URL to push target, use format http://servername.com (Supports http and https)">
</div>
</div>
<div class="row mb-3">
<label for="influxdb2-org" class="col-sm-2 col-form-label">InfluxDB v2 Org:</label>
<label for="influxdb2-org" class="col-sm-2 col-form-label">InfluxDB v2 Org</label>
<div class="col-sm-4">
<input type="text" maxlength="50" class="form-control" name="influxdb2-org" id="influxdb2-org" data-bs-toggle="tooltip" title="Identifier to what organisation to use">
</div>
</div>
<div class="row mb-3">
<label for="influxdb2-bucket" class="col-sm-2 col-form-label">InfluxDB v2 Bucket:</label>
<label for="influxdb2-bucket" class="col-sm-2 col-form-label">InfluxDB v2 Bucket</label>
<div class="col-sm-4">
<input type="text" maxlength="50" class="form-control" name="influxdb2-bucket" id="influxdb2-bucket" data-bs-toggle="tooltip" title="Identifier for the data bucket to use">
</div>
</div>
<div class="row mb-3">
<label for="influxdb2-auth" class="col-sm-2 col-form-label">InfluxDB v2 Auth:</label>
<label for="influxdb2-auth" class="col-sm-2 col-form-label">InfluxDB v2 Auth</label>
<div class="col-sm-4">
<input type="text" maxlength="100" class="form-control" name="influxdb2-auth" id="influxdb2-auth" data-bs-toggle="tooltip" title="Authentication token for accessing data bucket">
</div>
@ -276,28 +276,28 @@
<hr class="my-2">
<div class="row mb-3">
<label for="mqtt-push" class="col-sm-2 col-form-label">MQTT Server:</label>
<label for="mqtt-push" class="col-sm-2 col-form-label">MQTT Server</label>
<div class="col-sm-4">
<input type="text" maxlength="40" class="form-control" name="mqtt-push" id="mqtt-push" placeholder="www.internet.com" data-bs-toggle="tooltip" title="Name of server to connect to, use format servername.com">
</div>
</div>
<div class="row mb-3">
<label for="mqtt-topic" class="col-sm-2 col-form-label">MQTT Port:</label>
<label for="mqtt-topic" class="col-sm-2 col-form-label">MQTT Port</label>
<div class="col-sm-4">
<input type="number" min="1" max="65535" class="form-control" name="mqtt-port" id="mqtt-port" placeholder="1138" data-bs-toggle="tooltip" title="Port number to use, 1138 is standard. Ports higher than 8000 will assume to use SSL">
<input type="number" min="1" max="65535" class="form-control" name="mqtt-port" id="mqtt-port" placeholder="1883" data-bs-toggle="tooltip" title="Port number to use, 1883 is standard. Ports higher than 8000 will assume to use SSL">
</div>
</div>
<div class="row mb-3">
<label for="mqtt-user" class="col-sm-2 col-form-label">MQTT User:</label>
<label for="mqtt-user" class="col-sm-2 col-form-label">MQTT User</label>
<div class="col-sm-4">
<input type="text" maxlength="20" class="form-control" name="mqtt-user" id="mqtt-user" data-bs-toggle="tooltip" title="Username to use. Leave blank if authentication is disabled">
</div>
</div>
<div class="row mb-3">
<label for="mqtt-pass" class="col-sm-2 col-form-label">MQTT Password:</label>
<label for="mqtt-pass" class="col-sm-2 col-form-label">MQTT Password</label>
<div class="col-sm-4">
<input type="text" maxlength="20" class="form-control" name="mqtt-pass" id="mqtt-pass" data-bs-toggle="tooltip" title="Password to use. Leave blank if authentication is disabled">
</div>
@ -335,7 +335,7 @@
<div class="row mb-3">
<fieldset class="form-group row">
<legend class="col-form-label col-sm-2 float-sm-left pt-0">Gravity Format:</legend>
<label for="gravity-format" class="col-sm-2 col-form-label">Gravity Format</label>
<div class="col-sm-4">
<div class="form-check">
<input class="form-check-input" type="radio" name="gravity-format" id="gravity-format-g" value="G" checked data-bs-toggle="tooltip" title="Present gravity in SG format">
@ -352,12 +352,12 @@
<div class="row mb-3">
<label for="gravity-formula" class="col-sm-2 col-form-label">Formula</label>
<div class="col-sm-10">
<input type="text" maxlength="200" class="form-control" name="gravity-formula" id="gravity-formula" checked data-bs-toggle="tooltip" title="Formula used to convert angle to gravity">
<input type="text" maxlength="200" class="form-control" name="gravity-formula" id="gravity-formula" placeholder="0.0*tilt^2+0.01*tilt+0.2" checked data-bs-toggle="tooltip" title="Formula used to convert angle to gravity">
</div>
</div>
<div class="row mb-3">
<div class="col-sm-4 offset-sm-2">
<div class="col-sm-3 offset-sm-2">
<div class="form-check">
<input class="form-check-input" type="checkbox" name="gravity-temp-adjustment" id="gravity-temp-adjustment" checked data-bs-toggle="tooltip" title="Adjust the calculated gravity based on the current temperature. Assumes that calibration is done using 20C / 68F">
<label class="form-check-label" for="gravity-temp-adjustment">Temperature adjust gravity</label>
@ -388,22 +388,29 @@
<input type="text" name="id" id="id4" hidden>
<div class="row mb-3">
<label for="voltage-factor" class="col-sm-2 col-form-label">Voltage factor:</label>
<label for="voltage-factor" class="col-sm-2 col-form-label">Voltage factor</label>
<div class="col-sm-2">
<input type="number" step=".01" class="form-control" name="voltage-factor" id="voltage-factor" data-bs-toggle="tooltip" title="Factor used to calculate the battery voltage. When running on battery, the voltage should be less than 4.15V">
<input type="number" step=".01" class="form-control" name="voltage-factor" id="voltage-factor" placeholder="1.59" data-bs-toggle="tooltip" title="Factor used to calculate the battery voltage. Can vary depending on the R2 value">
</div>
<label for="voltage-factor" class="col-sm-3 col-form-label" id="battery">Loading...</label>
</div>
<div class="row mb-3">
<label for="temp-adjustment-value" class="col-sm-2 col-form-label">Temp Sensor Adj:</label>
<label for="voltage-config" class="col-sm-2 col-form-label">Config voltage</label>
<div class="col-sm-2">
<input type="number" step=".1" class="form-control" name="temp-adjustment-value" id="temp-adjustment-value" data-bs-toggle="tooltip" title="This value will be added to the sensor value in case the sensor dont show the correct temperature">
<input type="number" step=".01" min="3.00" max="6.00" class="form-control" name="voltage-config" id="voltage-config" placeholder="4.16" data-bs-toggle="tooltip" title="Over this level the device will always go into configuration mode, some batteries might have a higher voltage when fully charged">
</div>
</div>
<div class="row mb-3">
<div class="col-sm-3 offset-sm-2">
<label for="temp-adjustment-value" class="col-sm-2 col-form-label">Temp Sensor Adj</label>
<div class="col-sm-2">
<input type="number" step=".1" class="form-control" name="temp-adjustment-value" id="temp-adjustment-value" placeholder="0" data-bs-toggle="tooltip" title="This value will be added to the sensor value in case the sensor dont show the correct temperature">
</div>
</div>
<div class="row mb-3">
<div class="col-sm-4 offset-sm-2">
<div class="form-check">
<input class="form-check-input" type="checkbox" name="gyro-temp" id="gyro-temp" data-bs-toggle="tooltip" title="Use the temperature sensor in the gyro instead of DS18B20, require 300s update interval to be accurate">
<label class="form-check-label" for="gyro-temp">Use gyro temperature</label>
@ -411,6 +418,15 @@
</div>
</div>
<div class="row mb-3">
<div class="col-sm-4 offset-sm-2">
<div class="form-check">
<input class="form-check-input" type="checkbox" name="storage-sleep" id="storage-sleep" data-bs-toggle="tooltip" title="If enabled and the device is placed on its cap (less than 5 degress) it will go into sleep for 2000 minutes">
<label class="form-check-label" for="storage-sleep">Enable storage mode when placed on cap</label>
</div>
</div>
</div>
<div class="row mb-3">
<label class="col-sm-2 col-form-label" for="ble">Bluetooth tilt color:</label>
<div class="col-sm-2">
@ -429,7 +445,7 @@
</div>
<div class="row mb-3">
<label for="ota-url" class="col-sm-2 col-form-label">OTA base URL:</label>
<label for="ota-url" class="col-sm-2 col-form-label">OTA base URL</label>
<div class="col-sm-8">
<input type="url" maxlength="90" class="form-control" name="ota-url" id="ota-url" placeholder="http://www.local.com/path/" data-bs-toggle="tooltip" title="Base URL to where firmware and version.json file can be found. Needs to end with '/', example: http://www.mysite.com/firmware/">
</div>
@ -453,45 +469,72 @@
<div class="accordion-item">
<h2 class="accordion-header" id="headingAdvanced">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseAdvanced" aria-expanded="false" aria-controls="collapseAdvanced">
<b>Advanced Settings (use with caution)</b>
<b>Advanced Software Settings (use with caution)</b>
</button>
</h2>
<div id="collapseAdvanced" class="accordion-collapse collapse" aria-labelledby="headingAdvanced" data-bs-parent="#accordion">
<div class="accordion-body">
<div class="row mb-3">
<div class="col-sm-4">
<div class="form-check">
<input checked class="form-check-input" type="checkbox" name="adv-config" id="adv-config" data-bs-toggle="tooltip" title="Enable the advanced software settings.">
<label class="form-check-label" for="adv-config">Disable advanced software settings</label>
</div>
</div>
</div>
<form action="/api/config/advanced" method="post">
<input type="text" name="id" id="id6" hidden>
<div class="row mb-3">
<label for="gyro-read-count" class="col-sm-3 col-form-label">Gyro reads:</label>
<div class="col-sm-2">
<input disabled type="number" min="10" max="100" class="form-control" name="gyro-read-count" id="gyro-read-count" checked data-bs-toggle="tooltip" title="How many times should we read the gyro to get an accurate angle. More reads = better accuracy but higher battery drain">
<div class="col-sm-3">
<input disabled type="number" min="10" max="100" class="form-control" name="gyro-read-count" id="gyro-read-count" placeholder="50" checked data-bs-toggle="tooltip" title="How many times should we read the gyro to get an accurate angle. More reads = better accuracy but higher battery drain">
</div>
<div class="col-sm-5">(10-100) - default 50</div>
</div>
<div class="row mb-3">
<label for="gyro-moving-threashold" class="col-sm-3 col-form-label">Gyro moving theashold:</label>
<div class="col-sm-2">
<input disabled type="number" min="50" max="1000" class="form-control" name="gyro-moving-threashold" id="gyro-moving-threashold" checked data-bs-toggle="tooltip" title="How much deviation between gyro reads are acceptable in order to regard this as a valid angle">
<label for="gyro-moving-threashold" class="col-sm-3 col-form-label">Gyro moving theashold</label>
<div class="col-sm-3">
<input disabled type="number" min="50" max="1000" class="form-control" name="gyro-moving-threashold" id="gyro-moving-threashold" placeholder="500" checked data-bs-toggle="tooltip" title="How much deviation between gyro reads are acceptable in order to regard this as a valid angle">
</div>
<div class="col-sm-5">(50-1000) - default 500</div>
</div>
<div class="row mb-3">
<label for="formula-max-deviation" class="col-sm-3 col-form-label">Formula max deviation (SG):</label>
<div class="col-sm-2">
<input disabled type="number" step=".1" min="1" max="10" class="form-control" name="formula-max-deviation" id="formula-max-deviation" checked data-bs-toggle="tooltip" title="When validating the derived formula this is the maximum accepted deviation for the supplied values">
<label for="formula-max-deviation" class="col-sm-3 col-form-label">Formula max deviation (SG)</label>
<div class="col-sm-3">
<input disabled type="number" step=".1" min="1" max="10" class="form-control" name="formula-max-deviation" id="formula-max-deviation" placeholder="3" checked data-bs-toggle="tooltip" title="When validating the derived formula this is the maximum accepted deviation for the supplied values">
</div>
<div class="col-sm-5">(1 - 10) - default 1.6 SG</div>
<div class="col-sm-5">(1 - 10) - default 3 SG</div>
</div>
<div class="row mb-3">
<div class="col-sm-3 offset-sm-3">
<div class="form-check">
<input disabled class="form-check-input" type="checkbox" class="form-control" name="ignore-low-angles" id="ignore-low-angles" data-bs-toggle="tooltip" title="When active, angles below water will be ignored. Note! Angle must be defined under calibration, first field.">
<label class="form-check-label" for="ignore-low-angles">Ignore angles below water</label>
</div>
</div>
<div class="col-sm-5" name="water-angle" id="water-angle"></div>
</div>
<div class="row mb-3">
<label for="formula-calibration-temp" class="col-sm-3 col-form-label">Gravity calibration temp</label>
<div class="col-sm-3">
<input disabled type="number" step=".01" min="0" max="100" class="form-control" name="formula-calibration-temp" id="formula-calibration-temp" placeholder="20" checked data-bs-toggle="tooltip" title="Calibration temperature, used in temperatur correction formula, default 20C/68F">
</div>
<div class="col-sm-5">(0 - 100) - default 20C/68F</div>
</div>
<hr>
<div class="row mb-3">
<label for="tempsensor-resolution" class="col-sm-3 col-form-label">DS18B20 resolution (bits):</label>
<div class="col-sm-2">
<input disabled type="number" min="9" max="12" class="form-control" name="tempsensor-resolution" id="tempsensor-resolution" checked data-bs-toggle="tooltip" title="Resolution when reading the DS18B20 temperature sensor, higher resolution give better accuracy but takes longer">
<label for="tempsensor-resolution" class="col-sm-3 col-form-label">DS18B20 resolution (bits)</label>
<div class="col-sm-3">
<input disabled type="number" min="9" max="12" class="form-control" name="tempsensor-resolution" id="tempsensor-resolution" placeholder="9" checked data-bs-toggle="tooltip" title="Resolution when reading the DS18B20 temperature sensor, higher resolution give better accuracy but takes longer">
</div>
<div class="col-sm-5">(9 - 12) - default 9 bits</div>
</div>
@ -499,17 +542,17 @@
<hr>
<div class="row mb-3">
<label for="wifi-connect-timeout" class="col-sm-3 col-form-label">Wifi connect timeout (s):</label>
<div class="col-sm-2">
<input disabled type="number" min="1" max="60" class="form-control" name="wifi-connect-timeout" id="wifi-connect-timeout" checked data-bs-toggle="tooltip" title="Max time waiting for a wifi connection before going back to sleep">
<label for="wifi-connect-timeout" class="col-sm-3 col-form-label">Wifi connect timeout (s)</label>
<div class="col-sm-3">
<input disabled type="number" min="1" max="60" class="form-control" name="wifi-connect-timeout" id="wifi-connect-timeout" placeholder="20" checked data-bs-toggle="tooltip" title="Max time waiting for a wifi connection before going back to sleep">
</div>
<div class="col-sm-5">(1 - 60) - default 20 s</div>
</div>
<div class="row mb-3">
<label for="wifi-portal-timeout" class="col-sm-3 col-form-label">Wifi portal timeout (s):</label>
<div class="col-sm-2">
<input disabled type="number" min="10" max="240" class="form-control" name="wifi-portal-timeout" id="wifi-portal-timeout" checked data-bs-toggle="tooltip" title="Max time the wifi portal is active before existing">
<label for="wifi-portal-timeout" class="col-sm-3 col-form-label">Wifi portal timeout (s)</label>
<div class="col-sm-3">
<input disabled type="number" min="10" max="240" class="form-control" name="wifi-portal-timeout" id="wifi-portal-timeout" placeholder="120" checked data-bs-toggle="tooltip" title="Max time the wifi portal is active before existing">
</div>
<div class="col-sm-5">(10 - 240) - default 120 s</div>
</div>
@ -518,40 +561,40 @@
<div class="row mb-3">
<label for="int-http1" class="col-sm-3 col-form-label">Skip interval - HTTP 1 (POST):</label>
<div class="col-sm-2">
<input disabled type="number" min="0" max="5" class="form-control" name="int-http1" id="int-http1" checked data-bs-toggle="tooltip" title="Defines how many sleep cycles to skip between pushing data to this target, 1 = every second cycle">
<div class="col-sm-3">
<input disabled type="number" min="0" max="5" class="form-control" name="int-http1" id="int-http1" placeholder="0" checked data-bs-toggle="tooltip" title="Defines how many sleep cycles to skip between pushing data to this target, 1 = every second cycle">
</div>
<div class="col-sm-5">(0 - 5) - default 0</div>
</div>
<div class="row mb-3">
<label for="int-http2" class="col-sm-3 col-form-label">Skip interval - HTTP 2 (POST):</label>
<div class="col-sm-2">
<input disabled type="number" min="0" max="5" class="form-control" name="int-http2" id="int-http2" data-bs-toggle="tooltip" title="Defines how many sleep cycles to skip between pushing data to this target, 1 = every second cycle">
<label for="int-http2" class="col-sm-3 col-form-label">Skip interval - HTTP 2 (POST)</label>
<div class="col-sm-3">
<input disabled type="number" min="0" max="5" class="form-control" name="int-http2" id="int-http2" placeholder="0" data-bs-toggle="tooltip" title="Defines how many sleep cycles to skip between pushing data to this target, 1 = every second cycle">
</div>
<div class="col-sm-5">(0 - 5) - default 0</div>
</div>
<div class="row mb-3">
<label for="int-http3" class="col-sm-3 col-form-label">Skip interval - HTTP 3 (GET):</label>
<div class="col-sm-2">
<input disabled type="number" min="0" max="5" class="form-control" name="int-http3" id="int-http3" data-bs-toggle="tooltip" title="Defines how many sleep cycles to skip between pushing data to this target, 1 = every second cycle">
<label for="int-http3" class="col-sm-3 col-form-label">Skip interval - HTTP 3 (GET)</label>
<div class="col-sm-3">
<input disabled type="number" min="0" max="5" class="form-control" name="int-http3" id="int-http3" placeholder="0" data-bs-toggle="tooltip" title="Defines how many sleep cycles to skip between pushing data to this target, 1 = every second cycle">
</div>
<div class="col-sm-5">(0 - 5) - default 0</div>
</div>
<div class="row mb-3">
<label for="int-influx" class="col-sm-3 col-form-label">Skip interval - InfluxDB v2:</label>
<div class="col-sm-2">
<input disabled type="number" min="0" max="5" class="form-control" name="int-influx" id="int-influx" data-bs-toggle="tooltip" title="Defines how many sleep cycles to skip between pushing data to this target, 1 = every second cycle">
<label for="int-influx" class="col-sm-3 col-form-label">Skip interval - InfluxDB v2</label>
<div class="col-sm-3">
<input disabled type="number" min="0" max="5" class="form-control" name="int-influx" id="int-influx" placeholder="0" data-bs-toggle="tooltip" title="Defines how many sleep cycles to skip between pushing data to this target, 1 = every second cycle">
</div>
<div class="col-sm-5">(0 - 5) - default 0</div>
</div>
<div class="row mb-3">
<label for="int-mqtt" class="col-sm-3 col-form-label">Skip interval - MQTT:</label>
<div class="col-sm-2">
<input disabled type="number" min="0" max="5" class="form-control" name="int-mqtt" id="int-mqtt" data-bs-toggle="tooltip" title="Defines how many sleep cycles to skip between pushing data to this target, 1 = every second cycle">
<label for="int-mqtt" class="col-sm-3 col-form-label">Skip interval - MQTT</label>
<div class="col-sm-3">
<input disabled type="number" min="0" max="5" class="form-control" name="int-mqtt" id="int-mqtt" placeholder="0" data-bs-toggle="tooltip" title="Defines how many sleep cycles to skip between pushing data to this target, 1 = every second cycle">
</div>
<div class="col-sm-5">(0 - 5) - default 0</div>
</div>
@ -563,15 +606,6 @@
</div>
</form>
<div class="row mb-3">
<div class="col-sm-4 offset-sm-3">
<div class="form-check">
<input class="form-check-input" type="checkbox" name="adv-config" id="adv-config" checked data-bs-toggle="tooltip" title="Enabled the advanced configuration settings.">
<label class="form-check-label" for="adv-config">Enable advanced configuration</label>
</div>
</div>
</div>
</div>
</div>
@ -747,19 +781,21 @@
function checkAdvancedSection( b ) {
var b = $("#adv-config").is(":checked");
$("#advanced-btn").prop("disabled", b);
$("#gyro-read-count").prop("disabled", b);
$("#gyro-moving-threashold").prop("disabled", b);
$("#formula-max-deviation").prop("disabled", b);
$("#wifi-portal-timeout").prop("disabled", b);
$("#wifi-connect-timeout").prop("disabled", b);
$("#formula-calibration-temp").prop("disabled", b);
$("#int-http1").prop("disabled", b);
$("#int-http2").prop("disabled", b);
$("#int-http3").prop("disabled", b);
$("#int-influx").prop("disabled", b);
$("#int-mqtt").prop("disabled", b);
$("#tempsensor-resolution").prop("disabled", b);
$("#ignore-low-angles").prop("disabled", b);
}
// Get the advanced values from the API
@ -778,11 +814,18 @@
$("#wifi-portal-timeout").val(cfg["wifi-portal-timeout"]);
$("#wifi-connect-timeout").val(cfg["wifi-connect-timeout"]);
$("#tempsensor-resolution").val(cfg["tempsensor-resolution"]);
$("#ignore-low-angles").prop( "checked", cfg["ignore-low-angles"] );
$("#formula-calibration-temp").val(cfg["formula-calibration-temp"]);
$("#int-http1").val(cfg["int-http1"]);
$("#int-http2").val(cfg["int-http2"]);
$("#int-http3").val(cfg["int-http3"]);
$("#int-influx").val(cfg["int-influx"]);
$("#int-mqtt").val(cfg["int-mqtt"]);
if ( cfg["gyro-read-count"] != 50 || cfg["gyro-moving-threashold"] != 500 || cfg["formula-max-deviation"] != 3 || cfg["wifi-portal-timeout"] != 120 || cfg["wifi-connect-timeout"] != 20 || cfg["tempsensor-resolution"] != 9 ||
cfg["int-http1"] != 0 || cfg["int-http2"] != 0 || cfg["int-http3"] != 0 || cfg["int-influx"] != 0 || cfg["int-mqtt"] != 0 || cfg["ignore-low-angles"] != false || (cfg["formula-calibration-temp"] != 20 && cfg["formula-calibration-temp"] != 68)) {
$("#adv-config").attr("checked", false );
}
})
.fail(function () {
showError('Unable to get data from the device.');
@ -839,14 +882,17 @@
$("#mqtt-pass").val(cfg["mqtt-pass"]);
$("#sleep-interval").val(cfg["sleep-interval"]);
$("#voltage-factor").val(cfg["voltage-factor"]);
$("#voltage-config").val(cfg["voltage-config"]);
$("#gravity-formula").val(cfg["gravity-formula"]);
$("#temp-adjustment-value").val(cfg["temp-adjustment-value"]);
$("#gravity-temp-adjustment").prop( "checked", cfg["gravity-temp-adjustment"] );
$("#gyro-temp").prop( "checked", cfg["gyro-temp"] );
$("#storage-sleep").prop( "checked", cfg["storage-sleep"] );
$("#gyro-calibration-data").text( cfg["gyro-calibration-data"]["ax"] + "," + cfg["gyro-calibration-data"]["ay"] + "," + cfg["gyro-calibration-data"]["az"] + "," + cfg["gyro-calibration-data"]["gx"] + "," + cfg["gyro-calibration-data"]["gy"] + "," + cfg["gyro-calibration-data"]["gz"] );
$("#battery").text(cfg["battery"] + " V");
$("#angle").text(cfg["angle"]);
$("#runtime-average").val(cfg["runtime-average"]);
$("#water-angle").text( "(Water angle: " + cfg["formula-calculation-data"]["a1"] + ") - default off");
//$("#gravity").text(cfg["gravity"] + " SG");
})
.fail(function () {

File diff suppressed because one or more lines are too long

View File

@ -96,13 +96,15 @@
<script>
let formatTemplates = [
{ "id": "GravityMon-Post", "format": "%7B%0A%20%22name%22%20%3A%20%22%24%7Bmdns%7D%22%2C%0A%20%22ID%22%3A%20%22%24%7Bid%7D%22%2C%0A%20%22token%22%20%3A%20%22gravmon%22%2C%0A%20%22interval%22%3A%20%24%7Bsleep-interval%7D%2C%0A%20%22temperature%22%3A%20%24%7Btemp%7D%2C%0A%20%22temp_units%22%3A%20%22%24%7Btemp-unit%7D%22%2C%0A%20%22gravity%22%3A%20%24%7Bgravity%7D%2C%0A%20%22angle%22%3A%20%24%7Bangle%7D%2C%0A%20%22battery%22%3A%20%24%7Bbattery%7D%2C%0A%20%22RSSI%22%3A%20%24%7Brssi%7D%2C%0A%20%22corr-gravity%22%3A%20%24%7Bcorr-gravity%7D%2C%0A%20%22gravity-unit%22%3A%20%22%24%7Bgravity-unit%7D%22%2C%0A%20%22run-time%22%3A%20%24%7Brun-time%7D%0A%7D" },
{ "id": "GravityMon-Post", "format": "%7B%20%22name%22%20%3A%20%22%24%7Bmdns%7D%22%2C%20%22ID%22%3A%20%22%24%7Bid%7D%22%2C%20%22token%22%20%3A%20%22%24%7Btoken%7D%22%2C%20%22interval%22%3A%20%24%7Bsleep-interval%7D%2C%20%22temperature%22%3A%20%24%7Btemp%7D%2C%20%22temp_units%22%3A%20%22%24%7Btemp-unit%7D%22%2C%20%22gravity%22%3A%20%24%7Bgravity%7D%2C%20%22angle%22%3A%20%24%7Bangle%7D%2C%20%22battery%22%3A%20%24%7Bbattery%7D%2C%20%22RSSI%22%3A%20%24%7Brssi%7D%2C%20%22corr-gravity%22%3A%20%24%7Bcorr-gravity%7D%2C%20%22gravity-unit%22%3A%20%22%24%7Bgravity-unit%7D%22%2C%20%22run-time%22%3A%20%24%7Brun-time%7D%7D" },
{ "id": "GravityMon-Get", "format": "%3Fname%3D%24%7Bmdns%7D%26id%3D%24%7Bid%7D%26token%3D%24%7Btoken2%7D%26interval%3D%24%7Bsleep-interval%7D%26temperature%3D%24%7Btemp%7D%26%0Atemp-units%3D%24%7Btemp-unit%7D%26gravity%3D%24%7Bgravity%7D%26angle%3D%24%7Bangle%7D%26battery%3D%24%7Bbattery%7D%26rssi%3D%24%7Brssi%7D%26%0Acorr-gravity%3D%24%7Bcorr-gravity%7D%26gravity-unit%3D%24%7Bgravity-unit%7D%26run-time%3D%24%7Brun-time%7D" },
{ "id": "iSpindle-Post", "format": "%7B%0A%20%22name%22%20%3A%20%22%24%7Bmdns%7D%22%2C%0A%20%22ID%22%3A%20%22%24%7Bid%7D%22%2C%0A%20%22token%22%20%3A%20%22gravmon%22%2C%0A%20%22interval%22%3A%20%24%7Bsleep-interval%7D%2C%0A%20%22temperature%22%3A%20%24%7Btemp%7D%2C%0A%20%22temp_units%22%3A%20%22%24%7Btemp-unit%7D%22%2C%0A%20%22gravity%22%3A%20%24%7Bgravity%7D%2C%0A%20%22angle%22%3A%20%24%7Bangle%7D%2C%0A%20%22battery%22%3A%20%24%7Bbattery%7D%2C%0A%20%22RSSI%22%3A%20%24%7Brssi%7D%0A%7D" },
{ "id": "BrewFatherCustom-Post", "format": "%7B%0A%20%20%20%22name%22%3A%20%22%24%7Bmdns%7D%22%2C%0A%20%20%20%22temp%22%3A%20%24%7Btemp%7D%2C%0A%20%20%20%22aux_temp%22%3A%200%2C%0A%20%20%20%22ext_temp%22%3A%200%2C%0A%20%20%20%22temp_unit%22%3A%20%22%24%7Btemp-unit%7D%22%2C%0A%20%20%20%22gravity%22%3A%20%24%7Bgravity%7D%2C%0A%20%20%20%22gravity_unit%22%3A%20%22%24%7Bgravity-unit%7D%22%2C%0A%20%20%20%22pressure%22%3A%200%2C%0A%20%20%20%22pressure_unit%22%3A%20%22PSI%22%2C%0A%20%20%20%22ph%22%3A%200%2C%0A%20%20%20%22bpm%22%3A%200%2C%0A%20%20%20%22comment%22%3A%20%22%22%2C%0A%20%20%20%22beer%22%3A%20%22%22%2C%0A%20%20%20%22battery%22%3A%20%24%7Bbattery%7D%0A%7D" },
{ "id": "iSpindle-Post", "format": "%7B%20%22name%22%20%3A%20%22%24%7Bmdns%7D%22%2C%20%22ID%22%3A%20%22%24%7Bid%7D%22%2C%20%22token%22%20%3A%20%22%24%7Btoken%7D%22%2C%20%22interval%22%3A%20%24%7Bsleep-interval%7D%2C%20%22temperature%22%3A%20%24%7Btemp%7D%2C%20%22temp_units%22%3A%20%22%24%7Btemp-unit%7D%22%2C%20%22gravity%22%3A%20%24%7Bgravity%7D%2C%20%22angle%22%3A%20%24%7Bangle%7D%2C%20%22battery%22%3A%20%24%7Bbattery%7D%2C%20%22RSSI%22%3A%20%24%7Brssi%7D%7D" },
{ "id": "BrewFatherCustom-Post", "format": "%7B%20%20%20%22name%22%3A%20%22%24%7Bmdns%7D%22%2C%20%20%20%22temp%22%3A%20%24%7Btemp%7D%2C%20%20%20%22aux_temp%22%3A%200%2C%20%20%20%22ext_temp%22%3A%200%2C%20%20%20%22temp_unit%22%3A%20%22%24%7Btemp-unit%7D%22%2C%20%20%20%22gravity%22%3A%20%24%7Bgravity%7D%2C%20%20%20%22gravity_unit%22%3A%20%22%24%7Bgravity-unit%7D%22%2C%20%20%20%22pressure%22%3A%200%2C%20%20%20%22pressure_unit%22%3A%20%22PSI%22%2C%20%20%20%22ph%22%3A%200%2C%20%20%20%22bpm%22%3A%200%2C%20%20%20%22comment%22%3A%20%22%22%2C%20%20%20%22beer%22%3A%20%22%22%2C%20%20%20%22battery%22%3A%20%24%7Bbattery%7D%7D" },
{ "id": "iSpindle-Mqtt", "format": "ispindel%2F%24%7Bmdns%7D%2Ftilt%3A%24%7Bangle%7D%7C%0Aispindel%2F%24%7Bmdns%7D%2Ftemperature%3A%24%7Btemp%7D%7C%0Aispindel%2F%24%7Bmdns%7D%2Ftemp_units%3A%24%7Btemp-unit%7D%7C%0Aispindel%2F%24%7Bmdns%7D%2Fbattery%3A%24%7Bbattery%7D%7C%0Aispindel%2F%24%7Bmdns%7D%2Fgravity%3A%24%7Bgravity%7D%7C%0Aispindel%2F%24%7Bmdns%7D%2Finterval%3A%24%7Bsleep-interval%7D%7C%0Aispindel%2F%24%7Bmdns%7D%2FRSSI%3A%24%7Brssi%7D%7C" },
{ "id": "HomeAssistant-Mqtt", "format": "gravmon%2F%24%7Bmdns%7D%2Ftilt%3A%24%7Bangle%7D%7C%0Agravmon%2F%24%7Bmdns%7D%2Ftemperature%3A%24%7Btemp%7D%7C%0Agravmon%2F%24%7Bmdns%7D%2Ftemp_units%3A%24%7Btemp-unit%7D%7C" },
{ "id": "UBIDots1-Post", "format": "%7B%0A%20%20%20%22temperature%22%3A%20%24%7Btemp%7D%2C%0A%20%20%20%22gravity%22%3A%20%24%7Bgravity%7D%2C%0A%20%20%20%22angle%22%3A%20%24%7Bangle%7D%2C%0A%20%20%20%22battery%22%3A%20%24%7Bbattery%7D%2C%0A%20%20%20%22rssi%22%3A%20%24%7Brssi%7D%0A%7D" } ];
{ "id": "HomeAssistant-Mqtt", "format": "gravmon%2F%24%7Bmdns%7D%2Ftemperature%3A%24%7Btemp%7D%7C%0Agravmon%2F%24%7Bmdns%7D%2Fgravity%3A%24%7Bgravity%7D%7C%0Agravmon%2F%24%7Bmdns%7D%2Frssi%3A%24%7Brssi%7D%7C%0Agravmon%2F%24%7Bmdns%7D%2Ftilt%3A%24%7Btilt%7D%7C%0Agravmon%2F%24%7Bmdns%7D%2Fbattery%3A%24%7Bbattery%7D%7C%0A" },
{ "id": "HomeAssistant-Mqtt2", "format": "gravmon%2F%24%7Bmdns%7D%2Ftemperature%3A%24%7Btemp%7D%7C%0Agravmon%2F%24%7Bmdns%7D%2Fgravity%3A%24%7Bgravity%7D%7C%0Agravmon%2F%24%7Bmdns%7D%2Frssi%3A%24%7Brssi%7D%7C%0Agravmon%2F%24%7Bmdns%7D%2Ftilt%3A%24%7Btilt%7D%7C%0Agravmon%2F%24%7Bmdns%7D%2Fbattery%3A%24%7Bbattery%7D%7C%0Ahomeassistant%2Fsensor%2Fgravmon_%24%7Bid%7D%2Ftemperature%2Fconfig%3A%7B%22dev%22%3A%7B%22name%22%3A%22%24%7Bmdns%7D%22%2C%22mdl%22%3A%22gravmon%22%2C%22sw%22%3A%22%24%7Bapp-ver%7D%22%2C%22ids%22%3A%22%24%7Bid%7D%22%7D%2C%22uniq_id%22%3A%22%24%7Bid%7D_temp%22%2C%22name%22%3A%22temperature%22%2C%22dev_cla%22%3A%22temperature%22%2C%22unit_of_meas%22%3A%22%24%7Btemp-unit%7D%22%2C%22stat_t%22%3A%22gravmon%2F%24%7Bmdns%7D%2Ftemperature%22%7D%7C%0Ahomeassistant%2Fsensor%2Fgravmon_%24%7Bid%7D%2Fgravity%2Fconfig%3A%7B%22dev%22%3A%7B%22name%22%3A%22%24%7Bmdns%7D%22%2C%22mdl%22%3A%22gravmon%22%2C%22sw%22%3A%22%24%7Bapp-ver%7D%22%2C%22ids%22%3A%22%24%7Bid%7D%22%7D%2C%22uniq_id%22%3A%22%24%7Bid%7D_grav%22%2C%22name%22%3A%22gravity%22%2C%22dev_cla%22%3A%22temperature%22%2C%22unit_of_meas%22%3A%22%20%24%7Bgravity-unit%7D%22%2C%22stat_t%22%3A%22gravmon%2F%24%7Bmdns%7D%2Fgravity%22%7D%7C%0Ahomeassistant%2Fsensor%2Fgravmon_%24%7Bid%7D%2Frssi%2Fconfig%3A%7B%22dev%22%3A%7B%22name%22%3A%22%24%7Bmdns%7D%22%2C%22mdl%22%3A%22gravmon%22%2C%22sw%22%3A%22%24%7Bapp-ver%7D%22%2C%22ids%22%3A%22%24%7Bid%7D%22%7D%2C%22uniq_id%22%3A%22%24%7Bid%7D_rssi%22%2C%22name%22%3A%22rssi%22%2C%22dev_cla%22%3A%22temperature%22%2C%22unit_of_meas%22%3A%22dBm%22%2C%22stat_t%22%3A%22gravmon%2F%24%7Bmdns%7D%2Frssi%22%7D%7C%0Ahomeassistant%2Fsensor%2Fgravmon_%24%7Bid%7D%2Ftilt%2Fconfig%3A%7B%22dev%22%3A%7B%22name%22%3A%22%24%7Bmdns%7D%22%2C%22mdl%22%3A%22gravmon%22%2C%22sw%22%3A%22%24%7Bapp-ver%7D%22%2C%22ids%22%3A%22%24%7Bid%7D%22%7D%2C%22uniq_id%22%3A%22%24%7Bid%7D_tilt%22%2C%22name%22%3A%22tilt%22%2C%22dev_cla%22%3A%22temperature%22%2C%22stat_t%22%3A%22gravmon%2F%24%7Bmdns%7D%2Ftilt%22%7D%7C%0Ahomeassistant%2Fsensor%2Fgravmon_%24%7Bid%7D%2Fbattery%2Fconfig%3A%7B%22dev%22%3A%7B%22name%22%3A%22%24%7Bmdns%7D%22%2C%22mdl%22%3A%22gravmon%22%2C%22sw%22%3A%22%24%7Bapp-ver%7D%22%2C%22ids%22%3A%22%24%7Bid%7D%22%7D%2C%22uniq_id%22%3A%22%24%7Bid%7D_batt%22%2C%22name%22%3A%22battery%22%2C%22dev_cla%22%3A%22temperature%22%2C%22unit_of_meas%22%3A%22V%22%2C%22stat_t%22%3A%22gravmon%2F%24%7Bmdns%7D%2Fbattery%22%7D%7C%0A" },
{ "id": "Brewblox-Mqtt", "format": "brewcast%2Fhistory%3A%7B%22key%22%3A%22%24%7Bmdns%7D%22%2C%22data%22%3A%7B%22Temperature%5BdegC%5D%22%3A%20%24%7Btemp-c%7D%2C%22Temperature%5BdegF%5D%22%3A%20%24%7Btemp-f%7D%2C%22Battery%5BV%5D%22%3A%24%7Bbattery%7D%2C%22Tilt%5Bdeg%5D%22%3A%24%7Bangle%7D%2C%22Rssi%5BdBm%5D%22%3A%24%7Brssi%7D%2C%22SG%22%3A%24%7Bgravity-sg%7D%2C%22Plato%22%3A%24%7Bgravity-plato%7D%7D%7D%7C" },
{ "id": "UBIDots-Post", "format": "%7B%0A%20%20%20%22temperature%22%3A%20%24%7Btemp%7D%2C%0A%20%20%20%22gravity%22%3A%20%24%7Bgravity%7D%2C%0A%20%20%20%22angle%22%3A%20%24%7Bangle%7D%2C%0A%20%20%20%22battery%22%3A%20%24%7Bbattery%7D%2C%0A%20%20%20%22rssi%22%3A%20%24%7Brssi%7D%0A%7D" } ];
</script>
<div class="row mb-3">
@ -115,9 +117,12 @@
<option value="GravityMon-Post">GravityMon (POST)</option>
<option value="iSpindle-Mqtt">iSpindle (MQTT)</option>
<option value="HomeAssistant-Mqtt">Home Assistant (MQTT)</option>
<option value="UBIDots1-Post">UBIdots - Alternative 1 (POST)</option>
<option value="BrewFatherCustom-Post">Brewfather Custom Endpoint (POST)</option>
<option value="HomeAssistant-Mqtt2">Home Assistant - Auto register sensor (MQTT)</option>
<option value="UBIDots-Post">UBIdots (POST)</option>
<option value="BrewFatherCustom-Post">Brewfather - Custom Endpoint (POST)</option>
<option value="iSpindle-Post">Brewfather - iSpindle Endpoint (POST)</option>
<option value="GravityMon-Get">GravityMon (GET)</option>
<option value="Brewblox-Mqtt">BrewBlox (MQTT)</option>
</select>
<div class="col-sm-4">
<button class="btn btn-secondary" id="copy-btn" data-bs-toggle="tooltip" title="Copy the selected format template to the selected push target">Copy format</button>
@ -235,13 +240,15 @@
doc = doc.replaceAll("${corr-gravity}", cfg["gravity"]);
doc = doc.replaceAll("${angle}", cfg["angle"]);
doc = doc.replaceAll("${tilt}", cfg["angle"]);
doc = doc.replaceAll("${app-ver}", cfg["app-ver"]);
doc = doc.replaceAll("${app-build}", cfg["app-build"]);
// Format in a readable json string.
try {
var json = JSON.parse(doc);
doc = JSON.stringify(json, null, 2);
} catch(e) {
console.log("Not a javascript object!")
console.log("Not a JSON object!")
}
$("#preview").text(doc);

File diff suppressed because one or more lines are too long

View File

@ -73,66 +73,6 @@
</script>
<div class="accordion" id="accordion">
<div class="accordion-item">
<h2 class="accordion-header" id="headingSoftware">
<button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#collapseSoftware" aria-expanded="true" aria-controls="collapseSoftware">
<b>Device</b>
</button>
</h2>
<div id="collapseSoftware" class="accordion-collapse collapse show" aria-labelledby="headingSoftware" data-bs-parent="#accordion">
<div class="accordion-body">
<div class="row mb-3">
<div class="col-md-4 bg-light">Current version:</div>
<div class="col-md-4 bg-light" id="app-ver">Loading...</div>
</div>
<div class="row mb-3" id="h-app-ver-new" hidden>
<div class="col-md-4 bg-light">New version:</div>
<div class="col-md-4 bg-light" id="app-ver-new">Loading...</div>
</div>
<div class="row mb-3">
<div class="col-md-4 bg-light">Host name:</div>
<div class="col-md-4 bg-light" id="mdns">Loading...</div>
</div>
<div class="row mb-3">
<div class="col-md-4 bg-light">Device ID:</div>
<div class="col-md-4 bg-light" id="id">Loading...</div>
</div>
<div class="row mb-3">
<div class="col-md-4 bg-light">Platform:</div>
<div class="col-md-4 bg-light" id="platform">Loading...</div>
</div>
<div class="row mb-3">
<div class="col-md-4 bg-light">SSID:</div>
<div class="col-md-4 bg-light" id="wifi-ssid">Loading...</div>
</div>
<script>
$("#log-btn").click(function(e){
loadLog();
});
setInterval(function() {
loadLog();
}, 3000); //5 seconds
function loadLog() {
$("#logContent").load("/log");
//$("#logContent").load("/test/status.json");
};
</script>
<button class="btn btn-primary btn-sm" type="button" data-bs-toggle="collapse" data-bs-target="#collapseLog" aria-expanded="false" aria-controls="collapseLog" data-bs-toggle="tooltip" title="Load and show the last 10 errors that has occured on the device">
View error log
</button>
<div class="collapse row-margin-10" id="collapseLog">
<div class="card card-body">
<pre><code class="card-text" id="logContent"></code></pre>
</div>
</div>
</div>
</div>
</div>
<h2 class="accordion-header" id="headingData">
<button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#collapseData" aria-expanded="true" aria-controls="collapseData">
@ -173,12 +113,158 @@
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="headingSoftware">
<button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#collapseSoftware" aria-expanded="true" aria-controls="collapseSoftware">
<b>Device</b>
</button>
</h2>
<div id="collapseSoftware" class="accordion-collapse collapse show" aria-labelledby="headingSoftware" data-bs-parent="#accordion">
<div class="accordion-body">
<div class="row mb-3">
<div class="col-md-4 bg-light">Current version:</div>
<div class="col-md-4 bg-light" id="app-ver">Loading...</div>
</div>
<div class="row mb-3" id="h-app-ver-new" hidden>
<div class="col-md-4 bg-light">New version:</div>
<div class="col-md-4 bg-light" id="app-ver-new">Loading...</div>
</div>
<div class="row mb-3">
<div class="col-md-4 bg-light">Host name:</div>
<div class="col-md-4 bg-light" id="mdns">Loading...</div>
</div>
<div class="row mb-3">
<div class="col-md-4 bg-light">Device ID:</div>
<div class="col-md-4 bg-light" id="id">Loading...</div>
</div>
<div class="row mb-3">
<div class="col-md-4 bg-light">Platform:</div>
<div class="col-md-4 bg-light" id="platform">Loading...</div>
</div>
<div class="row mb-3">
<div class="col-md-4 bg-light">SSID:</div>
<div class="col-md-4 bg-light" id="wifi-ssid">Loading...</div>
</div>
<script>
$("#log-btn").click(function(e){
loadLog();
});
setInterval(function() {
loadLog();
}, 5000);
function loadLog() {
$("#logContent").load("/log");
//$("#logContent").load("/test/log");
};
</script>
<button class="btn btn-primary btn-sm" type="button" data-bs-toggle="collapse" data-bs-target="#collapseLog" aria-expanded="false" aria-controls="collapseLog" data-bs-toggle="tooltip" title="Load and show the last 10 errors that has occured on the device">
View error log
</button>
<button class="btn btn-secondary btn-sm" type="button" data-bs-toggle="tooltip" name="github-btn" id="github-btn" title="Go to github and place a issue">
Submit a issue on github
</button>
<button class="btn btn-secondary btn-sm" type="button" data-bs-toggle="collapse" data-bs-target="#collapseSupport" aria-expanded="false" aria-controls="collapseSupport" data-bs-toggle="tooltip" name="support-btn" id="support-btn" title="Collect data relevant for a support case">
Gather support information
</button>
<div class="collapse row-margin-10" id="collapseLog">
<div class="card card-body">
<pre><code class="card-text" id="logContent"></code></pre>
</div>
</div>
<div class="collapse row-margin-10" id="collapseSupport">
<div class="card card-body">
<pre><code class="card-text" id="supportContent"></code></pre>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript">
var debug = {};
window.onload = start;
$("#github-btn").click(function(e){
window.location.href = "https://github.com/mp-se/gravitymon/issues";
});
$("#support-btn").click(function(e){
$('#spinner').show();
var url = "/api/config";
//var url = "/test/config.json";
$.getJSON(url, function (cfg) {
debug = {};
debug["mdns"] = cfg["mdns"];
debug["id"] = cfg["id"];
debug["sleep-interval"] = cfg["sleep-interval"];
debug["temp-format"] = cfg["temp-format"];
debug["gravity-format"] = cfg["gravity-format"];
debug["gravity-temp-adjustment"] = cfg["gravity-temp-adjustment"];
debug["voltage-factor"] = cfg["voltage-factor"];
debug["platform"] = cfg["platform"];
debug["ble"] = cfg["ble"];
debug["gyro-temp"] = cfg["gyro-temp"];
debug["gyro-calibration-data"] = cfg["gyro-calibration-data"];
debug["temp-adjustment-value"] = cfg["temp-adjustment-value"];
var url = "/api/status";
//var url = "/test/status.json";
$.getJSON(url, function (cfg) {
debug["runtime-average"] = cfg["runtime-average"];
debug["rssi"] = cfg["rssi"];
debug["app-ver"] = cfg["app-ver"];
debug["app-build"] = cfg["app-build"];
});
var url = "/api/config/format";
//var url = "/test/format.json";
$.getJSON(url, function (cfg) {
debug["formats"] = cfg;
var url = "/api/config/advanced";
//var url = "/test/adv.json";
$.getJSON(url, function (cfg) {
debug["advanced"] = cfg;
var url = "/api/upload";
//var url = "/test/upload.json";
$.getJSON(url, function (cfg) {
debug["files"] = cfg;
var url = "/log";
//var url = "/test/log";
$.ajax({url: url, method: 'get', success: function (data) {
debug["log"] = data.split("\n");
var s = JSON.stringify(debug, null, 2);
$("#supportContent").text( s );
$('#spinner').hide();
//navigator.clipboard.writeText(s);
//alert("Support information copied to clipboard");
}
});
});
});
});
});
});
$("#sleep-mode").click(function(e){
console.log( "Blocking sleep mode = " + $("#sleep-mode").is(":checked"));
$.ajax( {

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,399 @@
/****************************************************************************************************************************
ESP_DoubleResetDetector.h
For ESP8266 / ESP32 boards
ESP_DoubleResetDetector is a library for the ESP8266/Arduino platform
to enable trigger configure mode by resetting ESP32 / ESP8266 twice.
Forked from DataCute https://github.com/datacute/DoubleResetDetector
Built by Khoi Hoang https://github.com/khoih-prog/ESP_DoubleResetDetector
Licensed under MIT license
Version: 1.3.1
Version Modified By Date Comments
------- ----------- ---------- -----------
1.0.0 K Hoang 15/12/2019 Initial coding
1.0.1 K Hoang 30/12/2019 Now can use EEPROM or SPIFFS for both ESP8266 and ESP32. RTC still OK for ESP8266
1.0.2 K Hoang 10/04/2020 Fix bug by left-over cpp file and in example.
1.0.3 K Hoang 13/05/2020 Update to use LittleFS for ESP8266 core 2.7.1+
1.1.0 K Hoang 04/12/2020 Add support to LittleFS for ESP32 using LITTLEFS Library
1.1.1 K Hoang 28/12/2020 Suppress all possible compiler warnings
1.1.2 K Hoang 10/10/2021 Update `platform.ini` and `library.json`
1.2.0 K Hoang 26/11/2021 Auto detect ESP32 core and use either built-in LittleFS or LITTLEFS library
1.2.1 K Hoang 26/11/2021 Fix compile error for ESP32 core v1.0.5-
1.3.0 K Hoang 10/02/2022 Add support to new ESP32-S3
1.3.1 K Hoang 04/03/2022 Add waitingForDRD() function to signal in DRD wating period
*****************************************************************************************************************************/
#pragma once
#ifndef ESP_DoubleResetDetector_H
#define ESP_DoubleResetDetector_H
#ifndef DOUBLERESETDETECTOR_DEBUG
#define DOUBLERESETDETECTOR_DEBUG false
#endif
#if defined(ARDUINO) && (ARDUINO >= 100)
#include <Arduino.h>
#else
#include <WProgram.h>
#endif
#ifndef ESP_DOUBLE_RESET_DETECTOR_VERSION
#define ESP_DOUBLE_RESET_DETECTOR_VERSION "ESP_DoubleResetDetector v1.3.1"
#define ESP_DOUBLE_RESET_DETECTOR_VERSION_MAJOR 1
#define ESP_DOUBLE_RESET_DETECTOR_VERSION_MINOR 3
#define ESP_DOUBLE_RESET_DETECTOR_VERSION_PATCH 1
#define ESP_DOUBLE_RESET_DETECTOR_VERSION_INT 1003001
#endif
#define ESP_DOUBLERESETDETECTOR_VERSION ESP_DOUBLE_RESET_DETECTOR_VERSION
//#define ESP_DRD_USE_EEPROM false
//#define ESP_DRD_USE_LITTLEFS false
//#define ESP_DRD_USE_SPIFFS false
//#define ESP8266_DRD_USE_RTC false //true
#ifdef ESP32
#if (!ESP_DRD_USE_EEPROM && !ESP_DRD_USE_SPIFFS && !ESP_DRD_USE_LITTLEFS)
#if (DOUBLERESETDETECTOR_DEBUG)
#warning Neither EEPROM, SPIFFS nor LittleFS selected. Default to EEPROM
#endif
#ifdef ESP_DRD_USE_EEPROM
#undef ESP_DRD_USE_EEPROM
#define ESP_DRD_USE_EEPROM true
#endif
#endif
#endif
#ifdef ESP8266
#if (!ESP8266_DRD_USE_RTC && !ESP_DRD_USE_EEPROM && !ESP_DRD_USE_SPIFFS && !ESP_DRD_USE_LITTLEFS)
#if (DOUBLERESETDETECTOR_DEBUG)
#warning Neither RTC, EEPROM, LITTLEFS nor SPIFFS selected. Default to EEPROM
#endif
#ifdef ESP_DRD_USE_EEPROM
#undef ESP_DRD_USE_EEPROM
#define ESP_DRD_USE_EEPROM true
#endif
#endif
#endif
//default to use EEPROM, otherwise, use LITTLEFS (higher priority), then SPIFFS
#if ESP_DRD_USE_EEPROM
#include <EEPROM.h>
#define FLAG_DATA_SIZE 4
#ifndef EEPROM_SIZE
#define EEPROM_SIZE 512
#endif
#ifndef EEPROM_START
#define EEPROM_START 256
#endif
#elif ( ESP_DRD_USE_LITTLEFS || ESP_DRD_USE_SPIFFS )
#include <FS.h>
#ifdef ESP32
#if ESP_DRD_USE_LITTLEFS
// Check cores/esp32/esp_arduino_version.h and cores/esp32/core_version.h
//#if ( ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(2, 0, 0) ) //(ESP_ARDUINO_VERSION_MAJOR >= 2)
#if ( defined(ESP_ARDUINO_VERSION_MAJOR) && (ESP_ARDUINO_VERSION_MAJOR >= 2) )
#if (DOUBLERESETDETECTOR_DEBUG)
#warning Using ESP32 Core 1.0.6 or 2.0.0+
#endif
// The library has been merged into esp32 core from release 1.0.6
#include <LittleFS.h>
#define FileFS LittleFS
#define FS_Name "LittleFS"
#else
#if (DOUBLERESETDETECTOR_DEBUG)
#warning Using ESP32 Core 1.0.5-. You must install LITTLEFS library
#endif
// The library has been merged into esp32 core from release 1.0.6
#include <LITTLEFS.h> // https://github.com/lorol/LITTLEFS
#define FileFS LITTLEFS
#define FS_Name "LittleFS"
#endif
#else
#include "SPIFFS.h"
// ESP32 core 1.0.4 still uses SPIFFS
#define FileFS SPIFFS
#endif
#else
// From ESP8266 core 2.7.1
#include <LittleFS.h>
#if ESP_DRD_USE_LITTLEFS
#define FileFS LittleFS
#else
#define FileFS SPIFFS
#endif
#endif // #if ESP_DRD_USE_EEPROM
#define DRD_FILENAME "/drd.dat"
#endif //#if ESP_DRD_USE_EEPROM
#define DOUBLERESETDETECTOR_FLAG_SET 0xD0D01234
#define DOUBLERESETDETECTOR_FLAG_CLEAR 0xD0D04321
class DoubleResetDetector
{
public:
DoubleResetDetector(int timeout, int address)
{
#if ESP_DRD_USE_EEPROM
#if (DOUBLERESETDETECTOR_DEBUG)
Serial.printf("EEPROM size = %d, start = %d\n", EEPROM_SIZE, EEPROM_START);
#endif
EEPROM.begin(EEPROM_SIZE);
#elif ( ESP_DRD_USE_LITTLEFS || ESP_DRD_USE_SPIFFS )
// LittleFS / SPIFFS code
if (!FileFS.begin())
{
#if (DOUBLERESETDETECTOR_DEBUG)
#if ESP_DRD_USE_LITTLEFS
Serial.println("LittleFS failed!. Please use SPIFFS or EEPROM.");
#else
Serial.println("SPIFFS failed!. Please use LittleFS or EEPROM.");
#endif
#endif
}
#else
#ifdef ESP8266
//RTC only for ESP8266
#endif
#endif
this->timeout = timeout * 1000;
this->address = address;
doubleResetDetected = false;
waitingForDoubleReset = false;
};
bool detectDoubleReset()
{
doubleResetDetected = detectRecentlyResetFlag();
if (doubleResetDetected)
{
#if (DOUBLERESETDETECTOR_DEBUG)
Serial.println("doubleResetDetected");
#endif
clearRecentlyResetFlag();
}
else
{
#if (DOUBLERESETDETECTOR_DEBUG)
Serial.println("No doubleResetDetected");
#endif
setRecentlyResetFlag();
waitingForDoubleReset = true;
}
return doubleResetDetected;
};
bool waitingForDRD()
{
return waitingForDoubleReset;
}
void loop()
{
if (waitingForDoubleReset && millis() > timeout)
{
#if (DOUBLERESETDETECTOR_DEBUG)
Serial.println("Stop doubleResetDetecting");
#endif
stop();
}
};
void stop()
{
clearRecentlyResetFlag();
waitingForDoubleReset = false;
};
bool doubleResetDetected;
private:
uint32_t DOUBLERESETDETECTOR_FLAG;
unsigned long timeout;
int address;
bool waitingForDoubleReset;
bool detectRecentlyResetFlag()
{
#if (ESP_DRD_USE_EEPROM)
EEPROM.get(EEPROM_START, DOUBLERESETDETECTOR_FLAG);
doubleResetDetectorFlag = DOUBLERESETDETECTOR_FLAG;
#if (DOUBLERESETDETECTOR_DEBUG)
Serial.printf("EEPROM Flag read = 0x%X\n", DOUBLERESETDETECTOR_FLAG);
#endif
#elif ( ESP_DRD_USE_LITTLEFS || ESP_DRD_USE_SPIFFS )
// LittleFS / SPIFFS code
if (FileFS.exists(DRD_FILENAME))
{
// if config file exists, load
File file = FileFS.open(DRD_FILENAME, "r");
if (!file)
{
#if (DOUBLERESETDETECTOR_DEBUG)
Serial.println("Loading config file failed");
#endif
}
file.readBytes((char *) &DOUBLERESETDETECTOR_FLAG, sizeof(DOUBLERESETDETECTOR_FLAG));
doubleResetDetectorFlag = DOUBLERESETDETECTOR_FLAG;
#if (DOUBLERESETDETECTOR_DEBUG)
#if ESP_DRD_USE_LITTLEFS
Serial.printf("LittleFS Flag read = 0x%X\n", DOUBLERESETDETECTOR_FLAG);
#else
Serial.printf("SPIFFS Flag read = 0x%X\n", DOUBLERESETDETECTOR_FLAG);
#endif
#endif
file.close();
}
#else
#ifdef ESP8266
//RTC only for ESP8266
ESP.rtcUserMemoryRead(address, &doubleResetDetectorFlag, sizeof(doubleResetDetectorFlag));
#endif
#endif
doubleResetDetected = (doubleResetDetectorFlag == DOUBLERESETDETECTOR_FLAG_SET);
return doubleResetDetected;
};
void setRecentlyResetFlag()
{
doubleResetDetectorFlag = DOUBLERESETDETECTOR_FLAG_SET;
DOUBLERESETDETECTOR_FLAG = DOUBLERESETDETECTOR_FLAG_SET;
#if (ESP_DRD_USE_EEPROM)
EEPROM.put(EEPROM_START, DOUBLERESETDETECTOR_FLAG);
EEPROM.commit();
#if (DOUBLERESETDETECTOR_DEBUG)
delay(1000);
EEPROM.get(EEPROM_START, DOUBLERESETDETECTOR_FLAG);
Serial.printf("SetFlag write = 0x%X\n", DOUBLERESETDETECTOR_FLAG);
#endif
#elif ( ESP_DRD_USE_LITTLEFS || ESP_DRD_USE_SPIFFS )
// LittleFS / SPIFFS code
File file = FileFS.open(DRD_FILENAME, "w");
#if (DOUBLERESETDETECTOR_DEBUG)
Serial.println("Saving config file...");
#endif
if (file)
{
file.write((uint8_t *) &DOUBLERESETDETECTOR_FLAG, sizeof(DOUBLERESETDETECTOR_FLAG));
file.close();
#if (DOUBLERESETDETECTOR_DEBUG)
Serial.println("Saving config file OK");
#endif
}
else
{
#if (DOUBLERESETDETECTOR_DEBUG)
Serial.println("Saving config file failed");
#endif
}
#else
#ifdef ESP8266
//RTC only for ESP8266
ESP.rtcUserMemoryWrite(address, &doubleResetDetectorFlag, sizeof(doubleResetDetectorFlag));
#endif
#endif
};
void clearRecentlyResetFlag()
{
doubleResetDetectorFlag = DOUBLERESETDETECTOR_FLAG_CLEAR;
DOUBLERESETDETECTOR_FLAG = DOUBLERESETDETECTOR_FLAG_CLEAR;
#if (ESP_DRD_USE_EEPROM)
//DOUBLERESETDETECTOR_FLAG = DOUBLERESETDETECTOR_FLAG_CLEAR;
EEPROM.put(EEPROM_START, DOUBLERESETDETECTOR_FLAG);
EEPROM.commit();
#if (DOUBLERESETDETECTOR_DEBUG)
delay(1000);
EEPROM.get(EEPROM_START, DOUBLERESETDETECTOR_FLAG);
Serial.printf("ClearFlag write = 0x%X\n", DOUBLERESETDETECTOR_FLAG);
#endif
#elif ( ESP_DRD_USE_LITTLEFS || ESP_DRD_USE_SPIFFS )
// LittleFS / SPIFFS code
File file = FileFS.open(DRD_FILENAME, "w");
#if (DOUBLERESETDETECTOR_DEBUG)
Serial.println("Saving config file...");
#endif
if (file)
{
file.write((uint8_t *) &DOUBLERESETDETECTOR_FLAG, sizeof(DOUBLERESETDETECTOR_FLAG));
file.close();
#if (DOUBLERESETDETECTOR_DEBUG)
Serial.println("Saving config file OK");
#endif
}
else
{
#if (DOUBLERESETDETECTOR_DEBUG)
Serial.println("Saving config file failed");
#endif
}
#else
#ifdef ESP8266
//RTC only for ESP8266
ESP.rtcUserMemoryWrite(address, &doubleResetDetectorFlag, sizeof(doubleResetDetectorFlag));
#endif
#endif
};
uint32_t doubleResetDetectorFlag;
};
#endif // ESP_DoubleResetDetector_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,72 @@
/****************************************************************************************************************************
ESP_WiFiManager.h
For ESP8266 / ESP32 boards
ESP_WiFiManager is a library for the ESP8266/Arduino platform
(https://github.com/esp8266/Arduino) to enable easy
configuration and reconfiguration of WiFi credentials using a Captive Portal
inspired by:
http://www.esp8266.com/viewtopic.php?f=29&t=2520
https://github.com/chriscook8/esp-arduino-apboot
https://github.com/esp8266/Arduino/blob/master/libraries/DNSServer/examples/CaptivePortalAdvanced/
Modified from Tzapu https://github.com/tzapu/WiFiManager
and from Ken Taylor https://github.com/kentaylor
Built by Khoi Hoang https://github.com/khoih-prog/ESP_WiFiManager
Licensed under MIT license
Version: 1.9.0
Version Modified By Date Comments
------- ----------- ---------- -----------
1.0.0 K Hoang 07/10/2019 Initial coding
1.0.1 K Hoang 13/12/2019 Fix bug. Add features. Add support for ESP32
1.0.2 K Hoang 19/12/2019 Fix bug thatkeeps ConfigPortal in endless loop if Portal/Router SSID or Password is NULL.
1.0.3 K Hoang 05/01/2020 Option not displaying AvailablePages in Info page. Enhance README.md. Modify examples
1.0.4 K Hoang 07/01/2020 Add RFC952 setHostname feature.
1.0.5 K Hoang 15/01/2020 Add configurable DNS feature. Thanks to @Amorphous of https://community.blynk.cc
1.0.6 K Hoang 03/02/2020 Add support for ArduinoJson version 6.0.0+ ( tested with v6.14.1 )
1.0.7 K Hoang 13/04/2020 Reduce start time, fix SPIFFS bug in examples, update README.md
1.0.8 K Hoang 10/06/2020 Fix STAstaticIP issue. Restructure code. Add LittleFS support for ESP8266 core 2.7.1+
1.0.9 K Hoang 29/07/2020 Fix ESP32 STAstaticIP bug. Permit changing from DHCP <-> static IP using Config Portal.
Add, enhance examples (fix MDNS for ESP32)
1.0.10 K Hoang 08/08/2020 Add more features to Config Portal. Use random WiFi AP channel to avoid conflict.
1.0.11 K Hoang 17/08/2020 Add CORS feature. Fix bug in softAP, autoConnect, resetSettings.
1.1.0 K Hoang 28/08/2020 Add MultiWiFi feature to autoconnect to best WiFi at runtime
1.1.1 K Hoang 30/08/2020 Add setCORSHeader function to allow flexible CORS. Fix typo and minor improvement.
1.1.2 K Hoang 17/08/2020 Fix bug. Add example.
1.2.0 K Hoang 09/10/2020 Restore cpp code besides Impl.h code to use if linker error. Fix bug.
1.3.0 K Hoang 04/12/2020 Add LittleFS support to ESP32 using LITTLEFS Library
1.4.1 K Hoang 22/12/2020 Fix staticIP not saved. Add functions. Add complex examples. Sync with ESPAsync_WiFiManager
1.4.2 K Hoang 14/01/2021 Fix examples' bug not using saved WiFi Credentials after losing all WiFi connections.
1.4.3 K Hoang 23/01/2021 Fix examples' bug not saving Static IP in certain cases.
1.5.0 K Hoang 12/02/2021 Add support to new ESP32-S2
1.5.1 K Hoang 26/03/2021 Fix compiler error if setting Compiler Warnings to All. Retest with esp32 core v1.0.6
1.5.2 K Hoang 08/04/2021 Fix example misleading messages.
1.5.3 K Hoang 13/04/2021 Add dnsServer error message.
1.6.0 K Hoang 20/04/2021 Add support to new ESP32-C3 using SPIFFS or EEPROM
1.6.1 K Hoang 25/04/2021 Fix MultiWiFi bug. Fix captive-portal bug if CP AP address is not default 192.168.4.1
1.7.0 K Hoang 06/05/2021 Set _timezoneName. Add support to new ESP32-S2 (METRO_ESP32S2, FUNHOUSE_ESP32S2, etc.)
1.7.1 K Hoang 08/05/2021 Fix Json bug. Fix timezoneName not displayed in Info page.
1.7.2 K Hoang 08/05/2021 Fix warnings with ESP8266 core v3.0.0
1.7.3 K Hoang 29/07/2021 Fix MultiWiFi connection issue with ESP32 core v2.0.0-rc1+
1.7.4 K Hoang 13/08/2021 Add WiFi scanning of hidden SSIDs
1.7.5 K Hoang 10/10/2021 Update `platform.ini` and `library.json`
1.7.6 K Hoang 26/11/2021 Auto detect ESP32 core and use either built-in LittleFS or LITTLEFS library
1.7.7 K Hoang 26/11/2021 Fix compile error for ESP32 core v1.0.5-
1.7.8 K Hoang 30/11/2021 Fix bug to permit using HTTP port different from 80. Fix bug
1.8.0 K Hoang 29/12/2021 Fix `multiple-definitions` linker error and weird bug related to src_cpp
1.9.0 K Hoang 17/01/2022 Enable compatibility with old code to include only ESP_WiFiManager.h
*****************************************************************************************************************************/
#pragma once
#ifndef ESP_WiFiManager_h
#define ESP_WiFiManager_h
#include <ESP_WiFiManager.hpp> //https://github.com/khoih-prog/ESP_WiFiManager
#include <ESP_WiFiManager-Impl.h> //https://github.com/khoih-prog/ESP_WiFiManager
#endif // ESP_WiFiManager_h

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,128 @@
/****************************************************************************************************************************
ESP_WiFiManager_Debug.h
For ESP8266 / ESP32 boards
ESP_WiFiManager is a library for the ESP8266/Arduino platform
(https://github.com/esp8266/Arduino) to enable easy
configuration and reconfiguration of WiFi credentials using a Captive Portal
inspired by:
http://www.esp8266.com/viewtopic.php?f=29&t=2520
https://github.com/chriscook8/esp-arduino-apboot
https://github.com/esp8266/Arduino/blob/master/libraries/DNSServer/examples/CaptivePortalAdvanced/
Modified from Tzapu https://github.com/tzapu/WiFiManager
and from Ken Taylor https://github.com/kentaylor
Built by Khoi Hoang https://github.com/khoih-prog/ESP_WiFiManager
Licensed under MIT license
Version: 1.9.0
Version Modified By Date Comments
------- ----------- ---------- -----------
1.0.0 K Hoang 07/10/2019 Initial coding
1.0.1 K Hoang 13/12/2019 Fix bug. Add features. Add support for ESP32
1.0.2 K Hoang 19/12/2019 Fix bug thatkeeps ConfigPortal in endless loop if Portal/Router SSID or Password is NULL.
1.0.3 K Hoang 05/01/2020 Option not displaying AvailablePages in Info page. Enhance README.md. Modify examples
1.0.4 K Hoang 07/01/2020 Add RFC952 setHostname feature.
1.0.5 K Hoang 15/01/2020 Add configurable DNS feature. Thanks to @Amorphous of https://community.blynk.cc
1.0.6 K Hoang 03/02/2020 Add support for ArduinoJson version 6.0.0+ ( tested with v6.14.1 )
1.0.7 K Hoang 13/04/2020 Reduce start time, fix SPIFFS bug in examples, update README.md
1.0.8 K Hoang 10/06/2020 Fix STAstaticIP issue. Restructure code. Add LittleFS support for ESP8266 core 2.7.1+
1.0.9 K Hoang 29/07/2020 Fix ESP32 STAstaticIP bug. Permit changing from DHCP <-> static IP using Config Portal.
Add, enhance examples (fix MDNS for ESP32)
1.0.10 K Hoang 08/08/2020 Add more features to Config Portal. Use random WiFi AP channel to avoid conflict.
1.0.11 K Hoang 17/08/2020 Add CORS feature. Fix bug in softAP, autoConnect, resetSettings.
1.1.0 K Hoang 28/08/2020 Add MultiWiFi feature to autoconnect to best WiFi at runtime
1.1.1 K Hoang 30/08/2020 Add setCORSHeader function to allow flexible CORS. Fix typo and minor improvement.
1.1.2 K Hoang 17/08/2020 Fix bug. Add example.
1.2.0 K Hoang 09/10/2020 Restore cpp code besides Impl.h code to use if linker error. Fix bug.
1.3.0 K Hoang 04/12/2020 Add LittleFS support to ESP32 using LITTLEFS Library
1.4.1 K Hoang 22/12/2020 Fix staticIP not saved. Add functions. Add complex examples. Sync with ESPAsync_WiFiManager
1.4.2 K Hoang 14/01/2021 Fix examples' bug not using saved WiFi Credentials after losing all WiFi connections.
1.4.3 K Hoang 23/01/2021 Fix examples' bug not saving Static IP in certain cases.
1.5.0 K Hoang 12/02/2021 Add support to new ESP32-S2
1.5.1 K Hoang 26/03/2021 Fix compiler error if setting Compiler Warnings to All. Retest with esp32 core v1.0.6
1.5.2 K Hoang 08/04/2021 Fix example misleading messages.
1.5.3 K Hoang 13/04/2021 Add dnsServer error message.
1.6.0 K Hoang 20/04/2021 Add support to new ESP32-C3 using SPIFFS or EEPROM
1.6.1 K Hoang 25/04/2021 Fix MultiWiFi bug. Fix captive-portal bug if CP AP address is not default 192.168.4.1
1.7.0 K Hoang 06/05/2021 Set _timezoneName. Add support to new ESP32-S2 (METRO_ESP32S2, FUNHOUSE_ESP32S2, etc.)
1.7.1 K Hoang 08/05/2021 Fix Json bug. Fix timezoneName not displayed in Info page.
1.7.2 K Hoang 08/05/2021 Fix warnings with ESP8266 core v3.0.0
1.7.3 K Hoang 29/07/2021 Fix MultiWiFi connection issue with ESP32 core v2.0.0-rc1+
1.7.4 K Hoang 13/08/2021 Add WiFi scanning of hidden SSIDs
1.7.5 K Hoang 10/10/2021 Update `platform.ini` and `library.json`
1.7.6 K Hoang 26/11/2021 Auto detect ESP32 core and use either built-in LittleFS or LITTLEFS library
1.7.7 K Hoang 26/11/2021 Fix compile error for ESP32 core v1.0.5-
1.7.8 K Hoang 30/11/2021 Fix bug to permit using HTTP port different from 80. Fix bug
1.8.0 K Hoang 29/12/2021 Fix `multiple-definitions` linker error and weird bug related to src_cpp
1.9.0 K Hoang 17/01/2022 Enable compatibility with old code to include only ESP_WiFiManager.h
*****************************************************************************************************************************/
#pragma once
#ifndef ESP_WiFiManager_Debug_H
#define ESP_WiFiManager_Debug_H
#ifdef WIFIMGR_DEBUG_PORT
#define WM_DBG_PORT WIFIMGR_DEBUG_PORT
#else
#define WM_DBG_PORT Serial
#endif
// Change _WIFIMGR_LOGLEVEL_ to set tracing and logging verbosity
// 0: DISABLED: no logging
// 1: ERROR: errors
// 2: WARN: errors and warnings
// 3: INFO: errors, warnings and informational (default)
// 4: DEBUG: errors, warnings, informational and debug
#ifndef _WIFIMGR_LOGLEVEL_
#define _WIFIMGR_LOGLEVEL_ 0
#endif
const char WM_MARK[] = "[WM] ";
const char WM_SP[] = " ";
#define WM_PRINT WM_DBG_PORT.print
#define WM_PRINTLN WM_DBG_PORT.println
#define WM_PRINT_MARK WM_PRINT(WM_MARK)
#define WM_PRINT_SP WM_PRINT(WM_SP)
////////////////////////////////////////////////////
#define LOGERROR(x) if(_WIFIMGR_LOGLEVEL_>0) { WM_PRINT_MARK; WM_PRINTLN(x); }
#define LOGERROR0(x) if(_WIFIMGR_LOGLEVEL_>0) { WM_PRINT(x); }
#define LOGERROR1(x,y) if(_WIFIMGR_LOGLEVEL_>0) { WM_PRINT_MARK; WM_PRINT(x); WM_PRINT_SP; WM_PRINTLN(y); }
#define LOGERROR2(x,y,z) if(_WIFIMGR_LOGLEVEL_>0) { WM_PRINT_MARK; WM_PRINT(x); WM_PRINT_SP; WM_PRINT(y); WM_PRINT_SP; WM_PRINTLN(z); }
#define LOGERROR3(x,y,z,w) if(_WIFIMGR_LOGLEVEL_>0) { WM_PRINT_MARK; WM_PRINT(x); WM_PRINT_SP; WM_PRINT(y); WM_PRINT_SP; WM_PRINT(z); WM_PRINT_SP; WM_PRINTLN(w); }
////////////////////////////////////////////////////
#define LOGWARN(x) if(_WIFIMGR_LOGLEVEL_>1) { WM_PRINT_MARK; WM_PRINTLN(x); }
#define LOGWARN0(x) if(_WIFIMGR_LOGLEVEL_>1) { WM_PRINT(x); }
#define LOGWARN1(x,y) if(_WIFIMGR_LOGLEVEL_>1) { WM_PRINT_MARK; WM_PRINT(x); WM_PRINT_SP; WM_PRINTLN(y); }
#define LOGWARN2(x,y,z) if(_WIFIMGR_LOGLEVEL_>1) { WM_PRINT_MARK; WM_PRINT(x); WM_PRINT_SP; WM_PRINT(y); WM_PRINT_SP; WM_PRINTLN(z); }
#define LOGWARN3(x,y,z,w) if(_WIFIMGR_LOGLEVEL_>1) { WM_PRINT_MARK; WM_PRINT(x); WM_PRINT_SP; WM_PRINT(y); WM_PRINT_SP; WM_PRINT(z); WM_PRINT_SP; WM_PRINTLN(w); }
////////////////////////////////////////////////////
#define LOGINFO(x) if(_WIFIMGR_LOGLEVEL_>2) { WM_PRINT_MARK; WM_PRINTLN(x); }
#define LOGINFO0(x) if(_WIFIMGR_LOGLEVEL_>2) { WM_PRINT(x); }
#define LOGINFO1(x,y) if(_WIFIMGR_LOGLEVEL_>2) { WM_PRINT_MARK; WM_PRINT(x); WM_PRINT_SP; WM_PRINTLN(y); }
#define LOGINFO2(x,y,z) if(_WIFIMGR_LOGLEVEL_>2) { WM_PRINT_MARK; WM_PRINT(x); WM_PRINT_SP; WM_PRINT(y); WM_PRINT_SP; WM_PRINTLN(z); }
#define LOGINFO3(x,y,z,w) if(_WIFIMGR_LOGLEVEL_>2) { WM_PRINT_MARK; WM_PRINT(x); WM_PRINT_SP; WM_PRINT(y); WM_PRINT_SP; WM_PRINT(z); WM_PRINT_SP; WM_PRINTLN(w); }
////////////////////////////////////////////////////
#define LOGDEBUG(x) if(_WIFIMGR_LOGLEVEL_>3) { WM_PRINT_MARK; WM_PRINTLN(x); }
#define LOGDEBUG0(x) if(_WIFIMGR_LOGLEVEL_>3) { WM_PRINT(x); }
#define LOGDEBUG1(x,y) if(_WIFIMGR_LOGLEVEL_>3) { WM_PRINT_MARK; WM_PRINT(x); WM_PRINT_SP; WM_PRINTLN(y); }
#define LOGDEBUG2(x,y,z) if(_WIFIMGR_LOGLEVEL_>3) { WM_PRINT_MARK; WM_PRINT(x); WM_PRINT_SP; WM_PRINT(y); WM_PRINT_SP; WM_PRINTLN(z); }
#define LOGDEBUG3(x,y,z,w) if(_WIFIMGR_LOGLEVEL_>3) { WM_PRINT_MARK; WM_PRINT(x); WM_PRINT_SP; WM_PRINT(y); WM_PRINT_SP; WM_PRINT(z); WM_PRINT_SP; WM_PRINTLN(w); }
////////////////////////////////////////////////////
#endif //ESP_WiFiManager_Debug_H

File diff suppressed because it is too large Load Diff

View File

@ -195,11 +195,7 @@ uint8_t OneWire::reset(void)
// Write a bit. Port and bit is used to cut lookup time and provide
// more certain timing.
//
#if defined(ARDUINO_ARCH_ESP32)
void IRAM_ATTR OneWire::write_bit(uint8_t v)
#else
void OneWire::write_bit(uint8_t v)
#endif
{
IO_REG_TYPE mask IO_REG_MASK_ATTR = bitmask;
volatile IO_REG_TYPE *reg IO_REG_BASE_ATTR = baseReg;
@ -227,11 +223,7 @@ void OneWire::write_bit(uint8_t v)
// Read a bit. Port and bit is used to cut lookup time and provide
// more certain timing.
//
#if defined(ARDUINO_ARCH_ESP32)
uint8_t IRAM_ATTR OneWire::read_bit(void)
#else
uint8_t OneWire::read_bit(void)
#endif
{
IO_REG_TYPE mask IO_REG_MASK_ATTR = bitmask;
volatile IO_REG_TYPE *reg IO_REG_BASE_ATTR = baseReg;
@ -585,4 +577,4 @@ uint16_t OneWire::crc16(const uint8_t* input, uint16_t len, uint16_t crc)
}
#endif
#endif
#endif

View File

@ -99,18 +99,10 @@ class OneWire
// Write a bit. The bus is always left powered at the end, see
// note in write() about that.
#if defined (ARDUINO_ARCH_ESP32)
void IRAM_ATTR write_bit(uint8_t v);
#else
void write_bit(uint8_t v);
#endif
// Read a bit.
#if defined (ARDUINO_ARCH_ESP32)
uint8_t IRAM_ATTR read_bit(void);
#else
uint8_t read_bit(void);
#endif
// Stop forcing power onto the bus. You only need to do this if
// you used the 'power' flag to write() or used a write_bit() call
@ -187,4 +179,4 @@ class OneWire
#endif
#endif // __cplusplus
#endif // OneWire_h
#endif // OneWire_h

View File

@ -127,10 +127,14 @@
static inline __attribute__((always_inline))
IO_REG_TYPE directRead(IO_REG_TYPE pin)
{
#if CONFIG_IDF_TARGET_ESP32C3
return (GPIO.in.val >> pin) & 0x1;
#else // plain ESP32
if ( pin < 32 )
return (GPIO.in >> pin) & 0x1;
else if ( pin < 40 )
else if ( pin < 46 )
return (GPIO.in1.val >> (pin - 32)) & 0x1;
#endif
return 0;
}
@ -138,38 +142,38 @@ IO_REG_TYPE directRead(IO_REG_TYPE pin)
static inline __attribute__((always_inline))
void directWriteLow(IO_REG_TYPE pin)
{
#if CONFIG_IDF_TARGET_ESP32C3
GPIO.out_w1tc.val = ((uint32_t)1 << pin);
#else // plain ESP32
if ( pin < 32 )
GPIO.out_w1tc = ((uint32_t)1 << pin);
else if ( pin < 34 )
else if ( pin < 46 )
GPIO.out1_w1tc.val = ((uint32_t)1 << (pin - 32));
#endif
}
static inline __attribute__((always_inline))
void directWriteHigh(IO_REG_TYPE pin)
{
#if CONFIG_IDF_TARGET_ESP32C3
GPIO.out_w1ts.val = ((uint32_t)1 << pin);
#else // plain ESP32
if ( pin < 32 )
GPIO.out_w1ts = ((uint32_t)1 << pin);
else if ( pin < 34 )
else if ( pin < 46 )
GPIO.out1_w1ts.val = ((uint32_t)1 << (pin - 32));
#endif
}
static inline __attribute__((always_inline))
void directModeInput(IO_REG_TYPE pin)
{
#if CONFIG_IDF_TARGET_ESP32C3
GPIO.enable_w1tc.val = ((uint32_t)1 << (pin));
#else
if ( digitalPinIsValid(pin) )
{
#if defined(ESP_ARDUINO_VERSION)
#if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(2, 0, 0)
int pin_io = rtc_io_number_get((gpio_num_t)pin);
uint32_t rtc_reg(rtc_io_desc[pin_io].reg);
if ( rtc_reg ) // RTC pins PULL settings
{
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_io_desc[pin_io].mux);
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_io_desc[pin_io].pullup | rtc_io_desc[pin_io].pulldown);
}
#endif
#else
#if ESP_IDF_VERSION_MAJOR < 4 // IDF 3.x ESP32/PICO-D4
uint32_t rtc_reg(rtc_gpio_desc[pin].reg);
if ( rtc_reg ) // RTC pins PULL settings
@ -177,40 +181,25 @@ void directModeInput(IO_REG_TYPE pin)
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].mux);
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].pullup | rtc_gpio_desc[pin].pulldown);
}
#endif
#endif
// Input
if ( pin < 32 )
GPIO.enable_w1tc = ((uint32_t)1 << pin);
else
GPIO.enable1_w1tc.val = ((uint32_t)1 << (pin - 32));
uint32_t pinFunction((uint32_t)2 << FUN_DRV_S); // what are the drivers?
pinFunction |= FUN_IE; // input enable but required for output as well?
pinFunction |= ((uint32_t)2 << MCU_SEL_S);
ESP_REG(DR_REG_IO_MUX_BASE + esp32_gpioMux[pin].reg) = pinFunction;
GPIO.pin[pin].val = 0;
}
#endif
}
static inline __attribute__((always_inline))
void directModeOutput(IO_REG_TYPE pin)
{
#if CONFIG_IDF_TARGET_ESP32C3
GPIO.enable_w1ts.val = ((uint32_t)1 << (pin));
#else
if ( digitalPinIsValid(pin) && pin <= 33 ) // pins above 33 can be only inputs
{
#if defined(ESP_ARDUINO_VERSION)
#if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(2, 0, 0)
int pin_io = rtc_io_number_get((gpio_num_t)pin);
uint32_t rtc_reg(rtc_io_desc[pin_io].reg);
if ( rtc_reg ) // RTC pins PULL settings
{
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_io_desc[pin_io].mux);
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_io_desc[pin_io].pullup | rtc_io_desc[pin_io].pulldown);
}
#endif
#else
#if ESP_IDF_VERSION_MAJOR < 4 // IDF 3.x ESP32/PICO-D4
uint32_t rtc_reg(rtc_gpio_desc[pin].reg);
if ( rtc_reg ) // RTC pins PULL settings
@ -218,21 +207,14 @@ void directModeOutput(IO_REG_TYPE pin)
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].mux);
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].pullup | rtc_gpio_desc[pin].pulldown);
}
#endif
#endif
// Output
if ( pin < 32 )
GPIO.enable_w1ts = ((uint32_t)1 << pin);
else // already validated to pins <= 33
GPIO.enable1_w1ts.val = ((uint32_t)1 << (pin - 32));
uint32_t pinFunction((uint32_t)2 << FUN_DRV_S); // what are the drivers?
pinFunction |= FUN_IE; // input enable but required for output as well?
pinFunction |= ((uint32_t)2 << MCU_SEL_S);
ESP_REG(DR_REG_IO_MUX_BASE + esp32_gpioMux[pin].reg) = pinFunction;
GPIO.pin[pin].val = 0;
}
#endif
}
#define DIRECT_READ(base, pin) directRead(pin)
@ -445,6 +427,20 @@ void directWriteHigh(IO_REG_TYPE mask)
#define DIRECT_MODE_INPUT(base, mask) directModeInput(mask)
#define DIRECT_MODE_OUTPUT(base, mask) directModeOutput(mask)
#elif defined(ARDUINO_ARCH_MBED_RP2040)|| defined(ARDUINO_ARCH_RP2040)
#define delayMicroseconds(time) busy_wait_us(time)
#define PIN_TO_BASEREG(pin) (0)
#define PIN_TO_BITMASK(pin) (pin)
#define IO_REG_TYPE unsigned int
#define IO_REG_BASE_ATTR
#define IO_REG_MASK_ATTR
#define DIRECT_READ(base, pin) digitalRead(pin)
#define DIRECT_WRITE_LOW(base, pin) digitalWrite(pin, LOW)
#define DIRECT_WRITE_HIGH(base, pin) digitalWrite(pin, HIGH)
#define DIRECT_MODE_INPUT(base, pin) pinMode(pin,INPUT)
#define DIRECT_MODE_OUTPUT(base, pin) pinMode(pin,OUTPUT)
#warning "OneWire. RP2040 in Fallback mode. Using API calls for pinMode,digitalRead and digitalWrite."
#else
#define PIN_TO_BASEREG(pin) (0)
#define PIN_TO_BITMASK(pin) (pin)
@ -460,4 +456,4 @@ void directWriteHigh(IO_REG_TYPE mask)
#endif
#endif
#endif

View File

@ -282,7 +282,8 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8
useWire->beginTransmission(devAddr);
useWire->write(regAddr);
useWire->endTransmission();
useWire->beginTransmission(devAddr);
// See: https://github.com/espressif/arduino-esp32/issues/6674
// useWire->beginTransmission(devAddr);
useWire->requestFrom((uint8_t)devAddr, (uint8_t)min((int)length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH));
for (; useWire->available() && (timeout == 0 || millis() - t1 < timeout); count++) {
@ -1485,4 +1486,4 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT;
return rxBufferLength - rxBufferIndex;
}
#endif
#endif

View File

@ -308,4 +308,4 @@ class I2Cdev {
#endif // I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE
#endif /* _I2CDEV_H_ */
#endif /* _I2CDEV_H_ */

View File

@ -2556,8 +2556,8 @@ void MPU6050_Base::setClockSource(uint8_t source) {
* -------------+------------------
* 0 | 1.25 Hz
* 1 | 2.5 Hz
* 2 | 5 Hz
* 3 | 10 Hz
* 2 | 20 Hz
* 3 | 40 Hz
* </pre>
*
* For further information regarding the MPU-60X0's power modes, please refer to
@ -3371,25 +3371,27 @@ void MPU6050_Base::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){
resetDMP();
}
void MPU6050_Base::PrintActiveOffsets() {
uint8_t AOffsetRegister = (getDeviceID() < 0x38 )? MPU6050_RA_XA_OFFS_H:0x77;
int16_t Data[3];
//Serial.print(F("Offset Register 0x"));
//Serial.print(AOffsetRegister>>4,HEX);Serial.print(AOffsetRegister&0x0F,HEX);
Serial.print(F("\n// X Accel Y Accel Z Accel X Gyro Y Gyro Z Gyro\n// OFFSETS "));
if(AOffsetRegister == 0x06) I2Cdev::readWords(devAddr, AOffsetRegister, 3, (uint16_t *)Data, I2Cdev::readTimeout, wireObj);
else {
I2Cdev::readWords(devAddr, AOffsetRegister, 1, (uint16_t *)Data, I2Cdev::readTimeout, wireObj);
I2Cdev::readWords(devAddr, AOffsetRegister+3, 1, (uint16_t *)Data+1, I2Cdev::readTimeout, wireObj);
I2Cdev::readWords(devAddr, AOffsetRegister+6, 1, (uint16_t *)Data+2, I2Cdev::readTimeout, wireObj);
}
// A_OFFSET_H_READ_A_OFFS(Data);
Serial.print((float)Data[0], 5); Serial.print(", ");
Serial.print((float)Data[1], 5); Serial.print(", ");
Serial.print((float)Data[2], 5); Serial.print(", ");
I2Cdev::readWords(devAddr, 0x13, 3, (uint16_t *)Data, I2Cdev::readTimeout, wireObj);
// XG_OFFSET_H_READ_OFFS_USR(Data);
Serial.print((float)Data[0], 5); Serial.print(", ");
Serial.print((float)Data[1], 5); Serial.print(", ");
Serial.print((float)Data[2], 5); Serial.print("\n");
int16_t * MPU6050_Base::GetActiveOffsets() {
uint8_t AOffsetRegister = (getDeviceID() < 0x38 )? MPU6050_RA_XA_OFFS_H:0x77;
if(AOffsetRegister == 0x06) I2Cdev::readWords(devAddr, AOffsetRegister, 3, (uint16_t *)offsets, I2Cdev::readTimeout, wireObj);
else {
I2Cdev::readWords(devAddr, AOffsetRegister, 1, (uint16_t *)offsets, I2Cdev::readTimeout, wireObj);
I2Cdev::readWords(devAddr, AOffsetRegister+3, 1, (uint16_t *)(offsets+1), I2Cdev::readTimeout, wireObj);
I2Cdev::readWords(devAddr, AOffsetRegister+6, 1, (uint16_t *)(offsets+2), I2Cdev::readTimeout, wireObj);
}
I2Cdev::readWords(devAddr, 0x13, 3, (uint16_t *)(offsets+3), I2Cdev::readTimeout, wireObj);
return offsets;
}
void MPU6050_Base::PrintActiveOffsets() {
GetActiveOffsets();
// A_OFFSET_H_READ_A_OFFS(Data);
Serial.print((float)offsets[0], 5); Serial.print(",\t");
Serial.print((float)offsets[1], 5); Serial.print(",\t");
Serial.print((float)offsets[2], 5); Serial.print(",\t");
// XG_OFFSET_H_READ_OFFS_USR(Data);
Serial.print((float)offsets[3], 5); Serial.print(",\t");
Serial.print((float)offsets[4], 5); Serial.print(",\t");
Serial.print((float)offsets[5], 5); Serial.print("\n\n");
}

View File

@ -832,12 +832,16 @@ class MPU6050_Base {
void CalibrateAccel(uint8_t Loops = 15);// Fine tune after setting offsets with less Loops.
void PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops); // Does the math
void PrintActiveOffsets(); // See the results of the Calibration
int16_t * GetActiveOffsets();
protected:
uint8_t devAddr;
void *wireObj;
uint8_t buffer[14];
uint32_t fifoTimeout = MPU6050_FIFO_DEFAULT_TIMEOUT;
private:
int16_t offsets[6];
};
#ifndef I2CDEVLIB_MPU6050_TYPEDEF
@ -845,4 +849,4 @@ class MPU6050_Base {
typedef MPU6050_Base MPU6050;
#endif
#endif /* _MPU6050_H_ */
#endif /* _MPU6050_H_ */

View File

@ -15,7 +15,7 @@ include_dir = lib
[common_env_data]
upload_speed = 921600
monitor_speed = 115200
platform = espressif8266 @ 3.2.0
platform = espressif8266 @ 4.0.1
framework = arduino
board = d1_mini
build_unflags =
@ -33,16 +33,16 @@ build_flags =
-D EMBED_HTML # If this is not used the html files needs to be on the file system (can be uploaded)
-D USER_SSID=\""\"" # =\""myssid\""
-D USER_SSID_PWD=\""\"" # =\""mypwd\""
-D CFG_APPVER="\"1.0.0\""
-D CFG_GITREV=\""beta-1\""
-D CFG_APPVER="\"1.1.0\""
-D CFG_GITREV=\""beta-2\""
#!python script/git_rev.py
lib_deps = # Switched to forks for better version control.
# Using local copy of these libraries
#https://github.com/jrowberg/i2cdevlib.git#<document>
#https://github.com/PaulStoffregen/OneWire
#https://github.com/milesburton/Arduino-Temperature-Control-Library
https://github.com/mp-se/ESP_WiFiManager#v1.9.0 # https://github.com/khoih-prog/ESP_WiFiManager
https://github.com/mp-se/ESP_DoubleResetDetector#v1.2.1 # https://github.com/khoih-prog/ESP_DoubleResetDetector
#https://github.com/mp-se/i2cdevlib.git#<document>
#https://github.com/mp-se/OneWire # Using this version; https://github.com/arendst/Tasmota/tree/development/lib/lib_basic/OneWire-Stickbreaker
#https://github.com/mp-se/Arduino-Temperature-Control-Library
#https://github.com/khoih-prog/ESP_WiFiManager
#https://github.com/khoih-prog/ESP_DoubleResetDetector
https://github.com/mp-se/tinyexpr # https://github.com/codeplea/tinyexpr
https://github.com/mp-se/incbin # https://github.com/graphitemaster/incbin
https://github.com/mp-se/Arduino-Log#1.1.1 # https://github.com/thijse/Arduino-Log
@ -128,7 +128,7 @@ board_build.filesystem = littlefs
[env:gravity32-release]
framework = arduino
platform = espressif32 @ 3.5.0
platform = espressif32 @ 5.0.0
upload_speed = ${common_env_data.upload_speed}
monitor_speed = ${common_env_data.monitor_speed}
extra_scripts =
@ -153,8 +153,8 @@ build_flags =
-D MAIN_DISABLE_LOGGING
lib_deps =
${common_env_data.lib_deps}
https://github.com/lorol/LITTLEFS#1.0.6
https://github.com/mp-se/NimBLE-Arduino#1.3.8 # https://github.com/h2zero/NimBLE-Arduino
lib_ignore =
board = featheresp32
build_type = release
board_build.partitions = part32.csv
@ -163,7 +163,7 @@ monitor_filters = esp32_exception_decoder
[env:gravity32-perf]
framework = arduino
platform = espressif32 @ 3.5.0
platform = espressif32 @ 5.0.0
upload_speed = ${common_env_data.upload_speed}
monitor_speed = ${common_env_data.monitor_speed}
extra_scripts =
@ -179,35 +179,9 @@ build_flags =
-D LOG_LEVEL=5
lib_deps =
${common_env_data.lib_deps}
https://github.com/lorol/LITTLEFS#1.0.6
https://github.com/mp-se/NimBLE-Arduino#1.3.8 # https://github.com/h2zero/NimBLE-Arduino
board = featheresp32
build_type = release
board_build.partitions = part32.csv
board_build.filesystem = littlefs
monitor_filters = esp32_exception_decoder
#[env:gravity32-release2]
#framework = arduino
#platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.2.3/platform-espressif32-2.0.2.3.zip # build fails
#platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.2.2/platform-tasmota-espressif32-2.0.2.zip
#platform = espressif32 @ 4.1.0
#upload_speed = ${common_env_data.upload_speed}
#monitor_speed = ${common_env_data.monitor_speed}
#extra_scripts =
# script/copy_html.py
# script/copy_firmware.py
# script/create_versionjson.py
#build_unflags =
# ${common_env_data.build_unflags}
#build_flags =
# ${common_env_data.build_flags}
# -D ESPRESSIF32_20 # v2.0 framework
# -D LOG_LEVEL=5
#lib_deps =
# ${common_env_data.lib_deps}
# https://github.com/mp-se/NimBLE-Arduino#1.3.8 # https://github.com/h2zero/NimBLE-Arduino
#board = featheresp32
#build_type = release
#board_build.partitions = part32.csv
#board_build.filesystem = littlefs

View File

@ -35,7 +35,8 @@ int createFormula(RawFormulaData &fd, char *formulaBuffer,
int noAngles = 0;
RawFormulaData fd2;
// Check how many valid values we have got and make sure we have a full series.
// Check how many valid values we have got and make sure we have a full
// series.
for (int i = 0; i < FORMULA_DATA_SIZE; i++) {
if (fd.a[i]) {
fd2.a[noAngles] = fd.a[i];
@ -50,7 +51,7 @@ int createFormula(RawFormulaData &fd, char *formulaBuffer,
order, noAngles);
#endif
if (noAngles <3) {
if (noAngles < 3) {
ErrorFileLog errLog;
errLog.addEntry(F("CALC: Not enough values for deriving formula"));
return ERR_FORMULA_NOTENOUGHVALUES;
@ -62,7 +63,8 @@ int createFormula(RawFormulaData &fd, char *formulaBuffer,
// Returned value is 0 if no error
if (ret == 0) {
#if LOG_LEVEL == 6 && !defined(CALC_DISABLE_LOGGING)
Log.verbose(F("CALC: Finshied processing data points, order = %d." CR), order);
Log.verbose(F("CALC: Finshied processing data points, order = %d." CR),
order);
#endif
// Print the formula based on 'order'
@ -96,18 +98,18 @@ int createFormula(RawFormulaData &fd, char *formulaBuffer,
// If the deviation is more than 2 degress we mark it as failed.
if (dev * 1000 > myAdvancedConfig.getMaxFormulaCreationDeviation()) {
char s[20];
snprintf(&s[0], sizeof(s), "%.8f", dev);
Log.error(F("CALC: Deviation to large: %s" CR), &s[0]);
char s[120];
snprintf(&s[0], sizeof(s),
"CALC: Validation failed on angle %f, deviation too large "
"%.2f SG, formula order %d",
fd.a[i], dev * 1000, order);
ErrorFileLog errLog;
errLog.addEntry(&s[0]);
valid = false;
}
}
if (!valid) {
ErrorFileLog errLog;
errLog.addEntry(
F("CALC: Error validating created formula. Deviation to large, "
"formula rejected."));
return ERR_FORMULA_UNABLETOFFIND;
}
@ -173,16 +175,15 @@ double calculateGravity(double angle, double temp, const char *tempFormula) {
//
// Source: https://homebrewacademy.com/hydrometer-temperature-correction/
//
double gravityTemperatureCorrectionC(double gravity, double tempC,
double gravityTemperatureCorrectionC(double gravitySG, double tempC,
double calTempC) {
#if LOG_LEVEL == 6 && !defined(CALC_DISABLE_LOGGING)
Log.verbose(F("CALC: Adjusting gravity based on temperature, gravity %F, "
"temp %F, calTemp %F." CR),
gravity, tempC, calTempC);
gravitySG, tempC, calTempC);
#endif
// float tempF = convertCtoF(tempC);
// float calTempF = convertCtoF(calTempC);
double tempF = convertCtoF(tempC);
double calTempF = convertCtoF(calTempC);
const char *formula =
"gravity*((1.00130346-0.000134722124*temp+0.00000204052596*temp^2-0."
"00000000232820948*temp^3)/"
@ -191,7 +192,7 @@ double gravityTemperatureCorrectionC(double gravity, double tempC,
// Store variable names and pointers.
te_variable vars[] = {
{"gravity", &gravity}, {"temp", &tempC}, {"cal", &calTempC}};
{"gravity", &gravitySG}, {"temp", &tempF}, {"cal", &calTempF}};
int err;
// Compile the expression with variables.
@ -202,9 +203,10 @@ double gravityTemperatureCorrectionC(double gravity, double tempC,
te_free(expr);
#if LOG_LEVEL == 6 && !defined(CALC_DISABLE_LOGGING)
char s[10];
snprintf(&s[0], sizeof(s), "%.8f", g);
Log.verbose(F("CALC: Corrected gravity is %s." CR), &s[0]);
char s[80];
snprintf(&s[0], sizeof(s), "Corrected gravity=%.8f, input gravity=%.8f", g,
gravitySG);
Log.verbose(F("CALC: %s." CR), &s[0]);
#endif
return g;
}
@ -213,7 +215,7 @@ double gravityTemperatureCorrectionC(double gravity, double tempC,
errLog.addEntry(
"CALC: Failed to parse expression for gravity temperature correction " +
String(err));
return gravity;
return gravitySG;
}
// EOF

View File

@ -32,9 +32,8 @@ SOFTWARE.
double calculateGravity(double angle, double tempC,
const char *tempFormula = 0);
double gravityTemperatureCorrectionC(
double gravity, double tempC,
double calTempC = myAdvancedConfig.getDefaultCalibrationTemp());
double gravityTemperatureCorrectionC(double gravity, double tempC,
double calTempC);
int createFormula(RawFormulaData &fd, char *formulaBuffer,
int formulaBufferSize, int order);

View File

@ -86,12 +86,14 @@ void Config::createJson(DynamicJsonDocument& doc) {
doc[PARAM_PUSH_MQTT_USER] = getMqttUser();
doc[PARAM_PUSH_MQTT_PASS] = getMqttPass();
doc[PARAM_SLEEP_INTERVAL] = getSleepInterval();
doc[PARAM_VOLTAGEFACTOR] = getVoltageFactor();
doc[PARAM_VOLTAGE_FACTOR] = getVoltageFactor();
doc[PARAM_VOLTAGE_CONFIG] = getVoltageConfig();
doc[PARAM_GRAVITY_FORMULA] = getGravityFormula();
doc[PARAM_GRAVITY_FORMAT] = String(getGravityFormat());
doc[PARAM_TEMP_ADJ] = getTempSensorAdjC();
doc[PARAM_GRAVITY_TEMP_ADJ] = isGravityTempAdj();
doc[PARAM_GYRO_TEMP] = isGyroTemp();
doc[PARAM_STORAGE_SLEEP] = isStorageSleep();
JsonObject cal = doc.createNestedObject(PARAM_GYRO_CALIBRATION);
cal["ax"] = _gyroCalibration.ax;
@ -148,7 +150,7 @@ bool Config::saveFile() {
return false;
}
DynamicJsonDocument doc(CFG_JSON_BUFSIZE);
DynamicJsonDocument doc(3000);
createJson(doc);
#if LOG_LEVEL == 6 && !defined(DISABLE_LOGGING)
@ -190,7 +192,7 @@ bool Config::loadFile() {
Log.notice(F("CFG : Size of configuration file=%d bytes." CR),
configFile.size());
DynamicJsonDocument doc(CFG_JSON_BUFSIZE);
DynamicJsonDocument doc(3000);
DeserializationError err = deserializeJson(doc, configFile);
#if LOG_LEVEL == 6
serializeJson(doc, Serial);
@ -253,14 +255,18 @@ bool Config::loadFile() {
if (!doc[PARAM_SLEEP_INTERVAL].isNull())
setSleepInterval(doc[PARAM_SLEEP_INTERVAL].as<int>());
if (!doc[PARAM_VOLTAGEFACTOR].isNull())
setVoltageFactor(doc[PARAM_VOLTAGEFACTOR].as<float>());
if (!doc[PARAM_VOLTAGE_FACTOR].isNull())
setVoltageFactor(doc[PARAM_VOLTAGE_FACTOR].as<float>());
if (!doc[PARAM_VOLTAGE_CONFIG].isNull())
setVoltageConfig(doc[PARAM_VOLTAGE_CONFIG].as<float>());
if (!doc[PARAM_GRAVITY_FORMULA].isNull())
setGravityFormula(doc[PARAM_GRAVITY_FORMULA]);
if (!doc[PARAM_GRAVITY_TEMP_ADJ].isNull())
setGravityTempAdj(doc[PARAM_GRAVITY_TEMP_ADJ].as<bool>());
if (!doc[PARAM_GYRO_TEMP].isNull())
setGyroTemp(doc[PARAM_GYRO_TEMP].as<bool>());
if (!doc[PARAM_STORAGE_SLEEP].isNull())
setStorageSleep(doc[PARAM_STORAGE_SLEEP].as<bool>());
if (!doc[PARAM_GRAVITY_FORMAT].isNull()) {
String s = doc[PARAM_GRAVITY_FORMAT];
setGravityFormat(s.charAt(0));
@ -390,7 +396,8 @@ bool AdvancedConfig::saveFile() {
doc[PARAM_HW_PUSH_INTERVAL_HTTP3] = this->getPushIntervalHttp3();
doc[PARAM_HW_PUSH_INTERVAL_INFLUX] = this->getPushIntervalInflux();
doc[PARAM_HW_PUSH_INTERVAL_MQTT] = this->getPushIntervalMqtt();
doc[PARAM_HW_TEMPSENSOR_RESOLUTION] = this->getTempSensorResolution();
doc[PARAM_HW_TEMPSENSOR_RESOLUTION] = this->getTempSensorResolution();
doc[PARAM_HW_IGNORE_LOW_ANGLES] = this->isIgnoreLowAnges();
#if LOG_LEVEL == 6 && !defined(DISABLE_LOGGING)
serializeJson(doc, Serial);
@ -478,7 +485,10 @@ bool AdvancedConfig::loadFile() {
if (!doc[PARAM_HW_PUSH_INTERVAL_MQTT].isNull())
this->setPushIntervalMqtt(doc[PARAM_HW_PUSH_INTERVAL_MQTT].as<int>());
if (!doc[PARAM_HW_TEMPSENSOR_RESOLUTION].isNull())
this->setTempSensorResolution(doc[PARAM_HW_TEMPSENSOR_RESOLUTION].as<int>());
this->setTempSensorResolution(
doc[PARAM_HW_TEMPSENSOR_RESOLUTION].as<int>());
if (!doc[PARAM_HW_IGNORE_LOW_ANGLES].isNull())
setIgnoreLowAnges(doc[PARAM_HW_IGNORE_LOW_ANGLES].as<bool>());
Log.notice(F("CFG : Configuration file " CFG_HW_FILENAME " loaded." CR));
return true;

View File

@ -27,8 +27,6 @@ SOFTWARE.
#include <helper.hpp>
#include <resources.hpp>
#define CFG_JSON_BUFSIZE 3192
#define CFG_APPNAME "GravityMon" // Name of firmware
#define CFG_FILENAME "/gravitymon.json" // Name of config file
#define CFG_HW_FILENAME "/hardware.json" // Name of config file for hw
@ -56,12 +54,12 @@ struct RawFormulaData {
class AdvancedConfig {
private:
int _wifiPortalTimeout = 120;
int _wifiConnectTimeout = 20;
float _maxFormulaCreationDeviation = 1.6;
float _defaultCalibrationTemp = 20.0;
int _wifiPortalTimeout = 120; // seconds
int _wifiConnectTimeout = 20; // seconds
float _maxFormulaCreationDeviation = 3; // SG
float _defaultCalibrationTemp = 20.0; // C
int _gyroSensorMovingThreashold = 500;
int _tempSensorResolution = 9;
int _tempSensorResolution = 9; // bits
int _gyroReadCount = 50;
int _gyroReadDelay = 3150; // us, empirical, to hold sampling to 200 Hz
int _pushTimeout = 10; // seconds
@ -70,6 +68,7 @@ class AdvancedConfig {
int _pushIntervalHttp3 = 0;
int _pushIntervalInflux = 0;
int _pushIntervalMqtt = 0;
bool _IgnoreLowAnges = false;
public:
int getWifiPortalTimeout() { return _wifiPortalTimeout; }
@ -86,9 +85,8 @@ class AdvancedConfig {
}
int getTempSensorResolution() { return _tempSensorResolution; }
void setTempSensorResolution(int t) {
if (t>=9 && t<=12)
_tempSensorResolution = t;
void setTempSensorResolution(int t) {
if (t >= 9 && t <= 12) _tempSensorResolution = t;
}
float getDefaultCalibrationTemp() { return _defaultCalibrationTemp; }
@ -128,6 +126,9 @@ class AdvancedConfig {
: true;
}
const bool isIgnoreLowAnges() { return _IgnoreLowAnges; }
void setIgnoreLowAnges(bool b) { _IgnoreLowAnges = b; }
bool saveFile();
bool loadFile();
};
@ -143,9 +144,11 @@ class Config {
String _otaURL = "";
char _tempFormat = 'C';
float _voltageFactor = 1.59;
float _voltageConfig = 4.15;
float _tempSensorAdjC = 0;
int _sleepInterval = 900;
bool _gyroTemp = false;
bool _storageSleep = false;
// Wifi Config
String _wifiSSID[2] = {"", ""};
@ -181,7 +184,8 @@ class Config {
// Gyro calibration and formula calculation data
RawGyroData _gyroCalibration = {0, 0, 0, 0, 0, 0};
RawFormulaData _formulaData = {{0, 0, 0, 0, 0}, {1, 1, 1, 1, 1}};
RawFormulaData _formulaData = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1}};
void formatFileSystem();
@ -203,6 +207,12 @@ class Config {
_saveNeeded = true;
}
const bool isStorageSleep() { return _storageSleep; }
void setStorageSleep(bool b) {
_storageSleep = b;
_saveNeeded = true;
}
const char* getOtaURL() { return _otaURL.c_str(); }
void setOtaURL(String s) {
_otaURL = s;
@ -367,6 +377,16 @@ class Config {
_saveNeeded = true;
}
float getVoltageConfig() { return _voltageConfig; }
void setVoltageConfig(float f) {
_voltageConfig = f;
_saveNeeded = true;
}
void setVoltageConfig(String s) {
_voltageConfig = s.toFloat();
_saveNeeded = true;
}
float getTempSensorAdjC() { return _tempSensorAdjC; }
void setTempSensorAdjC(float f) {
_tempSensorAdjC = f;

View File

@ -43,7 +43,9 @@ bool GyroSensor::setup() {
Wire.setClock(400000); // 400kHz I2C clock. Comment this line if having
// compilation difficulties
if (!accelgyro.testConnection()) {
uint8_t id = accelgyro.getDeviceID();
if (id != 0x34 && id != 0x38) { // Allow both MPU6050 and MPU6000
ErrorFileLog errLog;
errLog.addEntry(F("GYRO: Failed to connect to gyro, is it connected?"));
_sensorConnected = false;

View File

@ -194,14 +194,8 @@ void printBuildOptions() {
#ifdef SKIP_SLEEPMODE
"SKIP_SLEEP "
#endif
#ifdef EMBED_HTML
"EMBED_HTML "
#endif
#ifdef COLLECT_PERFDATA
"PERFDATA "
#endif
#ifdef ACTIVATE_OTA
"OTA "
#endif
CR),
CFG_APPVER, CFG_GITREV, LOG_LEVEL);
@ -318,7 +312,9 @@ void PerfLogging::pushInflux() {
if (!myConfig.isInfluxDb2Active()) return;
if (myConfig.isInfluxSSL()) {
Log.warning(F("PERF: InfluxDB2 with SSL is not supported when pushing performance data, skipping" CR));
Log.warning(
F("PERF: InfluxDB2 with SSL is not supported when pushing performance "
"data, skipping" CR));
return;
}

View File

@ -32,13 +32,13 @@ SOFTWARE.
#include <webserver.hpp>
#include <wifi.hpp>
//#define FORCE_GRAVITY_MODE
// #define FORCE_GRAVITY_MODE
// Define constats for this program
#ifdef DEACTIVATE_SLEEPMODE
const int interval = 1000; // ms, time to wait between changes to output
#else
int interval = 200; // ms, time to wait between changes to output
int interval = 200; // ms, time to wait between changes to output
#endif
bool sleepModeAlwaysSkip =
false; // Flag set in web interface to override normal behaviour
@ -50,9 +50,6 @@ uint32_t stableGyroMillis; // Used to calculate the total time since last
RunMode runMode = RunMode::gravityMode;
//
// Check if we should be in sleep mode
//
void checkSleepMode(float angle, float volt) {
#if defined(SKIP_SLEEPMODE)
runMode = RunMode::configurationMode;
@ -83,8 +80,12 @@ void checkSleepMode(float angle, float volt) {
Log.notice(F("MAIN: Sleep mode disabled from web interface." CR));
#endif
runMode = RunMode::configurationMode;
} else if ((volt < 4.15 && (angle > 85 && angle < 95)) || (volt > 4.15)) {
} else if ((volt < myConfig.getVoltageConfig() &&
(angle > 85 && angle < 95)) ||
(volt > myConfig.getVoltageConfig())) {
runMode = RunMode::configurationMode;
} else if (angle < 5 && myConfig.isStorageSleep()) {
runMode = RunMode::storageMode;
} else {
runMode = RunMode::gravityMode;
}
@ -104,12 +105,26 @@ void checkSleepMode(float angle, float volt) {
volt);
#endif
break;
case RunMode::storageMode:
#if !defined(MAIN_DISABLE_LOGGING)
Log.notice(F("MAIN: run mode STORAGE (angle=%F)." CR), angle);
#endif
break;
}
// If we are in storage mode, just go back to sleep
if (runMode == RunMode::storageMode) {
Log.notice(
F("Main: Storage mode entered, going to sleep for maximum time." CR));
#if defined(ESP8266)
ESP.deepSleep(ESP.deepSleepMax());
#else
#warning "Check and test the max deep sleep for esp32"
deepSleep(70 * 60); // quick search on internet suggest max time is 70 min
#endif
}
}
//
// Setup
//
void setup() {
LOG_PERF_START("run-time");
LOG_PERF_START("main-setup");
@ -264,7 +279,12 @@ bool loopReadGravity() {
LOG_PERF_STOP("loop-temp-read");
float gravitySG = calculateGravity(angle, tempC);
float corrGravitySG = gravityTemperatureCorrectionC(gravitySG, tempC);
float corrGravitySG = gravityTemperatureCorrectionC(
gravitySG, tempC, myAdvancedConfig.getDefaultCalibrationTemp());
if (myConfig.isGravityTempAdj()) {
gravitySG = corrGravitySG;
}
#if LOG_LEVEL == 6 && !defined(MAIN_DISABLE_LOGGING)
Log.verbose(F("Main: Sensor values gyro angle=%F, temp=%FC, gravity=%F, "
@ -275,6 +295,14 @@ bool loopReadGravity() {
bool pushExpired = (abs((int32_t)(millis() - pushMillis)) >
(myConfig.getSleepInterval() * 1000));
if (myAdvancedConfig.isIgnoreLowAnges() &&
(angle < myConfig.getFormulaData().a[0])) {
Log.warning(
F("Main: Angle is lower than water, so we regard this as faulty and "
"dont send any data." CR));
pushExpired = false;
}
if (pushExpired || runMode == RunMode::gravityMode) {
pushMillis = millis();
LOG_PERF_START("loop-push");
@ -350,11 +378,12 @@ void goToSleep(int sleepInterval) {
deepSleep(sleepInterval);
}
//
// Main loops
//
void loop() {
switch (runMode) {
case RunMode::storageMode:
// This point is never reached, just here to remove warning.
break;
case RunMode::configurationMode:
if (myWifi.isConnected()) myWebServerHandler.loop();

View File

@ -29,7 +29,12 @@ SOFTWARE.
#include <ArduinoLog.h>
#include <stdlib.h>
enum RunMode { gravityMode = 0, configurationMode = 1, wifiSetupMode = 2 };
enum RunMode {
gravityMode = 0,
configurationMode = 1,
wifiSetupMode = 2,
storageMode = 3
};
extern RunMode runMode;
#if defined(ESP8266)
@ -41,13 +46,8 @@ extern RunMode runMode;
#define PIN_LED 2
// #define PIN_A0 A0
#else // defined (ESP32)
#if defined(ESPRESSIF32_20)
#include <LittleFS.h>
#else
#include <LITTLEFS.h>
#define LittleFS LITTLEFS
#endif
#include <FS.h>
#include <LittleFS.h>
#define ESPhttpUpdate httpUpdate
#define ESP_RESET ESP.restart
#define ESP8266WebServer WebServer

View File

@ -108,8 +108,8 @@ void PushIntervalTracker::save() {
void PushTarget::sendAll(float angle, float gravitySG, float corrGravitySG,
float tempC, float runTime) {
printHeap("PUSH");
_http.setReuse(false);
_httpSecure.setReuse(false);
_http.setReuse(true);
_httpSecure.setReuse(true);
TemplatingEngine engine;
engine.initialize(angle, gravitySG, corrGravitySG, tempC, runTime);
@ -204,9 +204,11 @@ void PushTarget::sendInfluxDb2(TemplatingEngine& engine, bool isSecure) {
String auth = "Token " + String(myConfig.getInfluxDb2PushToken());
if (isSecure) {
#if defined( ESP8266 )
#if defined(ESP8266)
if (runMode == RunMode::configurationMode) {
Log.notice(F("PUSH: Skipping InfluxDB since SSL is enabled and we are in config mode." CR));
Log.notice(
F("PUSH: Skipping InfluxDB since SSL is enabled and we are in config "
"mode." CR));
_lastCode = -100;
return;
}
@ -217,8 +219,7 @@ void PushTarget::sendInfluxDb2(TemplatingEngine& engine, bool isSecure) {
probeMaxFragement(serverPath);
_httpSecure.setTimeout(myAdvancedConfig.getPushTimeout() * 1000);
_httpSecure.begin(_wifiSecure, serverPath);
_httpSecure.addHeader(F("Authorization"), auth.c_str());
_httpSecure.setReuse(true);
_httpSecure.addHeader(F("Authorization"), auth.c_str());
_lastCode = _httpSecure.POST(doc);
} else {
_http.setTimeout(myAdvancedConfig.getPushTimeout() * 1000);
@ -293,9 +294,11 @@ void PushTarget::sendHttpPost(TemplatingEngine& engine, bool isSecure,
#endif
if (isSecure) {
#if defined( ESP8266 )
#if defined(ESP8266)
if (runMode == RunMode::configurationMode) {
Log.notice(F("PUSH: Skipping HTTP since SSL is enabled and we are in config mode." CR));
Log.notice(
F("PUSH: Skipping HTTP since SSL is enabled and we are in config "
"mode." CR));
_lastCode = -100;
return;
}
@ -370,9 +373,11 @@ void PushTarget::sendHttpGet(TemplatingEngine& engine, bool isSecure) {
#endif
if (isSecure) {
#if defined( ESP8266 )
#if defined(ESP8266)
if (runMode == RunMode::configurationMode) {
Log.notice(F("PUSH: Skipping HTTP since SSL is enabled and we are in config mode." CR));
Log.notice(
F("PUSH: Skipping HTTP since SSL is enabled and we are in config "
"mode." CR));
_lastCode = -100;
return;
}
@ -424,9 +429,11 @@ void PushTarget::sendMqtt(TemplatingEngine& engine, bool isSecure) {
int port = myConfig.getMqttPort();
if (myConfig.isMqttSSL()) {
#if defined( ESP8266 )
#if defined(ESP8266)
if (runMode == RunMode::configurationMode) {
Log.notice(F("PUSH: Skipping MQTT since SSL is enabled and we are in config mode." CR));
Log.notice(
F("PUSH: Skipping MQTT since SSL is enabled and we are in config "
"mode." CR));
_lastCode = -100;
return;
}

View File

@ -45,7 +45,7 @@ class PushTarget {
void sendHttpPost(TemplatingEngine& engine, bool isSecure, int index);
void sendHttpGet(TemplatingEngine& engine, bool isSecure);
void addHttpHeader(HTTPClient& http, String header);
void probeMaxFragement( String& serverPath );
void probeMaxFragement(String& serverPath);
public:
void sendAll(float angle, float gravitySG, float corrGravitySG, float tempC,
@ -68,7 +68,7 @@ class PushTarget {
class PushIntervalTracker {
private:
int _counters[5] = { 0, 0, 0, 0, 0 };
int _counters[5] = {0, 0, 0, 0, 0};
void update(const int index, const int defaultValue);
public:

View File

@ -53,13 +53,15 @@ SOFTWARE.
#define PARAM_PUSH_MQTT_PORT "mqtt-port"
#define PARAM_SLEEP_INTERVAL "sleep-interval"
#define PARAM_TEMPFORMAT "temp-format"
#define PARAM_VOLTAGEFACTOR "voltage-factor"
#define PARAM_VOLTAGE_FACTOR "voltage-factor"
#define PARAM_VOLTAGE_CONFIG "voltage-config"
#define PARAM_GRAVITY_FORMULA "gravity-formula"
#define PARAM_GRAVITY_FORMAT "gravity-format"
#define PARAM_GRAVITY_TEMP_ADJ "gravity-temp-adjustment"
#define PARAM_TEMP_ADJ "temp-adjustment-value"
#define PARAM_GYRO_CALIBRATION "gyro-calibration-data"
#define PARAM_GYRO_TEMP "gyro-temp"
#define PARAM_STORAGE_SLEEP "storage-sleep"
#define PARAM_FORMULA_DATA "formula-calculation-data"
#define PARAM_FILES "files"
#define PARAM_FILE_NAME "file-name"
@ -90,6 +92,7 @@ SOFTWARE.
#define PARAM_HW_PUSH_INTERVAL_HTTP3 "int-http3"
#define PARAM_HW_PUSH_INTERVAL_INFLUX "int-influx"
#define PARAM_HW_PUSH_INTERVAL_MQTT "int-mqtt"
#define PARAM_HW_IGNORE_LOW_ANGLES "ignore-low-angles"
#define PARAM_FORMAT_HTTP1 "http-1"
#define PARAM_FORMAT_HTTP2 "http-2"
#define PARAM_FORMAT_HTTP3 "http-3"

View File

@ -130,6 +130,9 @@ void TemplatingEngine::initialize(float angle, float gravitySG,
setVal(TPL_GRAVITY_CORR_P, convertToPlato(corrGravitySG), 1);
setVal(TPL_GRAVITY_UNIT, myConfig.getGravityFormat());
setVal(TPL_APP_VER, CFG_APPVER);
setVal(TPL_APP_BUILD, CFG_GITREV);
#if LOG_LEVEL == 6
// dumpAll();
#endif

View File

@ -53,6 +53,8 @@ SOFTWARE.
#define TPL_GRAVITY_CORR_G "${corr-gravity-sg}"
#define TPL_GRAVITY_CORR_P "${corr-gravity-plato}"
#define TPL_GRAVITY_UNIT "${gravity-unit}" // G or P
#define TPL_APP_VER "${app-ver}"
#define TPL_APP_BUILD "${app-build}"
#define TPL_FNAME_HTTP1 "/http-1.tpl"
#define TPL_FNAME_HTTP2 "/http-2.tpl"
@ -73,7 +75,7 @@ class TemplatingEngine {
String val;
};
KeyVal items[21] = {{TPL_MDNS, ""}, {TPL_ID, ""},
KeyVal items[23] = {{TPL_MDNS, ""}, {TPL_ID, ""},
{TPL_SLEEP_INTERVAL, ""}, {TPL_TEMP, ""},
{TPL_TEMP_C, ""}, {TPL_TEMP_F, ""},
{TPL_TEMP_UNITS, ""}, {TPL_BATTERY, ""},
@ -83,7 +85,8 @@ class TemplatingEngine {
{TPL_GRAVITY_P, ""}, {TPL_GRAVITY_CORR, ""},
{TPL_GRAVITY_CORR_G, ""}, {TPL_GRAVITY_CORR_P, ""},
{TPL_GRAVITY_UNIT, ""}, {TPL_TOKEN, ""},
{TPL_TOKEN2, ""}};
{TPL_TOKEN2, ""}, {TPL_APP_VER, ""},
{TPL_APP_BUILD, ""}};
char buffer[20];
String baseTemplate;

View File

@ -51,10 +51,10 @@ void TempSensor::setup() {
if (mySensors.getDS18Count()) {
#if !defined(TSEN_DISABLE_LOGGING)
Log.notice(F("TSEN: Found %d temperature sensor(s). Using %d resolution" CR),
mySensors.getDS18Count(), myAdvancedConfig.getTempSensorResolution());
Log.notice(
F("TSEN: Found %d temperature sensor(s). Using %d resolution" CR),
mySensors.getDS18Count(), myAdvancedConfig.getTempSensorResolution());
#endif
mySensors.setResolution(myAdvancedConfig.getTempSensorResolution());
}
// Set the temp sensor adjustment values
@ -94,6 +94,7 @@ float TempSensor::getValue(bool useGyro) {
}
// Read the sensors
mySensors.setResolution(myAdvancedConfig.getTempSensorResolution());
mySensors.requestTemperatures();
float c = 0;

View File

@ -44,10 +44,14 @@ void WebServerHandler::webHandleConfig() {
LOG_PERF_START("webserver-api-config");
Log.notice(F("WEB : webServer callback for /api/config(get)." CR));
DynamicJsonDocument doc(CFG_JSON_BUFSIZE);
DynamicJsonDocument doc(2000);
myConfig.createJson(doc);
doc[PARAM_PASS] = ""; // dont show the wifi password
doc[PARAM_PASS2] = "";
doc[PARAM_APP_VER] = String(CFG_APPVER);
doc[PARAM_APP_BUILD] = String(CFG_GITREV);
double angle = 0;
@ -68,8 +72,8 @@ void WebServerHandler::webHandleConfig() {
doc[PARAM_TEMP_ADJ] = reduceFloatPrecision(myConfig.getTempSensorAdjC(), 1);
if (myConfig.isGravityTempAdj()) {
gravity =
gravityTemperatureCorrectionC(gravity, tempC, myConfig.getTempFormat());
gravity = gravityTemperatureCorrectionC(
gravity, tempC, myAdvancedConfig.getDefaultCalibrationTemp());
}
if (myConfig.isGravityPlato()) {
@ -96,8 +100,9 @@ void WebServerHandler::webHandleConfig() {
#endif
String out;
out.reserve(CFG_JSON_BUFSIZE);
out.reserve(2000);
serializeJson(doc, out);
doc.clear();
_server->send(200, "application/json", out.c_str());
LOG_PERF_STOP("webserver-api-config");
}
@ -159,6 +164,7 @@ void WebServerHandler::webHandleUpload() {
String out;
out.reserve(300);
serializeJson(doc, out);
doc.clear();
_server->send(200, "application/json", out.c_str());
LOG_PERF_STOP("webserver-api-upload");
}
@ -324,7 +330,7 @@ void WebServerHandler::webHandleStatus() {
LOG_PERF_START("webserver-api-status");
Log.notice(F("WEB : webServer callback for /api/status(get)." CR));
DynamicJsonDocument doc(512);
DynamicJsonDocument doc(500);
double angle = 0;
@ -336,7 +342,8 @@ void WebServerHandler::webHandleStatus() {
doc[PARAM_ID] = myConfig.getID();
doc[PARAM_ANGLE] = reduceFloatPrecision(angle);
if (myConfig.isGravityTempAdj()) {
gravity = gravityTemperatureCorrectionC(gravity, tempC);
gravity = gravityTemperatureCorrectionC(
gravity, tempC, myAdvancedConfig.getDefaultCalibrationTemp());
}
if (myConfig.isGravityPlato()) {
doc[PARAM_GRAVITY] = reduceFloatPrecision(convertToPlato(gravity), 1);
@ -375,8 +382,9 @@ void WebServerHandler::webHandleStatus() {
#endif
String out;
out.reserve(300);
out.reserve(500);
serializeJson(doc, out);
doc.clear();
_server->send(200, "application/json", out.c_str());
LOG_PERF_STOP("webserver-api-status");
}
@ -575,6 +583,9 @@ void WebServerHandler::webHandleConfigGravity() {
myConfig.setGravityTempAdj(
_server->arg(PARAM_GRAVITY_TEMP_ADJ).equalsIgnoreCase("on") ? true
: false);
else
myConfig.setGravityTempAdj(false);
myConfig.saveFile();
_server->sendHeader("Location", "/config.htm#collapseGravity", true);
_server->send(302, "text/plain", "Gravity config updated");
@ -601,8 +612,10 @@ void WebServerHandler::webHandleConfigHardware() {
Log.verbose(F("WEB : %s." CR), getRequestArguments().c_str());
#endif
if (_server->hasArg(PARAM_VOLTAGEFACTOR))
myConfig.setVoltageFactor(_server->arg(PARAM_VOLTAGEFACTOR).toFloat());
if (_server->hasArg(PARAM_VOLTAGE_FACTOR))
myConfig.setVoltageFactor(_server->arg(PARAM_VOLTAGE_FACTOR).toFloat());
if (_server->hasArg(PARAM_VOLTAGE_CONFIG))
myConfig.setVoltageConfig(_server->arg(PARAM_VOLTAGE_CONFIG).toFloat());
if (_server->hasArg(PARAM_TEMP_ADJ)) {
if (myConfig.isTempC()) {
myConfig.setTempSensorAdjC(_server->arg(PARAM_TEMP_ADJ));
@ -618,6 +631,15 @@ void WebServerHandler::webHandleConfigHardware() {
if (_server->hasArg(PARAM_GYRO_TEMP))
myConfig.setGyroTemp(
_server->arg(PARAM_GYRO_TEMP).equalsIgnoreCase("on") ? true : false);
else
myConfig.setGyroTemp(false);
if (_server->hasArg(PARAM_STORAGE_SLEEP))
myConfig.setStorageSleep(
_server->arg(PARAM_STORAGE_SLEEP).equalsIgnoreCase("on") ? true
: false);
else
myConfig.setStorageSleep(false);
myConfig.saveFile();
_server->sendHeader("Location", "/config.htm#collapseHardware", true);
_server->send(302, "text/plain", "Hardware config updated");
@ -656,9 +678,11 @@ void WebServerHandler::webHandleConfigAdvancedWrite() {
if (_server->hasArg(PARAM_HW_FORMULA_DEVIATION))
myAdvancedConfig.setMaxFormulaCreationDeviation(
_server->arg(PARAM_HW_FORMULA_DEVIATION).toFloat());
if (_server->hasArg(PARAM_HW_FORMULA_CALIBRATION_TEMP))
myAdvancedConfig.SetDefaultCalibrationTemp(
_server->arg(PARAM_HW_FORMULA_CALIBRATION_TEMP).toFloat());
if (_server->hasArg(PARAM_HW_FORMULA_CALIBRATION_TEMP)) {
float t = _server->arg(PARAM_HW_FORMULA_CALIBRATION_TEMP).toFloat();
if (myConfig.isTempF()) t = convertFtoC(t);
myAdvancedConfig.SetDefaultCalibrationTemp(t);
}
if (_server->hasArg(PARAM_HW_WIFI_PORTAL_TIMEOUT))
myAdvancedConfig.setWifiPortalTimeout(
_server->arg(PARAM_HW_WIFI_PORTAL_TIMEOUT).toInt());
@ -686,6 +710,13 @@ void WebServerHandler::webHandleConfigAdvancedWrite() {
if (_server->hasArg(PARAM_HW_TEMPSENSOR_RESOLUTION))
myAdvancedConfig.setTempSensorResolution(
_server->arg(PARAM_HW_TEMPSENSOR_RESOLUTION).toInt());
if (_server->hasArg(PARAM_HW_IGNORE_LOW_ANGLES))
myAdvancedConfig.setIgnoreLowAnges(
_server->arg(PARAM_HW_IGNORE_LOW_ANGLES).equalsIgnoreCase("on")
? true
: false);
else
myAdvancedConfig.setIgnoreLowAnges(false);
myAdvancedConfig.saveFile();
_server->sendHeader("Location", "/config.htm#collapseAdvanced", true);
@ -700,7 +731,7 @@ void WebServerHandler::webHandleConfigAdvancedRead() {
LOG_PERF_START("webserver-api-config-advanced");
Log.notice(F("WEB : webServer callback for /api/config/advanced(get)." CR));
DynamicJsonDocument doc(512);
DynamicJsonDocument doc(500);
doc[PARAM_HW_GYRO_READ_COUNT] = myAdvancedConfig.getGyroReadCount();
// doc[PARAM_HW_GYRO_READ_DELAY] = myAdvancedConfig.getGyroReadDelay();
@ -711,8 +742,9 @@ void WebServerHandler::webHandleConfigAdvancedRead() {
doc[PARAM_HW_WIFI_PORTAL_TIMEOUT] = myAdvancedConfig.getWifiPortalTimeout();
doc[PARAM_HW_WIFI_CONNECT_TIMEOUT] = myAdvancedConfig.getWifiConnectTimeout();
doc[PARAM_HW_PUSH_TIMEOUT] = myAdvancedConfig.getPushTimeout();
float t = myAdvancedConfig.getDefaultCalibrationTemp();
doc[PARAM_HW_FORMULA_CALIBRATION_TEMP] =
myAdvancedConfig.getDefaultCalibrationTemp();
myConfig.isTempC() ? t : reduceFloatPrecision(convertCtoF(t), 1);
doc[PARAM_HW_PUSH_INTERVAL_HTTP1] = myAdvancedConfig.getPushIntervalHttp1();
doc[PARAM_HW_PUSH_INTERVAL_HTTP2] = myAdvancedConfig.getPushIntervalHttp2();
doc[PARAM_HW_PUSH_INTERVAL_HTTP3] = myAdvancedConfig.getPushIntervalHttp3();
@ -720,6 +752,7 @@ void WebServerHandler::webHandleConfigAdvancedRead() {
doc[PARAM_HW_PUSH_INTERVAL_MQTT] = myAdvancedConfig.getPushIntervalMqtt();
doc[PARAM_HW_TEMPSENSOR_RESOLUTION] =
myAdvancedConfig.getTempSensorResolution();
doc[PARAM_HW_IGNORE_LOW_ANGLES] = myAdvancedConfig.isIgnoreLowAnges();
#if LOG_LEVEL == 6 && !defined(WEB_DISABLE_LOGGING)
serializeJson(doc, Serial);
@ -727,8 +760,9 @@ void WebServerHandler::webHandleConfigAdvancedRead() {
#endif
String out;
out.reserve(512);
out.reserve(500);
serializeJson(doc, out);
doc.clear();
_server->send(200, "application/json", out.c_str());
LOG_PERF_STOP("webserver-api-config-advanced");
}
@ -740,7 +774,7 @@ void WebServerHandler::webHandleFormulaRead() {
LOG_PERF_START("webserver-api-formula-read");
Log.notice(F("WEB : webServer callback for /api/formula(get)." CR));
DynamicJsonDocument doc(512);
DynamicJsonDocument doc(500);
const RawFormulaData& fd = myConfig.getFormulaData();
#if LOG_LEVEL == 6 && !defined(WEB_DISABLE_LOGGING)
@ -758,10 +792,13 @@ void WebServerHandler::webHandleFormulaRead() {
doc[PARAM_ERROR] = "Internal error creating formula.";
break;
case ERR_FORMULA_NOTENOUGHVALUES:
doc[PARAM_ERROR] = "Not enough values to create formula.";
doc[PARAM_ERROR] =
"Not enough values to create formula, need at least 3 angles.";
break;
case ERR_FORMULA_UNABLETOFFIND:
doc[PARAM_ERROR] = "Unable to find an accurate formula based on input.";
doc[PARAM_ERROR] =
"Unable to find an accurate formula based on input, check error log "
"and graph below.";
break;
default:
doc[PARAM_GRAVITY_FORMULA] = myConfig.getGravityFormula();
@ -809,8 +846,9 @@ void WebServerHandler::webHandleFormulaRead() {
#endif
String out;
out.reserve(256);
out.reserve(500);
serializeJson(doc, out);
doc.clear();
_server->send(200, "application/json", out.c_str());
LOG_PERF_STOP("webserver-api-formula-read");
}
@ -885,7 +923,8 @@ void WebServerHandler::webHandleTestPush() {
float angle = myGyro.getAngle();
float tempC = myTempSensor.getTempC(myConfig.isGyroTemp());
float gravitySG = calculateGravity(angle, tempC);
float corrGravitySG = gravityTemperatureCorrectionC(gravitySG, tempC);
float corrGravitySG = gravityTemperatureCorrectionC(
gravitySG, tempC, myAdvancedConfig.getDefaultCalibrationTemp());
TemplatingEngine engine;
engine.initialize(angle, gravitySG, corrGravitySG, tempC, 2.1);
@ -920,6 +959,7 @@ void WebServerHandler::webHandleTestPush() {
String out;
out.reserve(100);
serializeJson(doc, out);
doc.clear();
#if LOG_LEVEL == 6 && !defined(WEB_DISABLE_LOGGING)
serializeJson(doc, Serial);
@ -982,7 +1022,7 @@ void WebServerHandler::webHandleConfigFormatRead() {
LOG_PERF_START("webserver-api-config-format-read");
Log.notice(F("WEB : webServer callback for /api/config/formula(get)." CR));
DynamicJsonDocument doc(2048);
DynamicJsonDocument doc(5000);
doc[PARAM_ID] = myConfig.getID();
@ -1022,8 +1062,9 @@ void WebServerHandler::webHandleConfigFormatRead() {
#endif
String out;
out.reserve(2048);
out.reserve(3000);
serializeJson(doc, out);
doc.clear();
_server->send(200, "application/json", out.c_str());
LOG_PERF_STOP("webserver-api-config-format-read");
}
@ -1084,6 +1125,7 @@ void WebServerHandler::webHandleFormulaWrite() {
fd.g[9] = _server->arg("g10").toDouble();
}
fd.g[0] = 1; // force first point to SG gravity of water
myConfig.setFormulaData(fd);
int e;
@ -1129,17 +1171,17 @@ const char* WebServerHandler::getHtmlFileName(HtmlFile item) {
Log.notice(F("WEB : Looking up filename for %d." CR), item);
switch (item) {
case HTML_INDEX:
case HtmlFile::HTML_INDEX:
return "index.min.htm";
case HTML_CONFIG:
case HtmlFile::HTML_CONFIG:
return "config.min.htm";
case HTML_CALIBRATION:
case HtmlFile::HTML_CALIBRATION:
return "calibration.min.htm";
case HTML_FORMAT:
case HtmlFile::HTML_FORMAT:
return "format.min.htm";
case HTML_ABOUT:
case HtmlFile::HTML_ABOUT:
return "about.min.htm";
case HTML_TEST:
case HtmlFile::HTML_TEST:
return "test.min.htm";
}
@ -1181,6 +1223,37 @@ bool WebServerHandler::setupWebServer() {
MDNS.begin(myConfig.getMDNS());
MDNS.addService("http", "tcp", 80);
// Show files in the filessytem at startup
#if defined(ESP8266)
FSInfo fs;
LittleFS.info(fs);
Log.notice(F("WEB : File system Total=%d, Used=%d." CR), fs.totalBytes,
fs.usedBytes);
Dir dir = LittleFS.openDir("/");
while (dir.next()) {
Log.notice(F("WEB : File=%s, %d bytes" CR), dir.fileName().c_str(),
dir.fileSize());
if (!dir.fileSize()) {
Log.notice(F("WEB : Empty file detected, removing file." CR));
LittleFS.remove(dir.fileName().c_str());
}
}
#else // defined( ESP32 )
File root = LittleFS.open("/");
File f = root.openNextFile();
while (f) {
Log.notice(F("WEB : File=%s, %d bytes" CR), f.name(), f.size());
if (!f.size()) {
Log.notice(F("WEB : Empty file detected, removing file." CR));
LittleFS.remove(f.name());
}
f = root.openNextFile();
}
f.close();
root.close();
#endif
// Static content
#if defined(EMBED_HTML)
_server->on("/", std::bind(&WebServerHandler::webReturnIndexHtm, this));
@ -1197,18 +1270,6 @@ bool WebServerHandler::setupWebServer() {
_server->on("/test.htm",
std::bind(&WebServerHandler::webReturnTestHtm, this));
#else
// Show files in the filessytem at startup
FSInfo fs;
LittleFS.info(fs);
Log.notice(F("WEB : File system Total=%d, Used=%d." CR), fs.totalBytes,
fs.usedBytes);
Dir dir = LittleFS.openDir("/");
while (dir.next()) {
Log.notice(F("WEB : File=%s, %d bytes" CR), dir.fileName().c_str(),
dir.fileSize());
}
// Check if the html files exist, if so serve them, else show the static
// upload page.
if (checkHtmlFile(HTML_INDEX) && checkHtmlFile(HTML_CONFIG) &&

View File

@ -28,12 +28,12 @@ SOFTWARE.
#include <ESP8266WebServer.h>
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#define MAX_SKETCH_SPACE 1044464
#define MAX_SKETCH_SPACE 1044464
#else // defined (ESP32)
#include <ESPmDNS.h>
#include <Update.h>
#include <WebServer.h>
#include <WiFi.h>
#include <Update.h>
#define MAX_SKETCH_SPACE 1835008
#endif
#include <incbin.h>

View File

@ -74,10 +74,7 @@ bool WifiConnection::hasConfig() {
if (strlen(userSSID)) return true;
// Check if there are stored WIFI Settings we can use.
#if defined(ESP32)
#warning \
"Cant read SSID on ESP32 until a connection has been made, this part will not work, change to WifiManager"
#endif
#if defined(ESP8266)
String ssid = WiFi.SSID();
if (ssid.length()) {
Log.notice(F("WIFI: Found credentials in EEPORM." CR));
@ -88,6 +85,10 @@ bool WifiConnection::hasConfig() {
myConfig.saveFile();
return true;
}
#else // defined( ESP32 )
#warning "Cant read SSID property on ESP32 until a connection has been made!"
#endif
return false;
}
@ -279,16 +280,19 @@ bool WifiConnection::connect() {
if (!waitForConnection(timeout)) {
Log.warning(F("WIFI: Failed to connect to first SSID %s." CR),
myConfig.getWifiSSID(0));
connectAsync(1);
if (waitForConnection(timeout)) {
Log.notice(
F("WIFI: Connected to second SSID %s, making secondary default." CR),
myConfig.getWifiSSID(1));
if (strlen(myConfig.getWifiSSID(1))) {
connectAsync(1);
myConfig.swapPrimaryWifi();
myConfig.saveFile();
return true;
if (waitForConnection(timeout)) {
Log.notice(F("WIFI: Connected to second SSID %s, making secondary "
"default." CR),
myConfig.getWifiSSID(1));
myConfig.swapPrimaryWifi();
myConfig.saveFile();
return true;
}
}
Log.warning(F("WIFI: Failed to connect to any SSID." CR));

View File

@ -19,6 +19,10 @@ To reduce the need for adding custom endpoints for various services there is an
You enter the format data in the text field and the test button will show an example on what the output would look like. If the data cannot be formatted in json it will just be displayed as a long string.
The save button will save the current formla and reload the data from the device.
You can also select a template from the list and copy that to the current endpoint.
Saving an empty formula will reset it to the default value.
.. tip::
If you save a blank string the default template will be loaded.
@ -95,4 +99,10 @@ These are the format keys available for use in the format.
* - ${gravity-unit}
- Gravity format, `G` or `P`
- G
* - ${app-ver}
- Software version
- 1.1.0
* - ${app-build}
- Software revision (git hash)
- ..e456743

View File

@ -58,23 +58,9 @@ Other parameters are the same as in the configuration guide.
},
"formula-calculation-data": {
"a1":25,
"a2":30,
"a3":35,
"a4":40,
"a5":45,
"a5":0,
"a6":0,
"a7":0,
"a8":0,
"a10":0,
"g1":1,
"g2":1.01,
"g3":1.02,
"g4":1.03,
"g4":1.04,
"g5":1,
"g6":1,
"g7":1,
"g8":1
"g10":1
},
"angle": 90.93,
"gravity": 1.105,
@ -109,6 +95,7 @@ Other parameters are the same as in the configuration guide.
"temp-c": 0,
"temp-f": 32,
"battery": 0,
"wifi-ssid": "connected SSID",
"temp-format": "C",
"sleep-mode": false,
"token": "token",
@ -127,8 +114,8 @@ GET: /api/config/formula
Retrive the data used for formula calculation data via an HTTP GET command. Payload is in JSON format.
* ``a1``-``a8`` are the angles/tilt readings (up to 8 are currently supported)
* ``g1``-``g8`` are the corresponding gravity reaadings in SG or Plato depending on the device-format.
* ``a1``-``a10`` are the angles/tilt readings (up to 10 are currently supported)
* ``g1``-``g10`` are the corresponding gravity reaadings in SG or Plato depending on the device-format.
.. code-block:: json
@ -142,6 +129,8 @@ Retrive the data used for formula calculation data via an HTTP GET command. Payl
"a6": 0,
"a7": 0,
"a8": 0,
"a9": 0,
"a10": 0,
"g1": 1.000,
"g2": 1.053,
"g3": 1.062,
@ -150,6 +139,8 @@ Retrive the data used for formula calculation data via an HTTP GET command. Payl
"g6": 1,
"g7": 1,
"g8": 1,
"g9": 1,
"g10": 1,
"error": "Potential error message",
"gravity-format": "G",
"gravity-formula": "0.0*tilt^3+0.0*tilt^2+0.0017978*tilt+0.9436"
@ -165,11 +156,13 @@ Used for adjusting some internal constants and other advanced settings. Should b
{
"gyro-read-count": 50,
"gyro-read-delay": 3150,
"tempsensor-resolution": 9,
"gyro-moving-threashold": 500,
"formula-max-deviation": 1.6,
"wifi-portaltimeout": 120,
"wifi-portal-timeout": 120,
"wifi-connect-timeout": 20,
"formula-calibration-temp": 20,
"ignore-low-angles": false,
"int-http1": 0,
"int-http2": 0,
"int-http3": 0,
@ -182,8 +175,11 @@ POST: /api/config/advanced
Same parameters as above.
Payload should be in standard format used for posting a form
Payload should be in standard format used for posting a form.
.. note::
``ignore-low-angles`` is defined as "on" or "off" when posting since this is the output values
from a checkbox, when reading data it's sent as boolean (true,false).
GET: /api/clearwifi
===================
@ -324,8 +320,8 @@ POST: /api/config/formula
Used to update formula calculation data via an HTTP POST command. Payload is in JSON format.
* ``a1``-``a8`` are the angles/tilt readings (up to 5 are currently supported)
* ``g1``-``g8`` are the corresponding gravity reaadings (in SG)
* ``a1``-``a10`` are the angles/tilt readings (up to 10 are currently supported)
* ``g1``-``g10`` are the corresponding gravity reaadings (in SG)
Payload should be in standard format used for posting a form. Such as as: `id=value&mdns=value` etc. Key value pairs are shown below.
@ -340,6 +336,8 @@ Payload should be in standard format used for posting a form. Such as as: `id=va
a6=0
a7=0
a8=0
a9=0
a19=0
g1=1.000
g2=1.053
g3=1.062
@ -348,6 +346,8 @@ Payload should be in standard format used for posting a form. Such as as: `id=va
g6=1
g7=1
g8=1
g9=1
g10=1
Calling the API's from Python
@ -433,6 +433,8 @@ The requests package converts the json to standard form post format.
"a6": 0,
"a7": 0,
"a8": 0,
"a9": 0,
"a10": 0,
"g1": 1.000,
"g2": 1.053,
"g3": 1.062,
@ -440,6 +442,8 @@ The requests package converts the json to standard form post format.
"g5": 1,
"g6": 1,
"g7": 1,
"g8": 1
"g8": 1,
"g9": 1,
"g10": 1
}
set_config( url, json )

View File

@ -29,8 +29,9 @@ In the platformio config there are 3 targets defined
* gravity-debug; Maximum logging for trouble shooting, deep sleep is disabled.
* gravity-release; Standard release
* gravity-perf; Standard release but contains code for measuring performance
* gravity32-perf: Experimental version for ESP32.
* gravity-perf; Standard release but contains code for measuring performance.
* gravity32-release: Version for ESP32.
* gravity32-perf: Version for ESP32 but contains code for measuring performance.
.. note::
There is an experimental ESP32 target but since platformio only supports SDK 1.0.6 and the WIFI connection is really slow compared to ESP8266,
@ -68,8 +69,6 @@ Source structure
- Source code for software
* - /src_docs
- Source code for documentation
* - /stl
- 3d models
* - /test
- Test data for developing html files

View File

@ -22,7 +22,7 @@ copyright = '2021-2022, Magnus Persson'
author = 'Magnus Persson'
# The full version, including alpha/beta/rc tags
release = '1.0.0'
release = '1.1.0'
# -- General configuration ---------------------------------------------------

View File

@ -55,7 +55,8 @@ Device Setting
* **Device name:**
This is unique name for the device. It will be used in pushing data as well as mDNS name on the network (<name>.local)
This is unique name for the device. It will be used in pushing data as well as mDNS name on the network (<name>.local).
The limitation is 63 chars but using long names might break endpoints that data is sent to if they have other limitations.
* **Temperature format:**
@ -233,6 +234,11 @@ Hardware Settings
Factor used to calcualate the battery voltage. If you get a too low/high voltage you can adjust this value.
* **Config voltage:**
Defines the level of voltage when the device should enter config mode due to charging. This might vary between different battery manufacturers.
If you dont what the device to go into configuration mode when charging, set this to 6V.
* **Temperature correction:**
This value will be added to the temperature reading (negative value will reduce temperature reading). This is applied
@ -245,6 +251,12 @@ longer battery life (this is an experimental feature). The value used is the fir
device is activated, since the gyro should be cool this is reflecting the surronding temperature. After it has
been running the value would be totally off.
* **Enable storage mode when placed on cap**
When place on the cap (<5 degres tilt) the device will go into max sleep. In order to wake it up you need to do a reset (or wait for the device
to wake up). One option is to attach a magnetic reed switch (default open) to the reset pin and use a magnet to force a reset without opening
the tube. The reed switch is typically an electronic component of 14 mm long incapsulated in a small glass tube.
* **Bluetooth: (Only ESP32)**
If the build is using an ESP32 then you can send data over BLE, simulating a Tilt device. Choose the color that you want the device to simulate.
@ -282,7 +294,45 @@ Advanded Settings
:width: 800
:alt: Advanced Settings
* **Header:**
.. warning::
To be described
Changeing these parameters with caution. The wrong values might cause the device to become unresponsive.
* **Gyro reads:**
This defines how many gyro reads will be done before an angle is calculated. More reads will give better accuracy and also allow detection of
movement. Too many reads will take time and affecte batterylife. 50 takes about 800 ms to execute.
* **Gyro moving threashold:**
This is the max amount of deviation allowed for a stable reading.
* **Formula deviation:**
This is the maximum devation on the formlula allowed for it to be accepted. Once the formula has been derived it will be validated against the supplied
data and of the deviation on any point is bigger the formula will be rejected.
* **Ignore angles below water:**
If this option is checked any angles below that of SG 1 will be discarded as invalid and never sent to any server. Default = off.
* **DS18B20 Resolution:**
Define the resolution used on the temp sensor. 9 bits is default and will give an accuracy of 0.5C, 12 bits will give an accuracy of 0.0625C but will also
take longer time to measure..
* **Wifi connect timeout:**
This is the amount of time allowed for a wifi connect.
* **Wifi portal timeout:**
If the wifi portal is triggered (can be triggerd by reset) then this is the amount of time allowed before it exists again.
* **Skip Interval (...):**
These options allow the user to have variable push intervals for the diffrent endpoints. 0 means that every wakeup will send data to that endpoint. If you enter another number then that defines how many sleep cycles will be skipped.
If the sleep interval is 300s and MQTT is set to 0 and HTTP1 is set to 2 then MQTT will be sent every 300s while HTTP1 would be sent 900s. This is great if you want to send data to a local mqtt server often but brewfather will only
accept data every 15 min.

View File

@ -1,5 +1,33 @@
Contributing
############
Anyone is welcome to contribute to this project or create their own variant of it. I would appreciate a PR if your feature would be of benefit other users.
In order to keep the source code in good condition I use `pre-commit <https://pre-commit.com/>`_ to validate and format the code using their standards for C++/C.
.. note::
If you are using Windows as a base platform I would suggest that you install pre-commit under wsl (Windows Subssytem for Windows) and run it from there, I have found
that this approach works fine.
The following command will run pre-commit on all the source files. Assuming you are inte project directory.
.. code-block::
pre-commit run --files src/*
Design goals
------------
This section is under construction.
My goals with this software has been the following:
* Create an open software for the excellent iSpindle hardware platform that is open and available for anyone.
* Add user requested features that have not made it into the iSpindle project.
* Focus on long battery life and stability.
* Explore new technologies and create the next generation gravity monitoring for home brewers.
I will do my best to assist users and respond to new features, pr and suggestions. But keep in mind I'm doing this on my spare time.
Regards, Magnus

View File

@ -40,7 +40,7 @@ This is the format template used to create the json above.
{
"name" : "${mdns}",
"ID": "${id}",
"token" : "gravmon",
"token" : "${token}",
"interval": ${sleep-interval},
"temperature": ${temp},
"temp_units": "${temp-unit}",
@ -129,15 +129,6 @@ This is the format template used to create the json above.
ispindel/${mdns}/interval:${sleep-interval}|
ispindel/${mdns}/RSSI:${rssi}|
This is a format template that is compatible with v0.6. Just replace the `topic` with the topic you want to post data to.
.. code-block::
topic:{"name":"gravmon", "ID":"${id}", "token":"gravmon", "interval": ${sleep-interval},
"temperature": ${temp}, "temp_units": "${temp-unit}", "gravity":${gravity},
"angle": ${angle}, "battery":${battery}, "rssi": ${rssi}, "corr-gravity":${corr-gravity},
"gravity-unit": "${gravity-unit}", "run-time": ${run-time}}|
version.json
============
@ -150,13 +141,6 @@ they can be uploaded manually afterwards.
{
"project":"gravmon",
"version":"0.7.0",
"html": [
"index.min.htm",
"test.min.htm",
"config.min.htm",
"format.min.htm",
"calibration.min.htm",
"about.min.htm"
]
"version":"1.0.0",
"html": [ ]
}

View File

@ -7,10 +7,33 @@ Create formula
:width: 800
:alt: Formula data
Here you can enter up to 5 values (angles + gravity) that is then used to create the formula. Angles equal to zero will be regarded as empty even if there is a gravity reading.
Here you can enter up to 10 values (angles + gravity) that is then used to create the formula. Angles equal to zero will be regarded as empty even if there is a gravity reading.
When you submit the values the device will try create a forumla with increasing level of complexity. It will start
with a order 2 formula and then try 3 and 4.
Once the formula has been created it will validate the formula against the supplied angles/gravity and if there is a too
high difference, it will fail. You can adjust the sensitivity under advanced settings if you have issues.
Under the Error Log you will also find hints to what problem the formula creator encountered. Here is an example:
`CALC: Validation failed on angle 33.430000, deviation too large 5.86, formula order 4`
`CALC: Validation failed on angle 33.430000, deviation too large 3.14, formula order 2`
This means that the angle 33.43 had a deviation of 5.8 SG and since the default threashold is 3, it will fail. You
can also see that it has failed on that point in both a order 2 and 4 formula.
.. image:: images/qa_1.png
:width: 400
:alt: Example of deviating value
So in this case you can either increase the threashold or remove the angle that has an issue. You can also
use the graph on the calibration page to identify angles that is probably not correct.
.. image:: images/formula2.png
:width: 800
:alt: Formula graph
Once the formula is created a graph over the entered values and a simulation of the formula will give you a nice overview on how the formula will work.

View File

@ -33,10 +33,10 @@ The main features
Currently the device supports the following endpoints.
* http or https
* influxdb v2
* http (ssl optional)
* influxdb v2 (ssl optional)
* MQTT (ssl optional)
* Brewfather
* MQTT
* Home Assistant
* Brew Spy
* Brewers Friend
@ -65,11 +65,9 @@ The main features
Another big difference is that this software can create the gravity formula in the device, just enter the
angle/gravity data that you have collected. You will also see a graph simulating how the formula would work.
Currently the device can handle 5 data points which should be enough to get a accurate formula. At least 3 data points
Currently the device can handle 10 data points which should be enough to get a accurate formula. At least 3 data points
is needed to get an accurate formula.
If there is a need for more data points, raise a comment on github.
* **Customize the data format beeing sent to push targets**
In order to make it easier to support more targets there is a built in format editor that can be used to
@ -86,7 +84,8 @@ The main features
* **OTA support from webserver**
When starting up in configuration mode the device will check for a software update from a webserver. This is an easily
way to keep the software up to date. In the future I might add a hosted endpoint for providing updates.
way to keep the software up to date. In the future I might add a hosted endpoint for providing updates. OTA can also be
done over a SSL connection.
* **DS18B20 temperature adjustments**
@ -95,13 +94,14 @@ The main features
* **Gyro Movement**
The software will detect if the gyro is moving and if this is the case it will go back to sleep for 60seconds.
This way we should avoid faulty measurements and peaks in the graphs.
The software will detect if the gyro is moving and if this is the case it will go back to sleep for 60 seconds.
This way we should avoid faulty measurements and peaks in the graphs.
* **WIFI connection issues**
The software will not wait indefiently for a wifi connection. If it takes longer than 20 seconds to connect then
the device will go into deep sleep for 60 seoncds and then retry later. This to conserve batter as much as possible.
the device will try the seconday wifi configuration, and that also failes it will go into deep sleep for 60 seconds and then
retry later. This to conserve batter as much as possible.
* **Use gyro temperature sensor**

View File

@ -24,3 +24,22 @@ need to adjust the voltage factor so the battery reading is correct.
:width: 500
:alt: Mounting esp32
Schema for esp8266 build
------------------------
.. image:: images/schema_esp8266.png
:width: 700
:alt: Schema esp8266
Schema for esp32 build
----------------------
.. note::
This schema assumes that an ESP32 D1 Mini (pin compatible with ESP8266 D1 Mini is used)
The ESP32 has two rows of pins but only the inner row is used. The main difference is the added resistor R3 so we
get a voltage divider for measuring battery. The ESP8266 has a built in resistor thats not visible on the schema.
.. image:: images/schema_esp32.png
:width: 700
:alt: Schema esp32

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 MiB

After

Width:  |  Height:  |  Size: 7.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 73 KiB

View File

@ -7,7 +7,10 @@ Welcome to GravityMon's documentation!
######################################
.. note::
This documentation reflects **v1.0**. Last updated 2022-04-26
This documentation reflects **v1.1 BETA 2**. Last updated 2022-07-23
* Docs for: `v1.0 <https://mp-se.github.io/gravitymon/v1.0/index.html>`_
* Docs for: `v0.9 <https://mp-se.github.io/gravitymon/v0.9/index.html>`_
.. image:: images/gravitymon.gif
:width: 800

View File

@ -13,7 +13,8 @@ Brewflasher
===========
The prefered option for flashing GravityMon is using BrewFlasher, its a tools that support many brewing related firmwares for ESP8266 and ESP32. This works
on both Windows and Mac. You can download the latest version from here: `Brewflasher <https://www.brewflasher.com/>`_
on both Windows and Mac. You can download the latest version from here: `Brewflasher <https://www.brewflasher.com/>`_ there is also a web based version
available here `Brewflasher WEB <https://web.brewflasher.com/>`_.
.. image:: images/brewflasher.png
:width: 600
@ -34,7 +35,8 @@ In the /bin directory you will find 3 different firmware builds;
* **firmware32.bin**
This is the standard release build for an ESP32 variant
This is the standard release build for an ESP32 variant. When flashing an ESP32 you also need the **partition32.bin** file that outlines the flash memory structure. Due to
the size of the firmware we are using a custom partition setup.
In these versions all the html files are embedded in the binaries. The file system is currently only used for storing
the configuration file.
@ -90,7 +92,6 @@ browser and select the firmware.bin file that corresponds to the version you wan
``http://<device_name>/firmware.htm``
.. _serial_monitoring:
Serial Monitoring
@ -120,6 +121,14 @@ in the browser: **http://192.168.4.1**
Before pressing save on the network infomration, make a note of the devicename that is shown on the screen, this will be the name that is used
in the next step to access the configuration pages. The link would look like this: **http://gravitymon56EA34.local**
.. note::
When selecting a SSID in the list this will be populated in both wifi fields. This is the behaviour of the wifi manager library that I'm using,
in the future this is planned to be moved to the normal UI.
Under wifi settings you can define a primary and seconday wifi SSID. The seconday will be used in case the primary fails. If the seconday is
successful then it will be used as primary. *The second wifi setting is optional and not needed.*
.. image:: images/wifi.png
:width: 200
:alt: Wifi page

View File

@ -19,6 +19,12 @@ Step 2 - Setup WIFI
When the device starts up the first time it will first start an WIFI access point so that the WIFI Settings
can be configured. The instructions for that can be found here :ref:`setup_wifi`
.. note::
Since the user interface is built using modern frameworks the device requires access to the internet
for the UI to render and data to be populated. The sites that are needed are; https://cdn.jsdelivr.net/npm/bootstrap
and https://code.jquery.com
Step 3 - Configuration
----------------------

View File

@ -12,3 +12,36 @@ My device reports a temperature of -273C or -491F
-------------------------------------------------
- The DS18B20 temperature sensor cannot be found and this is the default value reported in this case.
- Check the orienation of the sensor and soldering.
Calibration error (unable to find a valid formula)
--------------------------------------------------
If you have issues to get a calibration formula. When a formula has been created the device always tries to validate the formula against the supplied values and if there is a to high deviation on any of the values then the formula will be rejected.
The image here shows such a case, one of the values is out of bounds.
.. image:: images/qa_1.png
:width: 500
:alt: Calibration Error
To fix these this you can;
- remove the value from the list (setting the angle to zero will do that)
- change the advanced setting (Formula max deviation) to a higher value and save the values again.
In the case above this paramater was changed from 1.6 SG to 4 SG and the formula was accepted. The deviation on this point was just above 3 SG.
User interface does not render correctly
----------------------------------------
Since the user interface is built using bootstrap v5 the device requires access to the internet
to download required javascripts and css files. Due to size it would not be possible to store these
on the device. Make sure the device can access: https://cdn.jsdelivr.net/npm/bootstrap
Data is not popoulated in the fields
------------------------------------
The user interface uses JQuery to fetch data from the device. This javascript library needs to be downloaded
from the internet. Due to size it would not be possible to store these on the device. Make sure the
device can access: https://code.jquery.com
Also ensure that any security tools does not block the execution of these features.

View File

@ -3,26 +3,97 @@
Releases
########
v1.1.0 - beta 2
===============
Documentation
+++++++++++++
* Fixed errors in data format section
* Added q&a on formula creation and value deviation
* Added documentation for Brewpiless as target
* Updated docs for ubidots service integration.
* Added brewblox as new service
* (beta2) Updated docs for HA integration since method was depricated
User interface
++++++++++++++
* Under format options its now possible to select brewfather ispindle format to avoid mixing endpoints.
* Added brewblox as format under format options.
* User can now edit the voltage level that forces the device into config mode (charging)
* (beta2) Calibration temperature (for temp adjustment) can now be set under advanced settings.
* (beta2) Changes length of device name from 12 to 63 chars. 63 is the max limit according to mdns.
Features
++++++++
* Added storage mode which is activated under hardware setting. When place on the cap (<5 degres tilt) the device will go into storage mode and sleep for the max allowed time.
* Added ${app-ver} and ${app-build} to format template as new variables.
* Added format templates for HA auto registration
* (beta2) Improved error messages when creating formula so the meaasurement points can be identified.
* (beta2) Changed defaule validation threashold from 1.6 SG to 3.0 SG, this should allow for some more variance when creating formula.
* (beta2) Updated format template for Home Assistant for using manual configuration (Aligned with new mqtt configuration format)
* (beta2) Added format template for Home Assistant with automatic device registration
Other
+++++
* Upgraded framework for ESP8266 to v5.0.0
* Upgraded framework for ESP32 to v2.0.2
* Updated OneWire library to be complaint with new ESP32 SDK
* Fixed issue in i2cdev connected to wrong usage of TwoWire on ESP32 (Gyro initialization hang).
Issues adressed
++++++++++++++++
* BUG: Copy format templates used an old format for iSpindle and Gravmon where the token was not used.
* BUG: Gravity correction formula not calculating correctly.
* (beta2) BUG: Temp corrected gravity was not used when pushing data to removed
* (beta2) BUG: Low memory in format api which resulted in mqtt template to be set to null
* (beta2) BUG: Large format templates could be saved but when loading it's only blank. Increased total memory from 3kb to 5kb
v1.0.0
------
* Upgraded to bootstrap v5.1 for web pages.
* Added tooltips to all fields in user interface
* Removed brewfather option (can use standard HTTP options), the old apporach can still be used via changing format template.
* Added 5 more points for formula creation, so a total of 10 angles/gravity values can be stored.
* Added function on format page so that it's easy to copy a format template from the docs (simplify service integration).
* Added https support for Influxdb
* Added possibility to have variable push intervals for different endpoints so that different frequency can be used, for example; 5min mqtt, 15min brewfather.
* Added advanced settings to configuration for adjusting some internal values (gyro reads, accepted formula deviation, timeouts, moving detection etc).
* Added additional http error codes to troubleshooting documentation
======
Documentation
+++++++++++++
* Update documentation to match v1.0
* Installation instructions updated on how to find the device after wifi has been configured.
* Documentation on brewfather has been updated to adress SG/Plato conversion
* BUG: Fixed issue in formula calculation in case there were a gap in the data series
* BUG: Field name for wifi strenght changed from "rssi" to "RSSI"
* Added circuit diagram for esp8266 and esp32
* Added additional http error codes to troubleshooting documentation
* TODO: Fix documentation for advanced settings.
User interface
++++++++++++++
* Upgraded to bootstrap v5.1 for web pages.
* Added button on indexpage to direct to github issues.
* Added button to extract important information for support requests.
* First point in gravity formula is now reserved for water gravity, this to allow detection of angles below water that can be filtered out.
* Changed layout on index page with measured data on top.
* Added tooltips to all fields in user interface
* Added function on format page so that it's easy to copy a format template from the docs (simplify service integration).
Features
++++++++
* Added advanced setting to ignore angles that are lower than water. This is disabled by default.
* Added support for MPU6500 (standard is MPU6050).
* Removed brewfather option (can use standard HTTP options), the old apporach can still be used via changing format template.
* Added 5 more points for formula creation, so a total of 10 angles/gravity values can be stored.
* Added https support for Influxdb v2
* Added possibility to set 2 wifi ssid where the second acts as a fallback in case it fails to connect. If succesful the seconday becomes the new primary.
* SSL connections are skipped on ESP8266 when in config mode since there is a high probability it will crash due to low memory.
* Advanced settings: Added possibility to have variable push intervals for different endpoints so that different frequency can be used, for example; 5min mqtt, 15min brewfather.
* Advanced settings: Changes how many times the gyro is read (less reads, quicker but less accurate)
* Advanced settings: Set amount of gyro movement is allowed for a accurate read.
* Advanced settings: What deviation is acceptable for creating formula deviation
* Advanced settings: Various timeouts, wifi connect, wifi portal, http connects.
* Advanced settings: Adjust resolution of temp sensor (9 bits to 12 bits), higher resolution takes longer thus reducing batterylife
Issues adressed
++++++++++++++++
* BUG: Fixed issue in formula calculation in case there were a gap in the data series
* BUG: Field name for wifi strength changed from "rssi" to "RSSI"
* BUG: Fixed issue with probing MFLN on non standard ports
* BUG: Changed http connection to keep-alive so that server does not close port before the client has had a chance to read the response.
v0.9.0
------
======
* Added one http push target that uses HTTP GET. This can be used with ubidots or blynk api's.
* Added function to test push targets from configuration page. It will send data and show the return code as a first step.
* Added documetation on how to integrate with Blynk.io using http get.
@ -47,8 +118,7 @@ v0.9.0
* BUG: Entering wifi setup and a timeout occured the wifi settings could be deleted.
v0.8.0
------
======
* Added option to set http headers (2 per http endpoint), these can be used for
other http formats than json (default) and for adding authentication headers.
* Added possibility to view last 10 errors on device page.
@ -68,8 +138,7 @@ v0.8.0
* Tested batterylife, 47 days using an update frequency of 5 min
v0.7.1
------
======
* Added instructions for how to configure integration with Fermentrack
* Added instructions for how to configure integration with Ubidots
* Added instructions for how to configure integration with HomeAssistant
@ -79,8 +148,7 @@ v0.7.1
* BUG: Fixed issue with default template so it now includes the device name correctly.
v0.7.0
------
======
Latest stable version. `Release v0.7 on Github <https://github.com/mp-se/gravitymon/releases/tag/v0.7.0>`_
* SSL support for HTTP targets
@ -106,10 +174,7 @@ Latest stable version. `Release v0.7 on Github <https://github.com/mp-se/gravity
the behaviour in v0.6 is wanted this can be done via the format editor.
v0.6.0
------
`Release v0.6 on Github <https://github.com/mp-se/gravitymon/releases/tag/v0.6.0>`_
======
* Changed the wifi manager and refactored wifi.cpp
* LED is now turned on when Wifi Portal is open
* Refactored main.cpp to make it easier to read
@ -122,10 +187,7 @@ v0.6.0
* Bug: MPU init sometimes caused crash during startup.
v0.5.0
------
`Release v0.5 on Github <https://github.com/mp-se/gravitymon/releases/tag/v0.5.0>`_
======
* Added feature to calcuate formula on device
* Total rewrite of documentation
* WIFI settings are now stored in config file
@ -134,8 +196,5 @@ v0.5.0
* Refactor code from C to C++
v0.4.0
------
`Release v0.4 on Github <https://github.com/mp-se/gravitymon/releases/tag/v0.4.0>`_
* First release
======
* First public release

View File

@ -75,7 +75,9 @@ GravityMon can be installed and used as an iSpindle. Just register the device as
UBIdots
+++++++
`UBIdots <https://www.ubidots.com>`_ is a IoT service that display data collected various sources.
`UBIdots <https://www.ubidots.com>`_ is a IoT service that display data collected various sources. There is a limitation on this service where it can only handle 10 variables per device so
you might need to reduce the number of values sent to the service. It will also treat every parameter as a number unless you create a custom device type and explicit define the string values
as text. This will require a paid subscription (as I interpret the documentation). The example format below will only send numbers so that should work fine with the paid subscription.
For this service there are two options to configure the integration. First you will need your default token which is found under `API Credentials` (<api-tokem> in the example below).
Swap the text <devicename> with the name you want to show in ubidots.
@ -120,14 +122,14 @@ format template that can be used. For information on customizing the format see
"gravity": ${gravity},
"angle": ${angle},
"battery": ${battery},
"rssi": ${rssi}
"RSSI": ${rssi}
}
Home Assistant
+++++++++++++++
`HomeAssistant <https://www.homeassistant.com>`_ is a platform for home automation and can collect sensor data
`HomeAssistant <https://www.homeassistant.io>`_ is a platform for home automation and can collect sensor data
from multiple devices.
This setup uses the MQTT integration with home assistant to collect values from the device.
@ -137,27 +139,50 @@ device is named `gravmon2`
::
mqtt:
sensor:
- platform: mqtt
name: "gravmon2_gravity"
state_topic: "gravmon/gravmon2/gravity"
- platform: mqtt
name: "gravmon2_battery"
state_topic: "gravmon/gravmon2/battery"
- platform: mqtt
name: "gravmon2_rssi"
state_topic: "gravmon/gravmon2/rssi"
- name: "Gravmon2-Gravity"
state_topic: "gravmon/gravmon2/gravity"
unique_id: gravmon2_grav
unit_of_measurement: "SG"
- name: "Gravmon2-RSSI"
state_topic: "gravmon/gravmon2/rssi"
unique_id: gravmon2_rssi
unit_of_measurement: "dBm"
Enter the name of the MQTT server in Home Assistant in the URL. You might need to install that option
first. This is the format needed to submit the data to the correct topics as needed above. You can add as
many sensors / topics as you want.
many sensors / topics as you want. It's also possible that you will need to create a user and supply the
username / password to be able to publish messages on a topic.
::
gravmon/${mdns}/gravity:${gravity}|
gravmon/${mdns}/rssi:${rssi}|
gravmon/${mdns}/battery:${battery}|
It's also possible to allow home assistant to do autodisovery and automatically create the sensor. This format
template will create two sensors and update the values for them.
.. warning::
This will only work on 1.1+ since the the memory allocation on previous versions are not enough to handle this large payload.
Earlier version can handle 2 of the values.
::
gravmon/${mdns}/tilt:${angle}|
gravmon/${mdns}/temperature:${temp}|
gravmon/${mdns}/temp_units:${temp-unit}|
gravmon/${mdns}/gravity:${gravity}|
gravmon/${mdns}/rssi:${rssi}|
gravmon/${mdns}/tilt:${tilt}|
gravmon/${mdns}/battery:${battery}|
homeassistant/sensor/gravmon_${id}/temperature/config:{"dev":{"name":"${mdns}","mdl":"gravmon","sw":"${app-ver}","ids":"${id}"},"uniq_id":"${id}_temp","name":"temperature","dev_cla":"temperature","unit_of_meas":"${temp-unit}","stat_t":"gravmon/${mdns}/temperature"}|
homeassistant/sensor/gravmon_${id}/gravity/config:{"dev":{"name":"${mdns}","mdl":"gravmon","sw":"${app-ver}","ids":"${id}"},"uniq_id":"${id}_grav","name":"gravity","dev_cla":"temperature","unit_of_meas":" ${gravity-unit}","stat_t":"gravmon/${mdns}/gravity"}|
homeassistant/sensor/gravmon_${id}/rssi/config:{"dev":{"name":"${mdns}","mdl":"gravmon","sw":"${app-ver}","ids":"${id}"},"uniq_id":"${id}_rssi","name":"rssi","dev_cla":"temperature","unit_of_meas":"dBm","stat_t":"gravmon/${mdns}/rssi"}|
homeassistant/sensor/gravmon_${id}/tilt/config:{"dev":{"name":"${mdns}","mdl":"gravmon","sw":"${app-ver}","ids":"${id}"},"uniq_id":"${id}_tilt","name":"tilt","dev_cla":"temperature","stat_t":"gravmon/${mdns}/tilt"}|
homeassistant/sensor/gravmon_${id}/battery/config:{"dev":{"name":"${mdns}","mdl":"gravmon","sw":"${app-ver}","ids":"${id}"},"uniq_id":"${id}_batt","name":"battery","dev_cla":"temperature","unit_of_meas":"V","stat_t":"gravmon/${mdns}/battery"}|
Brewer's Friend
@ -194,7 +219,7 @@ format for the endpoint. Just add you API key after token.
"gravity": ${gravity},
"angle": ${angle},
"battery": ${battery},
"rssi": ${rssi}
"RSSI": ${rssi}
}
@ -261,3 +286,43 @@ starting with a ``?``. This string will be added to the URL above when doing the
?token=${token2}&v1=${temp}&v2=${gravity}&v3=${angle}
Brewpiless
++++++++++
If you connect the device to the brewpiless access point there is not way to access the user interface for configuration so it's recommended to connect the device to your normal network.
The device need to have a name starting with iSpindle, for example `iSpindel000`. Set the URL for one of the http POST targets to `http://ip/gravity` where ip is the ip adress of Brewpiless.
BrewBlox
++++++++++
To send iSpindel data to brewblox over mqtt you need to modify the format template to match the expected format. Once you have configured the mqtt information you also need to update the format template
for this target.
This format template will post the expected json document on the topic, dont forget the `|` character at the end of the line which is needed to parse the payload. The first to words are the topic
name and after the first `:` this is the json playload. Text within the brackets will be used as the unit for the value and degC is displayed as °C. You can add other parameters under the data section
in the json document if you need other values as well.
.. code-block::
brewcast/history:{"key":"${mdns}","data":{"Temperature[degC]": ${temp-c},"Temperature[degF]": ${temp-f},"Battery[V]":${battery},"Tilt[deg]":${angle},"Rssi[dBm]":${rssi},"SG":${gravity-sg},"Plato":${gravity-plato}}}|
The json message on the mqtt topic would look like this:
.. code-block:: json
{
"key": "gravitymon",
"data": {
"Temperature[degC]": 27,
"Temperature[degF]": 80,
"Battery[V]": 4.1,
"Tilt[deg]": 25,
"Rssi[dBm]": -78,
"SG": 1,
"Plato": 0
}
}

View File

@ -53,9 +53,15 @@ Log errors
* -9 - Error encoding
* -10 - Error writing to stream
* -11 - Read timeout
* -100 - Endpoint skipped since its SSL and the device is in gravity mode
* MQTT push on <topic> failed error
* -1 - Buffer to short
* -2 - Overflow
* -3 - Network failed connected
* -4 - Network timeout
* -5 - Network read failed
* -6 - Network write failed
* -10 - Connection denied
* -11 - Failed subscription

View File

@ -1,15 +1,16 @@
{
"gyro-read-count": 51,
"gyro-moving-threashold": 501,
"formula-max-deviation": 1.7,
"wifi-portal-timeout": 121,
"wifi-connect-timeout": 21,
"formula-calibration-temp": 21,
"tempsensor-resolution": 12,
"gyro-read-count": 50,
"gyro-moving-threashold": 500,
"formula-max-deviation": 1.6,
"wifi-portal-timeout": 120,
"wifi-connect-timeout": 20,
"push-timeout": 10,
"int-http1": 1,
"int-http2": 2,
"int-http3": 3,
"int-influx": 4,
"int-mqtt": 5
"formula-calibration-temp": 20,
"int-http1": 0,
"int-http2": 0,
"int-http3": 0,
"int-influx": 0,
"int-mqtt": 0,
"tempsensor-resolution": 9,
"ignore-low-angles": false
}

View File

@ -20,8 +20,10 @@
"mqtt-port": 1883,
"mqtt-user": "user",
"mqtt-pass": "pass",
"storage-sleep": true,
"sleep-interval": 30,
"voltage-factor": 1.59,
"voltage-config": 4.15,
"gravity-formula": "0.0*tilt^3+0.0*tilt^2+0.0017978*tilt+0.9436",
"gravity-format": "G",
"temp-adjustment-value": 0,
@ -35,10 +37,34 @@
"gy": -6,
"gz": 4
},
"formula-calculation-data": {
"a1": 25,
"a3": 35,
"a2": 45,
"a4": 55,
"a5": 30,
"a6": 30,
"a7": 30,
"a8": 30,
"a9": 30,
"a10": 30,
"g1": 1.000,
"g3": 1.010,
"g2": 1.025,
"g4": 1.040,
"g5": 1.005,
"g6": 1.005,
"g7": 1.005,
"g8": 1.005,
"g9": 1.005,
"g10": 1.005
},
"angle": 90.93,
"gravity": 1.105,
"battery": 0.04,
"runtime-average": 3.0,
"ble": "pink",
"app-ver": "0.1.0",
"app-build": "build",
"platform": "esp32"
}

View File

@ -21,5 +21,6 @@
"g8": 1.005,
"g9": 1.005,
"g10": 1.005,
"error": ""
"error": "",
"gravity-format": "P"
}

4
test/log Normal file
View File

@ -0,0 +1,4 @@
Line 1
Line 2
Line 3
Line 4

View File

@ -1,8 +1,22 @@
{
"index": false,
"index": true,
"config": false,
"calibration": false,
"format": false,
"calibration": true,
"format": true,
"about": false,
"test": false,
"about": true
"files": [
{
"file-name": "calibration.min.htm",
"file-size": 0
},
{
"file-name": "drd.dat",
"file-size": 4
},
{
"file-name": "error.log",
"file-size": 839
}
]
}