Merge branch 'mega' of https://github.com/letscontrolit/ESPEasy into bugfix/P020-send-events-for-derived-values

This commit is contained in:
Ton Huisman
2026-07-12 15:25:57 +02:00
20 changed files with 176 additions and 120 deletions
Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 28 KiB

+1
View File
@@ -6,6 +6,7 @@
// #######################################################################################################
/** Changelog:
* 2026-07-03 tonhuisman: Cap humidity at 100% when applying temperature compensation value
* 2023-07-27 tonhuisman: Revert most below changes and implement PLUGIN_GET_DEVICEVTYPE so the P2P controller validates against the correct
* setting. Setting is only available if a remote data-feed is active, and offers BME280 and BMP280 options only.
* 2023-07-26 tonhuisman: Ignore all humidity data (and log messages) if BMP280 Sensor model is selected
+5 -2
View File
@@ -14,6 +14,8 @@
// Added to the main repository with some optimizations and some limitations.
// As long as the device is not enabled, no RAM is wasted.
//
// @andbad: 2026-07-09
// ADD: 72x40 OLED size added to the the existing sizes (128x64, 128x32, 64x48)
// @tonhuisman: 2025-03-03
// ADD: Setting for not showing the startup logo. Formatted source using Uncrustify with recent settings
// @uwekaditz: 2024-08-06
@@ -305,8 +307,9 @@ boolean Plugin_036(uint8_t function, struct EventStruct *event, String& string)
const int optionValues[] =
{ static_cast<int>(p036_resolution::pix128x64),
static_cast<int>(p036_resolution::pix128x32),
static_cast<int>(p036_resolution::pix64x48) };
OLedFormSizes(F("size"), optionValues, P036_RESOLUTION, true);
static_cast<int>(p036_resolution::pix64x48),
static_cast<int>(p036_resolution::pix72x40) };
OLedFormSizes(F("size"), optionValues, P036_RESOLUTION, NR_ELEMENTS(optionValues), true);
}
OLedFormRotation(F("rotate"), P036_ROTATE);
+8 -5
View File
@@ -17,11 +17,14 @@
// ########################## Adapted to ESPEasy 2.0 by Jochen Krapf #####################################
// #######################################################################################################
// Changelog:
// 2023-04-28 @iz8mbw: Rename sensor to SHT3x from SHT30/31/35
// 2021-06-12 @tonhuisman: Add temperature offset setting, with humidity compensation method 'borrowed' from BME280 sensor
// 2020-?? @TD-er: Maitenance updates
// 2017-07-18 @JK-de: Plugin adaption for ESPEasy 2.0
/** Changelog:
* 2026-07-03 tonhuisman: Cap humidity at 100% when applying temperature compensation value
* Reformat Changelog
* 2023-04-28 @iz8mbw: Rename sensor to SHT3x from SHT30/31/35
* 2021-06-12 @tonhuisman: Add temperature offset setting, with humidity compensation method 'borrowed' from BME280 sensor
* 2020-?? @TD-er: Maitenance updates
* 2017-07-18 @JK-de: Plugin adaption for ESPEasy 2.0
*/
# define PLUGIN_068
# define PLUGIN_ID_068 68
+3 -1
View File
@@ -27,6 +27,7 @@
*/
/** History:
* 2026-07-03 tonhuisman: Cap humidity at 100% when applying temperature compensation value
* 2024-12-21 chromoxdor: Add temperature offset + simple humidity compensation
* 2024-12-03 tonhuisman: Add alternative initialization for AHT10 (clone), see https://github.com/letscontrolit/ESPEasy/issues/5172
* Small code optimization.
@@ -155,6 +156,7 @@ boolean Plugin_105(uint8_t function, struct EventStruct *event, String& string)
FormSelectorOptions selector(optionCount, options, indices);
selector.reloadonchange = true;
selector.addFormSelector(F("Sensor model"), F("ahttype"), P105_AHT_TYPE);
// addFormNote(F("Changing Sensor model will reload the page."));
if (static_cast<int>(AHTx_device_type::AHT10_DEVICE) == P105_AHT_TYPE) {
@@ -220,7 +222,7 @@ boolean Plugin_105(uint8_t function, struct EventStruct *event, String& string)
P105_data->state = AHTx_state::AHTx_Values_read;
UserVar.setFloat(event->TaskIndex, 0, P105_data->getTemperature() + (P105_TEMPERATURE_OFFSET / 10.0f));
UserVar.setFloat(event->TaskIndex, 1, P105_data->getHumidity() * (1 - 0.005f * P105_TEMPERATURE_OFFSET));
UserVar.setFloat(event->TaskIndex, 1, min(P105_data->getHumidity() * (1 - 0.005f * P105_TEMPERATURE_OFFSET), 100.0f));
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
addLogMove(LOG_LEVEL_INFO, strformat(F("%s : Addr: 0x%02x"), P105_data->getDeviceName().c_str(), P105_I2C_ADRESS));
+13 -34
View File
@@ -7,6 +7,7 @@
// #######################################################################################################
/** Changelog:
* 2026-06-30 tonhuisman: Code optimization by moving ul2stringFixed to StringConverter_Numerical
* 2025-01-12 tonhuisman: Add support for MQTT AutoDiscovery (not supported for Shift registers)
* 2022-02-27 tonhuisman: Rename plugin title to Output - Shift registers (74HC595)
* 2022-02-25 tonhuisman: Again rename commands, now using separate prefix shiftout and the rest of the previous command as subcommand.
@@ -59,19 +60,6 @@
# include "./src/PluginStructs/P126_data_struct.h"
// TODO tonhuisman: ? Move to StringConverter ? though it is a bit specific, can also be used by P129
String P126_ul2stringFixed(uint32_t value, uint8_t base) {
uint64_t val = static_cast<uint64_t>(value);
val &= 0x0ffffffff; // Keep 32 bits
val |= 0x100000000; // Set bit just left of 32 bits so we will see the leading zeroes
String valStr = ull2String(val, base);
valStr.remove(0, 1); // Delete leading 1 we added
valStr.toUpperCase(); // uppercase hex for readability
return valStr;
}
boolean Plugin_126(uint8_t function, struct EventStruct *event, String& string)
{
boolean success = false;
@@ -286,15 +274,16 @@ boolean Plugin_126(uint8_t function, struct EventStruct *event, String& string)
(P126_CONFIG_FLAGS_GET_OUTPUT_SELECTION == P126_OUTPUT_HEXBIN)) {
string += '0';
string += (P126_CONFIG_FLAGS_GET_VALUES_DISPLAY ? 'b' : 'x');
string += P126_ul2stringFixed(UserVar.getUint32(event->TaskIndex, event->idx),
# ifdef P126_SHOW_VALUES
(P126_CONFIG_FLAGS_GET_VALUES_DISPLAY ? BIN :
# endif // ifdef P126_SHOW_VALUES
HEX
# ifdef P126_SHOW_VALUES
)
# endif // ifdef P126_SHOW_VALUES
);
string += ul2stringFixed(UserVar.getUint32(event->TaskIndex, event->idx),
# ifdef P126_SHOW_VALUES
(P126_CONFIG_FLAGS_GET_VALUES_DISPLAY ? BIN :
# endif // ifdef P126_SHOW_VALUES
HEX
# ifdef P126_SHOW_VALUES
)
# endif // ifdef P126_SHOW_VALUES
, 1 == event->ParN[event->idx]);
}
success = true;
break;
@@ -308,21 +297,15 @@ boolean Plugin_126(uint8_t function, struct EventStruct *event, String& string)
const String abcd = F("ABCDEFGH"); // In case anyone dares to extend
// VARS_PER_TASK to 8...
const uint16_t endCheck = P126_CONFIG_CHIP_COUNT + (P126_CONFIG_CHIP_COUNT == 255 ? 3 : 4); // 4(.0) = nr of bytes in an uint32_t.
const uint16_t maxVar = min(static_cast<uint8_t>(VARS_PER_TASK), static_cast<uint8_t>(ceil(P126_CONFIG_CHIP_COUNT / 4.0)));
uint8_t dotInsert;
uint8_t dotOffset;
const uint16_t maxVar = min(static_cast<uint8_t>(VARS_PER_TASK), static_cast<uint8_t>(ceilf(P126_CONFIG_CHIP_COUNT / 4.0f)));
for (uint16_t varNr = 0; varNr < maxVar; ++varNr) {
if (P126_CONFIG_FLAGS_GET_VALUES_DISPLAY) {
label = F("Bin");
state = F("0b");
dotInsert = 10;
dotOffset = 9;
} else {
label = F("Hex");
state = F("0x");
dotInsert = 4;
dotOffset = 3;
}
label += strformat(F(" State_%s "), abcd.substring(varNr, varNr + 1).c_str());
@@ -331,11 +314,7 @@ boolean Plugin_126(uint8_t function, struct EventStruct *event, String& string)
label += (P126_CONFIG_SHOW_OFFSET + (4 * varNr) + 1); // 4 = nr of bytes in an uint32_t.
if ((P126_CONFIG_SHOW_OFFSET + (4 * varNr) + 4) <= endCheck) { // Only show if still in range
state += P126_ul2stringFixed(UserVar.getUint32(event->TaskIndex, varNr), P126_CONFIG_FLAGS_GET_VALUES_DISPLAY ? BIN : HEX);
for (uint8_t i = 0; i < 3; ++i, dotInsert += dotOffset) { // Insert readability separators
state = state.substring(0, dotInsert) + '.' + state.substring(dotInsert);
}
state += ul2stringFixed(UserVar.getUint32(event->TaskIndex, varNr), P126_CONFIG_FLAGS_GET_VALUES_DISPLAY ? BIN : HEX, true);
pluginWebformShowValue(event->TaskIndex, VARS_PER_TASK + varNr, label, state, true);
}
}
+22 -42
View File
@@ -7,6 +7,7 @@
// #######################################################################################################
/** Changelog:
* 2026-06-30 tonhuisman: Code optimization by moving ul2stringFixed to StringConverter_Numerical
* 2025-06-14 tonhuisman: Add support for Custom Value Type per task value
* 2025-01-12 tonhuisman: Add support for MQTT AutoDiscovery (not supported for Shift registers)
* 2023-01-04 tonhuisman: Use DIRECT_pin GPIO functions for faster GPIO handling (mostly on ESP32), string optimization
@@ -43,19 +44,6 @@
# include "./src/PluginStructs/P129_data_struct.h"
// TODO tonhuisman: ? Move to StringConverter ? though it is a bit specific, can also be used by P126
String P129_ul2stringFixed(uint32_t value, uint8_t base) {
// Set bit just left of 32 bits so we will see the leading zeroes
const uint64_t val = static_cast<uint64_t>(value) | 0x100000000ull;
String valStr = ull2String(val, base).substring(1); // Delete leading 1 we added
if (base == HEX) {
valStr.toUpperCase(); // uppercase hex for readability
}
return valStr;
}
boolean Plugin_129(uint8_t function, struct EventStruct *event, String& string)
{
boolean success = false;
@@ -146,7 +134,7 @@ boolean Plugin_129(uint8_t function, struct EventStruct *event, String& string)
case PLUGIN_GET_DEVICEVALUECOUNT:
{
event->Par1 = min(static_cast<uint8_t>(VARS_PER_TASK),
static_cast<uint8_t>(ceil(P129_CONFIG_CHIP_COUNT / 4.0f)));
static_cast<uint8_t>(ceilf(P129_CONFIG_CHIP_COUNT / 4.0f)));
success = true;
break;
}
@@ -155,7 +143,7 @@ boolean Plugin_129(uint8_t function, struct EventStruct *event, String& string)
{
event->sensorType = static_cast<Sensor_VType>(
min(static_cast<uint8_t>(VARS_PER_TASK),
static_cast<uint8_t>(ceil(P129_CONFIG_CHIP_COUNT / 4.0f))));
static_cast<uint8_t>(ceilf(P129_CONFIG_CHIP_COUNT / 4.0f))));
event->idx = 0;
success = true;
break;
@@ -187,6 +175,7 @@ boolean Plugin_129(uint8_t function, struct EventStruct *event, String& string)
F("Number of chips (Q7 &rarr; DS)"), F("chipcnt"), P129_CONFIG_CHIP_COUNT);
addUnit(concat(F("Daisychained 1.."), P129_MAX_CHIP_COUNT));
# ifndef LIMIT_BUILD_SIZE
// addFormNote(F("Changing the number of chips will reload the page and update the Event configuration."));
# endif // ifndef LIMIT_BUILD_SIZE
}
@@ -240,12 +229,12 @@ boolean Plugin_129(uint8_t function, struct EventStruct *event, String& string)
if (i % 4 == 0) {
bits = PCONFIG_ULONG(i / 4) & 0x0ffffffff;
off = 0;
# ifndef P129_DEBUG_LOG
# ifdef P129_DEBUG_LOG
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
addLog(LOG_LEVEL_INFO, strformat(F("74HC165 Reading from: %d, bits: %s"), i / 4, P129_ul2stringFixed(bits, BIN).c_str()));
addLog(LOG_LEVEL_INFO, strformat(F("74HC165 Reading from: %d, bits: %s"), i / 4, ul2stringFixed(bits, BIN, false).c_str()));
}
# endif // ifndef P129_DEBUG_LOG
# endif // ifdef P129_DEBUG_LOG
}
html_TR();
addHtml(F("<td align =\"center\">"));
@@ -310,15 +299,15 @@ boolean Plugin_129(uint8_t function, struct EventStruct *event, String& string)
}
PCONFIG_ULONG(i / 4) = bits;
# ifndef P129_DEBUG_LOG
# ifdef P129_DEBUG_LOG
if (loglevelActiveFor(LOG_LEVEL_INFO) && ((i % 4 == 3) || (i == P129_CONFIG_CHIP_COUNT))) {
addLog(LOG_LEVEL_INFO, strformat(F("74HC165 Writing to: %d, offset: %d, bits: %s"),
i / 4,
off * 8,
P129_ul2stringFixed(bits, BIN).c_str()));
ul2stringFixed(bits, BIN, false).c_str()));
}
# endif // ifndef P129_DEBUG_LOG
# endif // ifdef P129_DEBUG_LOG
off++;
}
success = true;
@@ -391,15 +380,16 @@ boolean Plugin_129(uint8_t function, struct EventStruct *event, String& string)
(P129_CONFIG_FLAGS_GET_OUTPUT_SELECTION == P129_OUTPUT_HEXBIN)) {
string += '0';
string += (P129_CONFIG_FLAGS_GET_VALUES_DISPLAY ? 'b' : 'x');
string += P129_ul2stringFixed(UserVar.getUint32(event->TaskIndex, event->idx),
# ifdef P129_SHOW_VALUES
(P129_CONFIG_FLAGS_GET_VALUES_DISPLAY ? BIN :
# endif // ifdef P129_SHOW_VALUES
HEX
# ifdef P129_SHOW_VALUES
)
# endif // ifdef P129_SHOW_VALUES
);
string += ul2stringFixed(UserVar.getUint32(event->TaskIndex, event->idx),
# ifdef P129_SHOW_VALUES
(P129_CONFIG_FLAGS_GET_VALUES_DISPLAY ? BIN :
# endif // ifdef P129_SHOW_VALUES
HEX
# ifdef P129_SHOW_VALUES
)
# endif // ifdef P129_SHOW_VALUES
, 1 == event->ParN[event->idx]);
}
success = true;
break;
@@ -412,21 +402,15 @@ boolean Plugin_129(uint8_t function, struct EventStruct *event, String& string)
state.reserve(40);
const String abcd = F("ABCDEFGH"); // In case anyone dares to extend VARS_PER_TASK to 8...
const uint16_t endCheck = P129_CONFIG_CHIP_COUNT + 4; // 4(.0) = nr of bytes in an uint32_t.
const uint16_t maxVar = min(static_cast<uint8_t>(VARS_PER_TASK), static_cast<uint8_t>(ceil(P129_CONFIG_CHIP_COUNT / 4.0f)));
uint8_t dotInsert;
uint8_t dotOffset;
const uint16_t maxVar = min(static_cast<uint8_t>(VARS_PER_TASK), static_cast<uint8_t>(ceilf(P129_CONFIG_CHIP_COUNT / 4.0f)));
for (uint16_t varNr = 0; varNr < maxVar; ++varNr) {
if (P129_CONFIG_FLAGS_GET_VALUES_DISPLAY) {
label = F("Bin");
state = F("0b");
dotInsert = 10;
dotOffset = 9;
} else {
label = F("Hex");
state = F("0x");
dotInsert = 4;
dotOffset = 3;
}
label += strformat(F(" State_%s "), abcd.substring(varNr, varNr + 1).c_str());
@@ -435,11 +419,7 @@ boolean Plugin_129(uint8_t function, struct EventStruct *event, String& string)
label += (P129_CONFIG_SHOW_OFFSET + (4 * varNr) + 1); // 4 = nr of bytes in an uint32_t.
if ((P129_CONFIG_SHOW_OFFSET + (4 * varNr) + 4) <= endCheck) { // Only show if still in range
state += P129_ul2stringFixed(UserVar.getUint32(event->TaskIndex, varNr), P129_CONFIG_FLAGS_GET_VALUES_DISPLAY ? BIN : HEX);
for (uint8_t i = 0; i < 3; ++i, dotInsert += dotOffset) { // Insert readability separators
state = state.substring(0, dotInsert) + '.' + state.substring(dotInsert);
}
state += ul2stringFixed(UserVar.getUint32(event->TaskIndex, varNr), P129_CONFIG_FLAGS_GET_VALUES_DISPLAY ? BIN : HEX, true);
pluginWebformShowValue(event->TaskIndex, VARS_PER_TASK + varNr, label, state, true);
}
}
+26 -25
View File
@@ -1462,30 +1462,31 @@ void createRuleEvents(struct EventStruct *event) {
for (uint8_t varNr = 0; varNr < valueCount; varNr++) {
eventQueue.add(event->TaskIndex, Cache.getTaskDeviceValueName(event->TaskIndex, varNr), formatUserVarNoCheck(event, varNr));
}
#if FEATURE_STRING_VARIABLES
if (Settings.EventAndLogDerivedTaskValues(event->TaskIndex)) {
taskName.toLowerCase();
auto it = customStringVar.begin();
while (it != customStringVar.end()) {
if (it->first.startsWith(search) && it->first.endsWith(postfix)) {
String valueName = it->first.substring(search.length(), it->first.indexOf('-'));
const String vname2 = getDerivedValueName(taskName, valueName);
if (!vname2.isEmpty()) {
valueName = vname2;
}
if (!it->second.isEmpty()) {
String value(it->second);
value = parseTemplateAndCalculate(value);
eventQueue.add(event->TaskIndex, valueName, value);
}
}
else if (it->first.substring(0, search.length()).compareTo(search) > 0) {
break;
}
++it;
}
}
#endif // if FEATURE_STRING_VARIABLES
}
#if FEATURE_STRING_VARIABLES
if (!Settings.CombineTaskValues_SingleEvent(event->TaskIndex) // Send events of derived values for all sensorTypes when enabled
&& Settings.EventAndLogDerivedTaskValues(event->TaskIndex)) {
taskName.toLowerCase();
auto it = customStringVar.begin();
while (it != customStringVar.end()) {
if (it->first.startsWith(search) && it->first.endsWith(postfix)) {
String valueName = it->first.substring(search.length(), it->first.indexOf('-'));
const String vname2 = getDerivedValueName(taskName, valueName);
if (!vname2.isEmpty()) {
valueName = vname2;
}
if (!it->second.isEmpty()) {
String value(it->second);
value = parseTemplateAndCalculate(value);
eventQueue.add(event->TaskIndex, valueName, value);
}
}
else if (it->first.substring(0, search.length()).compareTo(search) > 0) {
break;
}
++it;
}
}
#endif // if FEATURE_STRING_VARIABLES
}
+9 -1
View File
@@ -952,9 +952,17 @@ void setTaskDevice_to_TaskIndex(pluginID_t taskdevicenumber, taskIndex_t taskInd
PluginCall(PLUGIN_SET_DEFAULTS, &TempEvent, dummy);
PluginCall(PLUGIN_GET_DEVICEVALUENAMES, &TempEvent, dummy); // the plugin should populate ExtraTaskSettings with its default values.
const deviceIndex_t DeviceIndex = getDeviceIndex_from_TaskIndex(taskIndex);
if (!Device[DeviceIndex].TimerOptional) { // Set default delay, unless it's optional...
Settings.TaskDeviceTimer[taskIndex] = Settings.Delay;
}
else {
Settings.TaskDeviceTimer[taskIndex] = 0;
}
#if FEATURE_MQTT_DISCOVER && FEATURE_CUSTOM_TASKVAR_VTYPE && FEATURE_TASKVALUE_UNIT_OF_MEASURE
// Fill in standard Unit of measurement and Value Type, if possible
const deviceIndex_t DeviceIndex = getDeviceIndex_from_TaskIndex(taskIndex);
std::vector<DiscoveryItem> discoveryItems;
MQTT_DiscoveryGetDeviceVType(taskIndex, discoveryItems, getValueCountForTask(taskIndex), dummy);
+5 -3
View File
@@ -66,12 +66,14 @@ void OLedFormContrast(const __FlashStringHelper *id,
void OLedFormSizes(const __FlashStringHelper *id,
const int *values,
uint8_t selectedIndex,
uint8_t optionsSize,
bool reloadOnChange) {
const __FlashStringHelper *options3[] = {
F("128x64"),
F("128x32"),
F("64x48") };
FormSelectorOptions selector(NR_ELEMENTS(options3), options3, values);
F("64x48"),
F("72x40") };
FormSelectorOptions selector(optionsSize, options3, values);
selector.reloadonchange = reloadOnChange;
selector.addFormSelector(
F("Display Size"),
@@ -128,4 +130,4 @@ bool OLedI2CAddressCheck(uint8_t function,
}
return success;
}
#endif
#endif
+1
View File
@@ -31,6 +31,7 @@ void OLedFormContrast(const __FlashStringHelper *id,
void OLedFormSizes(const __FlashStringHelper *id,
const int *values,
uint8_t selectedIndex,
uint8_t optionsSize = 3,
bool reloadOnChange = false);
void OLedSetContrast(OLEDDisplay *_display,
const uint8_t& OLED_contrast);
@@ -95,6 +95,42 @@ String ll2String(int64_t value, uint8_t base) {
}
}
/**
* format an uint32_t with 0-prefixed in the provided base of 2, 16 and insert an optional dot as separator for each byte
* separator only applied for base 2 and 16
*/
String ul2stringFixed(uint32_t value, uint8_t base, bool dotSeparator) {
// Set bit just left of 32 bits so we will see the leading zeroes
const uint64_t val = static_cast<uint64_t>(value) | 0x100000000ull;
String valStr = ull2String(val, base).substring(1); // Delete leading 1 we added
if (base == HEX) {
valStr.toUpperCase(); // uppercase hex for readability
}
if (dotSeparator) {
uint8_t dotInsert{};
uint8_t dotOffset{};
if (BIN == base) {
dotInsert = 10;
dotOffset = 9;
} else
if (HEX == base) {
dotInsert += 4;
dotOffset = 3;
}
if (dotInsert) {
for (uint8_t i = 0; i < 3; ++i, dotInsert += dotOffset) { // Insert readability separators
valStr = valStr.substring(0, dotInsert) + '.' + valStr.substring(dotInsert);
}
}
}
return valStr;
}
String trimTrailingZeros(const String& value) {
String res(value);
int dot_pos = res.lastIndexOf('.');
@@ -35,6 +35,11 @@ String ull2String(uint64_t value,
String ll2String(int64_t value,
uint8_t base = 10);
String ul2stringFixed(uint32_t value,
uint8_t base,
bool dotSeparator);
String trimTrailingZeros(const String& value);
String toStringNoZero(int64_t value);
+1 -1
View File
@@ -137,7 +137,7 @@ bool P028_data_struct::updateMeasurements(taskIndex_t task_index) {
log += concat(F(" humidity: "), last_hum_val);
}
# endif // ifndef LIMIT_BUILD_SIZE
last_hum_val = compute_humidity_from_dewpoint(last_temp_val + temp_offset, last_dew_temp_val);
last_hum_val = min(compute_humidity_from_dewpoint(last_temp_val + temp_offset, last_dew_temp_val), 100.0f);
# ifndef LIMIT_BUILD_SIZE
@@ -173,6 +173,10 @@ constexpr tSizeSettings SizeSettings[] = {
{ 64, 48, 32, // 64x48
3, // max. line count
32, 10 // WiFi indicator
},
{ 72, 40, 28, // 72x40
3, // max. line count
28, 12 // WiFi indicator
}
};
@@ -1164,6 +1168,8 @@ tIndividualFontSettings P036_data_struct::CalculateIndividualFontSettings(uint8_
break;
case p036_resolution::pix128x32: lSpace = -2;
break;
case p036_resolution::pix72x40: lSpace = -1;
break;
case p036_resolution::pix64x48: lSpace = -1;
break;
}
@@ -1310,6 +1316,8 @@ tFontSettings P036_data_struct::CalculateFontSettings(uint8_t lDefaultLines) {
break;
case p036_resolution::pix64x48: result.Space = -1;
break;
case p036_resolution::pix72x40: result.Space = -1;
break;
}
iFontIndex = NR_ELEMENTS(FontSizes) - 1;
}
+2 -1
View File
@@ -188,7 +188,8 @@ enum class eHeaderContent : uint8_t {
enum class p036_resolution : uint8_t {
pix128x64 = 0u,
pix128x32 = 1u,
pix64x48 = 2u
pix64x48 = 2u,
pix72x40 = 3u,
};
enum class ePageScrollSpeed : uint8_t {
+1 -1
View File
@@ -47,7 +47,7 @@ void P068_SHT3X::readFromSensor()
if (!essentiallyZero(tmpOff)) {
const float last_dew_temp_val = compute_dew_point_temp(tmp + (tmpOff / 2.0f), hum);
tmp += tmpOff;
hum = compute_humidity_from_dewpoint(tmp, last_dew_temp_val);
hum = min(compute_humidity_from_dewpoint(tmp, last_dew_temp_val), 100.0f);
}
}
}
+1 -1
View File
@@ -35,7 +35,7 @@ bool P126_data_struct::plugin_init(struct EventStruct *event) {
}
const uint16_t maxVar = min(static_cast<uint8_t>(VARS_PER_TASK),
static_cast<uint8_t>(ceil((P126_CONFIG_CHIP_COUNT - P126_CONFIG_SHOW_OFFSET) / 4.0)));
static_cast<uint8_t>(ceilf((P126_CONFIG_CHIP_COUNT - P126_CONFIG_SHOW_OFFSET) / 4.0f)));
uint32_t par;
for (uint16_t varNr = 0; varNr < maxVar; ++varNr) {
+6 -3
View File
@@ -1664,17 +1664,20 @@ void devicePage_show_controller_config(taskIndex_t taskIndex, deviceIndex_t Devi
F("Unchecked: Send event per value. Checked: Send single event (%s#All) containing all values"),
getTaskDeviceName(taskIndex).c_str()));
bool sendDerived{};
# if FEATURE_STRING_VARIABLES
if (!device.HideDerivedValues) {
sendDerived = Settings.EventAndLogDerivedTaskValues(taskIndex);
addFormCheckBox(F("Show derived values"), F("TSDV"), Settings.ShowDerivedTaskValues(taskIndex));
addFormCheckBox(F("Event &amp; Log derived values"), F("TELD"), Settings.EventAndLogDerivedTaskValues(taskIndex));
addFormCheckBox(F("Event &amp; Log derived values"), F("TELD"), sendDerived);
}
# endif // if FEATURE_STRING_VARIABLES
bool separatorAdded = false;
const uint8_t valueCount = getValueCountForTask(taskIndex);
bool separatorAdded = false;
for (controllerIndex_t controllerNr = 0; controllerNr < CONTROLLER_MAX; controllerNr++)
for (controllerIndex_t controllerNr = 0; controllerNr < CONTROLLER_MAX && (valueCount > 0 || sendDerived); controllerNr++)
{
if (Settings.Protocol[controllerNr] != 0)
{
+23
View File
@@ -519,6 +519,29 @@ void handle_json()
#endif // if FEATURE_STRING_VARIABLES
uom);
}
if (Device[DeviceIndex].HasFormatUserVar) {
struct EventStruct TempEvent(TaskIndex);
for (uint8_t x = 0; x < valueCount; x++)
{
String value;
TempEvent.idx = x;
TempEvent.ParN[x] = 1; // Get formatted version of the value
PluginCall(PLUGIN_FORMAT_USERVAR, &TempEvent, value);
if (!value.isEmpty()) {
handle_json_stream_task_value_data(taskValueWriter.get(),
VARS_PER_TASK + x + 1,
Cache.getTaskDeviceValueName(TaskIndex, x),
255,
value,
EMPTY_STRING,
EMPTY_STRING);
}
}
// FIXME tonhuisman: HasFormatUserVar is not really compatible with Derived Values...
}
#if FEATURE_STRING_VARIABLES
if (Settings.ShowDerivedTaskValues(TaskIndex)) {