Merge pull request #5636 from TD-er/bugfix/1wire_show_sensors

[1Wire] Fix not always showing 1-wire sensor & correct saving sensor
This commit is contained in:
TD-er authored and GitHub committed 2026-09-16 23:58:49 +02:00
commit b1ecd19790
10 files changed
+226 -121

No files matched your search

+23 -15
View File
@@ -27,11 +27,15 @@ jobs:
- uses: actions/setup-python@v7
with:
python-version: '3.13'
- name: Install uv
uses: astral-sh/setup-uv@v7
with:
version: "latest"
enable-cache: false
- name: Build documentation
run: |
cd docs
sudo apt install imagemagick zip
pip install uv
uv pip install --system -r requirements.txt
python ./builds_overview.py
make html
@@ -50,9 +54,13 @@ jobs:
- uses: actions/setup-python@v7
with:
python-version: '3.13'
- name: Install uv
uses: astral-sh/setup-uv@v7
with:
version: "latest"
enable-cache: false
- id: set-matrix
run: |
pip install uv
uv pip install --system pioarduino
python tools/ci/generate-matrix.py
@@ -66,24 +74,24 @@ jobs:
- uses: actions/setup-python@v7
with:
python-version: '3.13'
- name: Dependencies
- name: Install uv
uses: astral-sh/setup-uv@v7
with:
version: "latest"
enable-cache: false
- name: Install dependencies
run: |
sudo apt-get update
sudo apt install binutils build-essential libffi-dev libgit2-dev
pip install uv
uv pip install --system -r requirements.txt
pio pkg update -e ${{ matrix.env }}
uv pip install --system pioarduino
uv pip install --system pygit2>=1.10.1
- name: Get current date
id: date
run: |
echo "builddate=$(date +'%Y%m%d')" >> $GITHUB_OUTPUT
- name: Build and archive
id: build-and-archive
- name: Run PlatformIO
env:
CHIP: ${{ matrix.chip }}
ENV: ${{ matrix.env }}
run: |
python tools/ci/build-and-archive.py
PYTHONIOENCODING: utf-8
PYTHONUTF8: '1'
run: platformio run -e ${{ matrix.env }}
- id: string
uses: Entepotenz/change-string-case-action-min-dependencies@v1
with:
@@ -93,7 +101,7 @@ jobs:
# FIXME Workaround to (temporarily) not use # in the artifact name, see https://github.com/actions/upload-artifact/issues/473
name: Bin-${{ steps.string.outputs.uppercase }}-${{ matrix.env }}-${{ steps.date.outputs.builddate }}_PR_${{ github.event.number }}_${{ github.run_id }} # Sort by ESP type
path: |
bin
./build_output/bin
if-no-files-found: ignore
# Package all ESP82xx and ESP32 into a single ESPEasy-all-Binaries-<date>_PR#<pr_nr>_<runnr>.zip
+3 -3
View File
@@ -5,10 +5,10 @@
[debug_pio]
build_type = debug
;check_tool = clangtidy
check_tool = pvs-studio
check_tool = clangtidy
;check_tool = pvs-studio
check_flags =
pvs-studio: --analysis-mode=4 --errors-off=V532,V586,V795,V1042 --lic-file=../pvs_studio.lic
; pvs-studio: --analysis-mode=4 --errors-off=V532,V586,V795,V1042 --lic-file=../pvs_studio.lic
build_flags = ${compiler_warnings.build_flags}
+1 -1
View File
@@ -1,4 +1,4 @@
pioarduino==6.1.19
pioarduino==6.2.0
pygit2>=1.10.1
cryptography==50.0.0
setuptools>=75.8
+22 -2
View File
@@ -41,6 +41,20 @@ ValueStruct ValueStruct::makeHexFormatted(uint64_t val, uint8_t minNrDigits)
return res;
}
ValueStruct ValueStruct::makeHexDecimalFormatted(uint64_t val,
uint8_t minNrDigits)
{
ValueStruct res(val);
// TODO TD-er: Add factor option for decimal formatted, like in String formatToHex_decimal(uint32_t value, uint32_t factor)
// Or maybe just a flag to make it 'human readable' and maybe whether the factor should be 1000 or 1024.
res.setPreferredFormat(PreferredFormat::Hex_Dec);
res.setMinNrDigits(minNrDigits);
res.setCaseFormat(CaseFormat::ToUpper);
return res;
}
ValueStruct ValueStruct::makeBinFormatted(uint64_t val, uint8_t minNrDigits)
{
ValueStruct res(val);
@@ -685,8 +699,14 @@ size_t ValueStruct::print(Print& out, ValueType& valueType, bool unformatted) co
return out.print(concat(F("0b"), ull2String(u64_val, BIN, _minNrDigits)));
}
if (format == PreferredFormat::Hex) {
return out.print(concat(F("0x"), ull2String(u64_val, HEX, _minNrDigits, '\0', getCaseFormat(unformatted) == CaseFormat::ToUpper)));
if ((format == PreferredFormat::Hex) || (format == PreferredFormat::Hex_Dec)) {
String str = concat(F("0x"), ull2String(u64_val, HEX, _minNrDigits, '\0', getCaseFormat(unformatted) == CaseFormat::ToUpper));
if (format == PreferredFormat::Hex_Dec) {
// Old implementation: formatToHex_decimal
str += strformat(F(" (%s)"), ull2String(u64_val, DEC /*, _minNrDigits*/).c_str());
}
return out.print(std::move(str));
}
if ((_size > 32) || _minNrDigits) {
+6 -2
View File
@@ -46,7 +46,8 @@ public:
enum class PreferredFormat : uint8_t {
Default = 0,
Bin,
Hex
Hex,
Hex_Dec // for example: "0x1234 (4660)"
};
@@ -103,6 +104,8 @@ public:
static ValueStruct makeHexFormatted(uint64_t val,
uint8_t minNrDigits);
static ValueStruct makeHexDecimalFormatted(uint64_t val,
uint8_t minNrDigits);
static ValueStruct makeBinFormatted(uint64_t val,
uint8_t minNrDigits);
@@ -118,7 +121,8 @@ public:
void setInt(size_t val);
#endif
void setIPAddress(const IPAddress& ip, bool includeZone = false);
void setIPAddress(const IPAddress& ip,
bool includeZone = false);
ValueStruct::ValueType getValueType() const
{
+104 -89
View File
@@ -34,6 +34,12 @@
# endif // ifdef ESP32
# ifndef DALLAS_RESET_RETRIES
// Reset may fail if a
# define DALLAS_RESET_RETRIES 3
# endif // ifndef DALLAS_RESET_RETRIES
# include <vector>
unsigned char ROM_NO[8]{ 0 };
@@ -45,7 +51,6 @@ int32_t usec_release{};
int32_t presence_start{};
int32_t presence_end{};
void DALLAS_IRAM_ATTR Dallas_pinModeInput(uint32_t gpio_pin_rx, uint32_t gpio_pin_tx)
{
if (gpio_pin_rx == gpio_pin_tx) {
@@ -132,7 +137,8 @@ int Dallas_measure_rise_time(int8_t gpio_pin_rx, int8_t gpio_pin_tx)
// http://owfs.sourceforge.net/simple_family.html
// https://github.com/owfs/owfs-doc/wiki/1Wire-Device-List
const __FlashStringHelper* Dallas_getModel(uint8_t family, const bool hasFixedResolution) {
switch (family) {
switch (family)
{
case 0x28: return F("DS18B20");
case 0x3b: return hasFixedResolution ? F("MAX31826") : F("DS1825");
case 0x22: return F("DS1822");
@@ -271,13 +277,14 @@ void Dallas_addr_selector_webform_load(taskIndex_t TaskIndex, int8_t gpio_pin_rx
}
const bool selected = (memcmp(tmpAddress, savedAddress, 8) == 0);
addSelector_Item(option, index, selected);
addSelector_Item_index64(option, scan_res[index], selected);
}
addSelector_Foot();
}
}
# ifndef LIMIT_BUILD_SIZE
void Dallas_show_sensor_stats_webform_load(const Dallas_SensorData& sensor_data)
{
if (sensor_data.addr == 0) {
@@ -338,10 +345,10 @@ void Dallas_addr_selector_webform_save(taskIndex_t TaskIndex, int8_t gpio_pin_rx
uint8_t addr[8]{};
for (uint8_t var_index = 0; var_index < nrVariables; ++var_index) {
const int selection = getFormItemInt(concat(F("dallas_addr"), static_cast<int>(var_index)), -1);
const uint64_t selection = getFormItemUInt64(concat(F("dallas_addr"), static_cast<int>(var_index)), 0);
if (selection != -1) {
Dallas_scan(selection, addr, gpio_pin_rx, gpio_pin_tx);
if (selection != 0) {
Dallas_uint64_to_addr(selection, addr);
Dallas_plugin_set_addr(addr, TaskIndex, var_index);
}
}
@@ -411,6 +418,7 @@ uint8_t Dallas_scan(uint8_t getDeviceROM, uint8_t *ROM, int8_t gpio_pin_rx, int8
// read power supply
# ifndef LIMIT_BUILD_SIZE
bool Dallas_is_parasite(const uint8_t ROM[8], int8_t gpio_pin_rx, int8_t gpio_pin_tx, bool& isParasitePowered)
{
if (!Dallas_address_ROM(ROM, gpio_pin_rx, gpio_pin_tx)) {
@@ -435,6 +443,7 @@ bool Dallas_is_parasite(const uint8_t ROM[8], int8_t gpio_pin_rx, int8_t gpio_pi
Dallas_write(0x44, gpio_pin_rx, gpio_pin_tx);
}
*/
/*********************************************************************************************\
* Dallas Read temperature from scratchpad
\*********************************************************************************************/
@@ -535,6 +544,7 @@ Dallas_read_result Dallas_readTemp(const uint8_t ROM[8], float *value, int8_t gp
}
# ifdef USES_P080
bool Dallas_readiButton(const uint8_t addr[8], int8_t gpio_pin_rx, int8_t gpio_pin_tx, int8_t lastState)
{
// maybe this is needed to trigger the reading
@@ -783,113 +793,117 @@ bool Dallas_setResolution(const uint8_t ROM[8], uint8_t res, int8_t gpio_pin_rx,
\*********************************************************************************************/
uint8_t Dallas_reset(int8_t gpio_pin_rx, int8_t gpio_pin_tx)
{
presence_start = 0;
presence_end = 0;
for (uint8_t attempt = 0; attempt < DALLAS_RESET_RETRIES; ++attempt) {
presence_start = 0;
presence_end = 0;
// Keep track of usec_release as it is an indicator for the recovery time
usec_release = Dallas_measure_rise_time(gpio_pin_rx, gpio_pin_tx);
delayMicroseconds(10);
// Keep track of usec_release as it is an indicator for the recovery time
// Only call ISR_noInterrupts(); after this Dallas_measure_rise_time as it also disables interrupts.
usec_release = Dallas_measure_rise_time(gpio_pin_rx, gpio_pin_tx);
delayMicroseconds(10);
ISR_noInterrupts();
ISR_noInterrupts();
# ifdef DEBUG_LOGIC_ANALYZER_PIN
// DEBUG code using logic analyzer for timings
DIRECT_pinWrite(DEBUG_LOGIC_ANALYZER_PIN, 1);
# endif // ifdef DEBUG_LOGIC_ANALYZER_PIN
Dallas_pinInput;
# ifdef DEBUG_LOGIC_ANALYZER_PIN
// DEBUG code using logic analyzer for timings
DIRECT_pinWrite(DEBUG_LOGIC_ANALYZER_PIN, 0);
# endif // ifdef DEBUG_LOGIC_ANALYZER_PIN
// wait until the wire is high... just in case
if (Dallas_waitForPinHigh(gpio_pin_rx, micros(), 250)) {
# ifdef DEBUG_LOGIC_ANALYZER_PIN
// DEBUG code using logic analyzer for timings
DIRECT_pinWrite(DEBUG_LOGIC_ANALYZER_PIN, 1);
# endif // ifdef DEBUG_LOGIC_ANALYZER_PIN
// The master starts a transmission with a reset pulse,
// which pulls the wire to 0 volts for at least 480 µs.
// This resets communication of every slave device on the bus.
Dallas_pinLow;
delayMicroseconds(480); // t_RSTL 480 ... 960 usec
// puling pin high will be very fast, so start measurement before pulling high
const uint32_t start = micros();
Dallas_pinHigh;
// digitalWrite(gpio_pin_tx, 1);
delayMicroseconds(1);
// Set to 'input', state will be pulled high by pull-up resistor
// Or will be kept pulled low by sensor
Dallas_pinInput;
{
Dallas_pinInput;
# ifdef DEBUG_LOGIC_ANALYZER_PIN
// DEBUG code using logic analyzer for timings
DIRECT_pinWrite(DEBUG_LOGIC_ANALYZER_PIN, 0);
// DEBUG code using logic analyzer for timings
DIRECT_pinWrite(DEBUG_LOGIC_ANALYZER_PIN, 0);
# endif // ifdef DEBUG_LOGIC_ANALYZER_PIN
// wait until the wire is high... just in case
if (Dallas_waitForPinHigh(gpio_pin_rx, micros(), 250)) {
# ifdef DEBUG_LOGIC_ANALYZER_PIN
// DEBUG code using logic analyzer for timings
DIRECT_pinWrite(DEBUG_LOGIC_ANALYZER_PIN, 1);
# endif // ifdef DEBUG_LOGIC_ANALYZER_PIN
// The master starts a transmission with a reset pulse,
// which pulls the wire to 0 volts for at least 480 µs.
// This resets communication of every slave device on the bus.
Dallas_pinLow;
delayMicroseconds(480); // t_RSTL 480 ... 960 usec
// puling pin high will be very fast, so start measurement before pulling high
const uint32_t start = micros();
Dallas_pinHigh;
// digitalWrite(gpio_pin_tx, 1);
delayMicroseconds(1);
// Set to 'input', state will be pulled high by pull-up resistor
// Or will be kept pulled low by sensor
Dallas_pinInput;
# ifdef DEBUG_LOGIC_ANALYZER_PIN
// DEBUG code using logic analyzer for timings
DIRECT_pinWrite(DEBUG_LOGIC_ANALYZER_PIN, 0);
# endif // ifdef DEBUG_LOGIC_ANALYZER_PIN
// After that, any slave device, if present, shows that it exists with a "presence" pulse:
// it holds the bus low for at least 60 µs after the master releases the bus.
// This may take about 25 usec after release for present sensors to pull the line low.
// Sequence:
// - Release => pin high (typ: 1 usec as it was actively pulled high by GPIO)
// - Presence condition start (typ: 25 usec after release)
// - Presence condition end (minimal duration 60 usec, typ: 110 usec)
// - Wait till 480 usec after release.
// After that, any slave device, if present, shows that it exists with a "presence" pulse:
// it holds the bus low for at least 60 µs after the master releases the bus.
// This may take about 25 usec after release for present sensors to pull the line low.
// Sequence:
// - Release => pin high (typ: 1 usec as it was actively pulled high by GPIO)
// - Presence condition start (typ: 25 usec after release)
// - Presence condition end (minimal duration 60 usec, typ: 110 usec)
// - Wait till 480 usec after release.
// First check will only be to make sure the pin isn't pulled down for whatever reason
// Since we set the pin to high, this should return immediately
if (Dallas_waitForPinHigh(gpio_pin_rx, start, 15)) {
// Signal fall time will be quite fast, so no correction needed
presence_start = Dallas_measureWaitForPinLow(gpio_pin_rx, start, 60);
// First check will only be to make sure the pin isn't pulled down for whatever reason
// Since we set the pin to high, this should return immediately
if (Dallas_waitForPinHigh(gpio_pin_rx, start, 15)) {
// Signal fall time will be quite fast, so no correction needed
presence_start = Dallas_measureWaitForPinLow(gpio_pin_rx, start, 60);
if (presence_start > 15) {
// t_PDH 15 ... 60 usec
// t_PDL 60 ... 240 usec
if (presence_start > 15) {
// t_PDH 15 ... 60 usec
// t_PDL 60 ... 240 usec
// Signal will rise only due to pull-up resistor
// Meaning measured duration may be off by usec_release (too int32_t)
presence_end = Dallas_measureWaitForPinHigh(gpio_pin_rx, start, 60 + 240);
// Signal will rise only due to pull-up resistor
// Meaning measured duration may be off by usec_release (too int32_t)
presence_end = Dallas_measureWaitForPinHigh(gpio_pin_rx, start, 60 + 240);
// Set the pin high, just in case we have a (single) parasitic powered sensor
Dallas_pinHigh;
// Set the pin high, just in case we have a (single) parasitic powered sensor
Dallas_pinHigh;
// Enable interrupts again as soon as timing-critical section is done
ISR_interrupts();
// Enable interrupts again as soon as timing-critical section is done
ISR_interrupts();
const int32_t presence_duration = presence_end - presence_start;
const int32_t presence_duration = presence_end - presence_start;
if ((presence_duration >= 60) && (presence_duration < (240 /* + usec_release*/))) {
// t_RSTH = 480 usec
const int32_t timeLeft = 480 - usecPassedSince_fast(start);
if ((presence_duration >= 60) && (presence_duration < (240 /* + usec_release*/))) {
// t_RSTH = 480 usec
const int32_t timeLeft = 480 - usecPassedSince_fast(start);
if (timeLeft > 0) {
delayMicroseconds(timeLeft);
if (timeLeft > 0) {
delayMicroseconds(timeLeft);
}
return 1;
}
}
return 1;
}
return 0;
}
// Set the pin high, just in case we have a (single) parasitic powered sensor
Dallas_pinHigh;
ISR_interrupts();
}
}
// Set the pin high, just in case we have a (single) parasitic powered sensor
Dallas_pinHigh;
ISR_interrupts();
return 0;
}
@@ -1176,7 +1190,7 @@ void Dallas_write_bit(uint8_t v, int8_t gpio_pin_rx, int8_t gpio_pin_tx)
// High time is based on the recovery time, which is detected during reset
const int32_t low_time = (v & 1) ? 7 : 60;
const int32_t high_time = (v & 1) ? (40 + usec_release) : (2 * usec_release + 20); // Recovery time
uint32_t start = 0;
uint32_t start = 0;
Dallas_write_bit_ISR(v, gpio_pin_rx, gpio_pin_tx, low_time, high_time, start);
@@ -1191,8 +1205,8 @@ void Dallas_write_bit(uint8_t v, int8_t gpio_pin_rx, int8_t gpio_pin_tx)
void DALLAS_IRAM_ATTR Dallas_write_bit_ISR(uint8_t v,
int8_t gpio_pin_rx,
int8_t gpio_pin_tx,
int32_t low_time,
int32_t high_time,
int32_t low_time,
int32_t high_time,
uint32_t& start)
{
ISR_noInterrupts();
@@ -1345,7 +1359,8 @@ bool Dallas_SensorData::collect_value(int8_t gpio_rx, int8_t gpio_tx) {
--nrRetries;
Dallas_read_result res = Dallas_readTemp(tmpaddr, &value, gpio_rx, gpio_tx);
switch (res) {
switch (res)
{
case Dallas_read_result::OK:
++read_success;
lastReadError = false;
+18
View File
@@ -276,6 +276,24 @@ void addSelector_Item(const __FlashStringHelper *option, int index, bool sele
}
void addSelector_Item(const String& option, int index, bool selected, bool disabled, const String& attr)
{
addSelector_Item(option, String(index), selected, disabled, attr);
}
void addSelector_Item_index64(const String& option,
uint64_t index,
bool selected,
bool disabled,
const String& attr)
{
addSelector_Item(option, ull2String(index), selected, disabled, attr);
}
void addSelector_Item(const String& option,
const String& index,
bool selected,
bool disabled,
const String& attr)
{
addHtml(F("<option "));
addHtmlAttribute(F("value"), index);
+12
View File
@@ -101,6 +101,18 @@ void addSelector_Item(const String& option,
bool disabled = false,
const String& attr = EMPTY_STRING);
void addSelector_Item(const String& option,
const String& index,
bool selected,
bool disabled = false,
const String& attr = EMPTY_STRING);
void addSelector_Item_index64(const String& option,
uint64_t index,
bool selected,
bool disabled = false,
const String& attr = EMPTY_STRING);
void addSelector_Foot(bool reloadonchange = false);
void addSelector_OptGroup(const String& label);
+30 -9
View File
@@ -685,23 +685,44 @@ int getFormItemInt(const String& key, int defaultValue) {
return value;
}
uint64_t getFormItemUInt64(const String& key, uint64_t defaultValue)
{
uint64_t value = defaultValue;
getCheckWebserverArg_int(key, value);
return value;
}
bool getCheckWebserverArg_int(const String& key, int& value) {
const String valueStr = webArg(key);
if (valueStr.isEmpty()) return false;
// FIXME TD-er: Since ESP_IDF 5.1 int32_t != int
int32_t tmp{};
const bool res = validIntFromString(valueStr, tmp);
int64_t tmp{};
if (!getCheckWebserverArg_int(key, tmp)) return false;
value = tmp;
return res;
return true;
}
bool getCheckWebserverArg_int(const String& key,
uint32_t & value) {
uint64_t tmp{};
if (!getCheckWebserverArg_int(key, tmp)) return false;
value = tmp;
return true;
}
bool getCheckWebserverArg_int(const String& key,
uint64_t & value)
{
const String valueStr = webArg(key);
if (valueStr.isEmpty()) return false;
uint32_t tmp{};
const bool res = validUIntFromString(valueStr, tmp);
value = tmp;
const bool res = validUInt64FromString(valueStr, value);
return res;
}
bool getCheckWebserverArg_int(const String& key,
int64_t & value)
{
const String valueStr = webArg(key);
if (valueStr.isEmpty()) return false;
const bool res = validInt64FromString(valueStr, value);
return res;
}
+7
View File
@@ -322,6 +322,7 @@ void addFormPinStateSelect(int gpio,
int getFormItemInt(const __FlashStringHelper * key, int defaultValue);
int getFormItemInt(const String& key, int defaultValue);
uint64_t getFormItemUInt64(const String& key, uint64_t defaultValue);
bool getCheckWebserverArg_int(const String& key,
int & value);
@@ -329,6 +330,12 @@ bool getCheckWebserverArg_int(const String& key,
bool getCheckWebserverArg_int(const String& key,
uint32_t & value);
bool getCheckWebserverArg_int(const String& key,
uint64_t & value);
bool getCheckWebserverArg_int(const String& key,
int64_t & value);
bool update_whenset_FormItemInt(const __FlashStringHelper * key,
int & value,
bool* changed = nullptr);