Split websocket handling into a task
Read all added to BME-280 (MariusZ) New security menu in debug/telnet
This commit is contained in:
parent
5cdc5c95a5
commit
9ff2d9410b
|
@ -423,6 +423,129 @@ bool Adafruit_BME280::isReadingCalibration(void) {
|
|||
return (rStatus & (1 << 0)) != 0;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
* Pressure and humidity readings require precise temperature for correctness.
|
||||
* For this reason both readPressure() and readHumidity() call readTemperature() internally,
|
||||
* which results in 2 SPI/I2C transactions for those readings.
|
||||
*
|
||||
* If user code calls a sequence of individual read*() methods to get all sensed values
|
||||
* it may make sense to replace it with a call to this method
|
||||
* and get all readings in 3 SPI/I2C transactions, instead of 5.
|
||||
*
|
||||
* @brief Returns all environmental values sensed
|
||||
* @returns 0 on failure, otherwise a bitwise OR of BME280_{T,P,H}_OK flags
|
||||
* @param readings reference to bme280_readings structure to be filled with data
|
||||
*/
|
||||
int Adafruit_BME280::readAll(bme280_readings& readings)
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
readings.temperature = readTemperature(); // will set t_fine attribute, for immediate reuse
|
||||
|
||||
if (readings.temperature == NAN) // temperature is required for other measurements, abort
|
||||
{
|
||||
readings.humidity = NAN;
|
||||
readings.pressure = NAN;
|
||||
readings.altitude = NAN;
|
||||
return retval;
|
||||
}
|
||||
|
||||
retval |= BME280_T_OK; // temperature read OK
|
||||
|
||||
// t_fine attribute has just been updated by readTemperature(), proceed
|
||||
// below code copied almost verbatim from readPressure()
|
||||
|
||||
int64_t var1, var2, p;
|
||||
int32_t adc_P = read24(BME280_REGISTER_PRESSUREDATA);
|
||||
|
||||
// less readable code, but reading humidity register could be moved here to minimise
|
||||
// time before obtaining t_fine and applying it to humidity calculations
|
||||
// int32_t adc_H = read16(BME280_REGISTER_HUMIDDATA);
|
||||
|
||||
if (adc_P == 0x800000) // value in case pressure measurement was disabled
|
||||
{
|
||||
readings.pressure = NAN;
|
||||
}
|
||||
else
|
||||
{
|
||||
adc_P >>= 4;
|
||||
|
||||
var1 = ((int64_t)t_fine) - 128000;
|
||||
var2 = var1 * var1 * (int64_t)_bme280_calib.dig_P6;
|
||||
var2 = var2 + ((var1 * (int64_t)_bme280_calib.dig_P5) << 17);
|
||||
var2 = var2 + (((int64_t)_bme280_calib.dig_P4) << 35);
|
||||
var1 = ((var1 * var1 * (int64_t)_bme280_calib.dig_P3) >> 8) +
|
||||
((var1 * (int64_t)_bme280_calib.dig_P2) << 12);
|
||||
var1 = (((((int64_t)1) << 47) + var1)) * ((int64_t)_bme280_calib.dig_P1) >> 33;
|
||||
|
||||
if (var1 == 0)
|
||||
{
|
||||
readings.pressure = (float) 0.0; // avoid exception caused by division by zero
|
||||
}
|
||||
else
|
||||
{
|
||||
p = 1048576 - adc_P;
|
||||
p = (((p << 31) - var2) * 3125) / var1;
|
||||
var1 = (((int64_t)_bme280_calib.dig_P9) * (p >> 13) * (p >> 13)) >> 25;
|
||||
var2 = (((int64_t)_bme280_calib.dig_P8) * p) >> 19;
|
||||
|
||||
p = ((p + var1 + var2) >> 8) + (((int64_t)_bme280_calib.dig_P7) << 4);
|
||||
|
||||
readings.pressure = (float) p / 256;
|
||||
retval |= BME280_P_OK; // pressure read OK
|
||||
|
||||
// calculate altitude ref to std sea level pressure
|
||||
readings.altitude = readAltitude(1013.25);
|
||||
}
|
||||
}
|
||||
|
||||
// proceed with reading humidity
|
||||
// again, code copied almost verbatim from readHumidity()
|
||||
// t_fine attribute is assumed to be valid
|
||||
|
||||
int32_t adc_H = read16(BME280_REGISTER_HUMIDDATA);
|
||||
|
||||
if (adc_H == 0x8000)
|
||||
{ // value in case humidity measurement was disabled
|
||||
readings.humidity = NAN;
|
||||
}
|
||||
else
|
||||
{
|
||||
int32_t v_x1_u32r;
|
||||
|
||||
v_x1_u32r = (t_fine - ((int32_t)76800));
|
||||
|
||||
v_x1_u32r = (((((adc_H << 14) - (((int32_t)_bme280_calib.dig_H4) << 20) -
|
||||
(((int32_t)_bme280_calib.dig_H5) * v_x1_u32r)) +
|
||||
((int32_t)16384)) >>
|
||||
15) *
|
||||
(((((((v_x1_u32r * ((int32_t)_bme280_calib.dig_H6)) >> 10) *
|
||||
(((v_x1_u32r * ((int32_t)_bme280_calib.dig_H3)) >> 11) +
|
||||
((int32_t)32768))) >>
|
||||
10) +
|
||||
((int32_t)2097152)) *
|
||||
((int32_t)_bme280_calib.dig_H2) +
|
||||
8192) >>
|
||||
14));
|
||||
|
||||
v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) *
|
||||
((int32_t)_bme280_calib.dig_H1)) >>
|
||||
4));
|
||||
|
||||
v_x1_u32r = (v_x1_u32r < 0) ? 0 : v_x1_u32r;
|
||||
v_x1_u32r = (v_x1_u32r > 419430400) ? 419430400 : v_x1_u32r;
|
||||
|
||||
float h = (v_x1_u32r >> 12);
|
||||
readings.humidity = h / 1024.0;
|
||||
|
||||
retval |= BME280_H_OK; // humidity reading OK
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
* @brief Returns the temperature from the sensor
|
||||
* @returns the temperature read from the device
|
||||
|
|
|
@ -127,13 +127,27 @@ class Adafruit_BME280_Unified : public Adafruit_Sensor
|
|||
|
||||
*/
|
||||
|
||||
/***********************************************************/
|
||||
/*!
|
||||
@brief environment readings combined
|
||||
*/
|
||||
/***********************************************************/
|
||||
typedef struct {
|
||||
float temperature; // temperature sensed [C]
|
||||
float humidity; // humidity sensed [%Rh]
|
||||
float pressure; // pressure sensed [Pa]
|
||||
float altitude; // [m], referenced to std. sea level pressure
|
||||
} bme280_readings;
|
||||
/**************************************************************************/
|
||||
|
||||
/*!
|
||||
@brief Class that stores state and functions for interacting with BME280 IC
|
||||
*/
|
||||
/**************************************************************************/
|
||||
class Adafruit_BME280 {
|
||||
public:
|
||||
/*=========================================================*/
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief sampling rates
|
||||
|
@ -188,6 +202,19 @@ public:
|
|||
STANDBY_MS_1000 = 0b101
|
||||
};
|
||||
|
||||
|
||||
/*******************************************************/
|
||||
/*!
|
||||
@brief read status for readAll()
|
||||
*/
|
||||
/*******************************************************/
|
||||
enum read_success {
|
||||
BME280_T_OK = 0x01,
|
||||
BME280_P_OK = 0x02,
|
||||
BME280_H_OK = 0x04
|
||||
};
|
||||
|
||||
|
||||
// constructors
|
||||
Adafruit_BME280();
|
||||
Adafruit_BME280(int8_t cspin, SPIClass *theSPI = &SPI);
|
||||
|
@ -214,6 +241,8 @@ public:
|
|||
|
||||
float readAltitude(float seaLevel);
|
||||
float seaLevelForAltitude(float altitude, float pressure);
|
||||
int readAll(bme280_readings& readings);
|
||||
|
||||
uint32_t sensorID(void);
|
||||
|
||||
protected:
|
||||
|
|
|
@ -85,10 +85,10 @@ const int _number_of_closed_slots = CONFIG_LWIP_MAX_ACTIVE_TCP;
|
|||
static uint32_t _closed_slots[_number_of_closed_slots];
|
||||
static uint32_t _closed_index = []() {
|
||||
_slots_lock = xSemaphoreCreateBinary();
|
||||
xSemaphoreGive(_slots_lock);
|
||||
for (int i = 0; i < _number_of_closed_slots; ++ i) {
|
||||
_closed_slots[i] = 1;
|
||||
_closed_slots[i] = 1; // slot available
|
||||
}
|
||||
xSemaphoreGive(_slots_lock);
|
||||
return 1;
|
||||
}();
|
||||
|
||||
|
@ -849,21 +849,25 @@ void AsyncClient::_allocate_closed_slot(){
|
|||
}
|
||||
}
|
||||
if (_closed_slot != -1) {
|
||||
_closed_slots[_closed_slot] = 0;
|
||||
_closed_slots[_closed_slot] = 0; // slot in use!
|
||||
}
|
||||
xSemaphoreGive(_slots_lock);
|
||||
}
|
||||
|
||||
void AsyncClient::_free_closed_slot(){
|
||||
xSemaphoreTake(_slots_lock, portMAX_DELAY);
|
||||
if(_closed_slot >= 16 || _closed_slot < -1) {
|
||||
Serial.printf("CLOSED SLOTS BOUNDS!! free_closed_slot (%d)\r\n", _closed_slot);
|
||||
xSemaphoreGive(_slots_lock);
|
||||
return;
|
||||
}
|
||||
if (_closed_slot != -1) {
|
||||
_closed_slots[_closed_slot] = _closed_index;
|
||||
_closed_slots[_closed_slot] = _closed_index; // slot released by index
|
||||
_closed_slot = -1;
|
||||
++ _closed_index;
|
||||
if(_closed_index == 0) _closed_index = 1;
|
||||
}
|
||||
xSemaphoreGive(_slots_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -888,12 +892,12 @@ int8_t AsyncClient::_connected(void* pcb, int8_t err){
|
|||
void AsyncClient::_error(int8_t err) {
|
||||
if(_pcb){
|
||||
tcp_arg(_pcb, NULL);
|
||||
if(_pcb->state == LISTEN) {
|
||||
// if(_pcb->state == LISTEN) {
|
||||
tcp_sent(_pcb, NULL);
|
||||
tcp_recv(_pcb, NULL);
|
||||
tcp_err(_pcb, NULL);
|
||||
tcp_poll(_pcb, NULL, 0);
|
||||
}
|
||||
// }
|
||||
_pcb = NULL;
|
||||
}
|
||||
if(_error_cb) {
|
||||
|
@ -911,12 +915,12 @@ int8_t AsyncClient::_lwip_fin(tcp_pcb* pcb, int8_t err) {
|
|||
return ERR_OK;
|
||||
}
|
||||
tcp_arg(_pcb, NULL);
|
||||
if(_pcb->state == LISTEN) {
|
||||
// if(_pcb->state == LISTEN) {
|
||||
tcp_sent(_pcb, NULL);
|
||||
tcp_recv(_pcb, NULL);
|
||||
tcp_err(_pcb, NULL);
|
||||
tcp_poll(_pcb, NULL, 0);
|
||||
}
|
||||
// }
|
||||
if(tcp_close(_pcb) != ERR_OK) {
|
||||
tcp_abort(_pcb);
|
||||
}
|
||||
|
|
|
@ -152,6 +152,8 @@ void heaterOff();
|
|||
void updateFilteredData(CProtocol& HeaterInfo);
|
||||
bool HandleMQTTsetup(char rxVal);
|
||||
void showMainmenu();
|
||||
bool checkTemperatureSensors();
|
||||
void checkBlueWireEvents();
|
||||
|
||||
// DS18B20 temperature sensor support
|
||||
// Uses the RMT timeslot driver to operate as a one-wire bus
|
||||
|
@ -181,6 +183,7 @@ CGPIOalg GPIOalg;
|
|||
#endif
|
||||
|
||||
CMQTTsetup MQTTmenu;
|
||||
CSecuritySetup SecurityMenu;
|
||||
|
||||
|
||||
|
||||
|
@ -261,14 +264,52 @@ CBluetoothAbstract& getBluetoothClient()
|
|||
return Bluetooth;
|
||||
}
|
||||
|
||||
// collect and report any debug messages from the blue wire task
|
||||
char taskMsg[BLUEWIRE_MSGQUEUESIZE];
|
||||
void checkBlueWireDebugMsgs()
|
||||
|
||||
void checkBlueWireEvents()
|
||||
{
|
||||
// collect and report any debug messages from the blue wire task
|
||||
if(BlueWireMsgBuf && xQueueReceive(BlueWireMsgBuf, taskMsg, 0))
|
||||
DebugPort.print(taskMsg);
|
||||
|
||||
// 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
|
||||
if(RTC_Store.getCyclicEngaged() && (BlueWireRxData.getRunState() == 0) && (BlueWireRxData.getErrState() > 1)) {
|
||||
const char* msg = "Forcing cyclic cancel due to error induced shutdown\r\n";
|
||||
xQueueSend(BlueWireMsgBuf, msg, 0);
|
||||
// DebugPort.println("Forcing cyclic cancel due to error induced shutdown");
|
||||
RTC_Store.setCyclicEngaged(false);
|
||||
}
|
||||
|
||||
pHourMeter->monitor(BlueWireRxData);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// callback function for Keypad events.
|
||||
// must be an absolute function, cannot be a class member due the "this" element!
|
||||
void parentKeyHandler(uint8_t event)
|
||||
|
@ -308,6 +349,19 @@ void WatchdogTask(void * param)
|
|||
}
|
||||
}
|
||||
|
||||
void webSocketTask(void*)
|
||||
{
|
||||
for(;;) {
|
||||
#if USE_WEBSERVER == 1
|
||||
#ifndef OLD_WEBSOCKETHANDLER
|
||||
bHaveWebClient = doWebServer();
|
||||
#endif
|
||||
#endif //USE_WEBSERVER
|
||||
checkWebSocketSend();
|
||||
|
||||
vTaskDelay(1);
|
||||
}
|
||||
}
|
||||
|
||||
//**************************************************************************************************
|
||||
//** **
|
||||
|
@ -340,6 +394,8 @@ extern "C" unsigned long __wrap_millis() {
|
|||
|
||||
void setup() {
|
||||
|
||||
vTaskPrioritySet(NULL, TASK_PRIORITY_ARDUINO); // elevate normal ardion loop etc higher than the usual '1'
|
||||
|
||||
// ensure cyclic mode is disabled after power on
|
||||
bool bESP32PowerUpInit = false;
|
||||
if(rtc_get_reset_reason(0) == 1/* || bForceInit*/) {
|
||||
|
@ -522,13 +578,24 @@ void setup() {
|
|||
TempSensor.getDS18B20().mapSensor(2, NVstore.getHeaterTuning().DS18B20probe[2].romCode);
|
||||
|
||||
// create task to run blue wire interface
|
||||
TaskHandle_t bwTask;
|
||||
TaskHandle_t Task;
|
||||
xTaskCreate(BlueWireTask,
|
||||
"BlueWireTask",
|
||||
2000,
|
||||
NULL,
|
||||
3,
|
||||
&bwTask);
|
||||
TASK_PRIORITY_BLUEWIRE,
|
||||
&Task);
|
||||
|
||||
// create task to run the websockets
|
||||
xTaskCreate(webSocketTask,
|
||||
"WebSocketTask",
|
||||
6000,
|
||||
NULL,
|
||||
TASK_PRIORITY_ARDUINO,
|
||||
&Task);
|
||||
|
||||
|
||||
|
||||
|
||||
delay(1000); // just to hold the splash screeen for while
|
||||
}
|
||||
|
@ -541,23 +608,28 @@ void setup() {
|
|||
|
||||
void loop()
|
||||
{
|
||||
|
||||
float fTemperature;
|
||||
unsigned long timenow = millis();
|
||||
|
||||
// DebugPort.handle(); // keep telnet spy alive
|
||||
|
||||
// report any debug messages from the blue wire task
|
||||
checkBlueWireDebugMsgs();
|
||||
|
||||
feedWatchdog(); // feed watchdog
|
||||
|
||||
doStreaming(); // do wifi, BT tx etc
|
||||
|
||||
Clock.update();
|
||||
|
||||
if(checkTemperatureSensors())
|
||||
ScreenManager.reqUpdate();
|
||||
|
||||
checkDisplayUpdate();
|
||||
|
||||
long tDelta = timenow - lastTemperatureTime;
|
||||
checkBlueWireEvents();
|
||||
|
||||
vTaskDelay(1);
|
||||
} // loop
|
||||
|
||||
|
||||
bool checkTemperatureSensors()
|
||||
{
|
||||
long tDelta = millis() - lastTemperatureTime;
|
||||
if(tDelta > MIN_TEMPERATURE_INTERVAL) { // maintain a minimum holdoff period
|
||||
lastTemperatureTime = millis(); // reset time to observe temeprature
|
||||
|
||||
|
@ -567,6 +639,8 @@ void loop()
|
|||
}
|
||||
|
||||
TempSensor.readSensors();
|
||||
|
||||
float fTemperature;
|
||||
if(TempSensor.getTemperature(0, fTemperature)) { // get Primary sensor temperature
|
||||
if(DS18B20holdoff) {
|
||||
DS18B20holdoff--;
|
||||
|
@ -588,48 +662,10 @@ void loop()
|
|||
|
||||
TempSensor.startConvert(); // request a new conversion, will be ready by the time we loop back around
|
||||
|
||||
ScreenManager.reqUpdate();
|
||||
return true;
|
||||
}
|
||||
|
||||
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
|
||||
if(RTC_Store.getCyclicEngaged() && (BlueWireRxData.getRunState() == 0) && (BlueWireRxData.getErrState() > 1)) {
|
||||
const char* msg = "Forcing cyclic cancel due to error induced shutdown\r\n";
|
||||
xQueueSend(BlueWireMsgBuf, msg, 0);
|
||||
// DebugPort.println("Forcing cyclic cancel due to error induced shutdown");
|
||||
RTC_Store.setCyclicEngaged(false);
|
||||
}
|
||||
|
||||
pHourMeter->monitor(BlueWireRxData);
|
||||
|
||||
}
|
||||
|
||||
|
||||
} // loop
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void manageCyclicMode()
|
||||
{
|
||||
|
@ -827,6 +863,12 @@ void checkDebugCommands()
|
|||
}
|
||||
return;
|
||||
}
|
||||
if(SecurityMenu.Handle(rxVal)) {
|
||||
if(rxVal == 0) {
|
||||
showMainmenu();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(nGetConf) {
|
||||
DebugPort.print(rxVal);
|
||||
|
@ -1130,6 +1172,9 @@ void checkDebugCommands()
|
|||
else if(rxVal == 'm') {
|
||||
MQTTmenu.setActive();
|
||||
}
|
||||
else if(rxVal == 's') {
|
||||
SecurityMenu.setActive();
|
||||
}
|
||||
else if(rxVal == ('o' & 0x1f)) {
|
||||
bReportOEMresync = !bReportOEMresync;
|
||||
DebugPort.printf("Toggled OEM resync event reporting %s\r\n", bReportOEMresync ? "ON" : "OFF");
|
||||
|
@ -1413,7 +1458,9 @@ void doStreaming()
|
|||
doOTA();
|
||||
#endif // USE_OTA
|
||||
#if USE_WEBSERVER == 1
|
||||
#ifdef OLD_WEBSOCKETHANDLER
|
||||
bHaveWebClient = doWebServer();
|
||||
#endif
|
||||
#endif //USE_WEBSERVER
|
||||
#if USE_MQTT == 1
|
||||
// most MQTT is managed via callbacks, but need some sundry housekeeping
|
||||
|
@ -1586,26 +1633,6 @@ void setPassword(const char* name, int type)
|
|||
}
|
||||
}
|
||||
|
||||
void setWebUsername(const char* name)
|
||||
{
|
||||
sCredentials creds = NVstore.getCredentials();
|
||||
strncpy(creds.webUsername, name, 31);
|
||||
creds.webUsername[31] = 0;
|
||||
NVstore.setCredentials(creds);
|
||||
NVstore.save();
|
||||
NVstore.doSave(); // ensure NV storage
|
||||
}
|
||||
|
||||
void setWebPassword(const char* name)
|
||||
{
|
||||
sCredentials creds = NVstore.getCredentials();
|
||||
strncpy(creds.webPassword, name, 31);
|
||||
creds.webPassword[31] = 0;
|
||||
NVstore.setCredentials(creds);
|
||||
NVstore.save();
|
||||
NVstore.doSave(); // ensure NV storage
|
||||
}
|
||||
|
||||
|
||||
void showMainmenu()
|
||||
{
|
||||
|
@ -1614,13 +1641,8 @@ void showMainmenu()
|
|||
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.printf(" <N> - change AP SSID, currently \"%s\"\r\n", NVstore.getCredentials().APSSID);
|
||||
DebugPort.println(" <P> - change AP password");
|
||||
DebugPort.println(" <M> - configure MQTT");
|
||||
DebugPort.println(" <U> - change Web page username");
|
||||
DebugPort.println(" <W> - change Web page password");
|
||||
DebugPort.println(" <Y> - change Web /update username");
|
||||
DebugPort.println(" <Z> - change Web /update password");
|
||||
DebugPort.println(" <S> - configure Security");
|
||||
DebugPort.println(" <+> - request heater turns ON");
|
||||
DebugPort.println(" <-> - request heater turns OFF");
|
||||
DebugPort.println(" <CTRL-R> - restart the ESP");
|
||||
|
|
|
@ -61,6 +61,26 @@ CBME280Screen::show()
|
|||
_printMenuText(80, 26, msg, false);
|
||||
sprintf(msg, "%.0fm", altitude);
|
||||
_printMenuText(80, 36, msg, false);
|
||||
|
||||
// int rv = getTempSensor().getBME280().getAllReadings(readings);
|
||||
// if(rv & Adafruit_BME280::BME280_T_OK)
|
||||
// sprintf(msg, "%.1f`C", readings.temperature);
|
||||
// else
|
||||
// strcpy(msg, "n/a");
|
||||
// _printMenuText(80, 16, msg, false);
|
||||
//
|
||||
// if(rv & Adafruit_BME280::BME280_H_OK)
|
||||
// sprintf(msg, "%.1f%%", readings.humidity);
|
||||
// else
|
||||
// strcpy(msg, "n/a");
|
||||
// _printMenuText(80, 26, msg, false);
|
||||
//
|
||||
// if(rv & Adafruit_BME280::BME280_P_OK)
|
||||
// sprintf(msg, "%.0fm", readings.altitude);
|
||||
// else
|
||||
// strcpy(msg, "n/a");
|
||||
// _printMenuText(80, 36, msg, false);
|
||||
|
||||
}
|
||||
else {
|
||||
_printMenuText(64, 16, "Sensor not found", false, eCentreJustify);
|
||||
|
|
|
@ -84,7 +84,7 @@ CClock::update()
|
|||
_currentTime = _rtc.now(); // moderate I2C accesses
|
||||
Wire.setClock(origClock);
|
||||
_nextRTCfetch = millis() + 500;
|
||||
// _checkTimers();
|
||||
|
||||
// check timers upon minute rollovers
|
||||
if(_currentTime.minute() != _prevMinute) {
|
||||
CTimerManager::manageTime(_currentTime.hour(), _currentTime.minute(), _currentTime.dayOfTheWeek());
|
||||
|
|
|
@ -66,21 +66,30 @@ CGetLine::handle(char rxVal)
|
|||
if(rxVal < ' ') {
|
||||
if(_idx == 0) {
|
||||
if(_pTarget)
|
||||
strcpy(_buffer, _pTarget);
|
||||
strcpy(_buffer, _pTarget); // copy buffer if control upon first key, may well be a enter
|
||||
}
|
||||
if(rxVal == ('x' & 0x1f)) { // CTRL-X - erase string, return done
|
||||
memset(_buffer, 0, sizeof(_buffer));
|
||||
// CTRL-H (backspace)
|
||||
if(rxVal == ('h' & 0x1f)) {
|
||||
if(_idx)
|
||||
_idx--;
|
||||
}
|
||||
// CTRL-X
|
||||
if(rxVal == ('x' & 0x1f)) {
|
||||
memset(_buffer, 0, sizeof(_buffer)); // erase string, return done
|
||||
_zeroTarget();
|
||||
return true;
|
||||
}
|
||||
if(rxVal == '\r') // ignore CR
|
||||
return false;
|
||||
if(rxVal == '\n') { // accept buffered string upon LF, return done
|
||||
_copyTarget();
|
||||
// CR (ala CTRL-M)
|
||||
if(rxVal == '\r')
|
||||
return false; // do nothing upon CR
|
||||
// LF (ala CTRL-J)
|
||||
if(rxVal == '\n') {
|
||||
_copyTarget(); // accept buffered string upon LF, return done
|
||||
return true;
|
||||
}
|
||||
if(rxVal == 0x1b) { // abort, no change upon ESC, return done
|
||||
return true;
|
||||
// ESC
|
||||
if(rxVal == 0x1b) {
|
||||
return true; // abort, no change upon ESC, return done
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -89,10 +98,16 @@ CGetLine::handle(char rxVal)
|
|||
DebugPort.print('*');
|
||||
else
|
||||
DebugPort.print(rxVal);
|
||||
_buffer[_idx++] = rxVal;
|
||||
if(_idx == _maxlen) {
|
||||
_copyTarget();
|
||||
return true;
|
||||
if(rxVal == 0x7f) { // backspace
|
||||
if(_idx)
|
||||
_idx--;
|
||||
}
|
||||
else {
|
||||
_buffer[_idx++] = rxVal;
|
||||
if(_idx == _maxlen) {
|
||||
_copyTarget();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -109,6 +124,11 @@ CGetLine::_doNum(char rxVal)
|
|||
_Numeric = val;
|
||||
return true;
|
||||
}
|
||||
// CTRL-H (backspace)
|
||||
if(rxVal == ('h' & 0x1f)) {
|
||||
if(_idx)
|
||||
_idx--;
|
||||
}
|
||||
if(rxVal == 0x1b) {
|
||||
return true;
|
||||
}
|
||||
|
@ -125,6 +145,11 @@ CGetLine::_doNum(char rxVal)
|
|||
}
|
||||
}
|
||||
else {
|
||||
if(rxVal == 0x7f) { // backspace
|
||||
if(_idx)
|
||||
_idx--;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -183,3 +183,275 @@ CMQTTsetup::HandleMQTTsetup(char rxVal)
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
CSecuritySetup::CSecuritySetup()
|
||||
{
|
||||
_active = false;
|
||||
_password.Idx = 0;
|
||||
_password.State = 0;
|
||||
}
|
||||
|
||||
void
|
||||
CSecuritySetup::setActive()
|
||||
{
|
||||
_active = true;
|
||||
_showMenu(true);
|
||||
}
|
||||
|
||||
void insertDummy(int len);
|
||||
|
||||
void
|
||||
CSecuritySetup::_showMenu(bool init)
|
||||
{
|
||||
_mode = 0;
|
||||
_password.Idx = 0;
|
||||
_password.State = 0;
|
||||
|
||||
DebugPort.enable(true);
|
||||
if(init)
|
||||
_credsSetup = NVstore.getCredentials();
|
||||
|
||||
int len;
|
||||
|
||||
DebugPort.print("\014");
|
||||
DebugPort.println("Security configuration");
|
||||
DebugPort.println("");
|
||||
DebugPort.println(" Access Point credentials");
|
||||
DebugPort.printf(" <1> - set SSID, currently \"%s\"\r\n", _credsSetup.APSSID);
|
||||
DebugPort.print(" <2> - set password");
|
||||
len = strlen(_credsSetup.APpassword);
|
||||
if(len == 0)
|
||||
DebugPort.print(", currently UNRESTRICTED\r\n");
|
||||
else {
|
||||
insertDummy(len);
|
||||
}
|
||||
DebugPort.println("");
|
||||
|
||||
DebugPort.println(" Web page credentials");
|
||||
DebugPort.printf(" <3> - set username, currently \"%s\"\r\n", _credsSetup.webUsername);
|
||||
DebugPort.print(" <4> - set password");
|
||||
len = strlen(_credsSetup.webPassword);
|
||||
if(len == 0)
|
||||
DebugPort.printf(", currently UNRESTRICTED\r\n");
|
||||
else {
|
||||
insertDummy(len);
|
||||
}
|
||||
DebugPort.println("");
|
||||
|
||||
DebugPort.println(" /update web page credentials");
|
||||
DebugPort.printf(" <5> - set username, currently \"%s\"\r\n", _credsSetup.webUpdateUsername);
|
||||
DebugPort.printf(" <6> - set password");
|
||||
len = strlen(_credsSetup.webUpdatePassword);
|
||||
if(len == 0)
|
||||
DebugPort.printf(", UNRESTRICTED!\r\n");
|
||||
else {
|
||||
insertDummy(len);
|
||||
}
|
||||
DebugPort.println("");
|
||||
DebugPort.printf(" <ENTER> - save and exit\r\n");
|
||||
DebugPort.printf(" <ESC> - abort\r\n");
|
||||
|
||||
DebugPort.enable(false); // suppress sundry debug whilst Security menu is active
|
||||
}
|
||||
|
||||
void insertDummy(int len) {
|
||||
char dummy[32];
|
||||
memset(dummy, 0, 32);
|
||||
if(len > 31)
|
||||
len = 31;
|
||||
for(int i = 0; i < len; i++)
|
||||
dummy[i] = '*';
|
||||
DebugPort.printf(" (%s)\r\n", dummy);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
CSecuritySetup::Handle(char& rxVal)
|
||||
{
|
||||
if(_active) {
|
||||
DebugPort.enable(true);
|
||||
_active = _handle(rxVal);
|
||||
if(_active)
|
||||
DebugPort.enable(false);
|
||||
else
|
||||
rxVal = 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
CSecuritySetup::_handle(char rxVal)
|
||||
{
|
||||
bool bJumptoMenuRoot = false;
|
||||
if(_getPassword()) {
|
||||
if(_handlePassword(rxVal)) {
|
||||
if(!_getPassword())
|
||||
_showMenu();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
switch(_mode) {
|
||||
case 0: // initial menu entry selection
|
||||
if(rxVal == 0x1b) {
|
||||
_credsSetup = NVstore.getCredentials();
|
||||
return false;
|
||||
}
|
||||
if(rxVal == '\n') {
|
||||
NVstore.setCredentials(_credsSetup);
|
||||
NVstore.save();
|
||||
return false;
|
||||
}
|
||||
if(rxVal >= '1' && rxVal <= '6') {
|
||||
_mode = rxVal - '0';
|
||||
DebugPort.print("\014");
|
||||
switch(_mode) {
|
||||
case 1:
|
||||
DebugPort.printf("Enter new AP SSID (%s)", _credsSetup.APSSID);
|
||||
_lineInput.reset(_credsSetup.APSSID, 31);
|
||||
break;
|
||||
case 2:
|
||||
DebugPort.print("Enter current AP password");
|
||||
_initPassword(0);
|
||||
break;
|
||||
case 3:
|
||||
DebugPort.printf("Enter new Web page access username (currently '%s', CTRL-X to erase)", _credsSetup.webUsername);
|
||||
_lineInput.reset(_credsSetup.webUsername, 31);
|
||||
break;
|
||||
case 4:
|
||||
DebugPort.print("Enter current web page access password");
|
||||
_initPassword(1);
|
||||
break;
|
||||
case 5:
|
||||
DebugPort.printf("Enter new /update web page access username (currently '%s', CTRL-X to erase)", _credsSetup.webUpdateUsername);
|
||||
_lineInput.reset(_credsSetup.webUpdateUsername, 31);
|
||||
break;
|
||||
case 6:
|
||||
DebugPort.print("Enter current /update web page access password");
|
||||
_initPassword(2);
|
||||
break;
|
||||
}
|
||||
DebugPort.print("... ");
|
||||
}
|
||||
else {
|
||||
_showMenu();
|
||||
}
|
||||
return true;
|
||||
case 1: // enter AP SSID
|
||||
case 2: // enter AP password
|
||||
case 3: // enter web page username
|
||||
case 4: // enter web page password
|
||||
case 5: // enter /update username
|
||||
case 6: // enter /update password
|
||||
if(_lineInput.handle(rxVal)) {
|
||||
bJumptoMenuRoot = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(bJumptoMenuRoot) {
|
||||
_showMenu();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CSecuritySetup::_initPassword(int idx)
|
||||
{
|
||||
_lineInput.reset();
|
||||
_lineInput.maskEntry();
|
||||
_password.Idx = idx;
|
||||
_password.State = 1;
|
||||
}
|
||||
|
||||
bool
|
||||
CSecuritySetup::_getPassword()
|
||||
{
|
||||
return _password.State != 0;
|
||||
}
|
||||
|
||||
bool
|
||||
CSecuritySetup::_handlePassword(char rxVal)
|
||||
{
|
||||
switch(_password.State) {
|
||||
case 1:
|
||||
if(_lineInput.handle(rxVal)) {
|
||||
_password.str1 = _lineInput.getString();
|
||||
_password.str2 = _getCurrentPassword();
|
||||
if(_password.str1 != _password.str2) {
|
||||
DebugPort.println("\r\nPassword does not match existing - ABORTING");
|
||||
_password.State = 0;
|
||||
}
|
||||
else {
|
||||
_password.State = 2;
|
||||
DebugPort.print("\r\nPlease enter new password - ");
|
||||
DebugPort.enable(false); // block other debug msgs whilst we get the password
|
||||
}
|
||||
_lineInput.reset();
|
||||
_lineInput.maskEntry();
|
||||
}
|
||||
return true;
|
||||
case 2:
|
||||
if(_lineInput.handle(rxVal)) {
|
||||
_password.str1 = _lineInput.getString();
|
||||
if(_lineInput.getLen() < 8) {
|
||||
// ABORT - too short
|
||||
DebugPort.println("\r\nNew password must be at least 8 characters - ABORTING");
|
||||
_password.State = 0;
|
||||
}
|
||||
else if(_lineInput.getLen() > 31) {
|
||||
// ABORT - too long!
|
||||
DebugPort.println("\r\nNew password is longer than 31 characters - ABORTING");
|
||||
_password.State = 0;
|
||||
}
|
||||
else {
|
||||
_password.State = 3;
|
||||
DebugPort.print("\r\nPlease confirm new password - ");
|
||||
DebugPort.enable(false); // block other debug msgs whilst we get the password
|
||||
}
|
||||
_lineInput.reset();
|
||||
_lineInput.maskEntry();
|
||||
}
|
||||
return true;
|
||||
case 3:
|
||||
if(_lineInput.handle(rxVal)) {
|
||||
_password.str2 = _lineInput.getString();
|
||||
_lineInput.reset();
|
||||
if(_password.str1 != _password.str2) {
|
||||
DebugPort.println("\r\nNew passwords do not match - ABORTING");
|
||||
_password.State = 0;
|
||||
}
|
||||
else {
|
||||
_password.State = 4;
|
||||
DebugPort.print("\r\nSet new password (y/n) - ");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
case 4:
|
||||
if(rxVal == 'y' || rxVal == 'Y') {
|
||||
_setPassword(_password.str2.c_str());
|
||||
}
|
||||
_password.State = 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const char*
|
||||
CSecuritySetup::_getCurrentPassword() {
|
||||
switch(_password.Idx) {
|
||||
case 0: return _credsSetup.APpassword;
|
||||
case 1: return _credsSetup.webPassword;
|
||||
case 2: return _credsSetup.webUpdatePassword;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void
|
||||
CSecuritySetup::_setPassword(const char* newPW)
|
||||
{
|
||||
switch(_password.Idx) {
|
||||
case 0: strcpy(_credsSetup.APpassword, newPW); break;
|
||||
case 1: strcpy(_credsSetup.webPassword, newPW); break;
|
||||
case 2: strcpy(_credsSetup.webUpdatePassword, newPW); break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,3 +35,26 @@ public:
|
|||
bool Handle(char& rxVal);
|
||||
void setActive();
|
||||
};
|
||||
|
||||
class CSecuritySetup {
|
||||
CGetLine _lineInput;
|
||||
int _mode;
|
||||
bool _active;
|
||||
struct {
|
||||
int Idx;
|
||||
int State;
|
||||
String str1, str2;
|
||||
} _password;
|
||||
sCredentials _credsSetup;
|
||||
bool _handle(char rxVal);
|
||||
void _showMenu(bool init = false);
|
||||
void _initPassword(int idx);
|
||||
bool _getPassword();
|
||||
bool _handlePassword(char rxVal);
|
||||
const char* _getCurrentPassword();
|
||||
void _setPassword(const char* newPW);
|
||||
public:
|
||||
CSecuritySetup();
|
||||
bool Handle(char& rxVal);
|
||||
void setActive();
|
||||
};
|
||||
|
|
|
@ -429,6 +429,7 @@ CBME280Sensor::getTemperature(float& tempReading, bool filtered)
|
|||
float temperature = _bme.readTemperature();
|
||||
update(temperature);
|
||||
_lastSampleTime = millis() + 1000;
|
||||
DebugPort.println("Forced BME sensor reading");
|
||||
}
|
||||
|
||||
CSensor::getTemperature(tempReading, filtered);
|
||||
|
@ -457,6 +458,19 @@ CBME280Sensor::getHumidity(float& reading, bool fresh)
|
|||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
CBME280Sensor::getAllReadings(bme280_readings& readings)
|
||||
{
|
||||
int retval = _bme.readAll(readings);
|
||||
_fAltitude = readings.altitude;
|
||||
_fHumidity = readings.humidity;
|
||||
update(readings.temperature);
|
||||
|
||||
_lastSampleTime = millis() + 1000;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
const char*
|
||||
CBME280Sensor::getID()
|
||||
{
|
||||
|
@ -495,9 +509,8 @@ CTempSense::startConvert()
|
|||
bool
|
||||
CTempSense::readSensors()
|
||||
{
|
||||
float fDummy;
|
||||
getAltitude(fDummy, true);
|
||||
getHumidity(fDummy, true);
|
||||
bme280_readings readings;
|
||||
getBME280().getAllReadings(readings);
|
||||
|
||||
return DS18B20.readSensors();
|
||||
}
|
||||
|
|
|
@ -98,6 +98,7 @@ public:
|
|||
bool getTemperature(float& tempReading, bool filtered) ;
|
||||
bool getAltitude(float& reading, bool fresh=false);
|
||||
bool getHumidity(float& reading, bool fresh=false);
|
||||
int getAllReadings(bme280_readings& readings);
|
||||
const char* getID();
|
||||
int getCount() const { return _count; };
|
||||
};
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "BrowserUpload.h"
|
||||
#include <Update.h>
|
||||
#include "WebContentDL.h"
|
||||
#include <FreeRTOS.h>
|
||||
|
||||
extern WiFiManager wm;
|
||||
extern const char* stdHeader;
|
||||
|
@ -50,6 +51,8 @@ extern const char* updateIndex;
|
|||
extern const char* formatDoneContent;
|
||||
extern const char* rebootIndex;
|
||||
|
||||
QueueHandle_t webSocketQueue = NULL;
|
||||
|
||||
extern void checkSplashScreenUpdate();
|
||||
|
||||
sBrowserUpload BrowserUpload;
|
||||
|
@ -85,6 +88,7 @@ void onUploadProgression();
|
|||
void onRename();
|
||||
void build404Response(String& content, String file);
|
||||
void build500Response(String& content, String file);
|
||||
bool checkWebSocketSend();
|
||||
|
||||
|
||||
const char* getWebContent(bool start) {
|
||||
|
@ -99,6 +103,8 @@ const char* getWebContent(bool start) {
|
|||
|
||||
void initWebServer(void) {
|
||||
|
||||
webSocketQueue = xQueueCreate(10, sizeof(char*));
|
||||
|
||||
if (MDNS.begin("Afterburner")) {
|
||||
DebugPort.println("MDNS responder started");
|
||||
}
|
||||
|
@ -175,13 +181,18 @@ String getContentType(String filename) { // convert the file extension to the MI
|
|||
}
|
||||
|
||||
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
|
||||
if(path.indexOf("index.html") >= 0) {
|
||||
|
||||
if (path.endsWith("/")) path += "index.html"; // If a folder is requested, send the index file in that folder
|
||||
|
||||
if(path.indexOf("index.html") >= 0) { // if referencing
|
||||
sCredentials creds = NVstore.getCredentials();
|
||||
if (!server.authenticate(creds.webUsername, creds.webPassword)) {
|
||||
server.requestAuthentication();
|
||||
return true; // not entirely correct, but avoids 404 response
|
||||
if(strlen(creds.webPassword)) { // optionally present an authentication prompt for /index.html
|
||||
if (!server.authenticate(creds.webUsername, creds.webPassword)) {
|
||||
server.requestAuthentication();
|
||||
return true; // not entirely correct, but avoids 404 response
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -495,13 +506,18 @@ void rootRedirect()
|
|||
server.send(303);
|
||||
}
|
||||
|
||||
|
||||
bool sendWebSocketString(const char* Str)
|
||||
{
|
||||
#ifdef WEBTIMES
|
||||
CProfile profile;
|
||||
#endif
|
||||
|
||||
if(webSocket.connectedClients()) {
|
||||
char* pMsg = new char[strlen(Str)+1];
|
||||
strcpy(pMsg, Str);
|
||||
if(webSocketQueue) xQueueSend(webSocketQueue, &pMsg, 0);
|
||||
|
||||
/* if(webSocket.connectedClients()) {
|
||||
|
||||
#ifdef WEBTIMES
|
||||
unsigned long tCon = profile.elapsed(true);
|
||||
|
@ -516,6 +532,38 @@ bool sendWebSocketString(const char* Str)
|
|||
#endif
|
||||
feedWatchdog();
|
||||
return retval;
|
||||
}*/
|
||||
return false;
|
||||
}
|
||||
|
||||
bool checkWebSocketSend()
|
||||
{
|
||||
bool retval = false;
|
||||
#ifdef WEBTIMES
|
||||
CProfile profile;
|
||||
#endif
|
||||
|
||||
char* pMsg = NULL;
|
||||
if(webSocketQueue && xQueueReceive(webSocketQueue, &pMsg, 0)) {
|
||||
|
||||
if(webSocket.connectedClients()) {
|
||||
|
||||
#ifdef WEBTIMES
|
||||
unsigned long tCon = profile.elapsed(true);
|
||||
#endif
|
||||
|
||||
bTxWebData = true; // OLED tx data animation flag
|
||||
if(pMsg)
|
||||
retval = webSocket.broadcastTXT(pMsg);
|
||||
|
||||
#ifdef WEBTIMES
|
||||
unsigned long tWeb = profile.elapsed(true);
|
||||
DebugPort.printf("Websend times : %ld,%ld\r\n", tCon, tWeb);
|
||||
#endif
|
||||
// feedWatchdog();
|
||||
delete pMsg;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ void listSPIFFS(const char * dirname, uint8_t levels, String& HTMLreport, int wi
|
|||
|
||||
const char* getWebContent(bool start);
|
||||
void getWebContent(const char* filename);
|
||||
bool checkWebSocketSend();
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -117,3 +117,6 @@
|
|||
//
|
||||
#define USE_SW_WATCHDOG 1
|
||||
|
||||
|
||||
#define TASK_PRIORITY_ARDUINO 3
|
||||
#define TASK_PRIORITY_BLUEWIRE 5
|
||||
|
|
Loading…
Reference in New Issue