commit
a515a164fc
2
.github/workflows/pio-build.yaml
vendored
2
.github/workflows/pio-build.yaml
vendored
@ -36,7 +36,7 @@ jobs:
|
|||||||
git config --global advice.detachedHead false
|
git config --global advice.detachedHead false
|
||||||
|
|
||||||
- name: Run PlatformIO
|
- name: Run PlatformIO
|
||||||
run: pio run -e gravity-release -e gravity32-release -e gravity32c3-release -e gravity32s2-release
|
run: pio run -e gravity-release -e gravity32-release -e gravity32c3-release -e gravity32s2-release -e gravity32c3v1-release -e gravity32lite-release
|
||||||
|
|
||||||
- uses: EndBug/add-and-commit@v9 # You can change this to use a specific version. https://github.com/marketplace/actions/add-commit
|
- uses: EndBug/add-and-commit@v9 # You can change this to use a specific version. https://github.com/marketplace/actions/add-commit
|
||||||
with:
|
with:
|
||||||
|
2
.github/workflows/pre-commit.yaml
vendored
2
.github/workflows/pre-commit.yaml
vendored
@ -12,7 +12,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-python@v4
|
- uses: actions/setup-python@v3
|
||||||
- name: clang format support
|
- name: clang format support
|
||||||
run: |
|
run: |
|
||||||
sudo apt install clang-format cppcheck
|
sudo apt install clang-format cppcheck
|
||||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -2,3 +2,5 @@
|
|||||||
.vscode/*
|
.vscode/*
|
||||||
*.map
|
*.map
|
||||||
src_docs/_build/*
|
src_docs/_build/*
|
||||||
|
.env/*
|
||||||
|
*.pyc
|
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
GravityMon is a replacement firmware for the iSpindle firmware. It's 100% compatible with the iSpindle hardware design so it does not require any hardware changes.
|
GravityMon is a replacement firmware for the iSpindle firmware. It's 100% compatible with the iSpindle hardware design so it does not require any hardware changes. From v1.2 you can also use GravityMon for the DIY Floaty Hardware with ESP32 Lite.
|
||||||
|
|
||||||
Now also works with ESP32 d1 mini, ESP32 c3 mini, ESP32 S2 mini which both are pin compatible with ESP8266.
|
Now also works with ESP32 d1 mini, ESP32 c3 mini, ESP32 S2 mini which both are pin compatible with ESP8266.
|
||||||
|
|
||||||
@ -28,4 +28,4 @@ If you want to support my work you can do that through these options
|
|||||||
|
|
||||||
Thanks to the following persons for supporting me and this project:
|
Thanks to the following persons for supporting me and this project:
|
||||||
|
|
||||||
* David Conde
|
* David Conde, @davidconde
|
31
TEST.md
Normal file
31
TEST.md
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
# Unit testing - Python Script
|
||||||
|
|
||||||
|
I have moved my test scripts into this project now. They are mainly based on python scrips and validate the features from the API's.
|
||||||
|
|
||||||
|
Create a virtual environment and install the needed dependecies
|
||||||
|
```
|
||||||
|
python -m venv .env
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
Before you runt the script you need to update the IP adress to match the device that you have on your network.
|
||||||
|
|
||||||
|
Running the ALL tests
|
||||||
|
```
|
||||||
|
cd src/test
|
||||||
|
python3 -m unittest -v apitests.py -v
|
||||||
|
```
|
||||||
|
|
||||||
|
Running the ONE test
|
||||||
|
```
|
||||||
|
cd src/test
|
||||||
|
python3 -m unittest -v apitests.API.test_status -v
|
||||||
|
```
|
||||||
|
|
||||||
|
# Unit testing - Specific build
|
||||||
|
|
||||||
|
I've added a specific build that uses the AUnit (https://github.com/bxparks/AUnit) testing framework so that we can test functions or classes on the device itself. I hope this will simplify the release and testing cycle.
|
||||||
|
|
||||||
|
1. Select the build target (gravity-unit)
|
||||||
|
2. Build/upload the code to an iSpindle device.
|
||||||
|
3. Check the output from the serial console.
|
BIN
battery-test-1.2.xlsx
Normal file
BIN
battery-test-1.2.xlsx
Normal file
Binary file not shown.
BIN
bin/firmware.bin
BIN
bin/firmware.bin
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
bin/firmware32c3v1.bin
Normal file
BIN
bin/firmware32c3v1.bin
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -468,7 +468,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row mb-3">
|
<div class="row mb-3" id="ota-hide">
|
||||||
<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/">
|
||||||
@ -507,9 +507,9 @@
|
|||||||
|
|
||||||
if ( b ) {
|
if ( b ) {
|
||||||
$("#ota-url").val(gravitymonUrl);
|
$("#ota-url").val(gravitymonUrl);
|
||||||
$("#ota-url").prop("disabled", true);
|
$('#ota-hide').hide();
|
||||||
} else {
|
} else {
|
||||||
$("#ota-url").prop("disabled", false);
|
$('#ota-hide').show();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@ -966,7 +966,7 @@
|
|||||||
|
|
||||||
if( cfg["ota-url"] == gravitymonUrl) {
|
if( cfg["ota-url"] == gravitymonUrl) {
|
||||||
$("#gravitymon-com").prop( "checked", true );
|
$("#gravitymon-com").prop( "checked", true );
|
||||||
$("#ota-url").prop("disabled", true);
|
$("#ota-hide").hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
$("#token").val(cfg["token"]);
|
$("#token").val(cfg["token"]);
|
||||||
|
File diff suppressed because one or more lines are too long
@ -40,8 +40,8 @@ build_flags =
|
|||||||
-DUSER_SSID=\""\"" # =\""myssid\""
|
-DUSER_SSID=\""\"" # =\""myssid\""
|
||||||
-DUSER_SSID_PWD=\""\"" # =\""mypwd\""
|
-DUSER_SSID_PWD=\""\"" # =\""mypwd\""
|
||||||
-DCFG_APPVER="\"1.2.0\""
|
-DCFG_APPVER="\"1.2.0\""
|
||||||
-DCFG_GITREV=\""beta-2\""
|
#-DCFG_GITREV=\""beta-3\""
|
||||||
#!python script/git_rev.py
|
!python script/git_rev.py
|
||||||
lib_deps =
|
lib_deps =
|
||||||
# Using local copy of these libraries
|
# Using local copy of these libraries
|
||||||
# https://github.com/mp-se/i2cdevlib.git#<document>
|
# https://github.com/mp-se/i2cdevlib.git#<document>
|
||||||
@ -103,6 +103,26 @@ lib_deps =
|
|||||||
board = ${common_env_data.board}
|
board = ${common_env_data.board}
|
||||||
build_type = release
|
build_type = release
|
||||||
board_build.filesystem = littlefs
|
board_build.filesystem = littlefs
|
||||||
|
build_src_filter = +<*> -<../test/tests*.cpp>
|
||||||
|
|
||||||
|
[env:gravity-unit]
|
||||||
|
upload_speed = ${common_env_data.upload_speed}
|
||||||
|
monitor_speed = ${common_env_data.monitor_speed}
|
||||||
|
framework = ${common_env_data.framework}
|
||||||
|
platform = ${common_env_data.platform}
|
||||||
|
extra_scripts = ${common_env_data.extra_scripts}
|
||||||
|
build_unflags = ${common_env_data.build_unflags}
|
||||||
|
build_flags =
|
||||||
|
${common_env_data.build_flags}
|
||||||
|
-D LOG_LEVEL=4
|
||||||
|
lib_deps =
|
||||||
|
https://github.com/mp-se/incbin # https://github.com/graphitemaster/incbin
|
||||||
|
https://github.com/bxparks/AUnit#v1.6.1
|
||||||
|
${common_env_data.lib_deps}
|
||||||
|
board = ${common_env_data.board}
|
||||||
|
build_type = release
|
||||||
|
board_build.filesystem = littlefs
|
||||||
|
build_src_filter = +<*> -<main.cpp> +<../test/tests*.cpp>
|
||||||
|
|
||||||
[env:gravity32-release]
|
[env:gravity32-release]
|
||||||
framework = ${common_env_data.framework}
|
framework = ${common_env_data.framework}
|
||||||
@ -143,6 +163,39 @@ platform = ${common_env_data.platform32}
|
|||||||
upload_speed = ${common_env_data.upload_speed}
|
upload_speed = ${common_env_data.upload_speed}
|
||||||
monitor_speed = ${common_env_data.monitor_speed}
|
monitor_speed = ${common_env_data.monitor_speed}
|
||||||
extra_scripts = ${common_env_data.extra_scripts}
|
extra_scripts = ${common_env_data.extra_scripts}
|
||||||
|
build_unflags =
|
||||||
|
${common_env_data.build_unflags}
|
||||||
|
build_flags =
|
||||||
|
-Wl,-Map,output.map
|
||||||
|
${common_env_data.build_flags}
|
||||||
|
-DLOG_LEVEL=5
|
||||||
|
-DCORE_DEBUG_LEVEL=0
|
||||||
|
-DESP32C3
|
||||||
|
-DARDUINO_ESP32C3_DEV
|
||||||
|
#-DUSE_SERIAL_PINS # Use the TX/RX pins for the serial port
|
||||||
|
lib_deps =
|
||||||
|
${common_env_data.lib_deps}
|
||||||
|
${common_env_data.lib_deps32}
|
||||||
|
lib_ignore =
|
||||||
|
board = lolin_c3_mini
|
||||||
|
build_type = release
|
||||||
|
board_build.partitions = part32.csv
|
||||||
|
board_build.filesystem = littlefs
|
||||||
|
board_build.embed_txtfiles =
|
||||||
|
html/calibration.min.htm
|
||||||
|
html/config.min.htm
|
||||||
|
html/firmware.min.htm
|
||||||
|
html/format.min.htm
|
||||||
|
html/about.min.htm
|
||||||
|
html/index.min.htm
|
||||||
|
html/test.min.htm
|
||||||
|
|
||||||
|
[env:gravity32c3v1-release]
|
||||||
|
framework = ${common_env_data.framework}
|
||||||
|
platform = ${common_env_data.platform32}
|
||||||
|
upload_speed = ${common_env_data.upload_speed}
|
||||||
|
monitor_speed = ${common_env_data.monitor_speed}
|
||||||
|
extra_scripts = ${common_env_data.extra_scripts}
|
||||||
build_unflags =
|
build_unflags =
|
||||||
${common_env_data.build_unflags}
|
${common_env_data.build_unflags}
|
||||||
build_flags =
|
build_flags =
|
||||||
|
1
requirements.txt
Normal file
1
requirements.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
requests
|
@ -45,6 +45,12 @@ def after_build(source, target, env):
|
|||||||
print( "Copy file : " + source + " -> " + target )
|
print( "Copy file : " + source + " -> " + target )
|
||||||
shutil.copyfile( source, target )
|
shutil.copyfile( source, target )
|
||||||
|
|
||||||
|
if name == "gravity32c3v1-release" :
|
||||||
|
target = dir + "/bin/firmware32c3v1.bin"
|
||||||
|
source = dir + "/.pio/build/" + name + "/firmware.bin"
|
||||||
|
print( "Copy file : " + source + " -> " + target )
|
||||||
|
shutil.copyfile( source, target )
|
||||||
|
|
||||||
if name == "gravity32s2-release" :
|
if name == "gravity32s2-release" :
|
||||||
target = dir + "/bin/firmware32s2.bin"
|
target = dir + "/bin/firmware32s2.bin"
|
||||||
source = dir + "/.pio/build/" + name + "/firmware.bin"
|
source = dir + "/.pio/build/" + name + "/firmware.bin"
|
||||||
|
@ -27,9 +27,6 @@ SOFTWARE.
|
|||||||
#include <calc.hpp>
|
#include <calc.hpp>
|
||||||
#include <main.hpp>
|
#include <main.hpp>
|
||||||
|
|
||||||
//
|
|
||||||
// Use values to derive a formula
|
|
||||||
//
|
|
||||||
int createFormula(RawFormulaData &fd, char *formulaBuffer,
|
int createFormula(RawFormulaData &fd, char *formulaBuffer,
|
||||||
int formulaBufferSize, int order) {
|
int formulaBufferSize, int order) {
|
||||||
int noAngles = 0;
|
int noAngles = 0;
|
||||||
@ -118,10 +115,6 @@ int createFormula(RawFormulaData &fd, char *formulaBuffer,
|
|||||||
return ERR_FORMULA_INTERNAL;
|
return ERR_FORMULA_INTERNAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Calculates gravity according to supplied formula, compatible with
|
|
||||||
// iSpindle/Fermentrack formula
|
|
||||||
//
|
|
||||||
double calculateGravity(double angle, double temp, const char *tempFormula) {
|
double calculateGravity(double angle, double temp, const char *tempFormula) {
|
||||||
const char *formula = myConfig.getGravityFormula();
|
const char *formula = myConfig.getGravityFormula();
|
||||||
|
|
||||||
@ -163,12 +156,10 @@ double calculateGravity(double angle, double temp, const char *tempFormula) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Do a standard gravity temperature correction. This is a simple way to adjust
|
// Do a standard gravity temperature correction. This is a simple way to adjust
|
||||||
// for differnt worth temperatures. This function uses C as temperature.
|
// for differnt worth temperatures. This function uses C as temperature.
|
||||||
//
|
//
|
||||||
// Source: https://homebrewacademy.com/hydrometer-temperature-correction/
|
// Source: https://homebrewacademy.com/hydrometer-temperature-correction/
|
||||||
//
|
|
||||||
double gravityTemperatureCorrectionC(double gravitySG, double tempC,
|
double gravityTemperatureCorrectionC(double gravitySG, double tempC,
|
||||||
double calTempC) {
|
double calTempC) {
|
||||||
#if LOG_LEVEL == 6 && !defined(CALC_DISABLE_LOGGING)
|
#if LOG_LEVEL == 6 && !defined(CALC_DISABLE_LOGGING)
|
||||||
|
@ -133,12 +133,6 @@ void setup() {
|
|||||||
LOG_PERF_START("main-setup");
|
LOG_PERF_START("main-setup");
|
||||||
runtimeMillis = millis();
|
runtimeMillis = millis();
|
||||||
|
|
||||||
#if LOG_LEVEL == 6 && !defined(MAIN_DISABLE_LOGGING)
|
|
||||||
// Add a delay so that serial is started.
|
|
||||||
// delay(3000);
|
|
||||||
#endif
|
|
||||||
delay(2000);
|
|
||||||
|
|
||||||
// Main startup
|
// Main startup
|
||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
Log.notice(F("Main: Started setup for %s." CR),
|
Log.notice(F("Main: Started setup for %s." CR),
|
||||||
|
@ -80,9 +80,6 @@ const char mqttFormat[] PROGMEM =
|
|||||||
"ispindel/${mdns}/interval:${sleep-interval}|"
|
"ispindel/${mdns}/interval:${sleep-interval}|"
|
||||||
"ispindel/${mdns}/RSSI:${rssi}|";
|
"ispindel/${mdns}/RSSI:${rssi}|";
|
||||||
|
|
||||||
//
|
|
||||||
// Initialize the variables
|
|
||||||
//
|
|
||||||
void TemplatingEngine::initialize(float angle, float gravitySG,
|
void TemplatingEngine::initialize(float angle, float gravitySG,
|
||||||
float corrGravitySG, float tempC,
|
float corrGravitySG, float tempC,
|
||||||
float runTime) {
|
float runTime) {
|
||||||
@ -138,10 +135,9 @@ void TemplatingEngine::initialize(float angle, float gravitySG,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
// the useDefaultTemplate param is there to support unit tests.
|
||||||
// Create the data using defined template.
|
const char* TemplatingEngine::create(TemplatingEngine::Templates idx,
|
||||||
//
|
bool useDefaultTemplate) {
|
||||||
const char* TemplatingEngine::create(TemplatingEngine::Templates idx) {
|
|
||||||
String fname;
|
String fname;
|
||||||
_baseTemplate.reserve(600);
|
_baseTemplate.reserve(600);
|
||||||
|
|
||||||
@ -169,15 +165,16 @@ const char* TemplatingEngine::create(TemplatingEngine::Templates idx) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Add code to load templates from disk if they exist.
|
if (!useDefaultTemplate) {
|
||||||
File file = LittleFS.open(fname, "r");
|
File file = LittleFS.open(fname, "r");
|
||||||
if (file) {
|
if (file) {
|
||||||
char buf[file.size() + 1];
|
char buf[file.size() + 1];
|
||||||
memset(&buf[0], 0, file.size() + 1);
|
memset(&buf[0], 0, file.size() + 1);
|
||||||
file.readBytes(&buf[0], file.size());
|
file.readBytes(&buf[0], file.size());
|
||||||
_baseTemplate = String(&buf[0]);
|
_baseTemplate = String(&buf[0]);
|
||||||
file.close();
|
file.close();
|
||||||
Log.notice(F("TPL : Template loaded from disk %s." CR), fname.c_str());
|
Log.notice(F("TPL : Template loaded from disk %s." CR), fname.c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LOG_LEVEL == 6
|
#if LOG_LEVEL == 6
|
||||||
|
@ -200,7 +200,8 @@ class TemplatingEngine {
|
|||||||
}
|
}
|
||||||
void initialize(float angle, float gravitySG, float corrGravitySG,
|
void initialize(float angle, float gravitySG, float corrGravitySG,
|
||||||
float tempC, float runTime);
|
float tempC, float runTime);
|
||||||
const char *create(TemplatingEngine::Templates idx);
|
const char *create(TemplatingEngine::Templates idx,
|
||||||
|
bool useDefaultTemplate = false);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SRC_TEMPLATING_HPP_
|
#endif // SRC_TEMPLATING_HPP_
|
||||||
|
@ -58,9 +58,6 @@ void TempSensor::setup() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Retrieving value from sensor, value is in Celcius
|
|
||||||
//
|
|
||||||
float TempSensor::getValue(bool useGyro) {
|
float TempSensor::getValue(bool useGyro) {
|
||||||
if (useGyro) {
|
if (useGyro) {
|
||||||
// When using the gyro temperature only the first read value will be
|
// When using the gyro temperature only the first read value will be
|
||||||
|
@ -430,6 +430,8 @@ bool WifiConnection::checkFirmwareVersion() {
|
|||||||
}
|
}
|
||||||
http.end();
|
http.end();
|
||||||
|
|
||||||
|
if (_newFirmware) Log.notice(F("WIFI: Found new version." CR));
|
||||||
|
|
||||||
#if LOG_LEVEL == 6
|
#if LOG_LEVEL == 6
|
||||||
Log.verbose(F("WIFI: OTA found new version %s." CR),
|
Log.verbose(F("WIFI: OTA found new version %s." CR),
|
||||||
_newFirmware ? "true" : "false");
|
_newFirmware ? "true" : "false");
|
||||||
|
@ -30,9 +30,10 @@ 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
|
||||||
* gravity32-release: Version for ESP32 mini.
|
* gravity32-release: Version for ESP32 mini.
|
||||||
* gravity32-c3-release: Version for ESP32 C3 mini.
|
* gravity32c3-release: Version for ESP32 C3 mini v2.1+.
|
||||||
* gravity32-s2-release: Version for ESP32 S2 mini.
|
* gravity32c3v1-release: Version for ESP32 C3 mini v1.0.
|
||||||
* gravity32-lite-release: Version for ESP32 lite (Floaty hardware).
|
* gravity32s2-release: Version for ESP32 S2 mini.
|
||||||
|
* gravity32lite-release: Version for ESP32 lite (Floaty hardware).
|
||||||
|
|
||||||
.. warning::
|
.. warning::
|
||||||
The debug target can be unstable and crash the device under certain circumstanses. Excessive logging to the serial port can cause corruption and crashes.
|
The debug target can be unstable and crash the device under certain circumstanses. Excessive logging to the serial port can cause corruption and crashes.
|
||||||
|
@ -5,8 +5,8 @@ Hardware
|
|||||||
|
|
||||||
I'm not a hardware designer so I would recommend the following resources for more in depth information on this topic.
|
I'm not a hardware designer so I would recommend the following resources for more in depth information on this topic.
|
||||||
|
|
||||||
* `Cherry Philip Hardware design, <https://github.com/cherryphilip74/iSpindel-PCB>`_
|
* `Cherry Philip Hardware design <https://github.com/cherryphilip74/iSpindel-PCB>`_
|
||||||
* `OpenSource Distilling, <https://www.opensourcedistilling.com/ispindel>`_
|
* `OpenSource Distilling <https://www.opensourcedistilling.com/ispindel>`_
|
||||||
|
|
||||||
iSpindle based on esp8266
|
iSpindle based on esp8266
|
||||||
=========================
|
=========================
|
||||||
@ -25,24 +25,20 @@ Schema for esp8266 build
|
|||||||
:width: 700
|
:width: 700
|
||||||
:alt: Schema esp8266
|
:alt: Schema esp8266
|
||||||
|
|
||||||
|
|
||||||
iSpindle based on esp32
|
iSpindle based on esp32
|
||||||
=======================
|
=======================
|
||||||
|
|
||||||
I've experimented with porting my software version to esp32 and this is a selection of options i have been testing.
|
Gravitymon supports a number of ESP32 boards that offers bluetooth support.
|
||||||
|
|
||||||
.. warning::
|
|
||||||
Work to support esp32s2 is still ongoing, ESP32-mini and ESP32c3-mini is confirmed to be working. However I would recommend the C3 variant.
|
|
||||||
|
|
||||||
.. image:: images/esp32_hardware.jpg
|
.. image:: images/esp32_hardware.jpg
|
||||||
:width: 500
|
:width: 500
|
||||||
:alt: iSpindle esp32 hardware options
|
:alt: iSpindle esp32 hardware options
|
||||||
|
|
||||||
* esp32 mini, this was the first board i tried which is a smaller form factor of the first generetion esp32 with 2 cores. Slow on connecting to wifi is the main downside.
|
* esp32d1 mini, this was the first board i tried which is a smaller form factor of the first generetion esp32 with 2 cores. Slow on connecting to wifi is the main downside.
|
||||||
* esp32c3 mini, a newer version based on the latest risc v7 architecture, is seen as the replacement for the esp8266 with bluetooth support.
|
* esp32c3 mini, a newer version based on the latest risc v7 architecture, is seen as the replacement for the esp8266 with bluetooth support. Don't buy v1.0 since that has a faulty wifi antenna.
|
||||||
* esp32s2 mini, similar to the c3 board but without bluetooth support.
|
* esp32s2 mini, similar to the c3 board but without bluetooth support.
|
||||||
|
|
||||||
It's possible to use this PCB and mount an ESP32 mini on top of that (c3 and s2 are prefered). The esp32 mini is a larger formfactor and can be hard to fit into the tube.
|
It's possible to use this PCB and mount an ESP32 mini on top of that (c3 or s2 are prefered). The esp32 d1 mini is a larger formfactor and can be hard to fit into the tube.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
You need to add a resistor between A0 (Analog PIN) and ground of 470k. The reason is that the esp8266 has a build in resistor for a voltage divider
|
You need to add a resistor between A0 (Analog PIN) and ground of 470k. The reason is that the esp8266 has a build in resistor for a voltage divider
|
||||||
@ -52,7 +48,7 @@ It's possible to use this PCB and mount an ESP32 mini on top of that (c3 and s2
|
|||||||
ESP32c3 mini
|
ESP32c3 mini
|
||||||
++++++++++++
|
++++++++++++
|
||||||
|
|
||||||
This is model is now fully supported by gravitymon.
|
This is model is fully supported by gravitymon.
|
||||||
|
|
||||||
.. image:: images/ispindel_esp32c3.jpg
|
.. image:: images/ispindel_esp32c3.jpg
|
||||||
:width: 500
|
:width: 500
|
||||||
@ -67,7 +63,7 @@ Here is an image of where I added the resistor for the voltage divider.
|
|||||||
ESP32s2 mini
|
ESP32s2 mini
|
||||||
++++++++++++
|
++++++++++++
|
||||||
|
|
||||||
This is model is now fully supported by gravitymon. Same setup as for ESP32C3 mini.
|
This is model is fully supported by gravitymon. Same setup as for ESP32C3 mini.
|
||||||
|
|
||||||
ESP32 d1 mini
|
ESP32 d1 mini
|
||||||
+++++++++++++
|
+++++++++++++
|
||||||
@ -82,7 +78,7 @@ Schema for esp32 build
|
|||||||
++++++++++++++++++++++
|
++++++++++++++++++++++
|
||||||
|
|
||||||
.. note::
|
.. 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
|
This schema assumes that an ESP32 d1 mini (pin compatible with ESP8266). 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.
|
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 and this acts as a voltage divider.
|
The ESP8266 has a built in resistor thats not visible on the schema and this acts as a voltage divider.
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ Welcome to GravityMon
|
|||||||
#####################
|
#####################
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
This documentation reflects **v1.2 - beta 2**. Last updated 2022-11-19
|
This documentation reflects **v1.2.0**. Last updated 2022-12-06
|
||||||
|
|
||||||
What is GravityMon?
|
What is GravityMon?
|
||||||
--------------------
|
--------------------
|
||||||
@ -39,8 +39,8 @@ My approach to this software is a little different from that the original iSpind
|
|||||||
The github repository can be found here; `GravityMon on Github <https://github.com/mp-se/gravitymon>`_
|
The github repository can be found here; `GravityMon on Github <https://github.com/mp-se/gravitymon>`_
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
I don't take responsibility for any errors or issues caused by the software. The software is provided as-is. I will however
|
I don't take responsibility for any errors or issues caused by the software or hardware.
|
||||||
try my best to fix issues that might occur.
|
The software is provided as-is. I will however try my best to fix issues that might occur.
|
||||||
|
|
||||||
I have tested this software on 40+ brews with good results.
|
I have tested this software on 40+ brews with good results.
|
||||||
|
|
||||||
|
@ -45,8 +45,8 @@ In the /bin directory you will find 4 different firmware builds;
|
|||||||
|
|
||||||
* **firmware32c3.bin**
|
* **firmware32c3.bin**
|
||||||
|
|
||||||
This is the release build for an ESP32c3-mini variant. When flashing an ESP32 you also need the *partition32c3.bin* file that outlines the flash memory structure. Due to
|
This is the release build for an ESP32c3-mini variant v2.1 or newer. When flashing an ESP32 you also need the *partition32c3.bin* file that outlines the flash memory structure. Due to
|
||||||
the size of the firmware we are using a custom partition setup.
|
the size of the firmware we are using a custom partition setup. If you have a v1.0 board use the firmware32c3v1.bin instead.
|
||||||
|
|
||||||
* **firmware32s2.bin**
|
* **firmware32s2.bin**
|
||||||
|
|
||||||
|
@ -3,40 +3,31 @@
|
|||||||
Releases
|
Releases
|
||||||
########
|
########
|
||||||
|
|
||||||
v1.2.0 - beta2
|
v1.2.0
|
||||||
==============
|
======
|
||||||
|
|
||||||
Features
|
Features
|
||||||
++++++++
|
++++++++
|
||||||
* Added function to calcualate voltage factor based on measured value.
|
* Added function to calcualate voltage factor based on measured value.
|
||||||
* Updated battery estimation for the various esp32 boards.
|
* Updated battery estimation for the various esp32 boards.
|
||||||
* Added support for the ESP32 lite board which is used in the Floaty Hydrometer variant.
|
* Added support for the ESP32 lite board which is used in the Floaty Hydrometer variant.
|
||||||
|
|
||||||
Documentation
|
|
||||||
+++++++++++++
|
|
||||||
* Added section about the Floaty hardware.
|
|
||||||
|
|
||||||
|
|
||||||
v1.2.0 - beta1
|
|
||||||
==============
|
|
||||||
|
|
||||||
* Changes to 1.2.0 only affect the ESP32 hardware, the ESP8266 is the same as for v1.1.1
|
|
||||||
|
|
||||||
Features
|
|
||||||
++++++++
|
|
||||||
* Added support for the ESP32 C3 mini board
|
* Added support for the ESP32 C3 mini board
|
||||||
* Added support for the ESP32 S2 mini board
|
* Added support for the ESP32 S2 mini board
|
||||||
* Serial output is written to TX/RX pins instead of the USB connection for the ESP32c3. This way the serial console can be viewed when running on battery power.
|
* Serial output is written to TX/RX pins instead of the USB connection for the ESP32c3. This way the serial console can be viewed when running on battery power.
|
||||||
|
* Merged in unit tests and api tests into this project
|
||||||
|
* Added option to download firmware updates from https://www.gravitymon.com
|
||||||
|
|
||||||
|
Documentation
|
||||||
|
+++++++++++++
|
||||||
|
* Added section about the Floaty hardware
|
||||||
|
* Fixed schema errors in hardware section and linked PCB options
|
||||||
|
* Updated hardware section with options for ESP32 boards
|
||||||
|
* Updated installation instructions.
|
||||||
|
|
||||||
Issues adressed
|
Issues adressed
|
||||||
++++++++++++++++
|
++++++++++++++++
|
||||||
* BUG: The first portion of a format template was lost when doing conversion.
|
* BUG: The first portion of a format template was lost when doing conversion.
|
||||||
|
|
||||||
Documentation
|
|
||||||
+++++++++++++
|
|
||||||
* Updated hardware section with options for ESP32 boards
|
|
||||||
* Updated installation instructions.
|
|
||||||
|
|
||||||
v1.1.1
|
v1.1.1
|
||||||
======
|
======
|
||||||
* BUG: The text before the first variable was missed in the conversion of a format template.
|
* BUG: The text before the first variable was missed in the conversion of a format template.
|
||||||
|
643
test/apitests.py
Normal file
643
test/apitests.py
Normal file
@ -0,0 +1,643 @@
|
|||||||
|
import unittest, requests, json, time
|
||||||
|
|
||||||
|
ver = "1.2.0"
|
||||||
|
|
||||||
|
#host = "192.168.1.195"
|
||||||
|
#id = "6ac6f6"
|
||||||
|
|
||||||
|
host = "192.168.1.106"
|
||||||
|
id = "3045f4"
|
||||||
|
|
||||||
|
# python3 -m unittest -v apitests.API.test_bug_79
|
||||||
|
# python3 -m unittest -v apitests
|
||||||
|
|
||||||
|
def call_api_post( path, json ):
|
||||||
|
url = "http://" + host + path
|
||||||
|
return requests.post( url, data=json )
|
||||||
|
|
||||||
|
def call_api_get( path ):
|
||||||
|
url = "http://" + host + path
|
||||||
|
return requests.get( url )
|
||||||
|
|
||||||
|
class API(unittest.TestCase):
|
||||||
|
|
||||||
|
# Do factory reset for testing
|
||||||
|
def test_factory(self):
|
||||||
|
r = call_api_get( "/api/status" )
|
||||||
|
j = json.loads(r.text)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertEqual(j["id"], id)
|
||||||
|
r = call_api_get( "/api/factory?id=" + j["id"])
|
||||||
|
time.sleep(4)
|
||||||
|
|
||||||
|
# Check that all parameters exist
|
||||||
|
def test_status(self):
|
||||||
|
r = call_api_get( "/api/status" )
|
||||||
|
j = json.loads(r.text)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertEqual(j["id"], id)
|
||||||
|
self.assertEqual(j["wifi-ssid"], "@home")
|
||||||
|
self.assertNotEqual(j["angle"], 0)
|
||||||
|
self.assertNotEqual(j["gravity"], 2)
|
||||||
|
self.assertNotEqual(j["temp-c"], 0)
|
||||||
|
self.assertNotEqual(j["temp-f"], 0)
|
||||||
|
self.assertNotEqual(j["battery"], 0)
|
||||||
|
self.assertNotEqual(j["temp-format"], "")
|
||||||
|
self.assertNotEqual(j["gravity-format"], "")
|
||||||
|
self.assertNotEqual(j["sleep-mode"], True)
|
||||||
|
self.assertNotEqual(j["rssi"], 0)
|
||||||
|
self.assertNotEqual(j["app-ver"], "0.0.0")
|
||||||
|
self.assertNotEqual(j["app-build"], "test")
|
||||||
|
self.assertNotEqual(j["mdns"], "")
|
||||||
|
self.assertNotEqual(j["platform"], "")
|
||||||
|
self.assertNotEqual(j["runtime-average"], -1)
|
||||||
|
|
||||||
|
# Check that all parameters exist
|
||||||
|
def test_config_1(self):
|
||||||
|
j = { "id": id, "http-push": "https://push.me", "token": "mytoken", "token2": "mytoken2", "http-push2": "http://push.me", "http-push3": "http://push.me", "influxdb2-push": "http://influx.db", "influxdb2-org": "my-org",
|
||||||
|
"influxdb2-bucket": "my-bucket", "influxdb2-auth": "my-secret", "mqtt-push": "mqtt.com", "mqtt-port": 1883, "mqtt-user": "my-user",
|
||||||
|
"mqtt-pass": "my-pass", "http-push-h1": "header1", "http-push-h2": "header2", "http-push2-h1": "header1(2)", "http-push2-h2": "header2(2)" }
|
||||||
|
r = call_api_post( "/api/config/push", j )
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
r = call_api_get( "/api/config" )
|
||||||
|
j = json.loads(r.text)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertEqual(j["http-push-h1"], "header1")
|
||||||
|
self.assertEqual(j["http-push-h2"], "header2")
|
||||||
|
self.assertEqual(j["http-push2-h1"], "header1(2)")
|
||||||
|
self.assertEqual(j["http-push2-h2"], "header2(2)")
|
||||||
|
|
||||||
|
# Check that all parameters exist
|
||||||
|
def test_config_2(self):
|
||||||
|
j = { "id": id, "mdns": "gravmon", "temp-format": "C", "sleep-interval": 300 }
|
||||||
|
r = call_api_post( "/api/config/device", j )
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
def test_config_3(self):
|
||||||
|
j = { "id": id, "http-push": "https://push.me", "token": "mytoken", "token2": "mytoken2", "http-push2": "http://push.me", "http-push3": "http://push.me", "influxdb2-push": "http://influx.db", "influxdb2-org": "my-org",
|
||||||
|
"influxdb2-bucket": "my-bucket", "influxdb2-auth": "my-secret", "mqtt-push": "mqtt.com", "mqtt-port": 1883, "mqtt-user": "my-user",
|
||||||
|
"mqtt-pass": "my-pass" }
|
||||||
|
r = call_api_post( "/api/config/push", j )
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
def test_config_4(self):
|
||||||
|
j = { "id": id, "ota-url": "http://ota.url/path", "voltage-factor": 1.55, "temp-adjustment-value": -2, "gyro-temp": "on", "ble": "color" }
|
||||||
|
r = call_api_post( "/api/config/hardware", j )
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
r = call_api_get( "/api/config" )
|
||||||
|
j = json.loads(r.text)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertEqual(j["id"], id)
|
||||||
|
self.assertEqual(j["ble"], "color")
|
||||||
|
self.assertEqual(j["ota-url"], "http://ota.url/path")
|
||||||
|
self.assertEqual(j["voltage-factor"], 1.55)
|
||||||
|
self.assertEqual(j["temp-adjustment-value"], -2)
|
||||||
|
self.assertEqual(j["gyro-temp"], True)
|
||||||
|
# These are read only here, just checking them.
|
||||||
|
self.assertNotEqual(j["gyro-calibration-data"]["ax"], 0.0001)
|
||||||
|
self.assertNotEqual(j["gyro-calibration-data"]["ay"], 0.0001)
|
||||||
|
self.assertNotEqual(j["gyro-calibration-data"]["az"], 0.0001)
|
||||||
|
self.assertNotEqual(j["gyro-calibration-data"]["gx"], 0.0001)
|
||||||
|
self.assertNotEqual(j["gyro-calibration-data"]["gy"], 0.0001)
|
||||||
|
self.assertNotEqual(j["gyro-calibration-data"]["gz"], 0.0001)
|
||||||
|
self.assertNotEqual(j["formula-calculation-data"]["a1"], 0.0001)
|
||||||
|
self.assertNotEqual(j["formula-calculation-data"]["a2"], 0.0001)
|
||||||
|
self.assertNotEqual(j["formula-calculation-data"]["a3"], 0.0001)
|
||||||
|
self.assertNotEqual(j["formula-calculation-data"]["a4"], 0.0001)
|
||||||
|
self.assertNotEqual(j["formula-calculation-data"]["a5"], 0.0001)
|
||||||
|
self.assertNotEqual(j["formula-calculation-data"]["a6"], 0.0001)
|
||||||
|
self.assertNotEqual(j["formula-calculation-data"]["a7"], 0.0001)
|
||||||
|
self.assertNotEqual(j["formula-calculation-data"]["a8"], 0.0001)
|
||||||
|
self.assertNotEqual(j["formula-calculation-data"]["a9"], 0.0001)
|
||||||
|
self.assertNotEqual(j["formula-calculation-data"]["a10"], 0.0001)
|
||||||
|
self.assertNotEqual(j["formula-calculation-data"]["g1"], 0.0001)
|
||||||
|
self.assertNotEqual(j["formula-calculation-data"]["g2"], 0.0001)
|
||||||
|
self.assertNotEqual(j["formula-calculation-data"]["g3"], 0.0001)
|
||||||
|
self.assertNotEqual(j["formula-calculation-data"]["g4"], 0.0001)
|
||||||
|
self.assertNotEqual(j["formula-calculation-data"]["g5"], 0.0001)
|
||||||
|
self.assertNotEqual(j["formula-calculation-data"]["g6"], 0.0001)
|
||||||
|
self.assertNotEqual(j["formula-calculation-data"]["g7"], 0.0001)
|
||||||
|
self.assertNotEqual(j["formula-calculation-data"]["g8"], 0.0001)
|
||||||
|
self.assertNotEqual(j["formula-calculation-data"]["g9"], 0.0001)
|
||||||
|
self.assertNotEqual(j["formula-calculation-data"]["g10"], 0.0001)
|
||||||
|
self.assertNotEqual(j["angle"], 0)
|
||||||
|
self.assertNotEqual(j["gravity"], -10)
|
||||||
|
self.assertNotEqual(j["battery"], 0)
|
||||||
|
|
||||||
|
def test_config_5(self):
|
||||||
|
j = { "id": id, "gravity-formula": "my-formula", "gravity-temp-adjustment": "on", "gravity-format": "G" }
|
||||||
|
r = call_api_post( "/api/config/gravity", j )
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
r = call_api_get( "/api/config" )
|
||||||
|
j = json.loads(r.text)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertEqual(j["id"], id)
|
||||||
|
self.assertEqual(j["gravity-format"], "G")
|
||||||
|
self.assertEqual(j["gravity-formula"], "my-formula")
|
||||||
|
self.assertEqual(j["gravity-temp-adjustment"], True)
|
||||||
|
|
||||||
|
def test_config_6(self):
|
||||||
|
j = { "id": id, "mdns": "gravmon", "temp-format": "F", "sleep-interval": 300 }
|
||||||
|
r = call_api_post( "/api/config/device", j )
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
r = call_api_get( "/api/config" )
|
||||||
|
j = json.loads(r.text)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertEqual(j["id"], id)
|
||||||
|
self.assertEqual(j["mdns"], "gravmon")
|
||||||
|
self.assertEqual(j["wifi-ssid"], "@home")
|
||||||
|
self.assertEqual(j["wifi-pass"], "") # Should not be displayed in API
|
||||||
|
self.assertEqual(j["temp-format"], "F")
|
||||||
|
self.assertEqual(j["sleep-interval"], 300)
|
||||||
|
|
||||||
|
def test_config_7(self):
|
||||||
|
j = { "id": id, "ota-url": "", "voltage-factor": 1.55, "temp-adjustment-value": -2, "gyro-temp": "off", "ble": "blue" }
|
||||||
|
r = call_api_post( "/api/config/hardware", j )
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
r = call_api_get( "/api/config" )
|
||||||
|
j = json.loads(r.text)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertEqual(j["id"], id)
|
||||||
|
self.assertEqual(j["ble"], "blue")
|
||||||
|
self.assertEqual(j["ota-url"], "")
|
||||||
|
self.assertEqual(j["voltage-factor"], 1.55)
|
||||||
|
self.assertEqual(j["temp-adjustment-value"], -2)
|
||||||
|
self.assertEqual(j["gyro-temp"], False)
|
||||||
|
|
||||||
|
def test_config_8(self):
|
||||||
|
j = { "id": id, "gravity-formula": "", "gravity-temp-adjustment": "off", "gravity-format": "P" }
|
||||||
|
r = call_api_post( "/api/config/gravity", j )
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
r = call_api_get( "/api/config" )
|
||||||
|
j = json.loads(r.text)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertEqual(j["gravity-format"], "P")
|
||||||
|
self.assertEqual(j["gravity-temp-adjustment"], False)
|
||||||
|
self.assertEqual(j["gravity-formula"], "")
|
||||||
|
|
||||||
|
def test_config_9(self):
|
||||||
|
j = { "id": id, "gravity-temp-adjustment": "on" }
|
||||||
|
r = call_api_post( "/api/config/gravity", j )
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
r = call_api_get( "/api/config" )
|
||||||
|
j = json.loads(r.text)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertEqual(j["gravity-temp-adjustment"], True)
|
||||||
|
|
||||||
|
j = { "id": id } # No checkbox tag should set it to false.
|
||||||
|
r = call_api_post( "/api/config/gravity", j )
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
r = call_api_get( "/api/config" )
|
||||||
|
j = json.loads(r.text)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertEqual(j["gravity-temp-adjustment"], False)
|
||||||
|
|
||||||
|
def test_config_A(self):
|
||||||
|
j = { "id": id, "gyro-temp": "on" }
|
||||||
|
r = call_api_post( "/api/config/hardware", j )
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
r = call_api_get( "/api/config" )
|
||||||
|
j = json.loads(r.text)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertEqual(j["gyro-temp"], True)
|
||||||
|
|
||||||
|
j = { "id": id } # No checkbox tag should set it to false.
|
||||||
|
r = call_api_post( "/api/config/hardware", j )
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
r = call_api_get( "/api/config" )
|
||||||
|
j = json.loads(r.text)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertEqual(j["gyro-temp"], False)
|
||||||
|
|
||||||
|
# Check formula api (sg mode)
|
||||||
|
def test_formula_sg_1(self):
|
||||||
|
# Ensure we have SG defined as gravity
|
||||||
|
j = { "id": id, "gravity-formula": "", "gravity-temp-adjustment": "off", "gravity-format": "G" }
|
||||||
|
r = call_api_post("/api/config/gravity", j)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
def test_formula_sg_2(self):
|
||||||
|
# Fails due to wrong id
|
||||||
|
j = { "id": "wrong", "g1": 0, "g2": 1, "g3": 1.02, "g4": 1.0333, "g5": 1.00011, "g6": 1, "g7": 1, "g8": 1, "g9": 1, "g10": 1, "a1": 0, "a2": 25, "a3": 25.5, "a4": 25.55, "a5": 25.555, "a6": 0, "a7": 0, "a8": 0, "a9": 0, "a10": 0, "gravity-formula": "ThisShouldChange" }
|
||||||
|
r = call_api_post("/api/formula", j)
|
||||||
|
self.assertNotEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
# Fails due to to few values
|
||||||
|
j = { "id": id, "g1": 0, "g2": 1, "g3": 1.02, "g4": 1.0333, "g5": 1.00011, "g6": 1, "g7": 1, "g8": 1, "g9": 1, "g10": 1, "a1": 0, "a2": 25, "a3": 0, "a4": 0, "a5": 0, "a6": 0, "a7": 0, "a8": 0, "a9": 0, "a10": 0, "gravity-formula": "ThisShouldChange" }
|
||||||
|
r = call_api_post("/api/formula", j)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
# Checks that values from last call was stored
|
||||||
|
r = call_api_get( "/api/formula" )
|
||||||
|
j = json.loads(r.text)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertEqual(j["gravity-formula"], "")
|
||||||
|
self.assertEqual(j["error"], "Not enough values to create formula, need at least 3 angles.")
|
||||||
|
|
||||||
|
def test_formula_sg_3(self):
|
||||||
|
# Check a simple formula
|
||||||
|
j = { "id": id, "g1": 1.0, "g2": 1.01, "g3": 1.02, "g4": 1.03, "g5": 1.04, "g6": 1.05, "g7": 1.06, "g8": 1.07, "g9": 1.08, "g10": 1.1, "a1": 25, "a2": 30, "a3": 35, "a4": 40, "a5": 45, "a6": 50, "a7": 55, "a8": 60, "a9": 65, "a10": 70, "gravity-formula": "ThisShouldChange" }
|
||||||
|
r = call_api_post("/api/formula", j)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
r = call_api_get( "/api/formula" )
|
||||||
|
j = json.loads(r.text)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertEqual(j["gravity-formula"], "0.00000909*tilt^2+0.00124545*tilt+0.96445455")
|
||||||
|
|
||||||
|
# Check formula api (plato mode)
|
||||||
|
def test_formula_plato_1(self):
|
||||||
|
# Ensure we have Plato defined as gravity
|
||||||
|
j = { "id": id, "gravity-formula": "", "gravity-temp-adjustment": "off", "gravity-format": "P" }
|
||||||
|
r = call_api_post("/api/config/gravity", j)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
def test_formula_plato_2(self):
|
||||||
|
# Fails due to to few values
|
||||||
|
j = { "id": id, "g1": 0, "g2": 3, "g3": 5.3, "g4": 7.44, "g5": 8.555, "g6": 9, "g7": 9.1, "g8": 9.2, "g9": 9.3, "g10": 9.4, "a1": 0, "a2": 25, "a3": 25.5, "a4": 25.55, "a5": 25.555, "a6": 35, "a7": 36, "a8": 37, "a9": 38, "a10": 39, "gravity-formula": "ThisShouldChange" }
|
||||||
|
r = call_api_post("/api/formula", j)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
# Checks that values from last call was stored
|
||||||
|
r = call_api_get( "/api/formula" )
|
||||||
|
j = json.loads(r.text)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertEqual(j["id"], id)
|
||||||
|
self.assertEqual(j["g1"], 0)
|
||||||
|
self.assertEqual(j["g2"], 3)
|
||||||
|
self.assertEqual(j["g3"], 5.3)
|
||||||
|
self.assertEqual(j["g4"], 7.4)
|
||||||
|
self.assertEqual(j["g5"], 8.6)
|
||||||
|
self.assertEqual(j["g6"], 9)
|
||||||
|
self.assertEqual(j["g7"], 9.1)
|
||||||
|
self.assertEqual(j["g8"], 9.2)
|
||||||
|
self.assertEqual(j["g9"], 9.3)
|
||||||
|
self.assertEqual(j["g10"], 9.4)
|
||||||
|
self.assertEqual(j["a1"], 0)
|
||||||
|
self.assertEqual(j["a2"], 25)
|
||||||
|
self.assertEqual(j["a3"], 25.5)
|
||||||
|
self.assertEqual(j["a4"], 25.55)
|
||||||
|
self.assertEqual(j["a5"], 25.56)
|
||||||
|
self.assertEqual(j["a6"], 35)
|
||||||
|
self.assertEqual(j["a7"], 36)
|
||||||
|
self.assertEqual(j["a8"], 37)
|
||||||
|
self.assertEqual(j["a9"], 38)
|
||||||
|
self.assertEqual(j["a10"], 39)
|
||||||
|
self.assertEqual(j["gravity-format"], "P")
|
||||||
|
self.assertEqual(j["gravity-formula"], "-0.00012155*tilt^2+0.00874785*tilt+0.88003318")
|
||||||
|
self.assertEqual(j["error"], "")
|
||||||
|
|
||||||
|
def test_formula_plato_3(self):
|
||||||
|
j = { "id": id, "g1": 0, "g2": 3, "g3": 0, "g4": 0, "g5": 0, "g6": 0, "g7": 0, "g8": 0, "g9": 0, "g10": 0, "a1": 0, "a2": 25, "a3": 0, "a4": 0, "a5": 0, "a6": 0, "a7": 0, "a8": 0, "a9": 0, "a10": 0, "gravity-formula": "ThisShouldChange" }
|
||||||
|
r = call_api_post("/api/formula", j)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
# Checks that values from last call was stored
|
||||||
|
r = call_api_get( "/api/formula" )
|
||||||
|
j = json.loads(r.text)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertEqual(j["error"], "Not enough values to create formula, need at least 3 angles.")
|
||||||
|
|
||||||
|
def test_formula_plato_4(self):
|
||||||
|
# Ensure we have Plato defined as gravity
|
||||||
|
j = { "id": id, "gravity-formula": "", "gravity-temp-adjustment": "off", "gravity-format": "P" }
|
||||||
|
r = call_api_post("/api/config/gravity", j)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
# Check a simple formula
|
||||||
|
j = { "id": id, "g1": 1.0, "g2": 1.1, "g3": 1.2, "g4": 1.3, "g5": 1.4, "g6": 1.5, "g7": 1.6, "g8": 1.7, "g9": 1.8, "g10": 1.9, "a1": 25, "a2": 30, "a3": 35, "a4": 40, "a5": 45, "a6": 50, "a7": 55, "a8": 60, "a9": 65, "a10": 70, "gravity-formula": "ThisShouldChange" }
|
||||||
|
r = call_api_post("/api/formula", j)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
r = call_api_get( "/api/formula" )
|
||||||
|
j = json.loads(r.text)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
#self.assertEqual(j["gravity-formula"], "0.00000001*tilt^2+0.00007752*tilt+1.00193428") # 1.6 max deviation
|
||||||
|
self.assertEqual(j["gravity-formula"], "-0.00000352*tilt^2+0.00045454*tilt+0.99231483") # 3.0 max deviation
|
||||||
|
|
||||||
|
# Check format api
|
||||||
|
def test_pushtest_1(self):
|
||||||
|
j = { "id": id, "http-push": "http://push.me", "token": "mytoken", "token2": "mytoken2", "http-push2": "http://push.me", "http-push3": "http://push.me", "brewfather-push": "http://push.me", "influxdb2-push": "http://influx.db", "influxdb2-org": "my-org",
|
||||||
|
"influxdb2-bucket": "my-bucket", "influxdb2-auth": "my-secret", "mqtt-push": "mqtt.com", "mqtt-port": 1883, "mqtt-user": "my-user",
|
||||||
|
"mqtt-pass": "my-pass", "http-push-h1": "header1", "http-push-h2": "header2", "http-push2-h1": "header1(2)", "http-push2-h2": "header2(2)" }
|
||||||
|
r = call_api_post( "/api/config/push", j )
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
def test_pushtest_2(self):
|
||||||
|
r = call_api_get( "/api/test/push?id=" + id + "&format=http-1" )
|
||||||
|
j = json.loads(r.text)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertEqual(j["success"], False)
|
||||||
|
self.assertEqual(j["enabled"], True)
|
||||||
|
self.assertEqual(j["code"], -1)
|
||||||
|
|
||||||
|
def test_pushtest_3(self):
|
||||||
|
r = call_api_get( "/api/test/push?id=" + id + "&format=http-2" )
|
||||||
|
j = json.loads(r.text)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertEqual(j["success"], False)
|
||||||
|
self.assertEqual(j["enabled"], True)
|
||||||
|
self.assertEqual(j["code"], -1)
|
||||||
|
|
||||||
|
def test_pushtest_4(self):
|
||||||
|
r = call_api_get( "/api/test/push?id=" + id + "&format=http-3" )
|
||||||
|
j = json.loads(r.text)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertEqual(j["success"], False)
|
||||||
|
self.assertEqual(j["enabled"], True)
|
||||||
|
self.assertEqual(j["code"], -1)
|
||||||
|
|
||||||
|
def test_pushtest_5(self):
|
||||||
|
r = call_api_get( "/api/test/push?id=" + id + "&format=influxdb" )
|
||||||
|
j = json.loads(r.text)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertEqual(j["success"], False)
|
||||||
|
self.assertEqual(j["enabled"], True)
|
||||||
|
self.assertEqual(j["code"], -1)
|
||||||
|
|
||||||
|
def test_pushtest_6(self):
|
||||||
|
r = call_api_get( "/api/test/push?id=" + id + "&format=mqtt" )
|
||||||
|
j = json.loads(r.text)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertEqual(j["success"], False)
|
||||||
|
self.assertEqual(j["enabled"], True)
|
||||||
|
self.assertEqual(j["code"], -3)
|
||||||
|
|
||||||
|
# Check format api
|
||||||
|
def test_push_1(self):
|
||||||
|
r = call_api_get( "/api/factory?id=" + id)
|
||||||
|
time.sleep(4)
|
||||||
|
|
||||||
|
# Note: The endpoint test.php does not validate the payload, it only accepts the request and return 200.
|
||||||
|
j = { "id": id, "http-push": "http://www.allerum.net/test.php", "http-push2": "http://www.allerum.net/test.php", "http-push3": "http://www.allerum.net/test.php", "mqtt-push": "192.168.1.16", "mqtt-port": 1883, "mqtt-user": "", "mqtt-pass": "" }
|
||||||
|
r = call_api_post( "/api/config/push", j )
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
def test_push_2(self):
|
||||||
|
r = call_api_get( "/api/test/push?id=" + id + "&format=http-1" )
|
||||||
|
j = json.loads(r.text)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertEqual(j["success"], True)
|
||||||
|
|
||||||
|
def test_push_3(self):
|
||||||
|
r = call_api_get( "/api/test/push?id=" + id + "&format=http-2" )
|
||||||
|
j = json.loads(r.text)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertEqual(j["success"], True)
|
||||||
|
|
||||||
|
def test_push_4(self):
|
||||||
|
r = call_api_get( "/api/test/push?id=" + id + "&format=http-3" )
|
||||||
|
j = json.loads(r.text)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertEqual(j["success"], True)
|
||||||
|
|
||||||
|
def test_push_5(self):
|
||||||
|
r = call_api_get( "/api/test/push?id=" + id + "&format=mqtt" )
|
||||||
|
j = json.loads(r.text)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertEqual(j["success"], True)
|
||||||
|
|
||||||
|
def test_push_6(self):
|
||||||
|
r = call_api_get( "/api/test/push?id=" + id + "&format=influx" )
|
||||||
|
# TODO: Figure out how to test the influx db setup. Create my own mockup ?
|
||||||
|
|
||||||
|
# Check format api
|
||||||
|
def test_format_1(self):
|
||||||
|
j = { "id": id, "http-1": "one" }
|
||||||
|
r = call_api_post( "/api/config/format", j )
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
def test_format_2(self):
|
||||||
|
j = { "id": id, "http-2": "two" }
|
||||||
|
r = call_api_post( "/api/config/format", j )
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
def test_format_3(self):
|
||||||
|
j = { "id": id, "http-3": "five" }
|
||||||
|
r = call_api_post( "/api/config/format", j )
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
def test_format_4(self):
|
||||||
|
j = { "id": id, "influxdb": "three" }
|
||||||
|
r = call_api_post( "/api/config/format", j )
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
def test_format_5(self):
|
||||||
|
j = { "id": id, "mqtt": "four" }
|
||||||
|
r = call_api_post( "/api/config/format", j )
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
def test_format_6(self):
|
||||||
|
r = call_api_get( "/api/config/format" )
|
||||||
|
j = json.loads(r.text)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertEqual(j["id"], id)
|
||||||
|
self.assertEqual(j["http-1"], "one")
|
||||||
|
self.assertEqual(j["http-2"], "two")
|
||||||
|
self.assertEqual(j["http-3"], "five")
|
||||||
|
self.assertEqual(j["influxdb"], "three")
|
||||||
|
self.assertEqual(j["mqtt"], "four")
|
||||||
|
|
||||||
|
def test_format_7(self):
|
||||||
|
j = { "id": id, "http-1": "" }
|
||||||
|
r = call_api_post( "/api/config/format", j )
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
def test_format_8(self):
|
||||||
|
j = { "id": id, "http-2": "" }
|
||||||
|
r = call_api_post( "/api/config/format", j )
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
def test_format_9(self):
|
||||||
|
j = { "id": id, "http-3": "" }
|
||||||
|
r = call_api_post( "/api/config/format", j )
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
def test_format_A(self):
|
||||||
|
j = { "id": id, "influxdb": "" }
|
||||||
|
r = call_api_post( "/api/config/format", j )
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
def test_format_B(self):
|
||||||
|
j = { "id": id, "mqtt": "" }
|
||||||
|
r = call_api_post( "/api/config/format", j )
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
def test_format_C(self):
|
||||||
|
r = call_api_get( "/api/config/format" )
|
||||||
|
j = json.loads(r.text)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
#print(j["http-1"])
|
||||||
|
#print(j["http-2"])
|
||||||
|
#print(j["http-3"])
|
||||||
|
#print(j["influxdb"])
|
||||||
|
#print(j["mqtt"])
|
||||||
|
self.assertEqual(j["http-1"], "%7B%22name%22%20%3A%20%22%24%7Bmdns%7D%22%2C%20%22ID%22%3A%20%22%24%7Bid%7D%22%2C%20%22token%22%20%3A%20%22%24%7Btoken%7D%22%2C%20%22interval%22%3A%20%24%7Bsleep%2Dinterval%7D%2C%20%22temperature%22%3A%20%24%7Btemp%7D%2C%20%22temp%5Funits%22%3A%20%22%24%7Btemp%2Dunit%7D%22%2C%20%22gravity%22%3A%20%24%7Bgravity%7D%2C%20%22angle%22%3A%20%24%7Bangle%7D%2C%20%22battery%22%3A%20%24%7Bbattery%7D%2C%20%22RSSI%22%3A%20%24%7Brssi%7D%2C%20%22corr%2Dgravity%22%3A%20%24%7Bcorr%2Dgravity%7D%2C%20%22gravity%2Dunit%22%3A%20%22%24%7Bgravity%2Dunit%7D%22%2C%20%22run%2Dtime%22%3A%20%24%7Brun%2Dtime%7D%20%7D")
|
||||||
|
self.assertEqual(j["http-2"], "%7B%22name%22%20%3A%20%22%24%7Bmdns%7D%22%2C%20%22ID%22%3A%20%22%24%7Bid%7D%22%2C%20%22token%22%20%3A%20%22%24%7Btoken%7D%22%2C%20%22interval%22%3A%20%24%7Bsleep%2Dinterval%7D%2C%20%22temperature%22%3A%20%24%7Btemp%7D%2C%20%22temp%5Funits%22%3A%20%22%24%7Btemp%2Dunit%7D%22%2C%20%22gravity%22%3A%20%24%7Bgravity%7D%2C%20%22angle%22%3A%20%24%7Bangle%7D%2C%20%22battery%22%3A%20%24%7Bbattery%7D%2C%20%22RSSI%22%3A%20%24%7Brssi%7D%2C%20%22corr%2Dgravity%22%3A%20%24%7Bcorr%2Dgravity%7D%2C%20%22gravity%2Dunit%22%3A%20%22%24%7Bgravity%2Dunit%7D%22%2C%20%22run%2Dtime%22%3A%20%24%7Brun%2Dtime%7D%20%7D")
|
||||||
|
self.assertEqual(j["http-3"], "%3Fname%3D%24%7Bmdns%7D%26id%3D%24%7Bid%7D%26token%3D%24%7Btoken2%7D%26interval%3D%24%7Bsleep%2Dinterval%7D%26temperature%3D%24%7Btemp%7D%26temp%2Dunits%3D%24%7Btemp%2Dunit%7D%26gravity%3D%24%7Bgravity%7D%26angle%3D%24%7Bangle%7D%26battery%3D%24%7Bbattery%7D%26rssi%3D%24%7Brssi%7D%26corr%2Dgravity%3D%24%7Bcorr%2Dgravity%7D%26gravity%2Dunit%3D%24%7Bgravity%2Dunit%7D%26run%2Dtime%3D%24%7Brun%2Dtime%7D")
|
||||||
|
self.assertEqual(j["influxdb"], "measurement%2Chost%3D%24%7Bmdns%7D%2Cdevice%3D%24%7Bid%7D%2Ctemp%2Dformat%3D%24%7Btemp%2Dunit%7D%2Cgravity%2Dformat%3D%24%7Bgravity%2Dunit%7D%20gravity%3D%24%7Bgravity%7D%2Ccorr%2Dgravity%3D%24%7Bcorr%2Dgravity%7D%2Cangle%3D%24%7Bangle%7D%2Ctemp%3D%24%7Btemp%7D%2Cbattery%3D%24%7Bbattery%7D%2Crssi%3D%24%7Brssi%7D%0A")
|
||||||
|
self.assertEqual(j["mqtt"], "ispindel%2F%24%7Bmdns%7D%2Ftilt%3A%24%7Bangle%7D%7Cispindel%2F%24%7Bmdns%7D%2Ftemperature%3A%24%7Btemp%7D%7Cispindel%2F%24%7Bmdns%7D%2Ftemp%5Funits%3A%24%7Btemp%2Dunit%7D%7Cispindel%2F%24%7Bmdns%7D%2Fbattery%3A%24%7Bbattery%7D%7Cispindel%2F%24%7Bmdns%7D%2Fgravity%3A%24%7Bgravity%7D%7Cispindel%2F%24%7Bmdns%7D%2Finterval%3A%24%7Bsleep%2Dinterval%7D%7Cispindel%2F%24%7Bmdns%7D%2FRSSI%3A%24%7Brssi%7D%7C")
|
||||||
|
|
||||||
|
# Toggle sleep mode
|
||||||
|
def toggle_sleepmode_1(self):
|
||||||
|
j = { "id": id, "sleep-mode": "on" }
|
||||||
|
r = call_api_post( "/api/status/sleepmode" )
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
r = call_api_get( "/api/status" )
|
||||||
|
j = json.loads(r.text)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertEqual(j["sleep-mode"], True)
|
||||||
|
|
||||||
|
def toggle_sleepmode_2(self):
|
||||||
|
j = { "id": id, "sleep-mode": "off" }
|
||||||
|
r = call_api_post( "/api/status/sleepmode" )
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
r = call_api_get( "/api/status" )
|
||||||
|
j = json.loads(r.text)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertEqual(j["sleep-mode"], False)
|
||||||
|
|
||||||
|
# Clear setting
|
||||||
|
def default_settings_1(self):
|
||||||
|
j = { "id": id, "mdns": "gravmon", "temp-format": "C", "sleep-interval": 300 }
|
||||||
|
r = call_api_post( "/api/config/device", j )
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
def default_settings_2(self):
|
||||||
|
j = { "id": id, "token": "", "token2": "", "http-push": "", "http-push2": "", "http-push3": "", "influxdb2-push": "", "influxdb2-org": "", "influxdb2-bucket": "",
|
||||||
|
"influxdb2-auth": "", "mqtt-push": "", "mqtt-port": 1883, "mqtt-user": "", "mqtt-pass": "" }
|
||||||
|
r = call_api_post( "/api/config/push", j )
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
def default_settings_3(self):
|
||||||
|
j = { "id": id, "ota-url": "", "voltage-factor": 1.55, "temp-adjustment-value": -2, "gyro-temp": "off" }
|
||||||
|
r = call_api_post( "/api/config/hardware", j )
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
def default_settings_4(self):
|
||||||
|
j = { "id": id, "gravity-formula": "", "gravity-temp-adjustment": "off", "gravity-format": "G" }
|
||||||
|
r = call_api_post( "/api/config/gravity", j )
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
# Check advanced
|
||||||
|
def test_advanced_config_1(self):
|
||||||
|
r = call_api_get( "/api/status" )
|
||||||
|
j = json.loads(r.text)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertEqual(j["id"], id)
|
||||||
|
r = call_api_get( "/api/factory?id=" + j["id"])
|
||||||
|
time.sleep(4)
|
||||||
|
|
||||||
|
r = call_api_get( "/api/config/advanced" )
|
||||||
|
j = json.loads(r.text)
|
||||||
|
#print(j)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertEqual(j["gyro-read-count"], 50)
|
||||||
|
self.assertEqual(j["tempsensor-resolution"], 9)
|
||||||
|
self.assertEqual(j["gyro-moving-threashold"], 500)
|
||||||
|
self.assertEqual(j["formula-max-deviation"], 3)
|
||||||
|
self.assertEqual(j["formula-calibration-temp"], 20)
|
||||||
|
self.assertEqual(j["wifi-portal-timeout"], 120)
|
||||||
|
self.assertEqual(j["wifi-connect-timeout"], 20)
|
||||||
|
self.assertEqual(j["ignore-low-angles"], False)
|
||||||
|
self.assertEqual(j["formula-calibration-temp"], 20)
|
||||||
|
self.assertEqual(j["int-http1"], 0)
|
||||||
|
self.assertEqual(j["int-http2"], 0)
|
||||||
|
self.assertEqual(j["int-http3"], 0)
|
||||||
|
self.assertEqual(j["int-influx"], 0)
|
||||||
|
self.assertEqual(j["int-mqtt"], 0)
|
||||||
|
|
||||||
|
def test_advanced_config_2(self):
|
||||||
|
j = { "id": id, "gyro-read-count": 51, "tempsensor-resolution": 10, "gyro-moving-threashold": 501, "formula-max-deviation": 1.7, "ignore-low-angles": "on",
|
||||||
|
"formula-calibration-temp": 21, "wifi-portal-timeout": 121, "wifi-connect-timeout": 21, "int-http1": 1, "int-http2": 2, "int-http3": 3, "int-influx": 4, "int-mqtt": 5 }
|
||||||
|
r = call_api_post( "/api/config/advanced", j )
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
r = call_api_get( "/api/config/advanced" )
|
||||||
|
j = json.loads(r.text)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertEqual(j["gyro-read-count"], 51)
|
||||||
|
self.assertEqual(j["tempsensor-resolution"], 10)
|
||||||
|
self.assertEqual(j["gyro-moving-threashold"], 501)
|
||||||
|
self.assertEqual(j["formula-max-deviation"], 1.7)
|
||||||
|
self.assertEqual(j["formula-calibration-temp"], 21)
|
||||||
|
self.assertEqual(j["wifi-portal-timeout"], 121)
|
||||||
|
self.assertEqual(j["wifi-connect-timeout"], 21)
|
||||||
|
self.assertEqual(j["ignore-low-angles"], True)
|
||||||
|
self.assertEqual(j["int-http1"], 1)
|
||||||
|
self.assertEqual(j["int-http2"], 2)
|
||||||
|
self.assertEqual(j["int-http3"], 3)
|
||||||
|
self.assertEqual(j["int-influx"], 4)
|
||||||
|
self.assertEqual(j["int-mqtt"], 5)
|
||||||
|
|
||||||
|
def test_advanced_config_3(self):
|
||||||
|
j = { "id": id, "ignore-low-angles": "on" }
|
||||||
|
r = call_api_post( "/api/config/advanced", j )
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
r = call_api_get( "/api/config/advanced" )
|
||||||
|
j = json.loads(r.text)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertEqual(j["ignore-low-angles"], True)
|
||||||
|
|
||||||
|
j = { "id": id } # Skipping checkbox variable should set it to false
|
||||||
|
r = call_api_post( "/api/config/advanced", j )
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
r = call_api_get( "/api/config/advanced" )
|
||||||
|
j = json.loads(r.text)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertEqual(j["ignore-low-angles"], False)
|
||||||
|
|
||||||
|
def test_bug_71(self):
|
||||||
|
format = "gm%3A%7B%22name%22%3A%22%24%7Bmdns%7D%22%2C%20%22ID%22%3A%22%24%7Bid%7D%22%2C%20%22temperature%22%3A%20%24%7Btemp%7D%2C%20%22gravity%22%3A%24%7Bgravity%7D%2C%22angle%22%3A%20%24%7Bangle%7D%2C%20%22battery%22%3A%24%7Bbattery%7D%2C%20%22rssi%22%3A%20%24%7Brssi%7D%7D"
|
||||||
|
j = { "id": id, "mqtt": format }
|
||||||
|
r = call_api_post( "/api/config/format", j )
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
r = call_api_get( "/api/config/format" )
|
||||||
|
j = json.loads(r.text)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertEqual(j["mqtt"], format)
|
||||||
|
|
||||||
|
def test_bug_79(self):
|
||||||
|
j = { "id": id, "formula-max-deviation": 1.7 }
|
||||||
|
r = call_api_post( "/api/config/advanced", j )
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
j = { "id": id, "g1": 1.0, "g2": 1.009, "g3": 1.014, "g4": 1.027, "g5": 1.037, "g6": 1.042, "g7": 1.051, "g8": 1.060, "g9": 1.073, "g10": 1.078, "a1": 23.52, "a2": 26.47, "a3": 29.87, "a4": 33.43, "a5": 38.16, "a6": 40.6, "a7": 45.85, "a8": 50.12, "a9": 56.55, "a10": 59.078, "gravity-formula": "" }
|
||||||
|
r = call_api_post("/api/formula", j)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
r = call_api_get( "/api/formula" )
|
||||||
|
j = json.loads(r.text)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertEqual(j["error"], 'Unable to find an accurate formula based on input, check error log and graph below.')
|
||||||
|
|
||||||
|
j = { "id": id, "formula-max-deviation": 4 }
|
||||||
|
r = call_api_post( "/api/config/advanced", j )
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
j = { "id": id, "g1": 1.0, "g2": 1.009, "g3": 1.014, "g4": 1.027, "g5": 1.037, "g6": 1.042, "g7": 1.051, "g8": 1.060, "g9": 1.073, "g10": 1.078, "a1": 23.52, "a2": 26.47, "a3": 29.87, "a4": 33.43, "a5": 38.16, "a6": 40.6, "a7": 45.85, "a8": 50.12, "a9": 56.55, "a10": 59.078, "gravity-formula": "" }
|
||||||
|
r = call_api_post("/api/formula", j)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
|
r = call_api_get( "/api/formula" )
|
||||||
|
j = json.loads(r.text)
|
||||||
|
self.assertEqual(r.status_code, 200)
|
||||||
|
self.assertEqual(j["error"], '')
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
@ -3,7 +3,7 @@
|
|||||||
"wifi-ssid2": "ssid 2",
|
"wifi-ssid2": "ssid 2",
|
||||||
"mdns": "gravmon3",
|
"mdns": "gravmon3",
|
||||||
"id": "7376ef",
|
"id": "7376ef",
|
||||||
"ota-url": "http://192.168.1.100:80/firmware/gravmon/",
|
"ota-url": "https://www.gravitymon.com/firmware/",
|
||||||
"temp-format": "C",
|
"temp-format": "C",
|
||||||
"http-push": "http://192.168.1.10:9090/api/v1/ZYfjlUNeiuyu9N/telemetry",
|
"http-push": "http://192.168.1.10:9090/api/v1/ZYfjlUNeiuyu9N/telemetry",
|
||||||
"http-push-h1": "Auth: Basic T7IF9DD9fF3RDddE=",
|
"http-push-h1": "Auth: Basic T7IF9DD9fF3RDddE=",
|
||||||
|
82
test/tests.cpp
Normal file
82
test/tests.cpp
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2022 Magnus
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include <AUnit.h>
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
#include <main.hpp>
|
||||||
|
|
||||||
|
using aunit::Printer;
|
||||||
|
using aunit::TestRunner;
|
||||||
|
using aunit::Verbosity;
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Boolean
|
||||||
|
assertEqual(a, b)
|
||||||
|
assertNotEqual(a, b)
|
||||||
|
assertLess(a, b)
|
||||||
|
assertMore(a, b)
|
||||||
|
assertLessOrEqual(a, b)
|
||||||
|
assertMoreOrEqual(a, b)
|
||||||
|
|
||||||
|
// String
|
||||||
|
assertStringCaseEqual(a, b)
|
||||||
|
assertStringCaseNotEqual(a, b)
|
||||||
|
assertNear(a, b, error)
|
||||||
|
assertNotNear(a, b, error)
|
||||||
|
checkTestDone(name)
|
||||||
|
checkTestNotDone(name)
|
||||||
|
checkTestPass(name)
|
||||||
|
checkTestNotPass(name)
|
||||||
|
checkTestFail(name)
|
||||||
|
checkTestNotFail(name)
|
||||||
|
checkTestSkip(name)
|
||||||
|
checkTestNotSkip(name)
|
||||||
|
checkTestExpire(name) [*]
|
||||||
|
checkTestNotExpire(name) [*]
|
||||||
|
assertTestDone(name)
|
||||||
|
assertTestNotDone(name)
|
||||||
|
assertTestPass(name)
|
||||||
|
assertTestNotPass(name)
|
||||||
|
assertTestFail(name)
|
||||||
|
assertTestNotFail(name)
|
||||||
|
assertTestSkip(name)
|
||||||
|
assertTestNotSkip(name)
|
||||||
|
assertTestExpire(name) [*]
|
||||||
|
assertTestNotExpire(name) [*]
|
||||||
|
*/
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
Serial.println("Gravitymon - Unit Test Build");
|
||||||
|
delay(2000);
|
||||||
|
Printer::setPrinter(&Serial);
|
||||||
|
// TestRunner::setVerbosity(Verbosity::kAll);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
TestRunner::run();
|
||||||
|
delay(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
// EOF
|
31
test/tests_ble.cpp
Normal file
31
test/tests_ble.cpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2022 Magnus
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include <AUnit.h>
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
#include <main.hpp>
|
||||||
|
|
||||||
|
// No unit testing for the BLE module.
|
||||||
|
|
||||||
|
// EOF
|
67
test/tests_calc.cpp
Normal file
67
test/tests_calc.cpp
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2022 Magnus
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include <AUnit.h>
|
||||||
|
|
||||||
|
#include <calc.hpp>
|
||||||
|
#include <helper.hpp>
|
||||||
|
|
||||||
|
// TODO: Add more test cases to explore formula creation error conditions when
|
||||||
|
// values are out of bounds
|
||||||
|
// TODO: Add more test cases to check order 3 + 4 formula creation as well.
|
||||||
|
|
||||||
|
test(calc_createFormula1) {
|
||||||
|
char buffer[100];
|
||||||
|
RawFormulaData fd = {
|
||||||
|
{0.0, 25.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
|
||||||
|
{0.0, 1.0, 1.02, 1.033, 1.00011, 1.0, 1.0, 1.0, 1.0, 1.0}};
|
||||||
|
int i = createFormula(fd, &buffer[0], sizeof(buffer), 2);
|
||||||
|
assertEqual(i, ERR_FORMULA_NOTENOUGHVALUES);
|
||||||
|
}
|
||||||
|
|
||||||
|
test(calc_createFormula2) {
|
||||||
|
char buffer[100];
|
||||||
|
RawFormulaData fd = {
|
||||||
|
{25.0, 30.0, 35.0, 40.0, 45.0, 50.0, 55.0, 60.0, 65.0, 70.0},
|
||||||
|
{1.0, 1.01, 1.02, 1.03, 1.04, 1.05, 1.06, 1.07, 1.08, 1.1}};
|
||||||
|
int i = createFormula(fd, &buffer[0], sizeof(buffer), 2);
|
||||||
|
assertEqual(i, 0);
|
||||||
|
assertEqual(&buffer[0], "0.00000909*tilt^2+0.00124545*tilt+0.96445455");
|
||||||
|
}
|
||||||
|
|
||||||
|
test(calc_calculateGravity) {
|
||||||
|
const char* formula = "0.00000909*tilt^2+0.00124545*tilt+0.96445455";
|
||||||
|
double g = calculateGravity(30, 20, formula);
|
||||||
|
float v1 = reduceFloatPrecision(g, 2);
|
||||||
|
float v2 = 1.01;
|
||||||
|
assertEqual(v1, v2);
|
||||||
|
}
|
||||||
|
|
||||||
|
test(calc_gravityTemperatureCorrectionC) {
|
||||||
|
double g = gravityTemperatureCorrectionC(1.02, 45.0, 20.0);
|
||||||
|
float v1 = reduceFloatPrecision(g, 2);
|
||||||
|
float v2 = 1.03;
|
||||||
|
assertEqual(v1, v2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// EOF
|
73
test/tests_config.cpp
Normal file
73
test/tests_config.cpp
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2022 Magnus
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include <AUnit.h>
|
||||||
|
|
||||||
|
#include <config.hpp>
|
||||||
|
|
||||||
|
test(config_defaultValues) {
|
||||||
|
assertEqual(myConfig.getGravityFormat(), 'G');
|
||||||
|
assertEqual(myConfig.getTempFormat(), 'C');
|
||||||
|
assertEqual(myConfig.getSleepInterval(), 900);
|
||||||
|
assertEqual(myConfig.getTempSensorAdjC(), 0.0);
|
||||||
|
float f = 4.15;
|
||||||
|
assertEqual(myConfig.getVoltageConfig(), f);
|
||||||
|
}
|
||||||
|
|
||||||
|
test(config_advDefaultValues) {
|
||||||
|
assertEqual(myAdvancedConfig.getDefaultCalibrationTemp(), 20.0);
|
||||||
|
assertEqual(myAdvancedConfig.getGyroReadCount(), 50);
|
||||||
|
assertEqual(myAdvancedConfig.getGyroReadDelay(), 3150);
|
||||||
|
assertEqual(myAdvancedConfig.getGyroSensorMovingThreashold(), 500);
|
||||||
|
assertEqual(myAdvancedConfig.getMaxFormulaCreationDeviation(), 3.0);
|
||||||
|
assertEqual(myAdvancedConfig.getPushIntervalHttp1(), 0);
|
||||||
|
assertEqual(myAdvancedConfig.getPushIntervalHttp2(), 0);
|
||||||
|
assertEqual(myAdvancedConfig.getPushIntervalHttp3(), 0);
|
||||||
|
assertEqual(myAdvancedConfig.getPushIntervalMqtt(), 0);
|
||||||
|
assertEqual(myAdvancedConfig.getPushIntervalInflux(), 0);
|
||||||
|
assertEqual(myAdvancedConfig.getPushTimeout(), 10);
|
||||||
|
assertEqual(myAdvancedConfig.getTempSensorResolution(), 9);
|
||||||
|
assertEqual(myAdvancedConfig.getWifiConnectTimeout(), 20);
|
||||||
|
assertEqual(myAdvancedConfig.getWifiPortalTimeout(), 120);
|
||||||
|
assertEqual(myAdvancedConfig.isIgnoreLowAnges(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
test(config_tempFormat) {
|
||||||
|
myConfig.setTempFormat('F');
|
||||||
|
assertEqual(myConfig.getTempFormat(), 'F');
|
||||||
|
myConfig.setTempFormat('C');
|
||||||
|
assertEqual(myConfig.getTempFormat(), 'C');
|
||||||
|
myConfig.setTempFormat('X');
|
||||||
|
assertEqual(myConfig.getTempFormat(), 'C');
|
||||||
|
}
|
||||||
|
|
||||||
|
test(config_gravityFormat) {
|
||||||
|
myConfig.setGravityFormat('P');
|
||||||
|
assertEqual(myConfig.getGravityFormat(), 'P');
|
||||||
|
myConfig.setGravityFormat('G');
|
||||||
|
assertEqual(myConfig.getGravityFormat(), 'G');
|
||||||
|
myConfig.setGravityFormat('X');
|
||||||
|
assertEqual(myConfig.getGravityFormat(), 'G');
|
||||||
|
}
|
||||||
|
|
||||||
|
// EOF
|
44
test/tests_gyro.cpp
Normal file
44
test/tests_gyro.cpp
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2022 Magnus
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include <AUnit.h>
|
||||||
|
|
||||||
|
#include <gyro.hpp>
|
||||||
|
|
||||||
|
test(gyro_connectGyro) {
|
||||||
|
myGyro.setup();
|
||||||
|
assertEqual(myGyro.isConnected(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
test(gyro_readGyro) {
|
||||||
|
myGyro.setup();
|
||||||
|
assertEqual(myGyro.read(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
test(gyro_readGyroTemp) {
|
||||||
|
myGyro.setup();
|
||||||
|
assertNotEqual(myGyro.getInitialSensorTempC(), -273.0);
|
||||||
|
assertNotEqual(myGyro.getSensorTempC(), -273.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// EOF
|
93
test/tests_helper.cpp
Normal file
93
test/tests_helper.cpp
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2022 Magnus
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include <AUnit.h>
|
||||||
|
|
||||||
|
#include <helper.hpp>
|
||||||
|
|
||||||
|
BatteryVoltage myBatteryVoltage;
|
||||||
|
|
||||||
|
test(helper_convertToPlato) {
|
||||||
|
double p = convertToPlato(1.008);
|
||||||
|
char buffer[20];
|
||||||
|
String s = convertFloatToString(p, &buffer[0], 2);
|
||||||
|
s.trim();
|
||||||
|
assertEqual(s, "2.06");
|
||||||
|
}
|
||||||
|
|
||||||
|
test(helper_convertToSG) {
|
||||||
|
double p = convertToSG(2.06);
|
||||||
|
char buffer[20];
|
||||||
|
String s = convertFloatToString(p, &buffer[0], 3);
|
||||||
|
s.trim();
|
||||||
|
assertEqual(s, "1.008");
|
||||||
|
}
|
||||||
|
|
||||||
|
test(helper_convertCtoF) {
|
||||||
|
float t = convertCtoF(20.0);
|
||||||
|
assertEqual(t, 68.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
test(helper_convertFtoC) {
|
||||||
|
float t = convertFtoC(68.0);
|
||||||
|
assertEqual(t, 20.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
test(helper_urlEncode) {
|
||||||
|
String s = urlencode("Hello world");
|
||||||
|
assertEqual(s, "Hello%20world");
|
||||||
|
}
|
||||||
|
|
||||||
|
test(helper_urlDecode) {
|
||||||
|
String s = urldecode("Hello%20world");
|
||||||
|
assertEqual(s, "Hello world");
|
||||||
|
}
|
||||||
|
|
||||||
|
test(helper_convertFloatToString) {
|
||||||
|
char buffer[20];
|
||||||
|
String s = convertFloatToString(20.2, &buffer[0], 2);
|
||||||
|
s.trim();
|
||||||
|
assertEqual(s, "20.20");
|
||||||
|
}
|
||||||
|
|
||||||
|
test(helper_reduceFloatPrecision1) {
|
||||||
|
float v = 20.233;
|
||||||
|
float f = reduceFloatPrecision(v, 2);
|
||||||
|
v = 20.23;
|
||||||
|
assertEqual(f, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
test(helper_reduceFloatPrecision2) {
|
||||||
|
float v = 20.238;
|
||||||
|
float f = reduceFloatPrecision(v, 2);
|
||||||
|
v = 20.24;
|
||||||
|
assertEqual(f, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
test(helper_readBatteryVoltage) {
|
||||||
|
myBatteryVoltage.read();
|
||||||
|
float f = myBatteryVoltage.getVoltage();
|
||||||
|
assertMoreOrEqual(f, 2.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// EOF
|
32
test/tests_pushtarget.cpp
Normal file
32
test/tests_pushtarget.cpp
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2022 Magnus
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include <AUnit.h>
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
#include <main.hpp>
|
||||||
|
|
||||||
|
// TODO: Build some php scripts that run on gravitymon.com for testing the push
|
||||||
|
// data.
|
||||||
|
|
||||||
|
// EOF
|
128
test/tests_templating.cpp
Normal file
128
test/tests_templating.cpp
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
/*
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2022 Magnus
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include <AUnit.h>
|
||||||
|
|
||||||
|
#include <config.hpp>
|
||||||
|
#include <templating.hpp>
|
||||||
|
|
||||||
|
test(template_applyTemplate1) {
|
||||||
|
TemplatingEngine e;
|
||||||
|
char buffer[20];
|
||||||
|
myConfig.setMDNS("gravitymon");
|
||||||
|
|
||||||
|
e.initialize(45.0, 1.123, 1.223, 21.2, 2.98);
|
||||||
|
String s = e.create(TemplatingEngine::TEMPLATE_HTTP1);
|
||||||
|
String id = myConfig.getID();
|
||||||
|
String batt =
|
||||||
|
convertFloatToString(myBatteryVoltage.getVoltage(), &buffer[0], 2);
|
||||||
|
batt.trim();
|
||||||
|
String v = "{\"name\" : \"gravitymon\", \"ID\": \"" + id +
|
||||||
|
"\", \"token\" : \"\", \"interval\": 900, \"temperature\": 21.2, "
|
||||||
|
"\"temp_units\": \"C\", \"gravity\": 1.1230, \"angle\": 45.00, "
|
||||||
|
"\"battery\": " +
|
||||||
|
batt +
|
||||||
|
", \"RSSI\": 31, \"corr-gravity\": 1.2230, \"gravity-unit\": "
|
||||||
|
"\"G\", \"run-time\": 3.0 }";
|
||||||
|
assertEqual(s, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
test(template_applyTemplate2) {
|
||||||
|
TemplatingEngine e;
|
||||||
|
char buffer[20];
|
||||||
|
myConfig.setMDNS("gravitymon");
|
||||||
|
|
||||||
|
e.initialize(45.0, 1.123, 1.223, 21.2, 2.98);
|
||||||
|
String s = e.create(TemplatingEngine::TEMPLATE_HTTP2);
|
||||||
|
String id = myConfig.getID();
|
||||||
|
String batt =
|
||||||
|
convertFloatToString(myBatteryVoltage.getVoltage(), &buffer[0], 2);
|
||||||
|
batt.trim();
|
||||||
|
String v = "{\"name\" : \"gravitymon\", \"ID\": \"" + id +
|
||||||
|
"\", \"token\" : \"\", \"interval\": 900, \"temperature\": 21.2, "
|
||||||
|
"\"temp_units\": \"C\", \"gravity\": 1.1230, \"angle\": 45.00, "
|
||||||
|
"\"battery\": " +
|
||||||
|
batt +
|
||||||
|
", \"RSSI\": 31, \"corr-gravity\": 1.2230, \"gravity-unit\": "
|
||||||
|
"\"G\", \"run-time\": 3.0 }";
|
||||||
|
assertEqual(s, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
test(template_applyTemplate3) {
|
||||||
|
TemplatingEngine e;
|
||||||
|
char buffer[20];
|
||||||
|
myConfig.setMDNS("gravitymon");
|
||||||
|
|
||||||
|
e.initialize(45.0, 1.123, 1.223, 21.2, 2.98);
|
||||||
|
String s = e.create(TemplatingEngine::TEMPLATE_HTTP3);
|
||||||
|
String id = myConfig.getID();
|
||||||
|
String batt =
|
||||||
|
convertFloatToString(myBatteryVoltage.getVoltage(), &buffer[0], 2);
|
||||||
|
batt.trim();
|
||||||
|
String v = "?name=gravitymon&id=" + id +
|
||||||
|
"&token=&interval=900&temperature=21.2&temp-units=C&gravity=1."
|
||||||
|
"1230&angle=45.00&battery=" +
|
||||||
|
batt + "&rssi=31&corr-gravity=1.2230&gravity-unit=G&run-time=3.0";
|
||||||
|
assertEqual(s, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
test(template_applyTemplate4) {
|
||||||
|
TemplatingEngine e;
|
||||||
|
char buffer[20];
|
||||||
|
myConfig.setMDNS("gravitymon");
|
||||||
|
|
||||||
|
e.initialize(45.0, 1.123, 1.223, 21.2, 2.98);
|
||||||
|
String s = e.create(TemplatingEngine::TEMPLATE_INFLUX);
|
||||||
|
String id = myConfig.getID();
|
||||||
|
String batt =
|
||||||
|
convertFloatToString(myBatteryVoltage.getVoltage(), &buffer[0], 2);
|
||||||
|
batt.trim();
|
||||||
|
String v =
|
||||||
|
"measurement,host=gravitymon,device=" + id +
|
||||||
|
",temp-format=C,gravity-format=G "
|
||||||
|
"gravity=1.1230,corr-gravity=1.2230,angle=45.00,temp=21.2,battery=" +
|
||||||
|
batt + ",rssi=31\n";
|
||||||
|
assertEqual(s, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
test(template_applyTemplate5) {
|
||||||
|
TemplatingEngine e;
|
||||||
|
char buffer[20];
|
||||||
|
myConfig.setMDNS("gravitymon");
|
||||||
|
|
||||||
|
e.initialize(45.0, 1.123, 1.223, 21.2, 2.98);
|
||||||
|
String s = e.create(TemplatingEngine::TEMPLATE_MQTT);
|
||||||
|
String batt =
|
||||||
|
convertFloatToString(myBatteryVoltage.getVoltage(), &buffer[0], 2);
|
||||||
|
batt.trim();
|
||||||
|
String v =
|
||||||
|
"ispindel/gravitymon/tilt:45.00|ispindel/gravitymon/"
|
||||||
|
"temperature:21.2|ispindel/gravitymon/temp_units:C|ispindel/gravitymon/"
|
||||||
|
"battery:" +
|
||||||
|
batt +
|
||||||
|
"|ispindel/gravitymon/gravity:1.1230|ispindel/gravitymon/"
|
||||||
|
"interval:900|ispindel/gravitymon/RSSI:31|";
|
||||||
|
assertEqual(s, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
// EOF
|
34
test/tests_tempsensor.cpp
Normal file
34
test/tests_tempsensor.cpp
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2022 Magnus
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include <AUnit.h>
|
||||||
|
|
||||||
|
#include <tempsensor.hpp>
|
||||||
|
|
||||||
|
test(temp_readSensor) {
|
||||||
|
myTempSensor.setup();
|
||||||
|
myTempSensor.getTempC();
|
||||||
|
assertEqual(myTempSensor.isSensorAttached(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// EOF
|
32
test/tests_webserver.cpp
Normal file
32
test/tests_webserver.cpp
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2022 Magnus
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include <AUnit.h>
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
#include <main.hpp>
|
||||||
|
|
||||||
|
// No unit testing for the WEB module. These tests are done using python script
|
||||||
|
// and the API's
|
||||||
|
|
||||||
|
// EOF
|
32
test/tests_wifi.cpp
Normal file
32
test/tests_wifi.cpp
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2022 Magnus
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include <AUnit.h>
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
#include <main.hpp>
|
||||||
|
|
||||||
|
// No unit testing for the WIFI module. These tests are manual when testing the
|
||||||
|
// installation steps.
|
||||||
|
|
||||||
|
// EOF
|
Loading…
Reference in New Issue
Block a user