Compare commits

...
Author SHA1 Message Date
ESPEasy release bot b1c777e6fd automatically updated release notes for mega-20181003 2018-10-03 04:00:18 +02:00
Gijs NoorlanderandGitHub 651353cc99 Merge pull request #1842 from crankyoldgit/patch-2
Acknowledge credit & origin of code used in _P016IR.ino
2018-10-02 13:41:35 +02:00
Gijs NoorlanderandGitHub 85f97551c5 Merge pull request #1841 from crankyoldgit/patch-1
Acknowledge credit & origin of code used in IRTX
2018-10-02 13:41:23 +02:00
David ConranandGitHub 6a158f68f5 Acknowledge credit & origin of code used in _P016IR.ino
FYI @TD-er

Ref: https://github.com/letscontrolit/ESPEasy/pull/1645#issuecomment-422253497
2018-10-02 21:36:18 +10:00
David ConranandGitHub 1933714de5 Acknowledge credit & origin of code used in IRTX
FYI @TD-er

Ref: https://github.com/letscontrolit/ESPEasy/pull/1645#issuecomment-422253497
2018-10-02 21:29:57 +10:00
ESPEasy release bot 545117ddf7 automatically updated release notes for mega-20181002 2018-10-02 04:00:29 +02:00
Gijs NoorlanderandGitHub 8eb479c411 Merge pull request #1837 from TD-er/bugfix/schedule_commands_yield
[Stack] Report stack usage on ESP32 and increase stack for ESP8266normal
2018-10-01 23:27:07 +02:00
TD-er b39f51ca3c [Stack] Report stack usage on ESP32 and increase stack for ESP8266normal
Stack usage on ESP32 is querying current stack, not statistics per RTOS task.
2018-10-01 22:15:32 +02:00
Gijs NoorlanderandGitHub 4511e08d3c Merge pull request #1805 from giig1967g/new/parse
split parseTemplate function
2018-10-01 17:12:21 +02:00
Gijs NoorlanderandGitHub 086e836956 Merge pull request #1836 from TD-er/feature/esp32_pio_1_4_0
[ESP32] Update to platform espressif32@1.4.0
2018-10-01 17:10:45 +02:00
Gijs NoorlanderandGitHub 3e20f617ea Merge pull request #1827 from TD-er/bugfix/DTH_Si7021_reading_stability
[#1798] Bugfix Sonoff Si7021 stability
2018-10-01 17:10:23 +02:00
TD-er 8d9aacb6a4 [ESP32] Update to PIO espressif32@1.4.0
[ESP32 IDF 3.1](https://github.com/espressif/esp-idf/releases/tag/v3.1)
[ESP32 PIO 1.4.0](https://github.com/platformio/platform-espressif32/releases/tag/v1.4.0)
2018-10-01 16:34:21 +02:00
TD-er 0670fa98a6 [ESP32] Add default partition table for reference 2018-10-01 16:32:20 +02:00
TD-er c8ecd8d374 [#1798] Bugfix Sonoff Si7021 stability
See #1798
2018-09-29 22:50:24 +02:00
Plebs 6e7286c6fb split parseTemplate function
simplifying code
2018-09-26 23:40:01 +02:00
10 changed files with 472 additions and 365 deletions
+27
View File
@@ -1,3 +1,30 @@
-------------------------------------------------
Changes in release mega-20181003 (since mega-20181002)
-------------------------------------------------
Release date: Wed Oct 3 04:00:18 CEST 2018
David Conran (2):
Acknowledge credit & origin of code used in IRTX
Acknowledge credit & origin of code used in _P016IR.ino
-------------------------------------------------
Changes in release mega-20181002 (since mega-20181001)
-------------------------------------------------
Release date: Tue Oct 2 04:00:29 CEST 2018
Plebs (1):
split parseTemplate function
TD-er (4):
[#1798] Bugfix Sonoff Si7021 stability
[ESP32] Add default partition table for reference
[ESP32] Update to PIO espressif32@1.4.0
[Stack] Report stack usage on ESP32 and increase stack for ESP8266normal
-------------------------------------------------
Changes in release mega-20181001 (since mega-20180930)
-------------------------------------------------
+7
View File
@@ -0,0 +1,7 @@
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000,
app0, app, ota_0, 0x10000, 0x140000,
app1, app, ota_1, 0x150000,0x140000,
eeprom, data, 0x99, 0x290000,0x1000,
spiffs, data, spiffs, 0x291000,0x16F000,
1 # Name Type SubType Offset Size Flags
2 nvs data nvs 0x9000 0x5000
3 otadata data ota 0xe000 0x2000
4 app0 app ota_0 0x10000 0x140000
5 app1 app ota_1 0x150000 0x140000
6 eeprom data 0x99 0x290000 0x1000
7 spiffs data spiffs 0x291000 0x16F000
+6 -3
View File
@@ -73,11 +73,14 @@ platform = espressif32@1.2.0
[core_esp32_1_3_0]
platform = espressif32@1.3.0
[core_esp32_1_4_0]
platform = espressif32@1.4.0
[core_esp32_stage]
platform = https://github.com/platformio/platform-espressif32.git#feature/stage
[core_esp32]
platform = ${core_esp32_1_3_0.platform}
platform = ${core_esp32_1_4_0.platform}
build_unflags = -Wall
build_flags = -D BUILD_GIT='"${sysenv.TRAVIS_TAG}"'
lib_ignore = AS_BH1750, ESP8266WiFi, ESP8266Ping, ESP8266WebServer, ESP8266HTTPUpdateServer, ESP8266mDNS, IRremoteESP8266, ESPEasy_ESP8266Ping, SerialSensors, SDM
@@ -104,6 +107,7 @@ monitor_speed = 115200
; NO_EXTRA_4K_HEAP - this forces the default NONOS-SDK user's heap location
; Default currently overlaps cont stack (Arduino) with sys stack (System)
; to save up-to 4 kB of heap.
; CONT_STACKSIZE to set the 'cont' (Arduino) stack size. Default = 4096
[common]
board_build.f_cpu = 80000000L
@@ -125,10 +129,9 @@ board = esp12e
platform = ${core_2_4_2.platform}
monitor_speed = 115200
[normal]
platform = ${common.platform}
build_flags = -DNO_EXTRA_4K_HEAP
build_flags = -DNO_EXTRA_4K_HEAP -DCONT_STACKSIZE=5120
[testing]
platform = ${core_2_4_2.platform}
+3
View File
@@ -414,6 +414,9 @@ void addToLog(byte loglevel, const String& string);
void addToLog(byte logLevel, const __FlashStringHelper* flashString);
void statusLED(boolean traffic);
void backgroundtasks();
uint32_t getCurrentFreeStack();
uint32_t getFreeStackWatermark();
bool canYield();
bool getBitFromUL(uint32_t number, byte bitnr);
void setBitToUL(uint32_t& number, byte bitnr, bool value);
+1 -3
View File
@@ -109,9 +109,7 @@ void setup()
WiFi.persistent(false); // Do not use SDK storage of SSID/WPA parameters
WiFi.setAutoReconnect(false);
setWifiMode(WIFI_OFF);
#ifndef ESP32
lowestFreeStack = getFreeStackWatermark();
#endif
lowestFreeStack = getFreeStackWatermark();
lowestRAM = FreeMem();
Plugin_id.resize(PLUGIN_MAX);
+280 -238
View File
@@ -12,11 +12,37 @@ struct tcp_pcb;
extern struct tcp_pcb* tcp_tw_pcbs;
extern "C" void tcp_abort (struct tcp_pcb* pcb);
void tcpCleanup()
{
while(tcp_tw_pcbs!=NULL)
{
tcp_abort(tcp_tw_pcbs);
}
}
#endif
// For keeping track of 'cont' stack
// See: https://github.com/esp8266/Arduino/issues/2557
// https://github.com/esp8266/Arduino/issues/5148#issuecomment-424329183
// https://github.com/letscontrolit/ESPEasy/issues/1824
#ifndef ESP32
#ifdef ESP32
// FIXME TD-er: For ESP32 you need to provide the task number, or NULL to get from the calling task.
uint32_t getCurrentFreeStack() {
register uint8_t *sp asm("a1");
return (sp - pxTaskGetStackStart(NULL));
}
uint32_t getFreeStackWatermark() {
return uxTaskGetStackHighWaterMark(NULL);
}
// FIXME TD-er: Must check if these functions are also needed for ESP32.
bool canYield() { return true; }
#else
#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1)
// All version before core 2.4.2
extern "C" {
@@ -33,6 +59,10 @@ uint32_t getFreeStackWatermark() {
return cont_get_free_stack(&g_cont);
}
bool canYield() {
return cont_can_yield(&g_cont);
}
bool allocatedOnStack(const void* address) {
register uint32_t *sp asm("a1");
if (sp < address) return false;
@@ -59,6 +89,10 @@ uint32_t getFreeStackWatermark() {
return cont_get_free_stack(g_pcont);
}
bool canYield() {
return cont_can_yield(g_pcont);
}
bool allocatedOnStack(const void* address) {
register uint32_t *sp asm("a1");
if (sp < address) return false;
@@ -68,17 +102,6 @@ bool allocatedOnStack(const void* address) {
#endif // ARDUINO_ESP8266_RELEASE_2_x_x
#endif // ESP32
void tcpCleanup()
{
while(tcp_tw_pcbs!=NULL)
{
tcp_abort(tcp_tw_pcbs);
}
}
#endif
bool isDeepSleepEnabled()
{
if (!Settings.deepSleep)
@@ -1421,7 +1444,7 @@ String parseTemplate(String &tmpString, byte lineSize)
{
checkRAM(F("parseTemplate"));
String newString = "";
String tmpStringMid = "";
//String tmpStringMid = "";
newString.reserve(lineSize);
// replace task template variables
@@ -1440,7 +1463,7 @@ String parseTemplate(String &tmpString, byte lineSize)
int rightBracketIndex = tmpString.indexOf(']');
if (rightBracketIndex >= 0)
{
tmpStringMid = tmpString.substring(0, rightBracketIndex);
String tmpStringMid = tmpString.substring(0, rightBracketIndex);
tmpString = tmpString.substring(rightBracketIndex + 1);
int hashtagIndex = tmpStringMid.indexOf('#');
if (hashtagIndex >= 0) {
@@ -1477,232 +1500,14 @@ String parseTemplate(String &tmpString, byte lineSize)
if (valueName.equalsIgnoreCase(ExtraTaskSettings.TaskDeviceValueNames[z]))
{
// here we know the task and value, so find the uservar
// Try to format and transform the values
// y = taskNr
// z = var_of_task
match = true;
bool isvalid;
String value = formatUserVar(y, z, isvalid);
if (isvalid) {
// start changes by giig1967g - 2018-04-20
// Syntax: [task#value#transformation#justification]
// valueFormat="transformation#justification"
if (valueFormat.length() > 0) //do the checks only if a Format is defined to optimize loop
{
String valueJust = "";
hashtagIndex = valueFormat.indexOf('#');
if (hashtagIndex >= 0)
{
valueJust = valueFormat.substring(hashtagIndex + 1); //Justification part
valueFormat = valueFormat.substring(0, hashtagIndex); //Transformation part
}
// valueFormat="transformation"
// valueJust="justification"
if (valueFormat.length() > 0) //do the checks only if a Format is defined to optimize loop
{
const int val = value == "0" ? 0 : 1; //to be used for GPIO status (0 or 1)
const float valFloat = value.toFloat();
String tempValueFormat = valueFormat;
int tempValueFormatLength = tempValueFormat.length();
const int invertedIndex = tempValueFormat.indexOf('!');
const bool inverted = invertedIndex >= 0 ? 1 : 0;
if (inverted)
tempValueFormat.remove(invertedIndex,1);
const int rightJustifyIndex = tempValueFormat.indexOf('R');
const bool rightJustify = rightJustifyIndex >= 0 ? 1 : 0;
if (rightJustify)
tempValueFormat.remove(rightJustifyIndex,1);
tempValueFormatLength = tempValueFormat.length(); //needed because could have been changed after '!' and 'R' removal
//Check Transformation syntax
if (tempValueFormatLength > 0)
{
switch (tempValueFormat[0])
{
case 'V': //value = value without transformations
break;
case 'O':
value = val == inverted ? F("OFF") : F(" ON"); //(equivalent to XOR operator)
break;
case 'C':
value = val == inverted ? F("CLOSE") : F(" OPEN");
break;
case 'M':
value = val == inverted ? F("AUTO") : F(" MAN");
break;
case 'm':
value = val == inverted ? F("A") : F("M");
break;
case 'H':
value = val == inverted ? F("COLD") : F(" HOT");
break;
case 'U':
value = val == inverted ? F("DOWN") : F(" UP");
break;
case 'u':
value = val == inverted ? F("D") : F("U");
break;
case 'Y':
value = val == inverted ? F(" NO") : F("YES");
break;
case 'y':
value = val == inverted ? F("N") : F("Y");
break;
case 'X':
value = val == inverted ? F("O") : F("X");
break;
case 'I':
value = val == inverted ? F("OUT") : F(" IN");
break;
case 'Z' :// return "0" or "1"
value = val == inverted ? F("0") : F("1");
break;
case 'D' ://Dx.y min 'x' digits zero filled & 'y' decimal fixed digits
{
int x;
int y;
x = 0;
y = 0;
switch (tempValueFormatLength)
{
case 2: //Dx
if (isDigit(tempValueFormat[1]))
{
x = (int)tempValueFormat[1]-'0';
}
break;
case 3: //D.y
if (tempValueFormat[1]=='.' && isDigit(tempValueFormat[2]))
{
y = (int)tempValueFormat[2]-'0';
}
break;
case 4: //Dx.y
if (isDigit(tempValueFormat[1]) && tempValueFormat[2]=='.' && isDigit(tempValueFormat[3]))
{
x = (int)tempValueFormat[1]-'0';
y = (int)tempValueFormat[3]-'0';
}
break;
case 1: //D
default: //any other combination x=0; y=0;
break;
}
value = toString(valFloat,y);
int indexDot;
indexDot = value.indexOf('.') > 0 ? value.indexOf('.') : value.length();
for (byte f = 0; f < (x - indexDot); f++)
value = "0" + value;
break;
}
case 'F' :// FLOOR (round down)
value = (int)floorf(valFloat);
break;
case 'E' :// CEILING (round up)
value = (int)ceilf(valFloat);
break;
default:
value = F("ERR");
break;
}
// Check Justification syntax
const int valueJustLength = valueJust.length();
if (valueJustLength > 0) //do the checks only if a Justification is defined to optimize loop
{
value.trim(); //remove right justification spaces for backward compatibility
switch (valueJust[0])
{
case 'P' :// Prefix Fill with n spaces: Pn
if (valueJustLength > 1)
{
if (isDigit(valueJust[1])) //Check Pn where n is between 0 and 9
{
int filler = valueJust[1] - value.length() - '0' ; //char '0' = 48; char '9' = 58
for (byte f = 0; f < filler; f++)
newString += " ";
}
}
break;
case 'S' :// Suffix Fill with n spaces: Sn
if (valueJustLength > 1)
{
if (isDigit(valueJust[1])) //Check Sn where n is between 0 and 9
{
int filler = valueJust[1] - value.length() - '0' ; //48
for (byte f = 0; f < filler; f++)
value += " ";
}
}
break;
case 'L': //left part of the string
if (valueJustLength > 1)
{
if (isDigit(valueJust[1])) //Check n where n is between 0 and 9
{
value = value.substring(0,(int)valueJust[1]-'0');
}
}
break;
case 'R': //Right part of the string
if (valueJustLength > 1)
{
if (isDigit(valueJust[1])) //Check n where n is between 0 and 9
{
value = value.substring(std::max(0,(int)value.length()-((int)valueJust[1]-'0')));
}
}
break;
case 'U': //Substring Ux.y where x=firstChar and y=number of characters
if (valueJustLength > 1)
{
if (isDigit(valueJust[1]) && valueJust[2]=='.' && isDigit(valueJust[3]) && valueJust[1] > '0' && valueJust[3] > '0')
{
value = value.substring(std::min((int)value.length(),(int)valueJust[1]-'0'-1),(int)valueJust[1]-'0'-1+(int)valueJust[3]-'0');
}
else
{
newString += F("ERR");
}
}
break;
default:
newString += F("ERR");
break;
}
}
}
if (rightJustify)
{
int filler = lineSize - newString.length() - value.length() - tmpString.length() ;
for (byte f = 0; f < filler; f++)
newString += " ";
}
{
if (loglevelActiveFor(LOG_LEVEL_DEBUG)) {
String logFormatted = F("DEBUG: Formatted String='");
logFormatted += newString;
logFormatted += value;
logFormatted += "'";
addLog(LOG_LEVEL_DEBUG, logFormatted);
}
}
}
}
//end of changes by giig1967g - 2018-04-18
newString += String(value);
{
if (loglevelActiveFor(LOG_LEVEL_DEBUG_DEV)) {
String logParsed = F("DEBUG DEV: Parsed String='");
logParsed += newString;
logParsed += "'";
addLog(LOG_LEVEL_DEBUG_DEV, logParsed);
}
}
transformValue(newString, lineSize, value, valueFormat, tmpString);
break;
}
}
@@ -1741,6 +1546,245 @@ String parseTemplate(String &tmpString, byte lineSize)
return newString;
}
/********************************************************************************************\
Transform values
\*********************************************************************************************/
// Syntax: [task#value#transformation#justification]
// valueFormat="transformation#justification"
void transformValue(
String& newString,
byte lineSize,
String value,
String& valueFormat,
const String &tmpString)
{
checkRAM(F("transformValue"));
// start changes by giig1967g - 2018-04-20
// Syntax: [task#value#transformation#justification]
// valueFormat="transformation#justification"
if (valueFormat.length() > 0) //do the checks only if a Format is defined to optimize loop
{
String valueJust = "";
int hashtagIndex = valueFormat.indexOf('#');
if (hashtagIndex >= 0)
{
valueJust = valueFormat.substring(hashtagIndex + 1); //Justification part
valueFormat = valueFormat.substring(0, hashtagIndex); //Transformation part
}
// valueFormat="transformation"
// valueJust="justification"
if (valueFormat.length() > 0) //do the checks only if a Format is defined to optimize loop
{
const int val = value == "0" ? 0 : 1; //to be used for GPIO status (0 or 1)
const float valFloat = value.toFloat();
String tempValueFormat = valueFormat;
int tempValueFormatLength = tempValueFormat.length();
const int invertedIndex = tempValueFormat.indexOf('!');
const bool inverted = invertedIndex >= 0 ? 1 : 0;
if (inverted)
tempValueFormat.remove(invertedIndex,1);
const int rightJustifyIndex = tempValueFormat.indexOf('R');
const bool rightJustify = rightJustifyIndex >= 0 ? 1 : 0;
if (rightJustify)
tempValueFormat.remove(rightJustifyIndex,1);
tempValueFormatLength = tempValueFormat.length(); //needed because could have been changed after '!' and 'R' removal
//Check Transformation syntax
if (tempValueFormatLength > 0)
{
switch (tempValueFormat[0])
{
case 'V': //value = value without transformations
break;
case 'O':
value = val == inverted ? F("OFF") : F(" ON"); //(equivalent to XOR operator)
break;
case 'C':
value = val == inverted ? F("CLOSE") : F(" OPEN");
break;
case 'M':
value = val == inverted ? F("AUTO") : F(" MAN");
break;
case 'm':
value = val == inverted ? F("A") : F("M");
break;
case 'H':
value = val == inverted ? F("COLD") : F(" HOT");
break;
case 'U':
value = val == inverted ? F("DOWN") : F(" UP");
break;
case 'u':
value = val == inverted ? F("D") : F("U");
break;
case 'Y':
value = val == inverted ? F(" NO") : F("YES");
break;
case 'y':
value = val == inverted ? F("N") : F("Y");
break;
case 'X':
value = val == inverted ? F("O") : F("X");
break;
case 'I':
value = val == inverted ? F("OUT") : F(" IN");
break;
case 'Z' :// return "0" or "1"
value = val == inverted ? F("0") : F("1");
break;
case 'D' ://Dx.y min 'x' digits zero filled & 'y' decimal fixed digits
{
int x;
int y;
x = 0;
y = 0;
switch (tempValueFormatLength)
{
case 2: //Dx
if (isDigit(tempValueFormat[1]))
{
x = (int)tempValueFormat[1]-'0';
}
break;
case 3: //D.y
if (tempValueFormat[1]=='.' && isDigit(tempValueFormat[2]))
{
y = (int)tempValueFormat[2]-'0';
}
break;
case 4: //Dx.y
if (isDigit(tempValueFormat[1]) && tempValueFormat[2]=='.' && isDigit(tempValueFormat[3]))
{
x = (int)tempValueFormat[1]-'0';
y = (int)tempValueFormat[3]-'0';
}
break;
case 1: //D
default: //any other combination x=0; y=0;
break;
}
value = toString(valFloat,y);
int indexDot;
indexDot = value.indexOf('.') > 0 ? value.indexOf('.') : value.length();
for (byte f = 0; f < (x - indexDot); f++)
value = "0" + value;
break;
}
case 'F' :// FLOOR (round down)
value = (int)floorf(valFloat);
break;
case 'E' :// CEILING (round up)
value = (int)ceilf(valFloat);
break;
default:
value = F("ERR");
break;
}
// Check Justification syntax
const int valueJustLength = valueJust.length();
if (valueJustLength > 0) //do the checks only if a Justification is defined to optimize loop
{
value.trim(); //remove right justification spaces for backward compatibility
switch (valueJust[0])
{
case 'P' :// Prefix Fill with n spaces: Pn
if (valueJustLength > 1)
{
if (isDigit(valueJust[1])) //Check Pn where n is between 0 and 9
{
int filler = valueJust[1] - value.length() - '0' ; //char '0' = 48; char '9' = 58
for (byte f = 0; f < filler; f++)
newString += " ";
}
}
break;
case 'S' :// Suffix Fill with n spaces: Sn
if (valueJustLength > 1)
{
if (isDigit(valueJust[1])) //Check Sn where n is between 0 and 9
{
int filler = valueJust[1] - value.length() - '0' ; //48
for (byte f = 0; f < filler; f++)
value += " ";
}
}
break;
case 'L': //left part of the string
if (valueJustLength > 1)
{
if (isDigit(valueJust[1])) //Check n where n is between 0 and 9
{
value = value.substring(0,(int)valueJust[1]-'0');
}
}
break;
case 'R': //Right part of the string
if (valueJustLength > 1)
{
if (isDigit(valueJust[1])) //Check n where n is between 0 and 9
{
value = value.substring(std::max(0,(int)value.length()-((int)valueJust[1]-'0')));
}
}
break;
case 'U': //Substring Ux.y where x=firstChar and y=number of characters
if (valueJustLength > 1)
{
if (isDigit(valueJust[1]) && valueJust[2]=='.' && isDigit(valueJust[3]) && valueJust[1] > '0' && valueJust[3] > '0')
{
value = value.substring(std::min((int)value.length(),(int)valueJust[1]-'0'-1),(int)valueJust[1]-'0'-1+(int)valueJust[3]-'0');
}
else
{
newString += F("ERR");
}
}
break;
default:
newString += F("ERR");
break;
}
}
}
if (rightJustify)
{
int filler = lineSize - newString.length() - value.length() - tmpString.length() ;
for (byte f = 0; f < filler; f++)
newString += " ";
}
{
if (loglevelActiveFor(LOG_LEVEL_DEBUG)) {
String logFormatted = F("DEBUG: Formatted String='");
logFormatted += newString;
logFormatted += value;
logFormatted += "'";
addLog(LOG_LEVEL_DEBUG, logFormatted);
}
}
}
}
//end of changes by giig1967g - 2018-04-18
newString += String(value);
{
if (loglevelActiveFor(LOG_LEVEL_DEBUG_DEV)) {
String logParsed = F("DEBUG DEV: Parsed String='");
logParsed += newString;
logParsed += "'";
addLog(LOG_LEVEL_DEBUG_DEV, logParsed);
}
}
checkRAM(F("transformValue2"));
}
/********************************************************************************************\
Calculate function for simple expressions
\*********************************************************************************************/
@@ -2966,13 +3010,11 @@ void checkRAM( const __FlashStringHelper* flashString)
lowestRAM = freeRAM;
lowestRAMfunction = flashString;
}
#ifndef ESP32
uint32_t freeStack = getFreeStackWatermark();
if (freeStack < lowestFreeStack) {
lowestFreeStack = freeStack;
lowestFreeStackfunction = flashString;
}
#endif
}
void checkRAM( String &a ) {
-4
View File
@@ -876,14 +876,12 @@ void handle_root() {
TXBuffer += String(lowestRAMfunction);
TXBuffer += F(")");
html_TR_TD(); TXBuffer += F("Free Stack:<TD>");
#ifndef ESP32
TXBuffer += String(getCurrentFreeStack());
TXBuffer += F(" (");
TXBuffer += String(lowestFreeStack);
TXBuffer += F(" - ");
TXBuffer += String(lowestFreeStackfunction);
TXBuffer += F(")");
#endif
html_TR_TD(); TXBuffer += F("IP:<TD>");
TXBuffer += formatIP(ip);
@@ -5259,7 +5257,6 @@ void handle_sysinfo() {
TXBuffer += F(" - ");
TXBuffer += lowestRAMfunction;
TXBuffer += F(")");
#ifndef ESP32
html_TR_TD(); TXBuffer += F("Free Stack<TD>");
TXBuffer += getCurrentFreeStack();
TXBuffer += F(" (");
@@ -5267,7 +5264,6 @@ void handle_sysinfo() {
TXBuffer += F(" - ");
TXBuffer += lowestFreeStackfunction;
TXBuffer += F(")");
#endif
html_TR_TD(); TXBuffer += F("Boot<TD>");
TXBuffer += getLastBootCauseString();
+142 -116
View File
@@ -9,6 +9,19 @@
#define PLUGIN_VALUENAME1_005 "Temperature"
#define PLUGIN_VALUENAME2_005 "Humidity"
#define P005_DHT11 11
#define P005_DHT12 12
#define P005_DHT22 22
#define P005_AM2301 23
#define P005_SI7021 70
#define P005_error_no_reading 1
#define P005_error_protocol_timeout 2
#define P005_error_checksum_error 3
#define P005_error_invalid_NAN_reading 4
#define P005_info_temperature 5
#define P005_info_humidity 6
uint8_t Plugin_005_DHT_Pin;
boolean Plugin_005(byte function, struct EventStruct *event, String& string)
@@ -49,7 +62,7 @@ boolean Plugin_005(byte function, struct EventStruct *event, String& string)
case PLUGIN_WEBFORM_LOAD:
{
const String options[] = { F("DHT 11"), F("DHT 22"), F("DHT 12"), F("Sonoff am2301"), F("Sonoff si7021") };
int indices[] = { 11, 22, 12, 23, 70 };
int indices[] = { P005_DHT11, P005_DHT22, P005_DHT12, P005_AM2301, P005_SI7021 };
addFormSelector(F("DHT Type"), F("plugin_005_dhttype"), 5, options, indices, Settings.TaskDevicePluginConfig[event->TaskIndex][0] );
@@ -67,92 +80,7 @@ boolean Plugin_005(byte function, struct EventStruct *event, String& string)
case PLUGIN_READ:
{
byte dht_dat[5];
byte i;
boolean error = false;
byte Par3 = Settings.TaskDevicePluginConfig[event->TaskIndex][0];
Plugin_005_DHT_Pin = Settings.TaskDevicePin1[event->TaskIndex];
pinMode(Plugin_005_DHT_Pin, OUTPUT);
digitalWrite(Plugin_005_DHT_Pin, LOW); // Pull low
if(Par3 == 11 || Par3 == 22 || Par3 == 12) delay(18);
else if (Par3 == 23 ) delayMicroseconds(900);
else if (Par3 == 70 ) delayMicroseconds(500);
pinMode(Plugin_005_DHT_Pin, INPUT); // change pin to input
delayMicroseconds(50);
error = waitState(0);
if(error)
{ logError(event, F("DHT : no Reading !"));
break;
}
error = waitState(1);
if(error)
{ logError(event, F("DHT : no Reading !"));
break;
}
noInterrupts();
error = waitState(0);
if(error)
{ logError(event, F("DHT : no Reading !"));
break;
}
for (i = 0; i < 5; i++)
{
byte data = Plugin_005_read_dht_dat();
if(data == -1)
{ logError(event, F("DHT : protocol timeout!"));
break;
}
dht_dat[i] = data;
}
interrupts();
// Checksum calculation is a Rollover Checksum by design!
byte dht_check_sum = (dht_dat[0] + dht_dat[1] + dht_dat[2] + dht_dat[3]) & 0xFF; // check check_sum
if (dht_dat[4] != dht_check_sum)
{
logError(event, F("DHT : checksum error!"));
break;
}
float temperature = NAN;
float humidity = NAN;
if (Par3 == 11)
{
temperature = float(dht_dat[2]); // Temperature
humidity = float(dht_dat[0]); // Humidity
}
else if (Par3 == 12)
{
temperature = float(dht_dat[2]*10 + (dht_dat[3] & 0x7f)) / 10.0; // Temperature
if (dht_dat[3] & 0x80) { temperature = -temperature; } // Negative temperature
humidity = float(dht_dat[0]*10+dht_dat[1]) / 10.0; // Humidity
}
else if (Par3 == 22 || Par3 == 23 || Par3 == 70)
{
if (dht_dat[2] & 0x80) // negative temperature
temperature = -0.1 * word(dht_dat[2] & 0x7F, dht_dat[3]);
else
temperature = 0.1 * word(dht_dat[2], dht_dat[3]);
humidity = 0.1 * word(dht_dat[0], dht_dat[1]); // Humidity
}
if (temperature == NAN || humidity == NAN)
{ logError(event, F("DHT : invalid NAN reading !"));
break;
}
UserVar[event->BaseVarIndex] = temperature;
UserVar[event->BaseVarIndex + 1] = humidity;
String log = F("DHT : Temperature: ");
log += UserVar[event->BaseVarIndex];
addLog(LOG_LEVEL_INFO, log);
log = F("DHT : Humidity: ");
log += UserVar[event->BaseVarIndex + 1];
addLog(LOG_LEVEL_INFO, log);
success = true;
success = P005_do_plugin_read(event);
break;
}
}
@@ -163,28 +91,144 @@ boolean Plugin_005(byte function, struct EventStruct *event, String& string)
/*********************************************************************************************\
* DHT sub to log an error
\*********************************************************************************************/
void logError(struct EventStruct *event, String text)
void P005_log(struct EventStruct *event, int logNr)
{
bool isError = true;
String text = F("DHT : ");
switch (logNr) {
case P005_error_no_reading: text += F("No Reading"); break;
case P005_error_protocol_timeout: text += F("Protocol Timeout"); break;
case P005_error_checksum_error: text += F("Checksum Error"); break;
case P005_error_invalid_NAN_reading: text += F("Invalid NAN reading"); break;
case P005_info_temperature:
text += F("Temperature: ");
text += UserVar[event->BaseVarIndex];
isError = false;
break;
case P005_info_humidity:
text += F("Humidity: ");
text += UserVar[event->BaseVarIndex + 1];
isError = false;
break;
}
addLog(LOG_LEVEL_INFO, text);
UserVar[event->BaseVarIndex] = NAN;
UserVar[event->BaseVarIndex + 1] = NAN;
if (isError) {
UserVar[event->BaseVarIndex] = NAN;
UserVar[event->BaseVarIndex + 1] = NAN;
}
}
/*********************************************************************************************\
* DHT sub to wait until a pin is in a certiin state
* DHT sub to wait until a pin is in a certain state
\*********************************************************************************************/
boolean waitState(int state)
boolean P005_waitState(int state)
{
byte counter = 0;
while (( digitalRead(Plugin_005_DHT_Pin) != state) && (counter < 100))
unsigned long timeout = micros() + 100;
while (digitalRead(Plugin_005_DHT_Pin) != state)
{
if (usecTimeOutReached(timeout)) return false;
delayMicroseconds(1);
counter++;
}
if( counter < 100) return false;
return true;
}
/*********************************************************************************************\
* Perform the actual reading + interpreting of data.
\*********************************************************************************************/
bool P005_do_plugin_read(struct EventStruct *event) {
byte i;
byte Par3 = Settings.TaskDevicePluginConfig[event->TaskIndex][0];
Plugin_005_DHT_Pin = Settings.TaskDevicePin1[event->TaskIndex];
pinMode(Plugin_005_DHT_Pin, OUTPUT);
digitalWrite(Plugin_005_DHT_Pin, LOW); // Pull low
switch (Par3) {
case P005_DHT11:
case P005_DHT22:
case P005_DHT12: delay(18); break; // FIXME TD-er: Must this be so long?
case P005_AM2301: delayMicroseconds(900); break;
case P005_SI7021: delayMicroseconds(500); break;
}
switch (Par3) {
case P005_DHT11:
case P005_DHT22:
case P005_DHT12:
case P005_AM2301:
pinMode(Plugin_005_DHT_Pin, INPUT);
delayMicroseconds(50);
break;
case P005_SI7021:
// See: https://github.com/letscontrolit/ESPEasy/issues/1798
digitalWrite(Plugin_005_DHT_Pin, HIGH);
delayMicroseconds(20);
pinMode(Plugin_005_DHT_Pin, INPUT);
break;
}
if(!P005_waitState(0)) {P005_log(event, P005_error_no_reading); return false; }
if(!P005_waitState(1)) {P005_log(event, P005_error_no_reading); return false; }
noInterrupts();
if(!P005_waitState(0)) {P005_log(event, P005_error_no_reading); return false; }
bool readingAborted = false;
byte dht_dat[5];
for (i = 0; i < 5 && !readingAborted; i++)
{
byte data = Plugin_005_read_dht_dat();
if(data == -1)
{ P005_log(event, P005_error_protocol_timeout);
readingAborted = true;
}
dht_dat[i] = data;
}
interrupts();
if (readingAborted)
return false;
// Checksum calculation is a Rollover Checksum by design!
byte dht_check_sum = (dht_dat[0] + dht_dat[1] + dht_dat[2] + dht_dat[3]) & 0xFF; // check check_sum
if (dht_dat[4] != dht_check_sum)
{
P005_log(event, P005_error_checksum_error);
return false;
}
float temperature = NAN;
float humidity = NAN;
switch (Par3) {
case P005_DHT11:
temperature = float(dht_dat[2]); // Temperature
humidity = float(dht_dat[0]); // Humidity
break;
case P005_DHT12:
temperature = float(dht_dat[2]*10 + (dht_dat[3] & 0x7f)) / 10.0; // Temperature
if (dht_dat[3] & 0x80) { temperature = -temperature; } // Negative temperature
humidity = float(dht_dat[0]*10+dht_dat[1]) / 10.0; // Humidity
break;
case P005_DHT22:
case P005_AM2301:
case P005_SI7021:
if (dht_dat[2] & 0x80) // negative temperature
temperature = -0.1 * word(dht_dat[2] & 0x7F, dht_dat[3]);
else
temperature = 0.1 * word(dht_dat[2], dht_dat[3]);
humidity = 0.1 * word(dht_dat[0], dht_dat[1]); // Humidity
break;
}
if (temperature == NAN || humidity == NAN)
{ P005_log(event, P005_error_invalid_NAN_reading);
return false;
}
UserVar[event->BaseVarIndex] = temperature;
UserVar[event->BaseVarIndex + 1] = humidity;
P005_log(event, P005_info_temperature);
P005_log(event, P005_info_humidity);
return true;
}
/*********************************************************************************************\
* DHT sub to get an 8 bit value from the receiving bitstream
\*********************************************************************************************/
@@ -192,31 +236,13 @@ int Plugin_005_read_dht_dat(void)
{
byte i = 0;
byte result = 0;
byte counter = 0;
for (i = 0; i < 8; i++)
{
while ((!digitalRead(Plugin_005_DHT_Pin)) && (counter < 100))
{
delayMicroseconds(1);
counter++;
}
if (counter >= 100)
{
return -1;
}
if (!P005_waitState(1)) return -1;
delayMicroseconds(35); // was 30
if (digitalRead(Plugin_005_DHT_Pin))
result |= (1 << (7 - i));
counter = 0;
while ((digitalRead(Plugin_005_DHT_Pin)) && (counter < 100))
{
delayMicroseconds(1);
counter++;
}
if (counter >= 100)
{
return -1;
}
if (!P005_waitState(0)) return -1;
}
return result;
}
+3
View File
@@ -41,6 +41,9 @@ decode_results results;
#define PLUGIN_NAME_016 "Communication - TSOP4838"
#define PLUGIN_VALUENAME1_016 "IR"
// A lot of the following code has been taken directly (with permission) from the IRrecvDumpV2.ino example code
// of the IRremoteESP8266 library. (https://github.com/markszabo/IRremoteESP8266)
// ==================== start of TUNEABLE PARAMETERS ====================
// As this program is a special purpose capture/decoder, let us use a larger
// than normal buffer so we can handle Air Conditioner remote codes.
+3 -1
View File
@@ -274,6 +274,8 @@ boolean Plugin_035(byte function, struct EventStruct *event, String& string)
return success;
}
// A lot of the following code has been taken directly (with permission) from the IRMQTTServer.ino example code
// of the IRremoteESP8266 library. (https://github.com/markszabo/IRremoteESP8266)
// Parse an Air Conditioner A/C Hex String/code and send it.
// Args:
@@ -615,4 +617,4 @@ uint16_t countValuesInStr(const String str, char sep) {
// }
// return result;
//}
#endif // USES_P035
#endif // USES_P035