Compare commits
204 commits
Author | SHA1 | Date | |
---|---|---|---|
f041cf8cad | |||
d0a5da308d | |||
a9e0a1e60d | |||
ef04489fa6 | |||
f18cfbf2e5 | |||
2548191173 | |||
21e17d1a2b | |||
775f235ba8 | |||
24d8a4a7f1 | |||
7b36aa27f5 | |||
4b3951b465 | |||
97f3433158 | |||
3129a88cb9 | |||
c74f0a76eb | |||
b75254220c | |||
9ff2d9410b | |||
5cdc5c95a5 | |||
28bfb28ff6 | |||
baf8678e99 | |||
b58ed90432 | |||
67998747d7 | |||
9839571893 | |||
4625f98cf3 | |||
0ed7ba7e59 | |||
4eddcd0f1e | |||
3e3ef7d2f2 | |||
9c100f1954 | |||
8ec438e02a | |||
8b8aaf0024 | |||
87b1704335 | |||
1d80e34c4b | |||
4986a4d741 | |||
3ca3e633ae | |||
06d78860ca | |||
41d43813b7 | |||
7e1a4940ac | |||
083fb63764 | |||
88cf18bfcf | |||
af1ab021a4 | |||
194cc08ac9 | |||
f5d72e2ac8 | |||
69155f8e45 | |||
c76490481d | |||
c9298656fa | |||
c649517805 | |||
6fb7b9d608 | |||
eb2e2d4305 | |||
d8e71eebc1 | |||
53430d3fa0 | |||
7081391f63 | |||
f2af9c3fda | |||
96b3cecdb0 | |||
b1cee63ec3 | |||
4138d0b2f5 | |||
5efce879ce | |||
f330d812e6 | |||
8893abb575 | |||
2e25ad3da4 | |||
aabe6a54b3 | |||
7c43523d51 | |||
ab246244c9 | |||
af34331401 | |||
112628f103 | |||
573ebf3e3b | |||
8fb1981552 | |||
de9417ff73 | |||
6e86571a19 | |||
bf537d1ac5 | |||
095797f8b0 | |||
b2cc6ff36d | |||
c51b18dd36 | |||
3a70970356 | |||
36d1b06ba2 | |||
f93e5d7628 | |||
d30536e939 | |||
3a810d6eea | |||
fa36236948 | |||
ac5fdc5dfd | |||
583a4881cd | |||
9fbb6e8dfc | |||
77dada9d6b | |||
13fb3f715a | |||
8a237059fd | |||
3e4ce429c7 | |||
fdf4e9af99 | |||
61e246f6f1 | |||
253bc3f728 | |||
f6f721bd8a | |||
c79522233c | |||
08a39a26f7 | |||
7853102a4d | |||
e7bac339b5 | |||
f5a8c3c11e | |||
a491db257a | |||
79b6c06a2a | |||
d7e083b837 | |||
4873fa8c71 | |||
48a0254f13 | |||
10db95733f | |||
e205119b24 | |||
1c314e14f2 | |||
2a788cb2d0 | |||
27b988c895 | |||
e5e0f87e0b | |||
08d0307fc8 | |||
ac091fa6d8 | |||
945d9c88b7 | |||
8daf555950 | |||
1b3b478a49 | |||
a52143479f | |||
c1207e66ef | |||
f154580eb2 | |||
6c21a9c6a6 | |||
d563cb0c8a | |||
a7348fdbf5 | |||
dfa60eb491 | |||
ca0e763da6 | |||
d2116fc18c | |||
f86ae7cffb | |||
1dbfa67163 | |||
2084c7d60c | |||
c621f7078c | |||
9c338fa74c | |||
92283a3e0d | |||
204007401b | |||
04de63b07e | |||
8ebf6dbf3e | |||
cb79fd5dd0 | |||
db3343d362 | |||
672645c59a | |||
cf41285052 | |||
dca26680b4 | |||
d6bba90c84 | |||
06e69acc77 | |||
dd5e62c8cb | |||
04ae988d2d | |||
a543ba0748 | |||
e50d93bb8c | |||
77ac324d64 | |||
4d6ab5b280 | |||
16ee16f97f | |||
1f28bb7d5d | |||
de1eb48f78 | |||
b6b0c7afbd | |||
8dd5dc662e | |||
278d40af33 | |||
66f10445a4 | |||
2f38a33984 | |||
1b4b6699c5 | |||
c20b309184 | |||
6d7af0e010 | |||
40c0a72c77 | |||
4330d2eac5 | |||
fcd15ddb34 | |||
6b814e70d9 | |||
657bec98e7 | |||
0378e733ef | |||
592ace0f0a | |||
4491da1f2f | |||
d247d14945 | |||
471a423a19 | |||
e6b8365f09 | |||
8d143c03a5 | |||
a435aed47d | |||
129631c82a | |||
f718611bd6 | |||
924a079fb2 | |||
eef4365a83 | |||
52ecbcedae | |||
7210302e5e | |||
7081b957f1 | |||
19b17af925 | |||
ce8299609b | |||
a53d6eabd0 | |||
cfdedc0d7c | |||
dafd7ba856 | |||
811c15093c | |||
f4a3ce45bb | |||
200b928af6 | |||
0a6171ae8b | |||
4f9a77486a | |||
18927d758a | |||
7817b7f2e0 | |||
c83a0cc9c5 | |||
760aa2fc6f | |||
21cf587798 | |||
0572acaeca | |||
2ccd948001 | |||
fc8eef73a6 | |||
da33a02844 | |||
843c382325 | |||
a6540eb997 | |||
60d84e3681 | |||
58f4631f72 | |||
9f0a046f0a | |||
c1bcc83e8b | |||
39aba4819f | |||
7bc681e848 | |||
cfa5ac857d | |||
04fab40742 | |||
a36ef97af2 | |||
9072c6bb7a | |||
38711533cd | |||
e8f6b88aeb |
18
.gitignore
vendored
|
@ -7,3 +7,21 @@
|
|||
.vs
|
||||
__vm
|
||||
/Arduino/BTCDieselHeater/.vscode/*.json
|
||||
.pio
|
||||
.pioenvs
|
||||
.piolibdeps
|
||||
.vscode/.browse.c_cpp.db*
|
||||
.vscode/c_cpp_properties.json
|
||||
.vscode/launch.json
|
||||
/.vscode/settings.json
|
||||
/.vscode/extensions.json
|
||||
Arduino/Afterburner/data/*
|
||||
Arduino/Afterburner/src/*
|
||||
/Altium
|
||||
/Releases
|
||||
/webdev
|
||||
/case
|
||||
/DieselHeaterV2.PcbDoc
|
||||
/StandardResponse.txt
|
||||
/HeaterHack-Tested.zip
|
||||
/OTA_COM.txt
|
||||
|
|
67
.travis.yml
Normal file
|
@ -0,0 +1,67 @@
|
|||
# Continuous Integration (CI) is the practice, in software
|
||||
# engineering, of merging all developer working copies with a shared mainline
|
||||
# several times a day < https://docs.platformio.org/page/ci/index.html >
|
||||
#
|
||||
# Documentation:
|
||||
#
|
||||
# * Travis CI Embedded Builds with PlatformIO
|
||||
# < https://docs.travis-ci.com/user/integration/platformio/ >
|
||||
#
|
||||
# * PlatformIO integration with Travis CI
|
||||
# < https://docs.platformio.org/page/ci/travis.html >
|
||||
#
|
||||
# * User Guide for `platformio ci` command
|
||||
# < https://docs.platformio.org/page/userguide/cmd_ci.html >
|
||||
#
|
||||
#
|
||||
# Please choose one of the following templates (proposed below) and uncomment
|
||||
# it (remove "# " before each line) or use own configuration according to the
|
||||
# Travis CI documentation (see above).
|
||||
#
|
||||
|
||||
|
||||
#
|
||||
# Template #1: General project. Test it using existing `platformio.ini`.
|
||||
#
|
||||
|
||||
# language: python
|
||||
# python:
|
||||
# - "2.7"
|
||||
#
|
||||
# sudo: false
|
||||
# cache:
|
||||
# directories:
|
||||
# - "~/.platformio"
|
||||
#
|
||||
# install:
|
||||
# - pip install -U platformio
|
||||
# - platformio update
|
||||
#
|
||||
# script:
|
||||
# - platformio run
|
||||
|
||||
|
||||
#
|
||||
# Template #2: The project is intended to be used as a library with examples.
|
||||
#
|
||||
|
||||
# language: python
|
||||
# python:
|
||||
# - "2.7"
|
||||
#
|
||||
# sudo: false
|
||||
# cache:
|
||||
# directories:
|
||||
# - "~/.platformio"
|
||||
#
|
||||
# env:
|
||||
# - PLATFORMIO_CI_SRC=path/to/test/file.c
|
||||
# - PLATFORMIO_CI_SRC=examples/file.ino
|
||||
# - PLATFORMIO_CI_SRC=path/to/test/directory
|
||||
#
|
||||
# install:
|
||||
# - pip install -U platformio
|
||||
# - platformio update
|
||||
#
|
||||
# script:
|
||||
# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N
|
6
ABpartition.csv
Normal file
|
@ -0,0 +1,6 @@
|
|||
# Name, Type, SubType, Offset, Size, Flags
|
||||
nvs, data, nvs, 0x9000, 0x5000,
|
||||
otadata, data, ota, 0xe000, 0x2000,
|
||||
app0, app, ota_0, 0x10000, 0x1E0000,
|
||||
app1, app, ota_1, 0x1F0000,0x1E0000,
|
||||
spiffs, data, spiffs, 0x3D0000,0x30000,
|
|
BIN
AppInventor/BT.jpg
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
AppInventor/BTsmall.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
AppInventor/BTverysmall.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
AppInventor/BluetoothHeaterTQuery.aia
Normal file
BIN
AppInventor/bluetooth-icon-11.jpg
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
AppInventor/bluetooth-icon-32011.png
Normal file
After Width: | Height: | Size: 2 KiB |
34
Arduino/Afterburner/Afterburner.ino
Normal file
|
@ -0,0 +1,34 @@
|
|||
/**********************************************************************
|
||||
* This file is deliberately empty.
|
||||
*
|
||||
* It only exists to satisfy the Arduino IDE's perverse requirement that a
|
||||
* .ino must live directly below a parent directory, with the same name.
|
||||
*
|
||||
* In this instance Afterburner\Afterburner.ino
|
||||
*
|
||||
* I seriously recommend you use PLatformIO with your favourite editor.
|
||||
*
|
||||
* The real source code for the entire project is linked to via a symbolic
|
||||
* link to the ClonedRepo\src, lib & data directories.
|
||||
*
|
||||
* ie ClonedRepo\Arduino\Afterburner\src\src -> ClonedRepo\src (..\..\src)
|
||||
* ie ClonedRepo\Arduino\Afterburner\src\lib -> ClonedRepo\lib (..\..\lib)
|
||||
* ie ClonedRepo\Arduino\Afterburner\data -> ClonedRepo\data (..\..\data)
|
||||
*
|
||||
* A batch file is in this folder to create these links, please use it first.
|
||||
*
|
||||
* Whilst initially alarming that is .ino file is empty, the Arduino IDE
|
||||
* happily creates the required executable :-)
|
||||
*
|
||||
* The REAL host of setup() and loop() resides in ClonedRepo\src\Afterburner.cpp
|
||||
*
|
||||
*
|
||||
*****************************************************************************
|
||||
*****************************************************************************
|
||||
** **
|
||||
** DUMP the Arduino IDE, and use PlatformIO. **
|
||||
** Load the ClonedRepo path into PlatformIO. **
|
||||
** Builds much faster and meshes well with decent programming editors :-) **
|
||||
** **
|
||||
*****************************************************************************
|
||||
*****************************************************************************/
|
5
Arduino/Afterburner/MakeSymLinks_Linux.sh
Normal file
|
@ -0,0 +1,5 @@
|
|||
#!/bin/sh
|
||||
mkdir src
|
||||
ln -s ../../src src/src
|
||||
ln -s ../../lib src/lib
|
||||
ln -s ../../data data
|
7
Arduino/Afterburner/MakeSymLinks_Windows.bat
Normal file
|
@ -0,0 +1,7 @@
|
|||
rem mklink /H Afterburner.ino ..\..\src\AfterBurner\Afterburner.cpp
|
||||
mkdir src
|
||||
mklink /J src\lib ..\..\lib
|
||||
mklink /J src\src ..\..\src
|
||||
mklink /J data ..\..\data
|
||||
|
||||
|
20
Arduino/Afterburner/README.txt
Normal file
|
@ -0,0 +1,20 @@
|
|||
|
||||
TO WORK WITH ARDUINO IDE, EVERYTHING IN THIS FOLDER IS FAKE!
|
||||
|
||||
When you pull from gitlab, no symbolic links will be created.
|
||||
|
||||
You need to execute MakeSymLinks_Windows.bat from Explorer.
|
||||
|
||||
Arduino insists upon .ino for their projects, and the .ino
|
||||
file name also has to match the parent directory name.
|
||||
|
||||
The BIG trick here is Afterburner.ino is empty - zilch, nada, nothing!
|
||||
All the REAL source code lives via the src symbolic link.
|
||||
The real core exists as a .cpp file: repo\src\Afterburner.cpp
|
||||
|
||||
Arduino\Afterburner\Afterburner.ino is EMPTY
|
||||
Arduino\Afterburner\src\src links to repo\src\
|
||||
Arduino\Afterburner\src\lib links to repo\lib\
|
||||
Arduino\Afterburner\data links to repo\data
|
||||
|
||||
Ugggh. I hate Arduino IDE (and it's build environment!)
|
Before Width: | Height: | Size: 1.1 KiB |
|
@ -1,536 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<!-- <link rel="icon" href="data;,"> -->
|
||||
<script>
|
||||
|
||||
var Socket;
|
||||
function init() {
|
||||
Socket = new WebSocket('ws://' + window.location.hostname + ':81/');
|
||||
|
||||
Socket.onmessage = function(event){
|
||||
var heater = JSON.parse(event.data);
|
||||
var key;
|
||||
for(key in heater) {
|
||||
console.log("JSON decode:", key, heater[key]);
|
||||
switch(key) {
|
||||
case "RunState":
|
||||
if (heater[key] == 0) {
|
||||
document.getElementById("myonoffswitch").checked = false;
|
||||
document.getElementById("myonoffswitch").style = "block";
|
||||
document.getElementById("onoffswitch").style.visibility = "visible";
|
||||
} else if(heater[key] >= 7) {
|
||||
document.getElementById("myonoffswitch").checked = false;
|
||||
document.getElementById("myonoffswitch").style = "none";
|
||||
document.getElementById("onoffswitch").style.visibility = "hidden";
|
||||
} else {
|
||||
document.getElementById("myonoffswitch").checked = true;
|
||||
document.getElementById("myonoffswitch").style = "block";
|
||||
document.getElementById("onoffswitch").style.visibility = "visible";
|
||||
}
|
||||
document.getElementById("RunString").style.visibility = (heater[key] == 5 || heater[key] == 0) ? "hidden" : "visible";
|
||||
break;
|
||||
case "ErrorString":
|
||||
case "RunString":
|
||||
document.getElementById(key).innerHTML = heater[key];
|
||||
break;
|
||||
case "PumpFixed":
|
||||
case "TempCurrent":
|
||||
document.getElementById(key).innerHTML = parseFloat(heater[key]).toFixed(1);
|
||||
break;
|
||||
case "TempDesired":
|
||||
document.getElementById(key).value = heater[key];
|
||||
var ValKey = key + 'Val'; // eg 'PumpMinVal'
|
||||
document.getElementById(ValKey).innerHTML = heater[key];
|
||||
break;
|
||||
case "ErrorState":
|
||||
document.getElementById("ErrorDiv").hidden = heater[key] <= 1;
|
||||
break;
|
||||
case "TempBody":
|
||||
//The threshold levels for each bar to come on are: 21°C, 41°C, 61°C, 81°C, 101°C, 121°C
|
||||
if(heater[key] > 120){
|
||||
document.getElementById("TopBar").className = "active121";
|
||||
}
|
||||
else if(heater[key] > 100){
|
||||
document.getElementById("TopBar").className = "active101";
|
||||
}
|
||||
else if(heater[key] > 80){
|
||||
document.getElementById("TopBar").className = "active81";
|
||||
}
|
||||
else if(heater[key] > 60){
|
||||
document.getElementById("TopBar").className = "active61";
|
||||
}
|
||||
else if(heater[key] > 40){
|
||||
document.getElementById("TopBar").className = "active41";
|
||||
}
|
||||
else if(heater[key] > 20){
|
||||
document.getElementById("TopBar").className = "active21";
|
||||
}
|
||||
else {
|
||||
document.getElementById("TopBar").className = "active0";
|
||||
}
|
||||
break;
|
||||
case "PumpMin":
|
||||
case "PumpMax":
|
||||
var OneDecimalPlace = parseFloat(heater[key]).toFixed(1);
|
||||
var ValKey = key + 'Val'; // eg 'PumpMinVal'
|
||||
document.getElementById(key).value = OneDecimalPlace;
|
||||
document.getElementById(key).innerHTML = OneDecimalPlace;
|
||||
document.getElementById(ValKey).innerHTML = OneDecimalPlace;
|
||||
break;
|
||||
case "FanMin":
|
||||
case "FanMax":
|
||||
var RPM = heater[key];
|
||||
var ValKey = key + 'Val'; // eg 'FanMinVal'
|
||||
document.getElementById(key).value = RPM;
|
||||
document.getElementById(key).innerHTML = RPM;
|
||||
document.getElementById(ValKey).innerHTML = RPM;
|
||||
break;
|
||||
case "Thermostat":
|
||||
if(heater[key] != 0) {
|
||||
document.getElementById("FixedDiv").hidden = true;
|
||||
document.getElementById("ThermoDiv").hidden = false;
|
||||
}
|
||||
else {
|
||||
document.getElementById("FixedDiv").hidden = false;
|
||||
document.getElementById("ThermoDiv").hidden = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setSchedule(){
|
||||
//clearly need to add some code here to send the Json formatted data to the esp
|
||||
console.log("Set Schedule Button Press")
|
||||
}
|
||||
|
||||
Date.prototype.toDateInputValue = (function() {
|
||||
var local = new Date(this);
|
||||
local.setMinutes(this.getMinutes() - this.getTimezoneOffset());
|
||||
return local.toJSON().slice(0,10);
|
||||
});
|
||||
|
||||
function sendJSONobject(obj){
|
||||
var str = JSON.stringify(obj);
|
||||
console.log("JSON Tx:", str);
|
||||
Socket.send(str);
|
||||
}
|
||||
|
||||
// Scripts for date handling
|
||||
Date.prototype.today = function () {
|
||||
return ((this.getDate() < 10)?"0":"") + this.getDate() +"/"+(((this.getMonth()+1) < 10)?"0":"") + (this.getMonth()+1) +"/"+ this.getFullYear();
|
||||
}
|
||||
|
||||
// Scripts for setting date and time
|
||||
|
||||
function setcurrenttime(){
|
||||
var cmd = {};
|
||||
cmd.Time = document.getElementById("curtime").value;
|
||||
sendJSONobject(cmd);
|
||||
|
||||
|
||||
}
|
||||
|
||||
function setcurrentdate(){
|
||||
var cmd = {};
|
||||
cmd.Date = document.getElementById("curdate").value;
|
||||
sendJSONobject(cmd);
|
||||
|
||||
}
|
||||
|
||||
function funcNavLinks() {
|
||||
var x = document.getElementById("myLinks");
|
||||
if (x.style.display === "block") {
|
||||
x.style.display = "none";
|
||||
} else {
|
||||
x.style.display = "block";
|
||||
}
|
||||
}
|
||||
|
||||
function checkTime(i)
|
||||
{
|
||||
if (i<10)
|
||||
{
|
||||
i="0" + i;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
function funcdispSettings() {
|
||||
document.getElementById("Settings").style.display = "block";
|
||||
currentTime = new Date();
|
||||
var h = currentTime.getHours();
|
||||
var m = currentTime.getMinutes();
|
||||
var s = currentTime.getSeconds();
|
||||
// add a zero in front of numbers<10
|
||||
h = checkTime(h);
|
||||
m = checkTime(m);
|
||||
s = checkTime(s);
|
||||
|
||||
console.log("Hours",h);
|
||||
console.log("Minutes",m);
|
||||
console.log("Seconds",s);
|
||||
document.getElementById("curtime").value = h + ":" + m + ":" + s;
|
||||
document.getElementById("curdate").value = currentTime.today()
|
||||
document.getElementById("Home").style.display = "none";
|
||||
document.getElementById("Advanced").style.display = "none";
|
||||
document.getElementById("myLinks").style.display ="none";
|
||||
document.getElementById('curdate').valueAsDate = new Date();
|
||||
|
||||
|
||||
}
|
||||
|
||||
function funcdispHome(){
|
||||
document.getElementById("Settings").style.display = "none";
|
||||
document.getElementById("Home").style.display = "block";
|
||||
document.getElementById("Advanced").style.display = "none";
|
||||
document.getElementById("myLinks").style.display ="none";
|
||||
|
||||
}
|
||||
|
||||
function funcdispAdvanced(){
|
||||
document.getElementById("Settings").style.display = "none";
|
||||
document.getElementById("Home").style.display = "none";
|
||||
document.getElementById("Advanced").style.display = "block";
|
||||
document.getElementById("myLinks").style.display ="none";
|
||||
}
|
||||
|
||||
// Function to check the power on/off slide switch.
|
||||
function OnOffCheck(){
|
||||
|
||||
// Get the checkbox status and place in the checkbox variable
|
||||
var checkBox = document.getElementById("myonoffswitch");
|
||||
|
||||
// Send a message to the Devel console of web browser for debugging
|
||||
console.log("OnOffCheck:", document.getElementById("myonoffswitch").checked);
|
||||
|
||||
// If the checkbox is checked, display the output text
|
||||
// We also need to send a message back into the esp as we cannot directly run Arduino Functions from within the javascript
|
||||
|
||||
var cmd = {};
|
||||
if (checkBox.checked){
|
||||
//Insert Code Here To Turn On The Heater
|
||||
console.log("Turning On Heater");
|
||||
|
||||
cmd.RunState = 1;
|
||||
sendJSONobject(cmd);
|
||||
}
|
||||
else{
|
||||
//Insert Code Here To Turn Off The Heater
|
||||
console.log("Turning Off Heater");
|
||||
|
||||
cmd.RunState = 0;
|
||||
sendJSONobject(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
function onSlideDone(newVal, JSONKey) {
|
||||
//elementid must equal the JSON name for each setting
|
||||
|
||||
document.getElementById(JSONKey).innerHTML = newVal;
|
||||
|
||||
var cmd = {};
|
||||
cmd[JSONKey] = newVal; // note: variable name needs []
|
||||
cmd.NVsave = 8861; // named variable DOESN'T !!
|
||||
sendJSONobject(cmd);
|
||||
}
|
||||
|
||||
function onSlideUpdate(newVal, JSONKey) {
|
||||
//elementid must equal the JSON name for each setting
|
||||
|
||||
document.getElementById(JSONKey).innerHTML = newVal;
|
||||
}
|
||||
|
||||
function SetPumpMin(){
|
||||
var cmd = {};
|
||||
cmd['PumpMin'] = document.getElementById("PumpMin").value;
|
||||
cmd.NVsave = 8861;
|
||||
sendJSONobject(cmd);
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<meta name="viewport" content="height=device-height, width=device-width, initial-scale=1">
|
||||
<style>
|
||||
|
||||
.throb_me {
|
||||
animation: throbber 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes throbber {
|
||||
50% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.slider {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #ccc;
|
||||
-webkit-transition: .4s;
|
||||
transition: .4s;
|
||||
}
|
||||
|
||||
.slider:before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
height: 26px;
|
||||
width: 26px;
|
||||
left: 4px;
|
||||
bottom: 4px;
|
||||
background-color: white;
|
||||
-webkit-transition: .4s;
|
||||
transition: .4s;
|
||||
}
|
||||
body {
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
.onoffswitch {
|
||||
position: relative; width: 90px;
|
||||
-webkit-user-select:none; -moz-user-select:none; -ms-user-select: none;
|
||||
}
|
||||
.onoffswitch-checkbox {
|
||||
display: none;
|
||||
}
|
||||
.onoffswitch-label {
|
||||
display: block; overflow: hidden; cursor: pointer;
|
||||
border: 2px solid #999999; border-radius: 20px;
|
||||
}
|
||||
.onoffswitch-inner {
|
||||
display: block; width: 200%; margin-left: -100%;
|
||||
transition: margin 0.3s ease-in 0s;
|
||||
}
|
||||
.onoffswitch-inner:before, .onoffswitch-inner:after {
|
||||
display: block; float: left; width: 50%; height: 30px; padding: 0; line-height: 30px;
|
||||
font-size: 14px; color: white; font-family: Trebuchet, Arial, sans-serif; font-weight: bold;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.onoffswitch-inner:before {
|
||||
content: "ON";
|
||||
padding-left: 10px;
|
||||
background-color: #34A7C1; color: #FFFFFF;
|
||||
}
|
||||
.onoffswitch-inner:after {
|
||||
content: "OFF";
|
||||
padding-right: 10px;
|
||||
background-color: #EEEEEE; color: #999999;
|
||||
text-align: right;
|
||||
}
|
||||
.onoffswitch-switch {
|
||||
display: block; width: 18px; margin: 6px;
|
||||
background: #FFFFFF;
|
||||
position: absolute; top: 0; bottom: 0;
|
||||
right: 56px;
|
||||
border: 2px solid #999999; border-radius: 20px;
|
||||
transition: all 0.3s ease-in 0s;
|
||||
}
|
||||
.onoffswitch-checkbox:checked + .onoffswitch-label .onoffswitch-inner {
|
||||
margin-left: 0;
|
||||
}
|
||||
.onoffswitch-checkbox:checked + .onoffswitch-label .onoffswitch-switch {
|
||||
right: 0px;
|
||||
}
|
||||
|
||||
.mobile-container {
|
||||
|
||||
margin: auto;
|
||||
background-color: #555;
|
||||
height: 500px;
|
||||
color: white;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.topnav {
|
||||
overflow: hidden;
|
||||
background-color: #333;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.topnav #myLinks {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.topnav a {
|
||||
color: white;
|
||||
padding: 14px 16px;
|
||||
text-decoration: none;
|
||||
font-size: 17px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.topnav a.icon {
|
||||
background: black;
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.topnav a:hover {
|
||||
background-color: #ddd;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.active0 {
|
||||
background-color: #5e4fa2;
|
||||
color: black;
|
||||
}
|
||||
.active21 {
|
||||
background-color: #427bb1;
|
||||
color: #ffffff;
|
||||
}
|
||||
.active41 {
|
||||
background-color: #36c0a3;
|
||||
color: #ffffff;
|
||||
}
|
||||
.active61 {
|
||||
background-color: #29cf38;
|
||||
color: #000000;
|
||||
}
|
||||
.active81 {
|
||||
background-color: #92df1b;
|
||||
color: #ffffff;
|
||||
}
|
||||
.active101 {
|
||||
background-color: #efab0e;
|
||||
color: #ffffff;
|
||||
}
|
||||
.active121 {
|
||||
background-color: #ff0000;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
input:checked + .slider {
|
||||
background-color: #2196F3;
|
||||
}
|
||||
|
||||
input:focus + .slider {
|
||||
box-shadow: 0 0 1px #2196F3;
|
||||
}
|
||||
|
||||
input:checked + .slider:before {
|
||||
-webkit-transform: translateX(26px);
|
||||
-ms-transform: translateX(26px);
|
||||
transform: translateX(26px);
|
||||
}
|
||||
|
||||
.slider.round {
|
||||
border-radius: 34px;
|
||||
}
|
||||
|
||||
.slider.round:before {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
MainPage {
|
||||
display: block
|
||||
}
|
||||
#Advanced {
|
||||
display: none
|
||||
}
|
||||
#Settings {
|
||||
display: none
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<title>Chinese Diesel Heater Web Controller Interface</title>
|
||||
</head>
|
||||
<body onload="javascript:init()">
|
||||
<div class="mobile-container">
|
||||
|
||||
<!-- Top Navigation Menu -->
|
||||
<div class="topnav">
|
||||
<div id="TopBar" style="padding-left:30px"><a href="javascript:void(0);" onclick="funcdispHome()" >Chinese Diesel Heater Web Control</a></div>
|
||||
<div id="myLinks">
|
||||
<a href="javascript:void(0);" onclick="funcdispHome()">Home</a>
|
||||
<a href="javascript:void(0);" onclick="funcdispSettings()">Settings</a>
|
||||
<a href="javascript:void(0);" onclick="funcdispAdvanced()">Advanced Settings</a>
|
||||
</div>
|
||||
<a href="javascript:void(0);" class="icon" onclick="funcNavLinks()">
|
||||
</i>=
|
||||
</a>
|
||||
</div>
|
||||
<div style="padding-left:16px">
|
||||
<span class="MaingPage" id="Home">
|
||||
<div><H2>Power Control</H2></div>
|
||||
|
||||
<div class="onoffswitch" id="onoffswitch">
|
||||
<input type="checkbox" onclick="OnOffCheck()" name="onoffswitch" class="onoffswitch-checkbox" id="myonoffswitch" clicked>
|
||||
<label class="onoffswitch-label" for="myonoffswitch">
|
||||
<span class="onoffswitch-inner"></span>
|
||||
<span class="onoffswitch-switch"></span>
|
||||
</label>
|
||||
</div>
|
||||
<span class="throb_me" id="RunString" style="visibility:hidden"></span>
|
||||
|
||||
<div>
|
||||
<h2>Temperature Control</h2>
|
||||
</div>
|
||||
<input type="range" id="TempDesired" min="8" max="35" step="1" value="22" oninput="onSlideUpdate(this.value, 'TempDesiredVal')" onchange="onSlideDone(this.value, 'TempDesired')">
|
||||
<div id="ThermoDiv">
|
||||
<b>Desired Temp: </b> <span id="TempDesiredVal"></span>
|
||||
</div>
|
||||
<div id="FixedDiv">
|
||||
<b>Fixed Hz: </b>
|
||||
<span id="PumpFixed"></span>
|
||||
</div>
|
||||
<div>
|
||||
<b>Current Temp: </b><span id="TempCurrent">
|
||||
</div>
|
||||
<div id="ErrorDiv" style="color:crimson" hidden>
|
||||
<b>Error <span id="ErrorString"> </b>
|
||||
</div>
|
||||
</span>
|
||||
|
||||
<div id="Advanced">
|
||||
<h2><b>Advanced Settings</b></h2>
|
||||
<br>
|
||||
<h3><b>Minimum Fuel Settings</b></h3>
|
||||
<div>
|
||||
<b>Pump Min: </b><span id="PumpMinVal"> </span>
|
||||
<input type="range" id="PumpMin" min="1" max="10" step=".1" oninput="onSlideUpdate(parseFloat(this.value).toFixed(1), 'PumpMinVal')" onchange="onSlideDone(this.value, 'PumpMin')">
|
||||
</div>
|
||||
<div>
|
||||
<b>Fan Min: </b><span id="FanMinVal"> </span>
|
||||
<input type="range" id="FanMin" min="1000" max="5000" step="10" oninput="onSlideUpdate(this.value, 'FanMinVal')" onchange="onSlideDone(this.value, 'FanMin')">
|
||||
</div>
|
||||
<br>
|
||||
<h3><b>Maximum Fuel Settings</b></h3>
|
||||
<div>
|
||||
<b>Pump Max: </b><span id="PumpMaxVal"> </span>
|
||||
<input type="range" id="PumpMax" min=".5" max="10" step=".1" oninput="onSlideUpdate(parseFloat(this.value).toFixed(1), 'PumpMaxVal')" onchange="onSlideDone(this.value, 'PumpMax')">
|
||||
</div>
|
||||
<div>
|
||||
<b>Fan Max: </b><span id="FanMaxVal"> </span>
|
||||
<input type="range" id="FanMax" min="1000" max="5000" step="10" oninput="onSlideUpdate(this.value, 'FanMaxVal')" onchange="onSlideDone(this.value, 'FanMax')">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<Div id="Settings">
|
||||
Current Date:<br>
|
||||
<input type="date" id="curdate"><input type="button" Value="Set Date" onclick="setcurrentdate()">
|
||||
|
||||
<br>
|
||||
Current Time (24 Hour Format):<br>
|
||||
<input type="time" id="curtime"> <input type="button" Value="Set Time" onclick="setcurrenttime()">
|
||||
|
||||
<hr></hr>
|
||||
<br><br>
|
||||
Timer1: <input type="checkbox" border-radius="4px" name="Timer" id="Timer1onoff"> <input type="text" class="schedule" id="Timer1Start"> <input type="text" id="Timer1End"> <br>
|
||||
Timer2: <input type="checkbox" border-radius="4px" name="Tue"> <input type="text" class="schedule" id="Timer2Start"> <input type="text" id="Timer2End"><br>
|
||||
<input type="button" Value="Save Schedule" onclick="setSchedule()">
|
||||
</Div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,102 +0,0 @@
|
|||
1249177ms [BTC] 76 16 00 11 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 13 74
|
||||
+21ms [HTR] 8B 1D 76 16 00 00 00 84 00 00 00 84 00 2F 00 00 00 00 00 08 00 1A 64 00 verifyCRC FAILED: calc:E388 data:6400
|
||||
Bluetooth data not sent, CRC error
|
||||
1250198ms [BTC] 76 16 00 11 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 13 74
|
||||
+23ms [HTR] 8B 1D 76 16 00 00 00 84 00 00 00 84 00 2F 00 00 00 00 00 08 00 1A 64 00 verifyCRC FAILED: calc:E388 data:6400
|
||||
Bluetooth data not sent, CRC error
|
||||
|
||||
*** SWITCHED INTO VERBOSE MODE ****
|
||||
|
||||
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
|
||||
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
|
||||
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
|
||||
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
|
||||
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
|
||||
:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5
|
||||
1251221ms [BTC] 76 16 00 11 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 13 74 :6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6
|
||||
dT{16}:6,RD(8B)
|
||||
dT{1}:6,RD(1D)
|
||||
dT{1}:6,RD(76) <<<<<<<<<<<<<<<<<<<<<<<<<< THIS SHOULD BE FIRST RX BYTE!!!!
|
||||
dT{1}:6,RD(16)
|
||||
dT{1}:6,RD(0)
|
||||
dT{2}:6,RD(0)
|
||||
dT{1}:6,RD(0)
|
||||
dT{1}:6,RD(84)
|
||||
dT{1}:6,RD(0)
|
||||
dT{1}:6,RD(0)
|
||||
dT{1}:6,RD(0)
|
||||
dT{1}:6,RD(84)
|
||||
dT{2}:6,RD(0)
|
||||
dT{1}:6,RD(2F)
|
||||
dT{1}:6,RD(0)
|
||||
dT{1}:6,RD(0)
|
||||
dT{1}:6,RD(0)
|
||||
dT{1}:6,RD(0)
|
||||
dT{2}:6,RD(0)
|
||||
dT{1}:6,RD(8)
|
||||
dT{1}:6,RD(0)
|
||||
dT{1}:6,RD(1A)
|
||||
dT{1}:6,RD(64)
|
||||
dT{1}:6,RD(0)
|
||||
:7 +48ms [HTR] 8B 1D 76 16 00 00 00 84 00 00 00 84 00 2F 00 00 00 00 00 08 00 1A 64 00 verifyCRC FAILED: calc:E388 data:6400
|
||||
Bluetooth data not sent, CRC error
|
||||
:8
|
||||
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
|
||||
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
|
||||
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
|
||||
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
|
||||
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
|
||||
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
|
||||
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
|
||||
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
|
||||
|
||||
8< (lots of state :0 snipped)
|
||||
|
||||
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
|
||||
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
|
||||
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
|
||||
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
|
||||
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
|
||||
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
|
||||
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
|
||||
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
|
||||
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
|
||||
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
|
||||
:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5
|
||||
:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5
|
||||
:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5:5
|
||||
:5:5:5:5:5:5:5:5:5:5
|
||||
1252268ms [BTC] 76 16 00 11 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 13 74
|
||||
:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6:6
|
||||
dT{16}:6,RD(8B)
|
||||
dT{1}:6,RD(1D)
|
||||
dT{1}:6,RD(76) <<<<<<<<<<<<<<<<<<<<<<<<<< THIS SHOULD BE FIRST RX BYTE!!!!
|
||||
dT{2}:6,RD(16)
|
||||
dT{1}:6,RD(0)
|
||||
dT{1}:6,RD(0)
|
||||
dT{1}:6,RD(0)
|
||||
dT{1}:6,RD(84)
|
||||
dT{1}:6,RD(0)
|
||||
dT{2}:6,RD(0)
|
||||
dT{1}:6,RD(0)
|
||||
dT{1}:6,RD(84)
|
||||
dT{1}:6,RD(0)
|
||||
dT{1}:6,RD(2F)
|
||||
dT{1}:6,RD(0)
|
||||
dT{2}:6,RD(0)
|
||||
dT{1}:6,RD(0)
|
||||
dT{1}:6,RD(0)
|
||||
dT{1}:6,RD(0)
|
||||
dT{1}:6,RD(8)
|
||||
dT{1}:6,RD(0)
|
||||
dT{1}:6,RD(1A)
|
||||
dT{2}:6,RD(64)
|
||||
dT{1}:6,RD(0):7
|
||||
+49ms [HTR] 8B 1D 76 16 00 00 00 84 00 00 00 84 00 2F 00 00 00 00 00 08 00 1A 64 00 verifyCRC FAILED: calc:E388 data:6400
|
||||
Bluetooth data not sent, CRC error
|
||||
:8
|
||||
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
|
||||
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
|
||||
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
|
||||
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
|
||||
:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
|
|
@ -1,117 +0,0 @@
|
|||
Start updating sketch
|
||||
Progress: 100%
|
||||
End
|
||||
*WM: [1] AutoConnect
|
||||
*WM: [2] ESP32 event handler enabled
|
||||
*WM: [2] Connecting as wifi client...
|
||||
*WM: [2] setSTAConfig static ip not set
|
||||
*WM: [3] WIFI station disconnect
|
||||
*WM: [1] Connecting to saved AP: WigginsCorner
|
||||
*WM: [3] WiFi station enable
|
||||
*WM: [1] connectTimeout not set, ESP waitForConnectResult...
|
||||
*WM: [2] [EVENT] 4
|
||||
*WM: [2] [EVENT] 7
|
||||
*WM: [2] Connection result: WL_CONNECTED
|
||||
*WM: [3] lastconxresult: WL_CONNECTED
|
||||
*WM: [1] AutoConnect: SUCCESS
|
||||
*WM: [1] STA IP Address: 192.168.0.101
|
||||
connected...yeey :)
|
||||
Ready
|
||||
IP address: 192.168.0.101
|
||||
|
||||
|
||||
Attempting to detect HC-05 Bluetooth module...
|
||||
@ 9600 baud... OK.
|
||||
|
||||
HC-05 found
|
||||
Setting Name to "Diesel Heater"... OK
|
||||
Setting baud rate to 9600N81...OK
|
||||
|
||||
2313ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +22ms [HTR] 76 16 00 08 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 0B DE
|
||||
3335ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +22ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
4357ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
5380ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +24ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
6404ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
7427ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
8451ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
9474ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
10498ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
11521ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
12545ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
13568ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +24ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
14592ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
15615ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +24ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
16639ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
17662ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +24ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
18686ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
19709ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
20732ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +24ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
21756ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
22780ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
23803ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
24827ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
25850ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
26873ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
27897ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
28920ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 07 6C 2F 66 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
29944ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
30967ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +24ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
31991ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
33014ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +24ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
34038ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
35061ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
36084ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +24ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
37108ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
38131ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
39155ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
40178ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
41202ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
42225ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
43249ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
44272ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +24ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
45296ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
46319ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
47342ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +24ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
48366ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +24ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
49390ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
50413ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
51436ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +24ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
52460ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
53484ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
54507ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +24ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
55531ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
56555ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
57578ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
58602ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
59625ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
60649ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +22ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
61671ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +24ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
62695ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
63718ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +24ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
64742ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
65765ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
66788ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +24ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
67812ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
68836ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
69859ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
70882ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
71906ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
72929ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
73952ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +24ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
74976ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +24ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
76000ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 +23ms [HTR] 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A 3C
|
||||
77023ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 Timeout collecting BTC heater response data, returning to Idle State
|
||||
78047ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 verifyCRC FAILED: calc:AE26 data:6A
|
||||
+23ms [HTR] 3C 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A verifyCRC FAILED: calc:AE26 data:6A
|
||||
Bluetooth data not sent, CRC error
|
||||
79070ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 verifyCRC FAILED: calc:AE26 data:6A
|
||||
+23ms [HTR] 3C 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A verifyCRC FAILED: calc:AE26 data:6A
|
||||
Bluetooth data not sent, CRC error
|
||||
80093ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 verifyCRC FAILED: calc:AE26 data:6A
|
||||
+24ms [HTR] 3C 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A verifyCRC FAILED: calc:AE26 data:6A
|
||||
Bluetooth data not sent, CRC error
|
||||
81117ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 verifyCRC FAILED: calc:AE26 data:6A
|
||||
+23ms [HTR] 3C 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A verifyCRC FAILED: calc:AE26 data:6A
|
||||
Bluetooth data not sent, CRC error
|
||||
82140ms [BTC] 76 16 00 16 17 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC DF 60 verifyCRC FAILED: calc:AE26 data:6A
|
||||
+23ms [HTR] 3C 76 16 00 00 00 90 00 00 00 90 00 0B 00 00 00 00 00 08 00 1C 64 00 6A verifyCRC FAILED: calc:AE26 data:6A
|
|
@ -1,46 +0,0 @@
|
|||
1174404ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30
|
||||
+22ms [HTR] 76 16 00 00 00 85 00 00 00 85 00 2F 00 00 00 00 00 08 00 1A 64 00 9A 4E
|
||||
1175426ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30
|
||||
+22ms [HTR] 76 16 00 00 00 84 00 00 00 84 00 2F 00 00 00 00 00 08 00 1A 64 00 8B 1D
|
||||
1176448ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30
|
||||
+23ms [HTR] 76 16 00 00 00 84 00 00 00 84 00 2F 00 00 00 00 00 08 00 1A 64 00 8B 1D
|
||||
1177471ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30
|
||||
+22ms [HTR] 76 16 00 00 00 85 00 00 00 85 00 2F 00 00 00 00 00 08 00 1A 64 00 9A 4E
|
||||
1178493ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30
|
||||
+21ms [HTR] 76 16 00 00 00 85 00 00 00 85 00 2F 00 00 00 00 00 08 00 1A 64 00 9A 4E
|
||||
1179515ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30
|
||||
+22ms [HTR] 76 16 00 00 00 84 00 00 00 84 00 2F 00 00 00 00 00 08 00 1A 64 00 8B 1D
|
||||
1180537ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30
|
||||
+22ms [HTR] 76 16 00 00 00 85 00 00 00 85 00 2F 00 00 00 00 00 08 00 1A 64 00 9A 4E
|
||||
1181559ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30
|
||||
+23ms [HTR] 76 16 00 00 00 84 00 00 00 84 00 2F 00 00 00 00 00 08 00 1A 64 00 8B 1D
|
||||
1182583ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30 Timeout collecting BTC heater response data, returning to Idle State
|
||||
1183588ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30
|
||||
+22ms [HTR] 76 16 00 00 00 84 00 00 00 84 00 2F 00 00 00 00 00 08 00 1A 64 00 8B 1D
|
||||
1184611ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30
|
||||
+21ms [HTR] 76 16 00 00 00 85 00 00 00 85 00 2F 00 00 00 00 00 08 00 1A 64 00 9A 4E
|
||||
1185632ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30
|
||||
+22ms [HTR] 76 16 00 00 00 84 00 00 00 84 00 2F 00 00 00 00 00 08 00 1A 64 00 8B 1D
|
||||
1186654ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30 Timeout collecting BTC heater response data, returning to Idle State
|
||||
1187676ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30
|
||||
+22ms [HTR] 1D 76 16 00 00 00 84 00 00 00 84 00 2F 00 00 00 00 00 08 00 1A 64 00 8B verifyCRC FAILED: calc:58A8 data:8B
|
||||
Bluetooth data not sent, CRC error
|
||||
1188699ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30
|
||||
+22ms [HTR] 1D 76 16 00 00 00 85 00 00 00 85 00 2F 00 00 00 00 00 08 00 1A 64 00 9A verifyCRC FAILED: calc:B94 data:9A
|
||||
Bluetooth data not sent, CRC error
|
||||
1189721ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30
|
||||
+22ms [HTR] 4E 76 16 00 00 00 85 00 00 00 85 00 2F 00 00 00 00 00 08 00 1A 64 00 9A verifyCRC FAILED: calc:27B2 data:9A
|
||||
Bluetooth data not sent, CRC error
|
||||
1190743ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30
|
||||
+22ms [HTR] 4E 76 16 00 00 00 84 00 00 00 84 00 2F 00 00 00 00 00 08 00 1A 64 00 8B verifyCRC FAILED: calc:748E data:8B
|
||||
Bluetooth data not sent, CRC error
|
||||
1191765ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30
|
||||
+22ms [HTR] 1D 76 16 00 00 00 84 00 00 00 84 00 2F 00 00 00 00 00 08 00 1A 64 00 8B verifyCRC FAILED: calc:58A8 data:8B
|
||||
Bluetooth data not sent, CRC error
|
||||
1192788ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30
|
||||
+21ms [HTR] 1D 76 16 00 00 00 85 00 00 00 85 00 2F 00 00 00 00 00 08 00 1A 64 00 9A verifyCRC FAILED: calc:B94 data:9A
|
||||
Bluetooth data not sent, CRC error
|
||||
1193810ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30
|
||||
+23ms [HTR] 4E 76 16 00 00 00 84 00 00 00 84 00 2F 00 00 00 00 00 08 00 1A 64 00 8B verifyCRC FAILED: calc:748E data:8B
|
||||
Bluetooth data not sent, CRC error
|
||||
1194833ms [BTC] 76 16 00 12 15 0E 28 05 DC 11 94 78 01 32 08 23 05 00 01 2C 0D AC 57 30 Timeout collecting BTC heater response data, returning to Idle State
|
|
@ -1,786 +0,0 @@
|
|||
[Starting] Opening the serial port - COM9
|
||||
oad:0x3fff0018,len:4
|
||||
l<EFBFBD><EFBFBD><EFBFBD><EFBFBD>fff001c,len:952
|
||||
load:0x40078000,len:6084
|
||||
load:0x40080000,len:7936
|
||||
entry 0x40080310
|
||||
[Info] Opened the serial port - COM9
|
||||
1046[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
1086[HTR] 76 16 00 00 00 8A 00 00 00 8A 00 11 00 00 00 00 00 08 00 1B 64 00 4E F5
|
||||
No Bluetooth client
|
||||
Free heap 96224
|
||||
2070[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
2110[HTR] 76 16 00 00 00 8A 00 00 00 8A 00 10 00 00 00 00 00 08 00 1B 64 00 B2 F1
|
||||
No Bluetooth client
|
||||
Free heap 96224
|
||||
3093[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
3133[HTR] 76 16 00 00 00 8A 00 00 00 8A 00 11 00 00 00 00 00 08 00 1B 64 00 4E F5
|
||||
No Bluetooth client
|
||||
Free heap 96224
|
||||
4113[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
4153[HTR] 76 16 00 00 00 8A 00 00 00 8A 00 11 00 00 00 00 00 08 00 1B 64 00 4E F5
|
||||
No Bluetooth client
|
||||
Free heap 96224
|
||||
5132[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
5172[HTR] 76 16 00 00 00 8A 00 00 00 8A 00 11 00 00 00 00 00 08 00 1B 64 00 4E F5
|
||||
No Bluetooth client
|
||||
Free heap 96224
|
||||
6155[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
6195[HTR] 76 16 00 00 00 8A 00 00 00 8A 00 11 00 00 00 00 00 08 00 1B 64 00 4E F5
|
||||
No Bluetooth client
|
||||
Free heap 96224
|
||||
7179[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
7219[HTR] 76 16 00 00 00 8B 00 00 00 8B 00 10 00 00 00 00 00 08 00 1B 64 00 A3 A2
|
||||
No Bluetooth client
|
||||
Free heap 96224
|
||||
8202[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
8242[HTR] 76 16 00 00 00 8A 00 00 00 8A 00 10 00 00 00 00 00 08 00 1B 64 00 B2 F1
|
||||
No Bluetooth client
|
||||
Free heap 96224
|
||||
9222[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
9262[HTR] 76 16 00 00 00 8B 00 00 00 8B 00 11 00 00 00 00 00 08 00 1B 64 00 5F A6
|
||||
No Bluetooth client
|
||||
Free heap 96224
|
||||
10245[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
10285[HTR] 76 16 00 00 00 8B 00 00 00 8B 00 11 00 00 00 00 00 08 00 1B 64 00 5F A6
|
||||
No Bluetooth client
|
||||
Free heap 96224
|
||||
11265[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
11305[HTR] 76 16 00 00 00 8A 00 00 00 8A 00 11 00 00 00 00 00 08 00 1B 64 00 4E F5
|
||||
No Bluetooth client
|
||||
Free heap 96224
|
||||
12289[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
12329[HTR] 76 16 00 00 00 8A 00 00 00 8A 00 11 00 00 00 00 00 08 00 1B 64 00 4E F5
|
||||
No Bluetooth client
|
||||
Free heap 96224
|
||||
13308[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
13348[HTR] 76 16 00 00 00 8A 00 00 00 8A 00 11 00 00 00 00 00 08 00 1B 64 00 4E F5
|
||||
No Bluetooth client
|
||||
Free heap 96224
|
||||
14331[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
14371[HTR] 76 16 00 00 00 8A 00 00 00 8A 00 11 00 00 00 00 00 08 00 1B 64 00 4E F5
|
||||
No Bluetooth client
|
||||
Free heap 96224
|
||||
15354[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
15394[HTR] 76 16 00 00 00 8A 00 00 00 8A 00 11 00 00 00 00 00 08 00 1B 64 00 4E F5
|
||||
No Bluetooth client
|
||||
Free heap 96224
|
||||
16378[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
16418[HTR] 76 16 00 00 00 8A 00 00 00 8A 00 11 00 00 00 00 00 08 00 1B 64 00 4E F5
|
||||
No Bluetooth client
|
||||
Free heap 96224
|
||||
17401[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
17441[HTR] 76 16 00 00 00 8A 00 00 00 8A 00 11 00 00 00 00 00 08 00 1B 64 00 4E F5
|
||||
No Bluetooth client
|
||||
Free heap 96224
|
||||
18425[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
18465[HTR] 76 16 00 00 00 8A 00 00 00 8A 00 11 00 00 00 00 00 08 00 1B 64 00 4E F5
|
||||
No Bluetooth client
|
||||
Free heap 96224
|
||||
19445[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
19485[HTR] 76 16 00 00 00 8A 00 00 00 8A 00 11 00 00 00 00 00 08 00 1B 64 00 4E F5
|
||||
No Bluetooth client
|
||||
Free heap 96224
|
||||
20468[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
20508[HTR] 76 16 00 00 00 8A 00 00 00 8A 00 11 00 00 00 00 00 08 00 1B 64 00 4E F5
|
||||
No Bluetooth client
|
||||
Free heap 96224
|
||||
21488[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
21528[HTR] 76 16 00 00 00 8A 00 00 00 8A 00 10 00 00 00 00 00 08 00 1B 64 00 B2 F1
|
||||
No Bluetooth client
|
||||
Free heap 96224
|
||||
22508[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
22558[HTR] 76 16 00 00 00 8A 00 00 00 8A 00 11 00 00 00 00 00 08 00 1B 64 00 4E F5
|
||||
Free heap 92384
|
||||
[CMD]degC19
|
||||
Command decode: degC = 19
|
||||
[CMD]save
|
||||
Command decode: NV save
|
||||
[CMD]degC19
|
||||
Command decode: degC = 19
|
||||
[CMD]save
|
||||
Command decode: NV save
|
||||
23531[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
23581[HTR] 76 16 00 00 00 8A 00 00 00 8A 00 10 00 00 00 00 00 08 00 1B 64 00 B2 F1
|
||||
Free heap 92384
|
||||
[CMD]degC19
|
||||
Command decode: degC = 19
|
||||
[CMD]save
|
||||
Command decode: NV save
|
||||
24550[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
24600[HTR] 76 16 00 00 00 8A 00 00 00 8A 00 11 00 00 00 00 00 08 00 1B 64 00 4E F5
|
||||
Free heap 92384
|
||||
25573[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
25623[HTR] 76 16 00 00 00 8A 00 00 00 8A 00 11 00 00 00 00 00 08 00 1B 64 00 4E F5
|
||||
Free heap 92384
|
||||
26598[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
26648[HTR] 76 16 00 00 00 8A 00 00 00 8A 00 11 00 00 00 00 00 08 00 1B 64 00 4E F5
|
||||
Free heap 92384
|
||||
27620[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
27670[HTR] 76 16 00 00 00 8B 00 00 00 8B 00 10 00 00 00 00 00 08 00 1B 64 00 A3 A2
|
||||
Free heap 92384
|
||||
28643[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
28693[HTR] 76 16 00 00 00 8A 00 00 00 8A 00 10 00 00 00 00 00 08 00 1B 64 00 B2 F1
|
||||
Free heap 92384
|
||||
29667[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
29717[HTR] 76 16 00 00 00 8A 00 00 00 8A 00 11 00 00 00 00 00 08 00 1B 64 00 4E F5
|
||||
Free heap 92384
|
||||
[CMD]ON
|
||||
Command decode: Heater ON
|
||||
30691[BTC] 76 16 A0 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC E1 57
|
||||
30741[HTR] 76 16 01 00 00 8B 00 00 00 53 00 11 00 00 00 00 00 00 00 1B 64 00 96 5A
|
||||
Free heap 92384
|
||||
31712[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
31762[HTR] 76 16 02 01 00 8A 00 00 00 0A 00 10 00 02 00 5F 00 00 00 1B 64 00 C9 1D
|
||||
Free heap 92384
|
||||
32733[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
32783[HTR] 76 16 02 01 00 89 00 00 00 0B 00 10 00 04 00 B7 00 00 00 1B 64 00 16 AC
|
||||
Free heap 92384
|
||||
33753[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
33803[HTR] 76 16 02 01 00 89 00 00 00 0E 00 10 00 07 01 0E 00 00 00 1B 64 00 E4 5D
|
||||
Free heap 92384
|
||||
34777[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
34827[HTR] 76 16 02 01 00 89 00 00 00 11 00 10 00 09 01 62 00 00 00 1B 64 00 1D 97
|
||||
Free heap 92384
|
||||
35800[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
35850[HTR] 76 16 02 01 00 89 00 50 00 14 00 10 00 0A 01 86 00 00 00 1B 64 00 DA 7B
|
||||
Free heap 92384
|
||||
36822[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
36872[HTR] 76 16 02 01 00 89 00 C8 00 17 00 10 00 0B 01 C5 00 00 00 1B 64 00 27 99
|
||||
Free heap 92384
|
||||
37845[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
37895[HTR] 76 16 02 01 00 89 01 C2 00 1A 00 10 00 0E 02 21 00 00 00 1B 64 00 B6 1A
|
||||
Free heap 92384
|
||||
38867[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
38917[HTR] 76 16 02 01 00 89 02 80 00 1C 00 10 00 0F 02 41 00 00 00 1B 64 00 26 FC
|
||||
Free heap 92384
|
||||
39889[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
39939[HTR] 76 16 02 01 00 88 03 D4 00 1D 00 10 00 12 02 80 00 00 00 1B 64 00 04 7F
|
||||
Free heap 92384
|
||||
40912[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
40962[HTR] 76 16 02 01 00 88 04 CE 00 20 00 10 00 14 02 C0 00 00 00 1B 64 00 E4 9F
|
||||
Free heap 92384
|
||||
41935[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
41985[HTR] 76 16 02 01 00 88 06 04 00 20 00 10 00 16 02 EC 00 00 00 1B 64 00 70 A0
|
||||
Free heap 92384
|
||||
42958[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
43008[HTR] 76 16 02 01 00 88 06 9A 00 20 00 10 00 17 02 F8 00 00 00 1B 64 00 89 E7
|
||||
Free heap 92384
|
||||
43981[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
44031[HTR] 76 16 02 01 00 88 07 3A 00 20 00 10 00 1A 03 23 00 00 00 1B 64 00 30 74
|
||||
Free heap 92384
|
||||
45005[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
45055[HTR] 76 16 02 01 00 88 07 80 00 20 00 10 00 1C 03 43 00 00 00 1B 64 00 E5 05
|
||||
Free heap 92384
|
||||
46029[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
46079[HTR] 76 16 02 01 00 88 07 B2 00 1E 00 10 00 1E 03 5F 00 00 00 1B 64 00 2F 24
|
||||
Free heap 92384
|
||||
47052[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
47102[HTR] 76 16 02 01 00 87 07 B2 00 1A 00 10 00 1F 03 5F 00 00 00 1B 64 00 C8 12
|
||||
Free heap 92384
|
||||
48076[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
48126[HTR] 76 16 02 01 00 87 07 80 00 19 00 10 00 21 03 77 00 00 00 1B 64 00 7D 15
|
||||
Free heap 92384
|
||||
49100[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
49150[HTR] 76 16 02 01 00 87 07 26 00 18 00 10 00 23 03 8F 00 00 00 1B 64 00 29 51
|
||||
Free heap 92384
|
||||
50120[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
50170[HTR] 76 16 02 01 00 87 06 E0 00 18 00 10 00 25 03 9F 00 00 00 1B 64 00 8A EC
|
||||
Free heap 92384
|
||||
51144[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
51194[HTR] 76 16 02 01 00 87 06 7C 00 18 00 10 00 28 03 B3 00 00 00 1B 64 00 B1 C5
|
||||
Free heap 92384
|
||||
52163[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
52213[HTR] 76 16 02 01 00 87 06 36 00 18 00 10 00 2A 03 C7 00 00 00 1B 64 00 E1 22
|
||||
Free heap 92384
|
||||
53185[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
53235[HTR] 76 16 02 01 00 87 05 E6 00 19 00 10 00 2C 03 CF 00 00 00 1B 64 00 AD 12
|
||||
Free heap 92384
|
||||
54207[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
54257[HTR] 76 16 02 01 00 87 05 C8 00 18 00 10 00 2D 03 C3 00 00 00 1B 64 00 A0 7F
|
||||
Free heap 92384
|
||||
55229[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
55279[HTR] 76 16 02 01 00 87 05 A0 00 19 00 10 00 2F 03 CF 00 00 00 1B 64 00 6F C0
|
||||
Free heap 92384
|
||||
56249[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
56299[HTR] 76 16 02 01 00 86 05 8C 00 18 00 10 00 32 03 D3 00 00 00 1B 64 00 F2 F7
|
||||
Free heap 92384
|
||||
57272[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
57322[HTR] 76 16 02 01 00 86 05 8C 00 18 00 10 00 33 03 DF 00 00 00 1B 64 00 62 36
|
||||
Free heap 92384
|
||||
58292[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
58342[HTR] 76 16 02 01 00 86 05 8C 00 18 00 10 00 35 03 D3 00 00 00 1B 64 00 C2 D1
|
||||
Free heap 92384
|
||||
59315[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
59365[HTR] 76 16 02 01 00 86 05 8C 00 19 00 10 00 37 03 DF 00 00 00 1B 64 00 23 06
|
||||
Free heap 92384
|
||||
60335[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
60385[HTR] 76 16 02 01 00 86 05 8C 00 19 00 10 00 39 03 DB 00 00 00 1B 64 00 83 0F
|
||||
Free heap 92384
|
||||
61355[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
61405[HTR] 76 16 02 01 00 85 05 8C 00 18 00 10 00 3B 03 E6 00 00 00 1B 64 00 51 08
|
||||
Free heap 92384
|
||||
62379[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
62429[HTR] 76 16 02 01 00 85 05 96 00 19 00 10 00 3D 03 DF 00 00 00 1B 64 00 78 12
|
||||
Free heap 92384
|
||||
63398[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
63448[HTR] 76 16 02 01 00 85 05 8C 00 19 00 10 00 3F 03 DF 00 00 00 1B 64 00 13 91
|
||||
Free heap 92384
|
||||
64418[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
64468[HTR] 76 16 02 01 00 85 05 96 00 19 00 10 00 41 03 E6 00 00 00 1B 64 00 B9 8B
|
||||
Free heap 92384
|
||||
65441[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
65491[HTR] 76 16 02 01 00 85 05 8C 00 1A 00 10 00 42 03 DF 00 00 00 1B 64 00 82 A9
|
||||
Free heap 92384
|
||||
66462[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
66512[HTR] 76 16 02 01 00 85 05 96 00 1A 00 10 00 44 03 E6 00 00 00 1B 64 00 2A B1
|
||||
Free heap 92384
|
||||
67485[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
67535[HTR] 76 16 02 01 00 84 05 96 00 19 00 11 00 47 03 EA 00 00 00 1B 64 00 75 39
|
||||
Free heap 92384
|
||||
68508[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
68558[HTR] 76 16 02 01 00 84 05 A0 00 1A 00 10 00 49 03 F6 00 00 00 1B 64 00 FD 1F
|
||||
Free heap 92384
|
||||
69530[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
69580[HTR] 76 16 02 01 00 84 05 AA 00 1A 00 11 00 4A 03 EE 00 00 00 1B 64 00 F7 1D
|
||||
Free heap 92384
|
||||
70552[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
70602[HTR] 76 16 02 01 00 84 05 AA 00 1A 00 10 00 4C 03 F2 00 00 00 1B 64 00 6A EF
|
||||
Free heap 92384
|
||||
71574[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
71624[HTR] 76 16 02 01 00 83 05 B4 00 19 00 11 00 4F 03 FA 00 00 00 1B 64 00 5C 5F
|
||||
Free heap 92384
|
||||
72597[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
72647[HTR] 76 16 02 01 00 83 05 B4 00 1A 00 10 00 51 04 06 00 00 00 1B 64 00 2A A2
|
||||
Free heap 92384
|
||||
73621[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
73671[HTR] 76 16 02 01 00 83 05 BE 00 1A 00 10 00 52 03 FE 00 00 00 1B 64 00 F4 04
|
||||
Free heap 92384
|
||||
74644[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
74694[HTR] 76 16 02 01 00 83 05 BE 00 1A 00 10 00 54 04 06 00 00 00 1B 64 00 7D 17
|
||||
Free heap 92384
|
||||
75667[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
75717[HTR] 76 16 02 01 00 83 05 BE 00 1B 00 11 00 56 04 06 00 00 00 1B 64 00 60 08
|
||||
Free heap 92384
|
||||
76690[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
76740[HTR] 76 16 02 01 00 82 05 BE 00 1A 00 10 00 58 04 12 00 00 00 1B 64 00 EC 47
|
||||
Free heap 92384
|
||||
77712[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
77762[HTR] 76 16 02 01 00 82 05 C8 00 1A 00 10 00 58 04 06 00 00 00 1B 64 00 CB E5
|
||||
Free heap 92384
|
||||
78735[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
78785[HTR] 76 16 02 01 00 82 05 C8 00 1A 00 10 00 58 03 FA 00 00 00 1B 64 00 22 98
|
||||
Free heap 92384
|
||||
79756[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
79806[HTR] 76 16 02 01 00 82 05 D2 00 1A 00 10 00 59 03 F6 00 00 00 1B 64 00 B9 C3
|
||||
Free heap 92384
|
||||
80779[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
80829[HTR] 76 16 02 01 00 82 05 D2 00 1A 00 10 00 59 03 EE 00 00 00 1B 64 00 B8 5B
|
||||
Free heap 92384
|
||||
81803[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
81853[HTR] 76 16 02 01 00 83 05 D2 00 1C 00 10 00 59 03 E6 00 00 00 1B 64 00 2E 8A
|
||||
Free heap 92384
|
||||
82822[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
82872[HTR] 76 16 02 01 00 82 05 DC 00 1A 00 11 00 59 03 DF 00 00 00 1B 64 00 83 F1
|
||||
Free heap 92384
|
||||
83845[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
83895[HTR] 76 16 02 01 00 82 05 DC 00 1A 00 10 00 59 03 DB 00 00 00 1B 64 00 BF B0
|
||||
Free heap 92384
|
||||
84867[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
84917[HTR] 76 16 02 01 00 83 05 DC 00 1A 00 10 00 59 03 D3 00 00 00 1B 64 00 EF 68
|
||||
Free heap 92384
|
||||
85888[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
85938[HTR] 76 16 02 01 00 83 05 DC 00 1B 00 11 00 59 03 D7 00 00 00 1B 64 00 52 2B
|
||||
Free heap 92384
|
||||
86910[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
86960[HTR] 76 16 02 01 00 83 05 E6 00 1B 00 10 00 59 03 CF 00 00 00 1B 64 00 BC 0D
|
||||
Free heap 92384
|
||||
87933[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
87983[HTR] 76 16 02 01 00 83 05 E6 00 1B 00 10 00 59 03 CF 00 00 00 1B 64 00 BC 0D
|
||||
Free heap 92384
|
||||
88956[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
89006[HTR] 76 16 02 01 00 83 05 E6 00 1B 00 11 00 59 03 CB 00 00 00 1B 64 00 80 4C
|
||||
Free heap 92384
|
||||
89979[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
90029[HTR] 76 16 02 01 00 83 05 E6 00 1B 00 10 00 59 03 C7 00 00 00 1B 64 00 7C 84
|
||||
Free heap 92384
|
||||
91002[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
91052[HTR] 76 16 02 01 00 83 05 E6 00 1A 00 11 00 59 03 C3 00 00 00 1B 64 00 C1 C7
|
||||
Free heap 92384
|
||||
92024[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
92074[HTR] 76 16 02 01 00 83 05 E6 00 1A 00 11 00 59 03 C3 00 00 00 1B 64 00 C1 C7
|
||||
Free heap 92384
|
||||
93047[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
93097[HTR] 76 16 02 01 00 83 05 DC 00 1A 00 11 00 59 03 BF 00 00 00 1B 64 00 15 C0
|
||||
Free heap 92384
|
||||
94070[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
94120[HTR] 76 16 02 01 00 83 05 DC 00 1D 00 11 00 59 03 BF 00 00 00 1B 64 00 52 CB
|
||||
Free heap 92384
|
||||
95094[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
95144[HTR] 76 16 02 01 00 83 05 D2 00 1A 00 10 00 59 03 BF 00 00 00 1B 64 00 ED 4A
|
||||
Free heap 92384
|
||||
96117[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
96167[HTR] 76 16 02 01 00 83 05 D2 00 1A 00 11 00 59 03 BF 00 00 00 1B 64 00 11 4E
|
||||
Free heap 92384
|
||||
97139[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
97189[HTR] 76 16 02 01 00 83 05 D2 00 1A 00 10 00 59 03 BF 00 00 00 1B 64 00 ED 4A
|
||||
Free heap 92384
|
||||
98162[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
98212[HTR] 76 16 02 01 00 83 05 C8 00 1A 00 11 00 59 03 BB 00 00 00 1B 64 00 DA 91
|
||||
Free heap 92384
|
||||
99185[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
99235[HTR] 76 16 02 01 00 83 05 C8 00 1B 00 11 00 59 03 B7 00 00 00 1B 64 00 5B 5F
|
||||
Free heap 92384
|
||||
100207[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
100257[HTR] 76 16 02 01 00 83 05 BE 00 1A 00 11 00 59 03 B7 00 00 00 1B 64 00 FC AB
|
||||
Free heap 92384
|
||||
101230[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
101280[HTR] 76 16 02 01 00 83 05 BE 00 1A 00 10 00 59 03 BB 00 00 00 1B 64 00 00 63
|
||||
Free heap 92384
|
||||
102252[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
102302[HTR] 76 16 02 01 00 83 05 BE 00 1B 00 10 00 59 03 B7 00 00 00 1B 64 00 81 AD
|
||||
Free heap 92384
|
||||
103276[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
103326[HTR] 76 16 02 01 00 83 05 B4 00 1A 00 10 00 59 03 B7 00 00 00 1B 64 00 07 25
|
||||
Free heap 92384
|
||||
104298[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
104348[HTR] 76 16 02 01 00 83 05 BE 00 1B 00 10 00 59 03 B3 00 00 00 1B 64 00 41 E8
|
||||
Free heap 92384
|
||||
105320[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
105370[HTR] 76 16 02 01 00 83 05 BE 00 1B 00 11 00 59 03 B3 00 00 00 1B 64 00 BD EC
|
||||
Free heap 92384
|
||||
106344[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
106394[HTR] 76 16 02 01 00 83 05 D2 00 1B 00 11 00 59 03 B3 00 00 00 1B 64 00 90 80
|
||||
Free heap 92384
|
||||
107366[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
107416[HTR] 76 16 02 01 00 83 05 DC 00 1B 00 10 00 59 03 B3 00 00 00 1B 64 00 68 0A
|
||||
Free heap 92384
|
||||
108388[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
108438[HTR] 76 16 02 01 00 83 05 E6 00 1B 00 11 00 59 03 B3 00 00 00 1B 64 00 87 B4
|
||||
Free heap 92384
|
||||
109411[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
109461[HTR] 76 16 02 01 00 83 05 F0 00 1B 00 11 00 59 03 B3 00 00 00 1B 64 00 89 22
|
||||
Free heap 92384
|
||||
110435[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
110485[HTR] 76 16 02 01 00 83 05 FA 00 1B 00 11 00 59 03 AF 00 00 00 1B 64 00 4F 75
|
||||
Free heap 92384
|
||||
111457[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
111507[HTR] 76 16 02 01 00 83 05 FA 00 1B 00 11 00 59 03 AF 00 00 00 1B 64 00 4F 75
|
||||
Free heap 92384
|
||||
112480[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
112530[HTR] 76 16 02 01 00 83 05 FA 00 1A 00 11 00 59 03 AF 00 00 00 1B 64 00 CE 77
|
||||
Free heap 92384
|
||||
113500[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
113550[HTR] 76 16 02 01 00 83 05 FA 00 1A 00 11 00 59 03 AF 10 00 00 1B 64 00 5E 75
|
||||
Free heap 92384
|
||||
114523[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
114573[HTR] 76 16 02 01 00 81 05 F0 00 1A 00 11 00 59 03 AF 10 00 00 1B 64 00 39 5E
|
||||
Free heap 92384
|
||||
115546[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
115596[HTR] 76 16 02 01 00 83 05 F0 00 1B 00 11 00 59 03 B3 10 00 00 1B 64 00 19 20
|
||||
Free heap 92384
|
||||
116569[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
116619[HTR] 76 16 02 01 00 83 05 F0 00 1B 00 11 00 59 03 AF 10 00 00 1B 64 00 D8 FD
|
||||
Free heap 92384
|
||||
117593[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
117643[HTR] 76 16 02 01 00 82 05 FA 00 1A 00 11 00 59 03 AF 10 00 00 1B 64 00 CE 24
|
||||
Free heap 92384
|
||||
118616[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
118666[HTR] 76 16 02 01 00 83 05 F0 00 1B 00 11 00 59 03 AB 10 00 00 1B 64 00 18 B8
|
||||
Free heap 92384
|
||||
119639[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
119689[HTR] 76 16 02 01 00 83 05 FA 00 1B 00 11 00 59 03 AB 10 00 00 1B 64 00 1F 32
|
||||
Free heap 92384
|
||||
120661[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
120711[HTR] 76 16 02 01 00 80 06 04 00 1A 00 11 00 59 03 AB 10 00 00 1B 64 00 DF FE
|
||||
Free heap 92384
|
||||
121685[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
121735[HTR] 76 16 02 01 00 83 06 18 00 1C 00 11 00 59 03 AF 10 00 00 1B 64 00 20 5E
|
||||
Free heap 92384
|
||||
122708[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
122758[HTR] 76 16 02 01 00 83 06 22 00 1C 00 11 00 59 03 A7 10 00 00 1B 64 00 F3 6D
|
||||
Free heap 92384
|
||||
123728[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
123778[HTR] 76 16 02 01 00 83 06 2C 00 1C 00 11 00 59 03 AB 10 00 00 1B 64 00 F7 2F
|
||||
Free heap 92384
|
||||
124748[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
124798[HTR] 76 16 02 01 00 83 06 40 00 1C 00 11 00 59 03 AB 11 00 00 1B 64 00 0B 42
|
||||
Free heap 92384
|
||||
125770[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
125820[HTR] 76 16 02 01 00 83 06 54 00 1C 00 11 00 59 03 AB 11 00 00 1B 64 00 04 56
|
||||
Free heap 92384
|
||||
126792[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
126842[HTR] 76 16 02 01 00 83 06 5E 00 1C 00 11 00 59 03 AF 11 00 00 1B 64 00 C3 99
|
||||
Free heap 92384
|
||||
127812[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
127862[HTR] 76 16 02 01 00 83 06 68 00 1C 00 11 00 59 03 AB 11 00 00 1B 64 00 15 6A
|
||||
Free heap 92384
|
||||
128833[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
128883[HTR] 76 16 02 01 00 83 06 7C 00 1D 00 11 00 59 03 AB 11 00 00 1B 64 00 9B 7C
|
||||
Free heap 92384
|
||||
129853[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
129903[HTR] 76 16 02 01 00 83 06 7C 00 1D 00 11 00 59 03 AB 11 00 00 1B 64 00 9B 7C
|
||||
Free heap 92384
|
||||
130874[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
130924[HTR] 76 16 02 01 00 83 06 86 00 1D 00 11 00 59 03 AB 11 00 00 1B 64 00 D8 06
|
||||
Free heap 92384
|
||||
131894[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
131944[HTR] 76 16 02 01 00 83 06 90 00 1D 00 11 00 59 03 AF 11 00 00 1B 64 00 16 D5
|
||||
Free heap 92384
|
||||
132915[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
132965[HTR] 76 16 02 01 00 83 06 9A 00 1E 00 11 00 59 03 AB 11 00 00 1B 64 00 12 1F
|
||||
Free heap 92384
|
||||
133938[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
133988[HTR] 76 16 02 01 00 83 06 A4 00 1E 00 11 00 59 03 AF 12 00 00 1B 64 00 F1 E4
|
||||
Free heap 92384
|
||||
134957[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
135007[HTR] 76 16 02 01 00 83 06 AE 00 21 00 11 00 59 03 AB 12 00 00 1B 64 00 C9 7E
|
||||
Free heap 92384
|
||||
135981[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
136031[HTR] 76 16 02 01 00 83 06 C2 00 1F 00 11 00 59 03 AB 12 00 00 1B 64 00 9A 45
|
||||
Free heap 92384
|
||||
137003[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
137053[HTR] 76 16 02 01 00 82 06 CC 00 1E 00 11 00 59 03 A7 12 00 00 1B 64 00 8F 54
|
||||
Free heap 92384
|
||||
ASSERT_PARAM(512 0), in rwbt.c at line 273
|
||||
Guru Meditation Error: Core 0 panic'ed (Interrupt wdt timeout on CPU0)
|
||||
Core 0 register dump:
|
||||
PC : 0x400850c8 PS : 0x00060034 A0 : 0x80088b40 A1 : 0x3ffc05b0
|
||||
A2 : 0x00000001 A3 : 0x00000000 A4 : 0x00000000 A5 : 0x60008054
|
||||
A6 : 0x3ffc1030 A7 : 0x60008050 A8 : 0x800850c5 A9 : 0x3ffc0590
|
||||
A10 : 0x00000004 A11 : 0x00000000 A12 : 0x6000804c A13 : 0xffffffff
|
||||
A14 : 0x00000000 A15 : 0xfffffffc SAR : 0x00000004 EXCCAUSE: 0x00000005
|
||||
EXCVADDR: 0x00000000 LBEG : 0x40084ffd LEND : 0x40085004 LCOUNT : 0x00000000
|
||||
Core 0 was running in ISR context:
|
||||
EPC1 : 0x4017d35e EPC2 : 0x00000000 EPC3 : 0x00000000 EPC4 : 0x400850c8
|
||||
|
||||
Backtrace: 0x400850c8:0x3ffc05b0 0x40088b3d:0x3ffc05d0 0x400891cf:0x3ffc05f0 0x400817ad:0x3ffc0610 0x4017d35b:0x00000000
|
||||
|
||||
Core 1 register dump:
|
||||
PC : 0x400d1faa PS : 0x00060334 A0 : 0x800d1258 A1 : 0x3ffd55d0
|
||||
A2 : 0x00000000 A3 : 0x00000000 A4 : 0x00000000 A5 : 0x00000000
|
||||
A6 : 0x00000000 A7 : 0x3ffd36c0 A8 : 0x3ffc4920 A9 : 0x3ffd55b0
|
||||
A10 : 0x3ffe7f84 A11 : 0x3ffd0814 A12 : 0xd4000000 A13 : 0x3ffd54d0
|
||||
A14 : 0x00000002 A15 : 0x3ffd36c0 SAR : 0x0000000a EXCCAUSE: 0x00000005
|
||||
EXCVADDR: 0x00000000 LBEG : 0x4000c2e0 LEND : 0x4000c2f6 LCOUNT : 0x00000000
|
||||
|
||||
Backtrace: 0x400d1faa:0x3ffd55d0 0x400d1255:0x3ffd55f0 0x400d1718:0x3ffd5610 0x401692c4:0x3ffd5630
|
||||
|
||||
Rebooting...
|
||||
ets Jun 8 2016 00:22:57
|
||||
|
||||
rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
|
||||
configsip: 0, SPIWP:0xee
|
||||
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
|
||||
mode:DIO, clock div:1
|
||||
load:0x3fff0018,len:4
|
||||
load:0x3fff001c,len:952
|
||||
load:0x40078000,len:6084
|
||||
load:0x40080000,len:7936
|
||||
entry 0x40080310
|
||||
1045[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
1085[HTR] 76 16 02 01 00 81 06 FE 00 1F 00 11 00 59 03 A7 12 00 00 1B 64 00 EB 14
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
2065[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
2105[HTR] 76 16 02 01 00 82 07 26 00 20 00 11 00 59 03 AB 12 00 00 1B 64 00 2E 64
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
3086[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
3126[HTR] 76 16 02 01 00 83 07 3A 00 21 00 11 00 59 03 A7 12 00 00 1B 64 00 36 E7
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
4107[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
4147[HTR] 76 16 02 01 00 82 07 62 00 21 00 11 00 59 03 AF 12 00 00 1B 64 00 5C 67
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
5126[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
5166[HTR] 76 16 02 01 00 82 07 6C 00 20 00 11 00 59 03 AF 13 00 00 1B 64 00 08 EA
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
6146[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
6186[HTR] 76 16 02 01 00 82 07 94 00 22 00 11 00 59 03 AB 13 00 00 1B 64 00 C8 50
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
7167[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
7207[HTR] 76 16 02 01 00 82 07 A8 00 22 00 11 00 59 03 AF 13 00 00 1B 64 00 19 29
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
8187[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
8227[HTR] 76 16 02 01 00 82 07 BC 00 21 00 11 00 59 03 AB 13 00 00 1B 64 00 15 7D
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
9208[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
9248[HTR] 76 16 02 01 00 82 07 C6 00 23 00 11 00 59 03 AB 13 00 00 1B 64 00 74 80
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
10233[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
10273[HTR] 76 16 02 01 00 82 07 E4 00 23 00 11 00 59 03 AF 13 00 00 1B 64 00 AD 67
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
11253[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
11293[HTR] 76 16 02 01 00 82 07 F8 00 24 00 11 00 58 03 AF 13 00 00 1B 64 00 73 7D
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
12274[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
12314[HTR] 76 16 02 01 00 82 08 0C 00 24 00 11 00 59 03 AF 13 00 00 1B 64 00 50 C1
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
13294[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
13334[HTR] 76 16 02 01 00 82 08 20 00 24 00 11 00 59 03 AF 14 00 00 1B 64 00 FA EC
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
14314[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
14354[HTR] 76 16 02 01 00 82 08 48 00 25 00 11 00 59 03 AF 14 00 00 1B 64 00 55 86
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
15338[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
15378[HTR] 76 16 02 01 00 82 08 66 00 25 00 11 00 59 03 B3 14 00 00 1B 64 00 88 F5
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
16362[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
16402[HTR] 76 16 02 01 00 82 08 84 00 26 00 11 00 59 03 B3 14 00 00 1B 64 00 02 92
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
17382[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
17422[HTR] 76 16 02 01 00 82 08 A2 00 26 00 11 00 59 03 AF 14 00 00 1B 64 00 D9 E9
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
18403[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
18443[HTR] 76 16 02 01 00 80 08 C0 00 27 00 11 00 59 03 B3 14 00 00 1B 64 00 D0 75
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
19423[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
19463[HTR] 76 16 02 01 00 82 08 D4 00 27 00 11 00 59 03 B3 14 00 00 1B 64 00 BF C0
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
20443[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
20483[HTR] 76 16 02 01 00 82 08 E8 00 27 00 12 00 5A 03 AF 15 00 00 1B 64 00 0A 3B
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
21464[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
21504[HTR] 76 16 02 01 00 82 08 FC 00 28 00 11 00 59 03 B3 15 00 00 1B 64 00 7F FD
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
22488[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
22528[HTR] 76 16 02 01 00 82 09 10 00 27 00 12 00 59 03 AF 15 00 00 1B 64 00 28 16
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
23508[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
23548[HTR] 76 16 02 01 00 82 09 2E 00 28 00 12 00 59 03 B3 15 00 00 1B 64 00 F6 61
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
24529[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
24569[HTR] 76 16 02 01 00 80 09 42 00 28 00 11 00 59 03 B3 15 00 00 1B 64 00 FF A3
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
25549[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
25589[HTR] 76 16 02 01 00 82 09 60 00 2A 00 12 00 59 03 AF 15 00 00 1B 64 00 41 75
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
26570[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
26610[HTR] 76 16 02 01 00 82 09 74 00 2A 00 12 00 59 03 B3 16 00 00 1B 64 00 BC BC
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
27591[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
27631[HTR] 76 16 02 01 00 82 09 9C 00 2A 00 12 00 59 03 B7 16 00 00 1B 64 00 32 11
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
28613[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
28653[HTR] 76 16 02 01 00 82 09 B0 00 2B 00 12 00 59 03 B7 16 00 00 1B 64 00 AE 3F
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
29633[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
29673[HTR] 76 16 02 01 00 82 09 CE 00 2B 00 12 00 59 03 B7 16 00 00 1B 64 00 8E C1
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
30653[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
30693[HTR] 76 16 02 01 00 82 09 EC 00 2B 00 12 00 59 03 B7 16 00 00 1B 64 00 97 63
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
31674[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
31714[HTR] 76 16 02 01 00 82 09 F6 00 2C 00 12 00 59 03 B7 16 00 00 1B 64 00 DB F2
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
32694[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
32734[HTR] 76 16 02 01 00 82 0A 14 00 2C 00 12 00 59 03 B7 17 00 00 1B 64 00 B2 D1
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
33718[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
33758[HTR] 76 16 02 01 00 82 0A 1E 00 2D 00 12 00 59 03 B7 17 00 00 1B 64 00 34 59
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
34740[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
34780[HTR] 76 16 02 01 00 82 0A 32 00 2D 00 12 00 58 03 B7 17 00 00 1B 64 00 B9 78
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
35760[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
35800[HTR] 76 16 02 01 00 82 0A 46 00 2E 00 12 00 59 03 B7 17 00 00 1B 64 00 CD 04
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
36782[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
36822[HTR] 76 16 02 01 00 82 0A 5A 00 2E 00 12 00 59 03 B7 17 00 00 1B 64 00 C4 18
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
37803[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
37843[HTR] 76 16 02 01 00 82 0A 78 00 2F 00 12 00 59 03 B7 17 00 00 1B 64 00 5C B8
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
38823[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
38863[HTR] 76 16 02 01 00 82 0A 8C 00 2F 00 12 00 59 03 B7 18 00 00 1B 64 00 E4 4C
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
39843[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
39883[HTR] 76 16 02 01 00 80 0A AA 00 2F 00 12 00 59 03 B3 18 00 00 1B 64 00 5E 0E
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
40864[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
40904[HTR] 76 16 02 01 00 82 0A D2 00 30 00 12 00 59 03 BB 18 00 00 1B 64 00 43 74
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
41884[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
41924[HTR] 76 16 02 01 00 80 0A E6 00 30 00 12 00 59 03 B7 18 00 00 1B 64 00 34 2D
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
42906[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
42946[HTR] 76 16 02 01 00 82 0B 0E 00 31 00 12 00 59 03 B7 18 00 00 1B 64 00 0B A7
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
43925[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
43965[HTR] 76 16 02 01 00 80 0B 36 00 31 00 12 00 59 03 B7 19 00 00 1B 64 00 A8 3F
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
44946[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
44986[HTR] 76 16 02 01 00 82 0B 54 00 32 00 12 00 59 03 BB 19 00 00 1B 64 00 22 B5
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
45965[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
46005[HTR] 76 16 02 01 00 82 0B 68 00 32 00 13 00 59 03 B7 19 00 00 1B 64 00 CF 41
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
46986[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
47026[HTR] 76 16 02 01 00 82 0B 7C 00 33 00 12 00 59 03 BB 19 00 00 1B 64 00 BD 9F
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
48008[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
48048[HTR] 76 16 02 01 00 82 0B 9A 00 32 00 12 00 59 03 BB 1A 00 00 1B 64 00 45 FB
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
49031[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
49071[HTR] 76 16 02 01 00 82 0B A4 00 33 00 12 00 59 03 BF 1A 00 00 1B 64 00 14 02
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
50053[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
50093[HTR] 76 16 02 01 00 82 0B B8 00 33 00 13 00 59 03 BB 1A 00 00 1B 64 00 21 5F
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
51076[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
51116[HTR] 76 16 02 01 00 82 0B C2 00 34 00 13 00 59 03 BB 1A 00 00 1B 64 00 45 AE
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
52099[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
52139[HTR] 76 16 02 01 00 82 0B E0 00 34 00 13 00 59 03 BF 1A 00 00 1B 64 00 9C 49
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
53122[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
53162[HTR] 76 16 02 01 00 7F 0B EA 00 32 00 13 00 59 03 BB 1B 00 00 1B 64 00 EC 5E
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
54145[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
54185[HTR] 76 16 02 01 00 82 0C 08 00 35 00 13 00 59 03 C3 1B 00 00 1B 64 00 77 5D
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
55167[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
55207[HTR] 76 16 02 01 00 82 0C 1C 00 36 00 13 00 59 03 BB 1B 00 00 1B 64 00 BC B4
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
56187[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
56227[HTR] 76 16 02 01 00 81 0C 3A 00 36 00 13 00 59 03 BF 1B 00 00 1B 64 00 96 A7
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
57207[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
57247[HTR] 76 16 02 01 00 82 0C 58 00 36 00 13 00 59 03 BB 1C 00 00 1B 64 00 38 F1
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
||||
58230[BTC] 76 16 00 16 13 10 2D 05 DC 11 94 78 01 CD 08 23 02 00 01 2C 0D AC 58 CF
|
||||
No Bluetooth client
|
||||
58270[HTR] 76 16 02 01 00 82 0C 6C 00 37 00 13 00 59 03 BB 1C 00 00 1B 64 00 AE C7
|
||||
No Bluetooth client
|
||||
Free heap 96196
|
|
@ -1,265 +0,0 @@
|
|||
/*
|
||||
* This file is part of the "bluetoothheater" distribution
|
||||
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
|
||||
*
|
||||
* Copyright (C) 2018 Ray Jones <ray@mrjones.id.au>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "BluetoothHC05.h"
|
||||
#include "../cfg/pins.h"
|
||||
#include "../cfg/BTCConfig.h"
|
||||
#include "../Protocol/Protocol.h"
|
||||
#include "../Protocol/helpers.h"
|
||||
#include "../Utility/DebugPort.h"
|
||||
|
||||
// Bluetooth access via HC-05 Module, using a UART
|
||||
|
||||
|
||||
CBluetoothHC05::CBluetoothHC05(int keyPin, int sensePin)
|
||||
{
|
||||
// extra control pins required to fully drive a HC05 module
|
||||
_keyPin = keyPin; // used to enable AT command mode (ONLY ON SUPPORTED MODULES!!!!)
|
||||
_sensePin = sensePin; // feedback signal used to sense if a client is connected
|
||||
|
||||
pinMode(_keyPin, OUTPUT);
|
||||
digitalWrite(_keyPin, LOW); // request HC-05 module to enter data mode
|
||||
// attach to the SENSE line from the HC-05 module
|
||||
// this line goes high when a BT client is connected :-)
|
||||
pinMode(_sensePin, INPUT);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CBluetoothHC05::begin()
|
||||
{
|
||||
const int BTRates[] = {
|
||||
9600, 38400, 115200, 19200, 57600, 2400, 4800, 1200
|
||||
};
|
||||
|
||||
_rxLine.clear();
|
||||
|
||||
digitalWrite(_keyPin, HIGH); // request HC-05 module to enter command mode
|
||||
|
||||
delay(50);
|
||||
|
||||
openSerial(9600); // virtual function, may call derived class method here
|
||||
|
||||
DebugPort.println("\r\n\r\nAttempting to detect HC-05 Bluetooth module...");
|
||||
|
||||
int BTidx = 0;
|
||||
int maxTries = sizeof(BTRates)/sizeof(int);
|
||||
for(BTidx = 0; BTidx < maxTries; BTidx++) {
|
||||
DebugPort.print(" @ ");
|
||||
DebugPort.print(BTRates[BTidx]);
|
||||
DebugPort.print(" baud... ");
|
||||
openSerial(BTRates[BTidx]); // open serial port at a std. baud rate
|
||||
delay(10);
|
||||
flush();
|
||||
HC05_SerialPort.print("AT\r\n"); // clear the throat!
|
||||
delay(100);
|
||||
HC05_SerialPort.setTimeout(100);
|
||||
|
||||
if(ATCommand("AT\r\n")) { // probe with a simple "AT"
|
||||
DebugPort.println(" OK."); // got a response - woo hoo found the module!
|
||||
break;
|
||||
}
|
||||
if(ATCommand("AT\r\n")) { // sometimes a second try is good...
|
||||
DebugPort.println(" OK.");
|
||||
break;
|
||||
}
|
||||
|
||||
// failed, try another baud rate
|
||||
DebugPort.println("");
|
||||
HC05_SerialPort.flush();
|
||||
HC05_SerialPort.end();
|
||||
delay(100);
|
||||
}
|
||||
|
||||
DebugPort.println("");
|
||||
if(BTidx == maxTries) {
|
||||
// we could not get anywhere with the AT commands, but maybe this is the other module
|
||||
// plough on and assume 9600 baud, but at the mercy of whatever the module name is...
|
||||
DebugPort.println("FAILED to detect a HC-05 Bluetooth module :-(");
|
||||
// leave the EN pin high - if other style module keeps it powered!
|
||||
// assume it is 9600, and just (try to) use it like that...
|
||||
// we will sense the STATE line to prove a client is hanging off the link...
|
||||
DebugPort.println("ASSUMING a HC-05 module @ 9600baud (Unknown name)");
|
||||
openSerial(9600);
|
||||
}
|
||||
else {
|
||||
// found a HC-05 module at one of its supported baud rates.
|
||||
// now program it's name and force a 9600 baud data interface.
|
||||
// this is the defacto standard as shipped!
|
||||
|
||||
DebugPort.println("HC-05 found");
|
||||
|
||||
DebugPort.print(" Setting Name to \"Afterburner\"... ");
|
||||
if(!ATCommand("AT+NAME=\"Afterburner\"\r\n")) {
|
||||
DebugPort.println("FAILED");
|
||||
}
|
||||
else {
|
||||
DebugPort.println("OK");
|
||||
}
|
||||
|
||||
DebugPort.print(" Setting baud rate to 9600N81...");
|
||||
if(!ATCommand("AT+UART=9600,1,0\r\n")) {
|
||||
DebugPort.println("FAILED");
|
||||
}
|
||||
else {
|
||||
DebugPort.println("OK");
|
||||
}
|
||||
DebugPort.print(" Lowering power consumption...");
|
||||
if(!ATCommand("AT+IPSCAN=1024,1,1024,1\r\n")) {
|
||||
DebugPort.println("FAILED");
|
||||
}
|
||||
else {
|
||||
DebugPort.println("OK");
|
||||
}
|
||||
/*
|
||||
DebugPort.print(" Lowering power consumption...");
|
||||
if(!ATCommand("AT+SNIFF=40,20,1,8\r\n")) {
|
||||
DebugPort.println("FAILED");
|
||||
}
|
||||
else {
|
||||
DebugPort.println("OK");
|
||||
}
|
||||
|
||||
DebugPort.print(" Lowering power consumption...");
|
||||
if(!ATCommand("AT+ENSNIFF=0002,72,0A3C7F\r\n")) {
|
||||
DebugPort.println("FAILED");
|
||||
}
|
||||
else {
|
||||
DebugPort.println("OK");
|
||||
}*/
|
||||
flush();
|
||||
delay(100);
|
||||
openSerial(9600);
|
||||
|
||||
// leave HC-05 command mode, return to data mode
|
||||
digitalWrite(_keyPin, LOW);
|
||||
|
||||
}
|
||||
|
||||
delay(50);
|
||||
flush(); // ensure any AT command reponse dribbles are cleaned up!
|
||||
|
||||
DebugPort.println("");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CBluetoothHC05::check()
|
||||
{
|
||||
// check for data coming back over Bluetooth
|
||||
if(HC05_SerialPort.available()) { // serial rx data is available
|
||||
char rxVal = HC05_SerialPort.read();
|
||||
collectRxData(rxVal);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
CBluetoothHC05::isConnected()
|
||||
{
|
||||
return digitalRead(_sensePin);
|
||||
}
|
||||
|
||||
void
|
||||
CBluetoothHC05::send(const char* Str)
|
||||
{
|
||||
if(isConnected()) {
|
||||
HC05_SerialPort.print(Str);
|
||||
}
|
||||
else {
|
||||
// DebugPort.print("No Bluetooth client");
|
||||
}
|
||||
}
|
||||
/*
|
||||
void
|
||||
CBluetoothHC05::sendFrame(const char* pHdr, const CProtocol& Frame, bool lineterm)
|
||||
{
|
||||
// report to debug port
|
||||
CBluetoothAbstract::sendFrame(pHdr, Frame, false);
|
||||
|
||||
if(isConnected()) {
|
||||
if(Frame.verifyCRC()) {
|
||||
// send data frame to HC-05
|
||||
HC05_SerialPort.print(pHdr);
|
||||
HC05_SerialPort.write(Frame.Data, 24);
|
||||
// toggle LED
|
||||
#if BT_LED == 1
|
||||
digitalWrite(LED_Pin, !digitalRead(LED_Pin)); // toggle LED
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
DebugPort.print("Bluetooth data not sent, CRC error ");
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(lineterm) { // only report no client if this will be at end of line (long line support)
|
||||
DebugPort.print("No Bluetooth client");
|
||||
}
|
||||
// force LED off
|
||||
#if BT_LED == 1
|
||||
digitalWrite(LED_Pin, LOW);
|
||||
#endif
|
||||
}
|
||||
if(lineterm)
|
||||
DebugPort.println("");
|
||||
}
|
||||
*/
|
||||
|
||||
void
|
||||
CBluetoothHC05::openSerial(int baudrate)
|
||||
{
|
||||
// standard serial port for Due, Mega (ESP32 uses virtual, derived from this class)
|
||||
HC05_SerialPort.begin(baudrate);
|
||||
}
|
||||
|
||||
// protected function, to perform Hayes commands with HC-05
|
||||
bool
|
||||
CBluetoothHC05::ATCommand(const char* cmd)
|
||||
{
|
||||
flush(); // ensure response is for *this* command!
|
||||
HC05_SerialPort.print(cmd);
|
||||
char RxBuffer[16];
|
||||
memset(RxBuffer, 0, 16);
|
||||
int read = HC05_SerialPort.readBytesUntil('\n', RxBuffer, 16); // \n is not included in returned string!
|
||||
if((read == 3) && (0 == strcmp(RxBuffer, "OK\r")) ) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
CBluetoothHC05::foldbackDesiredTemp()
|
||||
{
|
||||
StaticJsonBuffer<32> jsonBuffer; // create a JSON buffer on the stack
|
||||
JsonObject& root = jsonBuffer.createObject(); // create object to add JSON commands to
|
||||
|
||||
if(foldbackModerator.addJson("TempDesired", getSetTemp(), root)) {
|
||||
char opStr[32];
|
||||
root.printTo(opStr);
|
||||
send(opStr);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CBluetoothHC05::flush()
|
||||
{
|
||||
while(HC05_SerialPort.available())
|
||||
HC05_SerialPort.read();
|
||||
}
|
|
@ -1,351 +0,0 @@
|
|||
/*
|
||||
* This file is part of the "bluetoothheater" distribution
|
||||
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
|
||||
*
|
||||
* Copyright (C) 2018 Ray Jones <ray@mrjones.id.au>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "128x64OLED.h"
|
||||
#include "fonts/tahoma16.h"
|
||||
#include "fonts/tahoma24.h"
|
||||
#include "fonts/Icons.h"
|
||||
#include "BasicScreen.h"
|
||||
#include "KeyPad.h"
|
||||
#include "../Protocol/helpers.h"
|
||||
#include "../Utility/UtilClasses.h"
|
||||
#include "../Utility/NVStorage.h"
|
||||
|
||||
|
||||
#define MAXIFONT tahoma_24ptFontInfo
|
||||
//#define MAXIFONT tahoma_16ptFontInfo
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CBasicScreen
|
||||
//
|
||||
// This screen provides a basic control function
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CBasicScreen::CBasicScreen(C128x64_OLED& display, CScreenManager& mgr) : CScreenHeader(display, mgr)
|
||||
{
|
||||
_showSetModeTime = 0;
|
||||
_showModeTime = 0;
|
||||
_feedbackType = 0;
|
||||
_nModeSel = 0;
|
||||
}
|
||||
|
||||
bool
|
||||
CBasicScreen::show()
|
||||
{
|
||||
CScreenHeader::show();
|
||||
|
||||
char msg[20];
|
||||
int xPos, yPos;
|
||||
|
||||
float fTemp = getTemperatureSensor();
|
||||
if(fTemp > -80) {
|
||||
if(NVstore.getDegFMode()) {
|
||||
fTemp = fTemp * 9 / 5 + 32;
|
||||
sprintf(msg, "%.1f`F", fTemp);
|
||||
}
|
||||
else {
|
||||
sprintf(msg, "%.1f`C", fTemp);
|
||||
}
|
||||
|
||||
{
|
||||
CTransientFont AF(_display, &MAXIFONT); // temporarily use a large font
|
||||
_printMenuText(_display.xCentre(), 23, msg, false, eCentreJustify);
|
||||
// _printMenuText(_display.xCentre(), 25, msg, false, eCentreJustify);
|
||||
}
|
||||
}
|
||||
else {
|
||||
_printMenuText(_display.xCentre(), 25, "No Temperature Sensor", false, eCentreJustify);
|
||||
}
|
||||
|
||||
|
||||
// at bottom of screen show either:
|
||||
// Selection between Fixed or Thermostat mode
|
||||
// Current heat demand setting
|
||||
// Run state of heater
|
||||
|
||||
if(_showModeTime) {
|
||||
const int border = 3;
|
||||
const int radius = 4;
|
||||
// Show selection between Fixed or Thermostat mode
|
||||
long tDelta = millis() - _showModeTime;
|
||||
if(tDelta < 0) {
|
||||
|
||||
yPos = _display.height() - _display.textHeight() - border; // bottom of screen, with room for box
|
||||
|
||||
// display "Fixed Hz" at lower right, allowing space for a selection surrounding box
|
||||
strcpy(msg, "Fixed Hz");
|
||||
xPos = _display.width() - border; // set X position to finish short of RHS
|
||||
_printMenuText(xPos, yPos, msg, _nModeSel == 1, eRightJustify);
|
||||
|
||||
// display "Thermostat" at lower left, allowing space for a selection surrounding box
|
||||
strcpy(msg, "Thermostat");
|
||||
xPos = border;
|
||||
_printMenuText(xPos, yPos, msg, _nModeSel == 0);
|
||||
|
||||
// setThermostatMode(_nModeSel == 0 ? 1 : 0); // set the new mode
|
||||
}
|
||||
else {
|
||||
// cancel selection mode, apply whatever is boxed
|
||||
_showModeTime = 0;
|
||||
_showSetModeTime = millis() + 5000; // then make the new mode setting be shown
|
||||
_feedbackType = 0;
|
||||
_ScreenManager.reqUpdate();
|
||||
}
|
||||
}
|
||||
if((_showModeTime == 0) && _showSetModeTime) {
|
||||
long tDelta = millis() - _showSetModeTime;
|
||||
if(tDelta < 0) {
|
||||
switch(_feedbackType) {
|
||||
case 0:
|
||||
// Show current heat demand setting
|
||||
|
||||
if(getThermostatModeActive()) {
|
||||
float fTemp = getTemperatureDesired();
|
||||
if(NVstore.getDegFMode()) {
|
||||
fTemp = fTemp * 9 / 5 + 32;
|
||||
sprintf(msg, "Setpoint = %.0f`F", fTemp);
|
||||
}
|
||||
else {
|
||||
sprintf(msg, "Setpoint = %.0f`C", fTemp);
|
||||
}
|
||||
}
|
||||
else {
|
||||
sprintf(msg, "Setpoint = %.1fHz", getHeaterInfo().getPump_Fixed());
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
sprintf(msg, "GPIO output #%d %s", _feedbackType, getGPIO(_feedbackType-1) ? "ON" : "OFF");
|
||||
break;
|
||||
}
|
||||
// centre message at bottom of screen
|
||||
_printMenuText(_display.xCentre(), _display.height() - _display.textHeight(), msg, false, eCentreJustify);
|
||||
}
|
||||
else {
|
||||
_showSetModeTime = 0;
|
||||
}
|
||||
}
|
||||
if((_showModeTime == 0) && (_showSetModeTime == 0)) {
|
||||
showRunState();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
CBasicScreen::keyHandler(uint8_t event)
|
||||
{
|
||||
static int repeatCount = -1;
|
||||
|
||||
if(event & keyPressed) {
|
||||
repeatCount = 0; // unlock tracking of repeat events
|
||||
}
|
||||
|
||||
//
|
||||
// use repeat function for key hold detection
|
||||
//
|
||||
if(event & keyRepeat) {
|
||||
if(repeatCount >= 0) {
|
||||
repeatCount++;
|
||||
// hold LEFT to toggle GPIO output #1
|
||||
if(event & key_Left) {
|
||||
if(repeatCount > 2) {
|
||||
repeatCount = -1; // prevent double handling
|
||||
setGPIO(0, !getGPIO(0)); // toggle GPIO output #1
|
||||
_showSetModeTime = millis() + 2000;
|
||||
_feedbackType = 1;
|
||||
_ScreenManager.reqUpdate();
|
||||
}
|
||||
}
|
||||
// hold RIGHT to toggle GPIO output #2
|
||||
if(event & key_Right) {
|
||||
if(repeatCount > 2) {
|
||||
repeatCount = -1; // prevent double handling
|
||||
setGPIO(1, !getGPIO(1)); // toggle GPIO output #2
|
||||
_showSetModeTime = millis() + 2000;
|
||||
_feedbackType = 2;
|
||||
_ScreenManager.reqUpdate();
|
||||
}
|
||||
}
|
||||
// hold DOWN to enter thermostat / fixed mode selection
|
||||
if(event & key_Down) {
|
||||
if(repeatCount > 2) {
|
||||
repeatCount = -1; // prevent double handling
|
||||
_showModeTime = millis() + 5000;
|
||||
_nModeSel = getThermostatModeActive() ? 0 : 1;
|
||||
}
|
||||
}
|
||||
// hold UP to toggle degC/degF mode selection
|
||||
if(event & key_Up) {
|
||||
if(repeatCount > 2) {
|
||||
repeatCount = -1; // prevent double handling
|
||||
_showModeTime = millis() + 5000;
|
||||
NVstore.setDegFMode(NVstore.getDegFMode() ? 0 : 1);
|
||||
}
|
||||
}
|
||||
// hold CENTRE to turn ON or OFF
|
||||
if(event & key_Centre) {
|
||||
int runstate = getHeaterInfo().getRunStateEx();
|
||||
if(runstate) { // running, including cyclic mode idle
|
||||
if(repeatCount > 5) {
|
||||
repeatCount = -1;
|
||||
requestOff();
|
||||
}
|
||||
}
|
||||
else { // standard idle state
|
||||
// standby, request ON
|
||||
if(repeatCount > 3) {
|
||||
repeatCount = -1;
|
||||
requestOn();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// key released handling
|
||||
//
|
||||
if(event & keyReleased) {
|
||||
if(!_showModeTime) {
|
||||
// release DOWN key to reduce set demand, provided we are not in mode select
|
||||
if(event & key_Down) {
|
||||
if(reqTempDelta(-1)) {
|
||||
_showSetModeTime = millis() + 2000;
|
||||
_feedbackType = 0;
|
||||
_ScreenManager.reqUpdate();
|
||||
}
|
||||
else
|
||||
_reqOEMWarning();
|
||||
}
|
||||
// release UP key to increase set demand, provided we are not in mode select
|
||||
if(event & key_Up) {
|
||||
if(reqTempDelta(+1)) {
|
||||
_showSetModeTime = millis() + 2000;
|
||||
_feedbackType = 0;
|
||||
_ScreenManager.reqUpdate();
|
||||
}
|
||||
else
|
||||
_reqOEMWarning();
|
||||
}
|
||||
}
|
||||
if(event & key_Left) {
|
||||
if(repeatCount >= 0) {
|
||||
if(!_showModeTime) {
|
||||
_ScreenManager.prevMenu();
|
||||
}
|
||||
else {
|
||||
if(hasOEMcontroller())
|
||||
_reqOEMWarning();
|
||||
else {
|
||||
_showModeTime = millis() + 5000;
|
||||
_nModeSel = 0;
|
||||
setThermostatMode(1); // set the new mode
|
||||
NVstore.save();
|
||||
}
|
||||
_ScreenManager.reqUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
if(event & key_Right) {
|
||||
if(repeatCount >= 0) {
|
||||
if(!_showModeTime)
|
||||
_ScreenManager.nextMenu();
|
||||
else {
|
||||
if(hasOEMcontroller())
|
||||
_reqOEMWarning();
|
||||
else {
|
||||
_showModeTime = millis() + 5000;
|
||||
_nModeSel = 1;
|
||||
setThermostatMode(0); // set the new mode
|
||||
NVstore.save();
|
||||
}
|
||||
_ScreenManager.reqUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
// release CENTRE to accept new mode, and/or show current setting
|
||||
if(event & key_Centre) {
|
||||
if(repeatCount != -2) { // prevent after off commands
|
||||
if(_showModeTime) {
|
||||
_showModeTime = millis(); // force immediate cancellation of showmode (via screen update)
|
||||
}
|
||||
_showSetModeTime = millis() + 2000;
|
||||
_feedbackType = 0;
|
||||
}
|
||||
_ScreenManager.reqUpdate();
|
||||
}
|
||||
|
||||
repeatCount = -1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CBasicScreen::showRunState()
|
||||
{
|
||||
int runstate = getHeaterInfo().getRunStateEx();
|
||||
int errstate = getHeaterInfo().getErrState();
|
||||
|
||||
if(errstate) errstate--; // correct for +1 biased return value
|
||||
|
||||
static bool toggle = false;
|
||||
const char* toPrint = NULL;
|
||||
_display.setTextColor(WHITE, BLACK);
|
||||
if(errstate && ((runstate == 0) || (runstate > 5))) {
|
||||
|
||||
// flash error code
|
||||
char msg[16];
|
||||
toggle = !toggle;
|
||||
if(toggle) {
|
||||
// create an "E-XX" message to display
|
||||
sprintf(msg, "E-%02d", errstate);
|
||||
}
|
||||
else {
|
||||
strcpy(msg, " ");
|
||||
}
|
||||
int xPos = _display.xCentre();
|
||||
int yPos = _display.height() - 2*_display.textHeight();
|
||||
_printMenuText(xPos, yPos, msg, false, eCentreJustify);
|
||||
|
||||
toPrint = getHeaterInfo().getErrStateStr();
|
||||
}
|
||||
else {
|
||||
if(runstate) {
|
||||
toPrint = getHeaterInfo().getRunStateStr();
|
||||
// simplify starting states
|
||||
switch(runstate) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
toPrint = "Starting";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(toPrint) {
|
||||
// locate at bottom centre
|
||||
_printMenuText(_display.xCentre(), _display.height() - _display.textHeight(), toPrint, false, eCentreJustify);
|
||||
}
|
||||
}
|
|
@ -1,107 +0,0 @@
|
|||
/*
|
||||
* This file is part of the "bluetoothheater" distribution
|
||||
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
|
||||
*
|
||||
* Copyright (C) 2018 Ray Jones <ray@mrjones.id.au>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "128x64OLED.h"
|
||||
#include "FontDumpScreen.h"
|
||||
#include "KeyPad.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CFontDumpScreen
|
||||
//
|
||||
// This screen provides control over experimental features
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static const int Lines[4] = { 24, 34, 44, 54 };
|
||||
|
||||
CFontDumpScreen::CFontDumpScreen(C128x64_OLED& display, CScreenManager& mgr) : CScreen(display, mgr)
|
||||
{
|
||||
_initUI();
|
||||
}
|
||||
|
||||
void
|
||||
CFontDumpScreen::onSelect()
|
||||
{
|
||||
CScreen::onSelect();
|
||||
}
|
||||
|
||||
void
|
||||
CFontDumpScreen::_initUI()
|
||||
{
|
||||
_startChar = 0;
|
||||
}
|
||||
|
||||
bool
|
||||
CFontDumpScreen::show()
|
||||
{
|
||||
_display.clearDisplay();
|
||||
|
||||
char msg[8];
|
||||
|
||||
_printInverted(_display.xCentre(), 0, " Adafruit Font ", true, eCentreJustify);
|
||||
int column = 15;
|
||||
for(int i=0; i<16; i++) {
|
||||
sprintf(msg, "%X", i);
|
||||
_printMenuText(column, 12, msg);
|
||||
column += 7;
|
||||
}
|
||||
for(int row = 0; row < 4; row++) {
|
||||
int currentChar = row * 16 + _startChar;
|
||||
sprintf(msg, "%02X", currentChar);
|
||||
_printMenuText(0, Lines[row], msg);
|
||||
column = 15;
|
||||
for(int i=0; i<16; i++) {
|
||||
msg[0] = currentChar++;
|
||||
msg[1] = 0;
|
||||
_printMenuText(column, Lines[row], msg);
|
||||
column += 7;
|
||||
}
|
||||
}
|
||||
_display.drawFastVLine(13, 12, 61, WHITE);
|
||||
_display.drawFastHLine(0, 21, 128, WHITE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
CFontDumpScreen::keyHandler(uint8_t event)
|
||||
{
|
||||
if(event & keyPressed) {
|
||||
// press LEFT or UP to show prior 64 characters
|
||||
if(event & (key_Left | key_Up)) {
|
||||
_startChar -= 64;
|
||||
}
|
||||
// press RIGHT or DOWN to show next 64 characters
|
||||
if(event & (key_Right | key_Down)) {
|
||||
_startChar += 64;
|
||||
}
|
||||
// CENTRE press
|
||||
if(event & key_Centre) {
|
||||
_ScreenManager.selectMenu(CScreenManager::UserSettingsLoop, CScreenManager::ExThermostatUI); // force return to prior menu
|
||||
}
|
||||
_ScreenManager.reqUpdate();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1,281 +0,0 @@
|
|||
/*
|
||||
* This file is part of the "bluetoothheater" distribution
|
||||
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
|
||||
*
|
||||
* Copyright (C) 2018 Ray Jones <ray@mrjones.id.au>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CFuelMixtureScreen
|
||||
//
|
||||
// This screen allows the fuel mixture endpoints to be adjusted
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "FuelMixtureScreen.h"
|
||||
#include "KeyPad.h"
|
||||
#include "../Protocol/helpers.h"
|
||||
#include "../Wifi/BTCWifi.h"
|
||||
#include "../utility/debugPort.h"
|
||||
|
||||
|
||||
CFuelMixtureScreen::CFuelMixtureScreen(C128x64_OLED& display, CScreenManager& mgr) : CPasswordScreen(display, mgr)
|
||||
{
|
||||
_initUI();
|
||||
}
|
||||
|
||||
void
|
||||
CFuelMixtureScreen::onSelect()
|
||||
{
|
||||
CPasswordScreen::onSelect();
|
||||
_initUI();
|
||||
|
||||
adjPump[0] = getHeaterInfo().getPump_Min();
|
||||
adjPump[1] = getHeaterInfo().getPump_Max();
|
||||
adjFan[0] = getHeaterInfo().getFan_Min();
|
||||
adjFan[1] = getHeaterInfo().getFan_Max();
|
||||
}
|
||||
|
||||
void
|
||||
CFuelMixtureScreen::_initUI()
|
||||
{
|
||||
_rowSel = 0;
|
||||
_colSel = 0;
|
||||
}
|
||||
|
||||
bool
|
||||
CFuelMixtureScreen::show()
|
||||
{
|
||||
char str[16];
|
||||
int xPos, yPos;
|
||||
const int col2 = 90;
|
||||
const int col3 = _display.width() - border;
|
||||
|
||||
_display.clearDisplay();
|
||||
|
||||
if(!CPasswordScreen::show()) {
|
||||
switch(_rowSel) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
// Pump Minimum adjustment
|
||||
yPos = border + 36;
|
||||
_printMenuText(80, yPos, "Min", false, eRightJustify);
|
||||
sprintf(str, "%.1f", adjPump[0]);
|
||||
_printMenuText(col3, yPos, str, _rowSel == 1, eRightJustify);
|
||||
// Pump Maximum adjustment
|
||||
yPos = border + 24;
|
||||
_printMenuText(80, yPos, "Pump Hz Max", false, eRightJustify);
|
||||
sprintf(str, "%.1f", adjPump[1]);
|
||||
_printMenuText(col3, yPos, str, _rowSel == 2, eRightJustify);
|
||||
// Fan Minimum adjustment
|
||||
yPos = border + 12;
|
||||
_printMenuText(80, yPos, "Min", false, eRightJustify);
|
||||
sprintf(str, "%d", adjFan[0]);
|
||||
_printMenuText(col3, yPos, str, _rowSel == 3, eRightJustify);
|
||||
// Fan Maximum adjustment
|
||||
yPos = border;
|
||||
_printMenuText(80, yPos, "Fan RPM Max", false, eRightJustify);
|
||||
sprintf(str, "%d", adjFan[1]);
|
||||
_printMenuText(col3, yPos, str, _rowSel == 4, eRightJustify);
|
||||
// navigation line
|
||||
yPos = 53;
|
||||
xPos = _display.xCentre();
|
||||
switch(_rowSel) {
|
||||
case 0:
|
||||
_printMenuText(xPos, yPos, " \021 Exit \020 ", _rowSel == 0, eCentreJustify); // " < Exit > "
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
_display.drawFastHLine(0, 52, 128, WHITE);
|
||||
_printMenuText(xPos, 56, "\030\031Sel Save \033\032 \3600.1", false, eCentreJustify); // "^vSel Save <> +-0.1"
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
_display.drawFastHLine(0, 52, 128, WHITE);
|
||||
_printMenuText(xPos, 56, "\030\031Sel Save \033\032 \36010", false, eCentreJustify); // "^vSel Save <> +-10"
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 5:
|
||||
_printInverted(_display.xCentre(), 0, " Save Fuel Settings ", true, eCentreJustify);
|
||||
_printMenuText(_display.xCentre(), 35, "Press UP to", false, eCentreJustify);
|
||||
_printMenuText(_display.xCentre(), 43, "confirm save", false, eCentreJustify);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
CFuelMixtureScreen::keyHandler(uint8_t event)
|
||||
{
|
||||
if(event & keyPressed) {
|
||||
// press CENTRE
|
||||
if(event & key_Centre) {
|
||||
switch(_rowSel) {
|
||||
case 0:
|
||||
_ScreenManager.selectMenu(CScreenManager::RootMenuLoop);
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
_rowSel = 5; // enter save confirm mode
|
||||
break;
|
||||
case 5:
|
||||
_rowSel = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// press LEFT
|
||||
if(event & key_Left) {
|
||||
switch(_rowSel) {
|
||||
case 0:
|
||||
_ScreenManager.prevMenu();
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
_adjustSetting(-1);
|
||||
break;
|
||||
case 5:
|
||||
_rowSel = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// press RIGHT
|
||||
if(event & key_Right) {
|
||||
switch(_rowSel) {
|
||||
case 0:
|
||||
_ScreenManager.nextMenu();
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
_adjustSetting(+1);
|
||||
break;
|
||||
case 5:
|
||||
_rowSel = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// press UP
|
||||
if(event & key_Up) {
|
||||
if(hasOEMcontroller())
|
||||
_reqOEMWarning();
|
||||
else {
|
||||
switch(_rowSel) {
|
||||
case 0:
|
||||
// grab current settings upon entry to edit mode
|
||||
adjPump[0] = getHeaterInfo().getPump_Min();
|
||||
adjPump[1] = getHeaterInfo().getPump_Max();
|
||||
adjFan[0] = getHeaterInfo().getFan_Min();
|
||||
adjFan[1] = getHeaterInfo().getFan_Max();
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
_rowSel++;
|
||||
_colSel = 0;
|
||||
UPPERLIMIT(_rowSel, 4);
|
||||
break;
|
||||
case 5:
|
||||
_showStoringMessage();
|
||||
setPumpMin(adjPump[0]);
|
||||
setPumpMax(adjPump[1]);
|
||||
setFanMin(adjFan[0]);
|
||||
setFanMax(adjFan[1]);
|
||||
saveNV();
|
||||
_rowSel = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// press DOWN
|
||||
if(event & key_Down) {
|
||||
switch(_rowSel) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
_rowSel--;
|
||||
_colSel = 0;
|
||||
break;
|
||||
case 5:
|
||||
_rowSel = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
_ScreenManager.reqUpdate();
|
||||
}
|
||||
|
||||
|
||||
if(event & keyRepeat) {
|
||||
switch(_rowSel) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
int adj = 0;
|
||||
if(event & key_Right) adj = +1;
|
||||
if(event & key_Left) adj = -1;
|
||||
if(adj) {
|
||||
_adjustSetting(adj);
|
||||
}
|
||||
break;
|
||||
}
|
||||
_ScreenManager.reqUpdate();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CFuelMixtureScreen::_adjustSetting(int dir)
|
||||
{
|
||||
switch(_rowSel) {
|
||||
case 1:
|
||||
adjPump[0] += (float(dir) * 0.1f);
|
||||
break;
|
||||
case 2:
|
||||
adjPump[1] += (float(dir) * 0.1f);
|
||||
break;
|
||||
case 3:
|
||||
adjFan[0] += dir * 10;
|
||||
break;
|
||||
case 4:
|
||||
adjFan[1] += dir * 10;
|
||||
break;
|
||||
}
|
||||
LOWERLIMIT(adjPump[0], 0.5f);
|
||||
UPPERLIMIT(adjPump[0], 10.f);
|
||||
LOWERLIMIT(adjPump[1], 0.5f);
|
||||
UPPERLIMIT(adjPump[1], 10.f);
|
||||
LOWERLIMIT(adjFan[0], 1000);
|
||||
UPPERLIMIT(adjFan[0], 5000);
|
||||
LOWERLIMIT(adjFan[1], 1000);
|
||||
UPPERLIMIT(adjFan[1], 5000);
|
||||
}
|
|
@ -1,386 +0,0 @@
|
|||
/*
|
||||
* This file is part of the "bluetoothheater" distribution
|
||||
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
|
||||
*
|
||||
* Copyright (C) 2018 Ray Jones <ray@mrjones.id.au>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "128x64OLED.h"
|
||||
#include "GPIOScreen.h"
|
||||
#include "KeyPad.h"
|
||||
#include "../Protocol/helpers.h"
|
||||
#include "../Utility/UtilClasses.h"
|
||||
#include "../Utility/NVStorage.h"
|
||||
#include "../Utility/GPIO.h"
|
||||
#include "fonts/Icons.h"
|
||||
|
||||
extern CGPIOout GPIOout;
|
||||
extern CGPIOin GPIOin;
|
||||
extern CGPIOalg GPIOalg;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CGPIOScreen
|
||||
//
|
||||
// This screen provides control over GPIO features
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static const int Line3 = 14;
|
||||
static const int Line2 = 27;
|
||||
static const int Line1 = 40;
|
||||
//static const int Column = 58;
|
||||
static const int Column = 38;
|
||||
|
||||
CGPIOScreen::CGPIOScreen(C128x64_OLED& display, CScreenManager& mgr) : CPasswordScreen(display, mgr)
|
||||
{
|
||||
_initUI();
|
||||
_GPIOinMode = 0;
|
||||
_GPIOoutMode = 0;
|
||||
_GPIOalgMode = 0;
|
||||
}
|
||||
|
||||
void
|
||||
CGPIOScreen::onSelect()
|
||||
{
|
||||
CPasswordScreen::onSelect();
|
||||
_initUI();
|
||||
_GPIOinMode = NVstore.getGPIOinMode();
|
||||
_GPIOoutMode = NVstore.getGPIOoutMode();
|
||||
_GPIOalgMode = NVstore.getGPIOalgMode();
|
||||
}
|
||||
|
||||
void
|
||||
CGPIOScreen::_initUI()
|
||||
{
|
||||
_rowSel = 0;
|
||||
_animateCount = 0;
|
||||
}
|
||||
|
||||
bool
|
||||
CGPIOScreen::show()
|
||||
{
|
||||
_display.clearDisplay();
|
||||
|
||||
if(!CPasswordScreen::show()) { // for showing "saving settings"
|
||||
|
||||
if(_rowSel == 4) {
|
||||
_printInverted(_display.xCentre(), 0, " Saving Settings ", true, eCentreJustify);
|
||||
_printMenuText(_display.xCentre(), 35, "Press UP to", false, eCentreJustify);
|
||||
_printMenuText(_display.xCentre(), 43, "confirm save", false, eCentreJustify);
|
||||
}
|
||||
else {
|
||||
_printInverted(_display.xCentre(), 0, " GPIO Settings ", true, eCentreJustify);
|
||||
_display.drawBitmap(10, 14, GPIOIcon, GPIOWidth, GPIOHeight, WHITE);
|
||||
// _printMenuText(55, Line3, "Inputs:", false, eRightJustify);
|
||||
// _printMenuText(55, Line2, "Outputs:", false, eRightJustify);
|
||||
// _printMenuText(55, Line1, "Analogue:", false, eRightJustify);
|
||||
{
|
||||
const char* msgText = NULL;
|
||||
switch(_GPIOinMode) {
|
||||
case 0: msgText = "Disabled"; break;
|
||||
case 1: msgText = "1-On 2-Off"; break;
|
||||
case 2: msgText = "1-On 2-\352T"; break;
|
||||
case 3: msgText = "1-On/Off"; break;
|
||||
}
|
||||
if(msgText)
|
||||
_printMenuText(Column, Line3, msgText, _rowSel == 3);
|
||||
}
|
||||
|
||||
{
|
||||
const char* msgText = NULL;
|
||||
switch(_GPIOoutMode) {
|
||||
case 0: msgText = "Disabled"; break;
|
||||
case 1: msgText = "1: Status LED"; break;
|
||||
case 2: msgText = "1&2 User"; break;
|
||||
}
|
||||
if(msgText)
|
||||
_printMenuText(Column, Line2, msgText, _rowSel == 2);
|
||||
}
|
||||
|
||||
{
|
||||
const char* msgText = NULL;
|
||||
switch(_GPIOalgMode) {
|
||||
case 0: msgText = "Disabled"; break;
|
||||
case 1: msgText = "Ip1 allows"; break;
|
||||
}
|
||||
if(msgText)
|
||||
_printMenuText(Column, Line1, msgText, _rowSel == 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CGPIOScreen::animate()
|
||||
{
|
||||
if(_rowSel != 4) {
|
||||
int yPos = 53;
|
||||
int xPos = _display.xCentre();
|
||||
const char* pMsg = NULL;
|
||||
switch(_rowSel) {
|
||||
case 0:
|
||||
_printMenuText(xPos, yPos, " \021 \030Edit Exit \020 ", true, eCentreJustify);
|
||||
break;
|
||||
case 1:
|
||||
_display.drawFastHLine(0, 52, 128, WHITE);
|
||||
switch(_GPIOalgMode) {
|
||||
case 0: pMsg = " Analogue input is ignored. "; break;
|
||||
case 1: pMsg = " Input 1 enables reading of analogue input to set temperature. "; break;
|
||||
}
|
||||
if(pMsg)
|
||||
_scrollMessage(56, pMsg, _scrollChar);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
_display.drawFastHLine(0, 52, 128, WHITE);
|
||||
switch(_GPIOoutMode) {
|
||||
case 0: pMsg = " Digital outputs are disabled. "; break;
|
||||
case 1: pMsg = " Output1: LED status indicator. "; break;
|
||||
case 2: pMsg = " Output 1&2: User controlled. "; break;
|
||||
}
|
||||
if(pMsg)
|
||||
_scrollMessage(56, pMsg, _scrollChar);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
_display.drawFastHLine(0, 52, 128, WHITE);
|
||||
switch(_GPIOinMode) {
|
||||
case 0: pMsg = " Digital inputs are disabled. "; break;
|
||||
case 1: pMsg = " Input 1: Starts upon closure. Input 2: Stops upon closure. "; break;
|
||||
case 2: pMsg = " Input 1: Starts when held closed, stops when opened. Input2: Max fuel when closed, min fuel when open. "; break;
|
||||
case 3: pMsg = " Input 1: Starts or Stops upon closure. "; break;
|
||||
}
|
||||
if(pMsg)
|
||||
_scrollMessage(56, pMsg, _scrollChar);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
CGPIOScreen::keyHandler(uint8_t event)
|
||||
{
|
||||
if(event & keyPressed) {
|
||||
// press LEFT to select previous screen
|
||||
if(event & key_Left) {
|
||||
switch(_rowSel) {
|
||||
case 0:
|
||||
_ScreenManager.prevMenu();
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
_scrollChar = 0;
|
||||
_adjust(-1);
|
||||
break;
|
||||
case 4:
|
||||
_rowSel = 0; // abort save
|
||||
break;
|
||||
}
|
||||
}
|
||||
// press RIGHT to select next screen
|
||||
if(event & key_Right) {
|
||||
switch(_rowSel) {
|
||||
case 0:
|
||||
_ScreenManager.nextMenu();
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
_scrollChar = 0;
|
||||
_adjust(+1);
|
||||
break;
|
||||
case 4:
|
||||
_rowSel = 0; // abort save
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(event & key_Down) {
|
||||
_scrollChar = 0;
|
||||
_rowSel--;
|
||||
LOWERLIMIT(_rowSel, 0);
|
||||
}
|
||||
// UP press
|
||||
if(event & key_Up) {
|
||||
switch(_rowSel) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
_scrollChar = 0;
|
||||
_rowSel++;
|
||||
UPPERLIMIT(_rowSel, 3);
|
||||
break;
|
||||
case 4: // confirmed save
|
||||
_showStoringMessage();
|
||||
NVstore.setGPIOinMode(_GPIOinMode);
|
||||
NVstore.setGPIOoutMode(_GPIOoutMode);
|
||||
NVstore.setGPIOalgMode(_GPIOalgMode);
|
||||
saveNV();
|
||||
|
||||
setupGPIO();
|
||||
|
||||
_rowSel = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// CENTRE press
|
||||
if(event & key_Centre) {
|
||||
switch(_rowSel) {
|
||||
case 0:
|
||||
_ScreenManager.selectMenu(CScreenManager::RootMenuLoop); // force return to main menu
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
_rowSel = 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
_ScreenManager.reqUpdate();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CGPIOScreen::_adjust(int dir)
|
||||
{
|
||||
switch(_rowSel) {
|
||||
case 1: // analogue mode
|
||||
_GPIOalgMode += dir;
|
||||
UPPERLIMIT(_GPIOalgMode, 1);
|
||||
LOWERLIMIT(_GPIOalgMode, 0);
|
||||
break;
|
||||
case 2: // outputs mode
|
||||
_GPIOoutMode += dir;
|
||||
ROLLLOWERLIMIT(_GPIOoutMode, 0, 2);
|
||||
ROLLUPPERLIMIT(_GPIOoutMode, 2, 0);
|
||||
break;
|
||||
case 3:
|
||||
_GPIOinMode += dir;
|
||||
ROLLUPPERLIMIT(_GPIOinMode, 3, 0);
|
||||
ROLLLOWERLIMIT(_GPIOinMode, 0, 3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
CGPIOInfoScreen::CGPIOInfoScreen(C128x64_OLED& display, CScreenManager& mgr) : CScreenHeader(display, mgr)
|
||||
{
|
||||
_keyRepeatCount = -1;
|
||||
}
|
||||
|
||||
void
|
||||
CGPIOInfoScreen::onSelect()
|
||||
{
|
||||
CScreenHeader::onSelect();
|
||||
}
|
||||
|
||||
void
|
||||
CGPIOInfoScreen::_initUI()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
CGPIOInfoScreen::show()
|
||||
{
|
||||
CScreenHeader::show();
|
||||
char msg[16];
|
||||
|
||||
_display.writeFillRect(49, 18, 30, 12, WHITE);
|
||||
_printInverted(64, 20, "GPIO", true, eCentreJustify);
|
||||
_printMenuText(22, 18, "In", false, eCentreJustify);
|
||||
_printMenuText(104, 18, "Out", false, eCentreJustify);
|
||||
_printMenuText(11, 20, "1", false, eCentreJustify);
|
||||
_printMenuText(34, 20, "2", false, eCentreJustify);
|
||||
_printMenuText(91, 20, "1", false, eCentreJustify);
|
||||
_printMenuText(118, 20, "2", false, eCentreJustify);
|
||||
|
||||
_printMenuText(55, Line1, "Analogue:", false, eRightJustify);
|
||||
|
||||
_display.drawBitmap(4, 29, GPIOin.getState(0) ? CloseIcon : OpenIcon, CloseIconWidth, CloseIconHeight, WHITE);
|
||||
_display.drawBitmap(27, 29, GPIOin.getState(1) ? CloseIcon : OpenIcon, CloseIconWidth, CloseIconHeight, WHITE);
|
||||
|
||||
_display.drawBitmap(86, 29, GPIOout.getState(0) ? BulbOnIcon : BulbOffIcon, BulbOnIconWidth, BulbOnIconHeight, WHITE);
|
||||
_display.drawBitmap(113, 29, GPIOout.getState(1) ? BulbOnIcon : BulbOffIcon, BulbOnIconWidth, BulbOnIconHeight, WHITE);
|
||||
|
||||
sprintf(msg, "%d", GPIOalg.getValue());
|
||||
_printMenuText(58, Line1, msg);
|
||||
|
||||
_printMenuText(_display.xCentre(), 53, " \021 \020 ", true, eCentreJustify);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
CGPIOInfoScreen::keyHandler(uint8_t event)
|
||||
{
|
||||
if(event & keyPressed) {
|
||||
_keyRepeatCount = 0; // unlock tracking of repeat events
|
||||
// UP press
|
||||
if(event & key_Up) {
|
||||
}
|
||||
// CENTRE press
|
||||
if(event & key_Centre) {
|
||||
}
|
||||
}
|
||||
if(event & keyRepeat) {
|
||||
if(_keyRepeatCount >= 0) {
|
||||
_keyRepeatCount++;
|
||||
// hold LEFT to toggle GPIO output #1
|
||||
if(event & key_Left) {
|
||||
if(_keyRepeatCount > 2) {
|
||||
_keyRepeatCount = -1; // prevent double handling
|
||||
setGPIO(0, !getGPIO(0)); // toggle GPIO output #1
|
||||
}
|
||||
}
|
||||
// hold RIGHT to toggle GPIO output #2
|
||||
if(event & key_Right) {
|
||||
if(_keyRepeatCount > 2) {
|
||||
_keyRepeatCount = -1; // prevent double handling
|
||||
setGPIO(1, !getGPIO(1)); // toggle GPIO output #2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// release event
|
||||
if(event & keyReleased) {
|
||||
if(_keyRepeatCount == 0) { // short Up press - lower target
|
||||
// press LEFT to select previous screen
|
||||
if(event & key_Left) {
|
||||
_ScreenManager.prevMenu();
|
||||
}
|
||||
// press RIGHT to select next screen
|
||||
if(event & key_Right) {
|
||||
_ScreenManager.nextMenu();
|
||||
}
|
||||
}
|
||||
_keyRepeatCount = -1;
|
||||
}
|
||||
_ScreenManager.reqUpdate();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1,216 +0,0 @@
|
|||
/*
|
||||
* This file is part of the "bluetoothheater" distribution
|
||||
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
|
||||
*
|
||||
* Copyright (C) 2018 Ray Jones <ray@mrjones.id.au>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "128x64OLED.h"
|
||||
#include "HomeMenuSelScreen.h"
|
||||
#include "KeyPad.h"
|
||||
#include "../Protocol/helpers.h"
|
||||
#include "../Utility/UtilClasses.h"
|
||||
#include "../Utility/NVStorage.h"
|
||||
#include "../Utility/GPIO.h"
|
||||
#include "fonts/Icons.h"
|
||||
|
||||
|
||||
|
||||
CHomeMenuSelScreen::CHomeMenuSelScreen(C128x64_OLED& display, CScreenManager& mgr) : CPasswordScreen(display, mgr)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
CHomeMenuSelScreen::onSelect()
|
||||
{
|
||||
CScreenHeader::onSelect();
|
||||
_rowSel = 0;
|
||||
_action = NVstore.getHomeMenu();
|
||||
}
|
||||
|
||||
void
|
||||
CHomeMenuSelScreen::_initUI()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
CHomeMenuSelScreen::show()
|
||||
{
|
||||
char msg[16];
|
||||
|
||||
_display.clearDisplay();
|
||||
|
||||
if(!CPasswordScreen::show()) { // for showing "saving settings"
|
||||
|
||||
if(_rowSel == 4) {
|
||||
_printInverted(_display.xCentre(), 0, " Saving Settings ", true, eCentreJustify);
|
||||
_printMenuText(_display.xCentre(), 35, "Press UP to", false, eCentreJustify);
|
||||
_printMenuText(_display.xCentre(), 43, "confirm save", false, eCentreJustify);
|
||||
}
|
||||
else {
|
||||
_printInverted(_display.xCentre(), 0, " Home Menu Actions ", true, eCentreJustify);
|
||||
|
||||
// _printMenuText(66, 14, "On timeout:", false, eRightJustify);
|
||||
_display.drawBitmap(30, 14, timeoutIcon, timeoutWidth, timeoutHeight, WHITE);
|
||||
switch(_action.onTimeout) {
|
||||
case 0: strcpy(msg, "Default"); break;
|
||||
case 1: strcpy(msg, "Detailed"); break;
|
||||
case 2: strcpy(msg, "Basic"); break;
|
||||
case 3: strcpy(msg, "Clock"); break;
|
||||
}
|
||||
_printMenuText(50, 14, msg, _rowSel == 3);
|
||||
|
||||
// _printMenuText(66, 26, "On start:", false, eRightJustify);
|
||||
_display.drawBitmap(32, 26, startIcon, startWidth, startHeight, WHITE);
|
||||
switch(_action.onStart) {
|
||||
case 0: strcpy(msg, "Default"); break;
|
||||
case 1: strcpy(msg, "Detailed"); break;
|
||||
case 2: strcpy(msg, "Basic"); break;
|
||||
case 3: strcpy(msg, "Clock"); break;
|
||||
}
|
||||
_printMenuText(50, 26, msg, _rowSel == 2);
|
||||
|
||||
// _printMenuText(66, 38, "On stop:", false, eRightJustify);
|
||||
_display.drawBitmap(31, 38, stopIcon, stopWidth, stopHeight, WHITE);
|
||||
switch(_action.onStop) {
|
||||
case 0: strcpy(msg, "Default"); break;
|
||||
case 1: strcpy(msg, "Detailed"); break;
|
||||
case 2: strcpy(msg, "Basic"); break;
|
||||
case 3: strcpy(msg, "Clock"); break;
|
||||
}
|
||||
_printMenuText(50, 38, msg, _rowSel == 1);
|
||||
|
||||
/* if(_rowSel == 0)
|
||||
_printMenuText(_display.xCentre(), 53, " \021 \030Edit Exit \020 ", true, eCentreJustify);
|
||||
else {
|
||||
_display.drawFastHLine(0, 52, 128, WHITE);
|
||||
_printMenuText(_display.xCentre(), 56, "\030\031Sel \033\032 Adj", false, eCentreJustify);
|
||||
_printMenuText(_display.xCentre(), 56, "Save", false, eCentreJustify);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CHomeMenuSelScreen::animate()
|
||||
{
|
||||
if(_rowSel != 4) {
|
||||
int yPos = 53;
|
||||
int xPos = _display.xCentre();
|
||||
const char* pMsg = NULL;
|
||||
switch(_rowSel) {
|
||||
case 0:
|
||||
_printMenuText(xPos, yPos, " \021 \030Edit Exit \020 ", true, eCentreJustify);
|
||||
break;
|
||||
case 1:
|
||||
_display.drawFastHLine(0, 52, 128, WHITE);
|
||||
pMsg = " Menu to switch to when the heater stops. ";
|
||||
_scrollMessage(56, pMsg, _scrollChar);
|
||||
break;
|
||||
case 2:
|
||||
_display.drawFastHLine(0, 52, 128, WHITE);
|
||||
pMsg = " Menu to switch to when the heater starts. ";
|
||||
_scrollMessage(56, pMsg, _scrollChar);
|
||||
break;
|
||||
case 3:
|
||||
_display.drawFastHLine(0, 52, 128, WHITE);
|
||||
pMsg = " Menu to return to after no keypad activity. ";
|
||||
_scrollMessage(56, pMsg, _scrollChar);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
CHomeMenuSelScreen::keyHandler(uint8_t event)
|
||||
{
|
||||
if(event & keyPressed) {
|
||||
// UP press
|
||||
if(event & key_Up) {
|
||||
if(_rowSel == 4) {
|
||||
_showStoringMessage();
|
||||
NVstore.setHomeMenu(_action);
|
||||
saveNV();
|
||||
_rowSel = 0;
|
||||
}
|
||||
else {
|
||||
_scrollChar = 0;
|
||||
_rowSel++;
|
||||
UPPERLIMIT(_rowSel, 3);
|
||||
}
|
||||
}
|
||||
// UP press
|
||||
if(event & key_Down) {
|
||||
_scrollChar = 0;
|
||||
_rowSel--;
|
||||
LOWERLIMIT(_rowSel, 0);
|
||||
}
|
||||
// CENTRE press
|
||||
if(event & key_Centre) {
|
||||
if(_rowSel == 0) {
|
||||
_ScreenManager.selectMenu(CScreenManager::RootMenuLoop); // force return to main menu
|
||||
}
|
||||
else {
|
||||
_rowSel = 4;
|
||||
}
|
||||
}
|
||||
// LEFT press
|
||||
if(event & key_Left) {
|
||||
if(_rowSel == 0)
|
||||
_ScreenManager.prevMenu();
|
||||
else
|
||||
adjust(-1);
|
||||
}
|
||||
// RIGHT press
|
||||
if(event & key_Right) {
|
||||
if(_rowSel == 0)
|
||||
_ScreenManager.nextMenu();
|
||||
else
|
||||
adjust(+1);
|
||||
}
|
||||
}
|
||||
|
||||
_ScreenManager.reqUpdate();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CHomeMenuSelScreen::adjust(int dir)
|
||||
{
|
||||
switch(_rowSel) {
|
||||
case 1:
|
||||
_action.onStop += dir;
|
||||
ROLLLOWERLIMIT(_action.onStop, 0, 3);
|
||||
ROLLUPPERLIMIT(_action.onStop, 3, 0);
|
||||
break;
|
||||
case 2:
|
||||
_action.onStart += dir;
|
||||
ROLLLOWERLIMIT(_action.onStart, 0, 3);
|
||||
ROLLUPPERLIMIT(_action.onStart, 3, 0);
|
||||
break;
|
||||
case 3:
|
||||
_action.onTimeout += dir;
|
||||
ROLLLOWERLIMIT(_action.onTimeout, 0, 3);
|
||||
ROLLUPPERLIMIT(_action.onTimeout, 3, 0);
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -1,235 +0,0 @@
|
|||
/*
|
||||
* This file is part of the "bluetoothheater" distribution
|
||||
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
|
||||
*
|
||||
* Copyright (C) 2018 Ray Jones <ray@mrjones.id.au>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "128x64OLED.h"
|
||||
#include "OtherOptionsScreen.h"
|
||||
#include "KeyPad.h"
|
||||
#include "../Protocol/helpers.h"
|
||||
#include "../Utility/UtilClasses.h"
|
||||
#include "../Utility/NVStorage.h"
|
||||
#include "../Utility/GPIO.h"
|
||||
#include "fonts/Icons.h"
|
||||
|
||||
|
||||
|
||||
COtherOptionsScreen::COtherOptionsScreen(C128x64_OLED& display, CScreenManager& mgr) : CPasswordScreen(display, mgr)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
COtherOptionsScreen::onSelect()
|
||||
{
|
||||
CScreenHeader::onSelect();
|
||||
_rowSel = 0;
|
||||
_repeatCount = -1;
|
||||
_frameRate = NVstore.getFrameRate();
|
||||
_dispTimeout = NVstore.getDimTime();
|
||||
_menuTimeout = 60000;
|
||||
}
|
||||
|
||||
void
|
||||
COtherOptionsScreen::_initUI()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
COtherOptionsScreen::show()
|
||||
{
|
||||
char msg[16];
|
||||
|
||||
_display.clearDisplay();
|
||||
|
||||
if(!CPasswordScreen::show()) { // for showing "saving settings"
|
||||
|
||||
if(_rowSel == 4) {
|
||||
_printInverted(_display.xCentre(), 0, " Saving Settings ", true, eCentreJustify);
|
||||
_printMenuText(_display.xCentre(), 35, "Press UP to", false, eCentreJustify);
|
||||
_printMenuText(_display.xCentre(), 43, "confirm save", false, eCentreJustify);
|
||||
}
|
||||
else {
|
||||
_printInverted(_display.xCentre(), 0, " Time Intervals ", true, eCentreJustify);
|
||||
|
||||
// data frame refresh rate
|
||||
_display.drawBitmap(15, 13, refreshIcon, refreshWidth, refreshHeight, WHITE);
|
||||
sprintf(msg, "%dms", _frameRate);
|
||||
_printMenuText(40, 14, msg, _rowSel == 3);
|
||||
|
||||
// display timeout
|
||||
_display.drawBitmap(10, 26, displayTimeoutIcon, displayTimeoutWidth, displayTimeoutHeight, WHITE);
|
||||
if(_dispTimeout) {
|
||||
float mins = float(abs(_dispTimeout)) / 60000.f;
|
||||
sprintf(msg, "%s %0.1f min%s", (_dispTimeout < 0) ? "Blank" : "Dim", mins, mins < 2 ? "" : "s");
|
||||
_printMenuText(40, 26, msg, _rowSel == 2);
|
||||
}
|
||||
else
|
||||
_printMenuText(40, 26, "Always on", _rowSel == 2);
|
||||
|
||||
// menu timeout
|
||||
_display.drawBitmap(10, 38, menuTimeoutIcon, menuTimeoutWidth, menuTimeoutHeight, WHITE);
|
||||
if(_menuTimeout) {
|
||||
float mins = float(abs(_menuTimeout)) / 60000.f;
|
||||
sprintf(msg, "Home %0.1f min%s", mins, mins < 2 ? "" : "s");
|
||||
_printMenuText(40, 38, msg, _rowSel == 1);
|
||||
}
|
||||
else
|
||||
_printMenuText(40, 38, "Disabled", _rowSel == 1);
|
||||
|
||||
/* if(_rowSel == 0)
|
||||
_printMenuText(_display.xCentre(), 53, " \021 Exit \020 ", _rowSel == 0, eCentreJustify);
|
||||
else {
|
||||
_display.drawFastHLine(0, 52, 128, WHITE);
|
||||
_printMenuText(_display.xCentre(), 56, "\030\031Sel \033\032 Adj", false, eCentreJustify);
|
||||
_printMenuText(_display.xCentre(), 56, "Save", false, eCentreJustify);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
COtherOptionsScreen::animate()
|
||||
{
|
||||
if(_rowSel != 4) {
|
||||
int yPos = 53;
|
||||
int xPos = _display.xCentre();
|
||||
const char* pMsg = NULL;
|
||||
switch(_rowSel) {
|
||||
case 0:
|
||||
_printMenuText(xPos, yPos, " \021 \030Edit Exit \020 ", true, eCentreJustify);
|
||||
break;
|
||||
case 1:
|
||||
_display.drawFastHLine(0, 52, 128, WHITE);
|
||||
pMsg = " No keypad activity returns to the home menu. ";
|
||||
_scrollMessage(56, pMsg, _scrollChar);
|
||||
break;
|
||||
case 2:
|
||||
_display.drawFastHLine(0, 52, 128, WHITE);
|
||||
pMsg = " No keypad activity either dims or blanks the display. Hold Left or Right to toggle Dim/Blank mode. ";
|
||||
_scrollMessage(56, pMsg, _scrollChar);
|
||||
break;
|
||||
case 3:
|
||||
_display.drawFastHLine(0, 52, 128, WHITE);
|
||||
pMsg = " Define the polling rate of the bluewire communications. ";
|
||||
_scrollMessage(56, pMsg, _scrollChar);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
COtherOptionsScreen::keyHandler(uint8_t event)
|
||||
{
|
||||
if(event & keyPressed) {
|
||||
_repeatCount = 0;
|
||||
// UP press
|
||||
if(event & key_Up) {
|
||||
if(_rowSel == 4) {
|
||||
_showStoringMessage();
|
||||
NVstore.setFrameRate(_frameRate);
|
||||
NVstore.setDimTime(_dispTimeout);
|
||||
saveNV();
|
||||
_rowSel = 0;
|
||||
}
|
||||
else {
|
||||
_scrollChar = 0;
|
||||
_rowSel++;
|
||||
UPPERLIMIT(_rowSel, 3);
|
||||
}
|
||||
}
|
||||
// UP press
|
||||
if(event & key_Down) {
|
||||
_scrollChar = 0;
|
||||
_rowSel--;
|
||||
LOWERLIMIT(_rowSel, 0);
|
||||
}
|
||||
// CENTRE press
|
||||
if(event & key_Centre) {
|
||||
if(_rowSel == 0) {
|
||||
_ScreenManager.selectMenu(CScreenManager::RootMenuLoop); // force return to main menu
|
||||
}
|
||||
else {
|
||||
_rowSel = 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(event & keyRepeat) {
|
||||
if(keyRepeat >= 0) {
|
||||
_repeatCount++;
|
||||
if(_repeatCount > 4) {
|
||||
// LEFT or RIGHT hold
|
||||
if(event & (key_Right | key_Left)) {
|
||||
if(_rowSel == 2) {
|
||||
_repeatCount = -1;
|
||||
_dispTimeout = -_dispTimeout;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(event & keyReleased) {
|
||||
if(_repeatCount == 0) {
|
||||
// LEFT short press
|
||||
if(event & key_Left) {
|
||||
if(_rowSel == 0)
|
||||
_ScreenManager.prevMenu();
|
||||
else
|
||||
adjust(-1);
|
||||
}
|
||||
// RIGHT short press
|
||||
if(event & key_Right) {
|
||||
if(_rowSel == 0)
|
||||
_ScreenManager.nextMenu();
|
||||
else
|
||||
adjust(+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ScreenManager.reqUpdate();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
COtherOptionsScreen::adjust(int dir)
|
||||
{
|
||||
switch(_rowSel) {
|
||||
case 1:
|
||||
_menuTimeout += dir * 30000;
|
||||
LOWERLIMIT(_menuTimeout, 0);
|
||||
UPPERLIMIT(_menuTimeout, 300000);
|
||||
break;
|
||||
case 2:
|
||||
_dispTimeout += dir * 30000;
|
||||
LOWERLIMIT(_dispTimeout, -600000);
|
||||
UPPERLIMIT(_dispTimeout, 600000);
|
||||
break;
|
||||
case 3:
|
||||
_frameRate += dir * 50;
|
||||
LOWERLIMIT(_frameRate, 300);
|
||||
UPPERLIMIT(_frameRate, 1500);
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -1,252 +0,0 @@
|
|||
/*
|
||||
* This file is part of the "bluetoothheater" distribution
|
||||
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
|
||||
*
|
||||
* Copyright (C) 2018 Ray Jones <ray@mrjones.id.au>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "PrimingScreen.h"
|
||||
#include "KeyPad.h"
|
||||
#include "../Protocol/helpers.h"
|
||||
#include "../Utility/NVStorage.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CPrimingScreen
|
||||
//
|
||||
// This screen allows the temperature control mode to be selected and
|
||||
// allows pump priming
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
CPrimingScreen::CPrimingScreen(C128x64_OLED& display, CScreenManager& mgr) : CScreenHeader(display, mgr)
|
||||
{
|
||||
_initUI();
|
||||
}
|
||||
|
||||
void
|
||||
CPrimingScreen::onSelect()
|
||||
{
|
||||
_stopPump();
|
||||
_initUI();
|
||||
}
|
||||
|
||||
void
|
||||
CPrimingScreen::onExit()
|
||||
{
|
||||
_stopPump();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CPrimingScreen::_initUI()
|
||||
{
|
||||
_PrimeStop = 0;
|
||||
_PrimeCheck = 0;
|
||||
_rowSel = 0;
|
||||
_colSel = 0;
|
||||
}
|
||||
|
||||
bool
|
||||
CPrimingScreen::show()
|
||||
{
|
||||
CScreenHeader::show();
|
||||
|
||||
CRect extents;
|
||||
|
||||
int yPos = 53;
|
||||
// show next/prev menu navigation line
|
||||
switch(_rowSel) {
|
||||
case 0:
|
||||
_printMenuText(_display.xCentre(), yPos, " \021 \030Edit \020 ", _rowSel == 0, eCentreJustify);
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
_display.drawFastHLine(0, 53, 128, WHITE);
|
||||
_printMenuText(_display.xCentre(), 57, "\030\031 Sel \033\032 Adj", false, eCentreJustify);
|
||||
break;
|
||||
case 3:
|
||||
_display.drawFastHLine(0, 53, 128, WHITE);
|
||||
if(_colSel == 2) {
|
||||
_printMenuText(_display.xCentre(), 57, "\033\030\031 Stop", false, eCentreJustify);
|
||||
}
|
||||
else {
|
||||
_printMenuText(_display.xCentre(), 57, "\032 Start \031 Sel", false, eCentreJustify);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
yPos = 40;
|
||||
if(_rowSel == 1) {
|
||||
// follow user desired setting, heater info is laggy
|
||||
_printMenuText(border, yPos, "Thermostat", _colSel == 0);
|
||||
_printMenuText(_display.width()-border, yPos, "Fixed Hz", _colSel == 1, eRightJustify);
|
||||
}
|
||||
else {
|
||||
// follow actual heater settings
|
||||
// int col = getHeaterInfo().isThermostat() ? 0 : 1;
|
||||
int col = getThermostatModeActive() ? 0 : 1;
|
||||
_printInverted(border, yPos, "Thermostat", col == 0);
|
||||
_printInverted(_display.width()-border, yPos, "Fixed Hz", col == 1, eRightJustify);
|
||||
}
|
||||
yPos = 28;
|
||||
if(_rowSel == 2) {
|
||||
_printMenuText(border, yPos, "degC", _colSel == 0);
|
||||
_printMenuText(_display.width()-border, yPos, "degF", _colSel == 1, eRightJustify);
|
||||
}
|
||||
else {
|
||||
int col = NVstore.getDegFMode();
|
||||
_printInverted(border, yPos, "degC", col == 0);
|
||||
_printInverted(_display.width()-border, yPos, "degF", col == 1, eRightJustify);
|
||||
}
|
||||
|
||||
// fuel pump priming menu
|
||||
yPos = 16;
|
||||
_printMenuText(border, yPos, "Pump");
|
||||
if(_rowSel == 3) {
|
||||
_printMenuText(40, yPos, "OFF", _colSel == 1);
|
||||
if(_colSel != 2) {
|
||||
if(!getHeaterInfo().getRunState()) { // prevent option if heater is running
|
||||
_printMenuText(70, yPos, "ON"); // becomes Hz when actually priming
|
||||
}
|
||||
}
|
||||
else {
|
||||
float pumpHz = getHeaterInfo().getPump_Actual();
|
||||
// recognise if heater has stopped pump, after an initial holdoff upon first starting
|
||||
long tDelta = millis() - _PrimeCheck;
|
||||
if(_PrimeCheck && tDelta > 0 && pumpHz < 0.1) {
|
||||
_stopPump();
|
||||
}
|
||||
// test if time is up, stop priming if so
|
||||
tDelta = millis() - _PrimeStop;
|
||||
if(_PrimeStop && tDelta > 0) {
|
||||
_stopPump();
|
||||
}
|
||||
|
||||
if(_PrimeStop) {
|
||||
char msg[16];
|
||||
sprintf(msg, "%.1fHz", pumpHz);
|
||||
_printMenuText(70, yPos, msg, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
CPrimingScreen::keyHandler(uint8_t event)
|
||||
{
|
||||
|
||||
if(event & keyPressed) {
|
||||
// press LEFT
|
||||
if(event & key_Left) {
|
||||
switch(_rowSel) {
|
||||
case 0:
|
||||
_ScreenManager.prevMenu();
|
||||
break;
|
||||
case 1:
|
||||
_colSel = 0;
|
||||
setThermostatMode(1);
|
||||
saveNV();
|
||||
break;
|
||||
case 2:
|
||||
_colSel = 0;
|
||||
NVstore.setDegFMode(0);
|
||||
break;
|
||||
case 3:
|
||||
_colSel = 1;
|
||||
break;
|
||||
case 4: break;
|
||||
}
|
||||
}
|
||||
// press RIGHT
|
||||
if(event & key_Right) {
|
||||
switch(_rowSel) {
|
||||
case 0:
|
||||
_ScreenManager.nextMenu();
|
||||
break;
|
||||
case 1:
|
||||
_colSel = 1;
|
||||
setThermostatMode(0);
|
||||
saveNV();
|
||||
break;
|
||||
case 2:
|
||||
_colSel = 1;
|
||||
NVstore.setDegFMode(1);
|
||||
break;
|
||||
case 3:
|
||||
if(!getHeaterInfo().getRunState())
|
||||
_colSel = 2;
|
||||
break;
|
||||
case 4: break;
|
||||
}
|
||||
}
|
||||
// press UP
|
||||
if(event & key_Up) {
|
||||
if(hasOEMcontroller())
|
||||
_reqOEMWarning();
|
||||
else {
|
||||
_rowSel++;
|
||||
UPPERLIMIT(_rowSel, 3);
|
||||
if(_rowSel == 3)
|
||||
_colSel = 1; // select OFF upon entry to priming menu
|
||||
if(_rowSel == 2)
|
||||
_colSel = NVstore.getDegFMode();
|
||||
if(_rowSel == 1)
|
||||
// _colSel = getHeaterInfo().isThermostat() ? 0 : 1;
|
||||
_colSel = getThermostatModeActive() ? 0 : 1;
|
||||
}
|
||||
}
|
||||
// press DOWN
|
||||
if(event & key_Down) {
|
||||
_rowSel--;
|
||||
LOWERLIMIT(_rowSel, 0);
|
||||
_colSel = 0;
|
||||
if(_rowSel == 1)
|
||||
// _colSel = getHeaterInfo().isThermostat() ? 0 : 1;
|
||||
_colSel = getThermostatModeActive() ? 0 : 1;
|
||||
if(_rowSel == 2)
|
||||
_colSel = NVstore.getDegFMode();
|
||||
}
|
||||
|
||||
// check if fuel priming was selected
|
||||
if(_rowSel == 3 && _colSel == 2) {
|
||||
reqPumpPrime(true);
|
||||
_PrimeStop = millis() + 150000; // allow 2.5 minutes - much the same as the heater itself cuts out at
|
||||
_PrimeCheck = millis() + 3000; // holdoff upon start before testing for heater shutting off pump
|
||||
}
|
||||
else {
|
||||
_stopPump();
|
||||
}
|
||||
|
||||
_ScreenManager.reqUpdate();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CPrimingScreen::_stopPump()
|
||||
{
|
||||
reqPumpPrime(false);
|
||||
_PrimeCheck = 0;
|
||||
_PrimeStop = 0;
|
||||
if(_colSel == 2)
|
||||
_colSel = 1;
|
||||
}
|
|
@ -1,292 +0,0 @@
|
|||
/*
|
||||
* This file is part of the "bluetoothheater" distribution
|
||||
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
|
||||
*
|
||||
* Copyright (C) 2018 Ray Jones <ray@mrjones.id.au>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "ScreenHeader.h"
|
||||
#include "../Protocol/Protocol.h"
|
||||
#include "../Protocol/helpers.h"
|
||||
#include "../Wifi/BTCWifi.h"
|
||||
#include "../Bluetooth/BluetoothAbstract.h"
|
||||
#include "../Utility/NVStorage.h"
|
||||
#include "../RTC/Clock.h"
|
||||
#include "fonts/Arial.h"
|
||||
#include "fonts/Icons.h"
|
||||
#include "fonts/MiniFont.h"
|
||||
#include "../RTC/TimerManager.h"
|
||||
|
||||
|
||||
#define MINIFONT miniFontInfo
|
||||
|
||||
#define X_BT_ICON 10
|
||||
#define Y_BT_ICON 0
|
||||
#define X_WIFI_ICON 19
|
||||
#define Y_WIFI_ICON 0
|
||||
#define X_CLOCK 50
|
||||
#define Y_CLOCK 0
|
||||
#define X_TIMER_ICON 83
|
||||
#define Y_TIMER_ICON 0
|
||||
#define X_BATT_ICON 103
|
||||
#define Y_BATT_ICON 0
|
||||
|
||||
/*#define X_BT_ICON 20
|
||||
#define Y_BT_ICON 0
|
||||
#define X_WIFI_ICON 29
|
||||
#define Y_WIFI_ICON 0
|
||||
#define X_GPIO_ICON 9
|
||||
#define X_CLOCK 56
|
||||
#define Y_CLOCK 0
|
||||
#define X_TIMER_ICON 84
|
||||
#define Y_TIMER_ICON 0
|
||||
#define X_BATT_ICON 103
|
||||
#define Y_BATT_ICON 0*/
|
||||
|
||||
|
||||
CScreenHeader::CScreenHeader(C128x64_OLED& disp, CScreenManager& mgr) : CScreen(disp, mgr)
|
||||
{
|
||||
_clearUpAnimation = false;
|
||||
_clearDnAnimation = false;
|
||||
_colon = false;
|
||||
}
|
||||
|
||||
bool
|
||||
CScreenHeader::show()
|
||||
{
|
||||
_display.clearDisplay();
|
||||
|
||||
// standard header items
|
||||
// Bluetooth
|
||||
showBTicon();
|
||||
|
||||
// WiFi
|
||||
showWifiIcon();
|
||||
|
||||
// battery
|
||||
showBatteryIcon(getHeaterInfo().getBattVoltage());
|
||||
|
||||
// timers
|
||||
int numTimers = showTimers();
|
||||
|
||||
// // GPIO
|
||||
// showGPIO();
|
||||
|
||||
// clock
|
||||
showTime(numTimers);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Animate IN/OUT arrows against the WiFi icon, according to actual web server traffic:
|
||||
// an IN (down) arrow is drawn if incoming data has been detected.
|
||||
// an OUT (up) arrow is drawn if outgoing data has been sent.
|
||||
//
|
||||
// Each arrow is drawn for one animation interval with a minimum of one clear interval
|
||||
// creating a clean flash on the display.
|
||||
// Both arrows may appear in the same interval.
|
||||
// The following is a typical sequence, relative to animation ticks, note the gap
|
||||
// that always appears in the animation interval between either arrow shown:
|
||||
//
|
||||
// | | | | | | | | | | | | | | | | |
|
||||
// _________^^^^^________________________________________^^^^^_________________________
|
||||
// ______________vvvvv_____vvvvv_______________vvvvv_____vvvvv_____vvvvv_______________
|
||||
|
||||
bool
|
||||
CScreenHeader::animate()
|
||||
{
|
||||
bool retval = false;
|
||||
if((isWifiConnected() || isWifiAP()) && isWebClientConnected()) {
|
||||
|
||||
int xPos = X_WIFI_ICON + W_WIFI_ICON;
|
||||
if(isWifiAP()) {
|
||||
xPos += 4;
|
||||
}
|
||||
|
||||
// UP arrow animation
|
||||
//
|
||||
int yPos = 0;
|
||||
if(_clearUpAnimation) {
|
||||
// arrow was drawn in the prior iteration, now erase it
|
||||
_display.fillRect(xPos, yPos, W_WIFIIN_ICON, H_WIFIIN_ICON, BLACK);
|
||||
retval = true;
|
||||
_clearUpAnimation = false;
|
||||
}
|
||||
else if(hasWebServerSpoken(true)) {
|
||||
// we have emitted data to the web client, show an UP arrow
|
||||
_display.drawBitmap(xPos, yPos, wifiOutIcon, W_WIFIIN_ICON, H_WIFIIN_ICON, WHITE);
|
||||
_clearUpAnimation = true; // clear arrow upon next iteration
|
||||
retval = true;
|
||||
}
|
||||
|
||||
// DOWN arrow animation
|
||||
//
|
||||
yPos = H_WIFI_ICON - H_WIFIIN_ICON + 1;
|
||||
if(_clearDnAnimation) {
|
||||
// arrow was drawn in the prior iteration, now erase it
|
||||
_display.fillRect(xPos, yPos, W_WIFIOUT_ICON, H_WIFIOUT_ICON, BLACK);
|
||||
retval = true;
|
||||
_clearDnAnimation = false;
|
||||
}
|
||||
else if(hasWebClientSpoken(true)) {
|
||||
// we have receievd data from the web client, show an DOWN arrow
|
||||
_display.drawBitmap(xPos, yPos, wifiInIcon, W_WIFIOUT_ICON, H_WIFIOUT_ICON, WHITE);
|
||||
_clearDnAnimation = true; // clear arrow upon next iteration
|
||||
retval = true;
|
||||
}
|
||||
}
|
||||
return retval; // true if we need to update the physical display
|
||||
}
|
||||
|
||||
void
|
||||
CScreenHeader::showBTicon()
|
||||
{
|
||||
if(getBluetoothClient().isConnected()) {
|
||||
_display.drawBitmap(X_BT_ICON, Y_BT_ICON, BTicon, W_BT_ICON, H_BT_ICON, WHITE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CScreenHeader::showWifiIcon()
|
||||
{
|
||||
if(isWifiConnected() || isWifiAP()) {
|
||||
_display.drawBitmap(X_WIFI_ICON, Y_WIFI_ICON, wifiIcon, W_WIFI_ICON, H_WIFI_ICON, WHITE);
|
||||
if(isWifiButton()) {
|
||||
_display.fillRect(X_WIFI_ICON + 11, Y_WIFI_ICON + 5, 15, 7, BLACK);
|
||||
CTransientFont AF(_display, &MINIFONT); // temporarily use a mini font
|
||||
_display.setCursor(X_WIFI_ICON+12, Y_WIFI_ICON+6);
|
||||
switch(isWifiButton()) {
|
||||
case 1: _display.print("CFG"); break;
|
||||
case 2: _display.print("HTR"); break;
|
||||
case 3: _display.print("ERS"); break;
|
||||
}
|
||||
}
|
||||
else if(isWifiConfigPortal()) {
|
||||
_display.fillRect(X_WIFI_ICON + 11, Y_WIFI_ICON + 5, 15, 7, BLACK);
|
||||
CTransientFont AF(_display, &MINIFONT); // temporarily use a mini font
|
||||
_display.setCursor(X_WIFI_ICON+12, Y_WIFI_ICON+6);
|
||||
// _display.print("PTL");
|
||||
_display.print("CFG");
|
||||
}
|
||||
else if(isWifiAP()) {
|
||||
_display.fillRect(X_WIFI_ICON + 11, Y_WIFI_ICON + 5, 10, 7, BLACK);
|
||||
CTransientFont AF(_display, &MINIFONT); // temporarily use a mini font
|
||||
_display.setCursor(X_WIFI_ICON+12, Y_WIFI_ICON+6);
|
||||
_display.print("AP");
|
||||
}
|
||||
if(NVstore.getOTAEnabled()) {
|
||||
_display.fillRect(X_WIFI_ICON +11, Y_WIFI_ICON, 14, 6, BLACK);
|
||||
CTransientFont AF(_display, &MINIFONT); // temporarily use a mini font
|
||||
_display.setCursor(X_WIFI_ICON+12, Y_WIFI_ICON);
|
||||
_display.print("OTA");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CScreenHeader::showBatteryIcon(float voltage)
|
||||
{
|
||||
_display.drawBitmap(X_BATT_ICON, Y_BATT_ICON, BatteryIcon, W_BATT_ICON, H_BATT_ICON, WHITE);
|
||||
char msg[16];
|
||||
sprintf(msg, "%.1fV", voltage);
|
||||
CTransientFont AF(_display, &MINIFONT); // temporarily use a mini font
|
||||
_display.setCursor(X_BATT_ICON + W_BATT_ICON/2,
|
||||
Y_BATT_ICON + H_BATT_ICON + 2);
|
||||
_display.printCentreJustified(msg);
|
||||
|
||||
// nominal 10.5 -> 13.5V bargraph
|
||||
int Capacity = (voltage - 10.7) * 4;
|
||||
if(Capacity < 0) Capacity = 0;
|
||||
if(Capacity > 11) Capacity = 11;
|
||||
_display.fillRect(X_BATT_ICON+2 + Capacity, Y_BATT_ICON+2, W_BATT_ICON-4-Capacity, 6, BLACK);
|
||||
}
|
||||
|
||||
int
|
||||
CScreenHeader::showTimers()
|
||||
{
|
||||
int nextTimer = CTimerManager::getNextTimer();
|
||||
if(nextTimer) {
|
||||
int xPos = X_TIMER_ICON;
|
||||
_display.drawBitmap(xPos, Y_TIMER_ICON, largeTimerIcon, W_TIMER_ICON, H_TIMER_ICON, WHITE);
|
||||
if(nextTimer & 0x80)
|
||||
_display.drawBitmap(xPos-3, Y_TIMER_ICON, verticalRepeatIcon, verticalRepeatWidthPixels, verticalRepeatHeightPixels, WHITE);
|
||||
|
||||
CTransientFont AF(_display, &miniFontInfo); // temporarily use a mini font
|
||||
if((nextTimer & 0x0f) >= 10)
|
||||
_display.setCursor(xPos+4, Y_TIMER_ICON+8);
|
||||
else
|
||||
_display.setCursor(xPos+6, Y_TIMER_ICON+8);
|
||||
_display.print(nextTimer & 0x0f);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
CScreenHeader::showTime(int numTimers)
|
||||
{
|
||||
const BTCDateTime& now = Clock.get();
|
||||
|
||||
char msg[16];
|
||||
if(now.day() == 0xA5) {
|
||||
sprintf(msg, "No RTC");
|
||||
}
|
||||
else {
|
||||
if(_colon)
|
||||
sprintf(msg, "%02d:%02d", now.hour(), now.minute());
|
||||
else
|
||||
sprintf(msg, "%02d %02d", now.hour(), now.minute());
|
||||
_colon = !_colon;
|
||||
}
|
||||
|
||||
{
|
||||
CTransientFont AF(_display, &arial_8ptFontInfo);
|
||||
// determine centre position of remaining real estate
|
||||
int xPos = X_WIFI_ICON + W_WIFI_ICON + W_WIFIIN_ICON; // rhs of wifi conglomeration
|
||||
if(isWifiAP()) xPos += 4; // add more if an Access Point
|
||||
|
||||
/* switch(numTimers) {
|
||||
case 0: xPos = _display.xCentre(); break;
|
||||
case 1: xPos += (X_TIMER_ICON - xPos) / 2; break;
|
||||
}
|
||||
_printMenuText(xPos, Y_CLOCK, msg, false, eCentreJustify);*/
|
||||
_printMenuText(X_CLOCK, Y_CLOCK, msg);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CScreenHeader::showGPIO()
|
||||
{
|
||||
/* int xPos = X_GPIO_ICON; // both are enabled - draw icon 1 to the left, otherwise leave to the right
|
||||
CTransientFont AF(_display, &MINIFONT); // temporarily use a mini font
|
||||
_display.setCursor(xPos, 0);
|
||||
_display.print("1");
|
||||
_display.drawBitmap(xPos + 4, 0, getGPIO(0) ? TickIcon : CrossIcon, TickIconWidth, TickIconHeight, WHITE);
|
||||
_display.setCursor(xPos, 6);
|
||||
_display.print("2");
|
||||
_display.drawBitmap(xPos + 4, 6, getGPIO(1) ? TickIcon : CrossIcon, TickIconWidth, TickIconHeight, WHITE);*/
|
||||
}
|
||||
/*void
|
||||
CScreenHeader::showGPIO()
|
||||
{
|
||||
int xPos = X_GPIO_ICON; // both are enabled - draw icon 1 to the left, otherwise leave to the right
|
||||
_display.drawBitmap(xPos, 0, getGPIO(0) ? GPIO1ONIcon : GPIO1OFFIcon, GPIOIconWidthPixels, GPIOIconHeightPixels, WHITE);
|
||||
_display.drawBitmap(xPos, 8, getGPIO(1) ? GPIO2ONIcon : GPIO2OFFIcon, GPIOIconWidthPixels, GPIOIconHeightPixels, WHITE);
|
||||
}*/
|
|
@ -1,517 +0,0 @@
|
|||
/*
|
||||
* This file is part of the "bluetoothheater" distribution
|
||||
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
|
||||
*
|
||||
* Copyright (C) 2018 Ray Jones <ray@mrjones.id.au>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ScreenManager.h"
|
||||
#include "DetailedScreen.h"
|
||||
#include "BasicScreen.h"
|
||||
#include "PrimingScreen.h"
|
||||
#include "WiFiScreen.h"
|
||||
#include "FuelMixtureScreen.h"
|
||||
#include "SetClockScreen.h"
|
||||
#include "SetTimerScreen.h"
|
||||
#include "ClockScreen.h"
|
||||
#include "RebootScreen.h"
|
||||
#include "HeaterSettingsScreen.h"
|
||||
#include "SettingsScreen.h"
|
||||
#include "ThermostatModeScreen.h"
|
||||
#include "FontDumpScreen.h"
|
||||
#include "TimerChartScreen.h"
|
||||
#include "InheritSettingsScreen.h"
|
||||
#include "GPIOScreen.h"
|
||||
#include "VersionInfoScreen.h"
|
||||
#include "HomeMenuSelScreen.h"
|
||||
#include "OtherOptionsScreen.h"
|
||||
#include <Wire.h>
|
||||
#include "../cfg/pins.h"
|
||||
#include "../cfg/BTCConfig.h"
|
||||
#include "../protocol/helpers.h"
|
||||
#include "keypad.h"
|
||||
#include "fonts/Icons.h"
|
||||
#include "fonts/MiniFont.h"
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// splash creen created using image2cpp http://javl.github.io/image2cpp/
|
||||
// Settings:
|
||||
// Black background
|
||||
// Invert [X]
|
||||
// Arduino code, single bitmap
|
||||
// Identifier: DieselSplash
|
||||
// Draw Mode: Horizontal
|
||||
//
|
||||
const unsigned char DieselSplash [] PROGMEM = {
|
||||
// 'Splash3, 128x64px
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x18, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x06, 0x00, 0x00, 0x00, 0x00,
|
||||
0x02, 0x3e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00,
|
||||
0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
|
||||
0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
|
||||
0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
|
||||
0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
|
||||
0x00, 0x08, 0x00, 0x00, 0x01, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x08, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x88, 0x00, 0x00,
|
||||
0x00, 0x10, 0x00, 0x00, 0x20, 0x80, 0x00, 0x40, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x84, 0x00, 0x00,
|
||||
0x00, 0x18, 0x00, 0x00, 0x20, 0x40, 0x00, 0x20, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x84, 0x00, 0x00,
|
||||
0x00, 0x14, 0x00, 0x00, 0x40, 0x40, 0x00, 0x10, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x84, 0x00, 0x00,
|
||||
0x00, 0x52, 0x00, 0x00, 0x40, 0x20, 0x00, 0x08, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00,
|
||||
0x00, 0x34, 0x00, 0x00, 0x40, 0x10, 0x00, 0x04, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00,
|
||||
0x00, 0x18, 0x00, 0x00, 0x80, 0x10, 0x00, 0x02, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00,
|
||||
0x00, 0x34, 0x00, 0x00, 0x80, 0x08, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00,
|
||||
0x00, 0x52, 0x00, 0x00, 0x80, 0x08, 0x01, 0xf1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00,
|
||||
0x00, 0x14, 0x00, 0x01, 0x00, 0x04, 0x3e, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00,
|
||||
0x00, 0x18, 0x00, 0x01, 0x00, 0x07, 0xc0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00,
|
||||
0x00, 0x10, 0x00, 0x06, 0x80, 0x1c, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0xc4, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x18, 0x40, 0x64, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3c, 0x78, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x3c, 0x40, 0x84, 0x00, 0x00, 0x01, 0x80, 0x00, 0x01, 0xc0, 0x40, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x26, 0x23, 0x04, 0x00, 0x00, 0x00, 0x60, 0x00, 0x1e, 0x00, 0x40, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x41, 0x88, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x43, 0x1c, 0x02, 0x00, 0x00, 0x00, 0x1c, 0x01, 0xe0, 0x00, 0x40, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x41, 0xf8, 0x02, 0x00, 0x00, 0x00, 0x03, 0xfe, 0x00, 0x00, 0x40, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x40, 0x88, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x40, 0x88, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x40, 0x88, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x60, 0x88, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x30, 0x88, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x10, 0x88, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x19, 0x88, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x0f, 0x88, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x07, 0xf8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x07, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0xf8, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x1f, 0x20, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x03, 0xe8, 0x20, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x7c, 0x08, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x08, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x01, 0x46, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x10, 0x00, 0x50, 0x00, 0x00,
|
||||
0x00, 0x02, 0x28, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x10, 0x00, 0x50, 0x00, 0x00,
|
||||
0x00, 0x02, 0x28, 0x73, 0x2d, 0xc9, 0x5a, 0x8c, 0xb0, 0x20, 0x31, 0xdd, 0x66, 0x53, 0x2c, 0x00,
|
||||
0x00, 0x03, 0xee, 0x44, 0xb1, 0x29, 0x63, 0x52, 0xc0, 0x20, 0x4a, 0x51, 0x89, 0x54, 0xb0, 0x00,
|
||||
0x00, 0x02, 0x28, 0x47, 0xa1, 0x29, 0x42, 0x5e, 0x80, 0x20, 0x4a, 0x51, 0x09, 0x57, 0xa0, 0x00,
|
||||
0x00, 0x02, 0x28, 0x44, 0x21, 0x2b, 0x42, 0x50, 0x80, 0x21, 0x4a, 0x51, 0x09, 0x54, 0x20, 0x00,
|
||||
0x00, 0x02, 0x28, 0x33, 0x21, 0xc5, 0x42, 0x4c, 0x80, 0x1e, 0x32, 0x4d, 0x06, 0x53, 0x20, 0x00
|
||||
};
|
||||
|
||||
|
||||
CScreenManager::CScreenManager()
|
||||
{
|
||||
_pDisplay = NULL;
|
||||
_menu = -1;
|
||||
_subMenu = 0;
|
||||
_rootMenu = -1;
|
||||
_bReqUpdate = false;
|
||||
_DimTime_ms = millis() + 60000;
|
||||
_MenuTimeout = millis() + 60000;
|
||||
_pRebootScreen = NULL;
|
||||
_bDimmed = false;
|
||||
}
|
||||
|
||||
CScreenManager::~CScreenManager()
|
||||
{
|
||||
for(int i=0; i < _Screens.size(); i++) {
|
||||
for(int j=0; j < _Screens[i].size(); j++) {
|
||||
if(_Screens[i][j]) {
|
||||
delete _Screens[i][j];
|
||||
_Screens[i][j] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(_pDisplay) {
|
||||
delete _pDisplay; _pDisplay = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CScreenManager::begin(bool bNoClock)
|
||||
{
|
||||
|
||||
// 128 x 64 OLED support (I2C)
|
||||
// xxxx_SWITCHCAPVCC = generate display voltage from 3.3V internally
|
||||
_pDisplay = new C128x64_OLED(OLED_SDA_pin, OLED_SCL_pin);
|
||||
#if USE_ADAFRUIT_SH1106 == 1
|
||||
_pDisplay->begin(SH1106_SWITCHCAPVCC);
|
||||
Wire.begin(OLED_SDA_pin, OLED_SCL_pin, 800000); // speed up I2C from the default crappy 100kHz set via the adafruit begin!
|
||||
#elif USE_ADAFRUIT_SSD1306 == 1
|
||||
_pDisplay->begin(SSD1306_SWITCHCAPVCC, 0x3c);
|
||||
_pDisplay->ssd1306_command(SSD1306_SETPRECHARGE); // 0xd9
|
||||
_pDisplay->ssd1306_command(0x1F); // correct lame reversal of OLED current phases
|
||||
#endif
|
||||
|
||||
// replace adafruit splash screen
|
||||
_pDisplay->clearDisplay();
|
||||
_pDisplay->drawBitmap(0, 0, DieselSplash, 128, 64, WHITE);
|
||||
_pDisplay->setCursor(90, 50);
|
||||
CTransientFont AF(*_pDisplay, &miniFontInfo); // temporarily use a mini font
|
||||
_pDisplay->setTextColor(WHITE);
|
||||
_pDisplay->print(getVersionStr());
|
||||
|
||||
// Show initial display buffer contents on the screen --
|
||||
_pDisplay->display();
|
||||
|
||||
DebugPort.println("Creating Screens");
|
||||
|
||||
std::vector<CScreen*> menuloop;
|
||||
// create root menu loop
|
||||
menuloop.push_back(new CDetailedScreen(*_pDisplay, *this)); // detail control
|
||||
menuloop.push_back(new CBasicScreen(*_pDisplay, *this)); // basic control
|
||||
if(!bNoClock)
|
||||
menuloop.push_back(new CClockScreen(*_pDisplay, *this)); // clock
|
||||
menuloop.push_back(new CPrimingScreen(*_pDisplay, *this)); // mode / priming
|
||||
menuloop.push_back(new CWiFiScreen(*_pDisplay, *this)); // comms info
|
||||
menuloop.push_back(new CGPIOInfoScreen(*_pDisplay, *this)); // GPIO info
|
||||
menuloop.push_back(new CSettingsScreen(*_pDisplay, *this)); // Tuning info
|
||||
_Screens.push_back(menuloop);
|
||||
|
||||
// create timer screens loop
|
||||
menuloop.clear();
|
||||
menuloop.push_back(new CTimerChartScreen(*_pDisplay, *this, 0)); // timer chart
|
||||
menuloop.push_back(new CSetTimerScreen(*_pDisplay, *this, 0)); // set timer 1
|
||||
menuloop.push_back(new CSetTimerScreen(*_pDisplay, *this, 1)); // set timer 2
|
||||
menuloop.push_back(new CSetTimerScreen(*_pDisplay, *this, 2)); // set timer 3
|
||||
menuloop.push_back(new CSetTimerScreen(*_pDisplay, *this, 3)); // set timer 4
|
||||
menuloop.push_back(new CSetTimerScreen(*_pDisplay, *this, 4)); // set timer 5
|
||||
menuloop.push_back(new CSetTimerScreen(*_pDisplay, *this, 5)); // set timer 6
|
||||
menuloop.push_back(new CSetTimerScreen(*_pDisplay, *this, 6)); // set timer 7
|
||||
menuloop.push_back(new CSetTimerScreen(*_pDisplay, *this, 7)); // set timer 8
|
||||
menuloop.push_back(new CSetTimerScreen(*_pDisplay, *this, 8)); // set timer 9
|
||||
menuloop.push_back(new CSetTimerScreen(*_pDisplay, *this, 9)); // set timer 10
|
||||
menuloop.push_back(new CSetTimerScreen(*_pDisplay, *this, 10)); // set timer 11
|
||||
menuloop.push_back(new CSetTimerScreen(*_pDisplay, *this, 11)); // set timer 12
|
||||
menuloop.push_back(new CSetTimerScreen(*_pDisplay, *this, 12)); // set timer 13
|
||||
menuloop.push_back(new CSetTimerScreen(*_pDisplay, *this, 13)); // set timer 14
|
||||
_Screens.push_back(menuloop);
|
||||
|
||||
// create heater tuning screens loop - password protected
|
||||
menuloop.clear();
|
||||
menuloop.push_back(new CFuelMixtureScreen(*_pDisplay, *this)); // tuning
|
||||
menuloop.push_back(new CHeaterSettingsScreen(*_pDisplay, *this)); // tuning
|
||||
_Screens.push_back(menuloop);
|
||||
|
||||
// create User Settings screens loop
|
||||
menuloop.clear();
|
||||
menuloop.push_back(new CThermostatModeScreen(*_pDisplay, *this)); // experimental settings screen
|
||||
menuloop.push_back(new CGPIOScreen(*_pDisplay, *this)); // GPIO settings screen
|
||||
menuloop.push_back(new CVersionInfoScreen(*_pDisplay, *this)); // GPIO settings screen
|
||||
menuloop.push_back(new CHomeMenuSelScreen(*_pDisplay, *this)); // Home menu settings screen
|
||||
menuloop.push_back(new COtherOptionsScreen(*_pDisplay, *this)); // Other options screen
|
||||
_Screens.push_back(menuloop);
|
||||
|
||||
// create branch screens
|
||||
menuloop.clear();
|
||||
menuloop.push_back(new CSetClockScreen(*_pDisplay, *this)); // clock set branch screen
|
||||
menuloop.push_back(new CInheritSettingsScreen(*_pDisplay, *this)); // inherit OEM settings branch screen
|
||||
menuloop.push_back(new CFontDumpScreen(*_pDisplay, *this)); // font dump branch screen
|
||||
_Screens.push_back(menuloop);
|
||||
|
||||
_menu = 0;
|
||||
#if RTC_USE_DS3231==0 && RTC_USE_DS1307==0 && RTC_USE_PCF8523==0
|
||||
_rootMenu = 2; // bring up clock set screen first if using millis based RTC!
|
||||
_subMenu = 2;
|
||||
#else
|
||||
_rootMenu = 1; // basic control screen
|
||||
_subMenu = 1;
|
||||
#endif
|
||||
|
||||
_enterScreen();
|
||||
}
|
||||
|
||||
bool
|
||||
CScreenManager::checkUpdate()
|
||||
{
|
||||
long dimTimeout = NVstore.getDimTime();
|
||||
|
||||
// manage dimming or blanking the display, according to user defined inactivity interval
|
||||
if(dimTimeout && _DimTime_ms) {
|
||||
long tDelta = millis() - _DimTime_ms;
|
||||
if(tDelta > 0) {
|
||||
// time to dim the display
|
||||
_dim(true);
|
||||
_DimTime_ms = 0;
|
||||
|
||||
if(dimTimeout < 0) {
|
||||
_pDisplay->clearDisplay();
|
||||
_pDisplay->display(); // blank screen
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(NVstore.getMenuTimeout() && _MenuTimeout) {
|
||||
long tDelta = millis() - _MenuTimeout;
|
||||
if(tDelta > 0) {
|
||||
_MenuTimeout = 0;
|
||||
// we will be blanking the display, transit through a dim stage first
|
||||
if(dimTimeout < 0)
|
||||
_dim(true);
|
||||
|
||||
_leaveScreen();
|
||||
// fall back to main menu
|
||||
selectMenu(RootMenuLoop);
|
||||
// upon dim timeout - sticky root menu screens are the first 3 in the list:
|
||||
// Detailed Control
|
||||
// Basic Control
|
||||
// Clock
|
||||
// return to those upon timeout, otherwise return to Basic Control screen
|
||||
if(_rootMenu > 2) {
|
||||
uint8_t userHomeMenu = NVstore.getHomeMenu().onTimeout;
|
||||
if(userHomeMenu) { // allow user to override defualt screen
|
||||
userHomeMenu--;
|
||||
DebugPort.print("Screen Manager: Menu timeout, falling back to user preferred screen: ");
|
||||
switch(userHomeMenu) {
|
||||
case 0: DebugPort.println("Detailed control menu"); break;
|
||||
case 1: DebugPort.println("Basic control menu"); break;
|
||||
case 2: DebugPort.println("Clock menu"); break;
|
||||
}
|
||||
_rootMenu = _subMenu = userHomeMenu;
|
||||
}
|
||||
else {
|
||||
_rootMenu = _subMenu = 1;
|
||||
DebugPort.print("Screen Manager: Menu timeout, falling back to Basic control screen");
|
||||
}
|
||||
}
|
||||
_enterScreen();
|
||||
}
|
||||
}
|
||||
|
||||
static int prevRunState = -1;
|
||||
int runState = getHeaterInfo().getRunStateEx();
|
||||
if(runState != prevRunState) {
|
||||
if(runState > 0 && prevRunState == 0) {
|
||||
// heater has started
|
||||
uint8_t userStartMenu = NVstore.getHomeMenu().onStart;
|
||||
if(userStartMenu && userStartMenu <= 3) { // allow user to override defualt screen
|
||||
userStartMenu--;
|
||||
DebugPort.print("Screen Manager: Heater start detected, switching to user preferred screen: ");
|
||||
switch(userStartMenu) {
|
||||
case 0: DebugPort.println("Detailed control menu"); break;
|
||||
case 1: DebugPort.println("Basic control menu"); break;
|
||||
case 2: DebugPort.println("Clock menu"); break;
|
||||
}
|
||||
_rootMenu = _subMenu = userStartMenu;
|
||||
_enterScreen();
|
||||
}
|
||||
}
|
||||
if(runState == 0 && prevRunState != 0) {
|
||||
// heater has stopped
|
||||
uint8_t userStopMenu = NVstore.getHomeMenu().onStop;
|
||||
if(userStopMenu && userStopMenu <= 3) { // allow user to override defualt screen
|
||||
userStopMenu--;
|
||||
DebugPort.print("Screen Manager: Heater stop detected, switching to user preferred screen: ");
|
||||
switch(userStopMenu) {
|
||||
case 0: DebugPort.println("Detailed control menu"); break;
|
||||
case 1: DebugPort.println("Basic control menu"); break;
|
||||
case 2: DebugPort.println("Clock menu"); break;
|
||||
}
|
||||
_rootMenu = _subMenu = userStopMenu;
|
||||
_enterScreen();
|
||||
}
|
||||
}
|
||||
prevRunState = runState;
|
||||
}
|
||||
|
||||
|
||||
if(_bReqUpdate) {
|
||||
if((dimTimeout < 0) && (_DimTime_ms == 0)) {
|
||||
// no screen updates, we should be blanked!
|
||||
}
|
||||
else {
|
||||
if(_pRebootScreen) {
|
||||
_pRebootScreen->show();
|
||||
_bReqUpdate = false;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
if(_menu >= 0) {
|
||||
_Screens[_menu][_subMenu]->show();
|
||||
_bReqUpdate = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
CScreenManager::reqUpdate()
|
||||
{
|
||||
_bReqUpdate = true;
|
||||
}
|
||||
|
||||
bool
|
||||
CScreenManager::animate()
|
||||
{
|
||||
if((NVstore.getDimTime() < 0) && (_DimTime_ms == 0)) {
|
||||
// no screen updates, we should be blanked!
|
||||
return false;
|
||||
}
|
||||
if(_menu >= 0)
|
||||
return _Screens[_menu][_subMenu]->animate();
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
CScreenManager::refresh()
|
||||
{
|
||||
if(_pDisplay)
|
||||
_pDisplay->display();
|
||||
}
|
||||
|
||||
void
|
||||
CScreenManager::_enterScreen()
|
||||
{
|
||||
if(_menu >= 0)
|
||||
_Screens[_menu][_subMenu]->onSelect();
|
||||
|
||||
reqUpdate();
|
||||
}
|
||||
|
||||
void
|
||||
CScreenManager::_leaveScreen()
|
||||
{
|
||||
if(_menu >= 0)
|
||||
_Screens[_menu][_subMenu]->onExit();
|
||||
}
|
||||
|
||||
void
|
||||
CScreenManager::_changeSubMenu(int dir)
|
||||
{
|
||||
_leaveScreen();
|
||||
_subMenu += dir;
|
||||
int bounds = _Screens[_menu].size() - 1;
|
||||
ROLLUPPERLIMIT(_subMenu, bounds, 0);
|
||||
ROLLLOWERLIMIT(_subMenu, 0, bounds);
|
||||
if(_menu == 0)
|
||||
_rootMenu = _subMenu; // track the root menu for when we branch then return
|
||||
_enterScreen();
|
||||
}
|
||||
|
||||
void
|
||||
CScreenManager::nextMenu()
|
||||
{
|
||||
if(_menu >= 0 && _menu != BranchMenu) {
|
||||
_changeSubMenu(+1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CScreenManager::prevMenu()
|
||||
{
|
||||
if(_menu >= 0 && _menu != BranchMenu) {
|
||||
_changeSubMenu(-1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CScreenManager::keyHandler(uint8_t event)
|
||||
{
|
||||
long dimTime = NVstore.getDimTime();
|
||||
|
||||
if(_bDimmed) {
|
||||
if(event & keyReleased) {
|
||||
_dim(false);
|
||||
_DimTime_ms = (millis() + abs(dimTime)) | 1;
|
||||
_MenuTimeout = millis() + NVstore.getMenuTimeout();
|
||||
}
|
||||
return; // initial press when dimmed is always thrown away
|
||||
}
|
||||
|
||||
// _dim(false);
|
||||
_DimTime_ms = (millis() + abs(dimTime)) | 1;
|
||||
_MenuTimeout = millis() + NVstore.getMenuTimeout();
|
||||
|
||||
// call key handler for active screen
|
||||
if(_menu >= 0)
|
||||
_Screens[_menu][_subMenu]->keyHandler(event);
|
||||
}
|
||||
|
||||
void
|
||||
CScreenManager::selectMenu(eUIMenuSets menuSet, int specific)
|
||||
{
|
||||
_leaveScreen();
|
||||
if(_menu >= 0) { // only true once we have created the screens
|
||||
_menu = menuSet;
|
||||
if(specific >= 0) {
|
||||
// targetting a specific menu
|
||||
_subMenu = specific;
|
||||
UPPERLIMIT(_subMenu, _Screens[_menu].size()-1); // check bounds!
|
||||
}
|
||||
else {
|
||||
// default sub menu behaviour
|
||||
if(_menu == 0)
|
||||
_subMenu = _rootMenu; // return to last used root menu
|
||||
else
|
||||
_subMenu = 0; // branches always go to first sub menu
|
||||
}
|
||||
}
|
||||
_enterScreen();
|
||||
}
|
||||
|
||||
void
|
||||
CScreenManager::showRebootMsg(const char* content[2], long delayTime)
|
||||
{
|
||||
if(_pRebootScreen == NULL)
|
||||
_pRebootScreen = new CRebootScreen(*_pDisplay, *this);
|
||||
|
||||
_pRebootScreen->setMessage(content, delayTime);
|
||||
_bReqUpdate = true;
|
||||
_dim(false);
|
||||
}
|
||||
|
||||
void
|
||||
CScreenManager::showOTAMessage(int percent)
|
||||
{
|
||||
static int prevPercent = -1;
|
||||
if(percent != prevPercent) {
|
||||
_pDisplay->clearDisplay();
|
||||
_pDisplay->setCursor(64,22);
|
||||
_pDisplay->printCentreJustified("OTA update active");
|
||||
if(percent) {
|
||||
char msg[16];
|
||||
sprintf(msg, "%d%%", percent);
|
||||
_pDisplay->setCursor(64,32);
|
||||
_pDisplay->printCentreJustified(msg);
|
||||
}
|
||||
prevPercent = percent;
|
||||
_pDisplay->display();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CScreenManager::_dim(bool state)
|
||||
{
|
||||
_bDimmed = state;
|
||||
_pDisplay->dim(state);
|
||||
}
|
|
@ -1,318 +0,0 @@
|
|||
/*
|
||||
* This file is part of the "bluetoothheater" distribution
|
||||
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
|
||||
*
|
||||
* Copyright (C) 2018 Ray Jones <ray@mrjones.id.au>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "128x64OLED.h"
|
||||
#include "ThermostatModeScreen.h"
|
||||
#include "KeyPad.h"
|
||||
#include "../Protocol/helpers.h"
|
||||
#include "../Utility/UtilClasses.h"
|
||||
#include "fonts/Icons.h"
|
||||
#include "../Utility/NVStorage.h"
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CThermostatModeScreen
|
||||
//
|
||||
// This screen provides control over experimental features
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static const int Line3 = 14;
|
||||
static const int Line2 = 27;
|
||||
static const int Line1 = 40;
|
||||
static const int Column = 40;
|
||||
|
||||
CThermostatModeScreen::CThermostatModeScreen(C128x64_OLED& display, CScreenManager& mgr) : CPasswordScreen(display, mgr)
|
||||
{
|
||||
_initUI();
|
||||
_window = 10;
|
||||
_thermoMode = 0;
|
||||
_cyclicMode.init();
|
||||
}
|
||||
|
||||
void
|
||||
CThermostatModeScreen::onSelect()
|
||||
{
|
||||
CPasswordScreen::onSelect();
|
||||
_initUI();
|
||||
_window = NVstore.getThermostatMethodWindow();
|
||||
_thermoMode = NVstore.getThermostatMethodMode();
|
||||
_cyclicMode = NVstore.getCyclicMode();
|
||||
}
|
||||
|
||||
void
|
||||
CThermostatModeScreen::_initUI()
|
||||
{
|
||||
_rowSel = 0;
|
||||
_animateCount = 0;
|
||||
_keyRepeat = -1;
|
||||
}
|
||||
|
||||
bool
|
||||
CThermostatModeScreen::show()
|
||||
{
|
||||
char msg[20];
|
||||
_display.clearDisplay();
|
||||
|
||||
if(!CPasswordScreen::show()) { // for showing "saving settings"
|
||||
|
||||
if(_rowSel == 10) {
|
||||
_printInverted(_display.xCentre(), 0, " Saving Settings ", true, eCentreJustify);
|
||||
_printMenuText(_display.xCentre(), 35, "Press UP to", false, eCentreJustify);
|
||||
_printMenuText(_display.xCentre(), 43, "confirm save", false, eCentreJustify);
|
||||
}
|
||||
else {
|
||||
_printInverted(_display.xCentre(), 0, " Thermostat Mode ", true, eCentreJustify);
|
||||
_display.drawBitmap(3, 14, thermostatIcon, thermostatWidth, thermostatHeight, WHITE);
|
||||
float fTemp = _window;
|
||||
if(NVstore.getDegFMode()) {
|
||||
fTemp = fTemp * 9 / 5;
|
||||
sprintf(msg, "%.1f\367F", fTemp);
|
||||
}
|
||||
else {
|
||||
sprintf(msg, "%.1f\367C", fTemp);
|
||||
}
|
||||
_printMenuText(Column, Line2, msg, _rowSel == 3);
|
||||
switch(_thermoMode) {
|
||||
case 1:
|
||||
_printMenuText(Column, Line3, "Deadband", _rowSel == 4);
|
||||
break;
|
||||
case 2:
|
||||
_printMenuText(Column, Line3, "Linear Hz", _rowSel == 4);
|
||||
break;
|
||||
default:
|
||||
_printMenuText(Column, Line3, "Standard", _rowSel == 4);
|
||||
break;
|
||||
}
|
||||
if(_cyclicMode.isEnabled()) {
|
||||
float fTemp = _cyclicMode.Stop+1;
|
||||
if(NVstore.getDegFMode()) {
|
||||
fTemp = fTemp * 9 / 5;
|
||||
sprintf(msg, "\352>%.0f\367F", fTemp);
|
||||
}
|
||||
else {
|
||||
sprintf(msg, "\352>%.0f\367C", fTemp);
|
||||
}
|
||||
}
|
||||
else {
|
||||
strcpy(msg, "OFF");
|
||||
}
|
||||
_printMenuText(Column, Line1, msg, _rowSel == 1);
|
||||
if(_cyclicMode.isEnabled()) {
|
||||
float fTemp = _cyclicMode.Start;
|
||||
if(NVstore.getDegFMode()) {
|
||||
fTemp = fTemp * 9 / 5;
|
||||
sprintf(msg, "\352<%.0f\367F", fTemp);
|
||||
}
|
||||
else {
|
||||
sprintf(msg, "\352<%.0f\367C", fTemp);
|
||||
}
|
||||
}
|
||||
else {
|
||||
strcpy(msg, "");
|
||||
}
|
||||
_printMenuText(Column + 42, Line1, msg, _rowSel == 2);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CThermostatModeScreen::animate()
|
||||
{
|
||||
if(_rowSel != 10) {
|
||||
int yPos = 53;
|
||||
int xPos = _display.xCentre();
|
||||
const char* pMsg = NULL;
|
||||
switch(_rowSel) {
|
||||
case 0:
|
||||
_printMenuText(xPos, yPos, " \021 \030Edit Exit \020 ", true, eCentreJustify);
|
||||
break;
|
||||
case 1:
|
||||
_display.drawFastHLine(0, 52, 128, WHITE);
|
||||
pMsg = " Heater shuts down over set point. ";
|
||||
_scrollMessage(56, pMsg, _scrollChar);
|
||||
break;
|
||||
case 2:
|
||||
_display.drawFastHLine(0, 52, 128, WHITE);
|
||||
pMsg = " Heater restarts below setpoint. ";
|
||||
_scrollMessage(56, pMsg, _scrollChar);
|
||||
break;
|
||||
case 3:
|
||||
_display.drawFastHLine(0, 52, 128, WHITE);
|
||||
pMsg = " User defined window for custom thermostat modes. ";
|
||||
_scrollMessage(56, pMsg, _scrollChar);
|
||||
break;
|
||||
case 4:
|
||||
_display.drawFastHLine(0, 52, 128, WHITE);
|
||||
switch(_thermoMode) {
|
||||
case 1:
|
||||
pMsg = " The user defined window sets the thermostat's hysteresis. ";
|
||||
break;
|
||||
case 2:
|
||||
pMsg = " The pump rate is adjusted linearly across the set point window. ";
|
||||
break;
|
||||
default:
|
||||
pMsg = " Use heater's standard thermostat control. ";
|
||||
break;
|
||||
}
|
||||
if(pMsg)
|
||||
_scrollMessage(56, pMsg, _scrollChar);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
CThermostatModeScreen::keyHandler(uint8_t event)
|
||||
{
|
||||
if(event & keyPressed) {
|
||||
_keyRepeat = 0; // unlock hold function
|
||||
// press LEFT to select previous screen
|
||||
if(event & key_Left) {
|
||||
switch(_rowSel) {
|
||||
case 0:
|
||||
_ScreenManager.prevMenu();
|
||||
break;
|
||||
case 4:
|
||||
_scrollChar = 0;
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
_adjust(-1);
|
||||
break;
|
||||
case 10:
|
||||
_rowSel = 0; // abort save
|
||||
break;
|
||||
}
|
||||
}
|
||||
// press RIGHT to select next screen
|
||||
if(event & key_Right) {
|
||||
switch(_rowSel) {
|
||||
case 0:
|
||||
_ScreenManager.nextMenu();
|
||||
break;
|
||||
case 4:
|
||||
_scrollChar = 0;
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
_adjust(+1);
|
||||
break;
|
||||
case 10:
|
||||
_rowSel = 0; // abort save
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(event & key_Down) {
|
||||
if(_rowSel != 0) {
|
||||
_scrollChar = 0;
|
||||
_rowSel--;
|
||||
if(_rowSel == 2 && !_cyclicMode.isEnabled())
|
||||
_rowSel--;
|
||||
LOWERLIMIT(_rowSel, 0);
|
||||
}
|
||||
}
|
||||
// UP press
|
||||
if(event & key_Up) {
|
||||
switch(_rowSel) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
_scrollChar = 0;
|
||||
_rowSel++;
|
||||
if(_rowSel == 2 && !_cyclicMode.isEnabled())
|
||||
_rowSel++;
|
||||
UPPERLIMIT(_rowSel, 4);
|
||||
break;
|
||||
case 10: // confirmed save
|
||||
_showStoringMessage();
|
||||
NVstore.setThermostatMethodMode(_thermoMode);
|
||||
NVstore.setThermostatMethodWindow(_window);
|
||||
NVstore.setCyclicMode(_cyclicMode);
|
||||
saveNV();
|
||||
_rowSel = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// CENTRE press
|
||||
if(event & key_Centre) {
|
||||
switch(_rowSel) {
|
||||
case 0:
|
||||
_ScreenManager.selectMenu(CScreenManager::RootMenuLoop); // force return to main menu
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
_rowSel = 10;
|
||||
break;
|
||||
}
|
||||
}
|
||||
_ScreenManager.reqUpdate();
|
||||
}
|
||||
if(event & keyRepeat) {
|
||||
_keyRepeat++;
|
||||
if((event & key_Down) && (keyRepeat >= 4)) {
|
||||
_keyRepeat = -1;
|
||||
if(_rowSel == 0) {
|
||||
_ScreenManager.selectMenu(CScreenManager::BranchMenu, CScreenManager::FontDumpUI);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(event & keyReleased) {
|
||||
_keyRepeat = -1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CThermostatModeScreen::_adjust(int dir)
|
||||
{
|
||||
switch(_rowSel) {
|
||||
case 1:
|
||||
_cyclicMode.Stop += dir;
|
||||
LOWERLIMIT(_cyclicMode.Stop, 0);
|
||||
UPPERLIMIT(_cyclicMode.Stop, 10);
|
||||
break;
|
||||
case 2:
|
||||
_cyclicMode.Start += dir;
|
||||
LOWERLIMIT(_cyclicMode.Start, -10);
|
||||
UPPERLIMIT(_cyclicMode.Start, 0);
|
||||
break;
|
||||
case 3: // window
|
||||
_window += (dir * 0.1);
|
||||
UPPERLIMIT(_window, 6.3);
|
||||
LOWERLIMIT(_window, 0.2);
|
||||
break;
|
||||
case 4: // thermostat mode
|
||||
_thermoMode += dir;
|
||||
ROLLLOWERLIMIT(_thermoMode, 0, 2);
|
||||
ROLLUPPERLIMIT(_thermoMode, 2, 0);
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
#include "FontTypes.h"
|
||||
|
||||
// Font data for Arial 8pt
|
||||
extern const uint8_t PROGMEM arial_8ptBitmaps [];
|
||||
extern const FONT_INFO arial_8ptFontInfo;
|
||||
extern const FONT_CHAR_INFO PROGMEM arial_8ptDescriptors[];
|
||||
|
||||
// Font data for Arial 7pt
|
||||
extern const uint8_t PROGMEM arial_7ptBitmaps [];
|
||||
extern const FONT_INFO arial_7ptFontInfo;
|
||||
extern const FONT_CHAR_INFO PROGMEM arial_7ptDescriptors[];
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
#include "FontTypes.h"
|
||||
|
||||
// Font data for Franklin Gothic Medium Cond 8pt
|
||||
extern const uint8_t PROGMEM franklinGothicMediumCond_8ptBitmaps [] ;
|
||||
extern const FONT_CHAR_INFO PROGMEM franklinGothicMediumCond_8ptDescriptors[] ;
|
||||
extern const FONT_INFO franklinGothicMediumCond_8ptFontInfo;
|
||||
|
||||
// Font data for Franklin Gothic Medium Cond 7pt
|
||||
extern const uint8_t PROGMEM franklinGothicMediumCond_7ptBitmaps [];
|
||||
extern const FONT_INFO franklinGothicMediumCond_7ptFontInfo;
|
||||
extern const FONT_CHAR_INFO PROGMEM franklinGothicMediumCond_7ptDescriptors[];
|
||||
|
||||
|
||||
|
|
@ -1,539 +0,0 @@
|
|||
/*
|
||||
* This file is part of the "bluetoothheater" distribution
|
||||
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
|
||||
*
|
||||
* Copyright (C) 2018 Ray Jones <ray@mrjones.id.au>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "Icons.h"
|
||||
|
||||
// 'Thermometer', 8x50px
|
||||
const unsigned char bodyThermometerIcon [] PROGMEM = {
|
||||
0x00, 0x18, 0x24, 0x24, 0x24, 0x24, 0x24, 0x26, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
|
||||
0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x26, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
|
||||
0x24, 0x24, 0x24, 0x24, 0x24, 0x26, 0x24, 0x24, 0x24, 0x24, 0x3c, 0x7e, 0xff, 0xff, 0xff, 0xff,
|
||||
0x7e, 0x3c
|
||||
};
|
||||
|
||||
// 'ThermometerActual', 8x50px
|
||||
const unsigned char ambientThermometerIcon [] PROGMEM = {
|
||||
0x00, 0x18, 0x24, 0x24, 0x24, 0x24, 0x24, 0x26, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
|
||||
0x24, 0x26, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x26, 0x24, 0x24, 0x24, 0x24,
|
||||
0x24, 0x24, 0x24, 0x24, 0x24, 0x26, 0x24, 0x24, 0x24, 0x24, 0x3c, 0x7e, 0xff, 0xff, 0xff, 0xff,
|
||||
0x7e, 0x3c
|
||||
};
|
||||
|
||||
|
||||
// 'ThermoPtr', 3x5px
|
||||
const unsigned char thermoPtr [] PROGMEM = {
|
||||
0x80, 0xc0, 0xe0, 0xc0, 0x80
|
||||
};
|
||||
|
||||
// 'Bluetooth icon', 6x11px
|
||||
const unsigned char BTicon [] PROGMEM = {
|
||||
0x20, 0x30, 0x28, 0xa4, 0x68, 0x30, 0x68, 0xa4, 0x28, 0x30, 0x20,
|
||||
};
|
||||
|
||||
// 'wifiIcon', 13x10px
|
||||
const unsigned char wifiIcon [] PROGMEM = {
|
||||
0x1f, 0xc0, 0x20, 0x20, 0x40, 0x10, 0x8f, 0x88, 0x10, 0x40, 0x20, 0x20,
|
||||
0x07, 0x00, 0x08, 0x80, 0x00, 0x00, 0x02, 0x00
|
||||
};
|
||||
|
||||
// 'wifiInIcon, 5x5px
|
||||
const unsigned char wifiInIcon [] PROGMEM = {
|
||||
0x70, 0x70, 0xf8, 0x70, 0x20
|
||||
};
|
||||
|
||||
// 'wifiOutIcon, 5x5px
|
||||
const unsigned char wifiOutIcon [] PROGMEM = {
|
||||
0x20, 0x70, 0xf8, 0x70, 0x70
|
||||
};
|
||||
|
||||
// 'BatteryIcon', 15x10px
|
||||
const unsigned char BatteryIcon [] PROGMEM = {
|
||||
0x30, 0x18, 0xff, 0xfe, 0x80, 0x02, 0xb6, 0xda, 0xb6, 0xda, 0xb6, 0xda, 0xb6, 0xda, 0xb6, 0xda,
|
||||
0x80, 0x02, 0xff, 0xfe
|
||||
};
|
||||
|
||||
// 'GlowPlugIcon', 16x9px
|
||||
const unsigned char GlowPlugIcon [] PROGMEM = {
|
||||
0x71, 0xc7, 0x0e, 0x38, 0x14, 0x14, 0x12, 0x24, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x0a, 0x28,
|
||||
0x0e, 0x38
|
||||
};
|
||||
|
||||
// 'HeatRise', 17x2px
|
||||
const unsigned char GlowHeatIcon [] PROGMEM = {
|
||||
0x80, 0x00, 0x80, 0x40, 0x01, 0x00
|
||||
};
|
||||
|
||||
// 'Fan3_1a', 16x16px
|
||||
const unsigned char FanIcon1 [] PROGMEM = {
|
||||
0x03, 0xc0, 0x04, 0x20, 0x04, 0x20, 0x04, 0x20, 0x04, 0x20, 0x03, 0xc0, 0x07, 0xe0, 0x06, 0x60,
|
||||
0x7e, 0x7e, 0x87, 0xe1, 0x87, 0xe1, 0x84, 0x21, 0x84, 0x21, 0x78, 0x1e, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
// 'Fan3_2a', 16x16px
|
||||
const unsigned char FanIcon2 [] PROGMEM = {
|
||||
0x00, 0x78, 0x00, 0x84, 0x00, 0x84, 0x00, 0x84, 0x00, 0x84, 0x7b, 0xf8, 0x87, 0xe0, 0x86, 0x60,
|
||||
0x86, 0x60, 0x87, 0xe0, 0x7b, 0xf8, 0x00, 0x84, 0x00, 0x84, 0x00, 0x84, 0x00, 0x84, 0x00, 0x78
|
||||
};
|
||||
// 'Fan3_3a', 16x16px
|
||||
const unsigned char FanIcon3 [] PROGMEM = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x78, 0x1e, 0x84, 0x21, 0x84, 0x21, 0x87, 0xe1, 0x87, 0xe1, 0x7e, 0x7e,
|
||||
0x06, 0x60, 0x07, 0xe0, 0x03, 0xc0, 0x04, 0x20, 0x04, 0x20, 0x04, 0x20, 0x04, 0x20, 0x03, 0xc0
|
||||
};
|
||||
// 'Fan3_4a', 16x16px
|
||||
const unsigned char FanIcon4 [] PROGMEM = {
|
||||
0x1e, 0x00, 0x21, 0x00, 0x21, 0x00, 0x21, 0x00, 0x21, 0x00, 0x1f, 0xde, 0x07, 0xe1, 0x06, 0x61,
|
||||
0x06, 0x61, 0x07, 0xe1, 0x1f, 0xde, 0x21, 0x00, 0x21, 0x00, 0x21, 0x00, 0x21, 0x00, 0x1e, 0x00
|
||||
};
|
||||
|
||||
|
||||
// 'FuelIcon', 7x12px
|
||||
const unsigned char FuelIcon [] PROGMEM = {
|
||||
0x10, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38
|
||||
};
|
||||
|
||||
// 'Target', 13x13px
|
||||
const unsigned char TargetIcon [] PROGMEM = {
|
||||
0x0f, 0x80, 0x10, 0x40, 0x20, 0x20, 0x47, 0x10, 0x88, 0x88, 0x92, 0x48, 0x97, 0x48, 0x92, 0x48,
|
||||
0x88, 0x88, 0x47, 0x10, 0x20, 0x20, 0x10, 0x40, 0x0f, 0x80
|
||||
};
|
||||
|
||||
// 'repeat', 15x15px
|
||||
const unsigned char repeatIcon [] PROGMEM = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x02, 0x00, 0x02, 0xf0, 0x04, 0xe0, 0x04, 0xe0, 0x08, 0x98, 0x30, 0x07, 0xc0
|
||||
};
|
||||
|
||||
// 'timerID1', 15x15px
|
||||
const unsigned char timerID1Icon [] PROGMEM = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x09, 0x20, 0x11, 0x10, 0x21, 0x08, 0x2d, 0x08, 0x25, 0xe8,
|
||||
0x24, 0x08, 0x24, 0x08, 0x10, 0x10, 0x08, 0x20, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
// 'timerID2', 15x15px
|
||||
const unsigned char timerID2Icon [] PROGMEM = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x09, 0x20, 0x11, 0x10, 0x21, 0x08, 0x2d, 0x08, 0x25, 0xe8,
|
||||
0x28, 0x08, 0x2c, 0x08, 0x10, 0x10, 0x08, 0x20, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
// 'timer', 15x15px
|
||||
const unsigned char timerIcon [] PROGMEM = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x09, 0x20, 0x11, 0x10, 0x21, 0x08, 0x21, 0x08, 0x21, 0xe8,
|
||||
0x20, 0x08, 0x20, 0x08, 0x10, 0x10, 0x08, 0x20, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
// 'large timer', 15x15px
|
||||
const unsigned char largeTimerIcon[] PROGMEM =
|
||||
{
|
||||
0x07, 0xC0, // #####
|
||||
0x19, 0x30, // ## # ##
|
||||
0x21, 0x08, // # # #
|
||||
0x41, 0x04, // # # #
|
||||
0x41, 0x04, // # # #
|
||||
0x81, 0x02, // # # #
|
||||
0x81, 0xF2, // # ##### #
|
||||
0x80, 0x02, // # #
|
||||
0x80, 0x02, // # #
|
||||
0x80, 0x02, // # #
|
||||
0x40, 0x04, // # #
|
||||
0x40, 0x04, // # #
|
||||
0x20, 0x08, // # #
|
||||
0x18, 0x30, // ## ##
|
||||
0x0F, 0xE0, // #######
|
||||
};
|
||||
|
||||
const uint8_t PROGMEM verticalRepeatIcon [] =
|
||||
{
|
||||
0x78, // ####
|
||||
0x38, // ###
|
||||
0x38, // ###
|
||||
0x48, // # #
|
||||
0x80, // #
|
||||
0x80, // #
|
||||
0x80, // #
|
||||
0x80, // #
|
||||
0x80, // #
|
||||
0x80, // #
|
||||
0x80, // #
|
||||
0x40, // #
|
||||
0x40, // #
|
||||
0x20, // #
|
||||
0x20, // #
|
||||
};
|
||||
|
||||
const uint8_t PROGMEM GPIO1OFFIcon[] =
|
||||
{
|
||||
0x3E, 0x00, // #####
|
||||
0x41, 0x00, // # #
|
||||
0x88, 0x80, // # # #
|
||||
0x98, 0x80, // # ## #
|
||||
0x88, 0x80, // # # #
|
||||
0x88, 0x80, // # # #
|
||||
0x9C, 0x80, // # ### #
|
||||
0x41, 0x00, // # #
|
||||
0x3E, 0x00, // #####
|
||||
};
|
||||
|
||||
const uint8_t PROGMEM GPIO1ONIcon[] =
|
||||
{
|
||||
0x3E, 0x00, // #####
|
||||
0x7F, 0x00, // #######
|
||||
0xF7, 0x80, // #### ####
|
||||
0xE7, 0x80, // ### ####
|
||||
0xF7, 0x80, // #### ####
|
||||
0xF7, 0x80, // #### ####
|
||||
0xE3, 0x80, // ### ###
|
||||
0x7F, 0x00, // #######
|
||||
0x3E, 0x00, // #####
|
||||
};
|
||||
|
||||
const uint8_t PROGMEM GPIO2OFFIcon[] =
|
||||
{
|
||||
0x3E, 0x00, // #####
|
||||
0x41, 0x00, // # #
|
||||
0x9C, 0x80, // # ### #
|
||||
0x84, 0x80, // # # #
|
||||
0x9C, 0x80, // # ### #
|
||||
0x90, 0x80, // # # #
|
||||
0x9C, 0x80, // # ### #
|
||||
0x41, 0x00, // # #
|
||||
0x3E, 0x00, // #####
|
||||
};
|
||||
|
||||
const uint8_t PROGMEM GPIO2ONIcon[] =
|
||||
{
|
||||
0x3E, 0x00, // #####
|
||||
0x7F, 0x00, // #######
|
||||
0xE3, 0x80, // ### ###
|
||||
0xFB, 0x80, // ##### ###
|
||||
0xE3, 0x80, // ### ###
|
||||
0xEF, 0x80, // ### #####
|
||||
0xE3, 0x80, // ### ###
|
||||
0x7F, 0x00, // #######
|
||||
0x3E, 0x00, // #####
|
||||
};
|
||||
|
||||
const uint8_t PROGMEM CrossIcon[] =
|
||||
{
|
||||
0x88, // # #
|
||||
0x50, // # #
|
||||
0x20, // #
|
||||
0x50, // # #
|
||||
0x88, // # #
|
||||
};
|
||||
|
||||
const uint8_t PROGMEM TickIcon[] =
|
||||
{
|
||||
0x00, //
|
||||
0x08, // #
|
||||
0x10, // #
|
||||
0xa0, // # #
|
||||
0x40, // #
|
||||
};
|
||||
|
||||
const uint8_t PROGMEM OpenIcon[] =
|
||||
{
|
||||
0x1F, 0xC0, // #######
|
||||
0x02, 0x00, // #
|
||||
0x02, 0x00, // #
|
||||
0x3A, 0xE0, // ### # ###
|
||||
0xEA, 0xB8, // ### # # # ###
|
||||
0x3A, 0xE0, // ### # ###
|
||||
0x00, 0x00, //
|
||||
};
|
||||
|
||||
const uint8_t PROGMEM CloseIcon[] =
|
||||
{
|
||||
0x00, 0x00, //
|
||||
0x00, 0x00, //
|
||||
0x3F, 0xE0, // #########
|
||||
0x3A, 0xE0, // ### # ###
|
||||
0xFA, 0xF8, // ##### # #####
|
||||
0x3A, 0xE0, // ### # ###
|
||||
0x02, 0x00, // #
|
||||
};
|
||||
|
||||
|
||||
const uint8_t PROGMEM BulbOnIcon[] =
|
||||
{
|
||||
0x08, 0x00, // #
|
||||
0x41, 0x00, // # #
|
||||
0x1C, 0x00, // ###
|
||||
0x22, 0x00, // # #
|
||||
0xA2, 0x80, // # # # #
|
||||
0x1C, 0x00, // ###
|
||||
0x14, 0x00, // # #
|
||||
0x1C, 0x00, // ###
|
||||
};
|
||||
|
||||
const uint8_t PROGMEM BulbOffIcon[] =
|
||||
{
|
||||
0x00, 0x00, //
|
||||
0x00, 0x00, //
|
||||
0x1C, 0x00, // ###
|
||||
0x22, 0x00, // # #
|
||||
0x22, 0x00, // # #
|
||||
0x1C, 0x00, // ###
|
||||
0x14, 0x00, // # #
|
||||
0x1C, 0x00, // ###
|
||||
};
|
||||
|
||||
|
||||
const uint8_t PROGMEM startIcon[] =
|
||||
{
|
||||
0x80, // #
|
||||
0xC0, // ##
|
||||
0xE0, // ###
|
||||
0xF0, // ####
|
||||
0xF8, // #####
|
||||
0xF0, // ####
|
||||
0xE0, // ###
|
||||
0xC0, // ##
|
||||
0x80, // #
|
||||
};
|
||||
|
||||
const uint8_t PROGMEM stopIcon[] =
|
||||
{
|
||||
0x00, //
|
||||
0xFC, // ######
|
||||
0xFC, // ######
|
||||
0xFC, // ######
|
||||
0xFC, // ######
|
||||
0xFC, // ######
|
||||
0xFC, // ######
|
||||
0x00, //
|
||||
};
|
||||
|
||||
const uint8_t PROGMEM displayTimeoutIcon[] =
|
||||
{
|
||||
0xFF, 0xE1, 0xFF, // ########### #########
|
||||
0x80, 0x20, 0x82, // # # # #
|
||||
0x80, 0x20, 0x82, // # # # #
|
||||
0x80, 0x20, 0x44, // # # # #
|
||||
0x80, 0x20, 0x28, // # # # #
|
||||
0x80, 0x20, 0x44, // # # # #
|
||||
0xFF, 0xE0, 0x92, // ########### # # #
|
||||
0x0E, 0x00, 0xBA, // ### # ### #
|
||||
0x3F, 0x80, 0xFE, // ####### #######
|
||||
0x00, 0x01, 0xFF, // #########
|
||||
};
|
||||
|
||||
const uint8_t PROGMEM menuTimeoutIcon[] =
|
||||
{
|
||||
0x00, 0x01, 0xFF, // #########
|
||||
0xFF, 0xC0, 0x82, // ########## # #
|
||||
0x00, 0x00, 0x82, // # #
|
||||
0xFF, 0x00, 0x44, // ######## # #
|
||||
0x00, 0x00, 0x28, // # #
|
||||
0xFC, 0x00, 0x44, // ###### # #
|
||||
0x00, 0x00, 0x92, // # # #
|
||||
0xFF, 0x80, 0xBA, // ######### # ### #
|
||||
0x00, 0x00, 0xFE, // #######
|
||||
0x00, 0x01, 0xFF, // #########
|
||||
};
|
||||
|
||||
const uint8_t PROGMEM timeoutIcon[] =
|
||||
{
|
||||
0xFF, 0x80, // #########
|
||||
0x41, 0x00, // # #
|
||||
0x41, 0x00, // # #
|
||||
0x22, 0x00, // # #
|
||||
0x14, 0x00, // # #
|
||||
0x22, 0x00, // # #
|
||||
0x49, 0x00, // # # #
|
||||
0x5D, 0x00, // # ### #
|
||||
0x7F, 0x00, // #######
|
||||
0xFF, 0x80, // #########
|
||||
};
|
||||
|
||||
const uint8_t PROGMEM refreshIcon[] =
|
||||
{
|
||||
0x01, 0x00, // #
|
||||
0x00, 0x80, // #
|
||||
0x7F, 0xC8, // ######### #
|
||||
0x80, 0x88, // # # #
|
||||
0x81, 0x08, // # # #
|
||||
0x80, 0x08, // # #
|
||||
0x84, 0x08, // # # #
|
||||
0x88, 0x08, // # # #
|
||||
0x9F, 0xF0, // # #########
|
||||
0x08, 0x00, // #
|
||||
0x04, 0x00, // #
|
||||
};
|
||||
|
||||
const uint8_t PROGMEM thermostatIcon[] =
|
||||
{
|
||||
0x00, 0x00, 0x07, 0x00, // ###
|
||||
0x00, 0x00, 0x0E, 0x00, // ###
|
||||
0x00, 0x00, 0x0C, 0x40, // ## #
|
||||
0x00, 0x00, 0x0C, 0xC0, // ## ##
|
||||
0x00, 0x00, 0x1F, 0xC0, // #######
|
||||
0x00, 0x00, 0x3F, 0x80, // #######
|
||||
0x00, 0x00, 0x7C, 0x00, // #####
|
||||
0x00, 0x00, 0xF8, 0x00, // #####
|
||||
0x38, 0x01, 0xF0, 0x00, // ### #####
|
||||
0x44, 0x01, 0xE0, 0x00, // # # ####
|
||||
0x44, 0x00, 0xC0, 0x00, // # # ##
|
||||
0x45, 0xC0, 0x00, 0x00, // # # ###
|
||||
0x44, 0x00, 0x00, 0x00, // # #
|
||||
0x55, 0xC0, 0x08, 0x00, // # # # ### #
|
||||
0x54, 0x00, 0x1C, 0x00, // # # # ###
|
||||
0x55, 0xC0, 0x2A, 0x00, // # # # ### # # #
|
||||
0x54, 0x00, 0x08, 0x00, // # # # #
|
||||
0x54, 0x00, 0x00, 0x00, // # # #
|
||||
0x54, 0x00, 0x08, 0x00, // # # # #
|
||||
0x54, 0x00, 0x2A, 0x00, // # # # # # #
|
||||
0x54, 0x00, 0x1C, 0x00, // # # # ###
|
||||
0x54, 0x00, 0x08, 0x00, // # # # #
|
||||
0x92, 0x00, 0x00, 0x00, // # # #
|
||||
0xBA, 0x00, 0x00, 0x00, // # ### #
|
||||
0xBA, 0x00, 0x00, 0x00, // # ### #
|
||||
0xBA, 0x00, 0x00, 0x00, // # ### #
|
||||
0x82, 0x00, 0x00, 0x00, // # #
|
||||
0x7C, 0x00, 0x00, 0x80, // ##### #
|
||||
0x00, 0x01, 0xB0, 0xC0, // ## ## ##
|
||||
0x00, 0x01, 0xB0, 0xE0, // ## ## ###
|
||||
0x00, 0x01, 0xB0, 0xF0, // ## ## ####
|
||||
0x00, 0x01, 0xB0, 0xE0, // ## ## ###
|
||||
0x00, 0x01, 0xB0, 0xC0, // ## ## ##
|
||||
0x00, 0x00, 0x00, 0x80, // #
|
||||
};
|
||||
|
||||
|
||||
const uint8_t PROGMEM GPIOIcon[] =
|
||||
{
|
||||
0x00, 0x00, 0x00, //
|
||||
0x00, 0x20, 0x00, // #
|
||||
0x01, 0x20, 0x00, // # #
|
||||
0x00, 0xA0, 0x70, // # # ###
|
||||
0x3F, 0xE0, 0x10, // ######### #
|
||||
0x00, 0xA5, 0x70, // # # # # ###
|
||||
0x01, 0x22, 0x40, // # # # #
|
||||
0x00, 0x25, 0x70, // # # # ###
|
||||
0x00, 0x00, 0x00, //
|
||||
0x00, 0x00, 0x00, //
|
||||
0x00, 0x00, 0x00, //
|
||||
0x00, 0x00, 0x00, //
|
||||
0x20, 0x00, 0x00, // #
|
||||
0x20, 0x80, 0x00, // # #
|
||||
0x20, 0x40, 0x70, // # # ###
|
||||
0x3F, 0xE0, 0x10, // ######### #
|
||||
0x20, 0x45, 0x70, // # # # # ###
|
||||
0x20, 0x82, 0x40, // # # # #
|
||||
0x20, 0x05, 0x70, // # # # ###
|
||||
0x00, 0x00, 0x00, //
|
||||
0x00, 0x00, 0x00, //
|
||||
0x00, 0x00, 0x00, //
|
||||
0x00, 0x00, 0x00, //
|
||||
0x00, 0x00, 0x00, //
|
||||
0x08, 0x00, 0x00, // #
|
||||
0x09, 0x00, 0x00, // # #
|
||||
0x05, 0x00, 0x00, // # #
|
||||
0x24, 0x08, 0x00, // # # #
|
||||
0x02, 0x00, 0x00, // #
|
||||
0x02, 0x00, 0x00, // #
|
||||
0x01, 0x00, 0x00, // #
|
||||
0xC3, 0x86, 0x00, // ## ### ##
|
||||
0x01, 0x80, 0x00, // ##
|
||||
/*
|
||||
0x00, 0x00, //
|
||||
0x00, 0x08, // #
|
||||
0x00, 0x48, // # #
|
||||
0x00, 0x28, // # #
|
||||
0x0F, 0xF8, // #########
|
||||
0x00, 0x28, // # #
|
||||
0x00, 0x48, // # #
|
||||
0x00, 0x08, // #
|
||||
0x00, 0x00, //
|
||||
0x00, 0x00, //
|
||||
0x00, 0x00, //
|
||||
0x00, 0x00, //
|
||||
0x08, 0x00, // #
|
||||
0x08, 0x20, // # #
|
||||
0x08, 0x10, // # #
|
||||
0x0F, 0xF8, // #########
|
||||
0x08, 0x10, // # #
|
||||
0x08, 0x20, // # #
|
||||
0x08, 0x00, // #
|
||||
0x00, 0x00, //
|
||||
0x00, 0x00, //
|
||||
0x00, 0x00, //
|
||||
0x00, 0x00, //
|
||||
0x00, 0x00, //
|
||||
0x08, 0x00, // #
|
||||
0x09, 0x00, // # #
|
||||
0x05, 0x00, // # #
|
||||
0x24, 0x08, // # # #
|
||||
0x02, 0x00, // #
|
||||
0x02, 0x00, // #
|
||||
0x01, 0x00, // #
|
||||
0xC3, 0x86, // ## ### ##
|
||||
0x01, 0x80, // ## */
|
||||
};
|
||||
|
||||
|
||||
const uint8_t PROGMEM firmwareIcon[] =
|
||||
{
|
||||
0xFF, 0xFF, 0xFF, 0xC0, // ##########################
|
||||
0x80, 0x00, 0x00, 0x40, // # #
|
||||
0x9F, 0xFF, 0x2A, 0x40, // # ############# # # # #
|
||||
0x80, 0x00, 0x00, 0x40, // # #
|
||||
0xFF, 0xFF, 0xFF, 0xC0, // ##########################
|
||||
0x80, 0x00, 0x00, 0x40, // # #
|
||||
0x80, 0x00, 0x00, 0x40, // # #
|
||||
0x80, 0x7F, 0x00, 0x40, // # ####### #
|
||||
0x80, 0x7F, 0x00, 0x40, // # ####### #
|
||||
0x80, 0x7F, 0x00, 0x40, // # ####### #
|
||||
0x80, 0x08, 0x00, 0x40, // # # #
|
||||
0x80, 0x08, 0x00, 0x40, // # # #
|
||||
0x83, 0xFF, 0xE0, 0x40, // # ############# #
|
||||
0x82, 0x08, 0x20, 0x40, // # # # # #
|
||||
0x82, 0x08, 0x20, 0x40, // # # # # #
|
||||
0x8F, 0xBE, 0xF8, 0x40, // # ##### ##### ##### #
|
||||
0x8F, 0xBE, 0xF8, 0x40, // # ##### ##### ##### #
|
||||
0x8F, 0xBE, 0xF8, 0x40, // # ##### ##### ##### #
|
||||
0x80, 0x00, 0x00, 0x40, // # #
|
||||
0x80, 0x00, 0x00, 0x40, // # #
|
||||
0xFF, 0xFF, 0xFF, 0xC0, // ##########################
|
||||
};
|
||||
|
||||
|
||||
const uint8_t PROGMEM hardwareIcon[] =
|
||||
{
|
||||
0xFF, 0xFF, // ################
|
||||
0x80, 0x01, // # #
|
||||
0x95, 0x09, // # # # # # #
|
||||
0x95, 0x09, // # # # # # #
|
||||
0xBF, 0x89, // # ####### # #
|
||||
0xA0, 0x89, // # # # # #
|
||||
0xA0, 0x81, // # # # #
|
||||
0xA0, 0x81, // # # # #
|
||||
0xA0, 0x81, // # # # #
|
||||
0xA0, 0x89, // # # # # #
|
||||
0xBF, 0x89, // # ####### # #
|
||||
0x95, 0x09, // # # # # # #
|
||||
0x95, 0x09, // # # # # # #
|
||||
0x80, 0x01, // # #
|
||||
0xFF, 0xFF, // ################
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,185 +0,0 @@
|
|||
/*
|
||||
* This file is part of the "bluetoothheater" distribution
|
||||
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
|
||||
*
|
||||
* Copyright (C) 2018 Ray Jones <ray@mrjones.id.au>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
// 'Thermometer', 8x50px
|
||||
#define W_BULB_ICON 8
|
||||
#define H_BULB_ICON 50
|
||||
extern const unsigned char ambientThermometerIcon [];
|
||||
extern const unsigned char bodyThermometerIcon [];
|
||||
|
||||
// 'ThermoPtr', 3x5px
|
||||
#define W_PTR_ICON 3
|
||||
#define H_PTR_ICON 5
|
||||
extern const unsigned char thermoPtr [];
|
||||
|
||||
// 'Bluetooth icon', 6x11px
|
||||
#define W_BT_ICON 6
|
||||
#define H_BT_ICON 11
|
||||
extern const unsigned char BTicon [];
|
||||
|
||||
// 'wifiIcon', 13x10px
|
||||
#define W_WIFI_ICON 13
|
||||
#define H_WIFI_ICON 10
|
||||
extern const unsigned char wifiIcon [];
|
||||
|
||||
// 'wifiInIcon', 5x5px
|
||||
#define W_WIFIIN_ICON 5
|
||||
#define H_WIFIIN_ICON 5
|
||||
extern const unsigned char wifiInIcon [];
|
||||
|
||||
// 'wifiOutIcon', 5x5px
|
||||
#define W_WIFIOUT_ICON 5
|
||||
#define H_WIFIOUT_ICON 5
|
||||
extern const unsigned char wifiOutIcon [];
|
||||
|
||||
// 'BatteryIcon', 15x10px
|
||||
#define W_BATT_ICON 15
|
||||
#define H_BATT_ICON 10
|
||||
extern const unsigned char BatteryIcon [];
|
||||
|
||||
// 'GlowPlugIcon', 16x9px
|
||||
#define W_GLOW_ICON 16
|
||||
#define H_GLOW_ICON 9
|
||||
extern const unsigned char GlowPlugIcon [];
|
||||
|
||||
// 'HeatRise', 17x2px
|
||||
#define W_HEAT_ICON 17
|
||||
#define H_HEAT_ICON 2
|
||||
extern const unsigned char GlowHeatIcon [];
|
||||
|
||||
#define W_FAN_ICON 16
|
||||
#define H_FAN_ICON 16
|
||||
// 'Fan3_1a', 16x16px
|
||||
extern const unsigned char FanIcon1 [];
|
||||
// 'Fan3_2a', 16x16px
|
||||
extern const unsigned char FanIcon2 [];
|
||||
// 'Fan3_3a', 16x16px
|
||||
extern const unsigned char FanIcon3 [];
|
||||
// 'Fan3_4a', 16x16px
|
||||
extern const unsigned char FanIcon4 [];
|
||||
|
||||
|
||||
// 'FuelIcon', 7x12px
|
||||
#define W_FUEL_ICON 7
|
||||
#define H_FUEL_ICON 12
|
||||
extern const unsigned char FuelIcon [];
|
||||
|
||||
// 'Target', 13x13px
|
||||
#define W_TARGET_ICON 13
|
||||
#define H_TARGET_ICON 13
|
||||
extern const unsigned char TargetIcon [];
|
||||
|
||||
#define W_TIMER_ICON 15
|
||||
#define H_TIMER_ICON 15
|
||||
extern const unsigned char repeatIcon [];
|
||||
extern const unsigned char timerID1Icon [];
|
||||
extern const unsigned char timerID2Icon [];
|
||||
extern const unsigned char timerIcon [];
|
||||
extern const unsigned char largeTimerIcon [];
|
||||
extern const uint8_t verticalRepeatIcon [];
|
||||
extern const uint8_t GPIO1OFFIcon[];
|
||||
extern const uint8_t GPIO1ONIcon[];
|
||||
extern const uint8_t GPIO2OFFIcon[];
|
||||
extern const uint8_t GPIO2ONIcon[];
|
||||
extern const uint8_t CrossIcon[];
|
||||
extern const uint8_t TickIcon[];
|
||||
// Bitmap sizes for verticalRepeat
|
||||
const uint8_t verticalRepeatWidthPixels = 6;
|
||||
const uint8_t verticalRepeatHeightPixels = 15;
|
||||
|
||||
// Bitmap sizes for GPIOIcons
|
||||
const uint8_t GPIOIconWidthPixels = 9;
|
||||
const uint8_t GPIOIconHeightPixels = 9;
|
||||
|
||||
// Bitmap sizes for TickIcons
|
||||
const uint8_t TickIconWidth = 5;
|
||||
const uint8_t TickIconHeight = 5;
|
||||
|
||||
// Bitmap for open
|
||||
extern const uint8_t OpenIcon[];
|
||||
const uint8_t OpenIconWidth = 13;
|
||||
const uint8_t OpenIconHeight = 7;
|
||||
|
||||
// Bitmap for close
|
||||
extern const uint8_t CloseIcon[];
|
||||
const uint8_t CloseIconWidth = 13;
|
||||
const uint8_t CloseIconHeight = 7;
|
||||
|
||||
// Bitmap for BulbOn
|
||||
extern const uint8_t BulbOnIcon[];
|
||||
const uint8_t BulbOnIconWidth = 9;
|
||||
const uint8_t BulbOnIconHeight = 8;
|
||||
|
||||
// Bitmap for BulbOff
|
||||
extern const uint8_t BulbOffIcon[];
|
||||
const uint8_t BulbOffIconWidth = 9;
|
||||
const uint8_t BulbOffIconHeight = 8;
|
||||
|
||||
// Bitmap for start
|
||||
extern const uint8_t startIcon[];
|
||||
const uint8_t startWidth = 5;
|
||||
const uint8_t startHeight = 9;
|
||||
|
||||
// Bitmap sizes for stop
|
||||
extern const uint8_t stopIcon[];
|
||||
const uint8_t stopWidth = 6;
|
||||
const uint8_t stopHeight = 8;
|
||||
|
||||
// Bitmap for displayTimeout
|
||||
extern const uint8_t displayTimeoutIcon[];
|
||||
const uint8_t displayTimeoutWidth = 24;
|
||||
const uint8_t displayTimeoutHeight = 10;
|
||||
|
||||
// Bitmap for menuTimeout
|
||||
extern const uint8_t menuTimeoutIcon[];
|
||||
const uint8_t menuTimeoutWidth = 24;
|
||||
const uint8_t menuTimeoutHeight = 10;
|
||||
|
||||
// Bitmap for timeout
|
||||
extern const uint8_t timeoutIcon[];
|
||||
const uint8_t timeoutWidth = 9;
|
||||
const uint8_t timeoutHeight = 10;
|
||||
|
||||
// Bitmap for refresh
|
||||
extern const uint8_t refreshIcon[];
|
||||
const uint8_t refreshWidth = 13;
|
||||
const uint8_t refreshHeight = 11;
|
||||
|
||||
// Bitmap for thermostat modes
|
||||
extern const uint8_t thermostatIcon[];
|
||||
const uint8_t thermostatWidth = 28;
|
||||
const uint8_t thermostatHeight = 34;
|
||||
|
||||
// Bitmap for gPIO
|
||||
extern const uint8_t GPIOIcon[];
|
||||
const uint8_t GPIOWidth = 20;
|
||||
const uint8_t GPIOHeight = 33;
|
||||
|
||||
// Bitmap for firmware
|
||||
extern const uint8_t firmwareIcon[];
|
||||
const uint8_t firmwareWidth = 26;
|
||||
const uint8_t firmwareHeight = 21;
|
||||
|
||||
// Bitmap for hardware
|
||||
extern const uint8_t hardwareIcon[];
|
||||
const uint8_t hardwareWidth = 16;
|
||||
const uint8_t hardwareHeight = 15;
|
||||
|
|
@ -1,314 +0,0 @@
|
|||
//
|
||||
// Font data for Tahoma 16pt
|
||||
//
|
||||
// Generated by The Dot Factory:
|
||||
// http://www.eran.io/the-dot-factory-an-lcd-font-and-image-generator/
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Dot Factory Settings
|
||||
//
|
||||
// Flip/Rotate Padding Removal Line Wrap Descriptors
|
||||
// [X] Flip X Height(Y): Tightest (O) At column [X] Generate descriptor array
|
||||
// [ ] Flip Y Width(X): Tightest ( ) At bitmap Char Width: In Bits
|
||||
// 90deg Char Height: In Bits
|
||||
// Font Height: In Bits
|
||||
// Comments Byte [ ] Multiple descriptor arrays
|
||||
// [X] Variable Name Bit layout: RowMajor
|
||||
// [X] BMP visualise [#] Order: MSBfirst Create new when exceeds [80]
|
||||
// [X] Char descriptor Format: Hex
|
||||
// Style: Cpp Leading: 0x Image width: In Bits
|
||||
// Image height: In Bits
|
||||
// Variable name format
|
||||
// Bitmaps: const uint8_t PROGMEM {0}Bitmaps Space char generation
|
||||
// Char Info: const FONT_CHAR_INFO PROGMEM {0}Descriptors [ ] Generate space bitmap
|
||||
// Font Info: const FONT_INFO {0}FontInfo [2] pixels for space char
|
||||
// Width: const uint8_t {0}Width
|
||||
// Height: const uint8_t {0}Height
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "tahoma16.h"
|
||||
|
||||
// Character bitmaps for Tahoma 16pt
|
||||
const uint8_t tahoma_16ptBitmaps[] PROGMEM =
|
||||
{
|
||||
// @0 '.' (4 pixels wide)
|
||||
0x00, 0x0F, // ####
|
||||
0x00, 0x0F, // ####
|
||||
0x00, 0x0F, // ####
|
||||
0x00, 0x0F, // ####
|
||||
|
||||
// @8 '0' (11 pixels wide)
|
||||
0x0F, 0xF0, // ########
|
||||
0x3F, 0xFC, // ############
|
||||
0x7F, 0xFE, // ##############
|
||||
0xFF, 0xFF, // ################
|
||||
0xF0, 0x0F, // #### ####
|
||||
0xE0, 0x07, // ### ###
|
||||
0xF0, 0x0F, // #### ####
|
||||
0xFF, 0xFF, // ################
|
||||
0x7F, 0xFE, // ##############
|
||||
0x3F, 0xFC, // ############
|
||||
0x0F, 0xF0, // ########
|
||||
|
||||
// @30 '1' (10 pixels wide)
|
||||
0x38, 0x07, // ### ###
|
||||
0x38, 0x07, // ### ###
|
||||
0x38, 0x07, // ### ###
|
||||
0xFF, 0xFF, // ################
|
||||
0xFF, 0xFF, // ################
|
||||
0xFF, 0xFF, // ################
|
||||
0xFF, 0xFF, // ################
|
||||
0x00, 0x07, // ###
|
||||
0x00, 0x07, // ###
|
||||
0x00, 0x07, // ###
|
||||
|
||||
// @50 '2' (11 pixels wide)
|
||||
0x70, 0x07, // ### ###
|
||||
0xE0, 0x0F, // ### ####
|
||||
0xE0, 0x1F, // ### #####
|
||||
0xE0, 0x3F, // ### ######
|
||||
0xE0, 0x7F, // ### #######
|
||||
0xF1, 0xF7, // #### ##### ###
|
||||
0xFF, 0xE7, // ########### ###
|
||||
0x7F, 0xC7, // ######### ###
|
||||
0x7F, 0x87, // ######## ###
|
||||
0x3E, 0x07, // ##### ###
|
||||
0x00, 0x07, // ###
|
||||
|
||||
// @72 '3' (11 pixels wide)
|
||||
0x70, 0x0E, // ### ###
|
||||
0xF0, 0x0F, // #### ####
|
||||
0xE0, 0x07, // ### ###
|
||||
0xE3, 0x87, // ### ### ###
|
||||
0xE3, 0x87, // ### ### ###
|
||||
0xE3, 0x87, // ### ### ###
|
||||
0xE7, 0xCF, // ### ##### ####
|
||||
0xFF, 0xFF, // ################
|
||||
0x7E, 0xFE, // ###### #######
|
||||
0x7E, 0xFE, // ###### #######
|
||||
0x3C, 0x78, // #### ####
|
||||
|
||||
// @94 '4' (12 pixels wide)
|
||||
0x00, 0xF0, // ####
|
||||
0x01, 0xF0, // #####
|
||||
0x07, 0x70, // ### ###
|
||||
0x0E, 0x70, // ### ###
|
||||
0x38, 0x70, // ### ###
|
||||
0x70, 0x70, // ### ###
|
||||
0xFF, 0xFF, // ################
|
||||
0xFF, 0xFF, // ################
|
||||
0xFF, 0xFF, // ################
|
||||
0xFF, 0xFF, // ################
|
||||
0x00, 0x70, // ###
|
||||
0x00, 0x70, // ###
|
||||
|
||||
// @118 '5' (11 pixels wide)
|
||||
0x00, 0x0E, // ###
|
||||
0xFF, 0x87, // ######### ###
|
||||
0xFF, 0x87, // ######### ###
|
||||
0xFF, 0x87, // ######### ###
|
||||
0xFF, 0x87, // ######### ###
|
||||
0xE3, 0x87, // ### ### ###
|
||||
0xE3, 0xCF, // ### #### ####
|
||||
0xE3, 0xFF, // ### ##########
|
||||
0xE3, 0xFE, // ### #########
|
||||
0xE1, 0xFC, // ### #######
|
||||
0xE0, 0xF8, // ### #####
|
||||
|
||||
// @140 '6' (11 pixels wide)
|
||||
0x07, 0xF0, // #######
|
||||
0x1F, 0xFC, // ###########
|
||||
0x3F, 0xFE, // #############
|
||||
0x7F, 0xFF, // ###############
|
||||
0xFB, 0x0F, // ##### ## ####
|
||||
0xF7, 0x07, // #### ### ###
|
||||
0xE7, 0x8F, // ### #### ####
|
||||
0xE7, 0xFF, // ### ###########
|
||||
0xE7, 0xFE, // ### ##########
|
||||
0xE3, 0xFC, // ### ########
|
||||
0x01, 0xF8, // ######
|
||||
|
||||
// @162 '7' (11 pixels wide)
|
||||
0xE0, 0x01, // ### #
|
||||
0xE0, 0x07, // ### ###
|
||||
0xE0, 0x1F, // ### #####
|
||||
0xE0, 0x7F, // ### #######
|
||||
0xE1, 0xFF, // ### #########
|
||||
0xE7, 0xFC, // ### #########
|
||||
0xFF, 0xF0, // ############
|
||||
0xFF, 0xC0, // ##########
|
||||
0xFF, 0x00, // ########
|
||||
0xFC, 0x00, // ######
|
||||
0xF0, 0x00, // ####
|
||||
|
||||
// @184 '8' (11 pixels wide)
|
||||
0x3C, 0x3C, // #### ####
|
||||
0x7E, 0xFE, // ###### #######
|
||||
0x7F, 0xFE, // ##############
|
||||
0xFF, 0xFF, // ################
|
||||
0xE7, 0x8F, // ### #### ####
|
||||
0xE3, 0x87, // ### ### ###
|
||||
0xE3, 0xC7, // ### #### ###
|
||||
0xFF, 0xFF, // ################
|
||||
0x7F, 0xFE, // ##############
|
||||
0x7E, 0xFE, // ###### #######
|
||||
0x3C, 0x7C, // #### #####
|
||||
|
||||
// @206 '9' (11 pixels wide)
|
||||
0x1F, 0x80, // ######
|
||||
0x3F, 0xC7, // ######## ###
|
||||
0x7F, 0xE7, // ########## ###
|
||||
0xFF, 0xE7, // ########### ###
|
||||
0xF1, 0xE7, // #### #### ###
|
||||
0xE0, 0xEF, // ### ### ####
|
||||
0xF0, 0xDF, // #### ## #####
|
||||
0xFF, 0xFE, // ###############
|
||||
0x7F, 0xFC, // #############
|
||||
0x3F, 0xF8, // ###########
|
||||
0x0F, 0xE0, // #######
|
||||
|
||||
// @228 '`' (8 pixels wide)
|
||||
0x3C, 0x00, // ####
|
||||
0x7E, 0x00, // ######
|
||||
0xE7, 0x00, // ### ###
|
||||
0xC3, 0x00, // ## ##
|
||||
0xC3, 0x00, // ## ##
|
||||
0xE7, 0x00, // ### ###
|
||||
0x7E, 0x00, // ######
|
||||
0x3C, 0x00, // ####
|
||||
|
||||
// @244 'C' (12 pixels wide)
|
||||
0x07, 0xE0, // ######
|
||||
0x1F, 0xF8, // ##########
|
||||
0x3F, 0xFC, // ############
|
||||
0x7F, 0xFE, // ##############
|
||||
0xF8, 0x1F, // ##### #####
|
||||
0xF0, 0x0F, // #### ####
|
||||
0xE0, 0x07, // ### ###
|
||||
0xE0, 0x07, // ### ###
|
||||
0xE0, 0x07, // ### ###
|
||||
0xE0, 0x07, // ### ###
|
||||
0x70, 0x0E, // ### ###
|
||||
0x78, 0x1E, // #### ####
|
||||
|
||||
// @268 ':' (4 pixels wide)
|
||||
0x3C, 0x3C, // #### ####
|
||||
0x3C, 0x3C, // #### ####
|
||||
0x3C, 0x3C, // #### ####
|
||||
0x3C, 0x3C, // #### ####
|
||||
|
||||
// @276 ' ' (4 pixels wide)
|
||||
0x00, 0x00, //
|
||||
0x00, 0x00, //
|
||||
0x00, 0x00, //
|
||||
0x00, 0x00, //
|
||||
|
||||
// @284 '-' (4 pixels wide)
|
||||
0x03, 0xC0, // ####
|
||||
0x03, 0xC0, // ####
|
||||
0x03, 0xC0, // ####
|
||||
0x03, 0xC0, // ####
|
||||
0x03, 0xC0, // ####
|
||||
0x03, 0xC0, // ####
|
||||
0x03, 0xC0, // ####
|
||||
0x03, 0xC0, // ####
|
||||
|
||||
// @300 'F' (9 pixels wide)
|
||||
0xFF, 0xFF, // ################
|
||||
0xFF, 0xFF, // ################
|
||||
0xFF, 0xFF, // ################
|
||||
0xFF, 0xFF, // ################
|
||||
0xE3, 0x80, // ### ###
|
||||
0xE3, 0x80, // ### ###
|
||||
0xE3, 0x80, // ### ###
|
||||
0xE3, 0x80, // ### ###
|
||||
0xE3, 0x80, // ### ###
|
||||
0xE3, 0x80, // ### ###
|
||||
|
||||
};
|
||||
|
||||
// Character descriptors for Tahoma 16pt
|
||||
// { [Char width in bits], [Char height in bits], [Offset into tahoma_16ptCharBitmaps in bytes] }
|
||||
const FONT_CHAR_INFO tahoma_16ptDescriptors[] PROGMEM =
|
||||
{
|
||||
{4, 16, 276}, // ' '
|
||||
{0, 0, 0}, // '!'
|
||||
{0, 0, 0}, // '"'
|
||||
{0, 0, 0}, // '#'
|
||||
{0, 0, 0}, // '$'
|
||||
{0, 0, 0}, // '%'
|
||||
{0, 0, 0}, // '&'
|
||||
{0, 0, 0}, // '''
|
||||
{0, 0, 0}, // '('
|
||||
{0, 0, 0}, // ')'
|
||||
{0, 0, 0}, // '*'
|
||||
{0, 0, 0}, // '+'
|
||||
{0, 0, 0}, // ,
|
||||
{8, 16, 284}, // -
|
||||
{4, 16, 0}, // '.'
|
||||
{0, 0, 0}, // '/'
|
||||
{11, 16, 8}, // '0'
|
||||
{10, 16, 30}, // '1'
|
||||
{11, 16, 50}, // '2'
|
||||
{11, 16, 72}, // '3'
|
||||
{12, 16, 94}, // '4'
|
||||
{11, 16, 118}, // '5'
|
||||
{11, 16, 140}, // '6'
|
||||
{11, 16, 162}, // '7'
|
||||
{11, 16, 184}, // '8'
|
||||
{11, 16, 206}, // '9'
|
||||
{4, 16, 268}, // ':'
|
||||
{0, 0, 0}, // ';'
|
||||
{0, 0, 0}, // '<'
|
||||
{0, 0, 0}, // '='
|
||||
{0, 0, 0}, // '>'
|
||||
{0, 0, 0}, // '?'
|
||||
{0, 0, 0}, // '@'
|
||||
{0, 0, 0}, // 'A'
|
||||
{0, 0, 0}, // 'B'
|
||||
{12, 16, 244}, // 'C'
|
||||
{0, 0, 0}, // 'D'
|
||||
{0, 0, 0}, // 'E'
|
||||
{10, 16, 300}, // 'F'
|
||||
{0, 0, 0}, // 'G'
|
||||
{0, 0, 0}, // 'H'
|
||||
{0, 0, 0}, // 'I'
|
||||
{0, 0, 0}, // 'J'
|
||||
{0, 0, 0}, // 'K'
|
||||
{0, 0, 0}, // 'L'
|
||||
{0, 0, 0}, // 'M'
|
||||
{0, 0, 0}, // 'N'
|
||||
{0, 0, 0}, // 'O'
|
||||
{0, 0, 0}, // 'P'
|
||||
{0, 0, 0}, // 'Q'
|
||||
{0, 0, 0}, // 'R'
|
||||
{0, 0, 0}, // 'S'
|
||||
{0, 0, 0}, // 'T'
|
||||
{0, 0, 0}, // 'U'
|
||||
{0, 0, 0}, // 'V'
|
||||
{0, 0, 0}, // 'W'
|
||||
{0, 0, 0}, // 'X'
|
||||
{0, 0, 0}, // 'Y'
|
||||
{0, 0, 0}, // 'Z'
|
||||
{0, 0, 0}, // '['
|
||||
{0, 0, 0}, // '\'
|
||||
{0, 0, 0}, // ']'
|
||||
{0, 0, 0}, // '^'
|
||||
{0, 0, 0}, // '_'
|
||||
{8, 16, 228}, // '`' use for degree symbol
|
||||
};
|
||||
|
||||
// Font information for Tahoma 16pt
|
||||
// easier to leave in RAM, not that big anyway
|
||||
const FONT_INFO tahoma_16ptFontInfo =
|
||||
{
|
||||
16, // Character height
|
||||
' ', // Start character
|
||||
'`', // End character
|
||||
2, // Width, in pixels, of space character
|
||||
tahoma_16ptDescriptors, // Character descriptor array
|
||||
tahoma_16ptBitmaps, // Character bitmap array
|
||||
};
|
|
@ -1,7 +0,0 @@
|
|||
#include "FontTypes.h"
|
||||
|
||||
// Font data for Tahoma 16pt
|
||||
extern const uint8_t tahoma_16ptBitmaps[] PROGMEM; // stored in program flash memory
|
||||
extern const FONT_CHAR_INFO tahoma_16ptDescriptors[] PROGMEM; // stored in program flash memory
|
||||
extern const FONT_INFO tahoma_16ptFontInfo;
|
||||
|
|
@ -1,251 +0,0 @@
|
|||
/*
|
||||
* This file is part of the "bluetoothheater" distribution
|
||||
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
|
||||
*
|
||||
* Copyright (C) 2018 Ray Jones <ray@mrjones.id.au>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _CPROTOCOL_H_
|
||||
#define _CPROTOCOL_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "../Utility/UtilClasses.h"
|
||||
|
||||
class CProtocol {
|
||||
public:
|
||||
union {
|
||||
unsigned char Data[24];
|
||||
struct {
|
||||
unsigned char Byte0; // [0] always 0x76
|
||||
unsigned char Len; // [1] always 0x16 == 22
|
||||
unsigned char Command; // [2] transient commands: 00: NOP, 0xa0 START, 0x05: STOP
|
||||
unsigned char ActualTemperature; // [3] 1degC / digit
|
||||
unsigned char DesiredTemperature; // [4] 1degC / digit
|
||||
unsigned char MinPumpFreq; // [5] 0.1Hz/digit
|
||||
unsigned char MaxPumpFreq; // [6] 0.1Hz/digit
|
||||
unsigned char MinFanRPM_MSB; // [7] 16 bit - big endian MSB
|
||||
unsigned char MinFanRPM_LSB; // [8] 16 bit - big endian LSB : 1 RPM / digit
|
||||
unsigned char MaxFanRPM_MSB; // [9] 16 bit - big endian MSB
|
||||
unsigned char MaxFanRPM_LSB; // [10] 16 bit - big endian LSB : 1 RPM / digit
|
||||
unsigned char OperatingVoltage; // [11] 120, 240 : 0.1V/digit
|
||||
unsigned char FanSensor; // [12] SN-1 or SN-2
|
||||
unsigned char OperatingMode; // [13] 0x32:Thermostat, 0xCD:Fixed
|
||||
unsigned char MinTemperature; // [14] Minimum settable temperature
|
||||
unsigned char MaxTemperature; // [15] Maximum settable temperature
|
||||
unsigned char GlowDrive; // [16] power to supply to glow plug
|
||||
unsigned char Prime; // [17] 00: normal, 0x5A: fuel prime
|
||||
unsigned char Unknown1_MSB; // [18] always 0x01
|
||||
unsigned char Unknown1_LSB; // [19] always 0x2c "300 secs = max run without burn detected"?
|
||||
unsigned char Unknown2_MSB; // [20] always 0x0d
|
||||
unsigned char Unknown2_LSB; // [21] always 0xac "3500 ?"
|
||||
unsigned char CRC_MSB; // [22]
|
||||
unsigned char CRC_LSB; // [23]
|
||||
} Controller;
|
||||
struct {
|
||||
unsigned char Byte0; // always 0x76
|
||||
unsigned char Len; // always 0x16 == 22 bytes
|
||||
unsigned char RunState; // operating state
|
||||
unsigned char ErrState; // 0: OFF, 1: ON, 2+ (E-0n + 1)
|
||||
unsigned char SupplyV_MSB; // 16 bit - big endian MSB
|
||||
unsigned char SupplyV_LSB; // 16 bit - big endian MSB : 0.1V / digit
|
||||
unsigned char FanRPM_MSB; // 16 bit - big endian MSB
|
||||
unsigned char FanRPM_LSB; // 16 bit - big endian LSB : 1 RPM / digit
|
||||
unsigned char FanVoltage_MSB; // 16 bit - big endian MSB
|
||||
unsigned char FanVoltage_LSB; // 16 bit - big endian LSB : 0.1V / digit
|
||||
unsigned char HeatExchgTemp_MSB; // 16 bit - big endian MSB
|
||||
unsigned char HeatExchgTemp_LSB; // 16 bit - big endian LSB : 1 degC / digit
|
||||
unsigned char GlowPlugVoltage_MSB; // 16 bit - big endian MSB
|
||||
unsigned char GlowPlugVoltage_LSB; // 16 bit - big endian LSB : 0.1V / digit
|
||||
unsigned char GlowPlugCurrent_MSB; // 16 bit - big endian MSB
|
||||
unsigned char GlowPlugCurrent_LSB; // 16 bit - big endian LSB : 10mA / digit
|
||||
unsigned char ActualPumpFreq; // fuel pump freq.: 0.1Hz / digit
|
||||
unsigned char StoredErrorCode; //
|
||||
unsigned char Unknown1; // always 0x00
|
||||
unsigned char FixedPumpFreq; // fixed mode frequency set point: 0.1Hz / digit
|
||||
unsigned char Unknown2; // always 0x64 "100 ?"
|
||||
unsigned char Unknown3; // always 0x00
|
||||
unsigned char CRC_MSB;
|
||||
unsigned char CRC_LSB;
|
||||
} Heater;
|
||||
};
|
||||
static const int CtrlMode = 1;
|
||||
static const int HeatMode = 2;
|
||||
const unsigned short wCRCTable[256] = {
|
||||
0X0000, 0XC0C1, 0XC181, 0X0140, 0XC301, 0X03C0, 0X0280, 0XC241,
|
||||
0XC601, 0X06C0, 0X0780, 0XC741, 0X0500, 0XC5C1, 0XC481, 0X0440,
|
||||
0XCC01, 0X0CC0, 0X0D80, 0XCD41, 0X0F00, 0XCFC1, 0XCE81, 0X0E40,
|
||||
0X0A00, 0XCAC1, 0XCB81, 0X0B40, 0XC901, 0X09C0, 0X0880, 0XC841,
|
||||
0XD801, 0X18C0, 0X1980, 0XD941, 0X1B00, 0XDBC1, 0XDA81, 0X1A40,
|
||||
0X1E00, 0XDEC1, 0XDF81, 0X1F40, 0XDD01, 0X1DC0, 0X1C80, 0XDC41,
|
||||
0X1400, 0XD4C1, 0XD581, 0X1540, 0XD701, 0X17C0, 0X1680, 0XD641,
|
||||
0XD201, 0X12C0, 0X1380, 0XD341, 0X1100, 0XD1C1, 0XD081, 0X1040,
|
||||
0XF001, 0X30C0, 0X3180, 0XF141, 0X3300, 0XF3C1, 0XF281, 0X3240,
|
||||
0X3600, 0XF6C1, 0XF781, 0X3740, 0XF501, 0X35C0, 0X3480, 0XF441,
|
||||
0X3C00, 0XFCC1, 0XFD81, 0X3D40, 0XFF01, 0X3FC0, 0X3E80, 0XFE41,
|
||||
0XFA01, 0X3AC0, 0X3B80, 0XFB41, 0X3900, 0XF9C1, 0XF881, 0X3840,
|
||||
0X2800, 0XE8C1, 0XE981, 0X2940, 0XEB01, 0X2BC0, 0X2A80, 0XEA41,
|
||||
0XEE01, 0X2EC0, 0X2F80, 0XEF41, 0X2D00, 0XEDC1, 0XEC81, 0X2C40,
|
||||
0XE401, 0X24C0, 0X2580, 0XE541, 0X2700, 0XE7C1, 0XE681, 0X2640,
|
||||
0X2200, 0XE2C1, 0XE381, 0X2340, 0XE101, 0X21C0, 0X2080, 0XE041,
|
||||
0XA001, 0X60C0, 0X6180, 0XA141, 0X6300, 0XA3C1, 0XA281, 0X6240,
|
||||
0X6600, 0XA6C1, 0XA781, 0X6740, 0XA501, 0X65C0, 0X6480, 0XA441,
|
||||
0X6C00, 0XACC1, 0XAD81, 0X6D40, 0XAF01, 0X6FC0, 0X6E80, 0XAE41,
|
||||
0XAA01, 0X6AC0, 0X6B80, 0XAB41, 0X6900, 0XA9C1, 0XA881, 0X6840,
|
||||
0X7800, 0XB8C1, 0XB981, 0X7940, 0XBB01, 0X7BC0, 0X7A80, 0XBA41,
|
||||
0XBE01, 0X7EC0, 0X7F80, 0XBF41, 0X7D00, 0XBDC1, 0XBC81, 0X7C40,
|
||||
0XB401, 0X74C0, 0X7580, 0XB541, 0X7700, 0XB7C1, 0XB681, 0X7640,
|
||||
0X7200, 0XB2C1, 0XB381, 0X7340, 0XB101, 0X71C0, 0X7080, 0XB041,
|
||||
0X5000, 0X90C1, 0X9181, 0X5140, 0X9301, 0X53C0, 0X5280, 0X9241,
|
||||
0X9601, 0X56C0, 0X5780, 0X9741, 0X5500, 0X95C1, 0X9481, 0X5440,
|
||||
0X9C01, 0X5CC0, 0X5D80, 0X9D41, 0X5F00, 0X9FC1, 0X9E81, 0X5E40,
|
||||
0X5A00, 0X9AC1, 0X9B81, 0X5B40, 0X9901, 0X59C0, 0X5880, 0X9841,
|
||||
0X8801, 0X48C0, 0X4980, 0X8941, 0X4B00, 0X8BC1, 0X8A81, 0X4A40,
|
||||
0X4E00, 0X8EC1, 0X8F81, 0X4F40, 0X8D01, 0X4DC0, 0X4C80, 0X8C41,
|
||||
0X4400, 0X84C1, 0X8581, 0X4540, 0X8701, 0X47C0, 0X4680, 0X8641,
|
||||
0X8201, 0X42C0, 0X4380, 0X8341, 0X4100, 0X81C1, 0X8081, 0X4040
|
||||
};
|
||||
|
||||
public:
|
||||
CProtocol() { Init(0); };
|
||||
CProtocol(int TxMode) { Init(TxMode); };
|
||||
|
||||
void Init(int Txmode);
|
||||
// CRC handlers
|
||||
unsigned short CalcCRC(int len) const; // calculate the CRC upon len bytes
|
||||
void setCRC(); // calculate and set the CRC in the buffer
|
||||
void setCRC(unsigned short CRC); // set the CRC in the buffer
|
||||
unsigned short getCRC() const; // extract CRC value from buffer
|
||||
bool verifyCRC(bool silent=false) const; // return true for CRC match
|
||||
|
||||
void setActiveMode() { Controller.Byte0 = 0x76; }; // this allows heater to save tuning params to EEPROM
|
||||
void setPassiveMode() { Controller.Byte0 = 0x78; }; // this prevents heater saving tuning params to EEPROM
|
||||
// command helpers
|
||||
void resetCommand() { setRawCommand(0x00); };
|
||||
void onCommand() { setRawCommand(0xA0); };
|
||||
void offCommand() { setRawCommand(0x05); };
|
||||
// raw command
|
||||
int getRawCommand() const { return Controller.Command; };
|
||||
void setRawCommand(int mode) { Controller.Command = mode; };
|
||||
// Run state
|
||||
unsigned char getRunState() const { return Heater.RunState; };
|
||||
void setRunState(unsigned char state) { Heater.RunState = state; };
|
||||
unsigned char getErrState() const { return Heater.ErrState; };
|
||||
void setErrState(unsigned char state) { Heater.ErrState = state; };
|
||||
unsigned char getStoredErrCode() const { return Heater.StoredErrorCode; };
|
||||
void setStoredErrCode(unsigned char state) { Heater.StoredErrorCode = state; };
|
||||
//
|
||||
float getVoltage_Supply() const;
|
||||
float getVoltage_SupplyRaw() const;
|
||||
void setVoltage_Supply(float volts);
|
||||
float getSystemVoltage() const { return float(Controller.OperatingVoltage) * 0.1; };
|
||||
void setSystemVoltage(float val);
|
||||
|
||||
// fan set/get
|
||||
short getFan_Actual() const; // Heater side, actual
|
||||
short getFan_Min() const; // Controller side, define min fan speed
|
||||
short getFan_Max() const; // Controller side, define max fan speed
|
||||
void setFan_Actual(short speed); // Heater side, actual
|
||||
void setFan_Min(short speed); // Controller side, define min fan speed
|
||||
void setFan_Max(short speed); // Controller side, define max fan speed
|
||||
float getFan_Voltage() const; // fan voltage
|
||||
void setFan_Voltage(float volts); // fan voltage
|
||||
|
||||
// pump set/get
|
||||
void setPump_Min(float Freq) { Controller.MinPumpFreq = (uint8_t)(Freq * 10.f + 0.5f); };
|
||||
void setPump_Max(float Freq) { Controller.MaxPumpFreq = (uint8_t)(Freq * 10.f + 0.5f); };
|
||||
void setPump_Actual(float Freq) { Heater.ActualPumpFreq = (uint8_t)(Freq * 10.f + 0.5f); };
|
||||
void setPump_Fixed(float Freq) { Heater.FixedPumpFreq = (uint8_t)(Freq * 10.f + 0.5f); };
|
||||
float getPump_Min() const { return float(Controller.MinPumpFreq) * 0.1f; }; // Tx side, min pump freq
|
||||
float getPump_Max() const { return float(Controller.MaxPumpFreq) * 0.1f; }; // Tx side, max pump freq
|
||||
float getPump_Actual() const { return float(Heater.ActualPumpFreq) * 0.1f; }; // Rx style, actual
|
||||
float getPump_Fixed() const { return float(Heater.FixedPumpFreq) * 0.1f; }; // Fixed mode pump frequency
|
||||
void setPump_Prime(bool on) { Controller.Prime = on ? 0x5A : 0; };
|
||||
// temperature set/get
|
||||
void setTemperature_Desired(unsigned char degC) { Controller.DesiredTemperature = degC; };
|
||||
void setTemperature_Min(unsigned char degC) { Controller.MinTemperature = degC; };
|
||||
void setTemperature_Max(unsigned char degC) { Controller.MaxTemperature = degC; };
|
||||
void setTemperature_Actual(unsigned char degC) { Controller.ActualTemperature = degC; };
|
||||
unsigned char getTemperature_Desired() const { return Controller.DesiredTemperature; };
|
||||
unsigned char getTemperature_Min() const { return Controller.MinTemperature; };
|
||||
unsigned char getTemperature_Max() const { return Controller.MaxTemperature; };
|
||||
unsigned char getTemperature_Actual() const { return Controller.ActualTemperature; };
|
||||
void setThermostatModeProtocol(unsigned on);
|
||||
bool isThermostat() const { return Controller.OperatingMode == 0x32; };
|
||||
// glow plug
|
||||
float getGlowPlug_Current() const; // glow plug current
|
||||
float getGlowPlug_Voltage() const; // glow plug voltage
|
||||
void setGlowPlug_Current(short ampsx100); // glow plug current
|
||||
void setGlowPlug_Voltage(short voltsx10); // glow plug voltage
|
||||
void setGlowDrive(unsigned char val) { Controller.GlowDrive = val; };
|
||||
unsigned char getGlowDrive() const { return Controller.GlowDrive; };
|
||||
// heat exchanger
|
||||
short getTemperature_HeatExchg() const; // temperature of heat exchanger
|
||||
void setTemperature_HeatExchg(short degC); // temperature of heat exchanger
|
||||
|
||||
void DebugReport(const char* hdr, const char* ftr);
|
||||
|
||||
CProtocol& operator=(const CProtocol& rhs);
|
||||
};
|
||||
|
||||
class CModeratedFrame : public CProtocol {
|
||||
unsigned long lastTime;
|
||||
public:
|
||||
CModeratedFrame() { lastTime = 0; };
|
||||
void setTime() { lastTime = millis(); };
|
||||
long elapsedTime() { return millis() - lastTime; };
|
||||
};
|
||||
|
||||
|
||||
class CProtocolPackage {
|
||||
CProtocol Heater;
|
||||
CProtocol Controller;
|
||||
CContextTimeStamp _timeStamp;
|
||||
public:
|
||||
void set(const CProtocol& htr, const CProtocol& ctl) { Heater = htr; Controller = ctl; };
|
||||
int getRunState() const { return Heater.getRunState(); };
|
||||
int getRunStateEx() const; // extra support for cyclic thermostat mode
|
||||
const char* getRunStateStr() const;
|
||||
int getErrState() const;
|
||||
const char* getErrStateStr() const;
|
||||
const char* getErrStateStrEx() const;
|
||||
float getBattVoltage() const { return Heater.getVoltage_Supply(); };
|
||||
bool isThermostat() const { return Controller.isThermostat(); };
|
||||
float getTemperature_Desired() const { return float(Controller.getTemperature_Desired()); };
|
||||
float getTemperature_HeatExchg() const { return float(Heater.getTemperature_HeatExchg()); };
|
||||
float getTemperature_Min() const { return float(Controller.getTemperature_Min()); };
|
||||
float getTemperature_Max() const { return float(Controller.getTemperature_Max()); };
|
||||
float getPump_Fixed() const { return Heater.getPump_Fixed(); };
|
||||
float getPump_Actual() const { return Heater.getPump_Actual(); };
|
||||
float getPump_Min() const { return Controller.getPump_Min(); };
|
||||
float getPump_Max() const { return Controller.getPump_Max(); };
|
||||
float getFan_Actual() const { return Heater.getFan_Actual(); };
|
||||
short getFan_Min() const { return Controller.getFan_Min(); };
|
||||
short getFan_Max() const { return Controller.getFan_Max(); };
|
||||
float getFan_Voltage() const { return Heater.getFan_Voltage(); };
|
||||
int getFan_Sensor() const { return Controller.Controller.FanSensor; };
|
||||
float getGlowPlug_Power() const { return Heater.getGlowPlug_Current() * Heater.getGlowPlug_Voltage(); };
|
||||
float getGlow_Voltage() const { return Heater.getGlowPlug_Voltage(); };
|
||||
float getGlow_Current() const { return Heater.getGlowPlug_Current(); };
|
||||
float getSystemVoltage() const { return Controller.getSystemVoltage(); };
|
||||
int getGlow_Drive() const { return Controller.getGlowDrive(); };
|
||||
|
||||
// void setRefTime();
|
||||
void reportFrames(bool isOEM);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
|
@ -1,120 +0,0 @@
|
|||
/*
|
||||
* This file is part of the "bluetoothheater" distribution
|
||||
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
|
||||
*
|
||||
* Copyright (C) 2018 Ray Jones <ray@mrjones.id.au>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "SmartError.h"
|
||||
#include "TxManage.h"
|
||||
|
||||
CSmartError::CSmartError()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
void
|
||||
CSmartError::reset()
|
||||
{
|
||||
m_prevRunState = 0;
|
||||
m_Error = 0;
|
||||
m_bInhibit = false;
|
||||
}
|
||||
|
||||
// we use inhibit when we manually command the heater off during preheat
|
||||
// otherwise we'll register an ignition fail event
|
||||
void
|
||||
CSmartError::inhibit()
|
||||
{
|
||||
m_bInhibit = true;
|
||||
m_Error = 0;
|
||||
}
|
||||
|
||||
// accept a fresh heater frame
|
||||
// inpsect the advertised run state, tracking when and how it transitions out
|
||||
// of preheat especially.
|
||||
// abnormal transitions are registered and becoem our smart m_Error
|
||||
// In addition, the hetaer frame has the ErrState updated to track the
|
||||
// smart error, providing no heater error exists!
|
||||
void
|
||||
CSmartError::monitor(const CProtocol& heaterFrame)
|
||||
{
|
||||
bool bSilent = true;
|
||||
if(heaterFrame.verifyCRC(bSilent)) { // check but don't report dodgy frames to debug
|
||||
// only accept valid heater frames!
|
||||
monitor(heaterFrame.getRunState());
|
||||
}
|
||||
}
|
||||
|
||||
// test the new run state value, comparing to previous
|
||||
// detect abnormal transitions
|
||||
void
|
||||
CSmartError::monitor(unsigned char newRunState)
|
||||
{
|
||||
// check if moving away from heater Idle state (S0)
|
||||
// especially useful if an OEM controller exists
|
||||
if((m_prevRunState == 0) && newRunState) {
|
||||
// reset the smart error
|
||||
m_Error = 0;
|
||||
m_bInhibit = false;
|
||||
}
|
||||
|
||||
if(!m_bInhibit) {
|
||||
if(m_prevRunState == 2) { // preheat state (S2)
|
||||
if(newRunState == 4) {
|
||||
// transitioned from preheat to ignited
|
||||
// - all good!
|
||||
m_Error = 0;
|
||||
}
|
||||
else if(newRunState > 5) {
|
||||
// transitioned from preheat to post glow
|
||||
// - second ignition attempt failed, heater is shutting down
|
||||
m_Error = 11;
|
||||
}
|
||||
else if(newRunState == 3) {
|
||||
// transitioned from preheat to retry
|
||||
// - first ignition attempt failed, heater will retry
|
||||
m_Error = 12;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(m_prevRunState != newRunState) {
|
||||
// check for transition to startup
|
||||
// - force cancellation of an on request if we generated it
|
||||
if(newRunState >= 2) {
|
||||
TxManage.queueOnRequest(false); // ensure ON request is cancelled
|
||||
}
|
||||
// check for transition to shutdown
|
||||
// - force cancellation of an off request if we generated it
|
||||
if(newRunState >= 7 || newRunState == 0) {
|
||||
TxManage.queueOffRequest(false); // ensure OFF request is cancelled
|
||||
}
|
||||
}
|
||||
|
||||
m_prevRunState = newRunState;
|
||||
}
|
||||
|
||||
// return our smart error, if it exists, as the registered code
|
||||
unsigned char
|
||||
CSmartError::getError()
|
||||
{
|
||||
if(m_Error) {
|
||||
return m_Error;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -1,253 +0,0 @@
|
|||
/*
|
||||
* This file is part of the "bluetoothheater" distribution
|
||||
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
|
||||
*
|
||||
* Copyright (C) 2018 Ray Jones <ray@mrjones.id.au>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "TxManage.h"
|
||||
#include "../Utility/NVStorage.h"
|
||||
#include "../Protocol/helpers.h"
|
||||
|
||||
//#define DEBUG_THERMOSTAT
|
||||
|
||||
|
||||
extern void DebugReportFrame(const char* hdr, const CProtocol&, const char* ftr);
|
||||
|
||||
// CTxManage is used to send a data frame to the blue wire
|
||||
//
|
||||
// As the blue wire is bidirectional, we need to only allow our transmit data
|
||||
// to reach the blue wire when we actually want to send data.
|
||||
// At all other times we are listening to the blue wire, receiving any async data
|
||||
//
|
||||
// This requires external circuitry to toggle the Tx/Rx modes.
|
||||
// A "Tx Gating" signal is used.
|
||||
// when high, transmit data is sent to the blue wire
|
||||
// when low, transmit data is blocked (Hi-Z)
|
||||
//
|
||||
// Ideally the circuit also prevents feeding back our own Tx data into the Rx pin
|
||||
// but the main software loop handles this situation by only accepting Rx data when expected.
|
||||
//
|
||||
// Timing diagram
|
||||
// ____________________
|
||||
// Tx Gate ____________________| |___________________________
|
||||
// _____________________________________________________________________
|
||||
// Tx Data |||||||||||||||
|
||||
|
||||
CTxManage::CTxManage(int TxGatePin, HardwareSerial& serial) :
|
||||
m_BlueWireSerial(serial),
|
||||
m_TxFrame(CProtocol::CtrlMode)
|
||||
{
|
||||
m_bOnReq = false;
|
||||
m_bOffReq = false;
|
||||
m_bTxPending = false;
|
||||
m_nStartTime = 0;
|
||||
m_nTxGatePin = TxGatePin;
|
||||
_rawCommand = 0;
|
||||
}
|
||||
|
||||
void CTxManage::begin()
|
||||
{
|
||||
pinMode(m_nTxGatePin, OUTPUT);
|
||||
digitalWrite(m_nTxGatePin, LOW); // default to receive mode
|
||||
}
|
||||
|
||||
void
|
||||
CTxManage::queueOnRequest(bool set)
|
||||
{
|
||||
m_bOnReq = set; // allow cancellation via heater response frame decode
|
||||
m_bOffReq = false;
|
||||
}
|
||||
|
||||
void
|
||||
CTxManage::queueOffRequest(bool set)
|
||||
{
|
||||
m_bOffReq = set; // allow cancellation via heater response frame decode
|
||||
m_bOnReq = false;
|
||||
}
|
||||
|
||||
void
|
||||
CTxManage::queueRawCommand(unsigned char val)
|
||||
{
|
||||
_rawCommand = val;
|
||||
}
|
||||
|
||||
void
|
||||
CTxManage::PrepareFrame(const CProtocol& basisFrame, bool isBTCmaster)
|
||||
{
|
||||
// copy supplied frame, typically this will be the values an OEM controller delivered
|
||||
// which means we parrot that data by default.
|
||||
// When parroting, we must especially avoid ping ponging "set temperature"!
|
||||
// Otherwise we are supplied with the default params for standalone mode, which we
|
||||
// then instil the NV parameters
|
||||
m_TxFrame = basisFrame;
|
||||
|
||||
// ALWAYS install on/off commands if required
|
||||
#ifndef PROTOCOL_INVESTIGATION
|
||||
m_TxFrame.resetCommand(); // no command upon blue wire initially, unless a request is pending
|
||||
if(_rawCommand) {
|
||||
m_TxFrame.setRawCommand(_rawCommand);
|
||||
_rawCommand = 0;
|
||||
}
|
||||
else {
|
||||
if(m_bOnReq) {
|
||||
// m_bOnReq = false; // requires cancel via queueOnRequest(false)
|
||||
m_TxFrame.onCommand();
|
||||
}
|
||||
if(m_bOffReq) {
|
||||
// m_bOffReq = false; // requires cancel via queueOffRequest(false)
|
||||
m_TxFrame.offCommand();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// 0x78 prevents the controller showing bum information when we parrot the OEM controller
|
||||
// heater is happy either way, the OEM controller has set the max/min stuff already
|
||||
if(isBTCmaster) {
|
||||
m_TxFrame.setActiveMode(); // this allows heater to save the tuning params to EEPROM
|
||||
m_TxFrame.setFan_Min(NVstore.getFmin());
|
||||
m_TxFrame.setFan_Max(NVstore.getFmax());
|
||||
m_TxFrame.setPump_Min(NVstore.getPmin());
|
||||
m_TxFrame.setPump_Max(NVstore.getPmax());
|
||||
|
||||
float tActual = getTemperatureSensor();
|
||||
uint8_t u8Temp = (uint8_t)(tActual);
|
||||
m_TxFrame.setTemperature_Actual(u8Temp); // use current temp, for now
|
||||
m_TxFrame.setTemperature_Desired(NVstore.getDesiredTemperature());
|
||||
|
||||
if(NVstore.getThermostatMode()) {
|
||||
uint8_t ThermoMode = NVstore.getThermostatMethodMode(); // get the METHOD of thermostat control
|
||||
float Window = NVstore.getThermostatMethodWindow();
|
||||
float tCurrent = getTemperatureSensor();
|
||||
float tDesired = float(NVstore.getDesiredTemperature());
|
||||
float tDelta = tCurrent - tDesired;
|
||||
float fTemp;
|
||||
#ifdef DEBUG_THERMOSTAT
|
||||
DebugPort.print("Window = "); DebugPort.print(Window); DebugPort.print(" tCurrent = "); DebugPort.print(tCurrent); DebugPort.print(" tDesired = "); DebugPort.print(tDesired); DebugPort.print(" tDelta = "); DebugPort.println(tDelta);
|
||||
#endif
|
||||
Window /= 2;
|
||||
switch(ThermoMode) {
|
||||
|
||||
case 0: // conventional heater controlled thermostat mode
|
||||
case 3: // conventional heater controlled thermostat mode
|
||||
m_TxFrame.setThermostatModeProtocol(1); // using heater thermostat control
|
||||
u8Temp = (uint8_t)(tActual + 0.5);
|
||||
m_TxFrame.setTemperature_Actual(u8Temp);
|
||||
#ifdef DEBUG_THERMOSTAT
|
||||
DebugPort.print("Conventional thermostat mode: tActual = "); DebugPort.println(u8Temp);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 1: // heater controlled thermostat mode - BUT actual temp is tweaked via a changed window
|
||||
m_TxFrame.setThermostatModeProtocol(1); // using heater thermostat control
|
||||
u8Temp = (uint8_t)(tActual + 0.5); // use rounded actual unless within window
|
||||
if(fabs(tDelta) < Window) {
|
||||
// hold at desired if inside window
|
||||
u8Temp = NVstore.getDesiredTemperature();
|
||||
}
|
||||
else if(fabs(tDelta) <= 1.0) {
|
||||
// force outside if delta is <= 1 but greater than window
|
||||
u8Temp = NVstore.getDesiredTemperature() + ((tDelta > 0) ? 1 : -1);
|
||||
}
|
||||
m_TxFrame.setTemperature_Actual(u8Temp);
|
||||
#ifdef DEBUG_THERMOSTAT
|
||||
DebugPort.print("Heater controlled windowed thermostat mode: tActual = "); DebugPort.println(u8Temp);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 2: // BTC controlled thermostat mode
|
||||
// map linear deviation within thermostat window to a Hz value,
|
||||
// Hz mode however uses the desired temperature field, somewhere between 8 - 35 for min/max
|
||||
// so create a desired "temp" according the the current hystersis
|
||||
tDelta /= Window; // convert tDelta to fraction of window (CAUTION - may be > +-1 !)
|
||||
#ifdef DEBUG_THERMOSTAT
|
||||
DebugPort.print("Linear window thermostat mode: Fraction = "); DebugPort.print(tDelta);
|
||||
#endif
|
||||
fTemp = (m_TxFrame.getTemperature_Max() + m_TxFrame.getTemperature_Min()) * 0.5; // midpoint - tDelta = 0 hinges here
|
||||
tDelta *= (m_TxFrame.getTemperature_Max() - fTemp); // linear offset from setpoint
|
||||
fTemp -= tDelta; // lower Hz when over temp, higher Hz when under!
|
||||
// bounds limit - recall original tDelta was NOT managed prior!
|
||||
LOWERLIMIT(fTemp, m_TxFrame.getTemperature_Min());
|
||||
UPPERLIMIT(fTemp, m_TxFrame.getTemperature_Max());
|
||||
// apply modifed desired temperature (works in conjunction with thermostatmode = 0!)
|
||||
u8Temp = (uint8_t)(fTemp + 0.5);
|
||||
m_TxFrame.setTemperature_Desired(u8Temp);
|
||||
m_TxFrame.setThermostatModeProtocol(0); // direct heater to use Hz Mode
|
||||
m_TxFrame.setTemperature_Actual(0); // must force actual to 0 for Hz mode
|
||||
#ifdef DEBUG_THERMOSTAT
|
||||
DebugPort.print(" tDesired (pseudo Hz demand) = "); DebugPort.println(u8Temp);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
m_TxFrame.setThermostatModeProtocol(0); // not using any form of thermostat control
|
||||
m_TxFrame.setTemperature_Actual(0); // must force actual to 0 for Hz mode
|
||||
}
|
||||
// m_TxFrame.setThermostatMode(NVstore.getThermostatMode());
|
||||
|
||||
m_TxFrame.Controller.OperatingVoltage = NVstore.getSysVoltage();
|
||||
m_TxFrame.Controller.FanSensor = NVstore.getFanSensor();
|
||||
m_TxFrame.Controller.GlowDrive = NVstore.getGlowDrive();
|
||||
}
|
||||
else {
|
||||
m_TxFrame.setPassiveMode(); // this prevents the tuning parameters being saved by heater
|
||||
}
|
||||
|
||||
// ensure CRC valid
|
||||
m_TxFrame.setCRC();
|
||||
}
|
||||
|
||||
void
|
||||
CTxManage::Start(unsigned long timenow)
|
||||
{
|
||||
if(timenow == 0) // avoid a black hole if millis() has wrapped to zero
|
||||
timenow++;
|
||||
|
||||
m_nStartTime = timenow;
|
||||
m_bTxPending = true;
|
||||
}
|
||||
|
||||
// generate a Tx Gate, then send the TxFrame to the Blue wire
|
||||
// Note the serial data is ISR driven, we need to hold off
|
||||
// for a while to let teh buffewred dat clear before closing the Tx Gate.
|
||||
bool
|
||||
CTxManage::CheckTx(unsigned long timenow)
|
||||
{
|
||||
if(m_nStartTime) {
|
||||
|
||||
long diff = timenow - m_nStartTime;
|
||||
|
||||
if(diff > m_nStartDelay) {
|
||||
// begin front porch of Tx gating pulse
|
||||
digitalWrite(m_nTxGatePin, HIGH);
|
||||
}
|
||||
if(m_bTxPending && (diff > (m_nStartDelay + m_nFrontPorch))) {
|
||||
// front porch expired, perform serial transmission
|
||||
// Tx gate remains held high
|
||||
m_bTxPending = false;
|
||||
m_BlueWireSerial.write(m_TxFrame.Data, 24); // write native binary values
|
||||
}
|
||||
if(diff > (m_nStartDelay + m_nFrameTime)) {
|
||||
// conclude Tx gating after (emperical) delay
|
||||
digitalWrite(m_nTxGatePin, LOW);
|
||||
m_nStartTime = 0; // cancel, we are DONE
|
||||
}
|
||||
}
|
||||
return m_nStartTime == 0; // returns true when done
|
||||
}
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
/*
|
||||
* This file is part of the "bluetoothheater" distribution
|
||||
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
|
||||
*
|
||||
* Copyright (C) 2018 Ray Jones <ray@mrjones.id.au>
|
||||
* Copyright (C) 2018 James Clark
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Protocol.h"
|
||||
|
||||
|
||||
extern void ToggleOnOff();
|
||||
extern void requestOn();
|
||||
extern void requestOff();
|
||||
extern bool reqTempDelta(int delta);
|
||||
extern bool reqTemp(unsigned char newTemp);
|
||||
extern bool reqThermoToggle();
|
||||
extern bool setThermostatMode(unsigned char);
|
||||
extern bool getThermostatModeActive(); // OEM: actual mode from blue wire, BTC: or our NV
|
||||
extern void reqPumpPrime(bool on);
|
||||
float getTemperatureDesired(); // OEM: the advertised value, BTC our setpoint
|
||||
extern float getTemperatureSensor();
|
||||
extern int getSetTemp();
|
||||
extern void setPumpMin(float);
|
||||
extern void setPumpMax(float);
|
||||
extern void setFanMin(short);
|
||||
extern void setFanMax(short);
|
||||
extern void setFanSensor(unsigned char cVal);
|
||||
extern void setDateTime(const char* newTime);
|
||||
extern void setDate(const char* newTime);
|
||||
extern void setTime(const char* newTime);
|
||||
extern void setGlowDrive(unsigned char val);
|
||||
extern void saveNV();
|
||||
extern void setSystemVoltage(float val);
|
||||
extern const CProtocolPackage& getHeaterInfo();
|
||||
extern void interpretJsonCommand(char* pLine);
|
||||
extern void resetWebModerator();
|
||||
extern void resetJSONmoderator();
|
||||
extern const char* getBlueWireStatStr();
|
||||
extern bool hasOEMcontroller();
|
||||
extern bool hasOEMLCDcontroller();
|
||||
extern int getBlueWireStat();
|
||||
extern int getSmartError();
|
||||
extern bool isCyclicActive();
|
||||
extern float getVersion();
|
||||
const char* getVersionStr();
|
||||
extern const char* getVersionDate();
|
||||
extern int getBoardRevision();
|
||||
extern void setupGPIO();
|
||||
extern void setGPIO(int channel, bool state);
|
||||
extern bool getGPIO(int channel);
|
||||
|
||||
|
||||
|
||||
#define LOWERLIMIT(A, B) if((A) < (B)) (A) = (B)
|
||||
#define UPPERLIMIT(A, B) if((A) > (B)) (A) = (B)
|
||||
#define ROLLUPPERLIMIT(A, B, C) if((A) > (B)) (A) = (C)
|
||||
#define ROLLLOWERLIMIT(A, B, C) if((A) < (B)) (A) = (C)
|
|
@ -1,332 +0,0 @@
|
|||
/*
|
||||
* This file is part of the "bluetoothheater" distribution
|
||||
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
|
||||
*
|
||||
* Copyright (C) 2018 Ray Jones <ray@mrjones.id.au>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "BTC_JSON.h"
|
||||
#include "DebugPort.h"
|
||||
#include "../Protocol/helpers.h"
|
||||
#include "NVstorage.h"
|
||||
#include "../RTC/BTCDateTime.h"
|
||||
#include "../RTC/Timers.h"
|
||||
#include "../RTC/TimerManager.h"
|
||||
#include "../Bluetooth/BluetoothAbstract.h"
|
||||
#include "../WiFi/BTCWebServer.h"
|
||||
#include "../cfg/BTCConfig.h"
|
||||
|
||||
|
||||
char defaultJSONstr[64];
|
||||
CModerator JSONmoderator;
|
||||
CTimerModerator TimerModerator;
|
||||
int timerConflict = 0;
|
||||
|
||||
void validateTimer(int ID);
|
||||
|
||||
void interpretJsonCommand(char* pLine)
|
||||
{
|
||||
if(strlen(pLine) == 0)
|
||||
return;
|
||||
|
||||
DebugPort.print("JSON parse... "); DebugPort.print(pLine);
|
||||
/* for(int i=0; i<strlen(pLine); i++) {
|
||||
char msg[8];
|
||||
sprintf(msg, "%02X ", pLine[i]);
|
||||
DebugPort.print(msg);
|
||||
}*/
|
||||
|
||||
StaticJsonBuffer<512> jsonBuffer; // create a JSON buffer on the heap
|
||||
JsonObject& obj = jsonBuffer.parseObject(pLine);
|
||||
if(!obj.success()) {
|
||||
DebugPort.println(" FAILED");
|
||||
return;
|
||||
}
|
||||
DebugPort.println(" OK");
|
||||
|
||||
JsonObject::iterator it;
|
||||
for(it = obj.begin(); it != obj.end(); ++it) {
|
||||
|
||||
if(strcmp("TempDesired", it->key) == 0) {
|
||||
if(!reqTemp(it->value.as<unsigned char>())) { // this request is blocked if OEM controller active
|
||||
JSONmoderator.reset("TempDesired");
|
||||
}
|
||||
}
|
||||
else if(strcmp("RunState", it->key) == 0) {
|
||||
if(it->value.as<unsigned char>()) {
|
||||
requestOn();
|
||||
}
|
||||
else {
|
||||
requestOff();
|
||||
}
|
||||
}
|
||||
else if(strcmp("PumpMin", it->key) == 0) {
|
||||
setPumpMin(it->value.as<float>());
|
||||
}
|
||||
else if(strcmp("PumpMax", it->key) == 0) {
|
||||
setPumpMax(it->value.as<float>());
|
||||
}
|
||||
else if(strcmp("FanMin", it->key) == 0) {
|
||||
setFanMin(it->value.as<short>());
|
||||
}
|
||||
else if(strcmp("FanMax", it->key) == 0) {
|
||||
setFanMax(it->value.as<short>());
|
||||
}
|
||||
else if(strcmp("ThermostatOvertemp", it->key) == 0) {
|
||||
sCyclicThermostat cyclic = NVstore.getCyclicMode();
|
||||
cyclic.Stop = it->value.as<char>();
|
||||
NVstore.setCyclicMode(cyclic);
|
||||
}
|
||||
else if(strcmp("ThermostatUndertemp", it->key) == 0) {
|
||||
sCyclicThermostat cyclic = NVstore.getCyclicMode();
|
||||
cyclic.Start = it->value.as<char>();
|
||||
NVstore.setCyclicMode(cyclic);
|
||||
}
|
||||
else if(strcmp("ThermostatMethod", it->key) == 0) {
|
||||
NVstore.setThermostatMethodMode(it->value.as<unsigned char>());
|
||||
}
|
||||
else if(strcmp("ThermostatWindow", it->key) == 0) {
|
||||
NVstore.setThermostatMethodWindow(it->value.as<float>());
|
||||
}
|
||||
else if(strcmp("Thermostat", it->key) == 0) {
|
||||
if(!setThermostatMode(it->value.as<unsigned char>())) { // this request is blocked if OEM controller active
|
||||
JSONmoderator.reset("ThermoStat");
|
||||
}
|
||||
}
|
||||
else if(strcmp("NVsave", it->key) == 0) {
|
||||
if(it->value.as<int>() == 8861)
|
||||
saveNV();
|
||||
}
|
||||
else if(strcmp("DateTime", it->key) == 0) {
|
||||
setDateTime(it->value.as<const char*>());
|
||||
}
|
||||
else if(strcmp("Date", it->key) == 0) {
|
||||
setDate(it->value.as<const char*>());
|
||||
}
|
||||
else if(strcmp("Time", it->key) == 0) {
|
||||
setTime(it->value.as<const char*>());
|
||||
}
|
||||
else if(strcmp("PumpPrime", it->key) == 0) {
|
||||
reqPumpPrime(it->value.as<unsigned char>());
|
||||
}
|
||||
else if(strcmp("Refresh", it->key) == 0) {
|
||||
resetJSONmoderator();
|
||||
}
|
||||
else if(strcmp("SystemVoltage", it->key) == 0) {
|
||||
setSystemVoltage(it->value.as<float>());
|
||||
}
|
||||
else if(strcmp("TimerDays", it->key) == 0) {
|
||||
// value encoded as "ID Days,Days"
|
||||
decodeJSONTimerDays(it->value.as<const char*>());
|
||||
}
|
||||
else if(strcmp("TimerStart", it->key) == 0) {
|
||||
// value encoded as "ID HH:MM"
|
||||
decodeJSONTimerTime(0, it->value.as<const char*>());
|
||||
}
|
||||
else if(strcmp("TimerStop", it->key) == 0) {
|
||||
// value encoded as "ID HH:MM"
|
||||
decodeJSONTimerTime(1, it->value.as<const char*>());
|
||||
}
|
||||
else if(strcmp("TimerRepeat", it->key) == 0) {
|
||||
// value encoded as "ID val"
|
||||
decodeJSONTimerNumeric(0, it->value.as<const char*>());
|
||||
}
|
||||
else if(strcmp("TimerTemp", it->key) == 0) {
|
||||
decodeJSONTimerNumeric(1, it->value.as<const char*>());
|
||||
}
|
||||
else if(strcmp("TimerConflict", it->key) == 0) {
|
||||
validateTimer(it->value.as<int>());
|
||||
}
|
||||
else if(strcmp("TimerRefresh", it->key) == 0) {
|
||||
TimerModerator.reset();
|
||||
}
|
||||
else if(strcmp("FanSensor", it->key) == 0) {
|
||||
setFanSensor(it->value.as<unsigned char>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void validateTimer(int ID)
|
||||
{
|
||||
ID--; // supplied as +1
|
||||
if(!(ID >= 0 && ID < 14))
|
||||
return;
|
||||
|
||||
timerConflict = CTimerManager::conflictTest(ID); // check targeted timer against other timers
|
||||
|
||||
TimerModerator.reset(ID); // ensure we update client with our (real) version of the selected timer
|
||||
}
|
||||
|
||||
bool makeJSONString(CModerator& moderator, char* opStr, int len)
|
||||
{
|
||||
StaticJsonBuffer<800> jsonBuffer; // create a JSON buffer on the stack
|
||||
JsonObject& root = jsonBuffer.createObject(); // create object to add JSON commands to
|
||||
|
||||
bool bSend = false; // reset should send flag
|
||||
|
||||
float tidyTemp = getTemperatureSensor();
|
||||
tidyTemp = int(tidyTemp * 10) * 0.1f; // round to 0.1 resolution
|
||||
if(tidyTemp > -80) {
|
||||
bSend |= moderator.addJson("TempCurrent", tidyTemp, root);
|
||||
}
|
||||
bSend |= moderator.addJson("TempDesired", getTemperatureDesired(), root);
|
||||
bSend |= moderator.addJson("TempMin", getHeaterInfo().getTemperature_Min(), root);
|
||||
bSend |= moderator.addJson("TempMax", getHeaterInfo().getTemperature_Max(), root);
|
||||
bSend |= moderator.addJson("TempBody", getHeaterInfo().getTemperature_HeatExchg(), root);
|
||||
// bSend |= moderator.addJson("RunState", getHeaterInfo().getRunState(), root);
|
||||
bSend |= moderator.addJson("RunState", getHeaterInfo().getRunStateEx(), root);
|
||||
bSend |= moderator.addJson("RunString", getHeaterInfo().getRunStateStr(), root); // verbose it up!
|
||||
bSend |= moderator.addJson("ErrorState", getHeaterInfo().getErrState(), root );
|
||||
bSend |= moderator.addJson("ErrorString", getHeaterInfo().getErrStateStrEx(), root); // verbose it up!
|
||||
bSend |= moderator.addJson("Thermostat", getThermostatModeActive(), root );
|
||||
bSend |= moderator.addJson("PumpFixed", getHeaterInfo().getPump_Fixed(), root );
|
||||
bSend |= moderator.addJson("PumpMin", getHeaterInfo().getPump_Min(), root );
|
||||
bSend |= moderator.addJson("PumpMax", getHeaterInfo().getPump_Max(), root );
|
||||
bSend |= moderator.addJson("PumpActual", getHeaterInfo().getPump_Actual(), root );
|
||||
bSend |= moderator.addJson("FanMin", getHeaterInfo().getFan_Min(), root );
|
||||
bSend |= moderator.addJson("FanMax", getHeaterInfo().getFan_Max(), root );
|
||||
bSend |= moderator.addJson("FanRPM", getHeaterInfo().getFan_Actual(), root );
|
||||
bSend |= moderator.addJson("FanVoltage", getHeaterInfo().getFan_Voltage(), root );
|
||||
bSend |= moderator.addJson("FanSensor", getHeaterInfo().getFan_Sensor(), root );
|
||||
bSend |= moderator.addJson("InputVoltage", getHeaterInfo().getBattVoltage(), root );
|
||||
bSend |= moderator.addJson("SystemVoltage", getHeaterInfo().getSystemVoltage(), root );
|
||||
bSend |= moderator.addJson("GlowVoltage", getHeaterInfo().getGlow_Voltage(), root );
|
||||
bSend |= moderator.addJson("GlowCurrent", getHeaterInfo().getGlow_Current(), root );
|
||||
bSend |= moderator.addJson("BluewireStat", getBlueWireStatStr(), root );
|
||||
bSend |= moderator.addJson("TempMode", NVstore.getDegFMode(), root);
|
||||
|
||||
if(bSend) {
|
||||
root.printTo(opStr, len);
|
||||
}
|
||||
|
||||
return bSend;
|
||||
}
|
||||
|
||||
bool makeJSONStringEx(CModerator& moderator, char* opStr, int len)
|
||||
{
|
||||
StaticJsonBuffer<800> jsonBuffer; // create a JSON buffer on the stack
|
||||
JsonObject& root = jsonBuffer.createObject(); // create object to add JSON commands to
|
||||
|
||||
bool bSend = false; // reset should send flag
|
||||
|
||||
bSend |= moderator.addJson("ThermostatMethod", NVstore.getThermostatMethodMode(), root);
|
||||
bSend |= moderator.addJson("ThermostatWindow", NVstore.getThermostatMethodWindow(), root);
|
||||
bSend |= moderator.addJson("ThermostatOvertemp", NVstore.getCyclicMode().Stop, root);
|
||||
bSend |= moderator.addJson("ThermostatUndertemp", NVstore.getCyclicMode().Start, root);
|
||||
|
||||
if(bSend) {
|
||||
root.printTo(opStr, len);
|
||||
}
|
||||
|
||||
return bSend;
|
||||
}
|
||||
|
||||
// the way the JSON timer strings are crafted, we have to iterate over each timer's parameters
|
||||
// individually, the JSON name is always the same for each timer, the payload IDs the specific
|
||||
// timer
|
||||
// Only timer parameters that have changed will be sent, after reset the typical string will be
|
||||
// {"TimerStart":XX:XX,"TimerStop":XX:XX,"TimerDays":XX,"TimerRepeat":X}
|
||||
bool makeJSONTimerString(int channel, char* opStr, int len)
|
||||
{
|
||||
StaticJsonBuffer<800> jsonBuffer; // create a JSON buffer on the stack
|
||||
JsonObject& root = jsonBuffer.createObject(); // create object to add JSON commands to
|
||||
|
||||
bool bSend = false; // reset should send flag
|
||||
|
||||
sTimer timerInfo;
|
||||
NVstore.getTimerInfo(channel, timerInfo);
|
||||
bSend |= TimerModerator.addJson(channel, timerInfo, root );
|
||||
|
||||
if(bSend) {
|
||||
root.printTo(opStr, len);
|
||||
}
|
||||
|
||||
return bSend;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void updateJSONclients(bool report)
|
||||
{
|
||||
// update general parameters
|
||||
char jsonStr[800];
|
||||
{
|
||||
if(makeJSONString(JSONmoderator, jsonStr, sizeof(jsonStr))) {
|
||||
if (report) {
|
||||
DebugPort.print("JSON send: "); DebugPort.println(jsonStr);
|
||||
}
|
||||
sendWebServerString( jsonStr );
|
||||
getBluetoothClient().send( jsonStr );
|
||||
}
|
||||
}
|
||||
// update extended params
|
||||
{
|
||||
if(makeJSONStringEx(JSONmoderator, jsonStr, sizeof(jsonStr))) {
|
||||
if (report) {
|
||||
DebugPort.print("JSON send: "); DebugPort.println(jsonStr);
|
||||
}
|
||||
sendWebServerString( jsonStr );
|
||||
getBluetoothClient().send( jsonStr );
|
||||
}
|
||||
}
|
||||
// update timer parameters
|
||||
bool bNewTimerInfo = false;
|
||||
for(int tmr=0; tmr<14; tmr++)
|
||||
{
|
||||
unsigned long tStart = millis();
|
||||
if(makeJSONTimerString(tmr, jsonStr, sizeof(jsonStr))) {
|
||||
unsigned long tJSON = millis() - tStart;
|
||||
if (report) {
|
||||
DebugPort.print("JSON send: "); DebugPort.println(jsonStr);
|
||||
}
|
||||
tStart = millis();
|
||||
sendWebServerString( jsonStr );
|
||||
unsigned long tWF = millis() - tStart;
|
||||
tStart = millis();
|
||||
getBluetoothClient().send( jsonStr );
|
||||
unsigned long tBT = millis() - tStart;
|
||||
bNewTimerInfo = true;
|
||||
DebugPort.print("JSON times : "); DebugPort.print(tJSON); DebugPort.print(",");DebugPort.print(tBT); DebugPort.print(",");DebugPort.println(tWF);
|
||||
}
|
||||
}
|
||||
// request timer refesh upon clients
|
||||
if(bNewTimerInfo) {
|
||||
StaticJsonBuffer<800> jsonBuffer; // create a JSON buffer on the stack
|
||||
JsonObject& root = jsonBuffer.createObject(); // create object to add JSON commands to
|
||||
|
||||
if(timerConflict) {
|
||||
root.set("TimerConflict", timerConflict);
|
||||
timerConflict = 0;
|
||||
}
|
||||
root.set("TimerRefresh", 1);
|
||||
root.printTo(jsonStr, 800);
|
||||
|
||||
DebugPort.print("JSON send: "); DebugPort.println(jsonStr);
|
||||
sendWebServerString( jsonStr );
|
||||
getBluetoothClient().send( jsonStr );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void resetJSONmoderator()
|
||||
{
|
||||
JSONmoderator.reset();
|
||||
TimerModerator.reset();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,374 +0,0 @@
|
|||
/*
|
||||
* This file is part of the "bluetoothheater" distribution
|
||||
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
|
||||
*
|
||||
* Copyright (C) 2018 Ray Jones <ray@mrjones.id.au>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "GPIO.h"
|
||||
#include "../Protocol/helpers.h"
|
||||
#include <driver/adc.h>
|
||||
#include "DebugPort.h"
|
||||
|
||||
const int BREATHINTERVAL = 45;
|
||||
const int FADEAMOUNT = 3;
|
||||
const int FLASHPERIOD = 2000;
|
||||
const int ONFLASHINTERVAL = 50;
|
||||
|
||||
CGPIOin::CGPIOin()
|
||||
{
|
||||
_Mode = GPIOinNone;
|
||||
_lastKey = 0;
|
||||
}
|
||||
|
||||
void
|
||||
CGPIOin::begin(int pin1, int pin2, GPIOinModes mode, int activeState)
|
||||
{
|
||||
_Debounce.addPin(pin1);
|
||||
_Debounce.addPin(pin2);
|
||||
_Debounce.setActiveState(activeState);
|
||||
|
||||
setMode(mode);
|
||||
}
|
||||
|
||||
uint8_t
|
||||
CGPIOin::getState(int channel)
|
||||
{
|
||||
int mask = 0x01 << (channel & 0x01);
|
||||
return (_Debounce.getState() & mask) != 0;
|
||||
}
|
||||
|
||||
void
|
||||
CGPIOin::manage()
|
||||
{
|
||||
switch (_Mode) {
|
||||
case GPIOinNone:
|
||||
break;
|
||||
case GPIOinOn1Off2:
|
||||
_doOn1Off2();
|
||||
break;
|
||||
case GPIOinOnHold1:
|
||||
_doOnHold1();
|
||||
break;
|
||||
case GPIOinOn1Off1:
|
||||
_doOn1Off1();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CGPIOin::_doOn1Off2()
|
||||
{
|
||||
uint8_t newKey = _Debounce.manage();
|
||||
// determine edge events
|
||||
uint8_t keyChange = newKey ^ _lastKey;
|
||||
_lastKey = newKey;
|
||||
|
||||
if(keyChange) {
|
||||
if(newKey & 0x01) {
|
||||
requestOn();
|
||||
}
|
||||
if(newKey & 0x02) {
|
||||
requestOff();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// mode where heater runs if input 1 is shorted
|
||||
// stops when open
|
||||
void
|
||||
CGPIOin::_doOnHold1()
|
||||
{
|
||||
uint8_t newKey = _Debounce.manage();
|
||||
// determine edge events
|
||||
uint8_t keyChange = newKey ^ _lastKey;
|
||||
_lastKey = newKey;
|
||||
|
||||
if(keyChange) {
|
||||
if(newKey & 0x01) {
|
||||
requestOn();
|
||||
}
|
||||
else {
|
||||
requestOff();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// mode where heater runs if input 1 is shorted
|
||||
// stops when open
|
||||
void
|
||||
CGPIOin::_doOn1Off1()
|
||||
{
|
||||
uint8_t newKey = _Debounce.manage();
|
||||
// determine edge events
|
||||
uint8_t keyChange = newKey ^ _lastKey;
|
||||
_lastKey = newKey;
|
||||
|
||||
if(keyChange) {
|
||||
if(newKey & 0x01) {
|
||||
if(getHeaterInfo().getRunStateEx())
|
||||
requestOff();
|
||||
else
|
||||
requestOn();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
CGPIOout::CGPIOout()
|
||||
{
|
||||
_Mode = GPIOoutNone;
|
||||
_pins[0] = 0;
|
||||
_pins[1] = 0;
|
||||
_breatheDelay = 0;
|
||||
_statusState = 0;
|
||||
_statusDelay = 0;
|
||||
_userState = 0;
|
||||
_prevState = -1;
|
||||
}
|
||||
|
||||
void
|
||||
CGPIOout::begin(int pin1, int pin2, GPIOoutModes mode)
|
||||
{
|
||||
_pins[0] = pin1;
|
||||
_pins[1] = pin2;
|
||||
if(pin1) {
|
||||
pinMode(pin1, OUTPUT); // GPIO output pin #1
|
||||
digitalWrite(pin1, LOW);
|
||||
ledcSetup(0, 500, 8); // create PWM channel for GPIO1: 500Hz, 8 bits
|
||||
}
|
||||
if(pin2) {
|
||||
pinMode(pin2, OUTPUT); // GPIO output pin #2
|
||||
digitalWrite(pin2, LOW);
|
||||
ledcSetup(1, 500, 8); // create PWM channel for GPIO2: 500Hz, 8 bits
|
||||
}
|
||||
|
||||
setMode(mode);
|
||||
}
|
||||
|
||||
void
|
||||
CGPIOout::setMode(GPIOoutModes mode)
|
||||
{
|
||||
_Mode = mode;
|
||||
_prevState = -1;
|
||||
ledcDetachPin(_pins[0]); // ensure PWM detached from IO line
|
||||
ledcDetachPin(_pins[1]); // ensure PWM detached from IO line
|
||||
};
|
||||
|
||||
void
|
||||
CGPIOout::manage()
|
||||
{
|
||||
switch (_Mode) {
|
||||
case GPIOoutNone: break;
|
||||
case GPIOoutStatus: _doStatus(); break;
|
||||
case GPIOoutUser: _doUser(); break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CGPIOout::_doStatus()
|
||||
{
|
||||
if(_pins[0] == 0)
|
||||
return;
|
||||
|
||||
// DebugPort.println("GPIOout::_doStatus()");
|
||||
int runstate = getHeaterInfo().getRunStateEx();
|
||||
int statusMode = 0;
|
||||
switch(runstate) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 9:
|
||||
// starting modes
|
||||
statusMode = 1;
|
||||
break;
|
||||
case 5:
|
||||
// run mode
|
||||
statusMode = 2;
|
||||
break;
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
case 11:
|
||||
case 12:
|
||||
// cooldown modes
|
||||
statusMode = 3;
|
||||
break;
|
||||
case 10:
|
||||
// suspend mode
|
||||
statusMode = 4;
|
||||
break;
|
||||
}
|
||||
|
||||
// change of mode typically requires changing from simple digital out
|
||||
// to PWM or vice versa
|
||||
if(_prevState != statusMode) {
|
||||
_prevState = statusMode;
|
||||
_statusState = 0;
|
||||
_statusDelay = millis() + BREATHINTERVAL;
|
||||
switch(statusMode) {
|
||||
case 0:
|
||||
ledcDetachPin(_pins[0]); // detach PWM from IO line
|
||||
digitalWrite(_pins[0], LOW);
|
||||
break;
|
||||
case 1:
|
||||
ledcAttachPin(_pins[0], 0); // attach PWM to GPIO line
|
||||
ledcWrite(0, _statusState);
|
||||
_breatheDelay = millis() + BREATHINTERVAL;
|
||||
break;
|
||||
case 2:
|
||||
ledcDetachPin(_pins[0]); // detach PWM from IO line
|
||||
digitalWrite(_pins[0], HIGH);
|
||||
break;
|
||||
case 3:
|
||||
ledcAttachPin(_pins[0], 0); // attach PWM to GPIO line
|
||||
_statusState = 255;
|
||||
ledcWrite(0, _statusState);
|
||||
_breatheDelay = millis() + BREATHINTERVAL;
|
||||
break;
|
||||
case 4:
|
||||
ledcDetachPin(_pins[0]); // detach PWM from IO line
|
||||
_breatheDelay += (FLASHPERIOD - ONFLASHINTERVAL); // extended off
|
||||
digitalWrite(_pins[0], LOW);
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch(statusMode) {
|
||||
case 1: _doStartMode(); break;
|
||||
case 3: _doStopMode(); break;
|
||||
case 4: _doSuspendMode(); break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CGPIOout::_doUser()
|
||||
{
|
||||
// DebugPort.println("GPIOout::_doUser()");
|
||||
if(_pins[0]) {
|
||||
digitalWrite(_pins[0], (_userState & 0x01) ? HIGH : LOW);
|
||||
}
|
||||
if(_pins[1]) {
|
||||
digitalWrite(_pins[1], (_userState & 0x02) ? HIGH : LOW);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CGPIOout::_doStartMode() // breath up PWM
|
||||
{
|
||||
long tDelta = millis() - _breatheDelay;
|
||||
if(tDelta >= 0) {
|
||||
_breatheDelay += BREATHINTERVAL;
|
||||
int expo = ((_statusState >> 5) + 1);
|
||||
_statusState += expo;
|
||||
_statusState &= 0xff;
|
||||
ledcWrite(0, _statusState);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CGPIOout::_doStopMode() // breath down PWM
|
||||
{
|
||||
long tDelta = millis() - _breatheDelay;
|
||||
if(tDelta >= 0) {
|
||||
_breatheDelay += BREATHINTERVAL;
|
||||
int expo = ((_statusState >> 5) + 1);
|
||||
_statusState -= expo;
|
||||
_statusState &= 0xff;
|
||||
ledcWrite(0, _statusState);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CGPIOout::_doSuspendMode() // brief flash
|
||||
{
|
||||
long tDelta = millis() - _breatheDelay;
|
||||
if(tDelta >= 0) {
|
||||
_statusState++;
|
||||
if(_statusState & 0x01) {
|
||||
_breatheDelay += ONFLASHINTERVAL; // brief flash on
|
||||
digitalWrite(_pins[0], HIGH);
|
||||
}
|
||||
else {
|
||||
_breatheDelay += (FLASHPERIOD - ONFLASHINTERVAL); // extended off
|
||||
digitalWrite(_pins[0], LOW);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CGPIOout::setState(int channel, bool state)
|
||||
{
|
||||
int mask = 0x01 << (channel & 0x01);
|
||||
if(state)
|
||||
_userState |= mask;
|
||||
else
|
||||
_userState &= ~mask;
|
||||
}
|
||||
|
||||
bool
|
||||
CGPIOout::getState(int channel)
|
||||
{
|
||||
int mask = 0x01 << (channel & 0x01);
|
||||
return (_userState & mask) != 0;
|
||||
}
|
||||
|
||||
|
||||
// expected external analogue circuit is a 10k pot.
|
||||
// Top end of pot is connected to GPIO Vcc (red wire) via 5k6 fixed resistor. (GPIO Vcc is 5V via schottky diode)
|
||||
// Bottom end of pot is connected to GND (black wire) via 1k fixed resistor.
|
||||
// Wiper is into Pin 6 of GPIO (white wire) - analogue input
|
||||
|
||||
CGPIOalg::CGPIOalg()
|
||||
{
|
||||
_expMean = 0;
|
||||
}
|
||||
|
||||
void
|
||||
CGPIOalg::begin(adc1_channel_t pin, GPIOalgModes mode)
|
||||
{
|
||||
_pin = pin;
|
||||
_Mode = mode;
|
||||
|
||||
if(_Mode != GPIOalgNone) {
|
||||
adc_gpio_init(ADC_UNIT_1, ADC_CHANNEL_5);
|
||||
adc1_config_width(ADC_WIDTH_BIT_12);
|
||||
adc1_config_channel_atten(ADC1_CHANNEL_5, ADC_ATTEN_11db);
|
||||
}
|
||||
}
|
||||
|
||||
void CGPIOalg::manage()
|
||||
{
|
||||
const float fAlpha = 0.95; // exponential mean alpha
|
||||
|
||||
if(_Mode != GPIOalgNone) {
|
||||
int read_raw;
|
||||
char msg[32];
|
||||
read_raw = adc1_get_raw( ADC1_CHANNEL_5);
|
||||
sprintf(msg, "ADC: %d", read_raw );
|
||||
_expMean = _expMean * fAlpha + (1-fAlpha) * float(read_raw);
|
||||
// DebugPort.println(msg);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
CGPIOalg::getValue()
|
||||
{
|
||||
return _expMean;
|
||||
}
|
|
@ -1,104 +0,0 @@
|
|||
/*
|
||||
* This file is part of the "bluetoothheater" distribution
|
||||
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
|
||||
*
|
||||
* Copyright (C) 2018 Ray Jones <ray@mrjones.id.au>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __BTCGPIO_H__
|
||||
#define __BTCGPIO_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <driver/adc.h>
|
||||
#include "Debounce.h"
|
||||
|
||||
enum GPIOinModes {
|
||||
GPIOinNone,
|
||||
GPIOinOn1Off2, // input 1 closure, heater starts; input2 closure, heater stops
|
||||
GPIOinOnHold1, // hold input 1 closure, heater runs; input 1 open, heater stops
|
||||
GPIOinOn1Off1 // alternate input 1 closures start or stop the heater
|
||||
};
|
||||
|
||||
enum GPIOoutModes {
|
||||
GPIOoutNone,
|
||||
GPIOoutStatus,
|
||||
GPIOoutUser
|
||||
};
|
||||
|
||||
enum GPIOalgModes {
|
||||
GPIOalgNone, // Unmodified V2.0 PCBs must use this - ADC2 / Wifi unresolvable conflict
|
||||
GPIOalgHeatDemand,
|
||||
};
|
||||
|
||||
|
||||
class CGPIOin {
|
||||
GPIOinModes _Mode;
|
||||
CDebounce _Debounce;
|
||||
// int _pinActive;
|
||||
// int _pins[2];
|
||||
// uint8_t _prevPins;
|
||||
// uint8_t _debouncedPins;
|
||||
uint8_t _lastKey;
|
||||
// unsigned long _lastDebounceTime;
|
||||
// unsigned long _debounceDelay;
|
||||
// uint8_t _scanInputs();
|
||||
void _doOn1Off2();
|
||||
void _doOnHold1();
|
||||
void _doOn1Off1();
|
||||
public:
|
||||
CGPIOin();
|
||||
void setMode(GPIOinModes mode) { _Mode = mode; };
|
||||
void begin(int pin1, int pin2, GPIOinModes mode, int activeState);
|
||||
void manage();
|
||||
uint8_t getState(int channel);
|
||||
};
|
||||
|
||||
class CGPIOout {
|
||||
GPIOoutModes _Mode;
|
||||
void _doStatus();
|
||||
void _doUser();
|
||||
int _pins[2];
|
||||
int _prevState;
|
||||
int _statusState;
|
||||
int _statusDelay;
|
||||
unsigned long _breatheDelay;
|
||||
uint8_t _userState;
|
||||
void _doStartMode();
|
||||
void _doStopMode();
|
||||
void _doSuspendMode();
|
||||
public:
|
||||
CGPIOout();
|
||||
void setMode(GPIOoutModes mode);
|
||||
void begin(int pin1, int pin2, GPIOoutModes mode);
|
||||
void manage();
|
||||
void setState(int channel, bool state);
|
||||
bool getState(int channel);
|
||||
};
|
||||
|
||||
class CGPIOalg {
|
||||
GPIOalgModes _Mode;
|
||||
float _expMean;
|
||||
adc1_channel_t _pin;
|
||||
public:
|
||||
CGPIOalg();
|
||||
void begin(adc1_channel_t pin, GPIOalgModes mode);
|
||||
void manage();
|
||||
int getValue();
|
||||
};
|
||||
|
||||
|
||||
#endif // __BTCGPIO_H__
|
|
@ -1,155 +0,0 @@
|
|||
/*
|
||||
* This file is part of the "bluetoothheater" distribution
|
||||
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
|
||||
*
|
||||
* Copyright (C) 2018 Ray Jones <ray@mrjones.id.au>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __BTC_MODERATOR_H__
|
||||
#define __BTC_MODERATOR_H__
|
||||
|
||||
#include <map>
|
||||
#include <ArduinoJSON.h>
|
||||
#include "../RTC/Timers.h"
|
||||
#include "DebugPort.h"
|
||||
|
||||
class CTimerModerator {
|
||||
sTimer Memory[14];
|
||||
enum eType { eStart, eStop, eDays, eRpt, eTemp};
|
||||
const char* _getName(eType type);
|
||||
int _shouldSend(int channel, const sTimer& toSend);
|
||||
public:
|
||||
CTimerModerator();
|
||||
bool addJson(int channel, const sTimer& toSend, JsonObject& root);
|
||||
void reset();
|
||||
void reset(int channel);
|
||||
};
|
||||
|
||||
|
||||
template <class T>
|
||||
class TModerator {
|
||||
std::map<const char*, T> Memory;
|
||||
public:
|
||||
bool shouldSend(const char* name, T value);
|
||||
bool addJson(const char* name, T value, JsonObject& root);
|
||||
void reset();
|
||||
void reset(const char* name);
|
||||
};
|
||||
|
||||
template<class T>
|
||||
bool TModerator<T>::shouldSend(const char* name, T value)
|
||||
{
|
||||
bool retval = true;
|
||||
auto it = Memory.find(name);
|
||||
if(it != Memory.end()) {
|
||||
retval = it->second != value;
|
||||
it->second = value;
|
||||
}
|
||||
else {
|
||||
Memory[name] = value;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool TModerator<T>::addJson(const char* name, T value, JsonObject& root)
|
||||
{
|
||||
bool retval;
|
||||
if( retval = shouldSend(name, value ) )
|
||||
root.set(name, value);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
void TModerator<T>::reset()
|
||||
{
|
||||
for(auto it = Memory.begin(); it != Memory.end(); ++it) {
|
||||
if(std::is_pointer<T>::value) {
|
||||
it->second = NULL;
|
||||
}
|
||||
else {
|
||||
it->second = it->second+100;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void TModerator<T>::reset(const char* name)
|
||||
{
|
||||
auto it = Memory.find(name);
|
||||
if(it != Memory.end()) {
|
||||
DebugPort.print("Resetting moderator: \""); DebugPort.print(name); DebugPort.println("\"");
|
||||
if(std::is_pointer<T>::value) {
|
||||
it->second = NULL;
|
||||
}
|
||||
else {
|
||||
it->second = it->second+100;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CModerator {
|
||||
TModerator<int> iModerator;
|
||||
TModerator<float> fModerator;
|
||||
TModerator<unsigned char> ucModerator;
|
||||
TModerator<const char*> szModerator;
|
||||
public:
|
||||
// integer values
|
||||
bool shouldSend(const char* name, int value) {
|
||||
return iModerator.shouldSend(name, value);
|
||||
};
|
||||
bool addJson(const char* name, int value, JsonObject& root) {
|
||||
return iModerator.addJson(name, value, root);
|
||||
};
|
||||
// float values
|
||||
bool shouldSend(const char* name, float value) {
|
||||
return fModerator.shouldSend(name, value);
|
||||
};
|
||||
bool addJson(const char* name, float value, JsonObject& root) {
|
||||
return fModerator.addJson(name, value, root);
|
||||
};
|
||||
// unsigned char values
|
||||
bool shouldSend(const char* name, unsigned char value) {
|
||||
return ucModerator.shouldSend(name, value);
|
||||
};
|
||||
bool addJson(const char* name, unsigned char value, JsonObject& root) {
|
||||
return ucModerator.addJson(name, value, root);
|
||||
};
|
||||
// const char* values
|
||||
bool shouldSend(const char* name, const char* value) {
|
||||
return szModerator.shouldSend(name, value);
|
||||
};
|
||||
bool addJson(const char* name, const char* value, JsonObject& root) {
|
||||
return szModerator.addJson(name, value, root);
|
||||
};
|
||||
// force changes on all held values
|
||||
void reset() {
|
||||
iModerator.reset();
|
||||
fModerator.reset();
|
||||
ucModerator.reset();
|
||||
szModerator.reset();
|
||||
};
|
||||
void reset(const char* name) {
|
||||
iModerator.reset(name);
|
||||
fModerator.reset(name);
|
||||
ucModerator.reset(name);
|
||||
szModerator.reset(name);
|
||||
};
|
||||
};
|
||||
|
||||
#endif // __BTC_MODERATOR_H__
|
|
@ -1,634 +0,0 @@
|
|||
/*
|
||||
* This file is part of the "bluetoothheater" distribution
|
||||
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
|
||||
*
|
||||
* Copyright (C) 2018 Ray Jones <ray@mrjones.id.au>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "NVStorage.h"
|
||||
#include "DebugPort.h"
|
||||
#include <driver/adc.h>
|
||||
|
||||
bool u8inBounds(uint8_t test, uint8_t minLim, uint8_t maxLim);
|
||||
bool s8inBounds(int8_t test, int8_t minLim, int8_t maxLim);
|
||||
bool u8Match2(uint8_t test, uint8_t test1, uint8_t test2);
|
||||
bool u16inBounds(uint16_t test, uint16_t minLim, uint16_t maxLim);
|
||||
bool s32inBounds(long test, long minLim, long maxLim);
|
||||
bool thermoMethodinBounds(uint8_t test, uint8_t minLim, uint8_t maxLim);
|
||||
|
||||
bool
|
||||
sNVStore::valid()
|
||||
{
|
||||
bool retval = true;
|
||||
retval &= Options.valid();
|
||||
for(int i=0; i<2; i++) {
|
||||
retval &= timer[i].valid();
|
||||
}
|
||||
retval &= Heater.valid();
|
||||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
sNVStore::init()
|
||||
{
|
||||
for(int i=0; i<2; i++) {
|
||||
timer[i].init();
|
||||
}
|
||||
Options.init();
|
||||
Heater.init();
|
||||
}
|
||||
|
||||
CHeaterStorage::CHeaterStorage()
|
||||
{
|
||||
_calValues.Heater.init();
|
||||
}
|
||||
|
||||
float
|
||||
CHeaterStorage::getPmin()
|
||||
{
|
||||
return float(_calValues.Heater.Pmin) * 0.1f;
|
||||
}
|
||||
|
||||
float
|
||||
CHeaterStorage::getPmax()
|
||||
{
|
||||
return float(_calValues.Heater.Pmax) * 0.1f;
|
||||
}
|
||||
|
||||
unsigned short
|
||||
CHeaterStorage::getFmin()
|
||||
{
|
||||
return _calValues.Heater.Fmin;
|
||||
}
|
||||
|
||||
unsigned short
|
||||
CHeaterStorage::getFmax()
|
||||
{
|
||||
return _calValues.Heater.Fmax;
|
||||
}
|
||||
|
||||
unsigned char
|
||||
CHeaterStorage::getDesiredTemperature()
|
||||
{
|
||||
return _calValues.Heater.setTemperature;
|
||||
}
|
||||
|
||||
unsigned char
|
||||
CHeaterStorage::getThermostatMode()
|
||||
{
|
||||
return _calValues.Heater.ThermostatMode;
|
||||
}
|
||||
|
||||
unsigned char
|
||||
CHeaterStorage::getThermostatMethodMode()
|
||||
{
|
||||
return _calValues.Options.ThermostatMethod & 0x03;
|
||||
}
|
||||
|
||||
float
|
||||
CHeaterStorage::getThermostatMethodWindow()
|
||||
{
|
||||
return float((_calValues.Options.ThermostatMethod >> 2) & 0x3f) * 0.1f; // top 5 bits / 10, then / 2
|
||||
}
|
||||
|
||||
void
|
||||
CHeaterStorage::setPmin(float val)
|
||||
{
|
||||
uint8_t cVal = (uint8_t)(val * 10.f + 0.5f);
|
||||
_calValues.Heater.Pmin = cVal;
|
||||
}
|
||||
|
||||
void
|
||||
CHeaterStorage::setPmax(float val)
|
||||
{
|
||||
uint8_t cVal = (uint8_t)(val * 10.f + 0.5f);
|
||||
_calValues.Heater.Pmax = cVal;
|
||||
}
|
||||
|
||||
void
|
||||
CHeaterStorage::setFmin(unsigned short val)
|
||||
{
|
||||
_calValues.Heater.Fmin = val;
|
||||
}
|
||||
|
||||
void
|
||||
CHeaterStorage::setFmax(unsigned short val)
|
||||
{
|
||||
_calValues.Heater.Fmax = val;
|
||||
}
|
||||
|
||||
void
|
||||
CHeaterStorage::setDesiredTemperature(unsigned char val)
|
||||
{
|
||||
_calValues.Heater.setTemperature = val;
|
||||
}
|
||||
|
||||
void
|
||||
CHeaterStorage::setThermostatMode(unsigned char val)
|
||||
{
|
||||
_calValues.Heater.ThermostatMode = val;
|
||||
}
|
||||
|
||||
void
|
||||
CHeaterStorage::setThermostatMethodMode(unsigned char val)
|
||||
{
|
||||
_calValues.Options.ThermostatMethod &= ~0x03;
|
||||
_calValues.Options.ThermostatMethod |= (val & 0x03);
|
||||
}
|
||||
|
||||
void
|
||||
CHeaterStorage::setThermostatMethodWindow(float val)
|
||||
{
|
||||
_calValues.Options.ThermostatMethod &= 0x03;
|
||||
int nVal = int(val * 10 + 0.5);
|
||||
_calValues.Options.ThermostatMethod |= ((nVal & 0x3F) << 2);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CHeaterStorage::setSystemVoltage(float fVal)
|
||||
{
|
||||
int val = int(fVal * 10.0);
|
||||
if(val == 120 || val == 240) {
|
||||
_calValues.Heater.sysVoltage = val;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char
|
||||
CHeaterStorage::getSysVoltage()
|
||||
{
|
||||
return _calValues.Heater.sysVoltage;
|
||||
}
|
||||
|
||||
void
|
||||
CHeaterStorage::setFanSensor(unsigned char val)
|
||||
{
|
||||
if(val == 2)
|
||||
_calValues.Heater.fanSensor = 2;
|
||||
else
|
||||
_calValues.Heater.fanSensor = 1;
|
||||
}
|
||||
|
||||
unsigned char
|
||||
CHeaterStorage::getFanSensor()
|
||||
{
|
||||
return _calValues.Heater.fanSensor;
|
||||
}
|
||||
|
||||
void
|
||||
CHeaterStorage::setGlowDrive(unsigned char val)
|
||||
{
|
||||
if(val >=1 && val <= 6)
|
||||
_calValues.Heater.glowDrive = val;
|
||||
else
|
||||
_calValues.Heater.glowDrive = 5;
|
||||
}
|
||||
|
||||
unsigned char
|
||||
CHeaterStorage::getGlowDrive()
|
||||
{
|
||||
return _calValues.Heater.glowDrive;
|
||||
}
|
||||
|
||||
void
|
||||
CHeaterStorage::getTimerInfo(int idx, sTimer& timerInfo)
|
||||
{
|
||||
if(idx >= 0 && idx < 14) {
|
||||
timerInfo = _calValues.timer[idx];
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CHeaterStorage::setTimerInfo(int idx, const sTimer& timerInfo)
|
||||
{
|
||||
if(idx >= 0 && idx < 14) {
|
||||
_calValues.timer[idx] = timerInfo;
|
||||
}
|
||||
}
|
||||
|
||||
long
|
||||
CHeaterStorage::getDimTime()
|
||||
{
|
||||
return _calValues.Options.dimTime;
|
||||
}
|
||||
|
||||
void
|
||||
CHeaterStorage::setDimTime(long val)
|
||||
{
|
||||
_calValues.Options.dimTime = val;
|
||||
}
|
||||
|
||||
long
|
||||
CHeaterStorage::getMenuTimeout()
|
||||
{
|
||||
return _calValues.Options.menuTimeout;
|
||||
}
|
||||
|
||||
void
|
||||
CHeaterStorage::setMenuTimeout(long val)
|
||||
{
|
||||
_calValues.Options.menuTimeout = val;
|
||||
}
|
||||
|
||||
unsigned char
|
||||
CHeaterStorage::getDegFMode()
|
||||
{
|
||||
return _calValues.Options.degF;
|
||||
}
|
||||
|
||||
void
|
||||
CHeaterStorage::setDegFMode(unsigned char val)
|
||||
{
|
||||
_calValues.Options.degF = val;
|
||||
save();
|
||||
}
|
||||
|
||||
unsigned char
|
||||
CHeaterStorage::getWifiEnabled()
|
||||
{
|
||||
return _calValues.Options.enableWifi;
|
||||
}
|
||||
|
||||
void
|
||||
CHeaterStorage::setWifiEnabled(unsigned char val)
|
||||
{
|
||||
_calValues.Options.enableWifi = val;
|
||||
save();
|
||||
}
|
||||
|
||||
unsigned char
|
||||
CHeaterStorage::getOTAEnabled()
|
||||
{
|
||||
return _calValues.Options.enableOTA;
|
||||
}
|
||||
|
||||
void
|
||||
CHeaterStorage::setOTAEnabled(unsigned char val)
|
||||
{
|
||||
_calValues.Options.enableOTA = val;
|
||||
save();
|
||||
}
|
||||
|
||||
const sCyclicThermostat&
|
||||
CHeaterStorage::getCyclicMode() const
|
||||
{
|
||||
return _calValues.Options.cyclic;
|
||||
}
|
||||
|
||||
void
|
||||
CHeaterStorage::setCyclicMode(const sCyclicThermostat& val)
|
||||
{
|
||||
_calValues.Options.cyclic = val;
|
||||
save();
|
||||
}
|
||||
|
||||
GPIOinModes
|
||||
CHeaterStorage::getGPIOinMode()
|
||||
{
|
||||
GPIOinModes inMode = GPIOinNone;
|
||||
switch(_calValues.Options.GPIOinMode) {
|
||||
case 0: inMode = GPIOinNone; break;
|
||||
case 1: inMode = GPIOinOn1Off2; break;
|
||||
case 2: inMode = GPIOinOnHold1; break;
|
||||
case 3: inMode = GPIOinOn1Off1; break;
|
||||
}
|
||||
return inMode;
|
||||
}
|
||||
|
||||
void
|
||||
CHeaterStorage::setGPIOinMode(unsigned char val)
|
||||
{
|
||||
_calValues.Options.GPIOinMode = val;
|
||||
}
|
||||
|
||||
GPIOoutModes
|
||||
CHeaterStorage::getGPIOoutMode()
|
||||
{
|
||||
GPIOoutModes outMode = GPIOoutNone;
|
||||
switch(_calValues.Options.GPIOoutMode) {
|
||||
case 0: outMode = GPIOoutNone; break;
|
||||
case 1: outMode = GPIOoutStatus; break;
|
||||
case 2: outMode = GPIOoutUser; break;
|
||||
}
|
||||
return outMode;
|
||||
}
|
||||
|
||||
void
|
||||
CHeaterStorage::setGPIOoutMode(unsigned char val)
|
||||
{
|
||||
_calValues.Options.GPIOoutMode = val;
|
||||
}
|
||||
|
||||
GPIOalgModes
|
||||
CHeaterStorage::getGPIOalgMode()
|
||||
{
|
||||
GPIOalgModes algMode = GPIOalgNone;
|
||||
switch (_calValues.Options.GPIOalgMode) {
|
||||
case 0: algMode = GPIOalgNone; break;
|
||||
case 1: algMode = GPIOalgHeatDemand; break;
|
||||
}
|
||||
return algMode;
|
||||
}
|
||||
|
||||
void
|
||||
CHeaterStorage::setGPIOalgMode(unsigned char val)
|
||||
{
|
||||
_calValues.Options.GPIOalgMode = val;
|
||||
}
|
||||
|
||||
uint16_t
|
||||
CHeaterStorage::getFrameRate()
|
||||
{
|
||||
return _calValues.Options.FrameRate;
|
||||
}
|
||||
|
||||
void
|
||||
CHeaterStorage::setFrameRate(uint16_t val)
|
||||
{
|
||||
_calValues.Options.FrameRate = val;
|
||||
}
|
||||
|
||||
const sHomeMenuActions&
|
||||
CHeaterStorage::getHomeMenu() const
|
||||
{
|
||||
return _calValues.Options.HomeMenu;
|
||||
}
|
||||
|
||||
void
|
||||
CHeaterStorage::setHomeMenu(sHomeMenuActions val)
|
||||
{
|
||||
_calValues.Options.HomeMenu = val;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
// ESP32
|
||||
//
|
||||
//#ifdef ESP32
|
||||
|
||||
CESP32HeaterStorage::CESP32HeaterStorage()
|
||||
{
|
||||
}
|
||||
|
||||
CESP32HeaterStorage::~CESP32HeaterStorage()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
CESP32HeaterStorage::init()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
CESP32HeaterStorage::load()
|
||||
{
|
||||
DebugPort.println("Reading from NV storage");
|
||||
loadHeater();
|
||||
for(int i=0; i<14; i++) {
|
||||
loadTimer(i);
|
||||
}
|
||||
loadUI();
|
||||
}
|
||||
|
||||
void
|
||||
CESP32HeaterStorage::save()
|
||||
{
|
||||
DebugPort.println("Saving to NV storage");
|
||||
saveHeater();
|
||||
for(int i=0; i<14; i++) {
|
||||
saveTimer(i);
|
||||
}
|
||||
saveUI();
|
||||
}
|
||||
|
||||
// **** MAX LENGTH is 15 for name and values ****
|
||||
void
|
||||
CESP32HeaterStorage::loadHeater()
|
||||
{
|
||||
// section for heater calibration params
|
||||
preferences.begin("Calibration", false);
|
||||
validatedLoad("minPump", _calValues.Heater.Pmin, 14, u8inBounds, 4, 100);
|
||||
validatedLoad("maxPump", _calValues.Heater.Pmax, 45, u8inBounds, 4, 150);
|
||||
validatedLoad("minFan", _calValues.Heater.Fmin, 1500, u16inBounds, 100, 5000);
|
||||
validatedLoad("maxFan", _calValues.Heater.Fmax, 4500, u16inBounds, 100, 6000);
|
||||
validatedLoad("thermostat", _calValues.Heater.ThermostatMode, 1, u8inBounds, 0, 1);
|
||||
validatedLoad("setTemperature", _calValues.Heater.setTemperature, 22, u8inBounds, 0, 40);
|
||||
validatedLoad("systemVoltage", _calValues.Heater.sysVoltage, 120, u8Match2, 120, 240);
|
||||
validatedLoad("fanSensor", _calValues.Heater.fanSensor, 1, u8inBounds, 1, 2);
|
||||
validatedLoad("glowDrive", _calValues.Heater.glowDrive, 5, u8inBounds, 1, 6);
|
||||
preferences.end();
|
||||
}
|
||||
|
||||
// **** MAX LENGTH is 15 for name and values ****
|
||||
void
|
||||
CESP32HeaterStorage::saveHeater()
|
||||
{
|
||||
// section for heater calibration params
|
||||
preferences.begin("Calibration", false);
|
||||
preferences.putUChar("minPump", _calValues.Heater.Pmin);
|
||||
preferences.putUChar("maxPump", _calValues.Heater.Pmax);
|
||||
preferences.putUShort("minFan", _calValues.Heater.Fmin);
|
||||
preferences.putUShort("maxFan", _calValues.Heater.Fmax);
|
||||
preferences.putUChar("thermostat", _calValues.Heater.ThermostatMode);
|
||||
preferences.putUChar("setTemperature", _calValues.Heater.setTemperature);
|
||||
preferences.putUChar("systemVoltage", _calValues.Heater.sysVoltage);
|
||||
preferences.putUChar("fanSensor", _calValues.Heater.fanSensor);
|
||||
preferences.putUChar("glowDrive", _calValues.Heater.glowDrive);
|
||||
preferences.end();
|
||||
}
|
||||
|
||||
// **** MAX LENGTH is 15 for name and values ****
|
||||
void
|
||||
CESP32HeaterStorage::loadTimer(int idx)
|
||||
{
|
||||
sTimer& timer = _calValues.timer[idx];
|
||||
timer.timerID = idx;
|
||||
char SectionName[16];
|
||||
sprintf(SectionName, "timer%d", idx+1);
|
||||
preferences.begin(SectionName, false);
|
||||
validatedLoad("startHour", timer.start.hour, 0, s8inBounds, 0, 23);
|
||||
validatedLoad("startMin", timer.start.min, 0, s8inBounds, 0, 59);
|
||||
validatedLoad("stopHour", timer.stop.hour, 0, s8inBounds, 0, 23);
|
||||
validatedLoad("stopMin", timer.stop.min, 0, s8inBounds, 0, 59);
|
||||
validatedLoad("enabled", timer.enabled, 0, u8inBounds, 0, 255); // all 8 bits used!
|
||||
validatedLoad("repeat", timer.repeat, 0, u8inBounds, 0, 1);
|
||||
validatedLoad("temperature", timer.temperature, 22, u8inBounds, 8, 35);
|
||||
preferences.end();
|
||||
}
|
||||
|
||||
// **** MAX LENGTH is 15 for name and values ****
|
||||
void
|
||||
CESP32HeaterStorage::saveTimer(int idx)
|
||||
{
|
||||
sTimer& timer = _calValues.timer[idx];
|
||||
char SectionName[16];
|
||||
sprintf(SectionName, "timer%d", idx+1);
|
||||
preferences.begin(SectionName, false);
|
||||
preferences.putChar("startHour", timer.start.hour);
|
||||
preferences.putChar("startMin", timer.start.min);
|
||||
preferences.putChar("stopHour", timer.stop.hour);
|
||||
preferences.putChar("stopMin", timer.stop.min);
|
||||
preferences.putUChar("enabled", timer.enabled);
|
||||
preferences.putUChar("repeat", timer.repeat);
|
||||
preferences.putUChar("temperature", timer.temperature);
|
||||
preferences.end();
|
||||
}
|
||||
|
||||
// **** MAX LENGTH is 15 for name and values ****
|
||||
void
|
||||
CESP32HeaterStorage::loadUI()
|
||||
{
|
||||
preferences.begin("user", false);
|
||||
validatedLoad("dimTime", _calValues.Options.dimTime, 60000, s32inBounds, -600000, 600000);
|
||||
validatedLoad("menuTimeout", _calValues.Options.menuTimeout, 60000, s32inBounds, 0, 300000);
|
||||
validatedLoad("degF", _calValues.Options.degF, 0, u8inBounds, 0, 1);
|
||||
validatedLoad("thermoMethod", _calValues.Options.ThermostatMethod, (10 << 2), u8inBounds, 0, 2, 0x03);
|
||||
validatedLoad("enableWifi", _calValues.Options.enableWifi, 1, u8inBounds, 0, 1);
|
||||
validatedLoad("enableOTA", _calValues.Options.enableOTA, 1, u8inBounds, 0, 1);
|
||||
validatedLoad("cyclicStop", _calValues.Options.cyclic.Stop, 0, s8inBounds, 0, 10);
|
||||
validatedLoad("cyclicStart", _calValues.Options.cyclic.Start, -1, s8inBounds, -10, 0);
|
||||
validatedLoad("GPIOinMode", _calValues.Options.GPIOinMode, 0, u8inBounds, 0, 3);
|
||||
validatedLoad("GPIOoutMode", _calValues.Options.GPIOoutMode, 0, u8inBounds, 0, 2);
|
||||
validatedLoad("GPIOalgMode", _calValues.Options.GPIOalgMode, 0, u8inBounds, 0, 2);
|
||||
validatedLoad("MenuonTimeout", _calValues.Options.HomeMenu.onTimeout, 0, u8inBounds, 0, 3);
|
||||
validatedLoad("MenuonStart", _calValues.Options.HomeMenu.onStart, 0, u8inBounds, 0, 3);
|
||||
validatedLoad("MenuonStop", _calValues.Options.HomeMenu.onStop, 0, u8inBounds, 0, 3);
|
||||
validatedLoad("FrameRate", _calValues.Options.FrameRate, 1000, u16inBounds, 300, 1500);
|
||||
preferences.end();
|
||||
}
|
||||
|
||||
void
|
||||
CESP32HeaterStorage::saveUI()
|
||||
{
|
||||
preferences.begin("user", false);
|
||||
preferences.putLong("dimTime", _calValues.Options.dimTime);
|
||||
preferences.putLong("menuTimeout", _calValues.Options.menuTimeout);
|
||||
preferences.putUChar("degF", _calValues.Options.degF);
|
||||
preferences.putUChar("thermoMethod", _calValues.Options.ThermostatMethod);
|
||||
preferences.putUChar("enableWifi", _calValues.Options.enableWifi);
|
||||
preferences.putUChar("enableOTA", _calValues.Options.enableOTA);
|
||||
preferences.putChar("cyclicStop", _calValues.Options.cyclic.Stop);
|
||||
preferences.putChar("cyclicStart", _calValues.Options.cyclic.Start);
|
||||
preferences.putUChar("GPIOinMode", _calValues.Options.GPIOinMode);
|
||||
preferences.putUChar("GPIOoutMode", _calValues.Options.GPIOoutMode);
|
||||
preferences.putUChar("GPIOalgMode", _calValues.Options.GPIOalgMode);
|
||||
preferences.putUChar("MenuOnTimeout", _calValues.Options.HomeMenu.onTimeout);
|
||||
preferences.putUChar("MenuonStart", _calValues.Options.HomeMenu.onStart);
|
||||
preferences.putUChar("MenuonStop", _calValues.Options.HomeMenu.onStop);
|
||||
preferences.putUShort("FrameRate", _calValues.Options.FrameRate);
|
||||
preferences.end();
|
||||
}
|
||||
|
||||
bool
|
||||
CESP32HeaterStorage::validatedLoad(const char* key, uint8_t& val, int defVal, std::function<bool(uint8_t, uint8_t, uint8_t)> validator, int min, int max, uint8_t mask)
|
||||
{
|
||||
val = preferences.getUChar(key, defVal);
|
||||
if(!validator(val & mask, min, max)) {
|
||||
|
||||
DebugPort.print("CESP32HeaterStorage::validatedLoad<uint8_t> invalid read ");
|
||||
DebugPort.print(key); DebugPort.print("="); DebugPort.print(val);
|
||||
DebugPort.print(" validator("); DebugPort.print(min); DebugPort.print(","); DebugPort.print(max); DebugPort.print(") reset to ");
|
||||
DebugPort.println(defVal);
|
||||
|
||||
val = defVal;
|
||||
preferences.putUChar(key, val);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CESP32HeaterStorage::validatedLoad(const char* key, int8_t& val, int defVal, std::function<bool(int8_t, int8_t, int8_t)> validator, int min, int max)
|
||||
{
|
||||
val = preferences.getChar(key, defVal);
|
||||
if(!validator(val, min, max)) {
|
||||
|
||||
DebugPort.print("CESP32HeaterStorage::validatedLoad<uint8_t> invalid read ");
|
||||
DebugPort.print(key); DebugPort.print("="); DebugPort.print(val);
|
||||
DebugPort.print(" validator("); DebugPort.print(min); DebugPort.print(","); DebugPort.print(max); DebugPort.print(") reset to ");
|
||||
DebugPort.println(defVal);
|
||||
|
||||
val = defVal;
|
||||
preferences.putChar(key, val);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CESP32HeaterStorage::validatedLoad(const char* key, uint16_t& val, int defVal, std::function<bool(uint16_t, uint16_t, uint16_t)> validator, int min, int max)
|
||||
{
|
||||
val = preferences.getUShort(key, defVal);
|
||||
if(!validator(val, min, max)) {
|
||||
|
||||
DebugPort.print("CESP32HeaterStorage::validatedLoad<uint16_t> invalid read ");
|
||||
DebugPort.print(key); DebugPort.print("="); DebugPort.print(val);
|
||||
DebugPort.print(" validator("); DebugPort.print(min); DebugPort.print(","); DebugPort.print(max); DebugPort.print(") reset to ");
|
||||
DebugPort.println(defVal);
|
||||
|
||||
val = defVal;
|
||||
preferences.putUShort(key, val);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CESP32HeaterStorage::validatedLoad(const char* key, long& val, long defVal, std::function<bool(long, long, long)> validator, long min, long max)
|
||||
{
|
||||
val = preferences.getLong(key, defVal);
|
||||
if(!validator(val, min, max)) {
|
||||
|
||||
DebugPort.print("CESP32HeaterStorage::validatedLoad<long> invalid read ");
|
||||
DebugPort.print(key); DebugPort.print("="); DebugPort.print(val);
|
||||
DebugPort.print(" validator("); DebugPort.print(min); DebugPort.print(","); DebugPort.print(max); DebugPort.print(") reset to ");
|
||||
DebugPort.println(defVal);
|
||||
|
||||
val = defVal;
|
||||
preferences.putLong(key, val);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool u8inBounds(uint8_t test, uint8_t minLim, uint8_t maxLim)
|
||||
{
|
||||
return (test >= minLim) && (test <= maxLim);
|
||||
}
|
||||
|
||||
bool s8inBounds(int8_t test, int8_t minLim, int8_t maxLim)
|
||||
{
|
||||
return (test >= minLim) && (test <= maxLim);
|
||||
}
|
||||
|
||||
bool u8Match2(uint8_t test, uint8_t test1, uint8_t test2)
|
||||
{
|
||||
return (test == test1) || (test == test2);
|
||||
}
|
||||
|
||||
bool u16inBounds(uint16_t test, uint16_t minLim, uint16_t maxLim)
|
||||
{
|
||||
return (test >= minLim) && (test <= maxLim);
|
||||
}
|
||||
|
||||
bool s32inBounds(long test, long minLim, long maxLim)
|
||||
{
|
||||
return (test >= minLim) && (test <= maxLim);
|
||||
}
|
||||
|
||||
|
||||
//#endif // ESP32
|
|
@ -1,268 +0,0 @@
|
|||
/*
|
||||
* This file is part of the "bluetoothheater" distribution
|
||||
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
|
||||
*
|
||||
* Copyright (C) 2018 Ray Jones <ray@mrjones.id.au>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __BTC_NV_STORAGE_H__
|
||||
#define __BTC_NV_STORAGE_H__
|
||||
|
||||
#include "../RTC/Timers.h" // for sTimer
|
||||
#include "GPIO.h"
|
||||
|
||||
struct sHeater {
|
||||
uint8_t Pmin;
|
||||
uint8_t Pmax;
|
||||
uint16_t Fmin;
|
||||
uint16_t Fmax;
|
||||
uint8_t ThermostatMode;
|
||||
uint8_t setTemperature;
|
||||
uint8_t sysVoltage;
|
||||
uint8_t fanSensor;
|
||||
uint8_t glowDrive;
|
||||
|
||||
bool valid() {
|
||||
bool retval = true;
|
||||
retval &= Pmin < 100;
|
||||
retval &= Pmax < 150;
|
||||
retval &= Fmin < 5000;
|
||||
retval &= Fmax < 6000;
|
||||
retval &= ThermostatMode < 2;
|
||||
retval &= setTemperature < 40;
|
||||
retval &= sysVoltage == 120 || sysVoltage == 240;
|
||||
retval &= fanSensor == 1 || fanSensor == 2;
|
||||
retval &= glowDrive >= 1 && glowDrive <= 6;
|
||||
return retval;
|
||||
};
|
||||
void init() {
|
||||
Pmin = 14;
|
||||
Pmax = 45;
|
||||
Fmin = 1500;
|
||||
Fmax = 4500;
|
||||
ThermostatMode = 1;
|
||||
setTemperature = 23;
|
||||
sysVoltage = 120;
|
||||
fanSensor = 1;
|
||||
glowDrive = 5;
|
||||
};
|
||||
};
|
||||
|
||||
struct sHomeMenuActions {
|
||||
uint8_t onTimeout;
|
||||
uint8_t onStart;
|
||||
uint8_t onStop;
|
||||
bool valid() {
|
||||
bool retval = true;
|
||||
retval &= onTimeout < 4;
|
||||
retval &= onStart < 4;
|
||||
retval &= onStop < 4;
|
||||
return retval;
|
||||
}
|
||||
void init() {
|
||||
onTimeout = 0;
|
||||
onStart = 0;
|
||||
onStop = 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct sCyclicThermostat {
|
||||
int8_t Stop;
|
||||
int8_t Start;
|
||||
bool valid() {
|
||||
bool retval = true;
|
||||
retval &= Start >= -10 && Start <= 0;
|
||||
retval &= Stop >= 0 && Stop <= 10;
|
||||
return retval;
|
||||
}
|
||||
void init() {
|
||||
Start = -1;
|
||||
Stop = 0;
|
||||
}
|
||||
bool isEnabled() const {
|
||||
return Stop != 0;
|
||||
}
|
||||
sCyclicThermostat& operator=(const sCyclicThermostat& rhs) {
|
||||
Stop = rhs.Stop;
|
||||
Start = rhs.Start;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
struct sBTCoptions {
|
||||
long dimTime;
|
||||
long menuTimeout;
|
||||
uint8_t degF;
|
||||
uint8_t ThermostatMethod; // 0: standard heater, 1: Narrow Hysterisis, 2:Managed Hz mode
|
||||
uint8_t enableWifi;
|
||||
uint8_t enableOTA;
|
||||
uint8_t GPIOinMode;
|
||||
uint8_t GPIOoutMode;
|
||||
uint8_t GPIOalgMode;
|
||||
uint16_t FrameRate;
|
||||
sCyclicThermostat cyclic;
|
||||
sHomeMenuActions HomeMenu;
|
||||
|
||||
bool valid() {
|
||||
bool retval = true;
|
||||
retval &= (dimTime >= -600000) && (dimTime < 600000); // +/- 10 mins
|
||||
retval &= (menuTimeout >= 0) && (menuTimeout < 300000); // 5 mins
|
||||
retval &= (degF == 0) || (degF == 1);
|
||||
retval &= (ThermostatMethod & 0x03) < 3; // only modes 0, 1 or 2
|
||||
retval &= (enableWifi == 0) || (enableWifi == 1);
|
||||
retval &= (enableOTA == 0) || (enableOTA == 1);
|
||||
retval &= GPIOinMode < 4;
|
||||
retval &= GPIOoutMode < 3;
|
||||
retval &= (FrameRate >= 300) && (FrameRate <= 1500);
|
||||
retval &= cyclic.valid();
|
||||
retval &= HomeMenu.valid();
|
||||
return retval;
|
||||
}
|
||||
void init() {
|
||||
dimTime = 60000;
|
||||
menuTimeout = 60000;
|
||||
degF = 0;
|
||||
ThermostatMethod = 0;
|
||||
enableWifi = 1;
|
||||
enableOTA = 1;
|
||||
GPIOinMode = 0;
|
||||
GPIOoutMode = 0;
|
||||
GPIOalgMode = 0;
|
||||
FrameRate = 1000;
|
||||
cyclic.init();
|
||||
HomeMenu.init();
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
// the actual data stored to NV memory
|
||||
struct sNVStore {
|
||||
sHeater Heater;
|
||||
sBTCoptions Options;
|
||||
sTimer timer[14];
|
||||
bool valid();
|
||||
void init();
|
||||
};
|
||||
|
||||
class CNVStorage {
|
||||
public:
|
||||
CNVStorage() {};
|
||||
virtual ~CNVStorage() {};
|
||||
virtual void init() = 0;
|
||||
virtual void load() = 0;
|
||||
virtual void save() = 0;
|
||||
};
|
||||
|
||||
|
||||
class CHeaterStorage : public CNVStorage {
|
||||
protected:
|
||||
sNVStore _calValues;
|
||||
public:
|
||||
CHeaterStorage();
|
||||
virtual ~CHeaterStorage() {};
|
||||
|
||||
// TODO: These are only here to allow building without fully
|
||||
// fleshing out NV storage for Due, Mega etc
|
||||
// these should be removed once complete (pure virtual)
|
||||
void init() {};
|
||||
void load() {};
|
||||
void save() {};
|
||||
|
||||
|
||||
float getPmin();
|
||||
float getPmax();
|
||||
unsigned short getFmin();
|
||||
unsigned short getFmax();
|
||||
unsigned char getDesiredTemperature();
|
||||
unsigned char getThermostatMode();
|
||||
unsigned char getThermostatMethodMode();
|
||||
float getThermostatMethodWindow();
|
||||
unsigned char getSysVoltage();
|
||||
unsigned char getFanSensor();
|
||||
unsigned char getGlowDrive();
|
||||
long getDimTime();
|
||||
long getMenuTimeout();
|
||||
unsigned char getDegFMode();
|
||||
unsigned char getWifiEnabled();
|
||||
unsigned char getOTAEnabled();
|
||||
const sCyclicThermostat& getCyclicMode() const;
|
||||
GPIOinModes getGPIOinMode();
|
||||
GPIOoutModes getGPIOoutMode();
|
||||
GPIOalgModes getGPIOalgMode();
|
||||
uint16_t getFrameRate();
|
||||
const sHomeMenuActions& getHomeMenu() const;
|
||||
|
||||
void setPmin(float);
|
||||
void setPmax(float);
|
||||
void setFmin(unsigned short val);
|
||||
void setFmax(unsigned short val);
|
||||
void setDesiredTemperature(unsigned char val);
|
||||
void setThermostatMode(unsigned char val);
|
||||
void setThermostatMethodMode(unsigned char val);
|
||||
void setThermostatMethodWindow(float val);
|
||||
void setSystemVoltage(float fVal);
|
||||
void setFanSensor(unsigned char val);
|
||||
void setGlowDrive(unsigned char val);
|
||||
void setDimTime(long val);
|
||||
void setMenuTimeout(long val);
|
||||
void setDegFMode(unsigned char val);
|
||||
void setWifiEnabled(unsigned char val);
|
||||
void setOTAEnabled(unsigned char val);
|
||||
void setCyclicMode(const sCyclicThermostat& val);
|
||||
void setGPIOinMode(unsigned char val);
|
||||
void setGPIOoutMode(unsigned char val);
|
||||
void setGPIOalgMode(unsigned char val);
|
||||
void setFrameRate(uint16_t val);
|
||||
void setHomeMenu(sHomeMenuActions val);
|
||||
|
||||
void getTimerInfo(int idx, sTimer& timerInfo);
|
||||
void setTimerInfo(int idx, const sTimer& timerInfo);
|
||||
};
|
||||
|
||||
|
||||
|
||||
#ifdef ESP32
|
||||
|
||||
#include <Preferences.h>
|
||||
#include <functional>
|
||||
|
||||
class CESP32HeaterStorage : public CHeaterStorage {
|
||||
Preferences preferences;
|
||||
public:
|
||||
CESP32HeaterStorage();
|
||||
virtual ~CESP32HeaterStorage();
|
||||
void init();
|
||||
void load();
|
||||
void save();
|
||||
void loadHeater();
|
||||
void saveHeater();
|
||||
void loadTimer(int idx);
|
||||
void saveTimer(int idx);
|
||||
void loadUI();
|
||||
void saveUI();
|
||||
bool validatedLoad(const char* key, int8_t& val, int defVal, std::function<bool(int8_t, int8_t, int8_t)> validator, int min, int max);
|
||||
bool validatedLoad(const char* key, uint8_t& val, int defVal, std::function<bool(uint8_t, uint8_t, uint8_t)> validator, int min, int max, uint8_t mask=0xff);
|
||||
bool validatedLoad(const char* key, uint16_t& val, int defVal, std::function<bool(uint16_t, uint16_t, uint16_t)> validator, int min, int max);
|
||||
bool validatedLoad(const char* key, long& val, long defVal, std::function<bool(long, long, long)> validator, long min, long max);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
extern CHeaterStorage& NVstore;
|
||||
|
||||
#endif // __BTC_NV_STORAGE_H__
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
/*
|
||||
* This file is part of the "bluetoothheater" distribution
|
||||
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
|
||||
*
|
||||
* Copyright (C) 2018 Ray Jones <ray@mrjones.id.au>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "../Protocol/Protocol.h"
|
||||
#include "UtilClasses.h"
|
||||
|
||||
|
||||
// a class to track the blue wire receive / transmit states
|
||||
// class CommStates
|
||||
|
||||
void
|
||||
CommStates::set(eCS eState)
|
||||
{
|
||||
_State = eState;
|
||||
_Count = 0;
|
||||
if(_report) {
|
||||
static const char* stateNames[] = {
|
||||
"Idle", "OEMCtrlRx", "OEMCtrlValidate", "HeaterRx1", "HeaterValidate1", "HeaterReport1",
|
||||
"BTC_Tx", "HeaterRx2", "HeaterValidate2", "HeaterReport2", "TemperatureRead"
|
||||
};
|
||||
if(_State == Idle) DebugPort.println(""); // clear screen
|
||||
DebugPort.print("State:");DebugPort.println(stateNames[_State]);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
CommStates::collectData(CProtocol& Frame, unsigned char val, int limit) { // returns true when buffer filled
|
||||
Frame.Data[_Count++] = val;
|
||||
return _Count >= limit;
|
||||
}
|
||||
|
||||
bool
|
||||
CommStates::collectDataEx(CProtocol& Frame, unsigned char val, int limit) { // returns true when buffer filled
|
||||
// guarding against rogue rx kernel buffer stutters....
|
||||
if((_Count == 0) && (val != 0x76)) {
|
||||
DebugPort.println("First heater byte not 0x76 - SKIPPING");
|
||||
return false;
|
||||
}
|
||||
Frame.Data[_Count++] = val;
|
||||
return _Count >= limit;
|
||||
}
|
||||
|
||||
bool
|
||||
CommStates::checkValidStart(unsigned char val)
|
||||
{
|
||||
if(_Count)
|
||||
return true;
|
||||
else
|
||||
return val == 0x76;
|
||||
}
|
||||
|
||||
void
|
||||
CommStates::setDelay(int ms)
|
||||
{
|
||||
_delay = millis() + ms;
|
||||
}
|
||||
|
||||
bool
|
||||
CommStates::delayExpired()
|
||||
{
|
||||
long test = millis() - _delay;
|
||||
return(test >= 0);
|
||||
}
|
|
@ -1,236 +0,0 @@
|
|||
/*
|
||||
* This file is part of the "bluetoothheater" distribution
|
||||
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
|
||||
*
|
||||
* Copyright (C) 2018 Ray Jones <ray@mrjones.id.au>
|
||||
* Copyright (C) 2018 James Clark
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "BTCWebServer.h"
|
||||
#include "../Utility/DebugPort.h"
|
||||
#include "../Protocol/TxManage.h"
|
||||
#include "../Protocol/helpers.h"
|
||||
#include "../cfg/pins.h"
|
||||
#include "Index.h"
|
||||
#include "../Utility/BTC_JSON.h"
|
||||
#include "../Utility/Moderator.h"
|
||||
#include <WiFiManager.h>
|
||||
#if USE_SPIFFS == 1
|
||||
#include <SPIFFS.h>
|
||||
#endif
|
||||
|
||||
extern WiFiManager wm;
|
||||
|
||||
WebServer server(80);
|
||||
WebSocketsServer webSocket = WebSocketsServer(81);
|
||||
|
||||
bool bRxWebData = false; // flags for OLED animation
|
||||
bool bTxWebData = false;
|
||||
|
||||
const int led = 13;
|
||||
|
||||
#if USE_SPIFFS == 1
|
||||
|
||||
String getContentType(String filename) { // convert the file extension to the MIME type
|
||||
if (filename.endsWith(".html")) return "text/html";
|
||||
else if (filename.endsWith(".css")) return "text/css";
|
||||
else if (filename.endsWith(".js")) return "application/javascript";
|
||||
else if (filename.endsWith(".ico")) return "image/x-icon";
|
||||
return "text/plain";
|
||||
}
|
||||
|
||||
bool handleFileRead(String path) { // send the right file to the client (if it exists)
|
||||
DebugPort.println("handleFileRead: " + path);
|
||||
if (path.endsWith("/")) path += "index.html"; // If a folder is requested, send the index file
|
||||
String contentType = getContentType(path); // Get the MIME type
|
||||
if (SPIFFS.exists(path)) { // If the file exists
|
||||
File file = SPIFFS.open(path, "r"); // Open it
|
||||
size_t sent = server.streamFile(file, contentType); // And send it to the client
|
||||
file.close(); // Then close the file again
|
||||
return true;
|
||||
}
|
||||
DebugPort.println("\tFile Not Found");
|
||||
return false; // If the file doesn't exist, return false
|
||||
}
|
||||
|
||||
/*void handleFavIcon() {
|
||||
handleFileRead("/favicon.ico");
|
||||
}*/
|
||||
|
||||
void handleBTCRoot() {
|
||||
handleFileRead("/index.html");
|
||||
/* if(SPIFFS.exists("/index.html")) {
|
||||
File html = SPIFFS.open("/index.html");
|
||||
server.streamFile(html, "text/html");
|
||||
html.close();
|
||||
}
|
||||
else {
|
||||
DebugPort.println("\"/index.html\" does not exist!!!");
|
||||
}*/
|
||||
}
|
||||
#else
|
||||
void handleBTCRoot() {
|
||||
String s = MAIN_PAGE; //Read HTML contents
|
||||
server.send(200, "text/html", s); //Send web page
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void handleWMConfig() {
|
||||
server.send(200, "text/plain", "Start Config Portal - Retaining credential");
|
||||
DebugPort.println("Starting web portal for wifi config");
|
||||
delay(500);
|
||||
// wm.startWebPortal();
|
||||
wifiEnterConfigPortal(true, false, 3000);
|
||||
}
|
||||
|
||||
void handleReset() {
|
||||
server.send(200, "text/plain", "Start Config Portal - Resetting Wifi credentials!");
|
||||
DebugPort.println("diconnecting client and wifi, then rebooting");
|
||||
delay(500);
|
||||
//client.disconnect();
|
||||
// wifi_station_disconnect();
|
||||
// wm.disconnect();
|
||||
// wm.resetSettings();
|
||||
wifiEnterConfigPortal(true, true, 3000);
|
||||
}
|
||||
|
||||
void handleFormat() {
|
||||
server.send(200, "text/plain", "Formatting SPIFFS partition!");
|
||||
DebugPort.println("Formatting SPIFFS partition");
|
||||
delay(500);
|
||||
SPIFFS.format();
|
||||
//client.disconnect();
|
||||
// wifi_station_disconnect();
|
||||
// wm.disconnect();
|
||||
// wm.resetSettings();
|
||||
}
|
||||
|
||||
void handleBTCNotFound() {
|
||||
digitalWrite(led, 1);
|
||||
String message = "File Not Found\n\n";
|
||||
message += "URI: ";
|
||||
message += server.uri();
|
||||
message += "\nMethod: ";
|
||||
message += (server.method() == HTTP_GET) ? "GET" : "POST";
|
||||
message += "\nArguments: ";
|
||||
message += server.args();
|
||||
message += "\n";
|
||||
for (uint8_t i = 0; i < server.args(); i++) {
|
||||
message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
|
||||
}
|
||||
server.send(404, "text/plain", message);
|
||||
digitalWrite(led, 0);
|
||||
}
|
||||
|
||||
void initWebServer(void) {
|
||||
|
||||
|
||||
if (MDNS.begin("BTCHeater")) {
|
||||
DebugPort.println("MDNS responder started");
|
||||
}
|
||||
|
||||
// server.on("/", handleBTCRoot);
|
||||
|
||||
server.on("/wmconfig", handleWMConfig);
|
||||
server.on("/resetwifi", handleReset);
|
||||
server.on("/formatspiffs", handleFormat);
|
||||
#if USE_SPIFFS == 1
|
||||
// NOTE: this serves the default home page, and favicon.ico
|
||||
server.onNotFound([]()
|
||||
{ // If the client requests any URI
|
||||
if (!handleFileRead(server.uri())) // send it if it exists
|
||||
server.send(404, "text/plain", "404: Not Found"); // otherwise, respond with a 404 (Not Found) error
|
||||
}
|
||||
);
|
||||
#else
|
||||
server.onNotFound(handleBTCNotFound);
|
||||
#endif
|
||||
|
||||
server.begin();
|
||||
webSocket.begin();
|
||||
webSocket.onEvent(webSocketEvent);
|
||||
DebugPort.println("HTTP server started");
|
||||
|
||||
}
|
||||
|
||||
unsigned char cVal;
|
||||
|
||||
// called my main sketch loop()
|
||||
bool doWebServer(void) {
|
||||
webSocket.loop();
|
||||
server.handleClient();
|
||||
}
|
||||
|
||||
bool isWebServerClientChange()
|
||||
{
|
||||
static int prevNumClients = -1;
|
||||
|
||||
int numClients = webSocket.connectedClients();
|
||||
if(numClients != prevNumClients) {
|
||||
prevNumClients = numClients;
|
||||
DebugPort.println("Changed number of web clients, should reset JSON moderator");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool sendWebServerString(const char* Str)
|
||||
{
|
||||
unsigned long tStart = millis();
|
||||
if(webSocket.connectedClients()) {
|
||||
unsigned long tCon = millis() - tStart;
|
||||
tStart = millis();
|
||||
bTxWebData = true; // OLED tx data animation flag
|
||||
webSocket.broadcastTXT(Str);
|
||||
unsigned long tWeb = millis() - tStart;
|
||||
// DebugPort.print("Websend times : "); DebugPort.print(tCon); DebugPort.print(","); DebugPort.println(tWeb);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) {
|
||||
if (type == WStype_TEXT) {
|
||||
bRxWebData = true;
|
||||
char cmd[256];
|
||||
memset(cmd, 0, 256);
|
||||
for (int i = 0; i < length && i < 256; i++) {
|
||||
cmd[i] = payload[i];
|
||||
}
|
||||
interpretJsonCommand(cmd); // send to the main heater controller decode routine
|
||||
}
|
||||
}
|
||||
|
||||
bool hasWebClientSpoken(bool reset)
|
||||
{
|
||||
bool retval = bRxWebData;
|
||||
if(reset)
|
||||
bRxWebData = false;
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool hasWebServerSpoken(bool reset)
|
||||
{
|
||||
bool retval = bTxWebData;
|
||||
if(reset)
|
||||
bTxWebData = false;
|
||||
return retval;
|
||||
}
|
||||
|
|
@ -1,331 +0,0 @@
|
|||
/*
|
||||
* This file is part of the "bluetoothheater" distribution
|
||||
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
|
||||
*
|
||||
* Copyright (C) 2019 Ray Jones
|
||||
* Copyright (C) 2019 James Clark
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
// Should be working - Jimmy C
|
||||
#include "BTCWifi.h"
|
||||
#include "../Utility/DebugPort.h"
|
||||
#include <DNSServer.h>
|
||||
#include "../OLED/ScreenManager.h"
|
||||
|
||||
#include "esp_system.h"
|
||||
#include <Preferences.h>
|
||||
#include "../Utility/NVStorage.h"
|
||||
|
||||
#define USE_AP
|
||||
|
||||
// function to control the behaviour upon reboot if no wifi manager credentials exist
|
||||
// or connection fails
|
||||
void prepBootIntoConfigPortal(bool state);
|
||||
bool shouldBootIntoConfigPortal();
|
||||
void saveParamsCallback();
|
||||
void APstartedCallback(WiFiManager*);
|
||||
|
||||
WiFiManager wm;
|
||||
|
||||
bool isPortalAP = false; // true if config portal is running
|
||||
bool isSTA = false; // true if connected to an access point
|
||||
int TRIG_PIN; // pin that triggers the configuration portal when set to LOW
|
||||
unsigned restartServer = 0; // set to time of portal reconfig - will cause reboot a while later
|
||||
char MACstr[2][20]; // MACstr[0] STA, MACstr[1] = AP
|
||||
int wifiButtonState = 0;
|
||||
|
||||
extern CScreenManager ScreenManager;
|
||||
|
||||
bool initWifi(int initpin,const char *failedssid, const char *failedpassword)
|
||||
{
|
||||
TRIG_PIN = initpin;
|
||||
pinMode(TRIG_PIN, INPUT_PULLUP);
|
||||
|
||||
// report the MAC addresses - note individual values for STA and AP modes
|
||||
uint8_t MAC[6];
|
||||
esp_read_mac(MAC, ESP_MAC_WIFI_STA);
|
||||
sprintf(MACstr[0], "%02X:%02X:%02X:%02X:%02X:%02X", MAC[0], MAC[1], MAC[2], MAC[3], MAC[4], MAC[5]);
|
||||
DebugPort.print(" STA MAC address: "); DebugPort.println(MACstr[0]);
|
||||
esp_read_mac(MAC, ESP_MAC_WIFI_SOFTAP);
|
||||
sprintf(MACstr[1], "%02X:%02X:%02X:%02X:%02X:%02X", MAC[0], MAC[1], MAC[2], MAC[3], MAC[4], MAC[5]);
|
||||
DebugPort.print(" AP MAC address: "); DebugPort.println(MACstr[1]);
|
||||
|
||||
char APname[32];
|
||||
sprintf(APname, "%s", failedssid);
|
||||
|
||||
//reset settings - wipe credentials for testing
|
||||
// wm.resetSettings();
|
||||
|
||||
// Automatically connect using saved credentials:
|
||||
// WiFiManager will prepare a link connection, using stored credentials if available.
|
||||
//
|
||||
// NO CREDENTIALS:
|
||||
// Using a stored NV variable, we control the link creation via wm.setEnableConfigPortal():
|
||||
// true - SoftAP is created (SSID = failedssid), and linked to the config portal
|
||||
// false - we need to create a Soft AP, the portal does not start, we provide a web server
|
||||
//
|
||||
// WITH CREDENTIALS:
|
||||
//
|
||||
// Connected to stored AP, AP provides an IP address to use, we are STA (station)
|
||||
// failed to connect to stored AP, using a stored NV variable we control the behaviour via wm.setEnableConfigPortal():
|
||||
// true - SoftAP is created (SSID = failedssid), and linked to the config portal
|
||||
// false - we need to create a Soft AP, the portal does not start, we provide a web server
|
||||
|
||||
DebugPort.println("Attempting to start STA mode (or config portal) via WifiManager...");
|
||||
|
||||
// wm.setHostname(failedssid);
|
||||
wm.setHostname(APname);
|
||||
wm.setConfigPortalTimeout(20);
|
||||
wm.setConfigPortalBlocking(false);
|
||||
wm.setSaveParamsCallback(saveParamsCallback); // ensure our webserver gets awoken when IP config changes to STA
|
||||
wm.setAPCallback(APstartedCallback);
|
||||
wm.setEnableConfigPortal(shouldBootIntoConfigPortal());
|
||||
//REMOVED - UNSTABLE WHETHER WE GET 192.168.4.1 or 192.168.100.1 ????
|
||||
// REMOVED wm.setAPStaticIPConfig(IPAddress(192, 168, 100, 1), IPAddress(192, 168, 100, 1), IPAddress(255,255,255,0));
|
||||
|
||||
// bool res = wm.autoConnect(failedssid, failedpassword); // auto generated AP name from chipid
|
||||
bool res = wm.autoConnect(APname, failedpassword); // auto generated AP name from chipid
|
||||
DebugPort.print("WifiMode after autoConnect = "); DebugPort.println(WiFi.getMode());
|
||||
|
||||
int chnl = 1;
|
||||
bool retval = false;
|
||||
if(!res) {
|
||||
// failed STA mode
|
||||
DebugPort.println("WiFimanager failed STA connection. Setting up AP...");
|
||||
WiFi.disconnect(); // apparently needed for AP only OTA to reboot properly!!!
|
||||
}
|
||||
else {
|
||||
// runs through here if STA connected OK
|
||||
// if you get here you have connected to the WiFi
|
||||
isSTA = true;
|
||||
DebugPort.println("WiFiManager connected in STA mode OK");
|
||||
DebugPort.print(" STA IP address: "); DebugPort.println(WiFi.localIP());
|
||||
// must use same radio channel as STA to go to STA+AP, otherwise we drop the STA!
|
||||
chnl = WiFi.channel();
|
||||
DebugPort.print("Now promoting to STA+AP mode");
|
||||
retval = true;
|
||||
}
|
||||
#ifdef USE_AP
|
||||
// always setup an AP - for STA+AP mode we *must* use the same RF channel as STA
|
||||
DebugPort.println("Starting AP mode");
|
||||
//REMOVED - UNSTABLE WHETHER WE GET 192.168.4.1 or 192.168.100.1 ????
|
||||
// REMOVED WiFi.softAPConfig(IPAddress(192, 168, 100, 1), IPAddress(192, 168, 100, 1), IPAddress(255,255,255,0));
|
||||
// WiFi.softAP(failedssid, failedpassword, chnl);
|
||||
WiFi.softAP(APname, failedpassword, chnl);
|
||||
WiFi.enableAP(true);
|
||||
DebugPort.print(" AP SSID: "); DebugPort.println(WiFi.softAPgetHostname());
|
||||
DebugPort.print(" AP IP address: "); DebugPort.println(WiFi.softAPIP());
|
||||
DebugPort.print("WifiMode after initWifi = "); DebugPort.println(WiFi.getMode());
|
||||
#endif
|
||||
|
||||
// even though we may have started in STA mode - start the config portal if demanded via the NV flag
|
||||
if(shouldBootIntoConfigPortal()) {
|
||||
DebugPort.println("Manually starting web portal");
|
||||
wm.startWebPortal();
|
||||
isPortalAP = true; // we started portal, we have to flag it!
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
// call from main sketch loop()
|
||||
void doWiFiManager()
|
||||
{
|
||||
wm.process();
|
||||
|
||||
|
||||
// manage handling of pin to enter WiFManager config portal
|
||||
// we typically use the BOOT pin for this (pins.h)
|
||||
//
|
||||
// Quick Press (< 1 sec) - enable config portal
|
||||
// > 1 second (< 5 sec) press - disable config portal
|
||||
// > 5 second press - erase credentials, enable config portal
|
||||
static bool pinDown = false;
|
||||
static long pinTime = 0;
|
||||
unsigned long tDelta;
|
||||
|
||||
if(digitalRead(TRIG_PIN) == LOW) {
|
||||
if(!pinDown) {
|
||||
pinTime = millis();
|
||||
ScreenManager.reqUpdate();
|
||||
}
|
||||
pinDown = true;
|
||||
// track hold duration - change OLED Wifi annotation according to length of press
|
||||
tDelta = millis() - pinTime;
|
||||
if(tDelta > 5000)
|
||||
wifiButtonState = 3; // we will show 'ERS' on OLED!
|
||||
else if(tDelta > 1000)
|
||||
wifiButtonState = 2; // we will show 'HTR' on OLED!
|
||||
else
|
||||
wifiButtonState = 1; // we will show 'CFG' on OLED!
|
||||
}
|
||||
else {
|
||||
if(pinDown) {
|
||||
pinDown = false;
|
||||
tDelta = millis() - pinTime;
|
||||
DebugPort.print("Wifi config button tDelta = "); DebugPort.println(tDelta);
|
||||
// > 5 second press?
|
||||
if(tDelta > 5000) {
|
||||
wifiEnterConfigPortal(true, true); // very long press - clear credentials, reboot into portal
|
||||
}
|
||||
// > 1 second press?
|
||||
else if(tDelta > 1000) {
|
||||
wifiEnterConfigPortal(false); // long press - reboot into web server
|
||||
}
|
||||
// > 50ms press?
|
||||
else if(tDelta > 50) {
|
||||
wifiEnterConfigPortal(true); // quick press - reboot into portal
|
||||
}
|
||||
// consider as contact bounce if < 50ms!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void wifiDisable(long rebootDelay)
|
||||
{
|
||||
NVstore.setWifiEnabled(0);
|
||||
NVstore.save();
|
||||
|
||||
DebugPort.println("*** Disabling WiFi ***");
|
||||
|
||||
restartServer = (millis() + rebootDelay) | 1; // prepare to reboot in the future - ensure non zero!
|
||||
|
||||
const char* content[2];
|
||||
content[0] = "WiFi Mode \032 DISABLED";
|
||||
content[1] = "";
|
||||
ScreenManager.showRebootMsg(content, rebootDelay);
|
||||
}
|
||||
|
||||
void wifiEnterConfigPortal(bool state, bool erase, long rebootDelay)
|
||||
{
|
||||
wm.disconnect();
|
||||
|
||||
NVstore.setWifiEnabled(1);
|
||||
NVstore.save();
|
||||
|
||||
prepBootIntoConfigPortal(state);
|
||||
|
||||
const char* content[2];
|
||||
|
||||
if(isWifiSTA() && !erase)
|
||||
content[0] = "WiFi Mode \032 STA+AP";
|
||||
else
|
||||
content[0] = "WiFi Mode \032 AP only";
|
||||
|
||||
if(erase) {
|
||||
wm.resetSettings();
|
||||
DebugPort.println("*** Erased wifi credentials ***");
|
||||
}
|
||||
|
||||
if(state) {
|
||||
DebugPort.println("*** Rebooting into config portal ***");
|
||||
content[1] = "Web \032 Config Portal";
|
||||
}
|
||||
else {
|
||||
DebugPort.println("*** Rebooting into web server ***");
|
||||
content[1] = "Web \032 Heater control";
|
||||
}
|
||||
|
||||
restartServer = (millis() + rebootDelay) | 1; // prepare to reboot in the future - ensure non zero!
|
||||
|
||||
ScreenManager.showRebootMsg(content, rebootDelay);
|
||||
}
|
||||
|
||||
// callback is invoked by WiFiManager after new credentials are saved and verified
|
||||
void saveParamsCallback()
|
||||
{
|
||||
wifiEnterConfigPortal(false); // stop config portal, reboot
|
||||
}
|
||||
|
||||
// callback called if the WiFiManager started the config portal
|
||||
void APstartedCallback(WiFiManager*)
|
||||
{
|
||||
isPortalAP = true; // will add CFG adornment to OLED WiFi icon
|
||||
}
|
||||
|
||||
const char* getWifiAPAddrStr()
|
||||
{
|
||||
noInterrupts();
|
||||
IPAddress IPaddr = WiFi.softAPIP(); // use stepping stone - function returns an automatic stack var - LAME!
|
||||
interrupts();
|
||||
return IPaddr.toString().c_str();
|
||||
}
|
||||
|
||||
const char* getWifiSTAAddrStr()
|
||||
{
|
||||
noInterrupts();
|
||||
IPAddress IPaddr = WiFi.localIP(); // use stepping stone - function returns an automatic stack var - LAME!
|
||||
interrupts();
|
||||
return IPaddr.toString().c_str();
|
||||
}
|
||||
|
||||
const char* getWifiAPMACStr()
|
||||
{
|
||||
return MACstr[1];
|
||||
}
|
||||
|
||||
const char* getWifiSTAMACStr()
|
||||
{
|
||||
return MACstr[0];
|
||||
}
|
||||
|
||||
bool isWifiConnected()
|
||||
{
|
||||
return WiFi.status() == WL_CONNECTED;
|
||||
}
|
||||
|
||||
bool isWifiAP()
|
||||
{
|
||||
int mode = WiFi.getMode();
|
||||
return !isSTA && ((mode & WIFI_MODE_AP) != 0);
|
||||
}
|
||||
|
||||
bool isWifiSTA()
|
||||
{
|
||||
return isSTA; // true: STAtion mode link is active
|
||||
}
|
||||
|
||||
bool isWifiConfigPortal()
|
||||
{
|
||||
return isPortalAP; // true: config portal is running
|
||||
}
|
||||
|
||||
// save an NV flag to determine whether config portal should run after reboot
|
||||
void prepBootIntoConfigPortal(bool state)
|
||||
{
|
||||
Preferences NV;
|
||||
NV.begin("user");
|
||||
NV.putBool("bootPortal", state);
|
||||
NV.end();
|
||||
DebugPort.print("Setting boot config portal if WiFiManager fails = "); DebugPort.println(state);
|
||||
}
|
||||
|
||||
// test the NV flag whether the config portal should run after reboot
|
||||
bool shouldBootIntoConfigPortal()
|
||||
{
|
||||
Preferences NV;
|
||||
NV.begin("user");
|
||||
bool retval = NV.getBool("bootPortal", false);
|
||||
NV.end();
|
||||
DebugPort.print("Boot config portal if WiFiManager fails = "); DebugPort.println(retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
int isWifiButton()
|
||||
{
|
||||
return wifiButtonState;
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* This file is part of the "bluetoothheater" distribution
|
||||
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
|
||||
*
|
||||
* Copyright (C) 2018 James Clark
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __BTCWIFI_H__
|
||||
#define __BTCWIFI_H__
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <WiFiManager.h>
|
||||
#include <WiFi.h>
|
||||
|
||||
void doWiFiManager();
|
||||
bool initWifi(int initpin,const char *failedssid, const char *failedpassword);
|
||||
const char* getWifiAPAddrStr();
|
||||
const char* getWifiSTAAddrStr();
|
||||
const char* getWifiAPMACStr();
|
||||
const char* getWifiSTAMACStr();
|
||||
bool isWifiConnected();
|
||||
bool isWifiAP();
|
||||
bool isWifiSTA();
|
||||
bool isWifiConfigPortal();
|
||||
bool isWebClientConnected();
|
||||
bool hasWebClientSpoken(bool reset = false);
|
||||
bool hasWebServerSpoken(bool reset = false);
|
||||
void wifiEnterConfigPortal(bool state, bool erase = false, long timeout = 7000);
|
||||
void wifiDisable(long rebootDelay = 7000);
|
||||
int isWifiButton();
|
||||
|
||||
#endif __BTCWIFI_H__
|
|
@ -1,86 +0,0 @@
|
|||
/*
|
||||
* This file is part of the "bluetoothheater" distribution
|
||||
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
|
||||
*
|
||||
* Copyright (C) 2018 James Clark
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "BTCota.h"
|
||||
#include "../cfg/BTCConfig.h"
|
||||
#if USE_SPIFFS == 1
|
||||
#include <SPIFFS.h>
|
||||
#endif
|
||||
extern void ShowOTAScreen(int percent=0);
|
||||
|
||||
|
||||
#include <esp_int_wdt.h>
|
||||
#include <esp_task_wdt.h>
|
||||
|
||||
void hard_restart() {
|
||||
esp_task_wdt_init(1,true);
|
||||
esp_task_wdt_add(NULL);
|
||||
while(true);
|
||||
}
|
||||
|
||||
void initOTA(){
|
||||
// ArduinoOTA.setHostname("myesp32");
|
||||
ArduinoOTA.setHostname("BTCOTA");
|
||||
|
||||
ArduinoOTA
|
||||
.onStart([]() {
|
||||
String type;
|
||||
if (ArduinoOTA.getCommand() == U_FLASH)
|
||||
type = "sketch";
|
||||
else // U_SPIFFS
|
||||
type = "filesystem";
|
||||
|
||||
// NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
|
||||
SPIFFS.end();
|
||||
DebugPort.println("Start updating " + type);
|
||||
DebugPort.handle(); // keep telnet spy alive
|
||||
ShowOTAScreen();
|
||||
|
||||
})
|
||||
.onEnd([]() {
|
||||
DebugPort.println("\nEnd");
|
||||
DebugPort.handle(); // keep telnet spy alive
|
||||
delay(100);
|
||||
// DebugPort.end(); // force graceful close of telnetspy - ensures a client will reconnect cleanly
|
||||
})
|
||||
.onProgress([](unsigned int progress, unsigned int total) {
|
||||
int percent = (progress / (total / 100));
|
||||
DebugPort.printf("Progress: %u%%\r", percent);
|
||||
DebugPort.handle(); // keep telnet spy alive
|
||||
ShowOTAScreen(percent);
|
||||
|
||||
})
|
||||
.onError([](ota_error_t error) {
|
||||
DebugPort.printf("Error[%u]: ", error);
|
||||
if (error == OTA_AUTH_ERROR) DebugPort.println("Auth Failed");
|
||||
else if (error == OTA_BEGIN_ERROR) DebugPort.println("Begin Failed");
|
||||
else if (error == OTA_CONNECT_ERROR) DebugPort.println("Connect Failed");
|
||||
else if (error == OTA_RECEIVE_ERROR) DebugPort.println("Receive Failed");
|
||||
else if (error == OTA_END_ERROR) DebugPort.println("End Failed");
|
||||
DebugPort.handle(); // keep telnet spy alive
|
||||
});
|
||||
|
||||
ArduinoOTA.begin();
|
||||
}
|
||||
|
||||
void DoOTA(){
|
||||
ArduinoOTA.handle();
|
||||
};
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
* This file is part of the "bluetoothheater" distribution
|
||||
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
|
||||
*
|
||||
* Copyright (C) 2018 Ray Jones <ray@mrjones.id.au>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <driver/adc.h>
|
||||
|
||||
const uint8_t UART_Tx = 1;
|
||||
const uint8_t LED_Pin = 2;
|
||||
const uint8_t UART_Rx = 3;
|
||||
const uint8_t HC05_KeyPin = 4;
|
||||
const uint8_t TxEnbPin = 5;
|
||||
const uint8_t Tx433MHz_pin = 12; // HSPI std pins
|
||||
const uint8_t Rx433MHz_pin = 13; // "
|
||||
const uint8_t GPIOout2_pin = 14; // "
|
||||
const uint8_t DS18B20_Pin = 15;
|
||||
const uint8_t Rx1Pin = 16;
|
||||
const uint8_t Tx1Pin = 17;
|
||||
const uint8_t Tx2Pin = 18;
|
||||
const uint8_t Rx2Pin = 19;
|
||||
const uint8_t OLED_SDA_pin = 21; // I2C std pins
|
||||
const uint8_t OLED_SCL_pin = 22; // "
|
||||
const uint8_t HC05_SensePin = 23;
|
||||
const uint8_t GPIOin2_pin = 25;
|
||||
const uint8_t GPIOin1_pinV21V10 = 26;
|
||||
const adc2_channel_t GPIOalg_pinINVALID = ADC2_CHANNEL_9; // GPIO 26 - Cannot use ADC2 with WiFi enabled!!!
|
||||
const uint8_t GPIOout1_pin = 27;
|
||||
|
||||
const uint8_t keyUp_pin = 32;
|
||||
const uint8_t GPIOin1_pinV20 = 33;
|
||||
const adc1_channel_t GPIOalg_pin = ADC1_CHANNEL_5; // GPIO 33 - OK with Wifi, ADC1 channel
|
||||
const uint8_t keyDown_pin = 34; // input only, no chip pullup
|
||||
const uint8_t keyCentre_pin = 35; // input only, no chip pullup
|
||||
const uint8_t keyRight_pin = 36; // input only, no chip pullup
|
||||
const uint8_t keyLeft_pin = 39; // input only, no chip pullup
|
||||
|
||||
//const uint8_t ListenOnlyPin = 33;
|
||||
const uint8_t WiFi_TriggerPin = 0; // BOOT switch!
|
||||
|
BIN
Bootload/Afterburner.partitions.bin
Normal file
BIN
Bootload/AfterburnerV3.1.9.bin
Normal file
|
@ -1 +1,5 @@
|
|||
esptool.exe --chip esp32 --port COM11 --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 80m --flash_size detect 0xe000 boot_app0.bin 0x1000 bootloader_qio_80m.bin 0x10000 Afterburner.bin 0x8000 Afterburner.partitions.bin
|
||||
REM Firmware
|
||||
esptool.exe --chip esp32 --port COM5 --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 80m --flash_size detect 0xe000 boot_app0.bin 0x1000 bootloader_qio_80m.bin 0x10000 AfterburnerV3.1.9.bin 0x8000 Afterburner.partitions.bin
|
||||
REM SPIFFS
|
||||
esptool.exe --chip esp32 --port COM5 --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_size detect 0x3d0000 spiffs.bin
|
||||
|
||||
|
|
22
Bootload/Checklist.txt
Normal file
|
@ -0,0 +1,22 @@
|
|||
Afterburner operation checklist
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
OLED intact
|
||||
Latest firmware uploaded
|
||||
SPIFFS uploaded
|
||||
Check temperature sensor
|
||||
Keypad functions OK
|
||||
Indicator LEDs function
|
||||
Web server functions and serves heater control page
|
||||
Bluetooth pairs and streams SPP data
|
||||
Set time
|
||||
Install battery
|
||||
|
||||
GPIO units only
|
||||
~~~~~~~~~~~~~~~
|
||||
Check pressure sensor
|
||||
GPIO functions:
|
||||
Input x2
|
||||
Output x2
|
||||
Analogue
|
||||
|
|
@ -1 +1 @@
|
|||
espota.exe -i 192.168.20.100 -p 3232 --auth= -f Afterburner.bin
|
||||
espota.exe -i 192.168.1.1 -p 3232 --auth= -f AfterburnerV3.0.1.bin
|
||||
|
|
1
Bootload/OTA_AP.bat
Normal file
|
@ -0,0 +1 @@
|
|||
espota.exe -i 192.168.4.1 -p 3232 --auth= -f AfterburnerV3.0.1.bin
|
BIN
Bootload/boot_app0.bin
Normal file
BIN
Bootload/bootloader_qio_80m.bin
Normal file
16
BuildREADME.txt
Normal file
|
@ -0,0 +1,16 @@
|
|||
This directory structure includes an Arduino path, and a src path.
|
||||
|
||||
The Arduino path is only to support builing with the restrictive Arduino IDE.
|
||||
The src path is for the awesome PlatformIO under VScode.
|
||||
Use it, you will not regret it.
|
||||
|
||||
Arduino builds are sloooooowwwww.
|
||||
Do it that way if you must, but seriously don't!
|
||||
PlatformIO rocks - just load the root repo directory with PIO in VScode
|
||||
and away you go.
|
||||
|
||||
The Arduino\Afterburner\Afterburner.ino file is a hard symbolic link to the
|
||||
proper src\Afterburner\Afterburner.cpp file.
|
||||
|
||||
Likewise the Arduino\Afterburner\src and Arduino\Afterburner\data paths are
|
||||
hard junctions to the src\Afterburner\src and src\Afterburner\data files.
|
BIN
CRCgen/AfterBurnerCRC.cpp
Normal file
11
CRCgen/Readme.txt
Normal file
|
@ -0,0 +1,11 @@
|
|||
AfterburnerCRC.cpp is used to append a CRC-16 value to the
|
||||
compiled binary file.
|
||||
|
||||
This CRC is used to confirm the binary image uploaded to the
|
||||
Afterburner was genuinely intended for the Afterburner.
|
||||
|
||||
Naively attempting to upload the direct compiled output binary
|
||||
will result in rejection of the upload attempt.
|
||||
|
||||
You will need to compile Afterburner.cpp and copy the resultant
|
||||
executable to the repository root (adjacent to plaformio.ini)
|
BIN
Documentation/20181220_122310.jpg
Normal file
After Width: | Height: | Size: 157 KiB |
BIN
Documentation/20181220_123008.jpg
Normal file
After Width: | Height: | Size: 3.8 MiB |
BIN
Documentation/20181220_123137.jpg
Normal file
After Width: | Height: | Size: 4.3 MiB |
BIN
Documentation/20181220_123410.jpg
Normal file
After Width: | Height: | Size: 3.4 MiB |
BIN
Documentation/20181220_123436.jpg
Normal file
After Width: | Height: | Size: 4.5 MiB |
BIN
Documentation/20181220_131828.jpg
Normal file
After Width: | Height: | Size: 933 KiB |
BIN
Documentation/20190110_201613.jpg
Normal file
After Width: | Height: | Size: 262 KiB |
BIN
Documentation/20190111_083207.jpg
Normal file
After Width: | Height: | Size: 122 KiB |
BIN
Documentation/20190111_124322.jpg
Normal file
After Width: | Height: | Size: 570 KiB |
BIN
Documentation/20190111_133926.jpg
Normal file
After Width: | Height: | Size: 4.8 MiB |
BIN
Documentation/20190111_134737.jpg
Normal file
After Width: | Height: | Size: 476 KiB |
BIN
Documentation/20190226_185402.jpg
Normal file
After Width: | Height: | Size: 55 KiB |
BIN
Documentation/20190226_190048.jpg
Normal file
After Width: | Height: | Size: 92 KiB |
BIN
Documentation/20190323_095325.jpg
Normal file
After Width: | Height: | Size: 604 KiB |
BIN
Documentation/3pinplug.jpg
Normal file
After Width: | Height: | Size: 449 KiB |
BIN
Documentation/3pinplugcircular.jpg
Normal file
After Width: | Height: | Size: 580 KiB |
After Width: | Height: | Size: 43 KiB |
BIN
Documentation/56161804_427457621343959_2334075276654280704_n.jpg
Normal file
After Width: | Height: | Size: 635 KiB |
BIN
Documentation/6a00d8341c5c8953ef0154379fb397970c-800wi.jpg
Normal file
After Width: | Height: | Size: 198 KiB |
BIN
Documentation/BTC1.jpg
Normal file
After Width: | Height: | Size: 427 KiB |
BIN
Documentation/BTC2.jpg
Normal file
After Width: | Height: | Size: 228 KiB |
BIN
Documentation/BTCavatar.jpg
Normal file
After Width: | Height: | Size: 133 KiB |
BIN
Documentation/Battery.jpg
Normal file
After Width: | Height: | Size: 1.2 MiB |
BIN
Documentation/Battery2.jpg
Normal file
After Width: | Height: | Size: 476 KiB |
BIN
Documentation/BlackHeaterControlBoard.PNG
Normal file
After Width: | Height: | Size: 625 KiB |
BIN
Documentation/BlackLCD.jpg
Normal file
After Width: | Height: | Size: 395 KiB |
BIN
Documentation/BlueLCD.jpg
Normal file
After Width: | Height: | Size: 3.4 MiB |