43 Commits

Author SHA1 Message Date
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
66 changed files with 741 additions and 319 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.

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) 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: The main differences:
--------------------- ---------------------
@ -23,17 +25,14 @@ The main differences:
* Efficient software, long lifespan (+45 days with 5min update frequencey) * Efficient software, long lifespan (+45 days with 5min update frequencey)
* Send data to multiple endpoints (http-post, http-get, influxdb v2, mqtt) * 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. * 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 * ESP32 support with Bluetooth push
* Customize data format to be pushed * Customize data format to be pushed
* Automatic temperature adjustment of gravity when enabled * Automatic temperature adjustment of gravity when enabled
* Use the temperature sensor in gyro instead of DS18B20 * 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. * 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 * Visual graph showing how gravity formula will be interpreted
* OTA support * OTA support or firmware upload via web interface
* Built in performance measurements (used to optimise code) * REST API for scripting
* REST API for scripting
No code has been reused from the iSpindle project. 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

@ -97,7 +97,8 @@
<div class="row mb-3"> <div class="row mb-3">
<label for="angle1" class="col-sm-1 col-form-label">1.</label> <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="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>
<div class="row mb-3"> <div class="row mb-3">
@ -369,6 +370,7 @@
if(isPlato()) { if(isPlato()) {
$("#gravity-header").text("Gravity (Plato):"); $("#gravity-header").text("Gravity (Plato):");
$("#g1").val( parseFloat(cfg["g1"]).toFixed(1) ); $("#g1").val( parseFloat(cfg["g1"]).toFixed(1) );
$("#g1a").val( "0.0" );
$("#g2").val( parseFloat(cfg["g2"]).toFixed(1) ); $("#g2").val( parseFloat(cfg["g2"]).toFixed(1) );
$("#g3").val( parseFloat(cfg["g3"]).toFixed(1) ); $("#g3").val( parseFloat(cfg["g3"]).toFixed(1) );
$("#g4").val( parseFloat(cfg["g4"]).toFixed(1) ); $("#g4").val( parseFloat(cfg["g4"]).toFixed(1) );
@ -381,6 +383,7 @@
} else { } else {
$("#gravity-header").text("Gravity (SG):"); $("#gravity-header").text("Gravity (SG):");
$("#g1").val( parseFloat(cfg["g1"]).toFixed(4) ); $("#g1").val( parseFloat(cfg["g1"]).toFixed(4) );
$("#g1a").val( "1.0000" );
$("#g2").val( parseFloat(cfg["g2"]).toFixed(4) ); $("#g2").val( parseFloat(cfg["g2"]).toFixed(4) );
$("#g3").val( parseFloat(cfg["g3"]).toFixed(4) ); $("#g3").val( parseFloat(cfg["g3"]).toFixed(4) );
$("#g4").val( parseFloat(cfg["g4"]).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> <input type="text" name="id" id="id1" hidden>
<div class="row mb-3"> <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"> <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="12" 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> </div>
<div class="row mb-3"> <div class="row mb-3">
<fieldset class="form-group row"> <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="col-sm-4">
<div class="form-check"> <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"> <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>
<div class="form-check"> <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"> <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>
</div> </div>
</fieldset> </fieldset>
</div> </div>
<div class="row mb-3"> <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"> <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> </div>
<label for="sleep-interval" class="col-sm-4 col-form-label" id="sleep-interval-info"></label> <label for="sleep-interval" class="col-sm-4 col-form-label" id="sleep-interval-info"></label>
</div> </div>
@ -145,7 +145,7 @@
<hr class="my-2"> <hr class="my-2">
<div class="row mb-3"> <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="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> <label for="gyro-calibration-data" class="col-sm-2 col-form-label" id="angle">Loading...</label>
<div class="col-sm-8 offset-sm-2"> <div class="col-sm-8 offset-sm-2">
@ -174,7 +174,7 @@
<input type="text" name="http-push2-h2" id="http-push2-h2" hidden> <input type="text" name="http-push2-h2" id="http-push2-h2" hidden>
<div class="row mb-3"> <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"> <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)"> <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> </div>
@ -184,7 +184,7 @@
</div> </div>
<div class="row mb-3"> <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"> <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)"> <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> </div>
@ -194,21 +194,21 @@
</div> </div>
<div class="row mb-3"> <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"> <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"> <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> </div>
<div class="row mb-3"> <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"> <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"> <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> </div>
<div class="row mb-3"> <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"> <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"> <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> </div>
@ -246,28 +246,28 @@
<input type="text" name="section" value="collapsePush2" hidden> <input type="text" name="section" value="collapsePush2" hidden>
<div class="row mb-3"> <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"> <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)"> <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> </div>
<div class="row mb-3"> <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"> <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"> <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> </div>
<div class="row mb-3"> <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"> <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"> <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> </div>
<div class="row mb-3"> <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"> <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"> <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> </div>
@ -276,28 +276,28 @@
<hr class="my-2"> <hr class="my-2">
<div class="row mb-3"> <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"> <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"> <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> </div>
<div class="row mb-3"> <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"> <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> </div>
<div class="row mb-3"> <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"> <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"> <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> </div>
<div class="row mb-3"> <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"> <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"> <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> </div>
@ -335,7 +335,7 @@
<div class="row mb-3"> <div class="row mb-3">
<fieldset class="form-group row"> <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="col-sm-4">
<div class="form-check"> <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"> <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"> <div class="row mb-3">
<label for="gravity-formula" class="col-sm-2 col-form-label">Formula</label> <label for="gravity-formula" class="col-sm-2 col-form-label">Formula</label>
<div class="col-sm-10"> <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> </div>
<div class="row mb-3"> <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"> <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"> <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> <label class="form-check-label" for="gravity-temp-adjustment">Temperature adjust gravity</label>
@ -388,17 +388,17 @@
<input type="text" name="id" id="id4" hidden> <input type="text" name="id" id="id4" hidden>
<div class="row mb-3"> <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"> <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. When running on battery, the voltage should be less than 4.15V">
</div> </div>
<label for="voltage-factor" class="col-sm-3 col-form-label" id="battery">Loading...</label> <label for="voltage-factor" class="col-sm-3 col-form-label" id="battery">Loading...</label>
</div> </div>
<div class="row mb-3"> <div class="row mb-3">
<label for="temp-adjustment-value" class="col-sm-2 col-form-label">Temp Sensor Adj:</label> <label for="temp-adjustment-value" class="col-sm-2 col-form-label">Temp Sensor Adj</label>
<div class="col-sm-2"> <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=".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> </div>
@ -429,7 +429,7 @@
</div> </div>
<div class="row mb-3"> <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"> <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/"> <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> </div>
@ -453,45 +453,64 @@
<div class="accordion-item"> <div class="accordion-item">
<h2 class="accordion-header" id="headingAdvanced"> <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"> <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> </button>
</h2> </h2>
<div id="collapseAdvanced" class="accordion-collapse collapse" aria-labelledby="headingAdvanced" data-bs-parent="#accordion"> <div id="collapseAdvanced" class="accordion-collapse collapse" aria-labelledby="headingAdvanced" data-bs-parent="#accordion">
<div class="accordion-body"> <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"> <form action="/api/config/advanced" method="post">
<input type="text" name="id" id="id6" hidden> <input type="text" name="id" id="id6" hidden>
<div class="row mb-3"> <div class="row mb-3">
<label for="gyro-read-count" class="col-sm-3 col-form-label">Gyro reads:</label> <label for="gyro-read-count" class="col-sm-3 col-form-label">Gyro reads:</label>
<div class="col-sm-2"> <div class="col-sm-3">
<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"> <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>
<div class="col-sm-5">(10-100) - default 50</div> <div class="col-sm-5">(10-100) - default 50</div>
</div> </div>
<div class="row mb-3"> <div class="row mb-3">
<label for="gyro-moving-threashold" class="col-sm-3 col-form-label">Gyro moving theashold:</label> <label for="gyro-moving-threashold" class="col-sm-3 col-form-label">Gyro moving theashold</label>
<div class="col-sm-2"> <div class="col-sm-3">
<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"> <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>
<div class="col-sm-5">(50-1000) - default 500</div> <div class="col-sm-5">(50-1000) - default 500</div>
</div> </div>
<div class="row mb-3"> <div class="row mb-3">
<label for="formula-max-deviation" class="col-sm-3 col-form-label">Formula max deviation (SG):</label> <label for="formula-max-deviation" class="col-sm-3 col-form-label">Formula max deviation (SG)</label>
<div class="col-sm-2"> <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" checked data-bs-toggle="tooltip" title="When validating the derived formula this is the maximum accepted deviation for the supplied values"> <input disabled type="number" step=".1" min="1" max="10" class="form-control" name="formula-max-deviation" id="formula-max-deviation" placeholder="1.6" checked data-bs-toggle="tooltip" title="When validating the derived formula this is the maximum accepted deviation for the supplied values">
</div> </div>
<div class="col-sm-5">(1 - 10) - default 1.6 SG</div> <div class="col-sm-5">(1 - 10) - default 1.6 SG</div>
</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>
<hr> <hr>
<div class="row mb-3"> <div class="row mb-3">
<label for="tempsensor-resolution" class="col-sm-3 col-form-label">DS18B20 resolution (bits):</label> <label for="tempsensor-resolution" class="col-sm-3 col-form-label">DS18B20 resolution (bits)</label>
<div class="col-sm-2"> <div class="col-sm-3">
<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"> <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>
<div class="col-sm-5">(9 - 12) - default 9 bits</div> <div class="col-sm-5">(9 - 12) - default 9 bits</div>
</div> </div>
@ -499,17 +518,17 @@
<hr> <hr>
<div class="row mb-3"> <div class="row mb-3">
<label for="wifi-connect-timeout" class="col-sm-3 col-form-label">Wifi connect timeout (s):</label> <label for="wifi-connect-timeout" class="col-sm-3 col-form-label">Wifi connect timeout (s)</label>
<div class="col-sm-2"> <div class="col-sm-3">
<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"> <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>
<div class="col-sm-5">(1 - 60) - default 20 s</div> <div class="col-sm-5">(1 - 60) - default 20 s</div>
</div> </div>
<div class="row mb-3"> <div class="row mb-3">
<label for="wifi-portal-timeout" class="col-sm-3 col-form-label">Wifi portal timeout (s):</label> <label for="wifi-portal-timeout" class="col-sm-3 col-form-label">Wifi portal timeout (s)</label>
<div class="col-sm-2"> <div class="col-sm-3">
<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"> <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>
<div class="col-sm-5">(10 - 240) - default 120 s</div> <div class="col-sm-5">(10 - 240) - default 120 s</div>
</div> </div>
@ -518,40 +537,40 @@
<div class="row mb-3"> <div class="row mb-3">
<label for="int-http1" class="col-sm-3 col-form-label">Skip interval - HTTP 1 (POST):</label> <label for="int-http1" class="col-sm-3 col-form-label">Skip interval - HTTP 1 (POST):</label>
<div class="col-sm-2"> <div class="col-sm-3">
<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"> <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>
<div class="col-sm-5">(0 - 5) - default 0</div> <div class="col-sm-5">(0 - 5) - default 0</div>
</div> </div>
<div class="row mb-3"> <div class="row mb-3">
<label for="int-http2" class="col-sm-3 col-form-label">Skip interval - HTTP 2 (POST):</label> <label for="int-http2" class="col-sm-3 col-form-label">Skip interval - HTTP 2 (POST)</label>
<div class="col-sm-2"> <div class="col-sm-3">
<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"> <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>
<div class="col-sm-5">(0 - 5) - default 0</div> <div class="col-sm-5">(0 - 5) - default 0</div>
</div> </div>
<div class="row mb-3"> <div class="row mb-3">
<label for="int-http3" class="col-sm-3 col-form-label">Skip interval - HTTP 3 (GET):</label> <label for="int-http3" class="col-sm-3 col-form-label">Skip interval - HTTP 3 (GET)</label>
<div class="col-sm-2"> <div class="col-sm-3">
<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"> <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>
<div class="col-sm-5">(0 - 5) - default 0</div> <div class="col-sm-5">(0 - 5) - default 0</div>
</div> </div>
<div class="row mb-3"> <div class="row mb-3">
<label for="int-influx" class="col-sm-3 col-form-label">Skip interval - InfluxDB v2:</label> <label for="int-influx" class="col-sm-3 col-form-label">Skip interval - InfluxDB v2</label>
<div class="col-sm-2"> <div class="col-sm-3">
<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"> <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>
<div class="col-sm-5">(0 - 5) - default 0</div> <div class="col-sm-5">(0 - 5) - default 0</div>
</div> </div>
<div class="row mb-3"> <div class="row mb-3">
<label for="int-mqtt" class="col-sm-3 col-form-label">Skip interval - MQTT:</label> <label for="int-mqtt" class="col-sm-3 col-form-label">Skip interval - MQTT</label>
<div class="col-sm-2"> <div class="col-sm-3">
<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"> <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>
<div class="col-sm-5">(0 - 5) - default 0</div> <div class="col-sm-5">(0 - 5) - default 0</div>
</div> </div>
@ -563,15 +582,6 @@
</div> </div>
</form> </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>
</div> </div>
@ -747,7 +757,7 @@
function checkAdvancedSection( b ) { function checkAdvancedSection( b ) {
var b = $("#adv-config").is(":checked"); var b = $("#adv-config").is(":checked");
$("#advanced-btn").prop("disabled", b); $("#advanced-btn").prop("disabled", b);
$("#gyro-read-count").prop("disabled", b); $("#gyro-read-count").prop("disabled", b);
$("#gyro-moving-threashold").prop("disabled", b); $("#gyro-moving-threashold").prop("disabled", b);
@ -760,6 +770,7 @@
$("#int-influx").prop("disabled", b); $("#int-influx").prop("disabled", b);
$("#int-mqtt").prop("disabled", b); $("#int-mqtt").prop("disabled", b);
$("#tempsensor-resolution").prop("disabled", b); $("#tempsensor-resolution").prop("disabled", b);
$("#ignore-low-angles").prop("disabled", b);
} }
// Get the advanced values from the API // Get the advanced values from the API
@ -778,11 +789,17 @@
$("#wifi-portal-timeout").val(cfg["wifi-portal-timeout"]); $("#wifi-portal-timeout").val(cfg["wifi-portal-timeout"]);
$("#wifi-connect-timeout").val(cfg["wifi-connect-timeout"]); $("#wifi-connect-timeout").val(cfg["wifi-connect-timeout"]);
$("#tempsensor-resolution").val(cfg["tempsensor-resolution"]); $("#tempsensor-resolution").val(cfg["tempsensor-resolution"]);
$("#ignore-low-angles").prop( "checked", cfg["ignore-low-angles"] );
$("#int-http1").val(cfg["int-http1"]); $("#int-http1").val(cfg["int-http1"]);
$("#int-http2").val(cfg["int-http2"]); $("#int-http2").val(cfg["int-http2"]);
$("#int-http3").val(cfg["int-http3"]); $("#int-http3").val(cfg["int-http3"]);
$("#int-influx").val(cfg["int-influx"]); $("#int-influx").val(cfg["int-influx"]);
$("#int-mqtt").val(cfg["int-mqtt"]); $("#int-mqtt").val(cfg["int-mqtt"]);
if ( cfg["gyro-read-count"] != 50 || cfg["gyro-moving-threashold"] != 500 || cfg["formula-max-deviation"] != 1.6 || 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 ) {
$("#adv-config").attr("checked", false );
}
}) })
.fail(function () { .fail(function () {
showError('Unable to get data from the device.'); showError('Unable to get data from the device.');
@ -847,6 +864,7 @@
$("#battery").text(cfg["battery"] + " V"); $("#battery").text(cfg["battery"] + " V");
$("#angle").text(cfg["angle"]); $("#angle").text(cfg["angle"]);
$("#runtime-average").val(cfg["runtime-average"]); $("#runtime-average").val(cfg["runtime-average"]);
$("#water-angle").text( "(Water angle: " + cfg["formula-calculation-data"]["a1"] + ") - default off");
//$("#gravity").text(cfg["gravity"] + " SG"); //$("#gravity").text(cfg["gravity"] + " SG");
}) })
.fail(function () { .fail(function () {

File diff suppressed because one or more lines are too long

View File

@ -102,7 +102,7 @@
{ "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": "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-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": "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": "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": "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> </script>
<div class="row mb-3"> <div class="row mb-3">
@ -115,7 +115,7 @@
<option value="GravityMon-Post">GravityMon (POST)</option> <option value="GravityMon-Post">GravityMon (POST)</option>
<option value="iSpindle-Mqtt">iSpindle (MQTT)</option> <option value="iSpindle-Mqtt">iSpindle (MQTT)</option>
<option value="HomeAssistant-Mqtt">Home Assistant (MQTT)</option> <option value="HomeAssistant-Mqtt">Home Assistant (MQTT)</option>
<option value="UBIDots1-Post">UBIdots - Alternative 1 (POST)</option> <option value="UBIDots-Post">UBIdots (POST)</option>
<option value="BrewFatherCustom-Post">Brewfather Custom Endpoint (POST)</option> <option value="BrewFatherCustom-Post">Brewfather Custom Endpoint (POST)</option>
<option value="GravityMon-Get">GravityMon (GET)</option> <option value="GravityMon-Get">GravityMon (GET)</option>
</select> </select>
@ -241,7 +241,7 @@
var json = JSON.parse(doc); var json = JSON.parse(doc);
doc = JSON.stringify(json, null, 2); doc = JSON.stringify(json, null, 2);
} catch(e) { } catch(e) {
console.log("Not a javascript object!") console.log("Not a JSON object!")
} }
$("#preview").text(doc); $("#preview").text(doc);

File diff suppressed because one or more lines are too long

View File

@ -73,66 +73,6 @@
</script> </script>
<div class="accordion" id="accordion"> <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"> <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"> <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> </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>
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
var debug = {};
window.onload = start; 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){ $("#sleep-mode").click(function(e){
console.log( "Blocking sleep mode = " + $("#sleep-mode").is(":checked")); console.log( "Blocking sleep mode = " + $("#sleep-mode").is(":checked"));
$.ajax( { $.ajax( {

File diff suppressed because one or more lines are too long

View File

@ -66,7 +66,7 @@ void MPU6050_Base::initialize() {
* @return True if connection is valid, false otherwise * @return True if connection is valid, false otherwise
*/ */
bool MPU6050_Base::testConnection() { bool MPU6050_Base::testConnection() {
return getDeviceID() == 0x34; return getDeviceID() == 0x34 || getDeviceID() == 0x38; // Allow both MPU6050 and MPU6000
} }
// AUX_VDDIO register (InvenSense demo code calls this RA_*G_OFFS_TC) // AUX_VDDIO register (InvenSense demo code calls this RA_*G_OFFS_TC)

View File

@ -34,8 +34,8 @@ build_flags =
-D USER_SSID=\""\"" # =\""myssid\"" -D USER_SSID=\""\"" # =\""myssid\""
-D USER_SSID_PWD=\""\"" # =\""mypwd\"" -D USER_SSID_PWD=\""\"" # =\""mypwd\""
-D CFG_APPVER="\"1.0.0\"" -D CFG_APPVER="\"1.0.0\""
-D CFG_GITREV=\""beta-1\"" #-D CFG_GITREV=\""beta-2\""
#!python script/git_rev.py !python script/git_rev.py
lib_deps = # Switched to forks for better version control. lib_deps = # Switched to forks for better version control.
# Using local copy of these libraries # Using local copy of these libraries
#https://github.com/jrowberg/i2cdevlib.git#<document> #https://github.com/jrowberg/i2cdevlib.git#<document>

View File

@ -35,7 +35,8 @@ int createFormula(RawFormulaData &fd, char *formulaBuffer,
int noAngles = 0; int noAngles = 0;
RawFormulaData fd2; 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++) { for (int i = 0; i < FORMULA_DATA_SIZE; i++) {
if (fd.a[i]) { if (fd.a[i]) {
fd2.a[noAngles] = fd.a[i]; fd2.a[noAngles] = fd.a[i];
@ -50,7 +51,7 @@ int createFormula(RawFormulaData &fd, char *formulaBuffer,
order, noAngles); order, noAngles);
#endif #endif
if (noAngles <3) { if (noAngles < 3) {
ErrorFileLog errLog; ErrorFileLog errLog;
errLog.addEntry(F("CALC: Not enough values for deriving formula")); errLog.addEntry(F("CALC: Not enough values for deriving formula"));
return ERR_FORMULA_NOTENOUGHVALUES; return ERR_FORMULA_NOTENOUGHVALUES;
@ -62,7 +63,8 @@ int createFormula(RawFormulaData &fd, char *formulaBuffer,
// Returned value is 0 if no error // Returned value is 0 if no error
if (ret == 0) { if (ret == 0) {
#if LOG_LEVEL == 6 && !defined(CALC_DISABLE_LOGGING) #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 #endif
// Print the formula based on 'order' // Print the formula based on 'order'

View File

@ -390,7 +390,8 @@ bool AdvancedConfig::saveFile() {
doc[PARAM_HW_PUSH_INTERVAL_HTTP3] = this->getPushIntervalHttp3(); doc[PARAM_HW_PUSH_INTERVAL_HTTP3] = this->getPushIntervalHttp3();
doc[PARAM_HW_PUSH_INTERVAL_INFLUX] = this->getPushIntervalInflux(); doc[PARAM_HW_PUSH_INTERVAL_INFLUX] = this->getPushIntervalInflux();
doc[PARAM_HW_PUSH_INTERVAL_MQTT] = this->getPushIntervalMqtt(); 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) #if LOG_LEVEL == 6 && !defined(DISABLE_LOGGING)
serializeJson(doc, Serial); serializeJson(doc, Serial);
@ -478,7 +479,10 @@ bool AdvancedConfig::loadFile() {
if (!doc[PARAM_HW_PUSH_INTERVAL_MQTT].isNull()) if (!doc[PARAM_HW_PUSH_INTERVAL_MQTT].isNull())
this->setPushIntervalMqtt(doc[PARAM_HW_PUSH_INTERVAL_MQTT].as<int>()); this->setPushIntervalMqtt(doc[PARAM_HW_PUSH_INTERVAL_MQTT].as<int>());
if (!doc[PARAM_HW_TEMPSENSOR_RESOLUTION].isNull()) 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)); Log.notice(F("CFG : Configuration file " CFG_HW_FILENAME " loaded." CR));
return true; return true;

View File

@ -70,6 +70,7 @@ class AdvancedConfig {
int _pushIntervalHttp3 = 0; int _pushIntervalHttp3 = 0;
int _pushIntervalInflux = 0; int _pushIntervalInflux = 0;
int _pushIntervalMqtt = 0; int _pushIntervalMqtt = 0;
bool _IgnoreLowAnges = false;
public: public:
int getWifiPortalTimeout() { return _wifiPortalTimeout; } int getWifiPortalTimeout() { return _wifiPortalTimeout; }
@ -86,9 +87,8 @@ class AdvancedConfig {
} }
int getTempSensorResolution() { return _tempSensorResolution; } int getTempSensorResolution() { return _tempSensorResolution; }
void setTempSensorResolution(int t) { void setTempSensorResolution(int t) {
if (t>=9 && t<=12) if (t >= 9 && t <= 12) _tempSensorResolution = t;
_tempSensorResolution = t;
} }
float getDefaultCalibrationTemp() { return _defaultCalibrationTemp; } float getDefaultCalibrationTemp() { return _defaultCalibrationTemp; }
@ -128,6 +128,9 @@ class AdvancedConfig {
: true; : true;
} }
const bool isIgnoreLowAnges() { return _IgnoreLowAnges; }
void setIgnoreLowAnges(bool b) { _IgnoreLowAnges = b; }
bool saveFile(); bool saveFile();
bool loadFile(); bool loadFile();
}; };

View File

@ -318,7 +318,9 @@ void PerfLogging::pushInflux() {
if (!myConfig.isInfluxDb2Active()) return; if (!myConfig.isInfluxDb2Active()) return;
if (myConfig.isInfluxSSL()) { 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; return;
} }

View File

@ -32,7 +32,7 @@ SOFTWARE.
#include <webserver.hpp> #include <webserver.hpp>
#include <wifi.hpp> #include <wifi.hpp>
//#define FORCE_GRAVITY_MODE // #define FORCE_GRAVITY_MODE
// Define constats for this program // Define constats for this program
#ifdef DEACTIVATE_SLEEPMODE #ifdef DEACTIVATE_SLEEPMODE
@ -275,6 +275,14 @@ bool loopReadGravity() {
bool pushExpired = (abs((int32_t)(millis() - pushMillis)) > bool pushExpired = (abs((int32_t)(millis() - pushMillis)) >
(myConfig.getSleepInterval() * 1000)); (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) { if (pushExpired || runMode == RunMode::gravityMode) {
pushMillis = millis(); pushMillis = millis();
LOG_PERF_START("loop-push"); LOG_PERF_START("loop-push");

View File

@ -108,8 +108,8 @@ void PushIntervalTracker::save() {
void PushTarget::sendAll(float angle, float gravitySG, float corrGravitySG, void PushTarget::sendAll(float angle, float gravitySG, float corrGravitySG,
float tempC, float runTime) { float tempC, float runTime) {
printHeap("PUSH"); printHeap("PUSH");
_http.setReuse(false); _http.setReuse(true);
_httpSecure.setReuse(false); _httpSecure.setReuse(true);
TemplatingEngine engine; TemplatingEngine engine;
engine.initialize(angle, gravitySG, corrGravitySG, tempC, runTime); engine.initialize(angle, gravitySG, corrGravitySG, tempC, runTime);
@ -204,9 +204,11 @@ void PushTarget::sendInfluxDb2(TemplatingEngine& engine, bool isSecure) {
String auth = "Token " + String(myConfig.getInfluxDb2PushToken()); String auth = "Token " + String(myConfig.getInfluxDb2PushToken());
if (isSecure) { if (isSecure) {
#if defined( ESP8266 ) #if defined(ESP8266)
if (runMode == RunMode::configurationMode) { 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; _lastCode = -100;
return; return;
} }
@ -217,8 +219,7 @@ void PushTarget::sendInfluxDb2(TemplatingEngine& engine, bool isSecure) {
probeMaxFragement(serverPath); probeMaxFragement(serverPath);
_httpSecure.setTimeout(myAdvancedConfig.getPushTimeout() * 1000); _httpSecure.setTimeout(myAdvancedConfig.getPushTimeout() * 1000);
_httpSecure.begin(_wifiSecure, serverPath); _httpSecure.begin(_wifiSecure, serverPath);
_httpSecure.addHeader(F("Authorization"), auth.c_str()); _httpSecure.addHeader(F("Authorization"), auth.c_str());
_httpSecure.setReuse(true);
_lastCode = _httpSecure.POST(doc); _lastCode = _httpSecure.POST(doc);
} else { } else {
_http.setTimeout(myAdvancedConfig.getPushTimeout() * 1000); _http.setTimeout(myAdvancedConfig.getPushTimeout() * 1000);
@ -293,9 +294,11 @@ void PushTarget::sendHttpPost(TemplatingEngine& engine, bool isSecure,
#endif #endif
if (isSecure) { if (isSecure) {
#if defined( ESP8266 ) #if defined(ESP8266)
if (runMode == RunMode::configurationMode) { 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; _lastCode = -100;
return; return;
} }
@ -370,9 +373,11 @@ void PushTarget::sendHttpGet(TemplatingEngine& engine, bool isSecure) {
#endif #endif
if (isSecure) { if (isSecure) {
#if defined( ESP8266 ) #if defined(ESP8266)
if (runMode == RunMode::configurationMode) { 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; _lastCode = -100;
return; return;
} }
@ -424,9 +429,11 @@ void PushTarget::sendMqtt(TemplatingEngine& engine, bool isSecure) {
int port = myConfig.getMqttPort(); int port = myConfig.getMqttPort();
if (myConfig.isMqttSSL()) { if (myConfig.isMqttSSL()) {
#if defined( ESP8266 ) #if defined(ESP8266)
if (runMode == RunMode::configurationMode) { 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; _lastCode = -100;
return; return;
} }

View File

@ -45,7 +45,7 @@ class PushTarget {
void sendHttpPost(TemplatingEngine& engine, bool isSecure, int index); void sendHttpPost(TemplatingEngine& engine, bool isSecure, int index);
void sendHttpGet(TemplatingEngine& engine, bool isSecure); void sendHttpGet(TemplatingEngine& engine, bool isSecure);
void addHttpHeader(HTTPClient& http, String header); void addHttpHeader(HTTPClient& http, String header);
void probeMaxFragement( String& serverPath ); void probeMaxFragement(String& serverPath);
public: public:
void sendAll(float angle, float gravitySG, float corrGravitySG, float tempC, void sendAll(float angle, float gravitySG, float corrGravitySG, float tempC,
@ -68,7 +68,7 @@ class PushTarget {
class PushIntervalTracker { class PushIntervalTracker {
private: 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); void update(const int index, const int defaultValue);
public: public:

View File

@ -90,6 +90,7 @@ SOFTWARE.
#define PARAM_HW_PUSH_INTERVAL_HTTP3 "int-http3" #define PARAM_HW_PUSH_INTERVAL_HTTP3 "int-http3"
#define PARAM_HW_PUSH_INTERVAL_INFLUX "int-influx" #define PARAM_HW_PUSH_INTERVAL_INFLUX "int-influx"
#define PARAM_HW_PUSH_INTERVAL_MQTT "int-mqtt" #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_HTTP1 "http-1"
#define PARAM_FORMAT_HTTP2 "http-2" #define PARAM_FORMAT_HTTP2 "http-2"
#define PARAM_FORMAT_HTTP3 "http-3" #define PARAM_FORMAT_HTTP3 "http-3"

View File

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

View File

@ -48,6 +48,7 @@ void WebServerHandler::webHandleConfig() {
myConfig.createJson(doc); myConfig.createJson(doc);
doc[PARAM_PASS] = ""; // dont show the wifi password doc[PARAM_PASS] = ""; // dont show the wifi password
doc[PARAM_PASS2] = "";
double angle = 0; double angle = 0;
@ -575,6 +576,9 @@ void WebServerHandler::webHandleConfigGravity() {
myConfig.setGravityTempAdj( myConfig.setGravityTempAdj(
_server->arg(PARAM_GRAVITY_TEMP_ADJ).equalsIgnoreCase("on") ? true _server->arg(PARAM_GRAVITY_TEMP_ADJ).equalsIgnoreCase("on") ? true
: false); : false);
else
myConfig.setGravityTempAdj(false);
myConfig.saveFile(); myConfig.saveFile();
_server->sendHeader("Location", "/config.htm#collapseGravity", true); _server->sendHeader("Location", "/config.htm#collapseGravity", true);
_server->send(302, "text/plain", "Gravity config updated"); _server->send(302, "text/plain", "Gravity config updated");
@ -618,6 +622,9 @@ void WebServerHandler::webHandleConfigHardware() {
if (_server->hasArg(PARAM_GYRO_TEMP)) if (_server->hasArg(PARAM_GYRO_TEMP))
myConfig.setGyroTemp( myConfig.setGyroTemp(
_server->arg(PARAM_GYRO_TEMP).equalsIgnoreCase("on") ? true : false); _server->arg(PARAM_GYRO_TEMP).equalsIgnoreCase("on") ? true : false);
else
myConfig.setGyroTemp(false);
myConfig.saveFile(); myConfig.saveFile();
_server->sendHeader("Location", "/config.htm#collapseHardware", true); _server->sendHeader("Location", "/config.htm#collapseHardware", true);
_server->send(302, "text/plain", "Hardware config updated"); _server->send(302, "text/plain", "Hardware config updated");
@ -686,6 +693,13 @@ void WebServerHandler::webHandleConfigAdvancedWrite() {
if (_server->hasArg(PARAM_HW_TEMPSENSOR_RESOLUTION)) if (_server->hasArg(PARAM_HW_TEMPSENSOR_RESOLUTION))
myAdvancedConfig.setTempSensorResolution( myAdvancedConfig.setTempSensorResolution(
_server->arg(PARAM_HW_TEMPSENSOR_RESOLUTION).toInt()); _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(); myAdvancedConfig.saveFile();
_server->sendHeader("Location", "/config.htm#collapseAdvanced", true); _server->sendHeader("Location", "/config.htm#collapseAdvanced", true);
@ -720,6 +734,7 @@ void WebServerHandler::webHandleConfigAdvancedRead() {
doc[PARAM_HW_PUSH_INTERVAL_MQTT] = myAdvancedConfig.getPushIntervalMqtt(); doc[PARAM_HW_PUSH_INTERVAL_MQTT] = myAdvancedConfig.getPushIntervalMqtt();
doc[PARAM_HW_TEMPSENSOR_RESOLUTION] = doc[PARAM_HW_TEMPSENSOR_RESOLUTION] =
myAdvancedConfig.getTempSensorResolution(); myAdvancedConfig.getTempSensorResolution();
doc[PARAM_HW_IGNORE_LOW_ANGLES] = myAdvancedConfig.isIgnoreLowAnges();
#if LOG_LEVEL == 6 && !defined(WEB_DISABLE_LOGGING) #if LOG_LEVEL == 6 && !defined(WEB_DISABLE_LOGGING)
serializeJson(doc, Serial); serializeJson(doc, Serial);
@ -1129,17 +1144,17 @@ const char* WebServerHandler::getHtmlFileName(HtmlFile item) {
Log.notice(F("WEB : Looking up filename for %d." CR), item); Log.notice(F("WEB : Looking up filename for %d." CR), item);
switch (item) { switch (item) {
case HTML_INDEX: case HtmlFile::HTML_INDEX:
return "index.min.htm"; return "index.min.htm";
case HTML_CONFIG: case HtmlFile::HTML_CONFIG:
return "config.min.htm"; return "config.min.htm";
case HTML_CALIBRATION: case HtmlFile::HTML_CALIBRATION:
return "calibration.min.htm"; return "calibration.min.htm";
case HTML_FORMAT: case HtmlFile::HTML_FORMAT:
return "format.min.htm"; return "format.min.htm";
case HTML_ABOUT: case HtmlFile::HTML_ABOUT:
return "about.min.htm"; return "about.min.htm";
case HTML_TEST: case HtmlFile::HTML_TEST:
return "test.min.htm"; return "test.min.htm";
} }
@ -1181,6 +1196,37 @@ bool WebServerHandler::setupWebServer() {
MDNS.begin(myConfig.getMDNS()); MDNS.begin(myConfig.getMDNS());
MDNS.addService("http", "tcp", 80); 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 // Static content
#if defined(EMBED_HTML) #if defined(EMBED_HTML)
_server->on("/", std::bind(&WebServerHandler::webReturnIndexHtm, this)); _server->on("/", std::bind(&WebServerHandler::webReturnIndexHtm, this));
@ -1197,18 +1243,6 @@ bool WebServerHandler::setupWebServer() {
_server->on("/test.htm", _server->on("/test.htm",
std::bind(&WebServerHandler::webReturnTestHtm, this)); std::bind(&WebServerHandler::webReturnTestHtm, this));
#else #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 // Check if the html files exist, if so serve them, else show the static
// upload page. // upload page.
if (checkHtmlFile(HTML_INDEX) && checkHtmlFile(HTML_CONFIG) && if (checkHtmlFile(HTML_INDEX) && checkHtmlFile(HTML_CONFIG) &&

View File

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

View File

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

View File

@ -58,23 +58,9 @@ Other parameters are the same as in the configuration guide.
}, },
"formula-calculation-data": { "formula-calculation-data": {
"a1":25, "a1":25,
"a2":30, "a10":0,
"a3":35,
"a4":40,
"a5":45,
"a5":0,
"a6":0,
"a7":0,
"a8":0,
"g1":1, "g1":1,
"g2":1.01, "g10":1
"g3":1.02,
"g4":1.03,
"g4":1.04,
"g5":1,
"g6":1,
"g7":1,
"g8":1
}, },
"angle": 90.93, "angle": 90.93,
"gravity": 1.105, "gravity": 1.105,
@ -109,6 +95,7 @@ Other parameters are the same as in the configuration guide.
"temp-c": 0, "temp-c": 0,
"temp-f": 32, "temp-f": 32,
"battery": 0, "battery": 0,
"wifi-ssid": "connected SSID",
"temp-format": "C", "temp-format": "C",
"sleep-mode": false, "sleep-mode": false,
"token": "token", "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. 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) * ``a1``-``a10`` are the angles/tilt readings (up to 10 are currently supported)
* ``g1``-``g8`` are the corresponding gravity reaadings in SG or Plato depending on the device-format. * ``g1``-``g10`` are the corresponding gravity reaadings in SG or Plato depending on the device-format.
.. code-block:: json .. code-block:: json
@ -142,6 +129,8 @@ Retrive the data used for formula calculation data via an HTTP GET command. Payl
"a6": 0, "a6": 0,
"a7": 0, "a7": 0,
"a8": 0, "a8": 0,
"a9": 0,
"a10": 0,
"g1": 1.000, "g1": 1.000,
"g2": 1.053, "g2": 1.053,
"g3": 1.062, "g3": 1.062,
@ -150,6 +139,8 @@ Retrive the data used for formula calculation data via an HTTP GET command. Payl
"g6": 1, "g6": 1,
"g7": 1, "g7": 1,
"g8": 1, "g8": 1,
"g9": 1,
"g10": 1,
"error": "Potential error message", "error": "Potential error message",
"gravity-format": "G", "gravity-format": "G",
"gravity-formula": "0.0*tilt^3+0.0*tilt^2+0.0017978*tilt+0.9436" "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-count": 50,
"gyro-read-delay": 3150, "tempsensor-resolution": 9,
"gyro-moving-threashold": 500, "gyro-moving-threashold": 500,
"formula-max-deviation": 1.6, "formula-max-deviation": 1.6,
"wifi-portaltimeout": 120, "wifi-portal-timeout": 120,
"wifi-connect-timeout": 20,
"formula-calibration-temp": 20, "formula-calibration-temp": 20,
"ignore-low-angles": false,
"int-http1": 0, "int-http1": 0,
"int-http2": 0, "int-http2": 0,
"int-http3": 0, "int-http3": 0,
@ -182,8 +175,11 @@ POST: /api/config/advanced
Same parameters as above. 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 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. 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) * ``a1``-``a10`` are the angles/tilt readings (up to 10 are currently supported)
* ``g1``-``g8`` are the corresponding gravity reaadings (in SG) * ``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. 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 a6=0
a7=0 a7=0
a8=0 a8=0
a9=0
a19=0
g1=1.000 g1=1.000
g2=1.053 g2=1.053
g3=1.062 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 g6=1
g7=1 g7=1
g8=1 g8=1
g9=1
g10=1
Calling the API's from Python Calling the API's from Python
@ -433,6 +433,8 @@ The requests package converts the json to standard form post format.
"a6": 0, "a6": 0,
"a7": 0, "a7": 0,
"a8": 0, "a8": 0,
"a9": 0,
"a10": 0,
"g1": 1.000, "g1": 1.000,
"g2": 1.053, "g2": 1.053,
"g3": 1.062, "g3": 1.062,
@ -440,6 +442,8 @@ The requests package converts the json to standard form post format.
"g5": 1, "g5": 1,
"g6": 1, "g6": 1,
"g7": 1, "g7": 1,
"g8": 1 "g8": 1,
"g9": 1,
"g10": 1
} }
set_config( url, json ) 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-debug; Maximum logging for trouble shooting, deep sleep is disabled.
* gravity-release; Standard release * gravity-release; Standard release
* gravity-perf; Standard release but contains code for measuring performance * gravity-perf; Standard release but contains code for measuring performance.
* gravity32-perf: Experimental version for ESP32. * gravity32-release: Version for ESP32.
* gravity32-perf: Version for ESP32 but contains code for measuring performance.
.. note:: .. 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, 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 - Source code for software
* - /src_docs * - /src_docs
- Source code for documentation - Source code for documentation
* - /stl
- 3d models
* - /test * - /test
- Test data for developing html files - Test data for developing html files

View File

@ -282,7 +282,45 @@ Advanded Settings
:width: 800 :width: 800
:alt: Advanced Settings :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 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

@ -7,7 +7,7 @@ Create formula
:width: 800 :width: 800
:alt: Formula data :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.
.. image:: images/formula2.png .. image:: images/formula2.png
:width: 800 :width: 800

View File

@ -33,10 +33,10 @@ The main features
Currently the device supports the following endpoints. Currently the device supports the following endpoints.
* http or https * http (ssl optional)
* influxdb v2 * influxdb v2 (ssl optional)
* MQTT (ssl optional)
* Brewfather * Brewfather
* MQTT
* Home Assistant * Home Assistant
* Brew Spy * Brew Spy
* Brewers Friend * 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 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. 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. 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** * **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 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** * **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 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** * **DS18B20 temperature adjustments**
@ -95,13 +94,14 @@ The main features
* **Gyro Movement** * **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. 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. This way we should avoid faulty measurements and peaks in the graphs.
* **WIFI connection issues** * **WIFI connection issues**
The software will not wait indefiently for a wifi connection. If it takes longer than 20 seconds to connect then 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** * **Use gyro temperature sensor**

View File

@ -24,3 +24,22 @@ need to adjust the voltage factor so the battery reading is correct.
:width: 500 :width: 500
:alt: Mounting esp32 :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: 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:: .. note::
This documentation reflects **v1.0**. Last updated 2022-04-26 This documentation reflects **v1.0**. Last updated 2022-05-08
* Docs for: `v0.8 <https://mp-se.github.io/gravitymon/v0.8/index.html>`_
* Docs for: `v0.9 <https://mp-se.github.io/gravitymon/v0.9/index.html>`_
.. image:: images/gravitymon.gif .. image:: images/gravitymon.gif
:width: 800 :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 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 .. image:: images/brewflasher.png
:width: 600 :width: 600
@ -34,7 +35,8 @@ In the /bin directory you will find 3 different firmware builds;
* **firmware32.bin** * **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 In these versions all the html files are embedded in the binaries. The file system is currently only used for storing
the configuration file. 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`` ``http://<device_name>/firmware.htm``
.. _serial_monitoring: .. _serial_monitoring:
Serial Monitoring Serial Monitoring
@ -120,6 +121,9 @@ 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 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** in the next step to access the configuration pages. The link would look like this: **http://gravitymon56EA34.local**
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 .. image:: images/wifi.png
:width: 200 :width: 200
:alt: Wifi page :alt: Wifi page

View File

@ -4,25 +4,51 @@ Releases
######## ########
v1.0.0 v1.0.0
------ ======
* Upgraded to bootstrap v5.1 for web pages.
* Added tooltips to all fields in user interface Documentation
* 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. * Update documentation to match v1.0
* 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
* Installation instructions updated on how to find the device after wifi has been configured. * 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 * 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 * Added circuit diagram for esp8266 and esp32
* BUG: Field name for wifi strenght changed from "rssi" to "RSSI" * 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 v0.9.0
------ ======
* Added one http push target that uses HTTP GET. This can be used with ubidots or blynk api's. * 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 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. * Added documetation on how to integrate with Blynk.io using http get.
@ -47,8 +73,7 @@ v0.9.0
* BUG: Entering wifi setup and a timeout occured the wifi settings could be deleted. * BUG: Entering wifi setup and a timeout occured the wifi settings could be deleted.
v0.8.0 v0.8.0
------ ======
* Added option to set http headers (2 per http endpoint), these can be used for * 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. other http formats than json (default) and for adding authentication headers.
* Added possibility to view last 10 errors on device page. * Added possibility to view last 10 errors on device page.
@ -68,8 +93,7 @@ v0.8.0
* Tested batterylife, 47 days using an update frequency of 5 min * Tested batterylife, 47 days using an update frequency of 5 min
v0.7.1 v0.7.1
------ ======
* Added instructions for how to configure integration with Fermentrack * 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 Ubidots
* Added instructions for how to configure integration with HomeAssistant * Added instructions for how to configure integration with HomeAssistant
@ -79,8 +103,7 @@ v0.7.1
* BUG: Fixed issue with default template so it now includes the device name correctly. * BUG: Fixed issue with default template so it now includes the device name correctly.
v0.7.0 v0.7.0
------ ======
Latest stable version. `Release v0.7 on Github <https://github.com/mp-se/gravitymon/releases/tag/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 * SSL support for HTTP targets
@ -106,10 +129,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. the behaviour in v0.6 is wanted this can be done via the format editor.
v0.6.0 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 * Changed the wifi manager and refactored wifi.cpp
* LED is now turned on when Wifi Portal is open * LED is now turned on when Wifi Portal is open
* Refactored main.cpp to make it easier to read * Refactored main.cpp to make it easier to read
@ -122,10 +142,7 @@ v0.6.0
* Bug: MPU init sometimes caused crash during startup. * Bug: MPU init sometimes caused crash during startup.
v0.5.0 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 * Added feature to calcuate formula on device
* Total rewrite of documentation * Total rewrite of documentation
* WIFI settings are now stored in config file * WIFI settings are now stored in config file
@ -134,8 +151,5 @@ v0.5.0
* Refactor code from C to C++ * Refactor code from C to C++
v0.4.0 v0.4.0
------ ======
* First public release
`Release v0.4 on Github <https://github.com/mp-se/gravitymon/releases/tag/v0.4.0>`_
* First release

View File

@ -120,7 +120,7 @@ format template that can be used. For information on customizing the format see
"gravity": ${gravity}, "gravity": ${gravity},
"angle": ${angle}, "angle": ${angle},
"battery": ${battery}, "battery": ${battery},
"rssi": ${rssi} "RSSI": ${rssi}
} }
@ -146,7 +146,10 @@ device is named `gravmon2`
state_topic: "gravmon/gravmon2/battery" state_topic: "gravmon/gravmon2/battery"
- platform: mqtt - platform: mqtt
name: "gravmon2_rssi" name: "gravmon2_rssi"
state_topic: "gravmon/gravmon2/rssi" state_topic: "gravmon/gravmon2/RSSI"
- platform: mqtt
name: "gravmon2_temp"
state_topic: "gravmon/gravmon2/temp"
Enter the name of the MQTT server in Home Assistant in the URL. You might need to install that option Enter the name of the MQTT server in Home Assistant in the URL. You might need to install that option
@ -155,9 +158,10 @@ many sensors / topics as you want.
:: ::
gravmon/${mdns}/tilt:${angle}| gravmon/${mdns}/gravity:${gravity}|
gravmon/${mdns}/temperature:${temp}| gravmon/${mdns}/battery:${battery}|
gravmon/${mdns}/temp_units:${temp-unit}| gravmon/${mdns}/RSSI:${rssi}|
gravmon/${mdns}/temp:${temp}|
Brewer's Friend Brewer's Friend
@ -194,7 +198,7 @@ format for the endpoint. Just add you API key after token.
"gravity": ${gravity}, "gravity": ${gravity},
"angle": ${angle}, "angle": ${angle},
"battery": ${battery}, "battery": ${battery},
"rssi": ${rssi} "RSSI": ${rssi}
} }
@ -260,4 +264,3 @@ starting with a ``?``. This string will be added to the URL above when doing the
.. code-block:: .. code-block::
?token=${token2}&v1=${temp}&v2=${gravity}&v3=${angle} ?token=${token2}&v1=${temp}&v2=${gravity}&v3=${angle}

View File

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

View File

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

View File

@ -35,6 +35,28 @@
"gy": -6, "gy": -6,
"gz": 4 "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, "angle": 90.93,
"gravity": 1.105, "gravity": 1.105,
"battery": 0.04, "battery": 0.04,

View File

@ -21,5 +21,6 @@
"g8": 1.005, "g8": 1.005,
"g9": 1.005, "g9": 1.005,
"g10": 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, "config": false,
"calibration": false, "calibration": true,
"format": false, "format": true,
"about": false,
"test": 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
}
]
} }