Added ssl and plato
This commit is contained in:
parent
10163f3aa7
commit
ddb34e129d
@ -86,19 +86,20 @@
|
||||
<div id="collapseOne" class="collapse show" aria-labelledby="headingOne" data-parent="#accordion">
|
||||
<div class="card-body">
|
||||
<form action="/api/formula" method="post">
|
||||
<input type="text" name="gravity-format" id="gravity-format" hidden>
|
||||
<input type="text" name="id" id="id" hidden>
|
||||
|
||||
<div class="row mb-3">
|
||||
Here you can create your gravity formula by entering angles/tilt and the corresponding gravity (SG). These values
|
||||
Here you can create your gravity formula by entering angles/tilt and the corresponding gravity. These values
|
||||
will be saved for future use. Angles with 0 (zero) will be skipped. The values below will be used to check the
|
||||
formula and if the deviation is more than 1.5 SG then the forumla will be rejected. On the bottom of the page you can
|
||||
see a graph over the entered values + values calcualated by the formula.
|
||||
formula and if the deviation is more than 1.5SG / 0.38P on any of the provided points then the forumla will be
|
||||
rejected. On the bottom of the page you can see a graph over the entered values + values calcualated by the formula.
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">#:</label>
|
||||
<label class="col-sm-4 col-form-label">Angle/Tilt:</label>
|
||||
<label class="col-sm-4 col-form-label">Gravity (SG):</label>
|
||||
<label class="col-sm-4 col-form-label" id="gravity-header">Gravity (SG):</label>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
@ -107,7 +108,7 @@
|
||||
<input type="number" min="0" max="90" step="0.001" class="form-control" name="a1" id="a1">
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
<input type="number" min="1" max="2" step="0.0001" class="form-control" name="g1" id="g1">
|
||||
<input type="number" min="0" max="26" step="0.0001" class="form-control" name="g1" id="g1">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -117,7 +118,7 @@
|
||||
<input type="number" min="0" max="90" step="0.001" class="form-control" name="a2" id="a2">
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
<input type="number" min="1" max="2" step="0.0001" class="form-control" name="g2" id="g2">
|
||||
<input type="number" min="0" max="26" step="0.0001" class="form-control" name="g2" id="g2">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -127,7 +128,7 @@
|
||||
<input type="number" min="0" max="90" step="0.001" class="form-control" name="a3" id="a3">
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
<input type="number" min="1" max="2" step="0.0001" class="form-control" name="g3" id="g3">
|
||||
<input type="number" min="0" max="26" step="0.0001" class="form-control" name="g3" id="g3">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -137,7 +138,7 @@
|
||||
<input type="number" min="0" max="90" step="0.001" class="form-control" name="a4" id="a4">
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
<input type="number" min="1" max="2" step="0.0001" class="form-control" name="g4" id="g4">
|
||||
<input type="number" min="0" max="26" step="0.0001" class="form-control" name="g4" id="g4">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -147,7 +148,7 @@
|
||||
<input type="number" min="0" max="90" step="0.001" class="form-control" name="a5" id="a5">
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
<input type="number" min="1" max="2" step="0.0001" class="form-control" name="g5" id="g5">
|
||||
<input type="number" min="0" max="26" step="0.0001" class="form-control" name="g5" id="g5">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -233,28 +234,40 @@
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
g1.onchange = setFourNumberDecimal
|
||||
g2.onchange = setFourNumberDecimal
|
||||
g3.onchange = setFourNumberDecimal
|
||||
g4.onchange = setFourNumberDecimal
|
||||
g5.onchange = setFourNumberDecimal
|
||||
g1.onchange = setGravityDecimal
|
||||
g2.onchange = setGravityDecimal
|
||||
g3.onchange = setGravityDecimal
|
||||
g4.onchange = setGravityDecimal
|
||||
g5.onchange = setGravityDecimal
|
||||
|
||||
a1.onchange = setTwoNumberDecimal
|
||||
a2.onchange = setTwoNumberDecimal
|
||||
a3.onchange = setTwoNumberDecimal
|
||||
a4.onchange = setTwoNumberDecimal
|
||||
a5.onchange = setTwoNumberDecimal
|
||||
a1.onchange = setAngleDecimal
|
||||
a2.onchange = setAngleDecimal
|
||||
a3.onchange = setAngleDecimal
|
||||
a4.onchange = setAngleDecimal
|
||||
a5.onchange = setAngleDecimal
|
||||
|
||||
window.onload = getConfig;
|
||||
setButtonDisabled( true );
|
||||
|
||||
function setTwoNumberDecimal(event) {
|
||||
function convertToPlato(sg) {
|
||||
return 259-(259/sg);
|
||||
}
|
||||
|
||||
function convertToSG(plato) {
|
||||
return 259/(259-plato);
|
||||
}
|
||||
|
||||
function setAngleDecimal(event) {
|
||||
this.value = parseFloat(this.value).toFixed(2);
|
||||
populateChart();
|
||||
}
|
||||
|
||||
function setFourNumberDecimal(event) {
|
||||
function setGravityDecimal(event) {
|
||||
if(isPlato())
|
||||
this.value = parseFloat(this.value).toFixed(1);
|
||||
else
|
||||
this.value = parseFloat(this.value).toFixed(4);
|
||||
|
||||
populateChart();
|
||||
}
|
||||
|
||||
@ -267,6 +280,10 @@
|
||||
chartDataCalc.push( { x: parseFloat(a), y: parseFloat(g) });
|
||||
}
|
||||
|
||||
function isPlato() {
|
||||
return $("#gravity-format").text() == "P";
|
||||
}
|
||||
|
||||
function populateChart() {
|
||||
|
||||
chartDataCalc.length = 0
|
||||
@ -278,6 +295,10 @@
|
||||
formula=formula.replaceAll( "tilt^2", angle+"*"+angle );
|
||||
formula=formula.replaceAll( "tilt", angle );
|
||||
var g = eval( formula );
|
||||
|
||||
if(isPlato())
|
||||
g = convertToPlato(g);
|
||||
|
||||
populateChartCalc( i, g );
|
||||
}
|
||||
|
||||
@ -314,6 +335,23 @@
|
||||
$("#id").val(cfg["id"]);
|
||||
$("#angle").text(cfg["angle"]);
|
||||
$("#formula").text(cfg["gravity-formula"]);
|
||||
$("#gravity-format").text(cfg["gravity-format"]); // Sets the variable used by isPlato()
|
||||
|
||||
if(isPlato()) {
|
||||
$("#gravity-header").text("Gravity (Plato):");
|
||||
$("#g1").val( parseFloat(cfg["g1"]).toFixed(1) );
|
||||
$("#g2").val( parseFloat(cfg["g2"]).toFixed(1) );
|
||||
$("#g3").val( parseFloat(cfg["g3"]).toFixed(1) );
|
||||
$("#g4").val( parseFloat(cfg["g4"]).toFixed(1) );
|
||||
$("#g5").val( parseFloat(cfg["g5"]).toFixed(1) );
|
||||
} else {
|
||||
$("#gravity-header").text("Gravity (SG):");
|
||||
$("#g1").val( parseFloat(cfg["g1"]).toFixed(4) );
|
||||
$("#g2").val( parseFloat(cfg["g2"]).toFixed(4) );
|
||||
$("#g3").val( parseFloat(cfg["g3"]).toFixed(4) );
|
||||
$("#g4").val( parseFloat(cfg["g4"]).toFixed(4) );
|
||||
$("#g5").val( parseFloat(cfg["g5"]).toFixed(4) );
|
||||
}
|
||||
|
||||
$("#a1").val( parseFloat(cfg["a1"]).toFixed(2) );
|
||||
$("#a2").val( parseFloat(cfg["a2"]).toFixed(2) );
|
||||
@ -321,11 +359,9 @@
|
||||
$("#a4").val( parseFloat(cfg["a4"]).toFixed(2) );
|
||||
$("#a5").val( parseFloat(cfg["a5"]).toFixed(2) );
|
||||
|
||||
$("#g1").val( parseFloat(cfg["g1"]).toFixed(4) );
|
||||
$("#g2").val( parseFloat(cfg["g2"]).toFixed(4) );
|
||||
$("#g3").val( parseFloat(cfg["g3"]).toFixed(4) );
|
||||
$("#g4").val( parseFloat(cfg["g4"]).toFixed(4) );
|
||||
$("#g5").val( parseFloat(cfg["g5"]).toFixed(4) );
|
||||
if( cfg["error"]!="" ) {
|
||||
showError(cfg["error"]);
|
||||
}
|
||||
|
||||
populateChart();
|
||||
})
|
||||
|
File diff suppressed because one or more lines are too long
@ -270,8 +270,25 @@
|
||||
<div class="card-body">
|
||||
<form action="/api/config/gravity" method="post">
|
||||
<input type="text" name="id" id="id3" hidden>
|
||||
<fieldset class="form-group row">
|
||||
<legend class="col-form-label col-sm-2 float-sm-left pt-0">Gravity Format:</legend>
|
||||
<div class="col-sm-4">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="gravity-format" id="gravity-format-g" value="G" checked>
|
||||
<label class="form-check-label" for="gravity-format-g">
|
||||
SG
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="gravity-format" id="gravity-format-p" value="P">
|
||||
<label class="form-check-label" for="gravity-format-p">
|
||||
Plato
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<div class="form-group row">
|
||||
<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 (SG)</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" maxlength="200" class="form-control" name="gravity-formula" id="gravity-formula">
|
||||
</div>
|
||||
@ -416,10 +433,10 @@
|
||||
$("#id3").val(cfg["id"]);
|
||||
$("#id4").val(cfg["id"]);
|
||||
$("#mdns").val(cfg["mdns"]);
|
||||
if( cfg["temp-format"] == "C" )
|
||||
$("#temp-format-c").click();
|
||||
else
|
||||
$("#temp-format-f").click();
|
||||
if( cfg["temp-format"] == "C" ) $("#temp-format-c").click();
|
||||
else $("#temp-format-f").click();
|
||||
if( cfg["gravity-format"] == "G" ) $("#gravity-format-g").click();
|
||||
else $("#gravity-format-p").click();
|
||||
$("#ota-url").val(cfg["ota-url"]);
|
||||
$("#http-push").val(cfg["http-push"]);
|
||||
$("#http-push2").val(cfg["http-push2"]);
|
||||
|
File diff suppressed because one or more lines are too long
@ -123,13 +123,19 @@
|
||||
console.log( cfg );
|
||||
$("#id").text(cfg["id"]);
|
||||
$("#angle").text(cfg["angle"]);
|
||||
|
||||
if( cfg["gravity-format"] == "G")
|
||||
$("#gravity").text(cfg["gravity"] + " SG");
|
||||
else
|
||||
$("#gravity").text(cfg["gravity"] + " °P");
|
||||
|
||||
$("#battery").text(cfg["battery"] + " V");
|
||||
|
||||
if( cfg["temp-format"] == "C")
|
||||
$("#temp").text(cfg["temp-c"] + " C");
|
||||
else
|
||||
$("#temp").text(cfg["temp-f"] + " F");
|
||||
//console.log(cfg["sleep-mode"] );
|
||||
|
||||
if( cfg["sleep-mode"] )
|
||||
$("#sleep-mode").attr("checked", true );
|
||||
else
|
||||
|
@ -1 +1 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"><meta name="description" content=""><title>Beer Gravity Monitor</title><link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous"><script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script><script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" crossorigin="anonymous"></script></head><body class="py-4"><!-- START MENU --><nav class="navbar navbar-expand-sm navbar-dark bg-primary"><a class="navbar-brand" href="/index.htm">Beer Gravity Monitor</a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbar" aria-controls="navbar" aria-expanded="false" aria-label="Toggle navigation"><span class="navbar-toggler-icon"></span></button><div class="collapse navbar-collapse" id="navbar"><ul class="navbar-nav mr-auto"><li class="nav-item active"><a class="nav-link" href="/index.htm">Home <span class="sr-only">(current)</span></a></li><li class="nav-item"><a class="nav-link" href="/device.htm">Device</a></li><li class="nav-item"><a class="nav-link" href="/config.htm">Configuration</a></li><li class="nav-item"><a class="nav-link" href="/calibration.htm">Calibration</a></li><li class="nav-item"><a class="nav-link" href="/about.htm">About</a></li></ul><div class="spinner-border text-light" id="spinner" role="status"></div></div></nav><!-- START MAIN INDEX --><div class="container"><hr class="my-4"><div class="alert alert-success alert-dismissible fade hide show d-none" role="alert" id="alert"><div id="alert-msg">...</div><button type="button" id="alert-btn" class="close" aria-label="Close"><span aria-hidden="true">×</span></button></div><script type="text/javascript">function showError(s){$(".alert").removeClass("alert-success").addClass("alert-danger").removeClass("d-none").addClass("show"),$("#alert-msg").text(s)}function showSuccess(s){$(".alert").addClass("alert-success").removeClass("alert-danger").removeClass("d-none").addClass("show"),$("#alert-msg").text(s)}$("#alert-btn").click(function(s){$(".alert").addClass("d-none").removeClass("show")})</script><div class="" id="id" hidden></div><div class="row mb-3"><div class="col-md-8 themed-grid-col bg-light">Gravity:</div><div class="col-md-4 themed-grid-col bg-light" id="gravity">Loading...</div></div><div class="row mb-3"><div class="col-md-8 themed-grid-col bg-light">Temperature:</div><div class="col-md-4 themed-grid-col bg-light" id="temp">Loading...</div></div><div class="row mb-3"><div class="col-md-8 themed-grid-col bg-light">Angle/Tilt:</div><div class="col-md-4 themed-grid-col bg-light" id="angle">Loading...</div></div><div class="row mb-3"><div class="col-md-8 themed-grid-col bg-light">Battery:</div><div class="col-md-4 themed-grid-col bg-light" id="battery">Loading...</div></div><div class="row mb-3"><div class="col-md-12 px-md-5 themed-grid-col bg-light custom-control custom-checkbox"><input type="checkbox" class="custom-control-input" name="sleep-mode" id="sleep-mode" disabled> <label class="custom-control-label" for="sleep-mode">Do not enter sleep mode when floating (check this if you are collecting angles/tilt for calibration).</label></div></div><hr class="my-4"></div><script type="text/javascript">function getStatus(){var e="/api/status";$("#spinner").show(),$.getJSON(e,function(e){console.log(e),$("#id").text(e.id),$("#angle").text(e.angle),$("#gravity").text(e.gravity+" SG"),$("#battery").text(e.battery+" V"),"C"==e["temp-format"]?$("#temp").text(e["temp-c"]+" C"):$("#temp").text(e["temp-f"]+" F"),e["sleep-mode"]?$("#sleep-mode").attr("checked",!0):$("#sleep-mode").attr("checked",!1),$("#sleep-mode").removeAttr("disabled")}).fail(function(){showError("Unable to get data from the device.")}).always(function(){$("#spinner").hide()})}function start(){setInterval(getStatus,3e3)}window.onload=start,$("#sleep-mode").click(function(e){console.log("Blocking sleep mode = "+$("#sleep-mode").is(":checked")),$.ajax({type:"POST",url:"/api/status/sleepmode",data:{id:$("#id").text(),"sleep-mode":$("#sleep-mode").is(":checked")},success:function(e){},error:function(e){showError("Could not update sleep mode for device.")}})})</script><!-- START FOOTER --><div class="container-fluid themed-container bg-primary text-light">(C) Copyright 2021-22 Magnus Persson</div></body></html>
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"><meta name="description" content=""><title>Beer Gravity Monitor</title><link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous"><script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script><script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" crossorigin="anonymous"></script></head><body class="py-4"><!-- START MENU --><nav class="navbar navbar-expand-sm navbar-dark bg-primary"><a class="navbar-brand" href="/index.htm">Beer Gravity Monitor</a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbar" aria-controls="navbar" aria-expanded="false" aria-label="Toggle navigation"><span class="navbar-toggler-icon"></span></button><div class="collapse navbar-collapse" id="navbar"><ul class="navbar-nav mr-auto"><li class="nav-item active"><a class="nav-link" href="/index.htm">Home <span class="sr-only">(current)</span></a></li><li class="nav-item"><a class="nav-link" href="/device.htm">Device</a></li><li class="nav-item"><a class="nav-link" href="/config.htm">Configuration</a></li><li class="nav-item"><a class="nav-link" href="/calibration.htm">Calibration</a></li><li class="nav-item"><a class="nav-link" href="/about.htm">About</a></li></ul><div class="spinner-border text-light" id="spinner" role="status"></div></div></nav><!-- START MAIN INDEX --><div class="container"><hr class="my-4"><div class="alert alert-success alert-dismissible fade hide show d-none" role="alert" id="alert"><div id="alert-msg">...</div><button type="button" id="alert-btn" class="close" aria-label="Close"><span aria-hidden="true">×</span></button></div><script type="text/javascript">function showError(s){$(".alert").removeClass("alert-success").addClass("alert-danger").removeClass("d-none").addClass("show"),$("#alert-msg").text(s)}function showSuccess(s){$(".alert").addClass("alert-success").removeClass("alert-danger").removeClass("d-none").addClass("show"),$("#alert-msg").text(s)}$("#alert-btn").click(function(s){$(".alert").addClass("d-none").removeClass("show")})</script><div class="" id="id" hidden></div><div class="row mb-3"><div class="col-md-8 themed-grid-col bg-light">Gravity:</div><div class="col-md-4 themed-grid-col bg-light" id="gravity">Loading...</div></div><div class="row mb-3"><div class="col-md-8 themed-grid-col bg-light">Temperature:</div><div class="col-md-4 themed-grid-col bg-light" id="temp">Loading...</div></div><div class="row mb-3"><div class="col-md-8 themed-grid-col bg-light">Angle/Tilt:</div><div class="col-md-4 themed-grid-col bg-light" id="angle">Loading...</div></div><div class="row mb-3"><div class="col-md-8 themed-grid-col bg-light">Battery:</div><div class="col-md-4 themed-grid-col bg-light" id="battery">Loading...</div></div><div class="row mb-3"><div class="col-md-12 px-md-5 themed-grid-col bg-light custom-control custom-checkbox"><input type="checkbox" class="custom-control-input" name="sleep-mode" id="sleep-mode" disabled> <label class="custom-control-label" for="sleep-mode">Do not enter sleep mode when floating (check this if you are collecting angles/tilt for calibration).</label></div></div><hr class="my-4"></div><script type="text/javascript">function getStatus(){var e="/api/status";$("#spinner").show(),$.getJSON(e,function(e){console.log(e),$("#id").text(e.id),$("#angle").text(e.angle),"G"==e["gravity-format"]?$("#gravity").text(e.gravity+" SG"):$("#gravity").text(e.gravity+" °P"),$("#battery").text(e.battery+" V"),"C"==e["temp-format"]?$("#temp").text(e["temp-c"]+" C"):$("#temp").text(e["temp-f"]+" F"),e["sleep-mode"]?$("#sleep-mode").attr("checked",!0):$("#sleep-mode").attr("checked",!1),$("#sleep-mode").removeAttr("disabled")}).fail(function(){showError("Unable to get data from the device.")}).always(function(){$("#spinner").hide()})}function start(){setInterval(getStatus,3e3)}window.onload=start,$("#sleep-mode").click(function(e){console.log("Blocking sleep mode = "+$("#sleep-mode").is(":checked")),$.ajax({type:"POST",url:"/api/status/sleepmode",data:{id:$("#id").text(),"sleep-mode":$("#sleep-mode").is(":checked")},success:function(e){},error:function(e){showError("Could not update sleep mode for device.")}})})</script><!-- START FOOTER --><div class="container-fluid themed-container bg-primary text-light">(C) Copyright 2021-22 Magnus Persson</div></body></html>
|
@ -27,19 +27,14 @@ build_flags =
|
||||
#-D DEBUG_ESP_HTTP_SERVER
|
||||
#-D DEBUG_ESP_PORT=Serial
|
||||
#-D DEBUG_ESP_WIFI
|
||||
#-D DEBUG_ESP_SSL
|
||||
#-D DEBUG_ESP_CORE
|
||||
#-D SKIP_SLEEPMODE
|
||||
-D CFG_DISABLE_LOGGING # Turn off verbose logging for some of the parts (too much will cause a crash) but also add space
|
||||
-D GYRO_DISABLE_LOGGING
|
||||
-D PUSH_DISABLE_LOGGING
|
||||
-D TSEN_DISABLE_LOGGING
|
||||
-D WEB_DISABLE_LOGGING
|
||||
-D MAIN_DISABLE_LOGGING
|
||||
-D USE_LITTLEFS=true
|
||||
-D EMBED_HTML # If this is not used the html files needs to be on the file system (can be uploaded)
|
||||
-D USER_SSID=\""\"" # =\""myssid\""
|
||||
-D USER_SSID_PWD=\""\"" # =\""mypwd\""
|
||||
-D CFG_APPVER="\"0.6.0\""
|
||||
-D CFG_APPVER="\"0.6.1\""
|
||||
lib_deps = # Switched to forks for better version control.
|
||||
# Using local copy of this library
|
||||
#https://github.com/jrowberg/i2cdevlib.git#<document>
|
||||
@ -65,20 +60,26 @@ extra_scripts =
|
||||
script/create_versionjson.py
|
||||
build_unflags =
|
||||
${common_env_data.build_unflags}
|
||||
# -D MAIN_DISABLE_LOGGING
|
||||
-D WEB_DISABLE_LOGGING
|
||||
-D PUSH_DISABLE_LOGGING
|
||||
build_flags =
|
||||
${common_env_data.build_flags}
|
||||
-D PIO_FRAMEWORK_ARDUINO_ENABLE_EXCEPTIONS
|
||||
#-D PIO_FRAMEWORK_ARDUINO_ENABLE_EXCEPTIONS
|
||||
#-D SKIP_SLEEPMODE
|
||||
-D DOUBLERESETDETECTOR_DEBUG=true
|
||||
#-D DOUBLERESETDETECTOR_DEBUG=true
|
||||
-D COLLECT_PERFDATA # This option will collect runtime data for a few defined methods to measure time, dumped to serial and/or influxdb
|
||||
-D LOG_LEVEL=6 # Maximum log level for the debug build.
|
||||
-D CFG_DISABLE_LOGGING # Turn off verbose/notice logging to reduce size and dont overload uart.
|
||||
-D GYRO_DISABLE_LOGGING
|
||||
-D CALC_DISABLE_LOGGING
|
||||
-D HELPER_DISABLE_LOGGING
|
||||
-D PUSH_DISABLE_LOGGING
|
||||
-D TSEN_DISABLE_LOGGING
|
||||
-D WIFI_DISABLE_LOGGING
|
||||
-D WEB_DISABLE_LOGGING
|
||||
-D MAIN_DISABLE_LOGGING
|
||||
lib_deps =
|
||||
${common_env_data.lib_deps}
|
||||
board = ${common_env_data.board}
|
||||
#build_type = debug # Using debug type crashes my devkit...
|
||||
#build_type = debug
|
||||
build_type = release
|
||||
board_build.filesystem = littlefs
|
||||
monitor_filters = esp8266_exception_decoder
|
||||
|
51
src/calc.cpp
51
src/calc.cpp
@ -29,7 +29,7 @@ SOFTWARE.
|
||||
#include <helper.hpp>
|
||||
#include <tempsensor.hpp>
|
||||
|
||||
#define FORMULA_MAX_DEVIATION 1.5
|
||||
#define FORMULA_MAX_DEVIATION 1.6
|
||||
|
||||
//
|
||||
// Use values to derive a formula
|
||||
@ -46,7 +46,7 @@ int createFormula(RawFormulaData &fd, char *formulaBuffer,
|
||||
else if (fd.a[0] > 0 && fd.a[1] > 0 && fd.a[2] > 0)
|
||||
noAngles = 3;
|
||||
|
||||
#if LOG_LEVEL == 6
|
||||
#if LOG_LEVEL == 6 && !defined(CALC_DISABLE_LOGGING)
|
||||
Log.verbose(
|
||||
F("CALC: Trying to create formula using order = %d, found %d angles" CR),
|
||||
order, noAngles);
|
||||
@ -62,7 +62,7 @@ int createFormula(RawFormulaData &fd, char *formulaBuffer,
|
||||
|
||||
// Returned value is 0 if no error
|
||||
if (ret == 0) {
|
||||
#if LOG_LEVEL == 6
|
||||
#if LOG_LEVEL == 6 && !defined(CALC_DISABLE_LOGGING)
|
||||
Log.verbose(F("CALC: Finshied processing data points." CR));
|
||||
#endif
|
||||
|
||||
@ -83,7 +83,7 @@ int createFormula(RawFormulaData &fd, char *formulaBuffer,
|
||||
coeffs[1]);
|
||||
}
|
||||
|
||||
#if LOG_LEVEL == 6
|
||||
#if LOG_LEVEL == 6 && !defined(CALC_DISABLE_LOGGING)
|
||||
Log.verbose(F("CALC: Formula: %s" CR), formulaBuffer);
|
||||
#endif
|
||||
|
||||
@ -96,7 +96,14 @@ int createFormula(RawFormulaData &fd, char *formulaBuffer,
|
||||
double dev = (g - fd.g[i]) < 0 ? (fd.g[i] - g) : (g - fd.g[i]);
|
||||
|
||||
// If the deviation is more than 2 degress we mark it as failed.
|
||||
if (dev * 1000 > FORMULA_MAX_DEVIATION) valid = false;
|
||||
if (dev * 1000 > FORMULA_MAX_DEVIATION) {
|
||||
#if LOG_LEVEL == 6 && !defined(CALC_DISABLE_LOGGING)
|
||||
char s[10];
|
||||
snprintf(&s[0], sizeof(s), "%.8f", dev);
|
||||
Log.verbose(F("CALC: Deviation is: %s" CR), &s[0]);
|
||||
#endif
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!valid) {
|
||||
@ -121,13 +128,13 @@ double calculateGravity(double angle, double temp, const char *tempFormula) {
|
||||
const char *formula = myConfig.getGravityFormula();
|
||||
|
||||
if (tempFormula != 0) {
|
||||
#if LOG_LEVEL == 6
|
||||
#if LOG_LEVEL == 6 && !defined(CALC_DISABLE_LOGGING)
|
||||
Log.verbose(F("CALC: Using temporary formula." CR));
|
||||
#endif
|
||||
formula = tempFormula;
|
||||
}
|
||||
|
||||
#if LOG_LEVEL == 6
|
||||
#if LOG_LEVEL == 6 && !defined(CALC_DISABLE_LOGGING)
|
||||
Log.verbose(F("CALC: Calculating gravity for angle %F, temp %F." CR), angle,
|
||||
temp);
|
||||
Log.verbose(F("CALC: Formula %s." CR), formula);
|
||||
@ -146,8 +153,10 @@ double calculateGravity(double angle, double temp, const char *tempFormula) {
|
||||
double g = te_eval(expr);
|
||||
te_free(expr);
|
||||
|
||||
#if LOG_LEVEL == 6
|
||||
Log.verbose(F("CALC: Calculated gravity is %F." CR), g);
|
||||
#if LOG_LEVEL == 6 && !defined(CALC_DISABLE_LOGGING)
|
||||
char s[10];
|
||||
snprintf(&s[0], sizeof(s), "%.8f", g);
|
||||
Log.verbose(F("CALC: Calculated gravity is %s." CR), &s[0]);
|
||||
#endif
|
||||
return g;
|
||||
}
|
||||
@ -158,18 +167,20 @@ double calculateGravity(double angle, double temp, const char *tempFormula) {
|
||||
|
||||
//
|
||||
// Do a standard gravity temperature correction. This is a simple way to adjust
|
||||
// for differnt worth temperatures
|
||||
// for differnt worth temperatures. This function uses C as temperature.
|
||||
//
|
||||
double gravityTemperatureCorrection(double gravity, double temp,
|
||||
char tempFormat, double calTemp) {
|
||||
#if LOG_LEVEL == 6
|
||||
// Source: https://homebrewacademy.com/hydrometer-temperature-correction/
|
||||
//
|
||||
double gravityTemperatureCorrectionC(double gravity, double tempC,
|
||||
double calTempC) {
|
||||
#if LOG_LEVEL == 6 && !defined(CALC_DISABLE_LOGGING)
|
||||
Log.verbose(F("CALC: Adjusting gravity based on temperature, gravity %F, "
|
||||
"temp %F, calTemp %F." CR),
|
||||
gravity, temp, calTemp);
|
||||
gravity, tempC, calTempC);
|
||||
#endif
|
||||
// float tempF = convertCtoF(tempC);
|
||||
// float calTempF = convertCtoF(calTempC);
|
||||
|
||||
if (tempFormat == 'C') temp = convertCtoF(temp);
|
||||
double calTempF = convertCtoF(calTemp); // calTemp is in C
|
||||
const char *formula =
|
||||
"gravity*((1.00130346-0.000134722124*temp+0.00000204052596*temp^2-0."
|
||||
"00000000232820948*temp^3)/"
|
||||
@ -178,7 +189,7 @@ double gravityTemperatureCorrection(double gravity, double temp,
|
||||
|
||||
// Store variable names and pointers.
|
||||
te_variable vars[] = {
|
||||
{"gravity", &gravity}, {"temp", &temp}, {"cal", &calTempF}};
|
||||
{"gravity", &gravity}, {"temp", &tempC}, {"cal", &calTempC}};
|
||||
|
||||
int err;
|
||||
// Compile the expression with variables.
|
||||
@ -188,8 +199,10 @@ double gravityTemperatureCorrection(double gravity, double temp,
|
||||
double g = te_eval(expr);
|
||||
te_free(expr);
|
||||
|
||||
#if LOG_LEVEL == 6
|
||||
Log.verbose(F("CALC: Corrected gravity is %F." CR), g);
|
||||
#if LOG_LEVEL == 6 && !defined(CALC_DISABLE_LOGGING)
|
||||
char s[10];
|
||||
snprintf(&s[0], sizeof(s), "%.8f", g);
|
||||
Log.verbose(F("CALC: Corrected gravity is %s." CR), &s[0]);
|
||||
#endif
|
||||
return g;
|
||||
}
|
||||
|
@ -26,16 +26,16 @@ SOFTWARE.
|
||||
|
||||
// Includes
|
||||
#include <config.hpp>
|
||||
#include <helper.hpp>
|
||||
|
||||
#define ERR_FORMULA_NOTENOUGHVALUES -1
|
||||
#define ERR_FORMULA_INTERNAL -2
|
||||
#define ERR_FORMULA_UNABLETOFFIND -3
|
||||
|
||||
// Functions
|
||||
double calculateGravity(double angle, double temp, const char *tempFormula = 0);
|
||||
double gravityTemperatureCorrection(double gravity, double temp,
|
||||
char tempFormat, double calTemp = 20);
|
||||
double calculateGravity(double angle, double tempC,
|
||||
const char *tempFormula = 0);
|
||||
double gravityTemperatureCorrectionC(double gravity, double tempC,
|
||||
double calTempC = 20);
|
||||
int createFormula(RawFormulaData &fd, char *formulaBuffer,
|
||||
int formulaBufferSize, int order);
|
||||
|
||||
|
@ -48,7 +48,7 @@ Config::Config() {
|
||||
setGravityFormat('G');
|
||||
setSleepInterval(900); // 15 minutes
|
||||
setVoltageFactor(1.59); // Conversion factor for battery
|
||||
setTempSensorAdj(0.0);
|
||||
setTempSensorAdjC(0.0);
|
||||
setGravityTempAdj(false);
|
||||
gyroCalibration = {0, 0, 0, 0, 0, 0};
|
||||
formulaData = {{0, 0, 0, 0, 0}, {1, 1, 1, 1, 1}};
|
||||
@ -82,7 +82,7 @@ void Config::createJson(DynamicJsonDocument& doc) {
|
||||
doc[CFG_PARAM_VOLTAGEFACTOR] = getVoltageFactor();
|
||||
doc[CFG_PARAM_GRAVITY_FORMULA] = getGravityFormula();
|
||||
doc[CFG_PARAM_GRAVITY_FORMAT] = String(getGravityFormat());
|
||||
doc[CFG_PARAM_TEMP_ADJ] = getTempSensorAdj();
|
||||
doc[CFG_PARAM_TEMP_ADJ] = getTempSensorAdjC();
|
||||
doc[CFG_PARAM_GRAVITY_TEMP_ADJ] = isGravityTempAdj();
|
||||
doc[CFG_PARAM_GYRO_TEMP] = isGyroTemp();
|
||||
|
||||
@ -239,7 +239,7 @@ bool Config::loadFile() {
|
||||
setGravityFormat(s.charAt(0));
|
||||
}
|
||||
if (!doc[CFG_PARAM_TEMP_ADJ].isNull())
|
||||
setTempSensorAdj(doc[CFG_PARAM_TEMP_ADJ].as<float>());
|
||||
setTempSensorAdjC(doc[CFG_PARAM_TEMP_ADJ].as<float>());
|
||||
|
||||
if (!doc[CFG_PARAM_GYRO_CALIBRATION]["ax"].isNull())
|
||||
gyroCalibration.ax = doc[CFG_PARAM_GYRO_CALIBRATION]["ax"];
|
||||
@ -318,7 +318,7 @@ void Config::debug() {
|
||||
Log.verbose(F("CFG : Sleep interval; %d." CR), getSleepInterval());
|
||||
Log.verbose(F("CFG : OTA; '%s'." CR), getOtaURL());
|
||||
Log.verbose(F("CFG : Temp Format; %c." CR), getTempFormat());
|
||||
Log.verbose(F("CFG : Temp Adj; %F." CR), getTempSensorAdj());
|
||||
Log.verbose(F("CFG : Temp Adj; %F." CR), getTempSensorAdjC());
|
||||
Log.verbose(F("CFG : VoltageFactor; %F." CR), getVoltageFactor());
|
||||
Log.verbose(F("CFG : Gravity formula; '%s'." CR), getGravityFormula());
|
||||
Log.verbose(F("CFG : Gravity format; '%c'." CR), getGravityFormat());
|
||||
|
@ -89,6 +89,7 @@ SOFTWARE.
|
||||
#define CFG_PARAM_BATTERY "battery"
|
||||
#define CFG_PARAM_SLEEP_MODE "sleep-mode"
|
||||
#define CFG_PARAM_RSSI "rssi"
|
||||
#define CFG_PARAM_ERROR "error"
|
||||
|
||||
// Used for holding sensordata or sensoroffsets
|
||||
struct RawGyroData {
|
||||
@ -118,41 +119,40 @@ class Config {
|
||||
String id;
|
||||
String mDNS;
|
||||
String otaURL;
|
||||
char tempFormat; // C, F
|
||||
char tempFormat;
|
||||
float voltageFactor;
|
||||
float tempSensorAdj; // This value will be added to the read sensor value
|
||||
float tempSensorAdjC;
|
||||
int sleepInterval;
|
||||
bool gyroTemp; // Experimental feature
|
||||
bool gyroTemp;
|
||||
|
||||
// Wifi Config
|
||||
String wifiSSID;
|
||||
String wifiPASS;
|
||||
|
||||
// Push target settings
|
||||
String brewfatherPushUrl; // URL For brewfather
|
||||
String brewfatherPushUrl;
|
||||
|
||||
String httpPushUrl; // URL 1 for standard http
|
||||
String httpPushUrl2; // URL 2 for standard http
|
||||
String httpPushUrl;
|
||||
String httpPushUrl2;
|
||||
|
||||
String influxDb2Url; // URL for InfluxDB v2
|
||||
String influxDb2Org; // Organisation for InfluxDB v2
|
||||
String influxDb2Bucket; // Bucket for InfluxDB v2
|
||||
String influxDb2Token; // Auth Token for InfluxDB v2
|
||||
String influxDb2Url;
|
||||
String influxDb2Org;
|
||||
String influxDb2Bucket;
|
||||
String influxDb2Token;
|
||||
|
||||
String mqttUrl; // Server name
|
||||
String mqttUrl;
|
||||
String mqttTopic;
|
||||
String mqttUser;
|
||||
String mqttPass;
|
||||
|
||||
// Gravity and temperature calculations
|
||||
String gravityFormula;
|
||||
bool gravityTempAdj; // true, false
|
||||
char gravityFormat; // G, P
|
||||
bool gravityTempAdj;
|
||||
char gravityFormat;
|
||||
|
||||
// Gyro calibration data
|
||||
RawGyroData
|
||||
gyroCalibration; // Holds the gyro calibration constants (6 * int16_t)
|
||||
RawFormulaData formulaData; // Used for creating formula
|
||||
// Gyro calibration and formula calculation data
|
||||
RawGyroData gyroCalibration;
|
||||
RawFormulaData formulaData;
|
||||
|
||||
void debug();
|
||||
void formatFileSystem();
|
||||
@ -273,11 +273,13 @@ class Config {
|
||||
|
||||
char getTempFormat() { return tempFormat; }
|
||||
void setTempFormat(char c) {
|
||||
if (c == 'C' || c == 'F') {
|
||||
tempFormat = c;
|
||||
saveNeeded = true;
|
||||
}
|
||||
bool isTempC() { return tempFormat == 'C' ? false : true; }
|
||||
bool isTempF() { return tempFormat == 'F' ? false : true; }
|
||||
}
|
||||
bool isTempC() { return tempFormat == 'C'; }
|
||||
bool isTempF() { return tempFormat == 'F'; }
|
||||
|
||||
float getVoltageFactor() { return voltageFactor; }
|
||||
void setVoltageFactor(float f) {
|
||||
@ -289,13 +291,17 @@ class Config {
|
||||
saveNeeded = true;
|
||||
}
|
||||
|
||||
float getTempSensorAdj() { return tempSensorAdj; }
|
||||
void setTempSensorAdj(float f) {
|
||||
tempSensorAdj = f;
|
||||
float getTempSensorAdjC() { return tempSensorAdjC; }
|
||||
void setTempSensorAdjC(float f) {
|
||||
tempSensorAdjC = f;
|
||||
saveNeeded = true;
|
||||
}
|
||||
void setTempSensorAdj(String s) {
|
||||
tempSensorAdj = s.toFloat();
|
||||
void setTempSensorAdjC(String s) {
|
||||
tempSensorAdjC = s.toFloat();
|
||||
saveNeeded = true;
|
||||
}
|
||||
void setTempSensorAdjF(String s) {
|
||||
tempSensorAdjC = convertFtoC(s.toFloat());
|
||||
saveNeeded = true;
|
||||
}
|
||||
|
||||
@ -313,11 +319,13 @@ class Config {
|
||||
|
||||
char getGravityFormat() { return gravityFormat; }
|
||||
void setGravityFormat(char c) {
|
||||
if (c == 'G' || c == 'P') {
|
||||
gravityFormat = c;
|
||||
saveNeeded = true;
|
||||
}
|
||||
bool isGravitySG() { return gravityFormat == 'G' ? false : true; }
|
||||
bool isGravityPlato() { return gravityFormat == 'P' ? false : true; }
|
||||
}
|
||||
bool isGravitySG() { return gravityFormat == 'G'; }
|
||||
bool isGravityPlato() { return gravityFormat == 'P'; }
|
||||
|
||||
const RawGyroData& getGyroCalibration() { return gyroCalibration; }
|
||||
void setGyroCalibration(const RawGyroData& r) {
|
||||
|
@ -24,19 +24,39 @@ SOFTWARE.
|
||||
#include <ESP8266HTTPClient.h>
|
||||
#include <ESP8266WiFi.h>
|
||||
|
||||
#include <config.hpp>
|
||||
#include <gyro.hpp>
|
||||
#include <helper.hpp>
|
||||
#include <tempsensor.hpp>
|
||||
#include <wifi.hpp>
|
||||
|
||||
SerialDebug mySerial;
|
||||
BatteryVoltage myBatteryVoltage;
|
||||
|
||||
//
|
||||
// Convert sg to plato
|
||||
//
|
||||
double convertToPlato(double sg) { return 259 - (259 / sg); }
|
||||
|
||||
//
|
||||
// Convert plato to sg
|
||||
//
|
||||
double convertToSG(double plato) { return 259 / (259 - plato); }
|
||||
|
||||
//
|
||||
// Conversion to F
|
||||
//
|
||||
float convertCtoF(float c) { return (c * 1.8) + 32.0; }
|
||||
|
||||
//
|
||||
// Conversion to C
|
||||
//
|
||||
float convertFtoC(float f) { return (f - 32.0) / 1.8; }
|
||||
|
||||
//
|
||||
// Print the heap information.
|
||||
//
|
||||
void printHeap() {
|
||||
#if LOG_LEVEL == 6
|
||||
#if LOG_LEVEL == 6 && !defined(HELPER_DISABLE_LOGGING)
|
||||
Log.verbose(F("HELP: Heap %d kb, HeapFrag %d %%, FreeSketch %d kb." CR),
|
||||
ESP.getFreeHeap() / 1024, ESP.getHeapFragmentation(),
|
||||
ESP.getFreeSketchSpace() / 1024);
|
||||
@ -47,7 +67,7 @@ void printHeap() {
|
||||
// Enter deep sleep for the defined duration (Argument is seconds)
|
||||
//
|
||||
void deepSleep(int t) {
|
||||
#if LOG_LEVEL == 6
|
||||
#if LOG_LEVEL == 6 && !defined(HELPER_DISABLE_LOGGING)
|
||||
Log.verbose(F("HELP: Entering sleep mode for %ds." CR), t);
|
||||
#endif
|
||||
uint32_t wake = t * 1000000;
|
||||
@ -106,7 +126,7 @@ void BatteryVoltage::read() {
|
||||
float factor = myConfig.getVoltageFactor(); // Default value is 1.63
|
||||
int v = analogRead(A0);
|
||||
batteryLevel = ((3.3 / 1023) * v) * factor;
|
||||
#if LOG_LEVEL == 6
|
||||
#if LOG_LEVEL == 6 && !defined(HELPER_DISABLE_LOGGING)
|
||||
Log.verbose(
|
||||
F("BATT: Reading voltage level. Factor=%F Value=%d, Voltage=%F." CR),
|
||||
factor, v, batteryLevel);
|
||||
@ -177,14 +197,13 @@ void PerfLogging::print() {
|
||||
void PerfLogging::pushInflux() {
|
||||
if (!myConfig.isInfluxDb2Active()) return;
|
||||
|
||||
WiFiClient client;
|
||||
HTTPClient http;
|
||||
String serverPath =
|
||||
String(myConfig.getInfluxDb2PushUrl()) +
|
||||
"/api/v2/write?org=" + String(myConfig.getInfluxDb2PushOrg()) +
|
||||
"&bucket=" + String(myConfig.getInfluxDb2PushBucket());
|
||||
|
||||
http.begin(client, serverPath);
|
||||
http.begin(myWifi.getWifiClient(), serverPath);
|
||||
|
||||
// Create body for influxdb2, format used
|
||||
// key,host=mdns value=0.0
|
||||
@ -225,7 +244,7 @@ void PerfLogging::pushInflux() {
|
||||
|
||||
// Log.notice(F("PERF: data %s." CR), body.c_str() );
|
||||
|
||||
#if LOG_LEVEL == 6
|
||||
#if LOG_LEVEL == 6 && !defined(HELPER_DISABLE_LOGGING)
|
||||
Log.verbose(F("PERF: url %s." CR), serverPath.c_str());
|
||||
Log.verbose(F("PERF: data %s." CR), body.c_str());
|
||||
#endif
|
||||
@ -236,15 +255,18 @@ void PerfLogging::pushInflux() {
|
||||
int httpResponseCode = http.POST(body);
|
||||
|
||||
if (httpResponseCode == 204) {
|
||||
#if !defined(HELPER_DISABLE_LOGGING)
|
||||
Log.notice(
|
||||
F("PERF: InfluxDB2 push performance data successful, response=%d" CR),
|
||||
httpResponseCode);
|
||||
#endif
|
||||
} else {
|
||||
Log.error(F("PERF: InfluxDB2 push performance data failed, response=%d" CR),
|
||||
httpResponseCode);
|
||||
}
|
||||
|
||||
http.end();
|
||||
myWifi.closeWifiClient();
|
||||
}
|
||||
|
||||
#endif // COLLECT_PERFDATA
|
||||
|
@ -33,6 +33,12 @@ void deepSleep(int t);
|
||||
// Show build options
|
||||
void printBuildOptions();
|
||||
|
||||
// Data conversion
|
||||
double convertToPlato(double sg);
|
||||
double convertToSG(double plato);
|
||||
float convertCtoF(float c);
|
||||
float convertFtoC(float f);
|
||||
|
||||
// Float to String
|
||||
char* convertFloatToString(float f, char* buf, int dec = 2);
|
||||
float reduceFloatPrecision(float f, int dec = 2);
|
||||
|
23
src/main.cpp
23
src/main.cpp
@ -63,14 +63,18 @@ void checkSleepMode(float angle, float volt) {
|
||||
|
||||
if (!g.ax && !g.ay && !g.az && !g.gx && !g.gy && !g.gz) {
|
||||
// Will not enter sleep mode if: no calibration data
|
||||
#if !defined(MAIN_DISABLE_LOGGING)
|
||||
Log.notice(
|
||||
F("MAIN: Missing calibration data, so forcing webserver to be "
|
||||
"active." CR));
|
||||
#endif
|
||||
runMode = RunMode::configurationMode;
|
||||
} else if (sleepModeAlwaysSkip) {
|
||||
// Check if the flag from the UI has been set, the we force configuration
|
||||
// mode.
|
||||
#if !defined(MAIN_DISABLE_LOGGING)
|
||||
Log.notice(F("MAIN: Sleep mode disabled from web interface." CR));
|
||||
#endif
|
||||
runMode = RunMode::configurationMode;
|
||||
} else if ((volt < 4.15 && (angle > 85 && angle < 95)) || (volt > 4.15)) {
|
||||
runMode = RunMode::configurationMode;
|
||||
@ -80,14 +84,18 @@ void checkSleepMode(float angle, float volt) {
|
||||
|
||||
switch (runMode) {
|
||||
case RunMode::configurationMode:
|
||||
#if !defined(MAIN_DISABLE_LOGGING)
|
||||
Log.notice(F("MAIN: run mode CONFIG (angle=%F volt=%F)." CR), angle,
|
||||
volt);
|
||||
#endif
|
||||
break;
|
||||
case RunMode::wifiSetupMode:
|
||||
break;
|
||||
case RunMode::gravityMode:
|
||||
#if !defined(MAIN_DISABLE_LOGGING)
|
||||
Log.notice(F("MAIN: run mode GRAVITY (angle=%F volt=%F)." CR), angle,
|
||||
volt);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -207,22 +215,21 @@ bool loopReadGravity() {
|
||||
stableGyroMillis = millis(); // Reset timer
|
||||
|
||||
LOG_PERF_START("loop-temp-read");
|
||||
float temp = myTempSensor.getTempC(myConfig.isGyroTemp());
|
||||
float tempC = myTempSensor.getTempC(myConfig.isGyroTemp());
|
||||
LOG_PERF_STOP("loop-temp-read");
|
||||
|
||||
float gravity = calculateGravity(angle, temp);
|
||||
float corrGravity =
|
||||
gravityTemperatureCorrection(gravity, temp, myConfig.getTempFormat());
|
||||
float gravity = calculateGravity(angle, tempC);
|
||||
float corrGravity = gravityTemperatureCorrectionC(gravity, tempC);
|
||||
|
||||
#if LOG_LEVEL == 6 && !defined(MAIN_DISABLE_LOGGING)
|
||||
Log.verbose(F("Main: Sensor values gyro angle=%F, temp=%F, gravity=%F, "
|
||||
"corr=%F." CR),
|
||||
angle, temp, gravity, corrGravity);
|
||||
Log.verbose(F("Main: Sensor values gyro angle=%F, temp=%FC, gravity=%F, "
|
||||
"corr_gravity=%F." CR),
|
||||
angle, tempC, gravity, corrGravity);
|
||||
#endif
|
||||
|
||||
LOG_PERF_START("loop-push");
|
||||
// Force the transmission if we are going to sleep
|
||||
myPushTarget.send(angle, gravity, corrGravity, temp,
|
||||
myPushTarget.send(angle, gravity, corrGravity, tempC,
|
||||
(millis() - runtimeMillis) / 1000,
|
||||
runMode == RunMode::gravityMode ? true : false);
|
||||
LOG_PERF_STOP("loop-push");
|
||||
|
@ -21,19 +21,21 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#include <ESP8266HTTPClient.h>
|
||||
#include <MQTT.h>
|
||||
|
||||
#include <config.hpp>
|
||||
#include <gyro.hpp>
|
||||
#include <pushtarget.hpp>
|
||||
#include <wifi.hpp>
|
||||
|
||||
PushTarget myPushTarget;
|
||||
|
||||
//
|
||||
// Send the pressure value
|
||||
// Send the data to targets
|
||||
//
|
||||
void PushTarget::send(float angle, float gravity, float corrGravity, float temp,
|
||||
float runTime, bool force) {
|
||||
void PushTarget::send(float angle, float gravity, float corrGravity,
|
||||
float tempC, float runTime, bool force) {
|
||||
uint32_t timePassed = abs((int32_t)(millis() - ms));
|
||||
uint32_t interval = myConfig.getSleepInterval() * 1000;
|
||||
|
||||
@ -45,41 +47,37 @@ void PushTarget::send(float angle, float gravity, float corrGravity, float temp,
|
||||
return;
|
||||
}
|
||||
|
||||
#if LOG_LEVEL == 6 && !defined(PUSH_DISABLE_LOGGING)
|
||||
Log.verbose(F("PUSH: Sending data." CR));
|
||||
#endif
|
||||
|
||||
ms = millis();
|
||||
|
||||
if (myConfig.isBrewfatherActive()) {
|
||||
LOG_PERF_START("push-brewfather");
|
||||
sendBrewfather(angle, gravity, corrGravity, temp);
|
||||
sendBrewfather(angle, gravity, corrGravity, tempC);
|
||||
LOG_PERF_STOP("push-brewfather");
|
||||
}
|
||||
|
||||
if (myConfig.isHttpActive()) {
|
||||
LOG_PERF_START("push-http");
|
||||
sendHttp(myConfig.getHttpPushUrl(), angle, gravity, corrGravity, temp,
|
||||
sendHttp(myConfig.getHttpPushUrl(), angle, gravity, corrGravity, tempC,
|
||||
runTime);
|
||||
LOG_PERF_STOP("push-http");
|
||||
}
|
||||
|
||||
if (myConfig.isHttpActive2()) {
|
||||
LOG_PERF_START("push-http2");
|
||||
sendHttp(myConfig.getHttpPushUrl2(), angle, gravity, corrGravity, temp,
|
||||
sendHttp(myConfig.getHttpPushUrl2(), angle, gravity, corrGravity, tempC,
|
||||
runTime);
|
||||
LOG_PERF_STOP("push-http2");
|
||||
}
|
||||
|
||||
if (myConfig.isInfluxDb2Active()) {
|
||||
LOG_PERF_START("push-influxdb2");
|
||||
sendInfluxDb2(angle, gravity, corrGravity, temp, runTime);
|
||||
sendInfluxDb2(angle, gravity, corrGravity, tempC, runTime);
|
||||
LOG_PERF_STOP("push-influxdb2");
|
||||
}
|
||||
|
||||
if (myConfig.isMqttActive()) {
|
||||
LOG_PERF_START("push-mqtt");
|
||||
sendMqtt(angle, gravity, corrGravity, temp, runTime);
|
||||
sendMqtt(angle, gravity, corrGravity, tempC, runTime);
|
||||
LOG_PERF_STOP("push-mqtt");
|
||||
}
|
||||
}
|
||||
@ -88,32 +86,43 @@ void PushTarget::send(float angle, float gravity, float corrGravity, float temp,
|
||||
// Send to influx db v2
|
||||
//
|
||||
void PushTarget::sendInfluxDb2(float angle, float gravity, float corrGravity,
|
||||
float temp, float runTime) {
|
||||
float tempC, float runTime) {
|
||||
#if !defined(PUSH_DISABLE_LOGGING)
|
||||
Log.notice(
|
||||
F("PUSH: Sending values to influxdb2 angle=%F, gravity=%F, temp=%F." CR),
|
||||
angle, gravity, temp);
|
||||
angle, gravity, tempC);
|
||||
#endif
|
||||
|
||||
WiFiClient client;
|
||||
HTTPClient http;
|
||||
String serverPath =
|
||||
String(myConfig.getInfluxDb2PushUrl()) +
|
||||
"/api/v2/write?org=" + String(myConfig.getInfluxDb2PushOrg()) +
|
||||
"&bucket=" + String(myConfig.getInfluxDb2PushBucket());
|
||||
|
||||
http.begin(client, serverPath);
|
||||
http.begin(myWifi.getWifiClient(), serverPath);
|
||||
|
||||
float temp = myConfig.isTempC() ? tempC : convertCtoF(tempC);
|
||||
gravity = myConfig.isGravityTempAdj() ? corrGravity : gravity;
|
||||
|
||||
// Create body for influxdb2
|
||||
char buf[1024];
|
||||
if (myConfig.isGravitySG()) {
|
||||
snprintf(&buf[0], sizeof(buf),
|
||||
"measurement,host=%s,device=%s,temp-format=%c,gravity-format=%s "
|
||||
"gravity=%.4f,corr-gravity=%.4f,angle=%.2f,temp=%.2f,battery=%.2f,"
|
||||
"rssi=%d\n",
|
||||
// TODO: Add support for plato format
|
||||
myConfig.getMDNS(), myConfig.getID(), myConfig.getTempFormat(), "SG",
|
||||
myConfig.isGravityTempAdj() ? corrGravity : gravity, corrGravity,
|
||||
angle, temp, myBatteryVoltage.getVoltage(), WiFi.RSSI());
|
||||
myConfig.getMDNS(), myConfig.getID(), myConfig.getTempFormat(),
|
||||
"G", gravity, corrGravity, angle, temp,
|
||||
myBatteryVoltage.getVoltage(), WiFi.RSSI());
|
||||
} else {
|
||||
snprintf(&buf[0], sizeof(buf),
|
||||
"measurement,host=%s,device=%s,temp-format=%c,gravity-format=%s "
|
||||
"gravity=%.1f,corr-gravity=%.1f,angle=%.2f,temp=%.2f,battery=%.2f,"
|
||||
"rssi=%d\n",
|
||||
myConfig.getMDNS(), myConfig.getID(), myConfig.getTempFormat(),
|
||||
"G", convertToPlato(gravity), convertToPlato(corrGravity), angle,
|
||||
convertCtoF(temp), myBatteryVoltage.getVoltage(), WiFi.RSSI());
|
||||
}
|
||||
|
||||
#if LOG_LEVEL == 6 && !defined(PUSH_DISABLE_LOGGING)
|
||||
Log.verbose(F("PUSH: url %s." CR), serverPath.c_str());
|
||||
@ -134,17 +143,18 @@ void PushTarget::sendInfluxDb2(float angle, float gravity, float corrGravity,
|
||||
}
|
||||
|
||||
http.end();
|
||||
myWifi.closeWifiClient();
|
||||
}
|
||||
|
||||
//
|
||||
// Send data to brewfather
|
||||
//
|
||||
void PushTarget::sendBrewfather(float angle, float gravity, float corrGravity,
|
||||
float temp) {
|
||||
float tempC) {
|
||||
#if !defined(PUSH_DISABLE_LOGGING)
|
||||
Log.notice(
|
||||
F("PUSH: Sending values to brewfather angle=%F, gravity=%F, temp=%F." CR),
|
||||
angle, gravity, temp);
|
||||
Log.notice(F("PUSH: Sending values to brewfather angle=%F, gravity=%F, "
|
||||
"corr-gravity=%F, temp=%F." CR),
|
||||
angle, gravity, corrGravity, tempC);
|
||||
#endif
|
||||
|
||||
DynamicJsonDocument doc(300);
|
||||
@ -165,21 +175,26 @@ void PushTarget::sendBrewfather(float angle, float gravity, float corrGravity,
|
||||
// "battery": 4.98
|
||||
// }
|
||||
//
|
||||
float temp = myConfig.isTempC() ? tempC : convertCtoF(tempC);
|
||||
|
||||
doc["name"] = myConfig.getMDNS();
|
||||
doc["temp"] = reduceFloatPrecision(temp, 1);
|
||||
doc["temp_unit"] = String(myConfig.getTempFormat());
|
||||
doc["battery"] = reduceFloatPrecision(myBatteryVoltage.getVoltage(), 2);
|
||||
// TODO: Add support for plato format
|
||||
if (myConfig.isGravitySG()) {
|
||||
doc["gravity"] = reduceFloatPrecision(
|
||||
myConfig.isGravityTempAdj() ? corrGravity : gravity, 4);
|
||||
} else {
|
||||
doc["gravity"] = reduceFloatPrecision(
|
||||
convertToPlato(myConfig.isGravityTempAdj() ? corrGravity : gravity), 1);
|
||||
}
|
||||
doc["gravity_unit"] = myConfig.isGravitySG() ? "G" : "P";
|
||||
|
||||
WiFiClient client;
|
||||
HTTPClient http;
|
||||
String serverPath = myConfig.getBrewfatherPushUrl();
|
||||
|
||||
// Your Domain name with URL path or IP address with path
|
||||
http.begin(client, serverPath);
|
||||
http.begin(myWifi.getWifiClient(), serverPath);
|
||||
String json;
|
||||
serializeJson(doc, json);
|
||||
#if LOG_LEVEL == 6 && !defined(PUSH_DISABLE_LOGGING)
|
||||
@ -200,6 +215,7 @@ void PushTarget::sendBrewfather(float angle, float gravity, float corrGravity,
|
||||
}
|
||||
|
||||
http.end();
|
||||
myWifi.closeWifiClient();
|
||||
}
|
||||
|
||||
//
|
||||
@ -207,24 +223,31 @@ void PushTarget::sendBrewfather(float angle, float gravity, float corrGravity,
|
||||
//
|
||||
void PushTarget::createIspindleFormat(DynamicJsonDocument &doc, float angle,
|
||||
float gravity, float corrGravity,
|
||||
float temp, float runTime) {
|
||||
float tempC, float runTime) {
|
||||
float temp = myConfig.isTempC() ? tempC : convertCtoF(tempC);
|
||||
|
||||
// Use iSpindle format for compatibility
|
||||
doc["name"] = myConfig.getMDNS();
|
||||
doc["ID"] = myConfig.getID();
|
||||
doc["token"] = "gravmon";
|
||||
doc["token"] = "gravitmon";
|
||||
doc["interval"] = myConfig.getSleepInterval();
|
||||
doc["temperature"] = reduceFloatPrecision(temp, 1);
|
||||
doc["temp-units"] = String(myConfig.getTempFormat());
|
||||
// TODO: Add support for plato format
|
||||
if (myConfig.isGravitySG()) {
|
||||
doc["gravity"] = reduceFloatPrecision(
|
||||
myConfig.isGravityTempAdj() ? corrGravity : gravity, 4);
|
||||
doc["corr-gravity"] = reduceFloatPrecision(corrGravity, 4);
|
||||
} else {
|
||||
doc["gravity"] = reduceFloatPrecision(
|
||||
convertToPlato(myConfig.isGravityTempAdj() ? corrGravity : gravity), 1);
|
||||
doc["corr-gravity"] = reduceFloatPrecision(convertToPlato(corrGravity), 1);
|
||||
}
|
||||
doc["angle"] = reduceFloatPrecision(angle, 2);
|
||||
doc["battery"] = reduceFloatPrecision(myBatteryVoltage.getVoltage(), 2);
|
||||
doc["rssi"] = WiFi.RSSI();
|
||||
|
||||
// Some additional information
|
||||
doc["gravity-units"] = "SG";
|
||||
doc["gravity-unit"] = myConfig.isGravitySG() ? "G" : "P";
|
||||
doc["run-time"] = reduceFloatPrecision(runTime, 2);
|
||||
}
|
||||
|
||||
@ -232,21 +255,26 @@ void PushTarget::createIspindleFormat(DynamicJsonDocument &doc, float angle,
|
||||
// Send data to http target
|
||||
//
|
||||
void PushTarget::sendHttp(String serverPath, float angle, float gravity,
|
||||
float corrGravity, float temp, float runTime) {
|
||||
float corrGravity, float tempC, float runTime) {
|
||||
#if !defined(PUSH_DISABLE_LOGGING)
|
||||
Log.notice(
|
||||
F("PUSH: Sending values to http angle=%F, gravity=%F, temp=%F." CR),
|
||||
angle, gravity, temp);
|
||||
Log.notice(F("PUSH: Sending values to http angle=%F, gravity=%F, "
|
||||
"corr-gravity=%F, temp=%F." CR),
|
||||
angle, gravity, corrGravity, tempC);
|
||||
#endif
|
||||
|
||||
DynamicJsonDocument doc(256);
|
||||
createIspindleFormat(doc, angle, gravity, corrGravity, temp, runTime);
|
||||
createIspindleFormat(doc, angle, gravity, corrGravity, tempC, runTime);
|
||||
|
||||
WiFiClient client;
|
||||
HTTPClient http;
|
||||
|
||||
// Your Domain name with URL path or IP address with path
|
||||
http.begin(client, serverPath);
|
||||
if (serverPath.startsWith("https://")) {
|
||||
myWifi.getWifiClientSecure().setInsecure();
|
||||
Log.notice(F("PUSH: HTTP, SSL enabled without validation." CR));
|
||||
http.begin(myWifi.getWifiClientSecure(), serverPath);
|
||||
} else {
|
||||
http.begin(myWifi.getWifiClient(), serverPath);
|
||||
}
|
||||
|
||||
String json;
|
||||
serializeJson(doc, json);
|
||||
#if LOG_LEVEL == 6 && !defined(PUSH_DISABLE_LOGGING)
|
||||
@ -266,26 +294,36 @@ void PushTarget::sendHttp(String serverPath, float angle, float gravity,
|
||||
}
|
||||
|
||||
http.end();
|
||||
myWifi.closeWifiClient();
|
||||
}
|
||||
|
||||
//
|
||||
// Send data to http target
|
||||
//
|
||||
void PushTarget::sendMqtt(float angle, float gravity, float corrGravity,
|
||||
float temp, float runTime) {
|
||||
float tempC, float runTime) {
|
||||
#if !defined(PUSH_DISABLE_LOGGING)
|
||||
Log.notice(
|
||||
F("PUSH: Sending values to mqtt angle=%F, gravity=%F, temp=%F." CR),
|
||||
angle, gravity, temp);
|
||||
Log.notice(F("PUSH: Sending values to mqtt angle=%F, gravity=%F, "
|
||||
"corr-gravity=%F, temp=%F." CR),
|
||||
angle, gravity, corrGravity, tempC);
|
||||
#endif
|
||||
|
||||
DynamicJsonDocument doc(256);
|
||||
createIspindleFormat(doc, angle, gravity, corrGravity, temp, runTime);
|
||||
createIspindleFormat(doc, angle, gravity, corrGravity, tempC, runTime);
|
||||
|
||||
WiFiClient client;
|
||||
MQTTClient mqtt(512); // Maximum message size
|
||||
String url = myConfig.getMqttUrl();
|
||||
|
||||
if (url.endsWith(":8883")) {
|
||||
// Allow secure channel, but without certificate validation
|
||||
myWifi.getWifiClientSecure().setInsecure();
|
||||
Log.notice(F("PUSH: MQTT, SSL enabled without validation." CR));
|
||||
url.replace(":8883", "");
|
||||
mqtt.begin(url.c_str(), 8883, myWifi.getWifiClientSecure());
|
||||
} else {
|
||||
mqtt.begin(myConfig.getMqttUrl(), myWifi.getWifiClient());
|
||||
}
|
||||
|
||||
mqtt.begin(myConfig.getMqttUrl(), client);
|
||||
mqtt.connect(myConfig.getMDNS(), myConfig.getMqttUser(),
|
||||
myConfig.getMqttPass());
|
||||
|
||||
@ -306,6 +344,7 @@ void PushTarget::sendMqtt(float angle, float gravity, float corrGravity,
|
||||
}
|
||||
|
||||
mqtt.disconnect();
|
||||
myWifi.closeWifiClient();
|
||||
}
|
||||
|
||||
// EOF
|
||||
|
@ -27,8 +27,6 @@ SOFTWARE.
|
||||
// Includes
|
||||
#include <Arduino.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <ESP8266HTTPClient.h>
|
||||
#include <ESP8266WiFi.h>
|
||||
|
||||
#include <helper.hpp>
|
||||
|
||||
@ -38,15 +36,15 @@ class PushTarget {
|
||||
uint32_t ms; // Used to check that we do not post to often
|
||||
|
||||
void sendBrewfather(float angle, float gravity, float corrGravity,
|
||||
float temp);
|
||||
float tempC);
|
||||
void sendHttp(String serverPath, float angle, float gravity,
|
||||
float corrGravity, float temp, float runTime);
|
||||
void sendInfluxDb2(float angle, float gravity, float corrGravity, float temp,
|
||||
float corrGravity, float tempC, float runTime);
|
||||
void sendInfluxDb2(float angle, float gravity, float corrGravity, float tempC,
|
||||
float runTime);
|
||||
void sendMqtt(float angle, float gravity, float corrGravity, float temp,
|
||||
void sendMqtt(float angle, float gravity, float corrGravity, float tempC,
|
||||
float runTime);
|
||||
void createIspindleFormat(DynamicJsonDocument &doc, float angle,
|
||||
float gravity, float corrGravity, float temp,
|
||||
float gravity, float corrGravity, float tempC,
|
||||
float runTime);
|
||||
|
||||
public:
|
||||
|
@ -30,11 +30,6 @@ SOFTWARE.
|
||||
#include <helper.hpp>
|
||||
#include <tempsensor.hpp>
|
||||
|
||||
//
|
||||
// Conversion between C and F
|
||||
//
|
||||
float convertCtoF(float t) { return (t * 1.8) + 32.0; }
|
||||
|
||||
OneWire myOneWire(D6);
|
||||
DallasTemperature mySensors(&myOneWire);
|
||||
#define TEMPERATURE_PRECISION 9
|
||||
@ -63,20 +58,12 @@ void TempSensor::setup() {
|
||||
mySensors.setResolution(TEMPERATURE_PRECISION);
|
||||
}
|
||||
|
||||
float t = myConfig.getTempSensorAdj();
|
||||
|
||||
// Set the temp sensor adjustment values
|
||||
if (myConfig.isTempC()) {
|
||||
tempSensorAdjF = t * 1.8; // Convert the adjustment value to C
|
||||
tempSensorAdjC = t;
|
||||
} else {
|
||||
tempSensorAdjF = t;
|
||||
tempSensorAdjC = t * 0.556; // Convert the adjustent value to F
|
||||
}
|
||||
tempSensorAdjC = myConfig.getTempSensorAdjC();
|
||||
|
||||
#if LOG_LEVEL == 6 && !defined(TSEN_DISABLE_LOGGING)
|
||||
Log.verbose(F("TSEN: Adjustment values for temp sensor %F C, %F F." CR),
|
||||
tempSensorAdjC, tempSensorAdjF);
|
||||
Log.verbose(F("TSEN: Adjustment values for temp sensor %F C." CR),
|
||||
tempSensorAdjC);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -101,7 +88,9 @@ float TempSensor::getValue(bool useGyro) {
|
||||
|
||||
// If we dont have sensors just return 0
|
||||
if (!mySensors.getDS18Count()) {
|
||||
Log.error(F("TSEN: No temperature sensors found. Skipping read." CR));
|
||||
#if !defined(TSEN_DISABLE_LOGGING)
|
||||
Log.notice(F("TSEN: No temperature sensors found. Skipping read." CR));
|
||||
#endif
|
||||
return -273;
|
||||
}
|
||||
|
||||
|
@ -25,13 +25,11 @@ SOFTWARE.
|
||||
#define SRC_TEMPSENSOR_HPP_
|
||||
|
||||
// definitions
|
||||
float convertCtoF(float t);
|
||||
|
||||
// classes
|
||||
class TempSensor {
|
||||
private:
|
||||
bool hasSensor = false;
|
||||
float tempSensorAdjF = 0;
|
||||
float tempSensorAdjC = 0;
|
||||
float getValue(bool useGyro);
|
||||
|
||||
@ -41,9 +39,6 @@ class TempSensor {
|
||||
float getTempC(bool useGyro = false) {
|
||||
return getValue(useGyro) + tempSensorAdjC;
|
||||
}
|
||||
float getTempF(bool useGyro = false) {
|
||||
return convertCtoF(getValue(useGyro)) + tempSensorAdjF;
|
||||
}
|
||||
};
|
||||
|
||||
// Global instance created
|
||||
|
@ -72,16 +72,23 @@ void WebServer::webHandleConfig() {
|
||||
doc[CFG_PARAM_PASS] = ""; // dont show the wifi password
|
||||
|
||||
double angle = myGyro.getAngle();
|
||||
double temp = myTempSensor.getTempC(myConfig.isGyroTemp());
|
||||
double gravity = calculateGravity(angle, temp);
|
||||
double tempC = myTempSensor.getTempC(myConfig.isGyroTemp());
|
||||
double gravity = calculateGravity(angle, tempC);
|
||||
|
||||
doc[CFG_PARAM_ANGLE] = reduceFloatPrecision(angle);
|
||||
if (myConfig.isGravityTempAdj())
|
||||
doc[CFG_PARAM_GRAVITY] = reduceFloatPrecision(
|
||||
gravityTemperatureCorrection(gravity, temp, myConfig.getTempFormat()),
|
||||
4);
|
||||
else
|
||||
doc[CFG_PARAM_GRAVITY_FORMAT] = String(myConfig.getGravityFormat());
|
||||
|
||||
if (myConfig.isGravityTempAdj()) {
|
||||
gravity =
|
||||
gravityTemperatureCorrectionC(gravity, tempC, myConfig.getTempFormat());
|
||||
}
|
||||
|
||||
if (myConfig.isGravityPlato()) {
|
||||
doc[CFG_PARAM_GRAVITY] = reduceFloatPrecision(convertToPlato(gravity), 1);
|
||||
} else {
|
||||
doc[CFG_PARAM_GRAVITY] = reduceFloatPrecision(gravity, 4);
|
||||
}
|
||||
|
||||
doc[CFG_PARAM_BATTERY] = reduceFloatPrecision(myBatteryVoltage.getVoltage());
|
||||
|
||||
#if LOG_LEVEL == 6 && !defined(WEB_DISABLE_LOGGING)
|
||||
@ -215,22 +222,24 @@ void WebServer::webHandleStatus() {
|
||||
DynamicJsonDocument doc(256);
|
||||
|
||||
double angle = myGyro.getAngle();
|
||||
double temp = myTempSensor.getTempC(myConfig.isGyroTemp());
|
||||
double gravity = calculateGravity(angle, temp);
|
||||
double tempC = myTempSensor.getTempC(myConfig.isGyroTemp());
|
||||
double gravity = calculateGravity(angle, tempC);
|
||||
|
||||
doc[CFG_PARAM_ID] = myConfig.getID();
|
||||
doc[CFG_PARAM_ANGLE] = reduceFloatPrecision(angle);
|
||||
if (myConfig.isGravityTempAdj())
|
||||
doc[CFG_PARAM_GRAVITY] = reduceFloatPrecision(
|
||||
gravityTemperatureCorrection(gravity, temp, myConfig.getTempFormat()),
|
||||
4);
|
||||
else
|
||||
if (myConfig.isGravityTempAdj()) {
|
||||
gravity = gravityTemperatureCorrectionC(gravity, tempC); //
|
||||
}
|
||||
if (myConfig.isGravityPlato()) {
|
||||
doc[CFG_PARAM_GRAVITY] = reduceFloatPrecision(convertToPlato(gravity), 1);
|
||||
} else {
|
||||
doc[CFG_PARAM_GRAVITY] = reduceFloatPrecision(gravity, 4);
|
||||
doc[CFG_PARAM_TEMP_C] = reduceFloatPrecision(temp, 1);
|
||||
doc[CFG_PARAM_TEMP_F] =
|
||||
reduceFloatPrecision(myTempSensor.getTempF(myConfig.isGyroTemp()), 1);
|
||||
}
|
||||
doc[CFG_PARAM_TEMP_C] = reduceFloatPrecision(tempC, 1);
|
||||
doc[CFG_PARAM_TEMP_F] = reduceFloatPrecision(convertCtoF(tempC), 1);
|
||||
doc[CFG_PARAM_BATTERY] = reduceFloatPrecision(myBatteryVoltage.getVoltage());
|
||||
doc[CFG_PARAM_TEMPFORMAT] = String(myConfig.getTempFormat());
|
||||
doc[CFG_PARAM_GRAVITY_FORMAT] = String(myConfig.getGravityFormat());
|
||||
doc[CFG_PARAM_SLEEP_MODE] = sleepModeAlwaysSkip;
|
||||
doc[CFG_PARAM_RSSI] = WiFi.RSSI();
|
||||
|
||||
@ -280,8 +289,7 @@ void WebServer::webHandleStatusSleepmode() {
|
||||
}
|
||||
|
||||
#if LOG_LEVEL == 6 && !defined(WEB_DISABLE_LOGGING)
|
||||
Log.verbose(F("WEB : sleep-mode=%s." CR),
|
||||
server->arg(CFG_PARAM_SLEEP_MODE).c_str());
|
||||
Log.verbose(F("WEB : %s." CR), getRequestArguments().c_str());
|
||||
#endif
|
||||
|
||||
if (server->arg(CFG_PARAM_SLEEP_MODE).equalsIgnoreCase("true"))
|
||||
@ -309,9 +317,7 @@ void WebServer::webHandleConfigDevice() {
|
||||
}
|
||||
|
||||
#if LOG_LEVEL == 6 && !defined(WEB_DISABLE_LOGGING)
|
||||
Log.verbose(F("WEB : mdns=%s, temp-format=%s." CR),
|
||||
server->arg(CFG_PARAM_MDNS).c_str(),
|
||||
server->arg(CFG_PARAM_TEMPFORMAT).c_str());
|
||||
Log.verbose(F("WEB : %s." CR), getRequestArguments().c_str());
|
||||
#endif
|
||||
|
||||
myConfig.setMDNS(server->arg(CFG_PARAM_MDNS).c_str());
|
||||
@ -339,14 +345,7 @@ void WebServer::webHandleConfigPush() {
|
||||
return;
|
||||
}
|
||||
#if LOG_LEVEL == 6 && !defined(WEB_DISABLE_LOGGING)
|
||||
Log.verbose(F("WEB : http=%s,%s, bf=%s influx2=%s, %s, %s, %s." CR),
|
||||
server->arg(CFG_PARAM_PUSH_HTTP).c_str(),
|
||||
server->arg(CFG_PARAM_PUSH_HTTP2).c_str(),
|
||||
server->arg(CFG_PARAM_PUSH_BREWFATHER).c_str(),
|
||||
server->arg(CFG_PARAM_PUSH_INFLUXDB2).c_str(),
|
||||
server->arg(CFG_PARAM_PUSH_INFLUXDB2_ORG).c_str(),
|
||||
server->arg(CFG_PARAM_PUSH_INFLUXDB2_BUCKET).c_str(),
|
||||
server->arg(CFG_PARAM_PUSH_INFLUXDB2_AUTH).c_str());
|
||||
Log.verbose(F("WEB : %s." CR), getRequestArguments().c_str());
|
||||
#endif
|
||||
|
||||
myConfig.setHttpPushUrl(server->arg(CFG_PARAM_PUSH_HTTP).c_str());
|
||||
@ -369,6 +368,25 @@ void WebServer::webHandleConfigPush() {
|
||||
LOG_PERF_STOP("webserver-api-config-push");
|
||||
}
|
||||
|
||||
//
|
||||
// Get string with all received arguments. Used for debugging only.
|
||||
//
|
||||
String WebServer::getRequestArguments() {
|
||||
String debug;
|
||||
|
||||
for (int i = 0; i < server->args(); i++) {
|
||||
if (!server->argName(i).equals(
|
||||
"plain")) { // this contains all the arguments, we dont need that.
|
||||
if (debug.length()) debug += ", ";
|
||||
|
||||
debug += server->argName(i);
|
||||
debug += "=";
|
||||
debug += server->arg(i);
|
||||
}
|
||||
}
|
||||
return debug;
|
||||
}
|
||||
|
||||
//
|
||||
// Update gravity settings.
|
||||
//
|
||||
@ -386,11 +404,10 @@ void WebServer::webHandleConfigGravity() {
|
||||
}
|
||||
|
||||
#if LOG_LEVEL == 6 && !defined(WEB_DISABLE_LOGGING)
|
||||
Log.verbose(F("WEB : formula=%s, temp-corr=%s." CR),
|
||||
server->arg(CFG_PARAM_GRAVITY_FORMULA).c_str(),
|
||||
server->arg(CFG_PARAM_GRAVITY_TEMP_ADJ).c_str());
|
||||
Log.verbose(F("WEB : %s." CR), getRequestArguments().c_str());
|
||||
#endif
|
||||
|
||||
myConfig.setGravityFormat(server->arg(CFG_PARAM_GRAVITY_FORMAT).charAt(0));
|
||||
myConfig.setGravityFormula(server->arg(CFG_PARAM_GRAVITY_FORMULA).c_str());
|
||||
myConfig.setGravityTempAdj(
|
||||
server->arg(CFG_PARAM_GRAVITY_TEMP_ADJ).equalsIgnoreCase("on") ? true
|
||||
@ -418,15 +435,15 @@ void WebServer::webHandleConfigHardware() {
|
||||
}
|
||||
|
||||
#if LOG_LEVEL == 6 && !defined(WEB_DISABLE_LOGGING)
|
||||
Log.verbose(F("WEB : vf=%s, tempadj=%s, ota=%s gyrotemp=%s." CR),
|
||||
server->arg(CFG_PARAM_VOLTAGEFACTOR).c_str(),
|
||||
server->arg(CFG_PARAM_TEMP_ADJ).c_str(),
|
||||
server->arg(CFG_PARAM_OTA).c_str(),
|
||||
server->arg(CFG_PARAM_GYRO_TEMP).c_str());
|
||||
Log.verbose(F("WEB : %s." CR), getRequestArguments().c_str());
|
||||
#endif
|
||||
|
||||
myConfig.setVoltageFactor(server->arg(CFG_PARAM_VOLTAGEFACTOR).toFloat());
|
||||
myConfig.setTempSensorAdj(server->arg(CFG_PARAM_TEMP_ADJ).toFloat());
|
||||
if (myConfig.isTempC()) {
|
||||
myConfig.setTempSensorAdjC(server->arg(CFG_PARAM_TEMP_ADJ));
|
||||
} else {
|
||||
myConfig.setTempSensorAdjF(server->arg(CFG_PARAM_TEMP_ADJ));
|
||||
}
|
||||
myConfig.setOtaURL(server->arg(CFG_PARAM_OTA).c_str());
|
||||
myConfig.setGyroTemp(
|
||||
server->arg(CFG_PARAM_GYRO_TEMP).equalsIgnoreCase("on") ? true : false);
|
||||
@ -447,24 +464,24 @@ void WebServer::webHandleFormulaRead() {
|
||||
const RawFormulaData& fd = myConfig.getFormulaData();
|
||||
|
||||
#if LOG_LEVEL == 6 && !defined(WEB_DISABLE_LOGGING)
|
||||
Log.verbose(F("WEB : %F %F %F %F %F." CR), fd.a[0], fd.a[1], fd.a[2], fd.a[3],
|
||||
fd.a[4]);
|
||||
Log.verbose(F("WEB : %F %F %F %F %F." CR), fd.g[0], fd.g[1], fd.g[2], fd.g[3],
|
||||
fd.g[4]);
|
||||
Log.verbose(F("WEB : %s." CR), getRequestArguments().c_str());
|
||||
#endif
|
||||
|
||||
doc[CFG_PARAM_ID] = myConfig.getID();
|
||||
doc[CFG_PARAM_ANGLE] = reduceFloatPrecision(myGyro.getAngle());
|
||||
doc[CFG_PARAM_GRAVITY_FORMAT] = String(myConfig.getGravityFormat());
|
||||
doc[CFG_PARAM_GRAVITY_FORMULA] = "";
|
||||
doc[CFG_PARAM_ERROR] = "";
|
||||
|
||||
switch (lastFormulaCreateError) {
|
||||
case ERR_FORMULA_INTERNAL:
|
||||
doc[CFG_PARAM_GRAVITY_FORMULA] = "Internal error creating formula.";
|
||||
doc[CFG_PARAM_ERROR] = "Internal error creating formula.";
|
||||
break;
|
||||
case ERR_FORMULA_NOTENOUGHVALUES:
|
||||
doc[CFG_PARAM_GRAVITY_FORMULA] = "Not enough values to create formula.";
|
||||
doc[CFG_PARAM_ERROR] = "Not enough values to create formula.";
|
||||
break;
|
||||
case ERR_FORMULA_UNABLETOFFIND:
|
||||
doc[CFG_PARAM_GRAVITY_FORMULA] =
|
||||
doc[CFG_PARAM_ERROR] =
|
||||
"Unable to find an accurate formula based on input.";
|
||||
break;
|
||||
default:
|
||||
@ -478,11 +495,19 @@ void WebServer::webHandleFormulaRead() {
|
||||
doc["a4"] = reduceFloatPrecision(fd.a[3], 2);
|
||||
doc["a5"] = reduceFloatPrecision(fd.a[4], 2);
|
||||
|
||||
if (myConfig.isGravityPlato()) {
|
||||
doc["g1"] = reduceFloatPrecision(convertToPlato(fd.g[0]), 1);
|
||||
doc["g2"] = reduceFloatPrecision(convertToPlato(fd.g[1]), 1);
|
||||
doc["g3"] = reduceFloatPrecision(convertToPlato(fd.g[2]), 1);
|
||||
doc["g4"] = reduceFloatPrecision(convertToPlato(fd.g[3]), 1);
|
||||
doc["g5"] = reduceFloatPrecision(convertToPlato(fd.g[4]), 1);
|
||||
} else {
|
||||
doc["g1"] = reduceFloatPrecision(fd.g[0], 4);
|
||||
doc["g2"] = reduceFloatPrecision(fd.g[1], 4);
|
||||
doc["g3"] = reduceFloatPrecision(fd.g[2], 4);
|
||||
doc["g4"] = reduceFloatPrecision(fd.g[3], 4);
|
||||
doc["g5"] = reduceFloatPrecision(fd.g[4], 4);
|
||||
}
|
||||
|
||||
#if LOG_LEVEL == 6 && !defined(WEB_DISABLE_LOGGING)
|
||||
serializeJson(doc, Serial);
|
||||
@ -512,13 +537,7 @@ void WebServer::webHandleFormulaWrite() {
|
||||
}
|
||||
|
||||
#if LOG_LEVEL == 6 && !defined(WEB_DISABLE_LOGGING)
|
||||
Log.verbose(F("WEB : angles=%F,%F,%F,%F,%F." CR), server->arg("a1").toFloat(),
|
||||
server->arg("a2").toFloat(), server->arg("a3").toFloat(),
|
||||
server->arg("a4").toFloat(), server->arg("a5").toFloat());
|
||||
Log.verbose(F("WEB : gravity=%F,%F,%F,%F,%F." CR),
|
||||
server->arg("g1").toFloat(), server->arg("g2").toFloat(),
|
||||
server->arg("g3").toFloat(), server->arg("g4").toFloat(),
|
||||
server->arg("g5").toFloat());
|
||||
Log.verbose(F("WEB : %s." CR), getRequestArguments().c_str());
|
||||
#endif
|
||||
|
||||
RawFormulaData fd;
|
||||
@ -527,11 +546,21 @@ void WebServer::webHandleFormulaWrite() {
|
||||
fd.a[2] = server->arg("a3").toDouble();
|
||||
fd.a[3] = server->arg("a4").toDouble();
|
||||
fd.a[4] = server->arg("a5").toDouble();
|
||||
|
||||
if (myConfig.isGravityPlato()) {
|
||||
fd.g[0] = convertToSG(server->arg("g1").toDouble());
|
||||
fd.g[1] = convertToSG(server->arg("g2").toDouble());
|
||||
fd.g[2] = convertToSG(server->arg("g3").toDouble());
|
||||
fd.g[3] = convertToSG(server->arg("g4").toDouble());
|
||||
fd.g[4] = convertToSG(server->arg("g5").toDouble());
|
||||
} else {
|
||||
fd.g[0] = server->arg("g1").toDouble();
|
||||
fd.g[1] = server->arg("g2").toDouble();
|
||||
fd.g[2] = server->arg("g3").toDouble();
|
||||
fd.g[3] = server->arg("g4").toDouble();
|
||||
fd.g[4] = server->arg("g5").toDouble();
|
||||
}
|
||||
|
||||
myConfig.setFormulaData(fd);
|
||||
|
||||
int e;
|
||||
@ -727,9 +756,8 @@ bool WebServer::setupWebServer() {
|
||||
// called from main loop
|
||||
//
|
||||
void WebServer::loop() {
|
||||
// Dont put serial debug output in this call
|
||||
server->handleClient();
|
||||
MDNS.update();
|
||||
server->handleClient();
|
||||
}
|
||||
|
||||
// EOF
|
||||
|
@ -65,6 +65,8 @@ class WebServer {
|
||||
void webHandleDevice();
|
||||
void webHandlePageNotFound();
|
||||
|
||||
String getRequestArguments();
|
||||
|
||||
// Inline functions.
|
||||
void webReturnOK() { server->send(200); }
|
||||
#if defined(EMBED_HTML)
|
||||
|
46
src/wifi.cpp
46
src/wifi.cpp
@ -110,6 +110,8 @@ String WifiConnection::getIPAddress() { return WiFi.localIP().toString(); }
|
||||
// Additional method to detect double reset.
|
||||
//
|
||||
bool WifiConnection::isDoubleResetDetected() {
|
||||
if (strlen(userSSID))
|
||||
return false; // Ignore this if we have hardcoded settings.
|
||||
return myDRD->detectDoubleReset();
|
||||
}
|
||||
|
||||
@ -230,11 +232,17 @@ bool WifiConnection::updateFirmware() {
|
||||
Log.verbose(F("WIFI: Updating firmware." CR));
|
||||
#endif
|
||||
|
||||
WiFiClient client;
|
||||
String serverPath = myConfig.getOtaURL();
|
||||
serverPath += "firmware.bin";
|
||||
HTTPUpdateResult ret;
|
||||
|
||||
HTTPUpdateResult ret = ESPhttpUpdate.update(client, serverPath);
|
||||
if (serverPath.startsWith("https://")) {
|
||||
myWifi.getWifiClientSecure().setInsecure();
|
||||
Log.notice(F("WIFI: OTA, SSL enabled without validation." CR));
|
||||
ret = ESPhttpUpdate.update(myWifi.getWifiClientSecure(), serverPath);
|
||||
} else {
|
||||
ret = ESPhttpUpdate.update(myWifi.getWifiClient(), serverPath);
|
||||
}
|
||||
|
||||
switch (ret) {
|
||||
case HTTP_UPDATE_FAILED:
|
||||
@ -257,16 +265,21 @@ bool WifiConnection::updateFirmware() {
|
||||
// Download and save file
|
||||
//
|
||||
void WifiConnection::downloadFile(const char *fname) {
|
||||
#if LOG_LEVEL == 6
|
||||
#if LOG_LEVEL == 6 && !defined(WIFI_DISABLE_LOGGING)
|
||||
Log.verbose(F("WIFI: Download file %s." CR), fname);
|
||||
#endif
|
||||
WiFiClient client;
|
||||
HTTPClient http;
|
||||
String serverPath = myConfig.getOtaURL();
|
||||
serverPath += fname;
|
||||
|
||||
// Your Domain name with URL path or IP address with path
|
||||
http.begin(client, serverPath);
|
||||
if (serverPath.startsWith("https://")) {
|
||||
myWifi.getWifiClientSecure().setInsecure();
|
||||
Log.notice(F("WIFI: OTA, SSL enabled without validation." CR));
|
||||
http.begin(myWifi.getWifiClientSecure(), serverPath);
|
||||
} else {
|
||||
http.begin(myWifi.getWifiClient(), serverPath);
|
||||
}
|
||||
|
||||
int httpResponseCode = http.GET();
|
||||
|
||||
if (httpResponseCode == 200) {
|
||||
@ -279,22 +292,28 @@ void WifiConnection::downloadFile(const char *fname) {
|
||||
httpResponseCode);
|
||||
}
|
||||
http.end();
|
||||
myWifi.closeWifiClient();
|
||||
}
|
||||
|
||||
//
|
||||
// Check what firmware version is available over OTA
|
||||
//
|
||||
bool WifiConnection::checkFirmwareVersion() {
|
||||
#if LOG_LEVEL == 6
|
||||
#if LOG_LEVEL == 6 && !defined(WIFI_DISABLE_LOGGING)
|
||||
Log.verbose(F("WIFI: Checking if new version exist." CR));
|
||||
#endif
|
||||
WiFiClient client;
|
||||
HTTPClient http;
|
||||
String serverPath = myConfig.getOtaURL();
|
||||
serverPath += "version.json";
|
||||
|
||||
// Your Domain name with URL path or IP address with path
|
||||
http.begin(client, serverPath);
|
||||
if (serverPath.startsWith("https://")) {
|
||||
myWifi.getWifiClientSecure().setInsecure();
|
||||
Log.notice(F("WIFI: OTA, SSL enabled without validation." CR));
|
||||
http.begin(myWifi.getWifiClientSecure(), serverPath);
|
||||
} else {
|
||||
http.begin(myWifi.getWifiClient(), serverPath);
|
||||
}
|
||||
|
||||
// Send HTTP GET request
|
||||
int httpResponseCode = http.GET();
|
||||
@ -303,7 +322,7 @@ bool WifiConnection::checkFirmwareVersion() {
|
||||
Log.notice(F("WIFI: Found version.json, response=%d" CR), httpResponseCode);
|
||||
|
||||
String payload = http.getString();
|
||||
#if LOG_LEVEL == 6
|
||||
#if LOG_LEVEL == 6 && !defined(WIFI_DISABLE_LOGGING)
|
||||
Log.verbose(F("WIFI: Payload %s." CR), payload.c_str());
|
||||
#endif
|
||||
DynamicJsonDocument ver(300);
|
||||
@ -311,7 +330,7 @@ bool WifiConnection::checkFirmwareVersion() {
|
||||
if (err) {
|
||||
Log.error(F("WIFI: Failed to parse version.json, %s" CR), err);
|
||||
} else {
|
||||
#if LOG_LEVEL == 6
|
||||
#if LOG_LEVEL == 6 && !defined(WIFI_DISABLE_LOGGING)
|
||||
Log.verbose(F("WIFI: Project %s version %s." CR),
|
||||
(const char *)ver["project"], (const char *)ver["version"]);
|
||||
#endif
|
||||
@ -320,7 +339,7 @@ bool WifiConnection::checkFirmwareVersion() {
|
||||
|
||||
if (parseFirmwareVersionString(newVer, (const char *)ver["version"])) {
|
||||
if (parseFirmwareVersionString(curVer, CFG_APPVER)) {
|
||||
#if LOG_LEVEL == 6
|
||||
#if LOG_LEVEL == 6 && !defined(WIFI_DISABLE_LOGGING)
|
||||
Log.verbose(F("WIFI: OTA checking new=%d.%d.%d cur=%d.%d.%d" CR),
|
||||
newVer[0], newVer[1], newVer[2], curVer[0], curVer[1],
|
||||
curVer[2]);
|
||||
@ -355,6 +374,7 @@ bool WifiConnection::checkFirmwareVersion() {
|
||||
httpResponseCode);
|
||||
}
|
||||
http.end();
|
||||
myWifi.closeWifiClient();
|
||||
#if LOG_LEVEL == 6
|
||||
Log.verbose(F("WIFI: OTA found new version %s." CR),
|
||||
newFirmware ? "true" : "false");
|
||||
@ -367,7 +387,7 @@ bool WifiConnection::checkFirmwareVersion() {
|
||||
//
|
||||
bool WifiConnection::parseFirmwareVersionString(int (&num)[3],
|
||||
const char *version) {
|
||||
#if LOG_LEVEL == 6
|
||||
#if LOG_LEVEL == 6 && !defined(WIFI_DISABLE_LOGGING)
|
||||
Log.verbose(F("WIFI: Parsing version number string %s." CR), version);
|
||||
#endif
|
||||
char temp[80];
|
||||
|
18
src/wifi.hpp
18
src/wifi.hpp
@ -26,11 +26,19 @@ SOFTWARE.
|
||||
|
||||
// Include
|
||||
#include <Arduino.h>
|
||||
#include <ESP8266WiFi.h>
|
||||
|
||||
// tcp cleanup, to avoid memory crash.
|
||||
struct tcp_pcb;
|
||||
extern struct tcp_pcb* tcp_tw_pcbs;
|
||||
extern "C" void tcp_abort(struct tcp_pcb* pcb);
|
||||
|
||||
// classes
|
||||
class WifiConnection {
|
||||
private:
|
||||
// WIFI
|
||||
WiFiClient _client;
|
||||
WiFiClientSecure _secureClient;
|
||||
|
||||
// OTA
|
||||
bool newFirmware = false;
|
||||
@ -53,6 +61,16 @@ class WifiConnection {
|
||||
void startPortal();
|
||||
void loop();
|
||||
|
||||
WiFiClient& getWifiClient() { return _client; }
|
||||
WiFiClientSecure& getWifiClientSecure() { return _secureClient; }
|
||||
void closeWifiClient() {
|
||||
_client.stopAll();
|
||||
_secureClient.stopAll();
|
||||
|
||||
// Cleanup memory allocated by open tcp connetions.
|
||||
while (tcp_tw_pcbs) tcp_abort(tcp_tw_pcbs);
|
||||
}
|
||||
|
||||
// OTA
|
||||
bool updateFirmware();
|
||||
bool checkFirmwareVersion();
|
||||
|
@ -83,19 +83,9 @@ This is a list of C++ defines that is used to enable/disable functions in the co
|
||||
* - ACTIVATE_OTA
|
||||
- Enables the OTA functionallity in the code
|
||||
* - SKIP_SLEEPMODE
|
||||
- THe device never goes into sleep mode, useful when developing.
|
||||
* - CFG_DISABLE_LOGGING
|
||||
- Done include verbose logging in Config class. Excessive logging may crash device.
|
||||
* - GYRO_DISABLE_LOGGING
|
||||
- Done include verbose logging in Gyro class. Excessive logging may crash device.
|
||||
* - PUSH_DISABLE_LOGGING
|
||||
- Done include verbose logging in PushTarget class. Excessive logging may crash device.
|
||||
* - TSEN_DISABLE_LOGGING
|
||||
- Done include verbose logging in TempSensor class. Excessive logging may crash device.
|
||||
* - WEB_DISABLE_LOGGING
|
||||
- Done include verbose logging in WebServer class. Excessive logging may crash device.
|
||||
* - MAIN_DISABLE_LOGGING
|
||||
- Done include verbose logging in Main class. Excessive logging may crash device.
|
||||
- The device never goes into sleep mode, useful when developing.
|
||||
* - xxx_DISABLE_LOGGING
|
||||
- Done include verbose logging in the corresponding class. Excessive logging may crash device.
|
||||
* - USE_LITTLEFS
|
||||
- Use the new filesystem in Ardurino
|
||||
* - EMBED_HTML
|
||||
|
@ -12,6 +12,7 @@ One of the following conditions will place the device in ``configuration mode``:
|
||||
- Placed in horizontal mode 85-90 degrees
|
||||
- Charger connected >4.15V
|
||||
|
||||
|
||||
Status
|
||||
======
|
||||
|
||||
@ -97,22 +98,36 @@ Push Settings
|
||||
:width: 800
|
||||
:alt: Push Settings
|
||||
|
||||
.. note::
|
||||
|
||||
When enabling SSL this will not validate the root CA of the remote service, this is a design decision based on two aspects. Enabling CA validation will take 3-4s extra on each connection which means way less
|
||||
battery life, so the decision is to prioritize battery life over security. The data transmitted is not really that sensitive anyway so I belive this is a good balance.
|
||||
|
||||
|
||||
* **HTTP URL 1:**
|
||||
|
||||
Endpoint to send data via http. Format used Format used :ref:`data-formats-ispindle`
|
||||
|
||||
If you add the prefix `https://` then the device will use SSL when sending data.
|
||||
|
||||
* **HTTP URL 2:**
|
||||
|
||||
Endpoint to send data via http. Format used :ref:`data-formats-ispindle`
|
||||
|
||||
If you add the prefix `https://` then the device will use SSL when sending data.
|
||||
|
||||
* **Brewfather URL:**
|
||||
|
||||
Endpoint to send data via http to brewfather. Format used :ref:`data-formats-brewfather`
|
||||
|
||||
SSL is not supported for this target.
|
||||
|
||||
* **Influx DB v2 URL:**
|
||||
|
||||
Endpoint to send data via http to InfluxDB. Format used :ref:`data-formats-influxdb2`
|
||||
|
||||
SSL is not supported for this target. Raise a issue on github if this is wanted.
|
||||
|
||||
* **Influx DB v2 Organisation:**
|
||||
|
||||
Name of organisation in Influx.
|
||||
@ -129,6 +144,8 @@ Push Settings
|
||||
|
||||
IP or name of server to send data to. Format used :ref:`data-formats-ispindle`
|
||||
|
||||
If you add the suffix `:8883` to the server name, then the device will use SSL when sending data.
|
||||
|
||||
* **MQTT Topic:**
|
||||
|
||||
Name of topic to publish sensor readings to, iSpindle format is used.
|
||||
@ -149,6 +166,10 @@ Gravity Settings
|
||||
:width: 800
|
||||
:alt: Gravity Settings
|
||||
|
||||
* **Gravity format:**
|
||||
|
||||
Gravity format can be eihter `SG` or `Plato`. The device will use SG Internally and convert to Plato when displaying data.
|
||||
|
||||
* **Gravity formula:**
|
||||
|
||||
Gravity formula is compatible with standard iSpindle formulas so any existing calculation option can be used. You can also use
|
||||
@ -159,9 +180,9 @@ Gravity Settings
|
||||
Will apply a temperature calibration formula to the gravity as a second step.
|
||||
|
||||
.. warning::
|
||||
This formula assumes that the calibration has been done at 20C.
|
||||
This formula assumes that the calibration has been done at 20°C / 68°F.
|
||||
|
||||
Formula used in temperature correction:
|
||||
Formula used in temperature correction.
|
||||
|
||||
::
|
||||
|
||||
@ -199,6 +220,8 @@ Hardware Settings
|
||||
For the OTA to work, place the following files (version.json + firmware.bin) at the location that you pointed out in OTA URL. If the version number in the json file is newer than in the
|
||||
code the update will be done during startup.
|
||||
|
||||
If you have the previx `https://` then the device will use secure transfer without CA validation.
|
||||
|
||||
Example; OTA URL (don't forget trailing dash), the name of the file should be firmware.bin
|
||||
|
||||
.. code-block::
|
||||
@ -325,7 +348,7 @@ GET: /api/config/formula
|
||||
Retrive the data used for formula calculation data via an HTTP GET command. Payload is in JSON format.
|
||||
|
||||
* ``a1``-``a4`` are the angles/tilt readings (up to 5 are currently supported)
|
||||
* ``g1``-``g4`` are the corresponding gravity reaadings (in SG)
|
||||
* ``g1``-``g4`` are the corresponding gravity reaadings in SG or Plato depending on the device-format.
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
@ -340,8 +363,9 @@ Retrive the data used for formula calculation data via an HTTP GET command. Payl
|
||||
"g2": 1.053,
|
||||
"g3": 1.062,
|
||||
"g4": 1,
|
||||
"g5": 1
|
||||
"gravity-formula": "0.0*tilt^3+0.0*tilt^2+0.0017978*tilt+0.9436",
|
||||
"g5": 1,
|
||||
"gravity-format": "G",
|
||||
"gravity-formula": "0.0*tilt^3+0.0*tilt^2+0.0017978*tilt+0.9436"
|
||||
}
|
||||
|
||||
|
||||
@ -350,7 +374,7 @@ POST: /api/config/device
|
||||
|
||||
Used to update device settings via an HTTP POST command. Payload is in JSON format.
|
||||
|
||||
* ``temp-format`` can be either ``C`` or ``F``
|
||||
* ``temp-format`` can be either ``C`` (Celcius) or ``F`` (Farenheight)
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
@ -391,6 +415,7 @@ POST: /api/config/gravity
|
||||
Used to update gravity settings via an HTTP POST command. Payload is in JSON format.
|
||||
|
||||
* ``gravity-formula`` keywords ``temp`` and ``tilt`` are supported.
|
||||
* ``gravity-format`` can be either ``G`` (SG) or ``P`` (PLATO)
|
||||
|
||||
.. note::
|
||||
``gravity-temp-adjustment`` is defined as "on" or "off" when posting since this is the output values
|
||||
@ -401,6 +426,7 @@ Used to update gravity settings via an HTTP POST command. Payload is in JSON for
|
||||
{
|
||||
"id": "ee1bfc",
|
||||
"gravity-formula": "0.0*tilt^3+0.0*tilt^2+0.0017978*tilt+0.9436",
|
||||
"gravity-format": "P",
|
||||
"gravity-temp-adjustment": "off"
|
||||
}
|
||||
|
||||
@ -500,6 +526,7 @@ present or the API call will fail.
|
||||
url = "http://" + host + "/api/config/gravity"
|
||||
json = { "id": id,
|
||||
"gravity-formula": "",
|
||||
"gravity-format": "P",
|
||||
"gravity-temp-adjustment": "off" # Adjust gravity (on/off)
|
||||
}
|
||||
set_config( url, json )
|
||||
@ -542,6 +569,7 @@ iSpindle format
|
||||
This is the format used for standard http posts.
|
||||
|
||||
* ``corr-gravity`` is an extended parameter containing a temperature corrected gravity reading.
|
||||
* ``gravity-format`` is an extended parameter containing the gravity format (G or P).
|
||||
* ``run-time`` is an extended parameter containing the number of seconds the execution took.
|
||||
|
||||
.. code-block:: json
|
||||
@ -554,10 +582,12 @@ This is the format used for standard http posts.
|
||||
"temperature": 20.5,
|
||||
"temp-units": "C",
|
||||
"gravity": 1.0050,
|
||||
"corr-gravity": 1.0050,
|
||||
"angle": 45.34,
|
||||
"battery": 3.67,
|
||||
"rssi": -12,
|
||||
|
||||
"corr-gravity": 1.0050,
|
||||
"gravity-unit": "G",
|
||||
"run-time": 6
|
||||
}
|
||||
|
||||
@ -567,14 +597,14 @@ This is the format used for standard http posts.
|
||||
Brewfather format
|
||||
=================
|
||||
|
||||
This is the format for Brewfather
|
||||
This is the format for Brewfather. See: `Brewfather API docs <https://docs.brewfather.app/integrations/custom-stream>`_
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"name" : "gravmon",
|
||||
"temp": 20.5,
|
||||
"temp-unit": "C",
|
||||
"temp_unit": "C",
|
||||
"battery": 3.67,
|
||||
"gravity": 1.0050,
|
||||
"gravity_unit": "G",
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 45 KiB |
@ -7,7 +7,7 @@ Welcome to GravityMon's documentation!
|
||||
######################################
|
||||
|
||||
.. note::
|
||||
This documentation reflects **v0.6**. Last updated 2022-01-15
|
||||
This documentation reflects **v0.7**. Last updated 2022-01-18
|
||||
|
||||
|
||||
GravityMon is a replacement firmare for the iSpindle firmware, it uses the same hardware configuration so
|
||||
@ -23,9 +23,6 @@ The hardware design comes from the fantastic iSpindle project so that is not cov
|
||||
My approach to this software is a little different from that the original ispindle firmware. The github repository can
|
||||
be found here; `GravityMon on Github <https://github.com/mp-se/gravitymon>`_
|
||||
|
||||
|
||||
|
||||
|
||||
.. note::
|
||||
This software is in the early stages even though its more than one year old so if you find issues, please
|
||||
open a ticket on github.
|
||||
@ -46,6 +43,7 @@ The main differences:
|
||||
* Visual graph showing how formula will be interpreted
|
||||
* Using the temperature sensor in gyro instead of DS18B20 (faster)
|
||||
* Built in performance measurements (used to optimise code)
|
||||
* SSL support in standard HTTP and MQTT connections.
|
||||
|
||||
For a complete breakdown see the :ref:`functionallity`
|
||||
|
||||
|
@ -3,6 +3,24 @@
|
||||
Releases
|
||||
########
|
||||
|
||||
v0.7.0
|
||||
------
|
||||
|
||||
Development version (dev branch)
|
||||
|
||||
* SSL support for HTTP targets (no validation of CA)
|
||||
* SSL support for MQTT targets (no validation of CA)
|
||||
* SSL support for OTA (no validation of CA)
|
||||
* Breaking change: To simplify the internal structure the
|
||||
temp sensor adjustment is now stored in C. So if you have
|
||||
enabled this function using F you will need to go into
|
||||
the configuration and update the factor again.
|
||||
* Added error handling for calibration page.
|
||||
|
||||
TODO:
|
||||
Update docs, MQTT ssl is enabled using :8883 at end, http targets enables using prefix https://
|
||||
Note! Brewfather don't support SSL.
|
||||
|
||||
v0.6.0
|
||||
------
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user