2018-12-16 07:38:34 +00:00
/*
* This file is part of the " bluetoothheater " distribution
* ( https : //gitlab.com/mrjones.id.au/bluetoothheater)
*
2019-09-08 00:14:36 +00:00
* Copyright ( C ) 2019 Ray Jones < ray @ mrjones . id . au >
2018-12-16 07:38:34 +00:00
* 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/>.
*
*/
/*
Chinese Heater Half Duplex Serial Data Sending Tool
Connects to the blue wire of a Chinese heater , which is the half duplex serial link .
Sends and receives data from hardware serial port 1.
Terminology : Tx is to the heater unit , Rx is from the heater unit .
Typical data frame timing on the blue wire is :
__Tx_Rx____________________________Tx_Rx____________________________Tx_Rx___________
This software can connect to the blue wire in a normal OEM system , detecting the
OEM controller and allowing extraction of the data or injecting on / off commands .
If Pin 21 is grounded on the Due , this simple stream will be reported over Serial and
no control from the Arduino will be allowed .
This allows passive sniffing of the blue wire in a normal system .
The binary data is received from the line .
If it has been > 100 ms since the last blue wire activity this indicates a new frame
sequence is starting from the OEM controller .
Synchronise as such then count off the next 24 bytes storing them in the Controller ' s
data array . These bytes are then reported over Serial to the PC in ASCII .
It is then expected the heater will respond with it ' s 24 bytes .
Capture those bytes and store them in the Heater1 data array .
Once again these bytes are then reported over Serial to the PC in ASCII .
If no activity is sensed in a second , it is assumed no OEM controller is attached and we
have full control over the heater .
Either way we can now inject a message onto the blue wire allowing our custom
on / off control .
We must remain synchronous with an OEM controller if it exists otherwise E - 07
faults will be caused .
Typical data frame timing on the blue wire is then :
__OEMTx_HtrRx__OurTx_HtrRx____________OEMTx_HtrRx__OurTx_HtrRx____________OEMTx_HtrRx__OurTx_HtrRx_________
The second HtrRx to the next OEMTx delay is always > 100 ms and is paced by the OEM controller .
The delay before seeing Heater Rx data after any Tx is usually much less than 10 ms .
But this does rise if new max / min or voltage settings are sent .
* * The heater only ever sends Rx data in response to a data frame from a controller * *
For Bluetooth connectivity , a HC - 05 Bluetooth module is attached to Serial2 :
TXD - > Rx2 ( pin 17 )
RXD - > Tx2 ( pin 16 )
EN ( key ) - > pin 15
STATE - > pin 4
This code only works with boards that have more than one hardware serial port like Arduino
Mega , Due , Zero , ESP32 etc .
The circuit :
- a Tx Rx multiplexer is required to combine the Arduino ' s Tx1 And Rx1 pins onto the blue wire .
- a Tx Enable signal from pin 22 controls the multiplexer , high for Tx , low for Rx
- Serial logging software on Serial0 via USB link
created 23 Sep 2018 by Ray Jones
This example code is in the public domain .
*/
2020-01-04 21:46:46 +00:00
# include "WiFi/ABMQTT.h"
2019-07-23 12:32:36 +00:00
# include "cfg/BTCConfig.h"
# include "cfg/pins.h"
# include "RTC/Timers.h"
# include "RTC/Clock.h"
2019-07-24 09:25:07 +00:00
# include "RTC/RTCStore.h"
2019-07-23 12:32:36 +00:00
# include "WiFi/BTCWifi.h"
# include "WiFi/BTCWebServer.h"
# include "WiFi/BTCota.h"
# include "Protocol/Protocol.h"
# include "Protocol/TxManage.h"
# include "Protocol/SmartError.h"
2020-03-23 05:54:15 +00:00
# include "Utility/helpers.h"
2019-07-23 12:32:36 +00:00
# include "Utility/NVStorage.h"
# include "Utility/DebugPort.h"
# include "Utility/macros.h"
# include "Utility/UtilClasses.h"
# include "Utility/BTC_JSON.h"
# include "Utility/BTC_GPIO.h"
# include "Utility/BoardDetect.h"
# include "Utility/FuelGauge.h"
# include "OLED/ScreenManager.h"
# include "OLED/KeyPad.h"
# include "Utility/TempSense.h"
# include "Utility/DataFilter.h"
2019-07-24 09:25:07 +00:00
# include "Utility/HourMeter.h"
2019-06-29 08:08:37 +00:00
# include <rom/rtc.h>
2019-06-25 07:49:07 +00:00
# include <esp_spiffs.h>
2019-01-20 10:14:45 +00:00
# include <SPIFFS.h>
2019-08-01 12:57:18 +00:00
# include <nvs.h>
2019-09-07 08:28:21 +00:00
# include "Utility/MQTTsetup.h"
2019-11-22 10:30:45 +00:00
# include <FreeRTOS.h>
2020-03-29 02:59:13 +00:00
# include "RTC/TimerManager.h"
2020-04-07 21:51:52 +00:00
# include "Utility/GetLine.h"
2020-04-11 08:49:52 +00:00
# include "Utility/DemandManager.h"
2020-04-24 23:23:16 +00:00
# include "Protocol/BlueWireTask.h"
2020-06-19 01:24:44 +00:00
# include "Protocol/433MHz.h"
2020-05-03 11:59:56 +00:00
# if USE_TWDT == 1
# include "esp_task_wdt.h"
# endif
2018-12-16 07:38:34 +00:00
2019-05-21 12:01:42 +00:00
// SSID & password now stored in NV storage - these are still the default values.
2019-05-16 11:12:29 +00:00
//#define AP_SSID "Afterburner"
//#define AP_PASSWORD "thereisnospoon"
2018-12-16 07:38:34 +00:00
2020-04-24 23:23:16 +00:00
// #define RX_DATA_TIMOUT 50
2018-12-16 07:38:34 +00:00
2020-03-23 05:54:15 +00:00
const int FirmwareRevision = 32 ;
2020-06-19 01:24:44 +00:00
const int FirmwareSubRevision = 1 ;
2020-06-22 02:15:57 +00:00
const int FirmwareMinorRevision = 0 ; // used for beta version - zero for releases
const char * FirmwareDate = " 22 Jun 2020 " ;
2019-04-19 11:38:39 +00:00
2020-05-03 11:59:56 +00:00
/*
* Macro to check the outputs of TWDT functions and trigger an abort if an
* incorrect code is returned .
*/
# define TWDT_TIMEOUT_S 15
# define CHECK_ERROR_CODE(returned, expected) ({ \
if ( returned ! = expected ) { \
printf ( " TWDT ERROR \n " ) ; \
abort ( ) ; \
} \
} )
2018-12-16 07:38:34 +00:00
# ifdef ESP32
2019-07-23 12:32:36 +00:00
# include "Bluetooth/BluetoothESP32.h"
2018-12-16 07:38:34 +00:00
# else
2019-07-23 12:32:36 +00:00
# include "Bluetooth/BluetoothHC05.h"
2018-12-16 07:38:34 +00:00
# endif
bool validateFrame ( const CProtocol & frame , const char * name ) ;
void checkDisplayUpdate ( ) ;
void checkDebugCommands ( ) ;
2020-05-13 00:37:31 +00:00
void manageStopStartMode ( ) ;
2019-04-04 10:48:05 +00:00
void manageCyclicMode ( ) ;
2019-10-31 22:24:58 +00:00
void manageFrostMode ( ) ;
2020-01-13 08:48:32 +00:00
void manageHumidity ( ) ;
2019-06-02 09:19:08 +00:00
void doStreaming ( ) ;
2019-06-15 23:09:29 +00:00
void heaterOn ( ) ;
void heaterOff ( ) ;
2020-04-24 23:23:16 +00:00
void updateFilteredData ( CProtocol & HeaterInfo ) ;
2019-08-31 07:34:56 +00:00
bool HandleMQTTsetup ( char rxVal ) ;
void showMainmenu ( ) ;
2020-04-26 06:15:08 +00:00
bool checkTemperatureSensors ( ) ;
void checkBlueWireEvents ( ) ;
2020-06-19 01:24:44 +00:00
void checkUHF ( ) ;
2018-12-16 07:38:34 +00:00
// DS18B20 temperature sensor support
2019-06-29 08:08:37 +00:00
// Uses the RMT timeslot driver to operate as a one-wire bus
2019-10-18 01:55:16 +00:00
//CBME280Sensor BMESensor;
2019-06-29 08:08:37 +00:00
CTempSense TempSensor ;
2018-12-16 07:38:34 +00:00
long lastTemperatureTime ; // used to moderate DS18B20 access
2019-01-11 05:40:25 +00:00
int DS18B20holdoff = 2 ;
2019-06-29 08:08:37 +00:00
2019-04-12 23:18:07 +00:00
int BoardRevision = 0 ;
2019-07-27 02:47:16 +00:00
bool bTestBTModule = false ;
2019-08-31 07:34:56 +00:00
bool bSetupMQTT = false ;
2020-04-20 03:39:39 +00:00
bool bReportStack = false ;
2018-12-16 07:38:34 +00:00
unsigned long lastAnimationTime ; // used to sequence updates to LCD for animation
2019-07-06 13:46:20 +00:00
sFilteredData FilteredSamples ;
2018-12-16 07:38:34 +00:00
CSmartError SmartError ;
CKeyPad KeyPad ;
CScreenManager ScreenManager ;
2019-10-27 03:25:40 +00:00
ABTelnetSpy DebugPort ;
2020-04-24 23:23:16 +00:00
2019-10-27 00:02:49 +00:00
# if USE_JTAG == 0
2019-11-10 04:44:54 +00:00
//CANNOT USE GPIO WITH JTAG DEBUG
2019-04-06 10:45:25 +00:00
CGPIOin GPIOin ;
2019-04-08 23:12:42 +00:00
CGPIOout GPIOout ;
2019-04-12 23:18:07 +00:00
CGPIOalg GPIOalg ;
2019-10-27 00:02:49 +00:00
# endif
2019-09-07 08:28:21 +00:00
CMQTTsetup MQTTmenu ;
2020-04-26 06:15:08 +00:00
CSecuritySetup SecurityMenu ;
2019-09-07 08:28:21 +00:00
2020-05-03 11:59:56 +00:00
TaskHandle_t handleWatchdogTask ;
TaskHandle_t handleBlueWireTask ;
2020-05-06 00:41:26 +00:00
extern TaskHandle_t handleWebServerTask ;
2019-07-18 12:28:40 +00:00
2019-06-29 08:08:37 +00:00
// these variables will persist over a soft reboot.
2019-07-24 20:06:47 +00:00
__NOINIT_ATTR float persistentRunTime ;
__NOINIT_ATTR float persistentGlowTime ;
2019-07-24 09:25:07 +00:00
2019-07-18 12:28:40 +00:00
CFuelGauge FuelGauge ;
2019-07-19 20:53:12 +00:00
CRTC_Store RTC_Store ;
2019-07-24 20:06:47 +00:00
CHourMeter * pHourMeter = NULL ;
2018-12-20 09:59:53 +00:00
2018-12-20 04:19:59 +00:00
bool bReportBlueWireData = REPORT_RAW_DATA ;
bool bReportJSONData = REPORT_JSON_TRANSMIT ;
2018-12-20 07:33:44 +00:00
bool bReportRecyleEvents = REPORT_BLUEWIRE_RECYCLES ;
2018-12-20 09:59:53 +00:00
bool bReportOEMresync = REPORT_OEM_RESYNC ;
2020-06-19 01:24:44 +00:00
bool pair433MHz = false ;
2018-12-16 07:38:34 +00:00
2020-04-24 23:23:16 +00:00
CProtocol BlueWireRxData ;
CProtocol BlueWireTxData ;
CProtocolPackage BlueWireData ;
2018-12-16 07:38:34 +00:00
bool bUpdateDisplay = false ;
bool bHaveWebClient = false ;
bool bBTconnected = false ;
2019-07-15 09:56:36 +00:00
long BootTime ;
2018-12-16 07:38:34 +00:00
////////////////////////////////////////////////////////////////////////////////////////////////////////
// Bluetooth instantiation
//
# ifdef ESP32
// Bluetooth options for ESP32
# if USE_HC05_BLUETOOTH == 1
CBluetoothESP32HC05 Bluetooth ( HC05_KeyPin , HC05_SensePin , Rx2Pin , Tx2Pin ) ; // Instantiate ESP32 using a HC-05
# elif USE_BLE_BLUETOOTH == 1
CBluetoothESP32BLE Bluetooth ; // Instantiate ESP32 BLE server
# elif USE_CLASSIC_BLUETOOTH == 1
CBluetoothESP32Classic Bluetooth ; // Instantiate ESP32 Classic Bluetooth server
# else // none selected
CBluetoothAbstract Bluetooth ; // default no bluetooth support - empty shell
# endif
# else // !ESP32
// Bluetooth for boards other than ESP32
# if USE_HC05_BLUETOOTH == 1
CBluetoothHC05 Bluetooth ( HC05_KeyPin , HC05_SensePin ) ; // Instantiate a HC-05
# else // none selected
CBluetoothAbstract Bluetooth ; // default no bluetooth support - empty shell
# endif // closing USE_HC05_BLUETOOTH
# endif // closing ESP32
//
// END Bluetooth instantiation
////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////
// setup Non Volatile storage
// this is very much hardware dependent, we can use the ESP32's FLASH
//
# ifdef ESP32
CESP32HeaterStorage actualNVstore ;
# else
CHeaterStorage actualNVstore ; // dummy, for now
# endif
// create reference to CHeaterStorage
// via the magic of polymorphism we can use this to access whatever
// storage is required for a specific platform in a uniform way
CHeaterStorage & NVstore = actualNVstore ;
//
////////////////////////////////////////////////////////////////////////////////////////////////////////
CBluetoothAbstract & getBluetoothClient ( )
{
return Bluetooth ;
}
2020-04-24 23:23:16 +00:00
char taskMsg [ BLUEWIRE_MSGQUEUESIZE ] ;
2020-04-26 06:15:08 +00:00
void checkBlueWireEvents ( )
2020-04-24 23:23:16 +00:00
{
2020-04-26 06:15:08 +00:00
// collect and report any debug messages from the blue wire task
2020-05-03 11:59:56 +00:00
if ( BlueWireMsgQueue & & xQueueReceive ( BlueWireMsgQueue , taskMsg , 0 ) )
2020-04-24 23:23:16 +00:00
DebugPort . print ( taskMsg ) ;
2020-04-26 06:15:08 +00:00
// check for complted data exchange from the blue wire task
if ( BlueWireSemaphore & & xSemaphoreTake ( BlueWireSemaphore , 0 ) ) {
updateJSONclients ( bReportJSONData ) ;
updateMQTT ( ) ;
NVstore . doSave ( ) ; // now is a good time to store to the NV storage, well away from any blue wire activity
}
// collect transmitted heater data from blue wire task
if ( BlueWireTxQueue & & xQueueReceive ( BlueWireTxQueue , BlueWireTxData . Data , 0 ) ) {
}
// collect and process received heater data from blue wire task
if ( BlueWireRxQueue & & xQueueReceive ( BlueWireRxQueue , BlueWireRxData . Data , 0 ) ) {
BlueWireData . set ( BlueWireRxData , BlueWireTxData ) ;
SmartError . monitor ( BlueWireRxData ) ;
updateFilteredData ( BlueWireRxData ) ;
FuelGauge . Integrate ( BlueWireRxData . getPump_Actual ( ) ) ;
if ( INBOUNDS ( BlueWireRxData . getRunState ( ) , 1 , 5 ) ) { // check for Low Voltage Cutout
SmartError . checkVolts ( FilteredSamples . FastipVolts . getValue ( ) , FilteredSamples . FastGlowAmps . getValue ( ) ) ;
SmartError . checkfuelUsage ( ) ;
}
// trap being in state 0 with a heater error - cancel user on memory to avoid unexpected cyclic restarts
2020-05-13 00:37:31 +00:00
if ( RTC_Store . getUserStart ( ) & & ( BlueWireRxData . getRunState ( ) = = 0 ) & & ( BlueWireRxData . getErrState ( ) > 1 ) ) {
2020-05-03 11:59:56 +00:00
DebugPort . println ( " Forcing cyclic cancel due to error induced shutdown " ) ;
2020-04-26 06:15:08 +00:00
// DebugPort.println("Forcing cyclic cancel due to error induced shutdown");
2020-05-13 00:37:31 +00:00
RTC_Store . setUserStart ( false ) ;
2020-04-26 06:15:08 +00:00
}
pHourMeter - > monitor ( BlueWireRxData ) ;
}
2020-04-24 23:23:16 +00:00
}
2020-04-26 06:15:08 +00:00
2018-12-16 07:38:34 +00:00
// callback function for Keypad events.
// must be an absolute function, cannot be a class member due the "this" element!
void parentKeyHandler ( uint8_t event )
{
ScreenManager . keyHandler ( event ) ; // call into the Screen Manager
}
2019-05-17 06:08:35 +00:00
void interruptReboot ( )
{
2020-04-20 03:39:39 +00:00
ets_printf ( " %ld Software watchdog reboot...... \r \n " , millis ( ) ) ;
2020-05-03 11:59:56 +00:00
abort ( ) ;
// esp_restart();
2019-05-17 06:08:35 +00:00
}
2019-11-22 10:30:45 +00:00
unsigned long WatchdogTick = - 1 ;
unsigned long JSONWatchdogTick = - 1 ;
void WatchdogTask ( void * param )
{
for ( ; ; ) {
if ( WatchdogTick > = 0 ) {
if ( WatchdogTick = = 0 ) {
interruptReboot ( ) ;
}
else {
WatchdogTick - - ;
}
}
if ( JSONWatchdogTick > = 0 ) {
if ( JSONWatchdogTick = = 0 ) {
interruptReboot ( ) ;
}
else {
JSONWatchdogTick - - ;
}
}
vTaskDelay ( 10 ) ;
}
}
2019-07-15 09:56:36 +00:00
//**************************************************************************************************
//** **
//** WORKAROUND for crap ESP32 millis() standard function **
//** **
//**************************************************************************************************
//
// Substitute shitfull ESP32 millis() with a true and proper ms counter
// The standard millis() on ESP32 is actually micros()/1000.
// This wraps every 71.5 minutes in a **very non linear fashion**.
//
// The FreeRTOS Tick Counter however does increment each ms, and rolls naturally past 0 every 49days.
// With this proper linear behaviour you can use valid timeout calcualtions even through wrap around.
// This elegance breaks using the standard library function, leading to many weird and obtuse issues.
//
// *** IMPORTANT ***
//
// You **MUST** use --wrap millis in the linker command, or -Wl,--wrap,millis in the GCC command.
// platformio.ini file for this project defines the latter as a build_flags entry.
//
// The linker will now link to __wrap_millis() instead of millis() for *any* usage of millis().
// Best of all this includes any library usages of millis() :-D
// If you really must call the shitty ESP32 Arduino millis(), you must call __real_millis()
// from your dubious code ;-) - basically DON'T do this.
extern " C " unsigned long __wrap_millis ( ) {
return xTaskGetTickCount ( ) ;
}
2019-01-10 13:10:05 +00:00
void setup ( ) {
2019-06-25 07:49:07 +00:00
2020-04-26 09:52:00 +00:00
vTaskPrioritySet ( NULL , TASK_PRIORITY_ARDUINO ) ; // elevate normal Arduino loop etc higher than the usual '1'
2020-04-26 06:15:08 +00:00
2019-06-30 00:37:24 +00:00
// ensure cyclic mode is disabled after power on
2019-07-24 09:25:07 +00:00
bool bESP32PowerUpInit = false ;
if ( rtc_get_reset_reason ( 0 ) = = 1 /* || bForceInit*/ ) {
bESP32PowerUpInit = true ;
2019-07-19 20:53:12 +00:00
// bForceInit = false;
2019-07-24 09:25:07 +00:00
}
2019-07-27 14:28:39 +00:00
2019-06-25 07:49:07 +00:00
// initially, ensure the GPIO outputs are not activated during startup
// (GPIO2 tends to be one with default chip startup)
2019-10-27 00:02:49 +00:00
# if USE_JTAG == 0
2019-11-10 04:44:54 +00:00
//CANNOT USE GPIO WITH JTAG DEBUG
2019-06-25 07:49:07 +00:00
pinMode ( GPIOout1_pin , OUTPUT ) ;
pinMode ( GPIOout2_pin , OUTPUT ) ;
digitalWrite ( GPIOout1_pin , LOW ) ;
digitalWrite ( GPIOout2_pin , LOW ) ;
2019-10-27 00:02:49 +00:00
# endif
2019-06-25 07:49:07 +00:00
2018-12-16 07:38:34 +00:00
// initialise TelnetSpy (port 23) as well as Serial to 115200
// Serial is the usual USB connection to a PC
// DO THIS BEFORE WE TRY AND SEND DEBUG INFO!
2019-06-26 20:04:24 +00:00
DebugPort . setWelcomeMsg ( ( char * ) (
" ************************************************* \r \n "
2018-12-16 07:38:34 +00:00
" * Connected to BTC heater controller debug port * \r \n "
2019-06-26 20:04:24 +00:00
" ************************************************* \r \n "
) ) ;
2018-12-16 07:38:34 +00:00
DebugPort . setBufferSize ( 8192 ) ;
DebugPort . begin ( 115200 ) ;
2019-01-14 03:30:41 +00:00
DebugPort . println ( " _______________________________________________________________ " ) ;
2020-04-22 06:21:24 +00:00
2020-03-23 05:54:15 +00:00
DebugPort . printf ( " Getting NVS stats \r \n " ) ;
nvs_stats_t nvs_stats ;
while ( nvs_get_stats ( NULL , & nvs_stats ) = = ESP_ERR_NVS_NOT_INITIALIZED ) ;
2019-06-29 08:08:37 +00:00
DebugPort . printf ( " Reset reason: core0:%d, core1:%d \r \n " , rtc_get_reset_reason ( 0 ) , rtc_get_reset_reason ( 0 ) ) ;
2019-07-19 20:53:12 +00:00
// DebugPort.printf("Previous user ON = %d\r\n", bUserON); // state flag required for cyclic mode to persist properly after a WD reboot :-)
2019-06-29 08:08:37 +00:00
// initialise DS18B20 sensor interface
2019-10-18 01:55:16 +00:00
TempSensor . begin ( DS18B20_Pin , 0x76 ) ;
2019-06-29 08:08:37 +00:00
TempSensor . startConvert ( ) ; // kick off initial temperature sample
2018-12-16 07:38:34 +00:00
2019-06-29 08:08:37 +00:00
lastTemperatureTime = millis ( ) ;
lastAnimationTime = millis ( ) ;
2019-04-12 23:18:07 +00:00
BoardRevision = BoardDetect ( ) ;
2019-05-12 10:15:18 +00:00
DebugPort . printf ( " Board revision: V%.1f \r \n " , float ( BoardRevision ) * 0.1 ) ;
2019-04-12 23:18:07 +00:00
2019-06-02 09:19:08 +00:00
DebugPort . printf ( " ESP32 IDF Version: %s \r \n " , esp_get_idf_version ( ) ) ;
2019-08-01 12:57:18 +00:00
DebugPort . printf ( " NVS: entries- free=%d used=%d total=%d namespace count=%d \r \n " , nvs_stats . free_entries , nvs_stats . used_entries , nvs_stats . total_entries , nvs_stats . namespace_count ) ;
2019-06-02 09:19:08 +00:00
2019-01-20 10:14:45 +00:00
// Initialize SPIFFS
if ( ! SPIFFS . begin ( true ) ) {
DebugPort . println ( " An Error has occurred while mounting SPIFFS " ) ;
}
else {
DebugPort . println ( " Mounted SPIFFS OK " ) ;
2019-06-26 20:04:24 +00:00
DebugPort . printf ( " SPIFFS usage: %d/%d \r \n " , SPIFFS . usedBytes ( ) , SPIFFS . totalBytes ( ) ) ;
2019-06-30 00:37:24 +00:00
DebugPort . println ( " Listing SPIFFS contents: " ) ;
String report ;
2019-07-07 07:18:38 +00:00
listSPIFFS ( " / " , 2 , report ) ;
2019-01-20 10:14:45 +00:00
}
2019-01-14 03:30:41 +00:00
NVstore . init ( ) ;
NVstore . load ( ) ;
2019-06-15 23:09:29 +00:00
2019-09-20 23:58:51 +00:00
initJSONMQTTmoderator ( ) ; // prevents JSON for MQTT unless requested
initJSONIPmoderator ( ) ; // prevents JSON for IP unless requested
initJSONTimermoderator ( ) ; // prevents JSON for timers unless requested
initJSONSysModerator ( ) ;
2019-05-30 10:31:34 +00:00
2019-10-18 01:55:16 +00:00
2019-01-14 03:30:41 +00:00
KeyPad . begin ( keyLeft_pin , keyRight_pin , keyCentre_pin , keyUp_pin , keyDown_pin ) ;
KeyPad . setCallback ( parentKeyHandler ) ;
// Initialize the rtc object
Clock . begin ( ) ;
2019-01-27 01:17:49 +00:00
2019-07-15 09:56:36 +00:00
BootTime = Clock . get ( ) . secondstime ( ) ;
2019-01-14 03:30:41 +00:00
2019-09-16 22:30:49 +00:00
ScreenManager . begin ( ) ;
if ( Clock . lostPower ( ) ) {
2019-07-19 20:53:12 +00:00
ScreenManager . selectMenu ( CScreenManager : : BranchMenu , CScreenManager : : SetClockUI ) ;
}
2018-12-16 07:38:34 +00:00
# if USE_WIFI == 1
2019-05-16 11:12:29 +00:00
2019-12-15 06:58:11 +00:00
if ( NVstore . getUserSettings ( ) . wifiMode ) {
2020-04-07 21:51:52 +00:00
initWifi ( ) ;
2018-12-16 07:38:34 +00:00
# if USE_OTA == 1
2019-06-06 01:32:43 +00:00
if ( NVstore . getUserSettings ( ) . enableOTA ) {
2019-03-24 05:48:03 +00:00
initOTA ( ) ;
}
2018-12-16 07:38:34 +00:00
# endif // USE_OTA
# if USE_WEBSERVER == 1
2019-03-24 05:48:03 +00:00
initWebServer ( ) ;
2018-12-16 07:38:34 +00:00
# endif // USE_WEBSERVER
2020-04-20 03:39:39 +00:00
initFOTA ( ) ;
2019-08-27 13:09:07 +00:00
# if USE_MQTT == 1
2019-08-31 07:34:56 +00:00
mqttInit ( ) ;
2019-08-27 13:09:07 +00:00
# endif // USE_MQTT
2019-03-24 05:48:03 +00:00
}
2018-12-16 07:38:34 +00:00
# endif // USE_WIFI
pinMode ( LED_Pin , OUTPUT ) ; // On board LED indicator
digitalWrite ( LED_Pin , LOW ) ;
bBTconnected = false ;
Bluetooth . begin ( ) ;
2019-04-09 23:28:46 +00:00
setupGPIO ( ) ;
2019-04-28 10:23:11 +00:00
2020-05-03 11:59:56 +00:00
# if USE_TWDT == 1
DebugPort . println ( " Initialize TWDT " ) ;
//Initialize or reinitialize TWDT
CHECK_ERROR_CODE ( esp_task_wdt_init ( TWDT_TIMEOUT_S , true ) , ESP_OK ) ; // invoke panic if WDT kicks
//Subscribe this task to TWDT, then check if it is subscribed
CHECK_ERROR_CODE ( esp_task_wdt_add ( NULL ) , ESP_OK ) ;
CHECK_ERROR_CODE ( esp_task_wdt_status ( NULL ) , ESP_OK ) ;
# else
2019-10-28 06:32:16 +00:00
# if USE_SW_WATCHDOG == 1 && USE_JTAG == 0
2019-11-22 10:30:45 +00:00
// create a high priority FreeRTOS task as a watchdog monitor
xTaskCreate ( WatchdogTask ,
" watchdogTask " ,
2020-05-03 11:59:56 +00:00
1024 ,
2019-11-22 10:30:45 +00:00
NULL ,
configMAX_PRIORITIES - 1 ,
2020-05-03 11:59:56 +00:00
& handleWatchdogTask ) ;
2019-05-17 06:08:35 +00:00
# endif
2020-05-03 11:59:56 +00:00
# endif
2019-11-22 10:30:45 +00:00
JSONWatchdogTick = - 1 ;
WatchdogTick = - 1 ;
2019-09-01 07:35:12 +00:00
2019-07-06 13:46:20 +00:00
FilteredSamples . ipVolts . setRounding ( 0.1 ) ;
FilteredSamples . GlowAmps . setRounding ( 0.01 ) ;
FilteredSamples . GlowVolts . setRounding ( 0.1 ) ;
FilteredSamples . Fan . setRounding ( 10 ) ;
FilteredSamples . Fan . setAlpha ( 0.7 ) ;
FilteredSamples . AmbientTemp . reset ( - 100.0 ) ;
2019-07-21 11:17:54 +00:00
FilteredSamples . FastipVolts . setRounding ( 0.1 ) ;
FilteredSamples . FastipVolts . setAlpha ( 0.7 ) ;
FilteredSamples . FastGlowAmps . setRounding ( 0.01 ) ;
FilteredSamples . FastGlowAmps . setAlpha ( 0.7 ) ;
2019-07-19 20:53:12 +00:00
RTC_Store . begin ( ) ;
FuelGauge . init ( RTC_Store . getFuelGauge ( ) ) ;
2020-05-13 00:37:31 +00:00
DebugPort . printf ( " Previous user start = %d \r \n " , RTC_Store . getUserStart ( ) ) ; // state flag required for cyclic mode to persist properly after a WD reboot :-)
2019-07-18 12:28:40 +00:00
2019-07-26 12:13:46 +00:00
pHourMeter = new CHourMeter ( persistentRunTime , persistentGlowTime ) ; // persistent vars passed by reference so they can be valid after SW reboots
pHourMeter - > init ( bESP32PowerUpInit | | RTC_Store . getBootInit ( ) ) ; // ensure persistent memory variable are reset after powerup, or OTA update
2019-07-25 12:31:31 +00:00
RTC_Store . setBootInit ( false ) ;
2019-07-24 09:25:07 +00:00
2020-04-11 08:49:52 +00:00
// apply saved set points!
CDemandManager : : reload ( ) ;
2019-09-22 04:46:39 +00:00
// Check for solo DS18B20
// store it's serial number as the primary sensor
// This allows seamless standard operation, and marks the iniital sensor
// as the primary if another is added later
OneWireBus_ROMCode romCode ;
2019-10-18 01:55:16 +00:00
TempSensor . getDS18B20 ( ) . getRomCodeIdx ( 0 , romCode ) ;
if ( TempSensor . getDS18B20 ( ) . getNumSensors ( ) = = 1 & &
memcmp ( NVstore . getHeaterTuning ( ) . DS18B20probe [ 0 ] . romCode . bytes , romCode . bytes , 8 ) ! = 0 )
2019-09-22 04:46:39 +00:00
{
sHeaterTuning tuning = NVstore . getHeaterTuning ( ) ;
2019-10-18 01:55:16 +00:00
tuning . DS18B20probe [ 0 ] . romCode = romCode ;
tuning . DS18B20probe [ 1 ] . romCode = { 0 } ;
tuning . DS18B20probe [ 2 ] . romCode = { 0 } ;
tuning . DS18B20probe [ 0 ] . offset = 0 ;
2019-09-22 04:46:39 +00:00
NVstore . setHeaterTuning ( tuning ) ;
NVstore . save ( ) ;
DebugPort . printf ( " Saved solo DS18B20 %02X:%02X:%02X:%02X:%02X:%02X to NVstore \r \n " ,
romCode . fields . serial_number [ 5 ] ,
romCode . fields . serial_number [ 4 ] ,
romCode . fields . serial_number [ 3 ] ,
romCode . fields . serial_number [ 2 ] ,
romCode . fields . serial_number [ 1 ] ,
romCode . fields . serial_number [ 0 ]
) ;
}
2019-10-18 01:55:16 +00:00
TempSensor . getDS18B20 ( ) . mapSensor ( 0 , NVstore . getHeaterTuning ( ) . DS18B20probe [ 0 ] . romCode ) ;
TempSensor . getDS18B20 ( ) . mapSensor ( 1 , NVstore . getHeaterTuning ( ) . DS18B20probe [ 1 ] . romCode ) ;
TempSensor . getDS18B20 ( ) . mapSensor ( 2 , NVstore . getHeaterTuning ( ) . DS18B20probe [ 2 ] . romCode ) ;
2020-04-24 23:23:16 +00:00
// create task to run blue wire interface
xTaskCreate ( BlueWireTask ,
" BlueWireTask " ,
2020-05-03 11:59:56 +00:00
1600 ,
2020-04-24 23:23:16 +00:00
NULL ,
2020-05-03 11:59:56 +00:00
TASK_PRIORITY_HEATERCOMMS ,
& handleBlueWireTask ) ;
2020-04-26 06:15:08 +00:00
2020-04-26 09:52:00 +00:00
2020-06-19 01:24:44 +00:00
UHFremote . begin ( Rx433MHz_pin , RMT_CHANNEL_4 ) ;
2020-04-26 06:15:08 +00:00
2020-04-24 23:23:16 +00:00
2019-04-28 10:23:11 +00:00
delay ( 1000 ) ; // just to hold the splash screeen for while
2020-04-22 06:21:24 +00:00
ScreenManager . clearDisplay ( ) ;
2018-12-16 07:38:34 +00:00
}
// main functional loop is based about a state machine approach, waiting for data
// to appear upon the blue wire, and marshalling into an appropriate receive buffers
// according to the state.
void loop ( )
{
2019-06-02 09:19:08 +00:00
// DebugPort.handle(); // keep telnet spy alive
2018-12-16 07:38:34 +00:00
2020-05-03 11:59:56 +00:00
feedWatchdog ( ) ; // feed watchdog
2019-05-17 06:08:35 +00:00
2020-04-24 23:23:16 +00:00
doStreaming ( ) ; // do wifi, BT tx etc
2019-06-02 09:19:08 +00:00
2020-04-24 23:23:16 +00:00
Clock . update ( ) ;
2018-12-16 07:38:34 +00:00
2020-04-26 06:15:08 +00:00
if ( checkTemperatureSensors ( ) )
ScreenManager . reqUpdate ( ) ;
2018-12-20 09:59:53 +00:00
2020-05-03 11:59:56 +00:00
checkDisplayUpdate ( ) ;
2018-12-16 07:38:34 +00:00
2020-04-26 06:15:08 +00:00
checkBlueWireEvents ( ) ;
2018-12-16 07:38:34 +00:00
2020-06-19 01:24:44 +00:00
checkUHF ( ) ;
2020-04-26 06:15:08 +00:00
vTaskDelay ( 1 ) ;
} // loop
2018-12-16 07:38:34 +00:00
2018-12-21 21:48:39 +00:00
2020-04-26 06:15:08 +00:00
bool checkTemperatureSensors ( )
{
long tDelta = millis ( ) - lastTemperatureTime ;
2020-05-03 11:59:56 +00:00
if ( tDelta > MIN_TEMPERATURE_INTERVAL ) { // maintain a minimum holdoff period
lastTemperatureTime = millis ( ) ; // reset time to observe temeprature
if ( bReportStack ) {
DebugPort . println ( " Stack high water marks " ) ;
DebugPort . printf ( " Arduino: %d \r \n " , uxTaskGetStackHighWaterMark ( NULL ) ) ;
DebugPort . printf ( " BlueWire: %d \r \n " , uxTaskGetStackHighWaterMark ( handleBlueWireTask ) ) ;
DebugPort . printf ( " Watchdog: %d \r \n " , uxTaskGetStackHighWaterMark ( handleWatchdogTask ) ) ;
2020-05-06 00:41:26 +00:00
DebugPort . printf ( " SSL loop: %d \r \n " , uxTaskGetStackHighWaterMark ( handleWebServerTask ) ) ;
2020-05-03 11:59:56 +00:00
}
2020-04-20 03:39:39 +00:00
2020-05-03 11:59:56 +00:00
TempSensor . readSensors ( ) ;
2020-04-26 06:15:08 +00:00
float fTemperature ;
2020-05-03 11:59:56 +00:00
if ( TempSensor . getTemperature ( 0 , fTemperature ) ) { // get Primary sensor temperature
if ( DS18B20holdoff ) {
DS18B20holdoff - - ;
DebugPort . printf ( " Skipped initial DS18B20 reading: %f \r \n " , fTemperature ) ;
} // first value upon sensor connect is bad
else {
// exponential mean to stabilse readings
FilteredSamples . AmbientTemp . update ( fTemperature ) ;
2019-01-10 13:10:05 +00:00
2020-05-03 11:59:56 +00:00
manageCyclicMode ( ) ;
manageFrostMode ( ) ;
manageHumidity ( ) ;
2020-05-13 00:37:31 +00:00
manageStopStartMode ( ) ;
2018-12-16 07:38:34 +00:00
}
2020-05-03 11:59:56 +00:00
}
else {
DS18B20holdoff = 3 ;
FilteredSamples . AmbientTemp . reset ( - 100.0 ) ;
}
TempSensor . startConvert ( ) ; // request a new conversion, will be ready by the time we loop back around
return true ;
}
2020-04-26 06:15:08 +00:00
return false ;
2018-12-16 07:38:34 +00:00
}
2020-05-13 00:37:31 +00:00
void manageStopStartMode ( )
{
if ( NVstore . getUserSettings ( ) . ThermostatMethod = = 4 & & RTC_Store . getUserStart ( ) ) {
float deltaT = getTemperatureSensor ( ) - CDemandManager : : getDegC ( ) ;
float thresh = NVstore . getUserSettings ( ) . ThermostatWindow / 2 ;
int heaterState = getHeaterInfo ( ) . getRunState ( ) ; // native heater state
if ( deltaT > thresh ) {
if ( heaterState > 0 & & heaterState < = 5 ) {
DebugPort . printf ( " STOP START MODE: Stopping heater, deltaT > +%.1f \r \n " , thresh ) ;
heaterOff ( ) ; // over temp - request heater stop
}
}
if ( deltaT < - thresh ) {
if ( heaterState = = 0 ) {
DebugPort . printf ( " STOP START MODE: Restarting heater, deltaT <%.1f \r \n " , thresh ) ;
heaterOn ( ) ; // under temp, start heater again
}
}
}
}
2019-04-04 10:48:05 +00:00
void manageCyclicMode ( )
{
2019-07-03 13:01:36 +00:00
const sCyclicThermostat & cyclic = NVstore . getUserSettings ( ) . cyclic ;
2020-05-13 00:37:31 +00:00
if ( cyclic . Stop & & RTC_Store . getUserStart ( ) ) { // cyclic mode enabled, and user has started heater
2019-04-27 10:41:47 +00:00
int stopDeltaT = cyclic . Stop + 1 ; // bump up by 1 degree - no point invoking at 1 deg over!
2020-04-11 08:49:52 +00:00
float deltaT = getTemperatureSensor ( ) - CDemandManager : : getDegC ( ) ;
2019-05-12 10:15:18 +00:00
// DebugPort.printf("Cyclic=%d bUserOn=%d deltaT=%d\r\n", cyclic, bUserON, deltaT);
2019-04-04 10:48:05 +00:00
// ensure we cancel user ON mode if heater throws an error
int errState = getHeaterInfo ( ) . getErrState ( ) ;
2019-06-16 08:13:16 +00:00
if ( ( errState > 1 ) & & ( errState < 12 ) & & ( errState ! = 8 ) ) {
// excludes errors 0,1(OK), 12(E1-11,Retry) & 8(E-07,Comms Error)
2019-04-04 10:48:05 +00:00
DebugPort . println ( " CYCLIC MODE: cancelling user ON status " ) ;
requestOff ( ) ; // forcibly cancel cyclic operation - pretend user pressed OFF
}
int heaterState = getHeaterInfo ( ) . getRunState ( ) ;
// check if over temp, turn off heater
2019-04-27 10:41:47 +00:00
if ( deltaT > stopDeltaT ) {
2019-04-04 10:48:05 +00:00
if ( heaterState > 0 & & heaterState < = 5 ) {
2019-05-12 10:15:18 +00:00
DebugPort . printf ( " CYCLIC MODE: Stopping heater, deltaT > +%d \r \n " , stopDeltaT ) ;
2019-04-04 10:48:05 +00:00
heaterOff ( ) ; // over temp - request heater stop
}
}
// check if under temp, turn on heater
2019-04-27 10:41:47 +00:00
if ( deltaT < cyclic . Start ) {
// typ. 1 degree below set point - restart heater
2019-04-04 10:48:05 +00:00
if ( heaterState = = 0 ) {
2019-05-12 10:15:18 +00:00
DebugPort . printf ( " CYCLIC MODE: Restarting heater, deltaT <%d \r \n " , cyclic . Start ) ;
2019-04-04 10:48:05 +00:00
heaterOn ( ) ;
}
}
}
}
2018-12-16 07:38:34 +00:00
2019-10-31 22:24:58 +00:00
void manageFrostMode ( )
{
uint8_t engage = NVstore . getUserSettings ( ) . FrostOn ;
if ( engage ) {
float deltaT = getTemperatureSensor ( ) - engage ;
int heaterState = getHeaterInfo ( ) . getRunState ( ) ;
if ( deltaT < 0 ) {
if ( heaterState = = 0 ) {
RTC_Store . setFrostOn ( true ) ;
DebugPort . printf ( " FROST MODE: Starting heater, < %d`C \r \n " , engage ) ;
2020-03-23 05:54:15 +00:00
if ( NVstore . getUserSettings ( ) . FrostRise = = 0 )
2020-05-13 00:37:31 +00:00
RTC_Store . setUserStart ( true ) ; // enable cyclic mode if user stop
2019-10-31 22:24:58 +00:00
heaterOn ( ) ;
}
}
uint8_t rise = NVstore . getUserSettings ( ) . FrostRise ;
2020-03-23 05:54:15 +00:00
if ( rise & & ( deltaT > rise ) ) { // if rise is set to 0, user must shut off heater
2019-10-31 22:24:58 +00:00
if ( RTC_Store . getFrostOn ( ) ) {
DebugPort . printf ( " FROST MODE: Stopping heater, > %d`C \r \n " , engage + rise ) ;
heaterOff ( ) ;
RTC_Store . setFrostOn ( false ) ; // cancel active frost mode
2020-05-13 00:37:31 +00:00
RTC_Store . setUserStart ( false ) ; // for cyclic mode
2019-10-31 22:24:58 +00:00
}
}
}
}
2020-01-13 08:48:32 +00:00
void manageHumidity ( )
{
uint8_t humidity = NVstore . getUserSettings ( ) . humidityStart ;
if ( humidity ) {
float reading ;
if ( getTempSensor ( ) . getHumidity ( reading ) ) {
uint8_t testval = ( uint8_t ) reading ;
if ( testval > humidity ) {
DebugPort . printf ( " HUMIDITY MODE: Starting heater, > %d%% \r \n " , humidity ) ;
requestOn ( ) ;
}
}
}
}
2020-04-10 21:51:25 +00:00
2020-04-11 08:49:52 +00:00
CDemandManager : : eStartCode
requestOn ( )
2019-04-04 10:48:05 +00:00
{
2020-03-31 08:46:25 +00:00
DebugPort . println ( " Start Request! " ) ;
2020-03-30 05:17:54 +00:00
bool fuelOK = 2 ! = SmartError . checkfuelUsage ( ) ;
if ( ! fuelOK ) {
2020-05-09 09:17:21 +00:00
DebugPort . println ( " Start denied - Low fuel " ) ;
2020-04-11 08:49:52 +00:00
return CDemandManager : : eStartLowFuel ;
2020-03-30 05:17:54 +00:00
}
bool LVCOK = 2 ! = SmartError . checkVolts ( FilteredSamples . FastipVolts . getValue ( ) , FilteredSamples . FastGlowAmps . getValue ( ) ) ;
2020-04-24 23:23:16 +00:00
if ( hasHtrData ( ) & & LVCOK ) {
2020-05-13 00:37:31 +00:00
RTC_Store . setUserStart ( true ) ; // for cyclic mode
2020-04-10 21:51:25 +00:00
RTC_Store . setFrostOn ( false ) ; // cancel frost mode
// only start if below appropriate temperature threshold, raised for cyclic mode
2020-04-11 08:49:52 +00:00
// int denied = checkStartTemp();
CDemandManager : : eStartCode startCode = CDemandManager : : checkStart ( ) ;
if ( startCode = = CDemandManager : : eStartOK ) {
2020-04-10 21:51:25 +00:00
heaterOn ( ) ;
2019-08-04 01:15:41 +00:00
}
2019-11-21 08:25:14 +00:00
else {
2020-04-11 08:49:52 +00:00
if ( startCode = = CDemandManager : : eStartSuspend ) {
SmartError . inhibit ( true ) ; // ensure our suspend does not get immediately cancelled by prior error sitting in system!
DebugPort . printf ( " CYCLIC MODE: Skipping directly to suspend, deltaT > +%d \r \n " , NVstore . getUserSettings ( ) . cyclic . Stop + 1 ) ;
heaterOff ( ) ; // over temp - request heater stop
}
2019-11-21 08:25:14 +00:00
}
2020-04-11 08:49:52 +00:00
return startCode ;
2019-11-21 08:25:14 +00:00
}
else {
2020-05-09 09:17:21 +00:00
DebugPort . println ( " Start denied - LVC " ) ;
2020-04-11 08:49:52 +00:00
return CDemandManager : : eStartLVC ; // LVC
2019-07-21 11:17:54 +00:00
}
2019-04-04 10:48:05 +00:00
}
void requestOff ( )
{
2020-03-31 08:46:25 +00:00
DebugPort . println ( " Stop Request! " ) ;
2019-04-04 10:48:05 +00:00
heaterOff ( ) ;
2020-05-13 00:37:31 +00:00
RTC_Store . setUserStart ( false ) ; // for cyclic mode
2019-10-31 22:24:58 +00:00
RTC_Store . setFrostOn ( false ) ; // cancel active frost mode
2020-05-09 09:17:21 +00:00
CTimerManager : : cancelActiveTimer ( ) ;
2019-04-04 10:48:05 +00:00
}
void heaterOn ( )
2018-12-16 07:38:34 +00:00
{
TxManage . queueOnRequest ( ) ;
SmartError . reset ( ) ;
}
2019-04-04 10:48:05 +00:00
void heaterOff ( )
2018-12-16 07:38:34 +00:00
{
TxManage . queueOffRequest ( ) ;
SmartError . inhibit ( ) ;
}
void checkDisplayUpdate ( )
{
// only update OLED when not processing blue wire
if ( ScreenManager . checkUpdate ( ) ) {
2019-07-15 09:56:36 +00:00
lastAnimationTime = millis ( ) + 100 ;
2018-12-16 07:38:34 +00:00
ScreenManager . animate ( ) ;
ScreenManager . refresh ( ) ; // always refresh post major update
}
long tDelta = millis ( ) - lastAnimationTime ;
if ( tDelta > = 100 ) {
2019-07-15 09:56:36 +00:00
lastAnimationTime = millis ( ) + 100 ;
2018-12-16 07:38:34 +00:00
if ( ScreenManager . animate ( ) )
ScreenManager . refresh ( ) ;
}
}
2019-06-29 08:08:37 +00:00
void forceBootInit ( )
{
2019-07-25 11:27:57 +00:00
RTC_Store . setBootInit ( ) ;
2019-06-29 08:08:37 +00:00
}
2019-03-14 10:52:59 +00:00
2019-10-18 01:55:16 +00:00
float getTemperatureSensor ( int source )
2018-12-16 07:38:34 +00:00
{
2019-10-18 01:55:16 +00:00
float retval ;
TempSensor . getTemperature ( source , retval ) ;
return retval ;
2018-12-16 07:38:34 +00:00
}
bool isWebClientConnected ( )
{
return bHaveWebClient ;
}
void checkDebugCommands ( )
{
2020-04-07 21:51:52 +00:00
static CGetLine line ;
2019-08-10 11:45:28 +00:00
2020-01-15 06:52:43 +00:00
// check for test commands received over Debug serial port or telnet
char rxVal ;
if ( DebugPort . getch ( rxVal ) ) {
2019-06-26 20:04:24 +00:00
# ifdef PROTOCOL_INVESTIGATION
2020-01-15 06:52:43 +00:00
static int mode = 0 ; 6
2018-12-16 07:38:34 +00:00
static int val = 0 ;
2019-06-26 20:04:24 +00:00
# endif
2018-12-16 07:38:34 +00:00
2019-07-27 02:47:16 +00:00
if ( bTestBTModule ) {
bTestBTModule = Bluetooth . test ( rxVal ) ;
return ;
}
2019-09-07 08:28:21 +00:00
if ( MQTTmenu . Handle ( rxVal ) ) {
2019-10-27 03:25:40 +00:00
if ( rxVal = = 0 ) {
2019-08-31 07:34:56 +00:00
showMainmenu ( ) ;
2019-10-27 03:25:40 +00:00
}
2019-08-31 07:34:56 +00:00
return ;
}
2020-04-26 06:15:08 +00:00
if ( SecurityMenu . Handle ( rxVal ) ) {
if ( rxVal = = 0 ) {
showMainmenu ( ) ;
2019-08-10 11:45:28 +00:00
}
2020-04-07 21:51:52 +00:00
return ;
2019-08-10 11:45:28 +00:00
}
2018-12-20 04:19:59 +00:00
rxVal = toLowerCase ( rxVal ) ;
# ifdef PROTOCOL_INVESTIGATION
2018-12-16 07:38:34 +00:00
bool bSendVal = false ;
2018-12-20 04:19:59 +00:00
# endif
2019-04-04 10:48:05 +00:00
if ( rxVal = = ' \n ' ) { // "End of Line"
2018-12-20 04:19:59 +00:00
# ifdef PROTOCOL_INVESTIGATION
2020-04-07 21:51:52 +00:00
String convert ( line . getString ( ) ) ;
2018-12-16 07:38:34 +00:00
val = convert . toInt ( ) ;
bSendVal = true ;
2020-04-07 21:51:52 +00:00
line . reset ( ) ;
2018-12-20 04:19:59 +00:00
# endif
2018-12-16 07:38:34 +00:00
}
else {
2018-12-20 04:19:59 +00:00
if ( rxVal = = ' ' ) { // SPACE to bring up menu
2019-08-31 07:34:56 +00:00
showMainmenu ( ) ;
2018-12-20 04:19:59 +00:00
}
# ifdef PROTOCOL_INVESTIGATION
else if ( isDigit ( rxVal ) ) {
2020-04-07 21:51:52 +00:00
line . handle ( rxVal ) ;
2018-12-16 07:38:34 +00:00
}
2018-12-20 04:19:59 +00:00
else if ( rxVal = = ' p ' ) {
2018-12-16 07:38:34 +00:00
DebugPort . println ( " Test Priming Byte... " ) ;
mode = 1 ;
}
2018-12-20 04:19:59 +00:00
else if ( rxVal = = ' g ' ) {
2018-12-16 07:38:34 +00:00
DebugPort . println ( " Test glow power byte... " ) ;
mode = 2 ;
}
2018-12-20 04:19:59 +00:00
else if ( rxVal = = ' i ' ) {
2020-01-14 20:55:57 +00:00
DebugPort . println ( " Test unknown bytes MSB " ) ;
2018-12-16 07:38:34 +00:00
mode = 3 ;
}
2020-01-14 20:55:57 +00:00
else if ( rxVal = = ' a ' ) {
DebugPort . println ( " Test unknown bytes LSB " ) ;
mode = 5 ;
}
2019-04-04 10:48:05 +00:00
else if ( rxVal = = ' c ' ) {
DebugPort . println ( " Test Command Byte... " ) ;
mode = 4 ;
}
else if ( rxVal = = ' x ' ) {
DebugPort . println ( " Special mode cancelled " ) ;
val = 0 ;
mode = 0 ;
DefaultBTCParams . Controller . Command = 0 ;
}
2020-01-14 20:55:57 +00:00
else if ( rxVal = = ' ] ' ) {
2018-12-16 07:38:34 +00:00
val + + ;
bSendVal = true ;
}
else if ( rxVal = = ' [ ' ) {
val - - ;
bSendVal = true ;
}
2018-12-20 04:19:59 +00:00
# endif
else if ( rxVal = = ' b ' ) {
bReportBlueWireData = ! bReportBlueWireData ;
2019-05-12 10:15:18 +00:00
DebugPort . printf ( " Toggled raw blue wire data reporting %s \r \n " , bReportBlueWireData ? " ON " : " OFF " ) ;
2018-12-20 04:19:59 +00:00
}
else if ( rxVal = = ' j ' ) {
bReportJSONData = ! bReportJSONData ;
2019-05-12 10:15:18 +00:00
DebugPort . printf ( " Toggled JSON data reporting %s \r \n " , bReportJSONData ? " ON " : " OFF " ) ;
2018-12-20 07:33:44 +00:00
}
2020-04-24 23:23:16 +00:00
else if ( rxVal = = ( ' w ' & 0x1f ) ) {
2018-12-20 07:33:44 +00:00
bReportRecyleEvents = ! bReportRecyleEvents ;
2020-04-24 23:23:16 +00:00
if ( NVstore . getUserSettings ( ) . menuMode = = 2 )
bReportRecyleEvents = false ;
2019-05-12 10:15:18 +00:00
DebugPort . printf ( " Toggled blue wire recycling event reporting %s \r \n " , bReportRecyleEvents ? " ON " : " OFF " ) ;
2018-12-20 04:19:59 +00:00
}
2019-08-31 07:34:56 +00:00
else if ( rxVal = = ' m ' ) {
2019-09-07 08:28:21 +00:00
MQTTmenu . setActive ( ) ;
2019-08-31 07:34:56 +00:00
}
2020-04-26 06:15:08 +00:00
else if ( rxVal = = ' s ' ) {
SecurityMenu . setActive ( ) ;
}
2020-04-24 23:23:16 +00:00
else if ( rxVal = = ( ' o ' & 0x1f ) ) {
2018-12-20 09:59:53 +00:00
bReportOEMresync = ! bReportOEMresync ;
2019-05-12 10:15:18 +00:00
DebugPort . printf ( " Toggled OEM resync event reporting %s \r \n " , bReportOEMresync ? " ON " : " OFF " ) ;
2018-12-20 09:59:53 +00:00
}
2020-04-24 23:23:16 +00:00
else if ( rxVal = = ( ' c ' & 0x1f ) ) {
2018-12-21 21:48:39 +00:00
CommState . toggleReporting ( ) ;
}
2018-12-20 04:19:59 +00:00
else if ( rxVal = = ' + ' ) {
TxManage . queueOnRequest ( ) ;
}
else if ( rxVal = = ' - ' ) {
TxManage . queueOffRequest ( ) ;
}
2020-03-24 10:14:41 +00:00
else if ( rxVal = = ' h ' ) {
2020-03-25 09:28:12 +00:00
getWebContent ( true ) ;
2020-03-24 10:14:41 +00:00
}
2020-05-03 11:59:56 +00:00
else if ( rxVal = = ' ! ' ) {
DebugPort . println ( " Invoking deliberate halt loop " ) ;
for ( ; ; ) ; // force watchdog reboot
}
2020-04-26 09:28:31 +00:00
else if ( rxVal = = ( ' b ' & 0x1f ) ) { // CTRL-B Tst Mode: bluetooth module route
2020-04-20 03:39:39 +00:00
bTestBTModule = ! bTestBTModule ;
Bluetooth . test ( bTestBTModule ? 0xff : 0x00 ) ; // special enter or leave BT test commands
2018-12-20 04:19:59 +00:00
}
2019-07-25 12:31:31 +00:00
else if ( rxVal = = ( ' h ' & 0x1f ) ) { // CTRL-H hourmeter reset
2019-07-26 12:13:46 +00:00
pHourMeter - > resetHard ( ) ;
2019-07-25 12:31:31 +00:00
}
2020-06-19 01:24:44 +00:00
else if ( rxVal = = ( ' p ' & 0x1f ) ) { // CTRL-P fuel usage reset
FuelGauge . reset ( ) ;
}
2020-04-20 03:39:39 +00:00
else if ( rxVal = = ( ' r ' & 0x1f ) ) { // CTRL-R reboot
ESP . restart ( ) ; // reset the esp
}
2020-04-24 23:23:16 +00:00
else if ( rxVal = = ( ' s ' & 0x1f ) ) { // CTRL-S Test Mode: bluetooth module route
2020-04-20 03:39:39 +00:00
bReportStack = ! bReportStack ;
2019-07-27 02:47:16 +00:00
}
2018-12-16 07:38:34 +00:00
}
2018-12-20 04:19:59 +00:00
# ifdef PROTOCOL_INVESTIGATION
2018-12-16 07:38:34 +00:00
if ( bSendVal ) {
switch ( mode ) {
case 1 :
DefaultBTCParams . Controller . Prime = val & 0xff ; // always 0x32:Thermostat, 0xCD:Fixed
break ;
case 2 :
2019-04-04 10:48:05 +00:00
DefaultBTCParams . Controller . GlowDrive = val & 0xff ; // always 0x05
2018-12-16 07:38:34 +00:00
break ;
case 3 :
2020-01-14 20:55:57 +00:00
DefaultBTCParams . Controller . Unknown1_MSB = val & 0xff ;
2018-12-16 07:38:34 +00:00
break ;
2019-04-04 10:48:05 +00:00
case 4 :
2019-05-12 10:15:18 +00:00
DebugPort . printf ( " Forced controller command = %d \r \n " , val & 0xff ) ;
2019-04-04 10:48:05 +00:00
DefaultBTCParams . Controller . Command = val & 0xff ;
break ;
2020-01-14 20:55:57 +00:00
case 5 :
DefaultBTCParams . Controller . Unknown1_LSB = val & 0xff ;
break ;
2018-12-16 07:38:34 +00:00
}
}
2018-12-20 04:19:59 +00:00
# endif
2018-12-16 07:38:34 +00:00
}
}
2019-02-27 11:51:02 +00:00
2018-12-22 06:34:10 +00:00
int getSmartError ( )
{
return SmartError . getError ( ) ;
2019-04-04 10:48:05 +00:00
}
2020-05-13 00:37:31 +00:00
bool isCyclicStopStartActive ( )
2019-04-04 10:48:05 +00:00
{
2020-05-13 00:37:31 +00:00
return RTC_Store . getUserStart ( ) & & ( NVstore . getUserSettings ( ) . cyclic . isEnabled ( ) | | NVstore . getUserSettings ( ) . ThermostatMethod = = 4 ) ;
2019-04-04 10:48:05 +00:00
}
2019-04-09 23:28:46 +00:00
void setupGPIO ( )
{
2019-10-27 00:02:49 +00:00
# if USE_JTAG == 1
2019-11-10 04:44:54 +00:00
//CANNOT USE GPIO WITH JTAG DEBUG
2019-10-27 00:02:49 +00:00
return ;
# else
2019-09-25 09:38:19 +00:00
if ( BoardRevision = = 10 | | BoardRevision = = 20 | | BoardRevision = = 21 | | BoardRevision = = 30 ) {
2019-04-12 23:18:07 +00:00
// some special considerations for GPIO inputs, depending upon PCB hardware
2019-04-13 09:05:53 +00:00
// V1.0 PCBs only expose bare inputs, which are pulled high. Active state into ESP32 is LOW.
// V2.0+ PCBs use an input transistor buffer. Active state into ESP32 is HIGH (inverted).
int activePinState = ( BoardRevision = = 10 ) ? LOW : HIGH ;
2019-04-12 23:18:07 +00:00
int Input1 = BoardRevision = = 20 ? GPIOin1_pinV20 : GPIOin1_pinV21V10 ;
2019-08-08 20:13:02 +00:00
GPIOin . begin ( Input1 ,
GPIOin2_pin ,
NVstore . getUserSettings ( ) . GPIO . in1Mode ,
NVstore . getUserSettings ( ) . GPIO . in2Mode ,
activePinState ) ;
2019-04-12 23:18:07 +00:00
// GPIO out is always active high from ESP32
// V1.0 PCBs only expose the bare pins
// V2.0+ PCBs provide an open collector output that conducts when active
2019-08-08 20:13:02 +00:00
GPIOout . begin ( GPIOout1_pin ,
GPIOout2_pin ,
NVstore . getUserSettings ( ) . GPIO . out1Mode ,
NVstore . getUserSettings ( ) . GPIO . out2Mode ) ;
2019-10-30 10:48:25 +00:00
GPIOout . setThresh ( NVstore . getUserSettings ( ) . GPIO . thresh [ 0 ] ,
NVstore . getUserSettings ( ) . GPIO . thresh [ 1 ] ) ;
2019-04-12 23:18:07 +00:00
// ### MAJOR ISSUE WITH ADC INPUTS ###
//
// V2.0 PCBs that have not been modified connect the analogue input to GPIO26.
// This is ADC2 channel (#9).
// Unfortunately it was subsequently discovered that any ADC2 input cannot be
// used if Wifi is enabled.
2019-10-30 10:48:25 +00:00
// THIS ISSUE IS NOT RESOLVABLE IN SOFTWARE.
2019-04-12 23:18:07 +00:00
// *** It is not possible to use ANY of the 10 ADC2 channels if Wifi is enabled :-( ***
//
// Fix is to cut traces to GPIO33 & GPIO26 and swap the connections.
// This directs GPIO input1 into GPIO26 and the analogue input into GPIO33 (ADC1_CHANNEL_5)
// This will be properly fixed in V2.1 PCBs
//
// As V1.0 PCBS expose the bare pins, the correct GPIO33 input can be readily chosen.
2019-08-08 20:13:02 +00:00
CGPIOalg : : Modes algMode = NVstore . getUserSettings ( ) . GPIO . algMode ;
2019-04-12 23:18:07 +00:00
if ( BoardRevision = = 20 )
2019-08-08 20:13:02 +00:00
algMode = CGPIOalg : : Disabled ; // force off analogue support in V2.0 PCBs
2019-04-12 23:18:07 +00:00
GPIOalg . begin ( GPIOalg_pin , algMode ) ;
}
else {
2019-08-01 12:57:18 +00:00
// unknown board or forced no GPIO by grounding pin26 - deny all GPIO operation
2019-08-07 08:59:30 +00:00
// set all pins as inputs with pull ups
pinMode ( GPIOin2_pin , INPUT_PULLUP ) ;
pinMode ( GPIOin1_pinV21V10 , INPUT_PULLUP ) ;
pinMode ( GPIOin1_pinV20 , INPUT_PULLUP ) ;
pinMode ( GPIOout1_pin , INPUT_PULLUP ) ;
pinMode ( GPIOout2_pin , INPUT_PULLUP ) ;
2019-08-08 20:13:02 +00:00
GPIOin . begin ( 0 , 0 , CGPIOin1 : : Disabled , CGPIOin2 : : Disabled , LOW ) ; // ensure modes disabled (should already be by constructors)
GPIOout . begin ( 0 , 0 , CGPIOout1 : : Disabled , CGPIOout2 : : Disabled ) ;
GPIOalg . begin ( ADC1_CHANNEL_5 , CGPIOalg : : Disabled ) ;
2019-04-12 23:18:07 +00:00
}
2019-10-27 00:02:49 +00:00
# endif
2019-04-09 23:28:46 +00:00
}
2019-06-02 12:47:35 +00:00
bool toggleGPIOout ( int channel )
{
2019-10-27 00:02:49 +00:00
# if USE_JTAG == 0
2019-11-10 04:44:54 +00:00
//CANNOT USE GPIO WITH JTAG DEBUG
2019-08-07 12:04:20 +00:00
if ( channel = = 0 ) {
2019-08-08 20:13:02 +00:00
if ( NVstore . getUserSettings ( ) . GPIO . out1Mode = = CGPIOout1 : : User ) {
2019-08-07 12:04:20 +00:00
setGPIOout ( channel , ! getGPIOout ( channel ) ) ; // toggle selected GPIO output
return true ;
}
}
else if ( channel = = 1 ) {
2019-08-08 20:13:02 +00:00
if ( NVstore . getUserSettings ( ) . GPIO . out2Mode = = CGPIOout2 : : User ) {
2019-08-07 12:04:20 +00:00
setGPIOout ( channel , ! getGPIOout ( channel ) ) ; // toggle selected GPIO output
return true ;
}
2019-06-02 12:47:35 +00:00
}
2019-10-27 00:02:49 +00:00
# endif
2019-06-02 12:47:35 +00:00
return false ;
}
2019-08-01 12:57:18 +00:00
bool setGPIOout ( int channel , bool state )
2019-04-09 23:28:46 +00:00
{
2019-10-27 00:02:49 +00:00
# if USE_JTAG == 0
2019-11-10 04:44:54 +00:00
//CANNOT USE GPIO WITH JTAG DEBUG
2019-08-07 12:04:20 +00:00
if ( channel = = 0 ) {
2019-08-08 20:13:02 +00:00
if ( GPIOout . getMode1 ( ) ! = CGPIOout1 : : Disabled ) {
2019-08-07 12:04:20 +00:00
DebugPort . printf ( " setGPIO: Output #%d = %d \r \n " , channel + 1 , state ) ;
GPIOout . setState ( channel , state ) ;
return true ;
}
}
else if ( channel = = 1 ) {
2019-08-08 20:13:02 +00:00
if ( GPIOout . getMode2 ( ) ! = CGPIOout2 : : Disabled ) {
2019-08-07 12:04:20 +00:00
DebugPort . printf ( " setGPIO: Output #%d = %d \r \n " , channel + 1 , state ) ;
GPIOout . setState ( channel , state ) ;
return true ;
}
2019-08-01 12:57:18 +00:00
}
2019-10-27 00:02:49 +00:00
# endif
2019-08-01 12:57:18 +00:00
return false ;
2019-04-09 23:28:46 +00:00
}
2019-06-02 12:47:35 +00:00
bool getGPIOout ( int channel )
2019-04-09 23:28:46 +00:00
{
2019-10-27 00:02:49 +00:00
# if USE_JTAG == 0
2019-04-09 23:28:46 +00:00
bool retval = GPIOout . getState ( channel ) ;
2019-05-12 10:15:18 +00:00
DebugPort . printf ( " getGPIO: Output #%d = %d \r \n " , channel + 1 , retval ) ;
2019-04-09 23:28:46 +00:00
return retval ;
2019-10-27 00:02:49 +00:00
# else
2019-11-10 04:44:54 +00:00
//CANNOT USE GPIO WITH JTAG DEBUG
2019-10-27 00:02:49 +00:00
return false ;
# endif
2019-04-09 23:28:46 +00:00
}
2019-04-19 11:38:39 +00:00
2020-06-19 06:49:40 +00:00
float getVersion ( bool betarevision )
2019-04-19 11:38:39 +00:00
{
2020-06-19 06:49:40 +00:00
if ( betarevision )
return float ( FirmwareMinorRevision ) ;
else
return float ( FirmwareRevision ) * 0.1f + float ( FirmwareSubRevision ) * .001f ;
2019-04-19 11:38:39 +00:00
}
2020-01-04 07:13:40 +00:00
const char * getVersionStr ( bool beta ) {
2019-04-28 10:23:11 +00:00
static char vStr [ 32 ] ;
2020-01-04 07:13:40 +00:00
if ( beta ) {
if ( FirmwareMinorRevision )
return " BETA " ;
else
return " " ;
}
else {
if ( FirmwareMinorRevision )
sprintf ( vStr , " V%.1f.%d.%d " , float ( FirmwareRevision ) * 0.1f , FirmwareSubRevision , FirmwareMinorRevision ) ;
else
sprintf ( vStr , " V%.1f.%d " , float ( FirmwareRevision ) * 0.1f , FirmwareSubRevision ) ;
}
2019-04-28 10:23:11 +00:00
return vStr ;
}
2019-04-19 11:38:39 +00:00
const char * getVersionDate ( )
{
return FirmwareDate ;
}
int getBoardRevision ( )
{
return BoardRevision ;
2019-04-20 09:13:24 +00:00
}
2019-06-02 20:34:45 +00:00
void ShowOTAScreen ( int percent , eOTAmodes updateType )
2019-05-11 02:18:06 +00:00
{
2019-06-02 20:34:45 +00:00
ScreenManager . showOTAMessage ( percent , updateType ) ;
2019-05-18 08:49:22 +00:00
}
void feedWatchdog ( )
{
2020-05-03 11:59:56 +00:00
# if USE_TWDT == 1
CHECK_ERROR_CODE ( esp_task_wdt_reset ( ) , ESP_OK ) ; //Comment this line to trigger a TWDT timeout
# else
2019-11-22 10:30:45 +00:00
# if USE_SW_WATCHDOG == 1 && USE_JTAG == 0
2019-11-10 04:44:54 +00:00
// BEST NOT USE WATCHDOG WITH JTAG DEBUG :-)
2020-04-20 03:39:39 +00:00
// DebugPort.printf("\r %ld Watchdog fed", millis());
2020-04-22 06:21:24 +00:00
// DebugPort.print("~");
2019-11-22 10:30:45 +00:00
WatchdogTick = 1500 ;
# else
WatchdogTick = - 1 ;
2019-11-10 04:44:54 +00:00
# endif
2020-05-03 11:59:56 +00:00
# endif
2019-05-18 08:49:22 +00:00
}
2019-06-02 09:19:08 +00:00
2019-09-01 07:35:12 +00:00
void doJSONwatchdog ( int topup )
{
2019-11-22 10:30:45 +00:00
if ( topup ) {
JSONWatchdogTick = topup * 100 ;
}
else {
JSONWatchdogTick = - 1 ;
}
2019-09-01 07:35:12 +00:00
}
2019-06-02 09:19:08 +00:00
void doStreaming ( )
{
# if USE_WIFI == 1
2019-12-15 06:58:11 +00:00
if ( NVstore . getUserSettings ( ) . wifiMode ) {
2019-09-11 20:32:21 +00:00
doWiFiManager ( ) ;
2019-06-02 09:19:08 +00:00
# if USE_OTA == 1
2020-04-07 21:51:52 +00:00
doOTA ( ) ;
2019-06-02 09:19:08 +00:00
# endif // USE_OTA
# if USE_WEBSERVER == 1
2019-09-11 20:32:21 +00:00
bHaveWebClient = doWebServer ( ) ;
2019-06-02 09:19:08 +00:00
# endif //USE_WEBSERVER
2019-08-27 13:09:07 +00:00
# if USE_MQTT == 1
2019-09-11 20:32:21 +00:00
// most MQTT is managed via callbacks, but need some sundry housekeeping
doMQTT ( ) ;
2019-08-27 13:09:07 +00:00
# endif
2019-09-11 20:32:21 +00:00
}
2019-06-02 09:19:08 +00:00
# endif // USE_WIFI
checkDebugCommands ( ) ;
KeyPad . update ( ) ; // scan keypad - key presses handler via callback functions!
2019-10-27 00:02:49 +00:00
# if USE_JTAG == 0
2020-05-03 11:59:56 +00:00
# if DBG_FREERTOS == 0
2019-11-10 04:44:54 +00:00
//CANNOT USE GPIO WITH JTAG DEBUG
2019-06-02 09:19:08 +00:00
GPIOin . manage ( ) ;
2019-09-20 23:58:51 +00:00
GPIOout . manage ( ) ;
2019-06-02 09:19:08 +00:00
GPIOalg . manage ( ) ;
2020-05-03 11:59:56 +00:00
# endif
2019-10-27 00:02:49 +00:00
# endif
2019-06-02 09:19:08 +00:00
2020-04-11 08:49:52 +00:00
Bluetooth . check ( ) ; // check for Bluetooth activity
2019-06-02 09:19:08 +00:00
// manage changes in Bluetooth connection status
if ( Bluetooth . isConnected ( ) ) {
if ( ! bBTconnected ) {
2019-09-20 23:58:51 +00:00
resetAllJSONmoderators ( ) ; // force full send upon BT client connect
2019-06-02 09:19:08 +00:00
}
bBTconnected = true ;
}
else {
bBTconnected = false ;
}
// manage changes in number of wifi clients
2019-07-07 07:18:38 +00:00
if ( isWebSocketClientChange ( ) ) {
2019-09-20 23:58:51 +00:00
resetAllJSONmoderators ( ) ; // force full send upon increase of Wifi clients
2019-06-02 09:19:08 +00:00
}
DebugPort . handle ( ) ; // keep telnet spy alive
2019-06-04 20:15:12 +00:00
}
void getGPIOinfo ( sGPIO & info )
{
2019-10-27 00:02:49 +00:00
# if USE_JTAG == 0
2019-06-04 20:15:12 +00:00
info . inState [ 0 ] = GPIOin . getState ( 0 ) ;
info . inState [ 1 ] = GPIOin . getState ( 1 ) ;
info . outState [ 0 ] = GPIOout . getState ( 0 ) ;
info . outState [ 1 ] = GPIOout . getState ( 1 ) ;
info . algVal = GPIOalg . getValue ( ) ;
2019-08-07 12:04:20 +00:00
info . in1Mode = GPIOin . getMode1 ( ) ;
info . in2Mode = GPIOin . getMode2 ( ) ;
info . out1Mode = GPIOout . getMode1 ( ) ;
info . out2Mode = GPIOout . getMode2 ( ) ;
2019-06-04 20:15:12 +00:00
info . algMode = GPIOalg . getMode ( ) ;
2019-10-27 00:02:49 +00:00
# endif
2019-06-04 20:15:12 +00:00
}
// hook for JSON input, simulating a GPIO key press
void simulateGPIOin ( uint8_t newKey )
{
2019-10-27 00:02:49 +00:00
# if USE_JTAG == 0
2019-06-04 20:15:12 +00:00
GPIOin . simulateKey ( newKey ) ;
2019-10-27 00:02:49 +00:00
# endif
2019-07-06 13:46:20 +00:00
}
2019-07-21 11:17:54 +00:00
float getBatteryVoltage ( bool fast )
2019-07-06 13:46:20 +00:00
{
# ifdef RAW_SAMPLES
return getHeaterInfo ( ) . getBattVoltage ( ) ;
# else
2019-07-21 11:17:54 +00:00
if ( fast )
return FilteredSamples . FastipVolts . getValue ( ) ;
else
return FilteredSamples . ipVolts . getValue ( ) ;
2019-07-06 13:46:20 +00:00
# endif
}
float getGlowVolts ( )
{
# ifdef RAW_SAMPLES
return getHeaterInfo ( ) . getGlow_Voltage ( ) ;
# else
return FilteredSamples . GlowVolts . getValue ( ) ;
# endif
}
float getGlowCurrent ( )
{
# ifdef RAW_SAMPLES
return getHeaterInfo ( ) . getGlow_Current ( ) ;
# else
return FilteredSamples . GlowAmps . getValue ( ) ;
# endif
}
2019-09-20 23:58:51 +00:00
int getFanSpeed ( )
2019-07-06 13:46:20 +00:00
{
# ifdef RAW_SAMPLES
return getHeaterInfo ( ) . getFan_Actual ( ) ;
# else
2019-09-20 23:58:51 +00:00
return ( int ) FilteredSamples . Fan . getValue ( ) ;
2019-07-06 13:46:20 +00:00
# endif
}
2020-04-24 23:23:16 +00:00
void updateFilteredData ( CProtocol & HeaterInfo )
2019-07-06 13:46:20 +00:00
{
2020-04-24 23:23:16 +00:00
FilteredSamples . ipVolts . update ( HeaterInfo . getVoltage_Supply ( ) ) ;
FilteredSamples . GlowVolts . update ( HeaterInfo . getGlowPlug_Voltage ( ) ) ;
FilteredSamples . GlowAmps . update ( HeaterInfo . getGlowPlug_Current ( ) ) ;
FilteredSamples . Fan . update ( HeaterInfo . getFan_Actual ( ) ) ;
FilteredSamples . FastipVolts . update ( HeaterInfo . getVoltage_Supply ( ) ) ;
FilteredSamples . FastGlowAmps . update ( HeaterInfo . getGlowPlug_Current ( ) ) ;
2019-07-15 09:56:36 +00:00
}
int sysUptime ( )
{
return Clock . get ( ) . secondstime ( ) - BootTime ;
2019-07-22 10:58:36 +00:00
}
2019-09-04 10:59:01 +00:00
void resetFuelGauge ( )
{
FuelGauge . reset ( ) ;
}
2020-04-24 23:23:16 +00:00
void setName ( const char * name , int type )
2019-08-10 11:45:28 +00:00
{
sCredentials creds = NVstore . getCredentials ( ) ;
2020-04-24 23:23:16 +00:00
char * pDest = NULL ;
switch ( type ) {
case 0 : pDest = creds . APSSID ; break ;
case 1 : pDest = creds . webUsername ; break ;
case 2 : pDest = creds . webUpdateUsername ; break ;
}
if ( pDest ) {
strncpy ( pDest , name , 31 ) ;
pDest [ 31 ] = 0 ;
}
2019-08-10 11:45:28 +00:00
NVstore . setCredentials ( creds ) ;
NVstore . save ( ) ;
NVstore . doSave ( ) ; // ensure NV storage
2020-04-24 23:23:16 +00:00
if ( type = = 0 ) {
2020-05-03 11:59:56 +00:00
DebugPort . println ( " Restarting ESP to invoke new network credentials " ) ;
DebugPort . handle ( ) ;
// initiate reboot
const char * content [ 2 ] ;
content [ 0 ] = " AP reconfig reset " ;
content [ 1 ] = " initiated " ;
ScreenManager . showRebootMsg ( content , 1000 ) ;
// delay(1000);
// ESP.restart();
}
2019-08-10 11:45:28 +00:00
}
2020-04-24 23:23:16 +00:00
void setPassword ( const char * name , int type )
2019-08-10 11:45:28 +00:00
{
sCredentials creds = NVstore . getCredentials ( ) ;
2020-04-24 23:23:16 +00:00
char * pDest = NULL ;
switch ( type ) {
case 0 : pDest = creds . APpassword ; break ;
case 1 : pDest = creds . webPassword ; break ;
case 2 : pDest = creds . webUpdatePassword ; break ;
}
if ( pDest ) {
strncpy ( pDest , name , 31 ) ;
pDest [ 31 ] = 0 ;
}
2019-08-10 11:45:28 +00:00
NVstore . setCredentials ( creds ) ;
NVstore . save ( ) ;
NVstore . doSave ( ) ; // ensure NV storage
2020-04-24 23:23:16 +00:00
if ( type = = 0 ) {
2020-05-03 11:59:56 +00:00
DebugPort . println ( " Restarting ESP to invoke new network credentials " ) ;
DebugPort . handle ( ) ;
// initate reboot
const char * content [ 2 ] ;
content [ 0 ] = " AP password " ;
content [ 1 ] = " changed " ;
ScreenManager . showRebootMsg ( content , 1000 ) ;
// delay(1000);
// ESP.restart();
}
2020-04-24 23:23:16 +00:00
}
2019-08-31 07:34:56 +00:00
void showMainmenu ( )
{
DebugPort . print ( " \014 " ) ;
DebugPort . println ( " MENU options " ) ;
DebugPort . println ( " " ) ;
DebugPort . printf ( " <B> - toggle raw blue wire data reporting, currently %s \r \n " , bReportBlueWireData ? " ON " : " OFF " ) ;
DebugPort . printf ( " <J> - toggle output JSON reporting, currently %s \r \n " , bReportJSONData ? " ON " : " OFF " ) ;
DebugPort . println ( " <M> - configure MQTT " ) ;
2020-04-26 06:15:08 +00:00
DebugPort . println ( " <S> - configure Security " ) ;
2019-08-31 07:34:56 +00:00
DebugPort . println ( " <+> - request heater turns ON " ) ;
DebugPort . println ( " <-> - request heater turns OFF " ) ;
2020-04-24 23:23:16 +00:00
DebugPort . println ( " <CTRL-R> - restart the ESP " ) ;
DebugPort . printf ( " <CTRL-C> - toggle reporting of state machine transits %s \r \n " , CommState . isReporting ( ) ? " ON " : " OFF " ) ;
DebugPort . printf ( " <CTRL-O> - toggle reporting of OEM resync event, currently %s \r \n " , bReportOEMresync ? " ON " : " OFF " ) ;
DebugPort . printf ( " <CTRL-W> - toggle reporting of blue wire timeout/recycling event, currently %s \r \n " , bReportRecyleEvents ? " ON " : " OFF " ) ;
2019-08-31 07:34:56 +00:00
DebugPort . println ( " " ) ;
DebugPort . println ( " " ) ;
DebugPort . println ( " " ) ;
DebugPort . println ( " " ) ;
DebugPort . println ( " " ) ;
DebugPort . println ( " " ) ;
DebugPort . println ( " " ) ;
}
2019-09-16 22:30:49 +00:00
void reloadScreens ( )
{
ScreenManager . reqReload ( ) ;
2019-10-18 01:55:16 +00:00
}
CTempSense & getTempSensor ( )
{
return TempSensor ;
}
2020-01-15 06:52:43 +00:00
2020-03-23 05:54:15 +00:00
void reqHeaterCalUpdate ( )
{
TxManage . queueSysUpdate ( ) ;
}
2020-04-24 23:23:16 +00:00
const CProtocolPackage & getHeaterInfo ( )
{
return BlueWireData ;
}
2020-06-19 01:24:44 +00:00
// int UHFsubcode(int val)
// {
// val &= 0x03;
// val = 0x0001 << val;
// return val;
// }
void checkUHF ( )
{
if ( ! pair433MHz ) {
UHFremote . manage ( ) ;
// unsigned long test = 0xF5F0AC10;
// if(UHFremote.available()) {
// unsigned long code;
// UHFremote.read(code);
// DebugPort.printf("UHF remote code = %08lX\r\n", code);
// unsigned long ID = (test >> 8) & 0xfffff0;
// if(((code ^ ID) & 0xfffff0) == 0) {
// int subCode = code & 0xf;
// if(test & 0x800) {
// if((UHFsubcode(test >> 6) ^ subCode) == 0xf) {
// DebugPort.println("UHF start request!");
// HeaterManager.reqOnOff(true);
// }
// }
// if(test & 0x400) {
// if((UHFsubcode(test >> 4) ^ subCode) == 0xf) {
// DebugPort.println("UHF stop request!");
// HeaterManager.reqOnOff(false);
// }
// }
// if(test & 0x200) {
// if((UHFsubcode(test >> 2) ^ subCode) == 0xf) {
// DebugPort.println("UHF inc temp request!");
// CDemandManager::deltaDemand(+1);
// }
// }
// if(test & 0x100) {
// if((UHFsubcode(test >> 0) ^ subCode) == 0xf) {
// DebugPort.println("UHF dec temp request!");
// CDemandManager::deltaDemand(+1);
// }
// }
// }
// }
}
}